initial load of upstream version 1.06.32
[xmlrpc-c] / src / cpp / curl.cpp
1 /*=============================================================================
2                                 curl.cpp
3 ===============================================================================
4   This is the Curl XML transport of the C++ XML-RPC client library for
5   Xmlrpc-c.
6
7   Note that unlike most of Xmlprc-c's C++ API, this is _not_ based on the
8   C client library.  This code is independent of the C client library, and
9   is based directly on the client XML transport libraries (with a little
10   help from internal C utility libraries).
11 =============================================================================*/
12
13 #include <stdlib.h>
14 #include <cassert>
15 #include <string>
16
17 #include "xmlrpc-c/girerr.hpp"
18 using girerr::error;
19 using girerr::throwf;
20 #include "xmlrpc-c/girmem.hpp"
21 using girmem::autoObjectPtr;
22 using girmem::autoObject;
23 #include "env_wrap.hpp"
24 #include "xmlrpc-c/base.h"
25 #include "xmlrpc-c/client.h"
26 #include "xmlrpc-c/transport.h"
27 #include "xmlrpc-c/base_int.h"
28
29 #include "xmlrpc_curl_transport.h"
30
31 /* transport_config.h defines MUST_BUILD_CURL_CLIENT */
32 #include "transport_config.h"
33
34 #include "xmlrpc-c/client_transport.hpp"
35
36
37 using namespace std;
38 using namespace xmlrpc_c;
39
40
41
42 namespace {
43
44 class globalConstant {
45 public:
46     globalConstant();
47     ~globalConstant();
48 };
49
50
51
52 globalConstant::globalConstant() {
53
54     // Not thread safe
55
56     xmlrpc_transport_setup setupFn;
57
58 #if MUST_BUILD_CURL_CLIENT
59     setupFn = xmlrpc_curl_transport_ops.setup_global_const;
60 #else
61     setupFn = NULL;
62 #endif
63     if (setupFn) {
64         env_wrap env;
65
66         setupFn(&env.env_c); // Not thread safe
67         
68         if (env.env_c.fault_occurred)
69             throwf("Failed to do global initialization "
70                    "of Curl transport code.  %s", env.env_c.fault_string);
71     }
72 }
73
74
75
76 globalConstant::~globalConstant() {
77
78     // Not thread safe
79
80     xmlrpc_transport_teardown teardownFn;
81
82 #if MUST_BUILD_CURL_CLIENT
83     teardownFn = xmlrpc_curl_transport_ops.teardown_global_const;
84 #else
85     teardownFn = NULL;
86 #endif
87     if (teardownFn)
88         teardownFn();  // not thread safe
89 }
90
91 globalConstant globalConst;
92     // This object is never accessed.  Its whole purpose to to be born and
93     // to die, which it does automatically as part of C++ program
94     // program initialization and termination.
95
96 } // namespace
97
98
99 namespace xmlrpc_c {
100
101 carriageParm_curl0::carriageParm_curl0(
102     string const serverUrl
103     ) {
104
105     this->instantiate(serverUrl);
106 }
107
108
109
110 carriageParm_curl0Ptr::carriageParm_curl0Ptr() {
111     // Base class constructor will construct pointer that points to nothing
112 }
113
114
115
116 carriageParm_curl0Ptr::carriageParm_curl0Ptr(
117     carriageParm_curl0 * const carriageParmP) {
118     this->point(carriageParmP);
119 }
120
121
122
123 carriageParm_curl0 *
124 carriageParm_curl0Ptr::operator->() const {
125
126     autoObject * const p(this->objectP);
127     return dynamic_cast<carriageParm_curl0 *>(p);
128 }
129
130
131
132 clientXmlTransport_curl::constrOpt::constrOpt() {
133
134     present.network_interface = false;
135     present.no_ssl_verifypeer = false;
136     present.no_ssl_verifyhost = false;
137     present.user_agent = false;
138     present.ssl_cert = false;
139     present.sslcerttype = false;
140     present.sslcertpasswd = false;
141     present.sslkey = false;
142     present.sslkeytype = false;
143     present.sslkeypasswd = false;
144     present.sslengine = false;
145     present.sslengine_default = false;
146     present.sslversion = false;
147     present.cainfo = false;
148     present.capath = false;
149     present.randomfile = false;
150     present.egdsocket = false;
151     present.ssl_cipher_list = false;
152 }
153
154
155
156 #define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \
157 clientXmlTransport_curl::constrOpt & \
158 clientXmlTransport_curl::constrOpt::OPTION_NAME(TYPE const& arg) { \
159     this->value.OPTION_NAME = arg; \
160     this->present.OPTION_NAME = true; \
161     return *this; \
162 }
163
164 DEFINE_OPTION_SETTER(network_interface, string);
165 DEFINE_OPTION_SETTER(no_ssl_verifypeer, bool);
166 DEFINE_OPTION_SETTER(no_ssl_verifyhost, bool);
167 DEFINE_OPTION_SETTER(user_agent, string);
168 DEFINE_OPTION_SETTER(ssl_cert, string);
169 DEFINE_OPTION_SETTER(sslcerttype, string);
170 DEFINE_OPTION_SETTER(sslcertpasswd, string);
171 DEFINE_OPTION_SETTER(sslkey, string);
172 DEFINE_OPTION_SETTER(sslkeytype, string);
173 DEFINE_OPTION_SETTER(sslkeypasswd, string);
174 DEFINE_OPTION_SETTER(sslengine, string);
175 DEFINE_OPTION_SETTER(sslengine_default, bool);
176 DEFINE_OPTION_SETTER(sslversion, xmlrpc_sslversion);
177 DEFINE_OPTION_SETTER(cainfo, string);
178 DEFINE_OPTION_SETTER(capath, string);
179 DEFINE_OPTION_SETTER(randomfile, string);
180 DEFINE_OPTION_SETTER(egdsocket, string);
181 DEFINE_OPTION_SETTER(ssl_cipher_list, string);
182
183 #undef DEFINE_OPTION_SETTER
184
185 #if MUST_BUILD_CURL_CLIENT
186
187 void
188 clientXmlTransport_curl::initialize(constrOpt const& opt) {
189     struct xmlrpc_curl_xportparms transportParms; 
190
191     transportParms.network_interface = opt.present.network_interface ?
192         opt.value.network_interface.c_str() : NULL;
193     transportParms.no_ssl_verifypeer = opt.present.no_ssl_verifypeer ? 
194         opt.value.no_ssl_verifypeer         : false;
195     transportParms.no_ssl_verifyhost = opt.present.no_ssl_verifyhost ? 
196         opt.value.no_ssl_verifyhost         : false;
197     transportParms.user_agent        = opt.present.user_agent ?
198         opt.value.user_agent.c_str()        : NULL;
199     transportParms.ssl_cert          = opt.present.ssl_cert ?
200         opt.value.ssl_cert.c_str()          : NULL;
201     transportParms.sslcerttype       = opt.present.sslcerttype ?
202         opt.value.sslcerttype.c_str()       : NULL;
203     transportParms.sslcertpasswd     = opt.present.sslcertpasswd ?
204         opt.value.sslcertpasswd.c_str()     : NULL;
205     transportParms.sslkey            = opt.present.sslkey ?
206         opt.value.sslkey.c_str()            : NULL;
207     transportParms.sslkeytype        = opt.present.sslkeytype ?
208         opt.value.sslkeytype.c_str()        : NULL;
209     transportParms.sslkeypasswd      = opt.present.sslkeypasswd ?
210         opt.value.sslkeypasswd.c_str()      : NULL;
211     transportParms.sslengine         = opt.present.sslengine ?
212         opt.value.sslengine.c_str()         : NULL;
213     transportParms.sslengine_default = opt.present.sslengine_default ? 
214         opt.value.sslengine_default         : false;
215     transportParms.sslversion        = opt.present.sslversion ? 
216         opt.value.sslversion                : XMLRPC_SSLVERSION_DEFAULT;
217     transportParms.cainfo            = opt.present.cainfo ?
218         opt.value.cainfo.c_str()            : NULL;
219     transportParms.capath            = opt.present.capath ?
220         opt.value.capath.c_str()            : NULL;
221     transportParms.randomfile        = opt.present.randomfile ? 
222         opt.value.randomfile.c_str()        : NULL;
223     transportParms.egdsocket         = opt.present.egdsocket ?
224         opt.value.egdsocket.c_str()         : NULL;
225     transportParms.ssl_cipher_list   = opt.present.ssl_cipher_list ? 
226         opt.value.ssl_cipher_list.c_str()   : NULL;
227
228     this->c_transportOpsP = &xmlrpc_curl_transport_ops;
229
230     env_wrap env;
231
232     xmlrpc_curl_transport_ops.create(
233         &env.env_c, 0, "", "", (xmlrpc_xportparms *)&transportParms,
234         XMLRPC_CXPSIZE(ssl_cipher_list),
235         &this->c_transportP);
236
237     if (env.env_c.fault_occurred)
238         throw(error(env.env_c.fault_string));
239 }
240
241 #else  // MUST_BUILD_CURL_CLIENT
242
243 void
244 clientXmlTransport_curl::initialize(constrOpt const& opt) {
245
246     throw(error("There is no Curl client XML transport in this XML-RPC client "
247                 "library"));
248 }
249
250 #endif
251
252 clientXmlTransport_curl::clientXmlTransport_curl(constrOpt const& opt) {
253
254     this->initialize(opt);
255 }
256
257
258
259 clientXmlTransport_curl::clientXmlTransport_curl(
260     string const networkInterface,
261     bool   const noSslVerifyPeer,
262     bool   const noSslVerifyHost,
263     string const userAgent) {
264
265     clientXmlTransport_curl::constrOpt opt;
266
267     if (networkInterface.size() > 0)
268         opt.network_interface(networkInterface);
269     opt.no_ssl_verifypeer(noSslVerifyPeer);
270     opt.no_ssl_verifyhost(noSslVerifyHost);
271     if (userAgent.size() > 0)
272         opt.user_agent(userAgent);
273
274     this->initialize(opt);
275 }
276
277
278
279 clientXmlTransport_curl::~clientXmlTransport_curl() {
280
281     this->c_transportOpsP->destroy(this->c_transportP);
282 }
283
284
285 } // namespace