XmlRpcCpp.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // -*- C++ -*- <-- an Emacs control
  2. // Copyright information is at the bottom of the file.
  3. //=========================================================================
  4. // XML-RPC C++ API
  5. //=========================================================================
  6. #ifndef _XMLRPCCPP_H_
  7. #define _XMLRPCCPP_H_ 1
  8. // The C++ standard says we should either include <string.h> (which gets
  9. // us the wrong header), or say 'using namespace std;' (which doesn't
  10. // work with our version of g++). So this header name is technically wrong.
  11. // Tell me what your compiler does; I can provide some autoconf magic to the
  12. // Right Thing on most platforms.
  13. //
  14. // 2004.12.22 Bryan: This looks like a problem with whatever g++ he was
  15. // using, so if anything, the special case should be for that. In any case,
  16. // we've already added using namespace std to other files, without knowing
  17. // there was an issue, so I'm just going to do the "using namespace"
  18. // unconditionally and see who complains. If there are complaints, we can
  19. // improve the documentation here.
  20. //
  21. // Formerly, the "using namespace std" was under
  22. // "#if defined(__GNUC__) && (__GNUC__ >= 3)".
  23. #include <string>
  24. using namespace std;
  25. #include <xmlrpc_config.h>
  26. #include <xmlrpc.h>
  27. #include <xmlrpc_client.h>
  28. #include <xmlrpc_server.h>
  29. #define XMLRPC_NO_ASSIGNMENT \
  30. XMLRPC_FATAL_ERROR("Assignment operator not available"); return *this;
  31. //=========================================================================
  32. // XmlRpcFault
  33. //=========================================================================
  34. // A C++ exception class representing an XML-RPC fault.
  35. class XmlRpcFault {
  36. private:
  37. xmlrpc_env mFault;
  38. XmlRpcFault& operator= (const XmlRpcFault& f)
  39. { (void) f; XMLRPC_NO_ASSIGNMENT }
  40. public:
  41. XmlRpcFault (const XmlRpcFault &fault);
  42. XmlRpcFault (const int faultCode, const string faultString);
  43. XmlRpcFault (const xmlrpc_env *env);
  44. ~XmlRpcFault (void);
  45. int getFaultCode (void) const;
  46. string getFaultString (void) const;
  47. xmlrpc_env *getFaultEnv (void);
  48. };
  49. inline int XmlRpcFault::getFaultCode (void) const {
  50. return mFault.fault_code;
  51. }
  52. inline xmlrpc_env *XmlRpcFault::getFaultEnv (void) {
  53. return &mFault;
  54. }
  55. //=========================================================================
  56. // XmlRpcEnv
  57. //=========================================================================
  58. // This class can be used to wrap xmlrpc_env object. Use it as follows:
  59. //
  60. // XmlRpcEnv env;
  61. // xmlrpc_parse_value(env, v, "(i)", &i);
  62. // env.throwIfFaultOccurred();
  63. class XmlRpcEnv {
  64. private:
  65. xmlrpc_env mEnv;
  66. void throwMe (void) const;
  67. XmlRpcEnv& operator= (const XmlRpcEnv& e)
  68. { (void) e; XMLRPC_NO_ASSIGNMENT }
  69. public:
  70. XmlRpcEnv (const XmlRpcEnv &env);
  71. XmlRpcEnv (void) { xmlrpc_env_init(&mEnv); }
  72. ~XmlRpcEnv (void) { xmlrpc_env_clean(&mEnv); }
  73. bool faultOccurred (void) const { return mEnv.fault_occurred; };
  74. bool hasFaultOccurred (void) const { return faultOccurred(); };
  75. /* hasFaultOccurred() is for backward compatibility.
  76. faultOccurred() is a superior name for this.
  77. */
  78. XmlRpcFault getFault (void) const;
  79. void throwIfFaultOccurred (void) const;
  80. operator xmlrpc_env * (void) { return &mEnv; }
  81. };
  82. inline void XmlRpcEnv::throwIfFaultOccurred (void) const {
  83. if (faultOccurred())
  84. throwMe();
  85. }
  86. //=========================================================================
  87. // XmlRpcValue
  88. //=========================================================================
  89. // An object in this class is an XML-RPC value.
  90. //
  91. // We have a complex structure to allow C code mixed in with C++ code
  92. // which uses this class to refer to the same XML-RPC value object.
  93. // This is especially important because there aren't proper C++ facilities
  94. // for much of Xmlrpc-c; you have to use the C facilities even if you'd
  95. // rather use proper C++.
  96. //
  97. // The XmlRpcValue object internally represents the value as an
  98. // xmlrpc_value. It hold one reference to the xmlrpc_value. Users
  99. // of XmlRpcValue never see that xmlrpc_value, but C code can. the
  100. // C code might create the xmlrpc_value and then bind it to an XmlRpcValue,
  101. // or it might get the xmlrpc_value handle from the XmlRpcValue. Finally,
  102. // C code can simply use the XmlRpcValue where an xmlrpc_value handle is
  103. // required and it gets converted automatically.
  104. //
  105. // So reference counting for the xmlrpc_value is quite a nightmare.
  106. class XmlRpcValue {
  107. private:
  108. xmlrpc_value *mValue;
  109. public:
  110. enum ReferenceBehavior {
  111. MAKE_REFERENCE,
  112. CONSUME_REFERENCE
  113. };
  114. typedef xmlrpc_int32 int32;
  115. XmlRpcValue (void);
  116. XmlRpcValue (xmlrpc_value *value,
  117. ReferenceBehavior behavior = MAKE_REFERENCE);
  118. XmlRpcValue (const XmlRpcValue& value);
  119. ~XmlRpcValue (void);
  120. XmlRpcValue& operator= (const XmlRpcValue& value);
  121. // Accessing the value's type (think of this as lightweight RTTI).
  122. xmlrpc_type getType(void) const;
  123. // We don't supply an automatic conversion operator--you need to say
  124. // whether you want to make or borrow this object's reference.
  125. // XXX - Is it really OK for these to be const?
  126. xmlrpc_value *makeReference (void) const;
  127. xmlrpc_value *borrowReference (void) const;
  128. // Some static "constructor" functions.
  129. static XmlRpcValue makeInt (const XmlRpcValue::int32 i);
  130. static XmlRpcValue makeBool (const bool b);
  131. static XmlRpcValue makeDouble (const double d);
  132. static XmlRpcValue makeDateTime (const string& dateTime);
  133. static XmlRpcValue makeString (const string& str);
  134. static XmlRpcValue makeString (const char *const str);
  135. static XmlRpcValue makeString (const char *const str, size_t len);
  136. static XmlRpcValue makeArray (void);
  137. static XmlRpcValue makeStruct (void);
  138. static XmlRpcValue makeBase64 (const unsigned char *const data,
  139. size_t len);
  140. /*
  141. // An interface to xmlrpc_build_value.
  142. static XmlRpcValue buildValue (const char *const format, ...);
  143. */
  144. // Some functions to get the underlying data.
  145. // These will throw an XmlRpcFault if the data is the wrong type.
  146. XmlRpcValue::int32 getInt (void) const;
  147. bool getBool (void) const;
  148. double getDouble (void) const;
  149. string getRawDateTime (void) const;
  150. string getString (void) const;
  151. XmlRpcValue getArray (void) const;
  152. XmlRpcValue getStruct (void) const;
  153. // This returns an internal pointer which will become invalid when
  154. // all references to the underlying value are destroyed.
  155. void getBase64 (const unsigned char *& out_data,
  156. size_t& out_len) const;
  157. /*
  158. // An interface to xmlrpc_parse_value.
  159. void parseValue (const char *const format, ...);
  160. */
  161. // Array functions. These will throw an XmlRpcFault if the value
  162. // isn't an array.
  163. size_t arraySize (void) const;
  164. void arrayAppendItem (const XmlRpcValue& value);
  165. XmlRpcValue arrayGetItem (int index) const;
  166. // Struct functions. These will throw an XmlRpcFault if the value
  167. // isn't a struct.
  168. size_t structSize (void) const;
  169. bool structHasKey (const string& key) const;
  170. XmlRpcValue structGetValue (const string& key) const;
  171. void structSetValue (const string& key, const XmlRpcValue& value);
  172. void structGetKeyAndValue (const int index,
  173. string& out_key,
  174. XmlRpcValue& out_value) const;
  175. };
  176. inline XmlRpcValue::XmlRpcValue (xmlrpc_value *value,
  177. ReferenceBehavior behavior)
  178. {
  179. mValue = value;
  180. if (behavior == MAKE_REFERENCE)
  181. xmlrpc_INCREF(value);
  182. }
  183. inline XmlRpcValue::XmlRpcValue (const XmlRpcValue& value) {
  184. mValue = value.mValue;
  185. xmlrpc_INCREF(mValue);
  186. }
  187. inline XmlRpcValue::~XmlRpcValue (void) {
  188. xmlrpc_DECREF(mValue);
  189. }
  190. inline XmlRpcValue& XmlRpcValue::operator= (const XmlRpcValue& value) {
  191. // Must increment before we decrement, in case of assignment to self.
  192. xmlrpc_INCREF(value.mValue);
  193. xmlrpc_DECREF(mValue);
  194. mValue = value.mValue;
  195. return *this;
  196. }
  197. inline xmlrpc_type XmlRpcValue::getType (void) const {
  198. return xmlrpc_value_type(mValue);
  199. }
  200. inline xmlrpc_value *XmlRpcValue::makeReference (void) const {
  201. xmlrpc_INCREF(mValue);
  202. return mValue;
  203. }
  204. inline xmlrpc_value *XmlRpcValue::borrowReference (void) const {
  205. return mValue;
  206. }
  207. //=========================================================================
  208. // XmlRpcClient
  209. //=========================================================================
  210. class XmlRpcClient {
  211. private:
  212. string mServerUrl;
  213. public:
  214. static void Initialize (string appname, string appversion);
  215. static void Terminate (void);
  216. XmlRpcClient (const string& server_url) : mServerUrl(server_url) {}
  217. ~XmlRpcClient (void) {}
  218. XmlRpcClient (const XmlRpcClient& client);
  219. XmlRpcClient& operator= (const XmlRpcClient& client);
  220. XmlRpcValue call (string method_name, XmlRpcValue param_array);
  221. void call_asynch (string method_name,
  222. XmlRpcValue param_array,
  223. xmlrpc_response_handler callback,
  224. void* user_data);
  225. void event_loop_asynch (unsigned long milliseconds);
  226. };
  227. inline void XmlRpcClient::call_asynch(string method_name,
  228. XmlRpcValue param_array,
  229. xmlrpc_response_handler callback,
  230. void* user_data)
  231. {
  232. xmlrpc_client_call_asynch_params(
  233. mServerUrl.c_str(),
  234. method_name.c_str(),
  235. callback,
  236. user_data,
  237. param_array.borrowReference());
  238. }
  239. inline void XmlRpcClient::event_loop_asynch(unsigned long milliseconds)
  240. {
  241. xmlrpc_client_event_loop_finish_asynch_timeout(milliseconds);
  242. }
  243. //=========================================================================
  244. // XmlRpcClient Methods
  245. //=========================================================================
  246. // These are inline for now, so we don't need to screw with linker issues
  247. // and build a separate client library.
  248. inline XmlRpcClient::XmlRpcClient (const XmlRpcClient& client)
  249. : mServerUrl(client.mServerUrl)
  250. {
  251. }
  252. inline XmlRpcClient& XmlRpcClient::operator= (const XmlRpcClient& client) {
  253. if (this != &client)
  254. mServerUrl = client.mServerUrl;
  255. return *this;
  256. }
  257. inline void XmlRpcClient::Initialize (string appname, string appversion) {
  258. xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS,
  259. appname.c_str(),
  260. appversion.c_str());
  261. }
  262. inline void XmlRpcClient::Terminate (void) {
  263. xmlrpc_client_cleanup();
  264. }
  265. inline XmlRpcValue XmlRpcClient::call (string method_name,
  266. XmlRpcValue param_array)
  267. {
  268. XmlRpcEnv env;
  269. xmlrpc_value *result =
  270. xmlrpc_client_call_params(env,
  271. mServerUrl.c_str(),
  272. method_name.c_str(),
  273. param_array.borrowReference());
  274. env.throwIfFaultOccurred();
  275. return XmlRpcValue(result, XmlRpcValue::CONSUME_REFERENCE);
  276. }
  277. //=========================================================================
  278. // XmlRpcGenSrv
  279. //=========================================================================
  280. class XmlRpcGenSrv {
  281. private:
  282. xmlrpc_registry* mRegistry;
  283. xmlrpc_mem_block* alloc (XmlRpcEnv& env, const string& body) const;
  284. public:
  285. XmlRpcGenSrv (int flags);
  286. ~XmlRpcGenSrv (void);
  287. xmlrpc_registry* getRegistry (void) const;
  288. XmlRpcGenSrv& addMethod (const string& name,
  289. xmlrpc_method method,
  290. void *data);
  291. XmlRpcGenSrv& addMethod (const string& name,
  292. xmlrpc_method method,
  293. void* data,
  294. const string& signature,
  295. const string& help);
  296. string handle (const string& body) const;
  297. };
  298. inline XmlRpcGenSrv::XmlRpcGenSrv (int flags) {
  299. XmlRpcEnv env;
  300. if (flags == flags){};
  301. mRegistry = xmlrpc_registry_new (env);
  302. env.throwIfFaultOccurred();
  303. }
  304. inline XmlRpcGenSrv::~XmlRpcGenSrv (void) {
  305. xmlrpc_registry_free (mRegistry);
  306. }
  307. inline xmlrpc_registry* XmlRpcGenSrv::getRegistry () const {
  308. return mRegistry;
  309. }
  310. #undef XMLRPC_NO_ASSIGNMENT
  311. // Copyright (C) 2001 by Eric Kidd. All rights reserved.
  312. //
  313. // Redistribution and use in source and binary forms, with or without
  314. // modification, are permitted provided that the following conditions
  315. // are met:
  316. // 1. Redistributions of source code must retain the above copyright
  317. // notice, this list of conditions and the following disclaimer.
  318. // 2. Redistributions in binary form must reproduce the above copyright
  319. // notice, this list of conditions and the following disclaimer in the
  320. // documentation and/or other materials provided with the distribution.
  321. // 3. The name of the author may not be used to endorse or promote products
  322. // derived from this software without specific prior written permission.
  323. //
  324. // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  325. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  326. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  327. // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  328. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  329. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  330. // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  331. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  332. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  333. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  334. // SUCH DAMAGE.
  335. #endif /* _XMLRPCCPP_H_ */