unify runtime handling of undefined CURLOPT
[ocurl.git] / curl-helper.c
blobdb0e27c586c1c02c1dbec13f81c0f01555d76afd
1 /***
2 *** curl-helper.c
3 ***
4 *** Copyright (c) 2003-2008, Lars Nilsson, <lars@quantumchamaeleon.com>
5 *** Copyright (c) 2009, ygrek, <ygrek@autistici.org>
6 ***/
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13 /* suppress false gcc warning on seekFunction */
14 #define CURL_DISABLE_TYPECHECK
15 #include <curl/curl.h>
17 #include <caml/alloc.h>
18 #include <caml/memory.h>
19 #include <caml/mlvalues.h>
20 #include <caml/callback.h>
21 #include <caml/fail.h>
22 #include <caml/unixsupport.h>
23 #include <caml/custom.h>
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #else
28 #pragma message("No config file given.")
29 #endif
31 void leave_blocking_section(void);
32 void enter_blocking_section(void);
34 #define Val_none Val_int(0)
36 static __inline value
37 Val_some( value v )
39 CAMLparam1( v );
40 CAMLlocal1( some );
41 some = caml_alloc(1, 0);
42 Store_field( some, 0, v );
43 CAMLreturn( some );
46 static value Val_pair(value v1, value v2)
48 CAMLparam2(v1,v2);
49 CAMLlocal1(pair);
50 pair = caml_alloc_small(2,0);
51 Field(pair,0) = v1;
52 Field(pair,1) = v2;
53 CAMLreturn(pair);
56 static value Val_cons(value list, value v) { return Val_pair(v,list); }
58 typedef struct Connection Connection;
59 typedef struct ConnectionList ConnectionList;
61 #define Connection_val(v) (*(Connection**)Data_custom_val(v))
63 enum OcamlValues
65 OcamlWriteCallback,
66 OcamlReadCallback,
67 OcamlErrorBuffer,
68 OcamlPostFields,
69 OcamlHTTPHeader,
70 OcamlHTTPPost,
71 OcamlQuote,
72 OcamlPostQuote,
73 OcamlHeaderCallback,
74 OcamlProgressCallback,
75 OcamlDebugCallback,
76 OcamlHTTP200Aliases,
77 OcamlIOCTLCallback,
78 OcamlSeekFunctionCallback,
79 OcamlOpenSocketFunctionCallback,
81 OcamlURL,
82 OcamlProxy,
83 OcamlUserPWD,
84 OcamlProxyUserPWD,
85 OcamlRange,
86 OcamlReferer,
87 OcamlUserAgent,
88 OcamlFTPPort,
89 OcamlCookie,
90 OcamlHTTPPostStrings,
91 OcamlSSLCert,
92 OcamlSSLCertType,
93 OcamlSSLCertPasswd,
94 OcamlSSLKey,
95 OcamlSSLKeyType,
96 OcamlSSLKeyPasswd,
97 OcamlSSLEngine,
98 OcamlCookieFile,
99 OcamlCustomRequest,
100 OcamlInterface,
101 OcamlCAInfo,
102 OcamlCAPath,
103 OcamlRandomFile,
104 OcamlEGDSocket,
105 OcamlCookieJar,
106 OcamlSSLCipherList,
107 OcamlPrivate,
108 OcamlNETRCFile,
109 OcamlFTPAccount,
110 OcamlCookieList,
111 OcamlFTPAlternativeToUser,
112 OcamlSSHPublicKeyFile,
113 OcamlSSHPrivateKeyFile,
114 OcamlSSHHostPublicKeyMD5,
115 OcamlCopyPostFields,
117 OcamlDNSServers,
119 OcamlMailFrom,
120 OcamlMailRcpt,
122 /* Not used, last for size */
123 OcamlValuesSize
126 struct Connection
128 CURL *connection;
129 Connection *next;
130 Connection *prev;
132 value ocamlValues;
134 size_t refcount; /* number of references to this structure */
136 char *url;
137 char *proxy;
138 char *userPwd;
139 char *proxyUserPwd;
140 char *range;
141 char *errorBuffer;
142 char *postFields;
143 int postFieldSize;
144 char *referer;
145 char *userAgent;
146 char *ftpPort;
147 char *cookie;
148 struct curl_slist *httpHeader;
149 struct curl_httppost *httpPostFirst;
150 struct curl_httppost *httpPostLast;
151 struct curl_slist *httpPostStrings;
152 struct curl_slist *resolve;
153 char *sslCert;
154 char *sslCertType;
155 char *sslCertPasswd;
156 char *sslKey;
157 char *sslKeyType;
158 char *sslKeyPasswd;
159 char *sslEngine;
160 struct curl_slist *quote;
161 struct curl_slist *postQuote;
162 char *cookieFile;
163 char *customRequest;
164 char *interface_; /* `interface` gives problems on windows */
165 char *caInfo;
166 char *caPath;
167 char *randomFile;
168 char *egdSocket;
169 char *cookieJar;
170 char *sslCipherList;
171 char *private;
172 struct curl_slist *http200Aliases;
173 char *netrcFile;
174 char *ftpaccount;
175 char *cookielist;
176 char *ftpAlternativeToUser;
177 char *sshPublicKeyFile;
178 char *sshPrivateKeyFile;
179 char *sshHostPublicKeyMD5;
180 char *copyPostFields;
181 char *dns_servers;
182 char *mailFrom;
183 struct curl_slist *mailRcpt;
186 struct ConnectionList
188 Connection *head;
189 Connection *tail;
192 static ConnectionList connectionList = {NULL, NULL};
194 typedef struct CURLErrorMapping CURLErrorMapping;
196 struct CURLErrorMapping
198 char *name;
199 CURLcode error;
202 CURLErrorMapping errorMap[] =
204 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
205 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
206 #else
207 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
208 #endif
209 #if HAVE_DECL_CURLE_FAILED_INIT
210 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
211 #else
212 {"CURLE_FAILED_INIT", -1},
213 #endif
214 #if HAVE_DECL_CURLE_URL_MALFORMAT
215 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
216 #else
217 {"CURLE_URL_MALFORMAT", -1},
218 #endif
219 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
220 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
221 #else
222 {"CURLE_URL_MALFORMAT_USER", -1},
223 #endif
224 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
225 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
226 #else
227 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
228 #endif
229 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
230 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
231 #else
232 {"CURLE_COULDNT_RESOLVE_HOST", -1},
233 #endif
234 #if HAVE_DECL_CURLE_COULDNT_CONNECT
235 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
236 #else
237 {"CURLE_COULDNT_CONNECT", -1},
238 #endif
239 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
240 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
241 #else
242 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
243 #endif
244 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
245 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
246 #else
247 {"CURLE_FTP_ACCESS_DENIED", -1},
248 #endif
249 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
250 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
251 #else
252 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
253 #endif
254 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
255 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
256 #else
257 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
258 #endif
259 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
260 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
261 #else
262 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
263 #endif
264 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
265 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
266 #else
267 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
268 #endif
269 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
270 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
271 #else
272 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
273 #endif
274 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
275 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
276 #else
277 {"CURLE_FTP_CANT_GET_HOST", -1},
278 #endif
279 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
280 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
281 #else
282 {"CURLE_FTP_CANT_RECONNECT", -1},
283 #endif
284 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
285 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
286 #else
287 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
288 #endif
289 #if HAVE_DECL_CURLE_PARTIAL_FILE
290 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
291 #else
292 {"CURLE_PARTIAL_FILE", -1},
293 #endif
294 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
295 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
296 #else
297 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
298 #endif
299 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
300 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
301 #else
302 {"CURLE_FTP_WRITE_ERROR", -1},
303 #endif
304 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
305 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
306 #else
307 {"CURLE_FTP_QUOTE_ERROR", -1},
308 #endif
309 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
310 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
311 #else
312 {"CURLE_HTTP_NOT_FOUND", -1},
313 #endif
314 #if HAVE_DECL_CURLE_WRITE_ERROR
315 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
316 #else
317 {"CURLE_WRITE_ERROR", -1},
318 #endif
319 #if HAVE_DECL_CURLE_MALFORMAT_USER
320 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
321 #else
322 {"CURLE_MALFORMAT_USER", -1},
323 #endif
324 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
325 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
326 #else
327 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
328 #endif
329 #if HAVE_DECL_CURLE_READ_ERROR
330 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
331 #else
332 {"CURLE_READ_ERROR", -1},
333 #endif
334 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
335 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
336 #else
337 {"CURLE_OUT_OF_MEMORY", -1},
338 #endif
339 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
340 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
341 #else
342 {"CURLE_OPERATION_TIMEOUTED", -1},
343 #endif
344 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
345 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
346 #else
347 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
348 #endif
349 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
350 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
351 #else
352 {"CURLE_FTP_PORT_FAILED", -1},
353 #endif
354 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
355 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
356 #else
357 {"CURLE_FTP_COULDNT_USE_REST", -1},
358 #endif
359 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
360 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
361 #else
362 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
363 #endif
364 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
365 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
366 #else
367 {"CURLE_HTTP_RANGE_ERROR", -1},
368 #endif
369 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
370 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
371 #else
372 {"CURLE_HTTP_POST_ERROR", -1},
373 #endif
374 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
375 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
376 #else
377 {"CURLE_SSL_CONNECT_ERROR", -1},
378 #endif
379 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
380 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
381 #else
382 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
383 #endif
384 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
385 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
386 #else
387 {"CURLE_FILE_COULDNT_READ_FILE", -1},
388 #endif
389 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
390 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
391 #else
392 {"CURLE_LDAP_CANNOT_BIND", -1},
393 #endif
394 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
395 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
396 #else
397 {"CURLE_LDAP_SEARCH_FAILED", -1},
398 #endif
399 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
400 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
401 #else
402 {"CURLE_LIBRARY_NOT_FOUND", -1},
403 #endif
404 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
405 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
406 #else
407 {"CURLE_FUNCTION_NOT_FOUND", -1},
408 #endif
409 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
410 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
411 #else
412 {"CURLE_ABORTED_BY_CALLBACK", -1},
413 #endif
414 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
415 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
416 #else
417 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
418 #endif
419 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
420 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
421 #else
422 {"CURLE_BAD_CALLING_ORDER", -1},
423 #endif
424 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
425 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
426 #else
427 {"CURLE_HTTP_PORT_FAILED", -1},
428 #endif
429 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
430 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
431 #else
432 {"CURLE_BAD_PASSWORD_ENTERED", -1},
433 #endif
434 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
435 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
436 #else
437 {"CURLE_TOO_MANY_REDIRECTS", -1},
438 #endif
439 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
440 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
441 #else
442 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
443 #endif
444 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
445 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
446 #else
447 {"CURLE_TELNET_OPTION_SYNTAX", -1},
448 #endif
449 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
450 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
451 #else
452 {"CURLE_SSL_PEER_CERTIFICATE", -1},
453 #endif
454 #if HAVE_DECL_CURLE_GOT_NOTHING
455 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
456 #else
457 {"CURLE_GOT_NOTHING", -1},
458 #endif
459 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
460 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
461 #else
462 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
463 #endif
464 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
465 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
466 #else
467 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
468 #endif
469 #if HAVE_DECL_CURLE_SEND_ERROR
470 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
471 #else
472 {"CURLE_SEND_ERROR", -1},
473 #endif
474 #if HAVE_DECL_CURLE_RECV_ERROR
475 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
476 #else
477 {"CURLE_RECV_ERROR", -1},
478 #endif
479 #if HAVE_DECL_CURLE_SHARE_IN_USE
480 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
481 #else
482 {"CURLE_SHARE_IN_USE", -1},
483 #endif
484 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
485 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
486 #else
487 {"CURLE_SSL_CERTPROBLEN", -1},
488 #endif
489 #if HAVE_DECL_CURLE_SSL_CIPHER
490 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
491 #else
492 {"CURLE_SSL_CIPHER", -1},
493 #endif
494 #if HAVE_DECL_CURLE_SSL_CACERT
495 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
496 #else
497 {"CURLE_SSL_CACERT", -1},
498 #endif
499 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
500 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
501 #else
502 {"CURLE_BAD_CONTENT_ENCODING", -1},
503 #endif
504 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
505 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
506 #else
507 {"CURLE_LDAP_INVALID_URL", -1},
508 #endif
509 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
510 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
511 #else
512 {"CURLE_FILESIZE_EXCEEDED", -1},
513 #endif
514 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
515 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
516 #else
517 {"CURLE_FTP_SSL_FAILED", -1},
518 #endif
519 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
520 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
521 #else
522 {"CURLE_SEND_FAIL_REWIND", -1},
523 #endif
524 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
525 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
526 #else
527 {"CURLE_SSL_ENGINE_INITFAILED", -1},
528 #endif
529 #if HAVE_DECL_CURLE_LOGIN_DENIED
530 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
531 #else
532 {"CURLE_LOGIN_DENIED", -1},
533 #endif
534 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
535 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
536 #else
537 {"CURLE_TFTP_NOTFOUND", -1},
538 #endif
539 #if HAVE_DECL_CURLE_TFTP_PERM
540 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
541 #else
542 {"CURLE_TFTP_PERM", -1},
543 #endif
544 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
545 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
546 #else
547 {"CURLE_REMOTE_DISK_FULL", -1},
548 #endif
549 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
550 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
551 #else
552 {"CURLE_TFTP_ILLEGAL", -1},
553 #endif
554 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
555 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
556 #else
557 {"CURLE_TFTP_UNKNOWNID", -1},
558 #endif
559 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
560 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
561 #else
562 {"CURLE_REMOTE_FILE_EXISTS", -1},
563 #endif
564 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
565 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
566 #else
567 {"CURLE_TFTP_NOSUCHUSER", -1},
568 #endif
569 #if HAVE_DECL_CURLE_CONV_FAILED
570 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
571 #else
572 {"CURLE_CONV_FAILED", -1},
573 #endif
574 #if HAVE_DECL_CURLE_CONV_REQUIRED
575 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
576 #else
577 {"CURLE_CONV_REQUIRED", -1},
578 #endif
579 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
580 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
581 #else
582 {"CURLE_SSL_CACERT_BADFILE", -1},
583 #endif
584 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
585 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
586 #else
587 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
588 #endif
589 #if HAVE_DECL_CURLE_SSH
590 {"CURLE_SSH", CURLE_SSH},
591 #else
592 {"CURLE_SSH", -1},
593 #endif
594 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
595 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
596 #else
597 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
598 #endif
599 #if HAVE_DECL_CURLE_AGAIN
600 {"CURLE_AGAIN", CURLE_AGAIN},
601 #else
602 {"CURLE_AGAIN", -1},
603 #endif
604 {"CURLE_OK", CURLE_OK},
605 {NULL, 0}
608 typedef struct CURLOptionMapping CURLOptionMapping;
610 struct CURLOptionMapping
612 void (*optionHandler)(Connection *, value);
613 char *name;
616 static void handleWriteFunction(Connection *, value);
617 static void handleReadFunction(Connection *, value);
618 static void handleInFileSize(Connection *, value);
619 static void handleURL(Connection *, value);
620 static void handleProxy(Connection *, value);
621 static void handleProxyPort(Connection *, value);
622 static void handleHTTPProxyTunnel(Connection *, value);
623 static void handleVerbose(Connection *, value);
624 static void handleHeader(Connection *, value);
625 static void handleNoProgress(Connection *, value);
626 static void handleNoSignal(Connection *, value);
627 static void handleNoBody(Connection *, value);
628 static void handleFailOnError(Connection *, value);
629 static void handleUpload(Connection *, value);
630 static void handlePost(Connection *, value);
631 static void handleFTPListOnly(Connection *, value);
632 static void handleFTPAppend(Connection *, value);
633 static void handleNETRC(Connection *, value);
634 static void handleEncoding(Connection *, value);
635 static void handleFollowLocation(Connection *, value);
636 static void handleTransferText(Connection *, value);
637 static void handlePut(Connection *, value);
638 static void handleUserPwd(Connection *, value);
639 static void handleProxyUserPwd(Connection *, value);
640 static void handleRange(Connection *, value);
641 static void handleErrorBuffer(Connection *, value);
642 static void handleTimeout(Connection *, value);
643 static void handlePostFields(Connection *, value);
644 static void handlePostFieldSize(Connection *, value);
645 static void handleReferer(Connection *, value);
646 static void handleUserAgent(Connection *, value);
647 static void handleFTPPort(Connection *, value);
648 static void handleLowSpeedLimit(Connection *, value);
649 static void handleLowSpeedTime(Connection *, value);
650 static void handleResumeFrom(Connection *, value);
651 static void handleCookie(Connection *, value);
652 static void handleHTTPHeader(Connection *, value);
653 static void handleHTTPPost(Connection *, value);
654 static void handleSSLCert(Connection *, value);
655 static void handleSSLCertType(Connection *, value);
656 static void handleSSLCertPasswd(Connection *, value);
657 static void handleSSLKey(Connection *, value);
658 static void handleSSLKeyType(Connection *, value);
659 static void handleSSLKeyPasswd(Connection *, value);
660 static void handleSSLEngine(Connection *, value);
661 static void handleSSLEngineDefault(Connection *, value);
662 static void handleCRLF(Connection *, value);
663 static void handleQuote(Connection *, value);
664 static void handlePostQuote(Connection *, value);
665 static void handleHeaderFunction(Connection *, value);
666 static void handleCookieFile(Connection *, value);
667 static void handleSSLVersion(Connection *, value);
668 static void handleTimeCondition(Connection *, value);
669 static void handleTimeValue(Connection *, value);
670 static void handleCustomRequest(Connection *, value);
671 static void handleInterface(Connection *, value);
672 static void handleKRB4Level(Connection *, value);
673 static void handleProgressFunction(Connection *, value);
674 static void handleSSLVerifyPeer(Connection *, value);
675 static void handleCAInfo(Connection *, value);
676 static void handleCAPath(Connection *, value);
677 static void handleFileTime(Connection *, value);
678 static void handleMaxRedirs(Connection *, value);
679 static void handleMaxConnects(Connection *, value);
680 static void handleClosePolicy(Connection *, value);
681 static void handleFreshConnect(Connection *, value);
682 static void handleForbidReuse(Connection *, value);
683 static void handleRandomFile(Connection *, value);
684 static void handleEGDSocket(Connection *, value);
685 static void handleConnectTimeout(Connection *, value);
686 static void handleHTTPGet(Connection *, value);
687 static void handleSSLVerifyHost(Connection *, value);
688 static void handleCookieJar(Connection *, value);
689 static void handleSSLCipherList(Connection *, value);
690 static void handleHTTPVersion(Connection *, value);
691 static void handleFTPUseEPSV(Connection *, value);
692 static void handleDNSCacheTimeout(Connection *, value);
693 static void handleDNSUseGlobalCache(Connection *, value);
694 static void handleDebugFunction(Connection *, value);
695 static void handlePrivate(Connection *, value);
696 static void handleHTTP200Aliases(Connection *, value);
697 static void handleUnrestrictedAuth(Connection *, value);
698 static void handleFTPUseEPRT(Connection *, value);
699 static void handleHTTPAuth(Connection *, value);
700 static void handleFTPCreateMissingDirs(Connection *, value);
701 static void handleProxyAuth(Connection *, value);
702 static void handleFTPResponseTimeout(Connection *, value);
703 static void handleIPResolve(Connection *, value);
704 static void handleMaxFileSize(Connection *, value);
705 static void handleInFileSizeLarge(Connection *, value);
706 static void handleResumeFromLarge(Connection *, value);
707 static void handleMaxFileSizeLarge(Connection *, value);
708 static void handleNETRCFile(Connection *, value);
709 static void handleFTPSSL(Connection *, value);
710 static void handlePostFieldSizeLarge(Connection *, value);
711 static void handleTCPNoDelay(Connection *, value);
712 static void handleFTPSSLAuth(Connection *, value);
713 static void handleIOCTLFunction(Connection *, value);
714 static void handleFTPAccount(Connection *, value);
715 static void handleCookieList(Connection *, value);
716 static void handleIgnoreContentLength(Connection *, value);
717 static void handleFTPSkipPASVIP(Connection *, value);
718 static void handleFTPFileMethod(Connection *, value);
719 static void handleLocalPort(Connection *, value);
720 static void handleLocalPortRange(Connection *, value);
721 static void handleConnectOnly(Connection *, value);
722 static void handleMaxSendSpeedLarge(Connection *, value);
723 static void handleMaxRecvSpeedLarge(Connection *, value);
724 static void handleFTPAlternativeToUser(Connection *, value);
725 static void handleSSLSessionIdCache(Connection *, value);
726 static void handleSSHAuthTypes(Connection *, value);
727 static void handleSSHPublicKeyFile(Connection *, value);
728 static void handleSSHPrivateKeyFile(Connection *, value);
729 static void handleFTPSSLCCC(Connection *, value);
730 static void handleTimeoutMS(Connection *, value);
731 static void handleConnectTimeoutMS(Connection *, value);
732 static void handleHTTPTransferDecoding(Connection *, value);
733 static void handleHTTPContentDecoding(Connection *, value);
734 static void handleNewFilePerms(Connection *, value);
735 static void handleNewDirectoryPerms(Connection *, value);
736 static void handlePost301(Connection *, value);
737 static void handleSSHHostPublicKeyMD5(Connection *, value);
738 static void handleCopyPostFields(Connection *, value);
739 static void handleProxyTransferMode(Connection *, value);
740 static void handleSeekFunction(Connection *, value);
741 static void handleAutoReferer(Connection *, value);
742 static void handleOpenSocketFunction(Connection *, value);
743 static void handleProxyType(Connection *, value);
744 static void handleProtocols(Connection *, value);
745 static void handleRedirProtocols(Connection *, value);
746 static void handleResolve(Connection *, value);
747 static void handleDnsServers(Connection *, value);
748 static void handleMailFrom(Connection *, value);
749 static void handleMailRcpt(Connection *, value);
751 CURLOptionMapping implementedOptionMap[] =
753 {handleWriteFunction, "CURLOPT_WRITEFUNCTION"},
754 {handleReadFunction, "CURLOPT_READFUNCTION"},
755 {handleInFileSize, "CURLOPT_INFILESIZE"},
756 {handleURL, "CURLOPT_URL"},
757 {handleProxy, "CURLOPT_PROXY"},
758 {handleProxyPort, "CURLOPT_PROXYPORT"},
759 {handleHTTPProxyTunnel, "CURLOPT_HTTPPROXYTUNNEL"},
760 {handleVerbose, "CURLOPT_VERBOSE"},
761 {handleHeader, "CURLOPT_HEADER"},
762 {handleNoProgress, "CURLOPT_NOPROGRESS"},
763 #if HAVE_DECL_CURLOPT_NOSIGNAL
764 {handleNoSignal, "CURLOPT_NOSIGNAL"},
765 #else
766 {NULL, "CURLOPT_NOSIGNAL"},
767 #endif
768 {handleNoBody, "CURLOPT_NOBODY"},
769 {handleFailOnError, "CURLOPT_FAILONERROR"},
770 {handleUpload, "CURLOPT_UPLOAD"},
771 {handlePost, "CURLOPT_POST"},
772 {handleFTPListOnly, "CURLOPT_FTPLISTONLY"},
773 {handleFTPAppend, "CURLOPT_FTPAPPEND"},
774 {handleNETRC, "CURLOPT_NETRC"},
775 #if HAVE_DECL_CURLOPT_ENCODING
776 {handleEncoding, "CURLOPT_ENCODING"},
777 #else
778 {NULL, "CURLOPT_ENCODING"},
779 #endif
780 {handleFollowLocation, "CURLOPT_FOLLOWLOCATION"},
781 {handleTransferText, "CURLOPT_TRANSFERTEXT"},
782 {handlePut, "CURLOPT_PUT"},
783 {handleUserPwd, "CURLOPT_USERPWD"},
784 {handleProxyUserPwd, "CURLOPT_PROXYUSERPWD"},
785 {handleRange, "CURLOPT_RANGE"},
786 {handleErrorBuffer, "CURLOPT_ERRORBUFFER"},
787 {handleTimeout, "CURLOPT_TIMEOUT"},
788 {handlePostFields, "CURLOPT_POSTFIELDS"},
789 {handlePostFieldSize, "CURLOPT_POSTFIELDSIZE"},
790 {handleReferer, "CURLOPT_REFERER"},
791 {handleUserAgent, "CURLOPT_USERAGENT"},
792 {handleFTPPort, "CURLOPT_FTPPORT"},
793 {handleLowSpeedLimit, "CURLOPT_LOW_SPEED_LIMIT"},
794 {handleLowSpeedTime, "CURLOPT_LOW_SPEED_TIME"},
795 {handleResumeFrom, "CURLOPT_RESUME_FROM"},
796 {handleCookie, "CURLOPT_COOKIE"},
797 {handleHTTPHeader, "CURLOPT_HTTPHEADER"},
798 {handleHTTPPost, "CURLOPT_HTTPPOST"},
799 {handleSSLCert, "CURLOPT_SSLCERT"},
800 {handleSSLCertType, "CURLOPT_SSLCERTTYPE"},
801 {handleSSLCertPasswd, "CURLOPT_SSLCERTPASSWD"},
802 {handleSSLKey, "CURLOPT_SSLKEY"},
803 {handleSSLKeyType, "CURLOPT_SSLKEYTYPE"},
804 {handleSSLKeyPasswd, "CURLOPT_SSLKEYPASSWD"},
805 {handleSSLEngine, "CURLOPT_SSLENGINE"},
806 {handleSSLEngineDefault, "CURLOPT_SSLENGINE_DEFAULT"},
807 {handleCRLF, "CURLOPT_CRLF"},
808 {handleQuote, "CURLOPT_QUOTE"},
809 {handlePostQuote, "CURLOPT_POSTQUOTE"},
810 {handleHeaderFunction, "CURLOPT_HEADERFUNCTION"},
811 {handleCookieFile, "CURLOPT_COOKIEFILE"},
812 {handleSSLVersion, "CURLOPT_SSLVERSION"},
813 {handleTimeCondition, "CURLOPT_TIMECONDITION"},
814 {handleTimeValue, "CURLOPT_TIMEVALUE"},
815 {handleCustomRequest, "CURLOPT_CUSTOMREQUEST"},
816 {handleInterface, "CURLOPT_INTERFACE"},
817 {handleKRB4Level, "CURLOPT_KRB4LEVEL"},
818 {handleProgressFunction, "CURLOPT_PROGRESSFUNCTION"},
819 {handleSSLVerifyPeer, "CURLOPT_SSLVERIFYPEER"},
820 {handleCAInfo, "CURLOPT_CAINFO"},
821 {handleCAPath, "CURLOPT_CAPATH"},
822 {handleFileTime, "CURLOPT_FILETIME"},
823 {handleMaxRedirs, "CURLOPT_MAXREDIRS"},
824 {handleMaxConnects, "CURLOPT_MAXCONNECTS"},
825 {handleClosePolicy, "CURLOPT_CLOSEPOLICY"},
826 {handleFreshConnect, "CURLOPT_FRESH_CONNECT"},
827 {handleForbidReuse, "CURLOPT_FORBID_REUSE"},
828 {handleRandomFile, "CURLOPT_RANDOM_FILE"},
829 {handleEGDSocket, "CURLOPT_EGDSOCKET"},
830 {handleConnectTimeout, "CURLOPT_CONNECTTIMEOUT"},
831 {handleHTTPGet, "CURLOPT_HTTPGET"},
832 {handleSSLVerifyHost, "CURLOPT_SSL_VERIFYHOST"},
833 {handleCookieJar, "CURLOPT_COOKIEJAR"},
834 {handleSSLCipherList, "CURLOPT_SSL_CIPHERLIST"},
835 {handleHTTPVersion, "CURLOPT_HTTP_VERSION"},
836 {handleFTPUseEPSV, "CURLOPT_FTP_USE_EPSV"},
837 {handleDNSCacheTimeout, "CURLOPT_DNS_CACHE_TIMEOUT"},
838 {handleDNSUseGlobalCache, "CURLOPT_DNS_USE_GLOBAL_CACHE"},
839 {handleDebugFunction, "CURLOPT_DEBUGFUNCTION"},
840 #if HAVE_DECL_CURLOPT_PRIVATE
841 {handlePrivate, "CURLOPT_PRIVATE"},
842 #else
843 {NULL, "CURLOPT_PRIVATE"},
844 #endif
845 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
846 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES"},
847 #else
848 {NULL, "CURLOPT_HTTP200ALIASES"},
849 #endif
850 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
851 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH"},
852 #else
853 {NULL, "CURLOPT_UNRESTRICTED_AUTH"},
854 #endif
855 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
856 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT"},
857 #else
858 {NULL, "CURLOPT_FTP_USE_EPRT"},
859 #endif
860 #if HAVE_DECL_CURLOPT_HTTPAUTH
861 {handleHTTPAuth, "CURLOPT_HTTPAUTH"},
862 #else
863 {NULL, "CURLOPT_HTTPAUTH"},
864 #endif
865 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
866 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS"},
867 #else
868 {NULL, "CURLOPT_FTP_CREATE_MISSING_DIRS"},
869 #endif
870 #if HAVE_DECL_CURLOPT_PROXYAUTH
871 {handleProxyAuth, "CURLOPT_PROXYAUTH"},
872 #else
873 {NULL, "CURLOPT_PROXYAUTH"},
874 #endif
875 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
876 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT"},
877 #else
878 {NULL, "CURLOPT_FTP_RESPONSE_TIMEOUT"},
879 #endif
880 #if HAVE_DECL_CURLOPT_IPRESOLVE
881 {handleIPResolve, "CURLOPT_IPRESOLVE"},
882 #else
883 {NULL, "CURLOPT_IPRESOLVE"},
884 #endif
885 #if HAVE_DECL_CURLOPT_MAXFILESIZE
886 {handleMaxFileSize, "CURLOPT_MAXFILESIZE"},
887 #else
888 {NULL, "CURLOPT_MAXFILESIZE"},
889 #endif
890 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
891 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE"},
892 #else
893 {NULL, "CURLOPT_INFILESIZE_LARGE"},
894 #endif
895 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
896 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE"},
897 #else
898 {NULL, "CURLOPT_RESUME_FROM_LARGE"},
899 #endif
900 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
901 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE"},
902 #else
903 {NULL, "CURLOPT_MAXFILESIZE_LARGE"},
904 #endif
905 #if HAVE_DECL_CURLOPT_NETRC_FILE
906 {handleNETRCFile, "CURLOPT_NETRC_FILE"},
907 #else
908 {NULL, "CURLOPT_NETRC_FILE"},
909 #endif
910 #if HAVE_DECL_CURLOPT_FTP_SSL
911 {handleFTPSSL, "CURLOPT_FTP_SSL"},
912 #else
913 {NULL, "CURLOPT_FTP_SSL"},
914 #endif
915 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
916 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE"},
917 #else
918 {NULL, "CURLOPT_POSTFIELDSIZE_LARGE"},
919 #endif
920 #if HAVE_DECL_CURLOPT_TCP_NODELAY
921 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY"},
922 #else
923 {NULL, "CURLOPT_TCP_NODELAY"},
924 #endif
925 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
926 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH"},
927 #else
928 {NULL, "CURLOPT_FTPSSLAUTH"},
929 #endif
930 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
931 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION"},
932 #else
933 {NULL, "CURLOPT_IOCTLFUNCTION"},
934 #endif
935 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
936 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT"},
937 #else
938 {NULL, "CURLOPT_FTP_ACCOUNT"},
939 #endif
940 #if HAVE_DECL_CURLOPT_COOKIELIST
941 {handleCookieList, "CURLOPT_COOKIELIST"},
942 #else
943 {NULL, "CURLOPT_COOKIELIST"},
944 #endif
945 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
946 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH"},
947 #else
948 {NULL, "CURLOPT_IGNORE_CONTENT_LENGTH"},
949 #endif
950 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
951 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP"},
952 #else
953 {NULL, "CURLOPT_FTP_SKIP_PASV_IP"},
954 #endif
955 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
956 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD"},
957 #else
958 {NULL, "CURLOPT_FTP_FILEMETHOD"},
959 #endif
960 #if HAVE_DECL_CURLOPT_LOCALPORT
961 {handleLocalPort, "CURLOPT_LOCALPORT"},
962 #else
963 {NULL, "CURLOPT_LOCALPORT"},
964 #endif
965 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
966 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE"},
967 #else
968 {NULL, "CURLOPT_LOCALPORTRANGE"},
969 #endif
970 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
971 {handleConnectOnly, "CURLOPT_CONNECT_ONLY"},
972 #else
973 {NULL, "CURLOPT_CONNECT_ONLY"},
974 #endif
975 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
976 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE"},
977 #else
978 {NULL, "CURLOPT_MAX_SEND_SPEED_LARGE"},
979 #endif
980 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
981 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE"},
982 #else
983 {NULL, "CURLOPT_MAX_RECV_SPEED_LARGE"},
984 #endif
985 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
986 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERNATIVE_TO_USER"},
987 #else
988 {NULL, "CURLOPT_FTP_ALTERMATIVE_TO_USER"},
989 #endif
990 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
991 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE"},
992 #else
993 {NULL, "CURLOPT_SSL_SESSIONID_CACHE"},
994 #endif
995 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
996 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES"},
997 #else
998 {NULL, "CURLOPT_SSH_AUTH_TYPES"},
999 #endif
1000 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
1001 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE"},
1002 #else
1003 {NULL, "CURLOPT_SSH_PUBLIC_KEYFILE"},
1004 #endif
1005 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
1006 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE"},
1007 #else
1008 {NULL, "CURLOPT_SSH_PRIVATE_KEYFILE"},
1009 #endif
1010 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
1011 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC"},
1012 #else
1013 {NULL, "CURLOPT_FTP_SSL_CCC"},
1014 #endif
1015 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
1016 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS"},
1017 #else
1018 {NULL, "CURLOPT_TIMEOUT_MS"},
1019 #endif
1020 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
1021 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS"},
1022 #else
1023 {NULL, "CURLOPT_CONNECTTIMEOUT_MS"},
1024 #endif
1025 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
1026 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING"},
1027 #else
1028 {NULL, "CURLOPT_HTTP_TRANSFER_DECODING"},
1029 #endif
1030 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
1031 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING"},
1032 #else
1033 {NULL, "CURLOPT_HTTP_CONTENT_DECODING"},
1034 #endif
1035 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
1036 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS"},
1037 #else
1038 {NULL, "CURLOPT_NEW_FILE_PERMS"},
1039 #endif
1040 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
1041 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS"},
1042 #else
1043 {NULL, "CURLOPT_NEW_DIRECTORY_PERMS"},
1044 #endif
1045 #if HAVE_DECL_CURLOPT_POST301
1046 {handlePost301, "CURLOPT_POST301"},
1047 #else
1048 {NULL, "CURLOPT_POST301"},
1049 #endif
1050 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
1051 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5"},
1052 #else
1053 {NULL, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5"},
1054 #endif
1055 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
1056 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS"},
1057 #else
1058 {NULL, "CURLOPT_COPYPOSTFIELDS"},
1059 #endif
1060 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
1061 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE"},
1062 #else
1063 {NULL, "CURLOPT_PROXY_TRANSFER_MODE"},
1064 #endif
1065 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1066 {handleSeekFunction, "CURLOPT_SEEKFUNCTION"},
1067 #else
1068 {NULL, "CURLOPT_SEEKFUNCTION"},
1069 #endif
1070 #if HAVE_DECL_CURLOPT_AUTOREFERER
1071 {handleAutoReferer, "CURLOPT_AUTOREFERER"},
1072 #else
1073 {NULL, "CURLOPT_AUTOREFERER"},
1074 #endif
1075 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1076 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION"},
1077 #else
1078 {NULL, "CURLOPT_OPENSOCKETFUNCTION"},
1079 #endif
1080 #if HAVE_DECL_CURLOPT_PROXYTYPE
1081 {handleProxyType, "CURLOPT_PROXYTYPE"},
1082 #else
1083 {NULL, "CURLOPT_PROXYTYPE"},
1084 #endif
1085 #if HAVE_DECL_CURLOPT_PROTOCOLS
1086 {handleProtocols, "CURLOPT_PROTOCOLS"},
1087 #else
1088 {NULL, "CURLOPT_PROTOCOLS"},
1089 #endif
1090 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
1091 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS"},
1092 #else
1093 {NULL, "CURLOPT_REDIR_PROTOCOLS"},
1094 #endif
1095 #if HAVE_DECL_CURLOPT_RESOLVE
1096 {handleResolve, "CURLOPT_RESOLVE"},
1097 #else
1098 {NULL, "CURLOPT_RESOLVE"},
1099 #endif
1100 #if HAVE_DECL_CURLOPT_DNS_SERVERS
1101 {handleDnsServers, "CURLOPT_DNS_SERVERS"},
1102 #else
1103 {NULL, "CURLOPT_DNS_SERVERS"},
1104 #endif
1105 #if HAVE_DECL_CURLOPT_MAIL_FROM
1106 {handleMailFrom, "CURLOPT_MAIL_FROM"},
1107 #else
1108 {NULL, "CURLOPT_MAIL_FROM"},
1109 #endif
1110 #if HAVE_DECL_CURLOPT_MAIL_RCPT
1111 {handleMailRcpt, "CURLOPT_MAIL_RCPT"},
1112 #else
1113 {NULL, "CURLOPT_MAIL_RCPT"},
1114 #endif
1117 static void free_curl_slist(struct curl_slist *slist)
1119 if (NULL == slist)
1120 return;
1122 curl_slist_free_all(slist);
1125 static void raiseError(Connection *conn, CURLcode code)
1127 CAMLparam0();
1128 CAMLlocal1(exceptionData);
1129 value *exception;
1130 char *errorString = "Unknown Error";
1131 int i;
1133 for (i = 0; errorMap[i].name != NULL; i++)
1135 if (errorMap[i].error == code)
1137 errorString = errorMap[i].name;
1138 break;
1142 exceptionData = caml_alloc(3, 0);
1144 Store_field(exceptionData, 0, Val_int(code));
1145 Store_field(exceptionData, 1, Val_int(code));
1146 Store_field(exceptionData, 2, copy_string(errorString));
1148 if (conn != NULL && conn->errorBuffer != NULL)
1150 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0,
1151 copy_string(conn->errorBuffer));
1154 exception = caml_named_value("CurlException");
1156 if (exception == NULL)
1157 caml_failwith("CurlException not registered");
1159 raise_with_arg(*exception, exceptionData);
1161 CAMLreturn0;
1164 static void resetOcamlValues(Connection* connection)
1166 int i;
1168 for (i = 0; i < OcamlValuesSize; i++)
1169 Store_field(connection->ocamlValues, i, Val_unit);
1172 static Connection* allocConnection(CURL* h)
1174 Connection* connection = (Connection *)malloc(sizeof(Connection));
1176 connection->ocamlValues = caml_alloc(OcamlValuesSize, 0);
1177 resetOcamlValues(connection);
1178 register_global_root(&connection->ocamlValues);
1180 connection->connection = h;
1182 connection->next = NULL;
1183 connection->prev = NULL;
1185 if (connectionList.tail == NULL)
1187 connectionList.tail = connection;
1188 connectionList.head = connection;
1190 else
1192 connection->prev = connectionList.head;
1193 connectionList.head->next = connection;
1194 connectionList.head = connection;
1197 connection->refcount = 0;
1199 connection->url = NULL;
1200 connection->proxy = NULL;
1201 connection->userPwd = NULL;
1202 connection->proxyUserPwd = NULL;
1203 connection->range = NULL;
1204 connection->errorBuffer = NULL;
1205 connection->postFields = NULL;
1206 connection->postFieldSize = -1;
1207 connection->referer = NULL;
1208 connection->userAgent = NULL;
1209 connection->ftpPort = NULL;
1210 connection->cookie = NULL;
1211 connection->httpHeader = NULL;
1212 connection->httpPostFirst = NULL;
1213 connection->httpPostLast = NULL;
1214 connection->httpPostStrings = NULL;
1215 connection->sslCert = NULL;
1216 connection->sslCertType = NULL;
1217 connection->sslCertPasswd = NULL;
1218 connection->sslKey = NULL;
1219 connection->sslKeyType = NULL;
1220 connection->sslKeyPasswd = NULL;
1221 connection->sslEngine = NULL;
1222 connection->quote = NULL;
1223 connection->postQuote = NULL;
1224 connection->cookieFile = NULL;
1225 connection->customRequest = NULL;
1226 connection->interface_ = NULL;
1227 connection->caInfo = NULL;
1228 connection->caPath = NULL;
1229 connection->randomFile = NULL;
1230 connection->egdSocket = NULL;
1231 connection->cookieJar = NULL;
1232 connection->sslCipherList = NULL;
1233 connection->private = NULL;
1234 connection->http200Aliases = NULL;
1235 connection->netrcFile = NULL;
1236 connection->ftpaccount = NULL;
1237 connection->cookielist = NULL;
1238 connection->ftpAlternativeToUser = NULL;
1239 connection->sshPublicKeyFile = NULL;
1240 connection->sshPrivateKeyFile = NULL;
1241 connection->copyPostFields = NULL;
1242 connection->resolve = NULL;
1243 connection->dns_servers = NULL;
1244 connection->mailFrom = NULL;
1245 connection->mailRcpt = NULL;
1247 return connection;
1250 static Connection *newConnection(void)
1252 CURL* h;
1254 caml_enter_blocking_section();
1255 h = curl_easy_init();
1256 caml_leave_blocking_section();
1258 return allocConnection(h);
1261 static Connection *duplicateConnection(Connection *original)
1263 Connection *connection;
1264 CURL* h;
1266 caml_enter_blocking_section();
1267 h = curl_easy_duphandle(original->connection);
1268 caml_leave_blocking_section();
1270 connection = allocConnection(h);
1272 Store_field(connection->ocamlValues, OcamlWriteCallback,
1273 Field(original->ocamlValues, OcamlWriteCallback));
1274 Store_field(connection->ocamlValues, OcamlReadCallback,
1275 Field(original->ocamlValues, OcamlReadCallback));
1276 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1277 Field(original->ocamlValues, OcamlErrorBuffer));
1278 Store_field(connection->ocamlValues, OcamlPostFields,
1279 Field(original->ocamlValues, OcamlPostFields));
1280 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1281 Field(original->ocamlValues, OcamlHTTPHeader));
1282 Store_field(connection->ocamlValues, OcamlQuote,
1283 Field(original->ocamlValues, OcamlQuote));
1284 Store_field(connection->ocamlValues, OcamlPostQuote,
1285 Field(original->ocamlValues, OcamlPostQuote));
1286 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1287 Field(original->ocamlValues, OcamlHeaderCallback));
1288 Store_field(connection->ocamlValues, OcamlProgressCallback,
1289 Field(original->ocamlValues, OcamlProgressCallback));
1290 Store_field(connection->ocamlValues, OcamlDebugCallback,
1291 Field(original->ocamlValues, OcamlDebugCallback));
1292 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1293 Field(original->ocamlValues, OcamlHTTP200Aliases));
1294 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1295 Field(original->ocamlValues, OcamlIOCTLCallback));
1296 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1297 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1299 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1300 handleURL(connection, Field(original->ocamlValues,
1301 OcamlURL));
1302 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1303 handleProxy(connection, Field(original->ocamlValues,
1304 OcamlProxy));
1305 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1306 handleUserPwd(connection, Field(original->ocamlValues,
1307 OcamlUserPWD));
1308 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1309 handleProxyUserPwd(connection, Field(original->ocamlValues,
1310 OcamlProxyUserPWD));
1311 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1312 handleRange(connection, Field(original->ocamlValues,
1313 OcamlRange));
1314 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1315 handleErrorBuffer(connection, Field(original->ocamlValues,
1316 OcamlErrorBuffer));
1317 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1318 handlePostFields(connection, Field(original->ocamlValues,
1319 OcamlPostFields));
1320 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1321 handleReferer(connection, Field(original->ocamlValues,
1322 OcamlReferer));
1323 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1324 handleUserAgent(connection, Field(original->ocamlValues,
1325 OcamlUserAgent));
1326 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1327 handleFTPPort(connection, Field(original->ocamlValues,
1328 OcamlFTPPort));
1329 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1330 handleCookie(connection, Field(original->ocamlValues,
1331 OcamlCookie));
1332 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1333 handleHTTPHeader(connection, Field(original->ocamlValues,
1334 OcamlHTTPHeader));
1335 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1336 handleHTTPPost(connection, Field(original->ocamlValues,
1337 OcamlHTTPPost));
1338 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1339 handleSSLCert(connection, Field(original->ocamlValues,
1340 OcamlSSLCert));
1341 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1342 handleSSLCertType(connection, Field(original->ocamlValues,
1343 OcamlSSLCertType));
1344 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1345 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1346 OcamlSSLCertPasswd));
1347 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1348 handleSSLKey(connection, Field(original->ocamlValues,
1349 OcamlSSLKey));
1350 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1351 handleSSLKeyType(connection, Field(original->ocamlValues,
1352 OcamlSSLKeyType));
1353 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1354 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1355 OcamlSSLKeyPasswd));
1356 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1357 handleSSLEngine(connection, Field(original->ocamlValues,
1358 OcamlSSLEngine));
1359 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1360 handleQuote(connection, Field(original->ocamlValues,
1361 OcamlQuote));
1362 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1363 handlePostQuote(connection, Field(original->ocamlValues,
1364 OcamlPostQuote));
1365 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1366 handleCookieFile(connection, Field(original->ocamlValues,
1367 OcamlCookieFile));
1368 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1369 handleCustomRequest(connection, Field(original->ocamlValues,
1370 OcamlCustomRequest));
1371 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1372 handleInterface(connection, Field(original->ocamlValues,
1373 OcamlInterface));
1374 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1375 handleCAInfo(connection, Field(original->ocamlValues,
1376 OcamlCAInfo));
1377 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1378 handleCAPath(connection, Field(original->ocamlValues,
1379 OcamlCAPath));
1380 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1381 handleRandomFile(connection, Field(original->ocamlValues,
1382 OcamlRandomFile));
1383 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1384 handleEGDSocket(connection, Field(original->ocamlValues,
1385 OcamlEGDSocket));
1386 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1387 handleCookieJar(connection, Field(original->ocamlValues,
1388 OcamlCookieJar));
1389 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1390 handleSSLCipherList(connection, Field(original->ocamlValues,
1391 OcamlSSLCipherList));
1392 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1393 handlePrivate(connection, Field(original->ocamlValues,
1394 OcamlPrivate));
1395 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1396 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1397 OcamlHTTP200Aliases));
1398 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1399 handleNETRCFile(connection, Field(original->ocamlValues,
1400 OcamlNETRCFile));
1401 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1402 handleFTPAccount(connection, Field(original->ocamlValues,
1403 OcamlFTPAccount));
1404 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1405 handleCookieList(connection, Field(original->ocamlValues,
1406 OcamlCookieList));
1407 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1408 handleFTPAlternativeToUser(connection,
1409 Field(original->ocamlValues,
1410 OcamlFTPAlternativeToUser));
1411 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1412 handleSSHPublicKeyFile(connection,
1413 Field(original->ocamlValues,
1414 OcamlSSHPublicKeyFile));
1415 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1416 handleSSHPrivateKeyFile(connection,
1417 Field(original->ocamlValues,
1418 OcamlSSHPrivateKeyFile));
1419 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1420 handleCopyPostFields(connection,
1421 Field(original->ocamlValues,
1422 OcamlCopyPostFields));
1423 if (Field(original->ocamlValues, OcamlDNSServers) != Val_unit)
1424 handleDnsServers(connection,
1425 Field(original->ocamlValues,
1426 OcamlDNSServers));
1427 if (Field(original->ocamlValues, OcamlMailFrom) != Val_unit)
1428 handleMailFrom(connection,
1429 Field(original->ocamlValues,
1430 OcamlMailFrom));
1431 if (Field(original->ocamlValues, OcamlMailRcpt) != Val_unit)
1432 handleMailRcpt(connection,
1433 Field(original->ocamlValues,
1434 OcamlMailRcpt));
1436 return connection;
1439 static void free_if(void* p) { if (NULL != p) free(p); }
1441 static void removeConnection(Connection *connection, int finalization)
1443 const char* fin_url = NULL;
1445 if (!connection->connection)
1447 return; /* already cleaned up */
1450 if (finalization)
1452 /* cannot engage OCaml runtime at finalization, just report leak */
1453 if (CURLE_OK != curl_easy_getinfo(connection->connection, CURLINFO_EFFECTIVE_URL, &fin_url) || NULL == fin_url)
1455 fin_url = "unknown";
1457 fprintf(stderr,"Curl: handle %p leaked, conn %p, url %s\n", connection->connection, connection, fin_url);
1458 fflush(stderr);
1460 else
1462 enter_blocking_section();
1463 curl_easy_cleanup(connection->connection);
1464 leave_blocking_section();
1467 connection->connection = NULL;
1469 if (connectionList.tail == connection)
1470 connectionList.tail = connectionList.tail->next;
1471 if (connectionList.head == connection)
1472 connectionList.head = connectionList.head->prev;
1474 if (connection->next != NULL)
1475 connection->next->prev = connection->prev;
1476 if (connection->prev != NULL)
1477 connection->prev->next = connection->next;
1479 remove_global_root(&connection->ocamlValues);
1481 free_if(connection->url);
1482 free_if(connection->proxy);
1483 free_if(connection->userPwd);
1484 free_if(connection->proxyUserPwd);
1485 free_if(connection->range);
1486 free_if(connection->errorBuffer);
1487 free_if(connection->postFields);
1488 free_if(connection->referer);
1489 free_if(connection->userAgent);
1490 free_if(connection->ftpPort);
1491 free_if(connection->cookie);
1492 free_curl_slist(connection->httpHeader);
1493 if (connection->httpPostFirst != NULL)
1494 curl_formfree(connection->httpPostFirst);
1495 free_curl_slist(connection->httpPostStrings);
1496 free_curl_slist(connection->resolve);
1497 free_if(connection->sslCert);
1498 free_if(connection->sslCertType);
1499 free_if(connection->sslCertPasswd);
1500 free_if(connection->sslKey);
1501 free_if(connection->sslKeyType);
1502 free_if(connection->sslKeyPasswd);
1503 free_if(connection->sslEngine);
1504 free_curl_slist(connection->quote);
1505 free_curl_slist(connection->postQuote);
1506 free_if(connection->cookieFile);
1507 free_if(connection->customRequest);
1508 free_if(connection->interface_);
1509 free_if(connection->caInfo);
1510 free_if(connection->caPath);
1511 free_if(connection->randomFile);
1512 free_if(connection->egdSocket);
1513 free_if(connection->cookieJar);
1514 free_if(connection->sslCipherList);
1515 free_if(connection->private);
1516 free_curl_slist(connection->http200Aliases);
1517 free_if(connection->netrcFile);
1518 free_if(connection->ftpaccount);
1519 free_if(connection->cookielist);
1520 free_if(connection->ftpAlternativeToUser);
1521 free_if(connection->sshPublicKeyFile);
1522 free_if(connection->sshPrivateKeyFile);
1523 free_if(connection->copyPostFields);
1524 free_if(connection->dns_servers);
1525 free_if(connection->mailFrom);
1526 free_curl_slist(connection->mailRcpt);
1529 #if 1
1530 static void checkConnection(Connection * connection)
1532 (void)connection;
1534 #else
1535 static void checkConnection(Connection *connection)
1537 Connection *listIter;
1539 listIter = connectionList.tail;
1541 while (listIter != NULL)
1543 if (listIter == connection)
1544 return;
1546 listIter = listIter->next;
1549 failwith("Invalid Connection");
1551 #endif
1553 static Connection* findConnection(CURL* h)
1555 Connection *listIter;
1557 listIter = connectionList.tail;
1559 while (listIter != NULL)
1561 if (listIter->connection == h)
1562 return listIter;
1564 listIter = listIter->next;
1567 failwith("Unknown handle");
1570 void op_curl_easy_finalize(value v)
1572 Connection* conn = Connection_val(v);
1573 /* same connection may be referenced by several different
1574 OCaml values, see e.g. caml_curl_multi_remove_finished */
1575 conn->refcount--;
1576 if (0 == conn->refcount)
1578 removeConnection(conn, 1);
1579 free(conn);
1583 int op_curl_easy_compare(value v1, value v2)
1585 size_t p1 = (size_t)Connection_val(v1);
1586 size_t p2 = (size_t)Connection_val(v2);
1587 return (p1 == p2 ? 0 : (p1 > p2 ? 1 : -1)); /* compare addresses */
1590 intnat op_curl_easy_hash(value v)
1592 return (size_t)Connection_val(v); /* address */
1595 static struct custom_operations curl_easy_ops = {
1596 "ygrek.curl_easy",
1597 op_curl_easy_finalize,
1598 op_curl_easy_compare,
1599 op_curl_easy_hash,
1600 custom_serialize_default,
1601 custom_deserialize_default,
1602 #if defined(custom_compare_ext_default)
1603 custom_compare_ext_default,
1604 #endif
1607 value caml_curl_alloc(Connection* conn)
1609 value v = caml_alloc_custom(&curl_easy_ops, sizeof(Connection*), 0, 1);
1610 Connection_val(v) = conn;
1611 conn->refcount++;
1612 return v;
1615 #define WRAP_DATA_CALLBACK(f) \
1616 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1618 size_t result;\
1619 leave_blocking_section();\
1620 result = f##_nolock(ptr,size,nmemb,data);\
1621 enter_blocking_section();\
1622 return result;\
1625 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1627 CAMLparam0();
1628 CAMLlocal2(result, str);
1629 Connection *conn = (Connection *)data;
1630 size_t i;
1632 checkConnection(conn);
1634 str = alloc_string(size*nmemb);
1636 for (i = 0; i < size*nmemb; i++)
1637 Byte(str, i) = ptr[i];
1639 result = callback_exn(Field(conn->ocamlValues, OcamlWriteCallback), str);
1641 CAMLreturnT(size_t, Is_exception_result(result) ? 0 : Int_val(result));
1644 WRAP_DATA_CALLBACK(writeFunction)
1646 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1648 CAMLparam0();
1649 CAMLlocal1(result);
1650 Connection *conn = (Connection *)data;
1651 size_t length;
1653 checkConnection(conn);
1655 result = callback_exn(Field(conn->ocamlValues, OcamlReadCallback),
1656 Val_int(size*nmemb));
1658 if (Is_exception_result(result))
1660 CAMLreturnT(size_t,CURL_READFUNC_ABORT);
1663 length = string_length(result);
1665 if (length <= size*nmemb)
1667 memcpy(ptr, String_val(result), length);
1669 CAMLreturnT(size_t,length);
1671 else
1673 CAMLreturnT(size_t,CURL_READFUNC_ABORT);
1677 WRAP_DATA_CALLBACK(readFunction)
1679 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1681 CAMLparam0();
1682 CAMLlocal2(result,str);
1683 Connection *conn = (Connection *)data;
1684 size_t i;
1686 checkConnection(conn);
1688 str = alloc_string(size*nmemb);
1690 for (i = 0; i < size*nmemb; i++)
1691 Byte(str, i) = ptr[i];
1693 result = callback_exn(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1695 CAMLreturnT(size_t, Is_exception_result(result) ? 0 : Int_val(result));
1698 WRAP_DATA_CALLBACK(headerFunction)
1700 static int progressFunction_nolock(void *data,
1701 double dlTotal,
1702 double dlNow,
1703 double ulTotal,
1704 double ulNow)
1706 CAMLparam0();
1707 CAMLlocal1(result);
1708 CAMLlocalN(callbackData, 4);
1709 Connection *conn = (Connection *)data;
1711 checkConnection(conn);
1713 callbackData[0] = copy_double(dlTotal);
1714 callbackData[1] = copy_double(dlNow);
1715 callbackData[2] = copy_double(ulTotal);
1716 callbackData[3] = copy_double(ulNow);
1718 result = callbackN_exn(Field(conn->ocamlValues, OcamlProgressCallback),
1719 4, callbackData);
1721 CAMLreturnT(int, Is_exception_result(result) ? 1 : Bool_val(result));
1724 static int progressFunction(void *data,
1725 double dlTotal,
1726 double dlNow,
1727 double ulTotal,
1728 double ulNow)
1730 int r;
1731 leave_blocking_section();
1732 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1733 enter_blocking_section();
1734 return r;
1737 static int debugFunction_nolock(CURL *debugConnection,
1738 curl_infotype infoType,
1739 char *buffer,
1740 size_t bufferLength,
1741 void *data)
1743 CAMLparam0();
1744 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1745 size_t i;
1746 Connection *conn = (Connection *)data;
1747 (void)debugConnection; /* not used */
1749 checkConnection(conn);
1751 camlDebugConnection = (value)conn;
1752 camlInfoType = Val_long(infoType);
1753 camlMessage = alloc_string(bufferLength);
1755 for (i = 0; i < bufferLength; i++)
1756 Byte(camlMessage, i) = buffer[i];
1758 callback3_exn(Field(conn->ocamlValues, OcamlDebugCallback),
1759 camlDebugConnection,
1760 camlInfoType,
1761 camlMessage);
1763 CAMLreturnT(int, 0);
1766 static int debugFunction(CURL *debugConnection,
1767 curl_infotype infoType,
1768 char *buffer,
1769 size_t bufferLength,
1770 void *data)
1772 int r;
1773 leave_blocking_section();
1774 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1775 enter_blocking_section();
1776 return r;
1779 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1780 int cmd,
1781 void *data)
1783 CAMLparam0();
1784 CAMLlocal3(camlResult, camlConnection, camlCmd);
1785 Connection *conn = (Connection *)data;
1786 curlioerr result = CURLIOE_OK;
1787 (void)ioctl; /* not used */
1789 checkConnection(conn);
1791 if (cmd == CURLIOCMD_NOP)
1792 camlCmd = Val_long(0);
1793 else if (cmd == CURLIOCMD_RESTARTREAD)
1794 camlCmd = Val_long(1);
1795 else
1796 failwith("Invalid IOCTL Cmd!");
1798 camlConnection = caml_curl_alloc(conn);
1800 camlResult = callback2_exn(Field(conn->ocamlValues, OcamlIOCTLCallback),
1801 camlConnection,
1802 camlCmd);
1804 if (Is_exception_result(camlResult))
1806 result = CURLIOE_FAILRESTART;
1808 else
1809 switch (Long_val(camlResult))
1811 case 0: /* CURLIOE_OK */
1812 result = CURLIOE_OK;
1813 break;
1815 case 1: /* CURLIOE_UNKNOWNCMD */
1816 result = CURLIOE_UNKNOWNCMD;
1817 break;
1819 case 2: /* CURLIOE_FAILRESTART */
1820 result = CURLIOE_FAILRESTART;
1821 break;
1823 default: /* Incorrect return value, but let's handle it */
1824 result = CURLIOE_FAILRESTART;
1825 break;
1828 CAMLreturnT(curlioerr, result);
1831 static curlioerr ioctlFunction(CURL *ioctl,
1832 int cmd,
1833 void *data)
1835 curlioerr r;
1836 leave_blocking_section();
1837 r = ioctlFunction_nolock(ioctl, cmd, data);
1838 enter_blocking_section();
1839 return r;
1842 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1843 static int seekFunction_nolock(void *data,
1844 curl_off_t offset,
1845 int origin)
1847 CAMLparam0();
1848 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1849 Connection *conn = (Connection *)data;
1851 camlOffset = copy_int64(offset);
1853 if (origin == SEEK_SET)
1854 camlOrigin = Val_long(0);
1855 else if (origin == SEEK_CUR)
1856 camlOrigin = Val_long(1);
1857 else if (origin == SEEK_END)
1858 camlOrigin = Val_long(2);
1859 else
1860 failwith("Invalid seek code");
1862 camlResult = callback2_exn(Field(conn->ocamlValues,
1863 OcamlSeekFunctionCallback),
1864 camlOffset,
1865 camlOrigin);
1867 int result;
1868 if (Is_exception_result(camlResult))
1869 result = CURL_SEEKFUNC_FAIL;
1870 else
1871 switch (Int_val(camlResult))
1873 case 0: result = CURL_SEEKFUNC_OK; break;
1874 case 1: result = CURL_SEEKFUNC_FAIL; break;
1875 case 2: result = CURL_SEEKFUNC_CANTSEEK; break;
1876 default: failwith("Invalid seek result");
1879 CAMLreturnT(int, result);
1882 static int seekFunction(void *data,
1883 curl_off_t offset,
1884 int origin)
1886 int r;
1887 leave_blocking_section();
1888 r = seekFunction_nolock(data,offset,origin);
1889 enter_blocking_section();
1890 return r;
1893 #endif
1895 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1896 static int openSocketFunction_nolock(void *data,
1897 curlsocktype purpose,
1898 struct curl_sockaddr *addr)
1900 CAMLparam0();
1901 CAMLlocal1(result);
1902 Connection *conn = (Connection *)data;
1903 int sock = -1;
1904 (void)purpose; /* not used */
1906 sock = socket(addr->family, addr->socktype, addr->protocol);
1908 if (-1 != sock)
1910 /* FIXME windows */
1911 result = callback_exn(Field(conn->ocamlValues, OcamlOpenSocketFunctionCallback), Val_int(sock));
1912 if (Is_exception_result(result))
1914 close(sock);
1915 sock = -1;
1919 CAMLreturnT(int, (sock == -1) ? CURL_SOCKET_BAD : sock);
1922 static int openSocketFunction(void *data,
1923 curlsocktype purpose,
1924 struct curl_sockaddr *address)
1926 int r;
1927 leave_blocking_section();
1928 r = openSocketFunction_nolock(data,purpose,address);
1929 enter_blocking_section();
1930 return r;
1933 #endif
1936 ** curl_global_init helper function
1939 CAMLprim value helper_curl_global_init(value initOption)
1941 CAMLparam1(initOption);
1943 switch (Long_val(initOption))
1945 case 0: /* CURLINIT_GLOBALALL */
1946 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1947 break;
1949 case 1: /* CURLINIT_GLOBALSSL */
1950 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1951 break;
1953 case 2: /* CURLINIT_GLOBALWIN32 */
1954 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1955 break;
1957 case 3: /* CURLINIT_GLOBALNOTHING */
1958 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1959 break;
1961 default:
1962 failwith("Invalid Initialization Option");
1963 break;
1966 /* Keep compiler happy, we should never get here due to failwith() */
1967 CAMLreturn(Val_unit);
1971 ** curl_global_cleanup helper function
1974 CAMLprim value helper_curl_global_cleanup(void)
1976 CAMLparam0();
1978 curl_global_cleanup();
1980 CAMLreturn(Val_unit);
1984 ** curl_easy_init helper function
1986 CAMLprim value helper_curl_easy_init(void)
1988 CAMLparam0();
1989 CAMLlocal1(result);
1991 result = caml_curl_alloc(newConnection());
1993 CAMLreturn(result);
1996 CAMLprim value helper_curl_easy_reset(value conn)
1998 CAMLparam1(conn);
1999 Connection *connection = Connection_val(conn);
2001 checkConnection(connection);
2002 curl_easy_reset(connection->connection);
2003 resetOcamlValues(connection);
2005 CAMLreturn(Val_unit);
2009 ** curl_easy_setopt helper utility functions
2012 static void handleWriteFunction(Connection *conn, value option)
2014 CAMLparam1(option);
2015 CURLcode result = CURLE_OK;
2017 if (Tag_val(option) == Closure_tag)
2018 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
2019 else
2020 failwith("Not a proper closure");
2022 result = curl_easy_setopt(conn->connection,
2023 CURLOPT_WRITEFUNCTION,
2024 writeFunction);
2026 if (result != CURLE_OK)
2027 raiseError(conn, result);
2029 result = curl_easy_setopt(conn->connection,
2030 CURLOPT_WRITEDATA,
2031 conn);
2033 if (result != CURLE_OK)
2034 raiseError(conn, result);
2036 CAMLreturn0;
2039 static void handleReadFunction(Connection *conn, value option)
2041 CAMLparam1(option);
2042 CURLcode result = CURLE_OK;
2044 if (Tag_val(option) == Closure_tag)
2045 Store_field(conn->ocamlValues, OcamlReadCallback, option);
2046 else
2047 failwith("Not a proper closure");
2049 result = curl_easy_setopt(conn->connection,
2050 CURLOPT_READFUNCTION,
2051 readFunction);
2053 if (result != CURLE_OK)
2054 raiseError(conn, result);
2056 result = curl_easy_setopt(conn->connection,
2057 CURLOPT_READDATA,
2058 conn);
2060 if (result != CURLE_OK)
2061 raiseError(conn, result);
2063 CAMLreturn0;
2066 static void handleURL(Connection *conn, value option)
2068 CAMLparam1(option);
2069 CURLcode result = CURLE_OK;
2071 Store_field(conn->ocamlValues, OcamlURL, option);
2073 if (conn->url != NULL)
2074 free(conn->url);
2076 conn->url = strdup(String_val(option));
2078 result = curl_easy_setopt(conn->connection,
2079 CURLOPT_URL,
2080 conn->url);
2082 if (result != CURLE_OK)
2083 raiseError(conn, result);
2085 CAMLreturn0;
2088 static void handleInFileSize(Connection *conn, value option)
2090 CAMLparam1(option);
2091 CURLcode result = CURLE_OK;
2093 result = curl_easy_setopt(conn->connection,
2094 CURLOPT_INFILESIZE,
2095 Long_val(option));
2097 if (result != CURLE_OK)
2098 raiseError(conn, result);
2100 CAMLreturn0;
2103 static void handleProxy(Connection *conn, value option)
2105 CAMLparam1(option);
2106 CURLcode result = CURLE_OK;
2108 Store_field(conn->ocamlValues, OcamlProxy, option);
2110 if (conn->proxy != NULL)
2111 free(conn->proxy);
2113 conn->proxy = strdup(String_val(option));
2115 result = curl_easy_setopt(conn->connection,
2116 CURLOPT_PROXY,
2117 conn->proxy);
2119 if (result != CURLE_OK)
2120 raiseError(conn, result);
2122 CAMLreturn0;
2125 static void handleProxyPort(Connection *conn, value option)
2127 CAMLparam1(option);
2128 CURLcode result = CURLE_OK;
2130 result = curl_easy_setopt(conn->connection,
2131 CURLOPT_PROXYPORT,
2132 Long_val(option));
2134 if (result != CURLE_OK)
2135 raiseError(conn, result);
2137 CAMLreturn0;
2140 static void handleHTTPProxyTunnel(Connection *conn, value option)
2142 CAMLparam1(option);
2143 CURLcode result = CURLE_OK;
2145 result = curl_easy_setopt(conn->connection,
2146 CURLOPT_HTTPPROXYTUNNEL,
2147 Bool_val(option));
2149 if (result != CURLE_OK)
2150 raiseError(conn, result);
2152 CAMLreturn0;
2155 static void handleVerbose(Connection *conn, value option)
2157 CAMLparam1(option);
2158 CURLcode result = CURLE_OK;
2160 result = curl_easy_setopt(conn->connection,
2161 CURLOPT_VERBOSE,
2162 Bool_val(option));
2164 if (result != CURLE_OK)
2165 raiseError(conn, result);
2167 CAMLreturn0;
2170 static void handleHeader(Connection *conn, value option)
2172 CAMLparam1(option);
2173 CURLcode result = CURLE_OK;
2175 result = curl_easy_setopt(conn->connection,
2176 CURLOPT_HEADER,
2177 Bool_val(option));
2179 if (result != CURLE_OK)
2180 raiseError(conn, result);
2182 CAMLreturn0;
2185 static void handleNoProgress(Connection *conn, value option)
2187 CAMLparam1(option);
2188 CURLcode result = CURLE_OK;
2190 result = curl_easy_setopt(conn->connection,
2191 CURLOPT_NOPROGRESS,
2192 Bool_val(option));
2194 if (result != CURLE_OK)
2195 raiseError(conn, result);
2197 CAMLreturn0;
2200 #if HAVE_DECL_CURLOPT_NOSIGNAL
2201 static void handleNoSignal(Connection *conn, value option)
2203 CAMLparam1(option);
2204 CURLcode result = CURLE_OK;
2206 result = curl_easy_setopt(conn->connection,
2207 CURLOPT_NOSIGNAL,
2208 Bool_val(option));
2210 if (result != CURLE_OK)
2211 raiseError(conn, result);
2213 CAMLreturn0;
2215 #endif
2217 static void handleNoBody(Connection *conn, value option)
2219 CAMLparam1(option);
2220 CURLcode result = CURLE_OK;
2222 result = curl_easy_setopt(conn->connection,
2223 CURLOPT_NOBODY,
2224 Bool_val(option));
2226 if (result != CURLE_OK)
2227 raiseError(conn, result);
2229 CAMLreturn0;
2232 static void handleFailOnError(Connection *conn, value option)
2234 CAMLparam1(option);
2235 CURLcode result = CURLE_OK;
2237 result = curl_easy_setopt(conn->connection,
2238 CURLOPT_FAILONERROR,
2239 Bool_val(option));
2241 if (result != CURLE_OK)
2242 raiseError(conn, result);
2244 CAMLreturn0;
2247 static void handleUpload(Connection *conn, value option)
2249 CAMLparam1(option);
2250 CURLcode result = CURLE_OK;
2252 result = curl_easy_setopt(conn->connection,
2253 CURLOPT_UPLOAD,
2254 Bool_val(option));
2256 if (result != CURLE_OK)
2257 raiseError(conn, result);
2259 CAMLreturn0;
2262 static void handlePost(Connection *conn, value option)
2264 CAMLparam1(option);
2265 CURLcode result = CURLE_OK;
2267 result = curl_easy_setopt(conn->connection,
2268 CURLOPT_POST,
2269 Bool_val(option));
2271 if (result != CURLE_OK)
2272 raiseError(conn, result);
2274 CAMLreturn0;
2277 static void handleFTPListOnly(Connection *conn, value option)
2279 CAMLparam1(option);
2280 CURLcode result = CURLE_OK;
2282 result = curl_easy_setopt(conn->connection,
2283 CURLOPT_FTPLISTONLY,
2284 Bool_val(option));
2286 if (result != CURLE_OK)
2287 raiseError(conn, result);
2289 CAMLreturn0;
2292 static void handleFTPAppend(Connection *conn, value option)
2294 CAMLparam1(option);
2295 CURLcode result = CURLE_OK;
2297 result = curl_easy_setopt(conn->connection,
2298 CURLOPT_FTPAPPEND,
2299 Bool_val(option));
2301 if (result != CURLE_OK)
2302 raiseError(conn, result);
2304 CAMLreturn0;
2307 static void handleNETRC(Connection *conn, value option)
2309 CAMLparam1(option);
2310 CURLcode result = CURLE_OK;
2311 long netrc;
2313 switch (Long_val(option))
2315 case 0: /* CURL_NETRC_OPTIONAL */
2316 netrc = CURL_NETRC_OPTIONAL;
2317 break;
2319 case 1:/* CURL_NETRC_IGNORED */
2320 netrc = CURL_NETRC_IGNORED;
2321 break;
2323 case 2: /* CURL_NETRC_REQUIRED */
2324 netrc = CURL_NETRC_REQUIRED;
2325 break;
2327 default:
2328 failwith("Invalid NETRC Option");
2329 break;
2332 result = curl_easy_setopt(conn->connection,
2333 CURLOPT_NETRC,
2334 netrc);
2336 if (result != CURLE_OK)
2337 raiseError(conn, result);
2339 CAMLreturn0;
2342 #if HAVE_DECL_CURLOPT_ENCODING
2343 static void handleEncoding(Connection *conn, value option)
2345 CAMLparam1(option);
2346 CURLcode result = CURLE_OK;
2348 switch (Long_val(option))
2350 case 0: /* CURL_ENCODING_NONE */
2351 result = curl_easy_setopt(conn->connection,
2352 CURLOPT_ENCODING,
2353 "identity");
2354 break;
2356 case 1: /* CURL_ENCODING_DEFLATE */
2357 result = curl_easy_setopt(conn->connection,
2358 CURLOPT_ENCODING,
2359 "deflate");
2360 break;
2362 case 2: /* CURL_ENCODING_GZIP */
2363 result = curl_easy_setopt(conn->connection,
2364 CURLOPT_ENCODING,
2365 "gzip");
2366 break;
2368 case 3: /* CURL_ENCODING_ANY */
2369 result = curl_easy_setopt(conn->connection,
2370 CURLOPT_ENCODING,
2371 "");
2372 break;
2374 default:
2375 failwith("Invalid Encoding Option");
2376 break;
2379 if (result != CURLE_OK)
2380 raiseError(conn, result);
2382 CAMLreturn0;
2384 #endif
2386 static void handleFollowLocation(Connection *conn, value option)
2388 CAMLparam1(option);
2389 CURLcode result = CURLE_OK;
2391 result = curl_easy_setopt(conn->connection,
2392 CURLOPT_FOLLOWLOCATION,
2393 Bool_val(option));
2395 if (result != CURLE_OK)
2396 raiseError(conn, result);
2398 CAMLreturn0;
2401 static void handleTransferText(Connection *conn, value option)
2403 CAMLparam1(option);
2404 CURLcode result = CURLE_OK;
2406 result = curl_easy_setopt(conn->connection,
2407 CURLOPT_TRANSFERTEXT,
2408 Bool_val(option));
2410 if (result != CURLE_OK)
2411 raiseError(conn, result);
2413 CAMLreturn0;
2416 static void handlePut(Connection *conn, value option)
2418 CAMLparam1(option);
2419 CURLcode result = CURLE_OK;
2421 result = curl_easy_setopt(conn->connection,
2422 CURLOPT_PUT,
2423 Bool_val(option));
2425 if (result != CURLE_OK)
2426 raiseError(conn, result);
2428 CAMLreturn0;
2431 static void handleUserPwd(Connection *conn, value option)
2433 CAMLparam1(option);
2434 CURLcode result = CURLE_OK;
2436 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2438 if (conn->userPwd != NULL)
2439 free(conn->userPwd);
2441 conn->userPwd = strdup(String_val(option));
2443 result = curl_easy_setopt(conn->connection,
2444 CURLOPT_USERPWD,
2445 conn->userPwd);
2447 if (result != CURLE_OK)
2448 raiseError(conn, result);
2450 CAMLreturn0;
2453 static void handleProxyUserPwd(Connection *conn, value option)
2455 CAMLparam1(option);
2456 CURLcode result = CURLE_OK;
2458 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2460 if (conn->proxyUserPwd != NULL)
2461 free(conn->proxyUserPwd);
2463 conn->proxyUserPwd = strdup(String_val(option));
2465 result = curl_easy_setopt(conn->connection,
2466 CURLOPT_PROXYUSERPWD,
2467 conn->proxyUserPwd);
2469 if (result != CURLE_OK)
2470 raiseError(conn, result);
2472 CAMLreturn0;
2475 static void handleRange(Connection *conn, value option)
2477 CAMLparam1(option);
2478 CURLcode result = CURLE_OK;
2480 Store_field(conn->ocamlValues, OcamlRange, option);
2482 if (conn->range != NULL)
2483 free(conn->range);
2485 conn->range = strdup(String_val(option));
2487 result = curl_easy_setopt(conn->connection,
2488 CURLOPT_RANGE,
2489 conn->range);
2491 if (result != CURLE_OK)
2492 raiseError(conn, result);
2494 CAMLreturn0;
2497 static void handleErrorBuffer(Connection *conn, value option)
2499 CAMLparam1(option);
2500 CURLcode result = CURLE_OK;
2502 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2504 if (conn->errorBuffer != NULL)
2505 free(conn->errorBuffer);
2507 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2509 result = curl_easy_setopt(conn->connection,
2510 CURLOPT_ERRORBUFFER,
2511 conn->errorBuffer);
2513 if (result != CURLE_OK)
2514 raiseError(conn, result);
2516 CAMLreturn0;
2519 static void handleTimeout(Connection *conn, value option)
2521 CAMLparam1(option);
2522 CURLcode result = CURLE_OK;
2524 result = curl_easy_setopt(conn->connection,
2525 CURLOPT_TIMEOUT,
2526 Long_val(option));
2528 if (result != CURLE_OK)
2529 raiseError(conn, result);
2531 CAMLreturn0;
2534 static void handlePostFields(Connection *conn, value option)
2536 CAMLparam1(option);
2537 CURLcode result = CURLE_OK;
2539 Store_field(conn->ocamlValues, OcamlPostFields, option);
2541 if (conn->postFields != NULL)
2542 free(conn->postFields);
2544 conn->postFields = malloc(string_length(option)+1);
2545 memcpy(conn->postFields, String_val(option), string_length(option)+1);
2547 result = curl_easy_setopt(conn->connection,
2548 CURLOPT_POSTFIELDS,
2549 conn->postFields);
2551 if (result != CURLE_OK)
2552 raiseError(conn, result);
2554 CAMLreturn0;
2557 static void handlePostFieldSize(Connection *conn, value option)
2559 CAMLparam1(option);
2560 CURLcode result = CURLE_OK;
2562 result = curl_easy_setopt(conn->connection,
2563 CURLOPT_POSTFIELDSIZE,
2564 Long_val(option));
2566 if (result != CURLE_OK)
2567 raiseError(conn, result);
2569 CAMLreturn0;
2572 static void handleReferer(Connection *conn, value option)
2574 CAMLparam1(option);
2575 CURLcode result = CURLE_OK;
2577 Store_field(conn->ocamlValues, OcamlReferer, option);
2579 if (conn->referer != NULL)
2580 free(conn->referer);
2582 conn->referer = strdup(String_val(option));
2584 result = curl_easy_setopt(conn->connection,
2585 CURLOPT_REFERER,
2586 conn->referer);
2588 if (result != CURLE_OK)
2589 raiseError(conn, result);
2591 CAMLreturn0;
2594 static void handleUserAgent(Connection *conn, value option)
2596 CAMLparam1(option);
2597 CURLcode result = CURLE_OK;
2599 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2601 if (conn->userAgent != NULL)
2602 free(conn->userAgent);
2604 conn->userAgent = strdup(String_val(option));
2606 result = curl_easy_setopt(conn->connection,
2607 CURLOPT_USERAGENT,
2608 conn->userAgent);
2610 if (result != CURLE_OK)
2611 raiseError(conn, result);
2613 CAMLreturn0;
2616 static void handleFTPPort(Connection *conn, value option)
2618 CAMLparam1(option);
2619 CURLcode result = CURLE_OK;
2621 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2623 if (conn->ftpPort != NULL)
2624 free(conn->ftpPort);
2626 conn->ftpPort = strdup(String_val(option));
2628 result = curl_easy_setopt(conn->connection,
2629 CURLOPT_FTPPORT,
2630 conn->ftpPort);
2632 if (result != CURLE_OK)
2633 raiseError(conn, result);
2635 CAMLreturn0;
2638 static void handleLowSpeedLimit(Connection *conn, value option)
2640 CAMLparam1(option);
2641 CURLcode result = CURLE_OK;
2643 result = curl_easy_setopt(conn->connection,
2644 CURLOPT_LOW_SPEED_LIMIT,
2645 Long_val(option));
2647 if (result != CURLE_OK)
2648 raiseError(conn, result);
2650 CAMLreturn0;
2653 static void handleLowSpeedTime(Connection *conn, value option)
2655 CAMLparam1(option);
2656 CURLcode result = CURLE_OK;
2658 result = curl_easy_setopt(conn->connection,
2659 CURLOPT_LOW_SPEED_TIME,
2660 Long_val(option));
2662 if (result != CURLE_OK)
2663 raiseError(conn, result);
2665 CAMLreturn0;
2668 static void handleResumeFrom(Connection *conn, value option)
2670 CAMLparam1(option);
2671 CURLcode result = CURLE_OK;
2673 result = curl_easy_setopt(conn->connection,
2674 CURLOPT_RESUME_FROM,
2675 Long_val(option));
2677 if (result != CURLE_OK)
2678 raiseError(conn, result);
2680 CAMLreturn0;
2683 static void handleCookie(Connection *conn, value option)
2685 CAMLparam1(option);
2686 CURLcode result = CURLE_OK;
2688 Store_field(conn->ocamlValues, OcamlCookie, option);
2690 if (conn->cookie != NULL)
2691 free(conn->cookie);
2693 conn->cookie = strdup(String_val(option));
2695 result = curl_easy_setopt(conn->connection,
2696 CURLOPT_COOKIE,
2697 conn->cookie);
2699 if (result != CURLE_OK)
2700 raiseError(conn, result);
2702 CAMLreturn0;
2705 static void handleHTTPHeader(Connection *conn, value option)
2707 CAMLparam1(option);
2708 CAMLlocal1(listIter);
2709 CURLcode result = CURLE_OK;
2711 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2713 free_curl_slist(conn->httpHeader);
2714 conn->httpHeader = NULL;
2716 listIter = option;
2718 while (!Is_long(listIter))
2720 conn->httpHeader = curl_slist_append(conn->httpHeader, String_val(Field(listIter, 0)));
2722 listIter = Field(listIter, 1);
2725 result = curl_easy_setopt(conn->connection,
2726 CURLOPT_HTTPHEADER,
2727 conn->httpHeader);
2729 if (result != CURLE_OK)
2730 raiseError(conn, result);
2732 CAMLreturn0;
2735 static void handleHTTPPost(Connection *conn, value option)
2737 CAMLparam1(option);
2738 CAMLlocal3(listIter, formItem, contentType);
2739 CURLcode result = CURLE_OK;
2740 char *str1, *str2, *str3, *str4;
2742 listIter = option;
2744 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2746 if (conn->httpPostFirst != NULL)
2747 curl_formfree(conn->httpPostFirst);
2749 conn->httpPostFirst = NULL;
2750 conn->httpPostLast = NULL;
2752 free_curl_slist(conn->httpPostStrings);
2753 conn->httpPostStrings = NULL;
2755 while (!Is_long(listIter))
2757 formItem = Field(listIter, 0);
2759 switch (Tag_val(formItem))
2761 case 0: /* CURLFORM_CONTENT */
2762 if (Wosize_val(formItem) < 3)
2764 failwith("Incorrect CURLFORM_CONTENT parameters");
2767 if (Is_long(Field(formItem, 2)) &&
2768 Long_val(Field(formItem, 2)) == 0)
2770 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2771 memcpy(str1,
2772 String_val(Field(formItem, 0)),
2773 string_length(Field(formItem, 0)));
2774 str1[string_length(Field(formItem, 0))] = 0;
2775 conn->httpPostStrings =
2776 curl_slist_append(conn->httpPostStrings, str1);
2778 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2779 memcpy(str2,
2780 String_val(Field(formItem, 1)),
2781 string_length(Field(formItem, 1)));
2782 str2[string_length(Field(formItem, 1))] = 0;
2783 conn->httpPostStrings =
2784 curl_slist_append(conn->httpPostStrings, str2);
2786 curl_formadd(&conn->httpPostFirst,
2787 &conn->httpPostLast,
2788 CURLFORM_PTRNAME,
2789 str1,
2790 CURLFORM_NAMELENGTH,
2791 string_length(Field(formItem, 0)),
2792 CURLFORM_PTRCONTENTS,
2793 str2,
2794 CURLFORM_CONTENTSLENGTH,
2795 string_length(Field(formItem, 1)),
2796 CURLFORM_END);
2798 else if (Is_block(Field(formItem, 2)))
2800 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2801 memcpy(str1,
2802 String_val(Field(formItem, 0)),
2803 string_length(Field(formItem, 0)));
2804 str1[string_length(Field(formItem, 0))] = 0;
2805 conn->httpPostStrings =
2806 curl_slist_append(conn->httpPostStrings, str1);
2808 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2809 memcpy(str2,
2810 String_val(Field(formItem, 1)),
2811 string_length(Field(formItem, 1)));
2812 str2[string_length(Field(formItem, 1))] = 0;
2813 conn->httpPostStrings =
2814 curl_slist_append(conn->httpPostStrings, str2);
2816 contentType = Field(formItem, 2);
2818 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2819 memcpy(str3,
2820 String_val(Field(contentType, 0)),
2821 string_length(Field(contentType, 0)));
2822 str3[string_length(Field(contentType, 0))] = 0;
2823 conn->httpPostStrings =
2824 curl_slist_append(conn->httpPostStrings, str3);
2826 curl_formadd(&conn->httpPostFirst,
2827 &conn->httpPostLast,
2828 CURLFORM_PTRNAME,
2829 str1,
2830 CURLFORM_NAMELENGTH,
2831 string_length(Field(formItem, 0)),
2832 CURLFORM_PTRCONTENTS,
2833 str2,
2834 CURLFORM_CONTENTSLENGTH,
2835 string_length(Field(formItem, 1)),
2836 CURLFORM_CONTENTTYPE,
2837 str3,
2838 CURLFORM_END);
2840 else
2842 failwith("Incorrect CURLFORM_CONTENT parameters");
2844 break;
2846 case 1: /* CURLFORM_FILECONTENT */
2847 if (Wosize_val(formItem) < 3)
2849 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2852 if (Is_long(Field(formItem, 2)) &&
2853 Long_val(Field(formItem, 2)) == 0)
2855 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2856 memcpy(str1,
2857 String_val(Field(formItem, 0)),
2858 string_length(Field(formItem, 0)));
2859 str1[string_length(Field(formItem, 0))] = 0;
2860 conn->httpPostStrings =
2861 curl_slist_append(conn->httpPostStrings, str1);
2863 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2864 memcpy(str2,
2865 String_val(Field(formItem, 1)),
2866 string_length(Field(formItem, 1)));
2867 str2[string_length(Field(formItem, 1))] = 0;
2868 conn->httpPostStrings =
2869 curl_slist_append(conn->httpPostStrings, str2);
2871 curl_formadd(&conn->httpPostFirst,
2872 &conn->httpPostLast,
2873 CURLFORM_PTRNAME,
2874 str1,
2875 CURLFORM_NAMELENGTH,
2876 string_length(Field(formItem, 0)),
2877 CURLFORM_FILECONTENT,
2878 str2,
2879 CURLFORM_END);
2881 else if (Is_block(Field(formItem, 2)))
2883 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2884 memcpy(str1,
2885 String_val(Field(formItem, 0)),
2886 string_length(Field(formItem, 0)));
2887 str1[string_length(Field(formItem, 0))] = 0;
2888 conn->httpPostStrings =
2889 curl_slist_append(conn->httpPostStrings, str1);
2891 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2892 memcpy(str2,
2893 String_val(Field(formItem, 1)),
2894 string_length(Field(formItem, 1)));
2895 str2[string_length(Field(formItem, 1))] = 0;
2896 conn->httpPostStrings =
2897 curl_slist_append(conn->httpPostStrings, str2);
2899 contentType = Field(formItem, 2);
2901 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2902 memcpy(str3,
2903 String_val(Field(contentType, 0)),
2904 string_length(Field(contentType, 0)));
2905 str3[string_length(Field(contentType, 0))] = 0;
2906 conn->httpPostStrings =
2907 curl_slist_append(conn->httpPostStrings, str3);
2909 curl_formadd(&conn->httpPostFirst,
2910 &conn->httpPostLast,
2911 CURLFORM_PTRNAME,
2912 str1,
2913 CURLFORM_NAMELENGTH,
2914 string_length(Field(formItem, 0)),
2915 CURLFORM_FILECONTENT,
2916 str2,
2917 CURLFORM_CONTENTTYPE,
2918 str3,
2919 CURLFORM_END);
2921 else
2923 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2925 break;
2927 case 2: /* CURLFORM_FILE */
2928 if (Wosize_val(formItem) < 3)
2930 failwith("Incorrect CURLFORM_FILE parameters");
2933 if (Is_long(Field(formItem, 2)) &&
2934 Long_val(Field(formItem, 2)) == 0)
2936 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2937 memcpy(str1,
2938 String_val(Field(formItem, 0)),
2939 string_length(Field(formItem, 0)));
2940 str1[string_length(Field(formItem, 0))] = 0;
2941 conn->httpPostStrings =
2942 curl_slist_append(conn->httpPostStrings, str1);
2944 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2945 memcpy(str2,
2946 String_val(Field(formItem, 1)),
2947 string_length(Field(formItem, 1)));
2948 str2[string_length(Field(formItem, 1))] = 0;
2949 conn->httpPostStrings =
2950 curl_slist_append(conn->httpPostStrings, str2);
2952 curl_formadd(&conn->httpPostFirst,
2953 &conn->httpPostLast,
2954 CURLFORM_PTRNAME,
2955 str1,
2956 CURLFORM_NAMELENGTH,
2957 string_length(Field(formItem, 0)),
2958 CURLFORM_FILE,
2959 str2,
2960 CURLFORM_END);
2962 else if (Is_block(Field(formItem, 2)))
2964 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2965 memcpy(str1,
2966 String_val(Field(formItem, 0)),
2967 string_length(Field(formItem, 0)));
2968 str1[string_length(Field(formItem, 0))] = 0;
2969 conn->httpPostStrings =
2970 curl_slist_append(conn->httpPostStrings, str1);
2972 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2973 memcpy(str2,
2974 String_val(Field(formItem, 1)),
2975 string_length(Field(formItem, 1)));
2976 str2[string_length(Field(formItem, 1))] = 0;
2977 conn->httpPostStrings =
2978 curl_slist_append(conn->httpPostStrings, str2);
2980 contentType = Field(formItem, 2);
2982 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2983 memcpy(str3,
2984 String_val(Field(contentType, 0)),
2985 string_length(Field(contentType, 0)));
2986 str3[string_length(Field(contentType, 0))] = 0;
2987 conn->httpPostStrings =
2988 curl_slist_append(conn->httpPostStrings, str3);
2990 curl_formadd(&conn->httpPostFirst,
2991 &conn->httpPostLast,
2992 CURLFORM_PTRNAME,
2993 str1,
2994 CURLFORM_NAMELENGTH,
2995 string_length(Field(formItem, 0)),
2996 CURLFORM_FILE,
2997 str2,
2998 CURLFORM_CONTENTTYPE,
2999 str3,
3000 CURLFORM_END);
3002 else
3004 failwith("Incorrect CURLFORM_FILE parameters");
3006 break;
3008 case 3: /* CURLFORM_BUFFER */
3009 if (Wosize_val(formItem) < 4)
3011 failwith("Incorrect CURLFORM_BUFFER parameters");
3014 if (Is_long(Field(formItem, 3)) &&
3015 Long_val(Field(formItem, 3)) == 0)
3017 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
3018 memcpy(str1,
3019 String_val(Field(formItem, 0)),
3020 string_length(Field(formItem, 0)));
3021 str1[string_length(Field(formItem, 0))] = 0;
3022 conn->httpPostStrings =
3023 curl_slist_append(conn->httpPostStrings, str1);
3025 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
3026 memcpy(str2,
3027 String_val(Field(formItem, 1)),
3028 string_length(Field(formItem, 1)));
3029 str2[string_length(Field(formItem, 1))] = 0;
3030 conn->httpPostStrings =
3031 curl_slist_append(conn->httpPostStrings, str2);
3033 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
3034 memcpy(str3,
3035 String_val(Field(formItem, 2)),
3036 string_length(Field(formItem, 2)));
3037 str3[string_length(Field(formItem, 2))] = 0;
3038 conn->httpPostStrings =
3039 curl_slist_append(conn->httpPostStrings, str3);
3041 curl_formadd(&conn->httpPostFirst,
3042 &conn->httpPostLast,
3043 CURLFORM_PTRNAME,
3044 str1,
3045 CURLFORM_NAMELENGTH,
3046 string_length(Field(formItem, 0)),
3047 CURLFORM_BUFFER,
3048 str2,
3049 CURLFORM_BUFFERPTR,
3050 str3,
3051 CURLFORM_BUFFERLENGTH,
3052 string_length(Field(formItem, 2)),
3053 CURLFORM_END);
3055 else if (Is_block(Field(formItem, 3)))
3057 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
3058 memcpy(str1,
3059 String_val(Field(formItem, 0)),
3060 string_length(Field(formItem, 0)));
3061 str1[string_length(Field(formItem, 0))] = 0;
3062 conn->httpPostStrings =
3063 curl_slist_append(conn->httpPostStrings, str1);
3065 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
3066 memcpy(str2,
3067 String_val(Field(formItem, 1)),
3068 string_length(Field(formItem, 1)));
3069 str2[string_length(Field(formItem, 1))] = 0;
3070 conn->httpPostStrings =
3071 curl_slist_append(conn->httpPostStrings, str2);
3073 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
3074 memcpy(str3,
3075 String_val(Field(formItem, 2)),
3076 string_length(Field(formItem, 2)));
3077 str3[string_length(Field(formItem, 2))] = 0;
3078 conn->httpPostStrings =
3079 curl_slist_append(conn->httpPostStrings, str3);
3081 contentType = Field(formItem, 3);
3083 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
3084 memcpy(str4,
3085 String_val(Field(contentType, 0)),
3086 string_length(Field(contentType, 0)));
3087 str4[string_length(Field(contentType, 0))] = 0;
3088 conn->httpPostStrings =
3089 curl_slist_append(conn->httpPostStrings, str4);
3091 curl_formadd(&conn->httpPostFirst,
3092 &conn->httpPostLast,
3093 CURLFORM_PTRNAME,
3094 str1,
3095 CURLFORM_NAMELENGTH,
3096 string_length(Field(formItem, 0)),
3097 CURLFORM_BUFFER,
3098 str2,
3099 CURLFORM_BUFFERPTR,
3100 str3,
3101 CURLFORM_BUFFERLENGTH,
3102 string_length(Field(formItem, 2)),
3103 CURLFORM_CONTENTTYPE,
3104 str4,
3105 CURLFORM_END);
3107 else
3109 failwith("Incorrect CURLFORM_BUFFER parameters");
3111 break;
3114 listIter = Field(listIter, 1);
3117 result = curl_easy_setopt(conn->connection,
3118 CURLOPT_HTTPPOST,
3119 conn->httpPostFirst);
3121 if (result != CURLE_OK)
3122 raiseError(conn, result);
3124 CAMLreturn0;
3127 static void handleSSLCert(Connection *conn, value option)
3129 CAMLparam1(option);
3130 CURLcode result = CURLE_OK;
3132 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3134 if (conn->sslCert != NULL)
3135 free(conn->sslCert);
3137 conn->sslCert = strdup(String_val(option));
3139 result = curl_easy_setopt(conn->connection,
3140 CURLOPT_SSLCERT,
3141 conn->sslCert);
3143 if (result != CURLE_OK)
3144 raiseError(conn, result);
3146 CAMLreturn0;
3149 static void handleSSLCertType(Connection *conn, value option)
3151 CAMLparam1(option);
3152 CURLcode result = CURLE_OK;
3154 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3156 if (conn->sslCertType != NULL)
3157 free(conn->sslCertType);
3159 conn->sslCertType = strdup(String_val(option));
3161 result = curl_easy_setopt(conn->connection,
3162 CURLOPT_SSLCERTTYPE,
3163 conn->sslCertType);
3165 if (result != CURLE_OK)
3166 raiseError(conn, result);
3168 CAMLreturn0;
3171 static void handleSSLCertPasswd(Connection *conn, value option)
3173 CAMLparam1(option);
3174 CURLcode result = CURLE_OK;
3176 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3178 if (conn->sslCertPasswd != NULL)
3179 free(conn->sslCertPasswd);
3181 conn->sslCertPasswd = strdup(String_val(option));
3183 result = curl_easy_setopt(conn->connection,
3184 CURLOPT_SSLCERTPASSWD,
3185 conn->sslCertPasswd);
3187 if (result != CURLE_OK)
3188 raiseError(conn, result);
3190 CAMLreturn0;
3193 static void handleSSLKey(Connection *conn, value option)
3195 CAMLparam1(option);
3196 CURLcode result = CURLE_OK;
3198 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3200 if (conn->sslKey != NULL)
3201 free(conn->sslKey);
3203 conn->sslKey = strdup(String_val(option));
3205 result = curl_easy_setopt(conn->connection,
3206 CURLOPT_SSLKEY,
3207 conn->sslKey);
3209 if (result != CURLE_OK)
3210 raiseError(conn, result);
3212 CAMLreturn0;
3215 static void handleSSLKeyType(Connection *conn, value option)
3217 CAMLparam1(option);
3218 CURLcode result = CURLE_OK;
3220 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3222 if (conn->sslKeyType != NULL)
3223 free(conn->sslKeyType);
3225 conn->sslKeyType = strdup(String_val(option));
3227 result = curl_easy_setopt(conn->connection,
3228 CURLOPT_SSLKEYTYPE,
3229 conn->sslKeyType);
3231 if (result != CURLE_OK)
3232 raiseError(conn, result);
3234 CAMLreturn0;
3237 static void handleSSLKeyPasswd(Connection *conn, value option)
3239 CAMLparam1(option);
3240 CURLcode result = CURLE_OK;
3242 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3244 if (conn->sslKeyPasswd != NULL)
3245 free(conn->sslKeyPasswd);
3247 conn->sslKeyPasswd = strdup(String_val(option));
3249 result = curl_easy_setopt(conn->connection,
3250 CURLOPT_SSLKEYPASSWD,
3251 conn->sslKeyPasswd);
3253 if (result != CURLE_OK)
3254 raiseError(conn, result);
3256 CAMLreturn0;
3259 static void handleSSLEngine(Connection *conn, value option)
3261 CAMLparam1(option);
3262 CURLcode result = CURLE_OK;
3264 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3266 if (conn->sslEngine != NULL)
3267 free(conn->sslEngine);
3269 conn->sslEngine = strdup(String_val(option));
3271 result = curl_easy_setopt(conn->connection,
3272 CURLOPT_SSLENGINE,
3273 conn->sslEngine);
3275 if (result != CURLE_OK)
3276 raiseError(conn, result);
3278 CAMLreturn0;
3281 static void handleSSLEngineDefault(Connection *conn, value option)
3283 CAMLparam1(option);
3284 CURLcode result = CURLE_OK;
3286 result = curl_easy_setopt(conn->connection,
3287 CURLOPT_SSLENGINE_DEFAULT,
3288 Bool_val(option));
3290 if (result != CURLE_OK)
3291 raiseError(conn, result);
3293 CAMLreturn0;
3296 static void handleCRLF(Connection *conn, value option)
3298 CAMLparam1(option);
3299 CURLcode result = CURLE_OK;
3301 result = curl_easy_setopt(conn->connection,
3302 CURLOPT_CRLF,
3303 Bool_val(option));
3305 if (result != CURLE_OK)
3306 raiseError(conn, result);
3308 CAMLreturn0;
3311 static void handleQuote(Connection *conn, value option)
3313 CAMLparam1(option);
3314 CAMLlocal1(listIter);
3315 CURLcode result = CURLE_OK;
3317 Store_field(conn->ocamlValues, OcamlQuote, option);
3319 free_curl_slist(conn->quote);
3320 conn->quote = NULL;
3322 listIter = option;
3324 while (!Is_long(listIter))
3326 conn->quote = curl_slist_append(conn->quote, String_val(Field(listIter, 0)));
3328 listIter = Field(listIter, 1);
3331 result = curl_easy_setopt(conn->connection,
3332 CURLOPT_QUOTE,
3333 conn->quote);
3335 if (result != CURLE_OK)
3336 raiseError(conn, result);
3338 CAMLreturn0;
3341 static void handlePostQuote(Connection *conn, value option)
3343 CAMLparam1(option);
3344 CAMLlocal1(listIter);
3345 CURLcode result = CURLE_OK;
3347 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3349 free_curl_slist(conn->postQuote);
3350 conn->postQuote = NULL;
3352 listIter = option;
3354 while (!Is_long(listIter))
3356 conn->postQuote = curl_slist_append(conn->postQuote, String_val(Field(listIter, 0)));
3358 listIter = Field(listIter, 1);
3361 result = curl_easy_setopt(conn->connection,
3362 CURLOPT_POSTQUOTE,
3363 conn->postQuote);
3365 if (result != CURLE_OK)
3366 raiseError(conn, result);
3368 CAMLreturn0;
3371 static void handleHeaderFunction(Connection *conn, value option)
3373 CAMLparam1(option);
3374 CURLcode result = CURLE_OK;
3376 if (Tag_val(option) == Closure_tag)
3377 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3378 else
3379 failwith("Not a proper closure");
3381 result = curl_easy_setopt(conn->connection,
3382 CURLOPT_HEADERFUNCTION,
3383 headerFunction);
3385 if (result != CURLE_OK)
3386 raiseError(conn, result);
3388 result = curl_easy_setopt(conn->connection,
3389 CURLOPT_WRITEHEADER,
3390 conn);
3392 if (result != CURLE_OK)
3393 raiseError(conn, result);
3395 CAMLreturn0;
3398 static void handleCookieFile(Connection *conn, value option)
3400 CAMLparam1(option);
3401 CURLcode result = CURLE_OK;
3403 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3405 if (conn->cookieFile != NULL)
3406 free(conn->cookieFile);
3408 conn->cookieFile = strdup(String_val(option));
3410 result = curl_easy_setopt(conn->connection,
3411 CURLOPT_COOKIEFILE,
3412 conn->cookieFile);
3414 if (result != CURLE_OK)
3415 raiseError(conn, result);
3417 CAMLreturn0;
3420 static void handleSSLVersion(Connection *conn, value option)
3422 CAMLparam1(option);
3423 CURLcode result = CURLE_OK;
3425 result = curl_easy_setopt(conn->connection,
3426 CURLOPT_SSLVERSION,
3427 Long_val(option));
3429 if (result != CURLE_OK)
3430 raiseError(conn, result);
3432 CAMLreturn0;
3435 static void handleTimeCondition(Connection *conn, value option)
3437 CAMLparam1(option);
3438 CURLcode result = CURLE_OK;
3439 int timecond = CURL_TIMECOND_NONE;
3441 switch (Long_val(option))
3443 case 0: timecond = CURL_TIMECOND_NONE; break;
3444 case 1: timecond = CURL_TIMECOND_IFMODSINCE; break;
3445 case 2: timecond = CURL_TIMECOND_IFUNMODSINCE; break;
3446 case 3: timecond = CURL_TIMECOND_LASTMOD; break;
3447 default:
3448 failwith("Invalid TIMECOND Option");
3449 break;
3452 result = curl_easy_setopt(conn->connection, CURLOPT_TIMECONDITION, timecond);
3454 if (result != CURLE_OK)
3455 raiseError(conn, result);
3457 CAMLreturn0;
3460 static void handleTimeValue(Connection *conn, value option)
3462 CAMLparam1(option);
3463 CURLcode result = CURLE_OK;
3465 result = curl_easy_setopt(conn->connection,
3466 CURLOPT_TIMEVALUE,
3467 Int32_val(option));
3469 if (result != CURLE_OK)
3470 raiseError(conn, result);
3472 CAMLreturn0;
3475 static void handleCustomRequest(Connection *conn, value option)
3477 CAMLparam1(option);
3478 CURLcode result = CURLE_OK;
3480 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3482 if (conn->customRequest != NULL)
3483 free(conn->customRequest);
3485 conn->customRequest = strdup(String_val(option));
3487 result = curl_easy_setopt(conn->connection,
3488 CURLOPT_CUSTOMREQUEST,
3489 conn->customRequest);
3491 if (result != CURLE_OK)
3492 raiseError(conn, result);
3494 CAMLreturn0;
3497 static void handleInterface(Connection *conn, value option)
3499 CAMLparam1(option);
3500 CURLcode result = CURLE_OK;
3502 Store_field(conn->ocamlValues, OcamlInterface, option);
3504 if (conn->interface_ != NULL)
3505 free(conn->interface_);
3507 conn->interface_ = strdup(String_val(option));
3509 result = curl_easy_setopt(conn->connection,
3510 CURLOPT_INTERFACE,
3511 conn->interface_);
3513 if (result != CURLE_OK)
3514 raiseError(conn, result);
3516 CAMLreturn0;
3519 static void handleKRB4Level(Connection *conn, value option)
3521 CAMLparam1(option);
3522 CURLcode result = CURLE_OK;
3524 switch (Long_val(option))
3526 case 0: /* KRB4_NONE */
3527 result = curl_easy_setopt(conn->connection,
3528 CURLOPT_KRB4LEVEL,
3529 NULL);
3530 break;
3532 case 1: /* KRB4_CLEAR */
3533 result = curl_easy_setopt(conn->connection,
3534 CURLOPT_KRB4LEVEL,
3535 "clear");
3536 break;
3538 case 2: /* KRB4_SAFE */
3539 result = curl_easy_setopt(conn->connection,
3540 CURLOPT_KRB4LEVEL,
3541 "safe");
3542 break;
3544 case 3: /* KRB4_CONFIDENTIAL */
3545 result = curl_easy_setopt(conn->connection,
3546 CURLOPT_KRB4LEVEL,
3547 "confidential");
3548 break;
3550 case 4: /* KRB4_PRIVATE */
3551 result = curl_easy_setopt(conn->connection,
3552 CURLOPT_KRB4LEVEL,
3553 "private");
3554 break;
3556 default:
3557 failwith("Invalid KRB4 Option");
3558 break;
3561 if (result != CURLE_OK)
3562 raiseError(conn, result);
3564 CAMLreturn0;
3567 static void handleProgressFunction(Connection *conn, value option)
3569 CAMLparam1(option);
3570 CURLcode result = CURLE_OK;
3572 if (Tag_val(option) == Closure_tag)
3573 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3574 else
3575 failwith("Not a proper closure");
3577 result = curl_easy_setopt(conn->connection,
3578 CURLOPT_PROGRESSFUNCTION,
3579 progressFunction);
3580 if (result != CURLE_OK)
3581 raiseError(conn, result);
3583 result = curl_easy_setopt(conn->connection,
3584 CURLOPT_PROGRESSDATA,
3585 conn);
3587 if (result != CURLE_OK)
3588 raiseError(conn, result);
3590 CAMLreturn0;
3593 static void handleSSLVerifyPeer(Connection *conn, value option)
3595 CAMLparam1(option);
3596 CURLcode result = CURLE_OK;
3598 result = curl_easy_setopt(conn->connection,
3599 CURLOPT_SSL_VERIFYPEER,
3600 Bool_val(option));
3602 if (result != CURLE_OK)
3603 raiseError(conn, result);
3605 CAMLreturn0;
3608 static void handleCAInfo(Connection *conn, value option)
3610 CAMLparam1(option);
3611 CURLcode result = CURLE_OK;
3613 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3615 if (conn->caInfo != NULL)
3616 free(conn->caInfo);
3618 conn->caInfo = strdup(String_val(option));
3620 result = curl_easy_setopt(conn->connection,
3621 CURLOPT_CAINFO,
3622 conn->caInfo);
3624 if (result != CURLE_OK)
3625 raiseError(conn, result);
3627 CAMLreturn0;
3630 static void handleCAPath(Connection *conn, value option)
3632 CAMLparam1(option);
3633 CURLcode result = CURLE_OK;
3635 Store_field(conn->ocamlValues, OcamlCAPath, option);
3637 if (conn->caPath != NULL)
3638 free(conn->caPath);
3640 conn->caPath = strdup(String_val(option));
3642 result = curl_easy_setopt(conn->connection,
3643 CURLOPT_CAPATH,
3644 conn->caPath);
3646 if (result != CURLE_OK)
3647 raiseError(conn, result);
3649 CAMLreturn0;
3652 static void handleFileTime(Connection *conn, value option)
3654 CAMLparam1(option);
3655 CURLcode result = CURLE_OK;
3657 result = curl_easy_setopt(conn->connection,
3658 CURLOPT_FILETIME,
3659 Bool_val(option));
3661 if (result != CURLE_OK)
3662 raiseError(conn, result);
3664 CAMLreturn0;
3667 static void handleMaxRedirs(Connection *conn, value option)
3669 CAMLparam1(option);
3670 CURLcode result = CURLE_OK;
3672 result = curl_easy_setopt(conn->connection,
3673 CURLOPT_MAXREDIRS,
3674 Long_val(option));
3676 if (result != CURLE_OK)
3677 raiseError(conn, result);
3679 CAMLreturn0;
3682 static void handleMaxConnects(Connection *conn, value option)
3684 CAMLparam1(option);
3685 CURLcode result = CURLE_OK;
3687 result = curl_easy_setopt(conn->connection,
3688 CURLOPT_MAXCONNECTS,
3689 Long_val(option));
3691 if (result != CURLE_OK)
3692 raiseError(conn, result);
3694 CAMLreturn0;
3697 static void handleClosePolicy(Connection *conn, value option)
3699 CAMLparam1(option);
3700 CURLcode result = CURLE_OK;
3702 switch (Long_val(option))
3704 case 0: /* CLOSEPOLICY_OLDEST */
3705 result = curl_easy_setopt(conn->connection,
3706 CURLOPT_CLOSEPOLICY,
3707 CURLCLOSEPOLICY_OLDEST);
3708 break;
3710 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3711 result = curl_easy_setopt(conn->connection,
3712 CURLOPT_CLOSEPOLICY,
3713 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3714 break;
3716 default:
3717 failwith("Invalid CLOSEPOLICY Option");
3718 break;
3721 if (result != CURLE_OK)
3722 raiseError(conn, result);
3724 CAMLreturn0;
3727 static void handleFreshConnect(Connection *conn, value option)
3729 CAMLparam1(option);
3730 CURLcode result = CURLE_OK;
3732 result = curl_easy_setopt(conn->connection,
3733 CURLOPT_FRESH_CONNECT,
3734 Bool_val(option));
3736 if (result != CURLE_OK)
3737 raiseError(conn, result);
3739 CAMLreturn0;
3742 static void handleForbidReuse(Connection *conn, value option)
3744 CAMLparam1(option);
3745 CURLcode result = CURLE_OK;
3747 result = curl_easy_setopt(conn->connection,
3748 CURLOPT_FORBID_REUSE,
3749 Bool_val(option));
3751 if (result != CURLE_OK)
3752 raiseError(conn, result);
3754 CAMLreturn0;
3757 static void handleRandomFile(Connection *conn, value option)
3759 CAMLparam1(option);
3760 CURLcode result = CURLE_OK;
3762 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3764 if (conn->randomFile != NULL)
3765 free(conn->randomFile);
3767 conn->randomFile = strdup(String_val(option));
3769 result = curl_easy_setopt(conn->connection,
3770 CURLOPT_RANDOM_FILE,
3771 conn->randomFile);
3773 if (result != CURLE_OK)
3774 raiseError(conn, result);
3776 CAMLreturn0;
3779 static void handleEGDSocket(Connection *conn, value option)
3781 CAMLparam1(option);
3782 CURLcode result = CURLE_OK;
3784 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3786 if (conn->egdSocket != NULL)
3787 free(conn->egdSocket);
3789 conn->egdSocket = strdup(String_val(option));
3791 result = curl_easy_setopt(conn->connection,
3792 CURLOPT_EGDSOCKET,
3793 conn->egdSocket);
3795 if (result != CURLE_OK)
3796 raiseError(conn, result);
3798 CAMLreturn0;
3801 static void handleConnectTimeout(Connection *conn, value option)
3803 CAMLparam1(option);
3804 CURLcode result = CURLE_OK;
3806 result = curl_easy_setopt(conn->connection,
3807 CURLOPT_CONNECTTIMEOUT,
3808 Long_val(option));
3810 if (result != CURLE_OK)
3811 raiseError(conn, result);
3813 CAMLreturn0;
3816 static void handleHTTPGet(Connection *conn, value option)
3818 CAMLparam1(option);
3819 CURLcode result = CURLE_OK;
3821 result = curl_easy_setopt(conn->connection,
3822 CURLOPT_HTTPGET,
3823 Bool_val(option));
3825 if (result != CURLE_OK)
3826 raiseError(conn, result);
3828 CAMLreturn0;
3831 static void handleSSLVerifyHost(Connection *conn, value option)
3833 CAMLparam1(option);
3834 CURLcode result = CURLE_OK;
3836 switch (Long_val(option))
3838 case 0: /* SSLVERIFYHOST_NONE */
3839 case 1: /* SSLVERIFYHOST_EXISTENCE */
3840 case 2: /* SSLVERIFYHOST_HOSTNAME */
3841 result = curl_easy_setopt(conn->connection,
3842 CURLOPT_SSL_VERIFYHOST,
3843 /* map EXISTENCE to HOSTNAME */
3844 Long_val(option) == 0 ? 0 : 2);
3845 break;
3847 default:
3848 failwith("Invalid SSLVERIFYHOST Option");
3849 break;
3852 if (result != CURLE_OK)
3853 raiseError(conn, result);
3855 CAMLreturn0;
3858 static void handleCookieJar(Connection *conn, value option)
3860 CAMLparam1(option);
3861 CURLcode result = CURLE_OK;
3863 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3865 if (conn->cookieJar != NULL)
3866 free(conn->cookieJar);
3868 conn->cookieJar = strdup(String_val(option));
3870 result = curl_easy_setopt(conn->connection,
3871 CURLOPT_COOKIEJAR,
3872 conn->cookieJar);
3874 if (result != CURLE_OK)
3875 raiseError(conn, result);
3877 CAMLreturn0;
3880 static void handleSSLCipherList(Connection *conn, value option)
3882 CAMLparam1(option);
3883 CURLcode result = CURLE_OK;
3885 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3887 if (conn->sslCipherList != NULL)
3888 free(conn->sslCipherList);
3890 conn->sslCipherList = strdup(String_val(option));
3892 result = curl_easy_setopt(conn->connection,
3893 CURLOPT_SSL_CIPHER_LIST,
3894 conn->sslCipherList);
3896 if (result != CURLE_OK)
3897 raiseError(conn, result);
3899 CAMLreturn0;
3902 static void handleHTTPVersion(Connection *conn, value option)
3904 CAMLparam1(option);
3905 CURLcode result = CURLE_OK;
3907 switch (Long_val(option))
3909 case 0: /* HTTP_VERSION_NONE */
3910 result = curl_easy_setopt(conn->connection,
3911 CURLOPT_HTTP_VERSION,
3912 CURL_HTTP_VERSION_NONE);
3913 break;
3915 case 1: /* HTTP_VERSION_1_0 */
3916 result = curl_easy_setopt(conn->connection,
3917 CURLOPT_HTTP_VERSION,
3918 CURL_HTTP_VERSION_1_0);
3919 break;
3921 case 2: /* HTTP_VERSION_1_1 */
3922 result = curl_easy_setopt(conn->connection,
3923 CURLOPT_HTTP_VERSION,
3924 CURL_HTTP_VERSION_1_1);
3925 break;
3927 default:
3928 failwith("Invalid HTTP_VERSION Option");
3929 break;
3932 if (result != CURLE_OK)
3933 raiseError(conn, result);
3935 CAMLreturn0;
3938 static void handleFTPUseEPSV(Connection *conn, value option)
3940 CAMLparam1(option);
3941 CURLcode result = CURLE_OK;
3943 result = curl_easy_setopt(conn->connection,
3944 CURLOPT_FTP_USE_EPSV,
3945 Bool_val(option));
3947 if (result != CURLE_OK)
3948 raiseError(conn, result);
3950 CAMLreturn0;
3953 static void handleDNSCacheTimeout(Connection *conn, value option)
3955 CAMLparam1(option);
3956 CURLcode result = CURLE_OK;
3958 result = curl_easy_setopt(conn->connection,
3959 CURLOPT_DNS_CACHE_TIMEOUT,
3960 Long_val(option));
3962 if (result != CURLE_OK)
3963 raiseError(conn, result);
3965 CAMLreturn0;
3968 static void handleDNSUseGlobalCache(Connection *conn, value option)
3970 CAMLparam1(option);
3971 CURLcode result = CURLE_OK;
3973 result = curl_easy_setopt(conn->connection,
3974 CURLOPT_DNS_USE_GLOBAL_CACHE,
3975 Bool_val(option));
3977 if (result != CURLE_OK)
3978 raiseError(conn, result);
3980 CAMLreturn0;
3983 static void handleDebugFunction(Connection *conn, value option)
3985 CAMLparam1(option);
3986 CURLcode result = CURLE_OK;
3988 if (Tag_val(option) == Closure_tag)
3989 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3990 else
3991 failwith("Not a proper closure");
3993 result = curl_easy_setopt(conn->connection,
3994 CURLOPT_DEBUGFUNCTION,
3995 debugFunction);
3996 if (result != CURLE_OK)
3997 raiseError(conn, result);
3999 result = curl_easy_setopt(conn->connection,
4000 CURLOPT_DEBUGDATA,
4001 conn);
4003 if (result != CURLE_OK)
4004 raiseError(conn, result);
4006 CAMLreturn0;
4009 #if HAVE_DECL_CURLOPT_PRIVATE
4010 static void handlePrivate(Connection *conn, value option)
4012 CAMLparam1(option);
4013 CURLcode result = CURLE_OK;
4015 Store_field(conn->ocamlValues, OcamlPrivate, option);
4017 if (conn->private != NULL)
4018 free(conn->private);
4020 conn->private = strdup(String_val(option));
4022 result = curl_easy_setopt(conn->connection,
4023 CURLOPT_PRIVATE,
4024 conn->private);
4026 if (result != CURLE_OK)
4027 raiseError(conn, result);
4029 CAMLreturn0;
4031 #endif
4033 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
4034 static void handleHTTP200Aliases(Connection *conn, value option)
4036 CAMLparam1(option);
4037 CAMLlocal1(listIter);
4038 CURLcode result = CURLE_OK;
4040 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
4042 free_curl_slist(conn->http200Aliases);
4043 conn->http200Aliases = NULL;
4045 listIter = option;
4047 while (!Is_long(listIter))
4049 conn->http200Aliases = curl_slist_append(conn->http200Aliases, String_val(Field(listIter, 0)));
4051 listIter = Field(listIter, 1);
4054 result = curl_easy_setopt(conn->connection,
4055 CURLOPT_HTTP200ALIASES,
4056 conn->http200Aliases);
4058 if (result != CURLE_OK)
4059 raiseError(conn, result);
4061 CAMLreturn0;
4063 #endif
4065 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
4066 static void handleUnrestrictedAuth(Connection *conn, value option)
4068 CAMLparam1(option);
4069 CURLcode result = CURLE_OK;
4071 result = curl_easy_setopt(conn->connection,
4072 CURLOPT_UNRESTRICTED_AUTH,
4073 Bool_val(option));
4075 if (result != CURLE_OK)
4076 raiseError(conn, result);
4078 CAMLreturn0;
4080 #endif
4082 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4083 static void handleFTPUseEPRT(Connection *conn, value option)
4085 CAMLparam1(option);
4086 CURLcode result = CURLE_OK;
4088 result = curl_easy_setopt(conn->connection,
4089 CURLOPT_FTP_USE_EPRT,
4090 Bool_val(option));
4092 if (result != CURLE_OK)
4093 raiseError(conn, result);
4095 CAMLreturn0;
4097 #endif
4099 #if HAVE_DECL_CURLOPT_HTTPAUTH
4100 static void handleHTTPAuth(Connection *conn, value option)
4102 CAMLparam1(option);
4103 CAMLlocal1(listIter);
4104 CURLcode result = CURLE_OK;
4105 long auth = CURLAUTH_NONE;
4107 listIter = option;
4109 while (!Is_long(listIter))
4111 switch (Long_val(Field(listIter, 0)))
4113 case 0: /* CURLAUTH_BASIC */
4114 auth |= CURLAUTH_BASIC;
4115 break;
4117 case 1: /* CURLAUTH_DIGEST */
4118 auth |= CURLAUTH_DIGEST;
4119 break;
4121 case 2: /* CURLAUTH_GSSNEGOTIATE */
4122 auth |= CURLAUTH_GSSNEGOTIATE;
4123 break;
4125 case 3: /* CURLAUTH_NTLM */
4126 auth |= CURLAUTH_NTLM;
4127 break;
4129 case 4: /* CURLAUTH_ANY */
4130 auth |= CURLAUTH_ANY;
4131 break;
4133 case 5: /* CURLAUTH_ANYSAFE */
4134 auth |= CURLAUTH_ANYSAFE;
4135 break;
4137 default:
4138 failwith("Invalid HTTPAUTH Value");
4139 break;
4142 listIter = Field(listIter, 1);
4145 result = curl_easy_setopt(conn->connection,
4146 CURLOPT_HTTPAUTH,
4147 auth);
4149 if (result != CURLE_OK)
4150 raiseError(conn, result);
4152 CAMLreturn0;
4154 #endif
4156 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4157 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4159 CAMLparam1(option);
4160 CURLcode result = CURLE_OK;
4162 result = curl_easy_setopt(conn->connection,
4163 CURLOPT_FTP_CREATE_MISSING_DIRS,
4164 Bool_val(option));
4166 if (result != CURLE_OK)
4167 raiseError(conn, result);
4169 CAMLreturn0;
4171 #endif
4173 #if HAVE_DECL_CURLOPT_PROXYAUTH
4174 static void handleProxyAuth(Connection *conn, value option)
4176 CAMLparam1(option);
4177 CAMLlocal1(listIter);
4178 CURLcode result = CURLE_OK;
4179 long auth = CURLAUTH_NONE;
4181 listIter = option;
4183 while (!Is_long(listIter))
4185 switch (Long_val(Field(listIter, 0)))
4187 case 0: /* CURLAUTH_BASIC */
4188 auth |= CURLAUTH_BASIC;
4189 break;
4191 case 1: /* CURLAUTH_DIGEST */
4192 auth |= CURLAUTH_DIGEST;
4193 break;
4195 case 2: /* CURLAUTH_GSSNEGOTIATE */
4196 auth |= CURLAUTH_GSSNEGOTIATE;
4197 break;
4199 case 3: /* CURLAUTH_NTLM */
4200 auth |= CURLAUTH_NTLM;
4201 break;
4203 case 4: /* CURLAUTH_ANY */
4204 auth |= CURLAUTH_ANY;
4205 break;
4207 case 5: /* CURLAUTH_ANYSAFE */
4208 auth |= CURLAUTH_ANYSAFE;
4209 break;
4211 default:
4212 failwith("Invalid HTTPAUTH Value");
4213 break;
4216 listIter = Field(listIter, 1);
4219 result = curl_easy_setopt(conn->connection,
4220 CURLOPT_PROXYAUTH,
4221 auth);
4223 if (result != CURLE_OK)
4224 raiseError(conn, result);
4226 CAMLreturn0;
4228 #endif
4230 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4231 static void handleFTPResponseTimeout(Connection *conn, value option)
4233 CAMLparam1(option);
4234 CURLcode result = CURLE_OK;
4236 result = curl_easy_setopt(conn->connection,
4237 CURLOPT_FTP_RESPONSE_TIMEOUT,
4238 Long_val(option));
4240 if (result != CURLE_OK)
4241 raiseError(conn, result);
4243 CAMLreturn0;
4245 #endif
4247 #if HAVE_DECL_CURLOPT_IPRESOLVE
4248 static void handleIPResolve(Connection *conn, value option)
4250 CAMLparam1(option);
4251 CURLcode result = CURLE_OK;
4253 switch (Long_val(option))
4255 case 0: /* CURL_IPRESOLVE_WHATEVER */
4256 result = curl_easy_setopt(conn->connection,
4257 CURLOPT_IPRESOLVE,
4258 CURL_IPRESOLVE_WHATEVER);
4259 break;
4261 case 1: /* CURL_IPRESOLVE_V4 */
4262 result = curl_easy_setopt(conn->connection,
4263 CURLOPT_IPRESOLVE,
4264 CURL_IPRESOLVE_V4);
4265 break;
4267 case 2: /* CURL_IPRESOLVE_V6 */
4268 result = curl_easy_setopt(conn->connection,
4269 CURLOPT_IPRESOLVE,
4270 CURL_IPRESOLVE_V6);
4271 break;
4273 default:
4274 failwith("Invalid IPRESOLVE Value");
4275 break;
4278 if (result != CURLE_OK)
4279 raiseError(conn, result);
4281 CAMLreturn0;
4283 #endif
4285 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4286 static void handleMaxFileSize(Connection *conn, value option)
4288 CAMLparam1(option);
4289 CURLcode result = CURLE_OK;
4291 result = curl_easy_setopt(conn->connection,
4292 CURLOPT_MAXFILESIZE,
4293 Int32_val(option));
4295 if (result != CURLE_OK)
4296 raiseError(conn, result);
4298 CAMLreturn0;
4300 #endif
4302 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4303 static void handleInFileSizeLarge(Connection *conn, value option)
4305 CAMLparam1(option);
4306 CURLcode result = CURLE_OK;
4308 result = curl_easy_setopt(conn->connection,
4309 CURLOPT_INFILESIZE_LARGE,
4310 Int64_val(option));
4312 if (result != CURLE_OK)
4313 raiseError(conn, result);
4315 CAMLreturn0;
4317 #endif
4319 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4320 static void handleResumeFromLarge(Connection *conn, value option)
4322 CAMLparam1(option);
4323 CURLcode result = CURLE_OK;
4325 result = curl_easy_setopt(conn->connection,
4326 CURLOPT_RESUME_FROM_LARGE,
4327 Int64_val(option));
4329 if (result != CURLE_OK)
4330 raiseError(conn, result);
4332 CAMLreturn0;
4334 #endif
4336 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4337 static void handleMaxFileSizeLarge(Connection *conn, value option)
4339 CAMLparam1(option);
4340 CURLcode result = CURLE_OK;
4342 result = curl_easy_setopt(conn->connection,
4343 CURLOPT_MAXFILESIZE_LARGE,
4344 Int64_val(option));
4346 if (result != CURLE_OK)
4347 raiseError(conn, result);
4349 CAMLreturn0;
4351 #endif
4353 #if HAVE_DECL_CURLOPT_NETRC_FILE
4354 static void handleNETRCFile(Connection *conn, value option)
4356 CAMLparam1(option);
4357 CURLcode result = CURLE_OK;
4359 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4361 if (conn->netrcFile != NULL)
4362 free(conn->netrcFile);
4364 conn->netrcFile = strdup(String_val(option));
4366 result = curl_easy_setopt(conn->connection,
4367 CURLOPT_NETRC_FILE,
4368 conn->netrcFile);
4370 if (result != CURLE_OK)
4371 raiseError(conn, result);
4373 CAMLreturn0;
4375 #endif
4377 #if HAVE_DECL_CURLOPT_FTP_SSL
4378 static void handleFTPSSL(Connection *conn, value option)
4380 CAMLparam1(option);
4381 CURLcode result = CURLE_OK;
4383 switch (Long_val(option))
4385 case 0: /* CURLFTPSSL_NONE */
4386 result = curl_easy_setopt(conn->connection,
4387 CURLOPT_FTP_SSL,
4388 CURLFTPSSL_NONE);
4389 break;
4391 case 1: /* CURLFTPSSL_TRY */
4392 result = curl_easy_setopt(conn->connection,
4393 CURLOPT_FTP_SSL,
4394 CURLFTPSSL_TRY);
4395 break;
4397 case 2: /* CURLFTPSSL_CONTROL */
4398 result = curl_easy_setopt(conn->connection,
4399 CURLOPT_FTP_SSL,
4400 CURLFTPSSL_CONTROL);
4401 break;
4403 case 3: /* CURLFTPSSL_ALL */
4404 result = curl_easy_setopt(conn->connection,
4405 CURLOPT_FTP_SSL,
4406 CURLFTPSSL_ALL);
4407 break;
4409 default:
4410 failwith("Invalid FTP_SSL Value");
4411 break;
4414 if (result != CURLE_OK)
4415 raiseError(conn, result);
4417 CAMLreturn0;
4419 #endif
4421 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4422 static void handlePostFieldSizeLarge(Connection *conn, value option)
4424 CAMLparam1(option);
4425 CURLcode result = CURLE_OK;
4427 result = curl_easy_setopt(conn->connection,
4428 CURLOPT_POSTFIELDSIZE_LARGE,
4429 Int64_val(option));
4431 if (result != CURLE_OK)
4432 raiseError(conn, result);
4434 CAMLreturn0;
4436 #endif
4438 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4439 static void handleTCPNoDelay(Connection *conn, value option)
4441 CAMLparam1(option);
4442 CURLcode result = CURLE_OK;
4444 result = curl_easy_setopt(conn->connection,
4445 CURLOPT_TCP_NODELAY,
4446 Bool_val(option));
4448 if (result != CURLE_OK)
4449 raiseError(conn, result);
4451 CAMLreturn0;
4453 #endif
4455 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4456 static void handleFTPSSLAuth(Connection *conn, value option)
4458 CAMLparam1(option);
4459 CURLcode result = CURLE_OK;
4461 switch (Long_val(option))
4463 case 0: /* CURLFTPAUTH_DEFAULT */
4464 result = curl_easy_setopt(conn->connection,
4465 CURLOPT_FTPSSLAUTH,
4466 CURLFTPAUTH_DEFAULT);
4467 break;
4469 case 1: /* CURLFTPAUTH_SSL */
4470 result = curl_easy_setopt(conn->connection,
4471 CURLOPT_FTPSSLAUTH,
4472 CURLFTPAUTH_SSL);
4473 break;
4475 case 2: /* CURLFTPAUTH_TLS */
4476 result = curl_easy_setopt(conn->connection,
4477 CURLOPT_FTPSSLAUTH,
4478 CURLFTPAUTH_TLS);
4479 break;
4481 default:
4482 failwith("Invalid FTPSSLAUTH value");
4483 break;
4486 if (result != CURLE_OK)
4487 raiseError(conn, result);
4489 CAMLreturn0;
4491 #endif
4493 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4494 static void handleIOCTLFunction(Connection *conn, value option)
4496 CAMLparam1(option);
4497 CURLcode result = CURLE_OK;
4499 if (Tag_val(option) == Closure_tag)
4500 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4501 else
4502 failwith("Not a proper closure");
4504 result = curl_easy_setopt(conn->connection,
4505 CURLOPT_IOCTLFUNCTION,
4506 ioctlFunction);
4507 if (result != CURLE_OK)
4508 raiseError(conn, result);
4510 result = curl_easy_setopt(conn->connection,
4511 CURLOPT_DEBUGDATA,
4512 conn);
4514 if (result != CURLE_OK)
4515 raiseError(conn, result);
4517 CAMLreturn0;
4519 #endif
4521 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4522 static void handleFTPAccount(Connection *conn, value option)
4524 CAMLparam1(option);
4525 CURLcode result = CURLE_OK;
4527 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4529 if (conn->ftpaccount != NULL)
4530 free(conn->ftpaccount);
4532 conn->ftpaccount = strdup(String_val(option));
4534 result = curl_easy_setopt(conn->connection,
4535 CURLOPT_FTP_ACCOUNT,
4536 conn->ftpaccount);
4538 if (result != CURLE_OK)
4539 raiseError(conn, result);
4541 CAMLreturn0;
4543 #endif
4545 #if HAVE_DECL_CURLOPT_COOKIELIST
4546 static void handleCookieList(Connection *conn, value option)
4548 CAMLparam1(option);
4549 CURLcode result = CURLE_OK;
4551 Store_field(conn->ocamlValues, OcamlCookieList, option);
4553 if (conn->cookielist != NULL)
4554 free(conn->cookielist);
4556 conn->cookielist = strdup(String_val(option));
4558 result = curl_easy_setopt(conn->connection,
4559 CURLOPT_COOKIELIST,
4560 conn->cookielist);
4562 if (result != CURLE_OK)
4563 raiseError(conn, result);
4565 CAMLreturn0;
4567 #endif
4569 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4570 static void handleIgnoreContentLength(Connection *conn, value option)
4572 CAMLparam1(option);
4573 CURLcode result = CURLE_OK;
4575 result = curl_easy_setopt(conn->connection,
4576 CURLOPT_IGNORE_CONTENT_LENGTH,
4577 Bool_val(option));
4579 if (result != CURLE_OK)
4580 raiseError(conn, result);
4582 CAMLreturn0;
4584 #endif
4586 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4587 static void handleFTPSkipPASVIP(Connection *conn, value option)
4589 CAMLparam1(option);
4590 CURLcode result = CURLE_OK;
4592 result = curl_easy_setopt(conn->connection,
4593 CURLOPT_FTP_SKIP_PASV_IP,
4594 Bool_val(option));
4596 if (result != CURLE_OK)
4597 raiseError(conn, result);
4599 CAMLreturn0;
4601 #endif
4603 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4604 static void handleFTPFileMethod(Connection *conn, value option)
4606 CAMLparam1(option);
4607 CURLcode result = CURLE_OK;
4609 switch (Long_val(option))
4611 case 0: /* CURLFTPMETHOD_DEFAULT */
4612 result = curl_easy_setopt(conn->connection,
4613 CURLOPT_FTP_FILEMETHOD,
4614 CURLFTPMETHOD_DEFAULT);
4615 break;
4617 case 1: /* CURLFTMETHOD_MULTICWD */
4618 result = curl_easy_setopt(conn->connection,
4619 CURLOPT_FTP_FILEMETHOD,
4620 CURLFTPMETHOD_MULTICWD);
4621 break;
4623 case 2: /* CURLFTPMETHOD_NOCWD */
4624 result = curl_easy_setopt(conn->connection,
4625 CURLOPT_FTP_FILEMETHOD,
4626 CURLFTPMETHOD_NOCWD);
4627 break;
4629 case 3: /* CURLFTPMETHOD_SINGLECWD */
4630 result = curl_easy_setopt(conn->connection,
4631 CURLOPT_FTP_FILEMETHOD,
4632 CURLFTPMETHOD_SINGLECWD);
4634 default:
4635 failwith("Invalid FTP_FILEMETHOD value");
4636 break;
4639 if (result != CURLE_OK)
4640 raiseError(conn, result);
4642 CAMLreturn0;
4644 #endif
4646 #if HAVE_DECL_CURLOPT_LOCALPORT
4647 static void handleLocalPort(Connection *conn, value option)
4649 CAMLparam1(option);
4650 CURLcode result = CURLE_OK;
4652 result = curl_easy_setopt(conn->connection,
4653 CURLOPT_LOCALPORT,
4654 Long_val(option));
4656 if (result != CURLE_OK)
4657 raiseError(conn, result);
4659 CAMLreturn0;
4661 #endif
4663 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4664 static void handleLocalPortRange(Connection *conn, value option)
4666 CAMLparam1(option);
4667 CURLcode result = CURLE_OK;
4669 result = curl_easy_setopt(conn->connection,
4670 CURLOPT_LOCALPORTRANGE,
4671 Long_val(option));
4673 if (result != CURLE_OK)
4674 raiseError(conn, result);
4676 CAMLreturn0;
4678 #endif
4680 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4681 static void handleConnectOnly(Connection *conn, value option)
4683 CAMLparam1(option);
4684 CURLcode result = CURLE_OK;
4686 result = curl_easy_setopt(conn->connection,
4687 CURLOPT_CONNECT_ONLY,
4688 Bool_val(option));
4690 if (result != CURLE_OK)
4691 raiseError(conn, result);
4693 CAMLreturn0;
4695 #endif
4697 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4698 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4700 CAMLparam1(option);
4701 CURLcode result = CURLE_OK;
4703 result = curl_easy_setopt(conn->connection,
4704 CURLOPT_MAX_SEND_SPEED_LARGE,
4705 Int64_val(option));
4707 if (result != CURLE_OK)
4708 raiseError(conn, result);
4710 CAMLreturn0;
4712 #endif
4714 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4715 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4717 CAMLparam1(option);
4718 CURLcode result = CURLE_OK;
4720 result = curl_easy_setopt(conn->connection,
4721 CURLOPT_MAX_RECV_SPEED_LARGE,
4722 Int64_val(option));
4724 if (result != CURLE_OK)
4725 raiseError(conn, result);
4727 CAMLreturn0;
4729 #endif
4731 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4732 static void handleFTPAlternativeToUser(Connection *conn, value option)
4734 CAMLparam1(option);
4735 CURLcode result = CURLE_OK;
4737 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4739 if (conn->ftpAlternativeToUser != NULL)
4740 free(conn->ftpAlternativeToUser);
4742 conn->ftpAlternativeToUser = strdup(String_val(option));
4744 result = curl_easy_setopt(conn->connection,
4745 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4746 conn->ftpAlternativeToUser);
4748 if (result != CURLE_OK)
4749 raiseError(conn, result);
4751 CAMLreturn0;
4753 #endif
4755 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4756 static void handleSSLSessionIdCache(Connection *conn, value option)
4758 CAMLparam1(option);
4759 CURLcode result = CURLE_OK;
4761 result = curl_easy_setopt(conn->connection,
4762 CURLOPT_SSL_SESSIONID_CACHE,
4763 Bool_val(option));
4765 if (result != CURLE_OK)
4766 raiseError(conn, result);
4768 CAMLreturn0;
4770 #endif
4772 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4773 static void handleSSHAuthTypes(Connection *conn, value option)
4775 CAMLparam1(option);
4776 CAMLlocal1(listIter);
4777 CURLcode result = CURLE_OK;
4778 long authTypes = CURLSSH_AUTH_NONE;
4780 listIter = option;
4782 while (!Is_long(listIter))
4784 switch (Long_val(Field(listIter, 0)))
4786 case 0: /* CURLSSH_AUTH_ANY */
4787 authTypes |= CURLSSH_AUTH_ANY;
4788 break;
4790 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4791 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4792 break;
4794 case 2: /* CURLSSH_AUTH_PASSWORD */
4795 authTypes |= CURLSSH_AUTH_PASSWORD;
4796 break;
4798 case 3: /* CURLSSH_AUTH_HOST */
4799 authTypes |= CURLSSH_AUTH_HOST;
4800 break;
4802 case 4: /* CURLSSH_AUTH_KEYBOARD */
4803 authTypes |= CURLSSH_AUTH_KEYBOARD;
4804 break;
4806 default:
4807 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4808 break;
4811 listIter = Field(listIter, 1);
4814 result = curl_easy_setopt(conn->connection,
4815 CURLOPT_SSH_AUTH_TYPES,
4816 authTypes);
4818 if (result != CURLE_OK)
4819 raiseError(conn, result);
4821 CAMLreturn0;
4823 #endif
4825 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4826 static void handleSSHPublicKeyFile(Connection *conn, value option)
4828 CAMLparam1(option);
4829 CURLcode result = CURLE_OK;
4831 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4833 if (conn->sshPublicKeyFile != NULL)
4834 free(conn->sshPublicKeyFile);
4836 conn->sshPublicKeyFile = strdup(String_val(option));
4838 result = curl_easy_setopt(conn->connection,
4839 CURLOPT_SSH_PUBLIC_KEYFILE,
4840 conn->sshPublicKeyFile);
4842 if (result != CURLE_OK)
4843 raiseError(conn, result);
4845 CAMLreturn0;
4847 #endif
4849 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4850 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4852 CAMLparam1(option);
4853 CURLcode result = CURLE_OK;
4855 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4857 if (conn->sshPrivateKeyFile != NULL)
4858 free(conn->sshPrivateKeyFile);
4860 conn->sshPrivateKeyFile = strdup(String_val(option));
4862 result = curl_easy_setopt(conn->connection,
4863 CURLOPT_SSH_PRIVATE_KEYFILE,
4864 conn->sshPrivateKeyFile);
4866 if (result != CURLE_OK)
4867 raiseError(conn, result);
4869 CAMLreturn0;
4871 #endif
4873 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4874 static void handleFTPSSLCCC(Connection *conn, value option)
4876 CAMLparam1(option);
4877 CURLcode result = CURLE_OK;
4879 switch (Long_val(option))
4881 case 0: /* CURLFTPSSL_CCC_NONE */
4882 result = curl_easy_setopt(conn->connection,
4883 CURLOPT_FTP_SSL_CCC,
4884 CURLFTPSSL_CCC_NONE);
4885 break;
4887 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4888 result = curl_easy_setopt(conn->connection,
4889 CURLOPT_FTP_SSL_CCC,
4890 CURLFTPSSL_CCC_PASSIVE);
4891 break;
4893 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4894 result = curl_easy_setopt(conn->connection,
4895 CURLOPT_FTP_SSL_CCC,
4896 CURLFTPSSL_CCC_ACTIVE);
4897 break;
4899 default:
4900 failwith("Invalid FTPSSL_CCC value");
4901 break;
4904 if (result != CURLE_OK)
4905 raiseError(conn, result);
4907 CAMLreturn0;
4909 #endif
4911 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4912 static void handleTimeoutMS(Connection *conn, value option)
4914 CAMLparam1(option);
4915 CURLcode result = CURLE_OK;
4917 result = curl_easy_setopt(conn->connection,
4918 CURLOPT_TIMEOUT_MS,
4919 Long_val(option));
4921 if (result != CURLE_OK)
4922 raiseError(conn, result);
4924 CAMLreturn0;
4926 #endif
4928 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4929 static void handleConnectTimeoutMS(Connection *conn, value option)
4931 CAMLparam1(option);
4932 CURLcode result = CURLE_OK;
4934 result = curl_easy_setopt(conn->connection,
4935 CURLOPT_CONNECTTIMEOUT_MS,
4936 Long_val(option));
4938 if (result != CURLE_OK)
4939 raiseError(conn, result);
4941 CAMLreturn0;
4943 #endif
4945 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
4946 static void handleHTTPTransferDecoding(Connection *conn, value option)
4948 CAMLparam1(option);
4949 CURLcode result = CURLE_OK;
4951 result = curl_easy_setopt(conn->connection,
4952 CURLOPT_HTTP_TRANSFER_DECODING,
4953 Bool_val(option));
4955 if (result != CURLE_OK)
4956 raiseError(conn, result);
4958 CAMLreturn0;
4960 #endif
4962 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
4963 static void handleHTTPContentDecoding(Connection *conn, value option)
4965 CAMLparam1(option);
4966 CURLcode result = CURLE_OK;
4968 result = curl_easy_setopt(conn->connection,
4969 CURLOPT_HTTP_CONTENT_DECODING,
4970 Bool_val(option));
4972 if (result != CURLE_OK)
4973 raiseError(conn, result);
4975 CAMLreturn0;
4977 #endif
4979 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
4980 static void handleNewFilePerms(Connection *conn, value option)
4982 CAMLparam1(option);
4983 CURLcode result = CURLE_OK;
4985 result = curl_easy_setopt(conn->connection,
4986 CURLOPT_NEW_FILE_PERMS,
4987 Long_val(option));
4989 if (result != CURLE_OK)
4990 raiseError(conn, result);
4992 CAMLreturn0;
4994 #endif
4996 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
4997 static void handleNewDirectoryPerms(Connection *conn, value option)
4999 CAMLparam1(option);
5000 CURLcode result = CURLE_OK;
5002 result = curl_easy_setopt(conn->connection,
5003 CURLOPT_NEW_DIRECTORY_PERMS,
5004 Long_val(option));
5006 if (result != CURLE_OK)
5007 raiseError(conn, result);
5009 CAMLreturn0;
5011 #endif
5013 #if HAVE_DECL_CURLOPT_POST301
5014 static void handlePost301(Connection *conn, value option)
5016 CAMLparam1(option);
5017 CURLcode result = CURLE_OK;
5019 result = curl_easy_setopt(conn->connection,
5020 CURLOPT_POST301,
5021 Bool_val(option));
5023 if (result != CURLE_OK)
5024 raiseError(conn, result);
5026 CAMLreturn0;
5028 #endif
5030 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5031 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5033 CAMLparam1(option);
5034 CURLcode result = CURLE_OK;
5036 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5038 if (conn->sshHostPublicKeyMD5 != NULL)
5039 free(conn->sshHostPublicKeyMD5);
5041 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5043 result = curl_easy_setopt(conn->connection,
5044 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5045 conn->sshHostPublicKeyMD5);
5047 if (result != CURLE_OK)
5048 raiseError(conn, result);
5050 CAMLreturn0;
5052 #endif
5054 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5055 static void handleCopyPostFields(Connection *conn, value option)
5057 CAMLparam1(option);
5058 CURLcode result = CURLE_OK;
5060 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5062 if (conn->copyPostFields != NULL)
5063 free(conn->copyPostFields);
5065 conn->copyPostFields = strdup(String_val(option));
5067 result = curl_easy_setopt(conn->connection,
5068 CURLOPT_COPYPOSTFIELDS,
5069 conn->copyPostFields);
5071 if (result != CURLE_OK)
5072 raiseError(conn, result);
5074 CAMLreturn0;
5076 #endif
5078 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5079 static void handleProxyTransferMode(Connection *conn, value option)
5081 CAMLparam1(option);
5082 CURLcode result = CURLE_OK;
5084 result = curl_easy_setopt(conn->connection,
5085 CURLOPT_PROXY_TRANSFER_MODE,
5086 Bool_val(option));
5088 if (result != CURLE_OK)
5089 raiseError(conn, result);
5091 CAMLreturn0;
5093 #endif
5095 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5096 static void handleSeekFunction(Connection *conn, value option)
5098 CAMLparam1(option);
5099 CURLcode result = CURLE_OK;
5101 if (Tag_val(option) == Closure_tag)
5102 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5103 else
5104 failwith("Not a proper closure");
5106 result = curl_easy_setopt(conn->connection,
5107 CURLOPT_SEEKFUNCTION,
5108 seekFunction);
5110 if (result != CURLE_OK)
5111 raiseError(conn, result);
5113 result = curl_easy_setopt(conn->connection,
5114 CURLOPT_SEEKDATA,
5115 conn);
5117 if (result != CURLE_OK)
5118 raiseError(conn, result);
5120 CAMLreturn0;
5122 #endif
5124 #if HAVE_DECL_CURLOPT_AUTOREFERER
5125 static void handleAutoReferer(Connection *conn, value option)
5127 CAMLparam1(option);
5128 CURLcode result = curl_easy_setopt(conn->connection,
5129 CURLOPT_AUTOREFERER,
5130 Bool_val(option));
5132 if (result != CURLE_OK)
5133 raiseError(conn, result);
5135 CAMLreturn0;
5137 #endif
5139 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
5140 static void handleOpenSocketFunction(Connection *conn, value option)
5142 CAMLparam1(option);
5143 CURLcode result = CURLE_OK;
5145 Store_field(conn->ocamlValues, OcamlOpenSocketFunctionCallback, option);
5147 result = curl_easy_setopt(conn->connection,
5148 CURLOPT_OPENSOCKETDATA,
5149 conn);
5151 if (result != CURLE_OK)
5152 raiseError(conn, result);
5154 result = curl_easy_setopt(conn->connection,
5155 CURLOPT_OPENSOCKETFUNCTION,
5156 openSocketFunction);
5158 if (result != CURLE_OK)
5159 raiseError(conn, result);
5161 CAMLreturn0;
5163 #endif
5165 #if HAVE_DECL_CURLOPT_PROXYTYPE
5166 static void handleProxyType(Connection *conn, value option)
5168 CAMLparam1(option);
5169 CURLcode result = CURLE_OK;
5170 long proxy_type;
5172 switch (Long_val(option))
5174 case 0: proxy_type = CURLPROXY_HTTP; break;
5175 case 1: proxy_type = CURLPROXY_HTTP_1_0; break;
5176 case 2: proxy_type = CURLPROXY_SOCKS4; break;
5177 case 3: proxy_type = CURLPROXY_SOCKS5; break;
5178 case 4: proxy_type = CURLPROXY_SOCKS4A; break;
5179 case 5: proxy_type = CURLPROXY_SOCKS5_HOSTNAME; break;
5180 default:
5181 failwith("Invalid curl proxy type");
5184 result = curl_easy_setopt(conn->connection,
5185 CURLOPT_PROXYTYPE,
5186 proxy_type);
5188 if (result != CURLE_OK)
5189 raiseError(conn, result);
5191 CAMLreturn0;
5193 #endif
5195 #if HAVE_DECL_CURLOPT_PROTOCOLS || HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
5197 long protoMap[] =
5199 CURLPROTO_ALL,
5200 CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_FTP, CURLPROTO_FTPS, CURLPROTO_SCP, CURLPROTO_SFTP,
5201 CURLPROTO_TELNET, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_TFTP,
5202 /* factor out with autoconf? */
5203 #if defined(CURLPROTO_IMAP)
5204 CURLPROTO_IMAP,
5205 #else
5207 #endif
5208 #if defined(CURLPROTO_IMAPS)
5209 CURLPROTO_IMAPS,
5210 #else
5212 #endif
5213 #if defined(CURLPROTO_POP3)
5214 CURLPROTO_POP3,
5215 #else
5217 #endif
5218 #if defined(CURLPROTO_POP3S)
5219 CURLPROTO_POP3S,
5220 #else
5222 #endif
5223 #if defined(CURLPROTO_SMTP)
5224 CURLPROTO_SMTP,
5225 #else
5227 #endif
5228 #if defined(CURLPROTO_SMTPS)
5229 CURLPROTO_SMTPS,
5230 #else
5232 #endif
5233 #if defined(CURLPROTO_RTSP)
5234 CURLPROTO_RTSP,
5235 #else
5237 #endif
5238 #if defined(CURLPROTO_RTMP)
5239 CURLPROTO_RTMP,
5240 #else
5242 #endif
5243 #if defined(CURLPROTO_RTMPT)
5244 CURLPROTO_RTMPT,
5245 #else
5247 #endif
5248 #if defined(CURLPROTO_RTMPE)
5249 CURLPROTO_RTMPE,
5250 #else
5252 #endif
5253 #if defined(CURLPROTO_RTMPTE)
5254 CURLPROTO_RTMPTE,
5255 #else
5257 #endif
5258 #if defined(CURLPROTO_RTMPS)
5259 CURLPROTO_RTMPS,
5260 #else
5262 #endif
5263 #if defined(CURLPROTO_RTMPTS)
5264 CURLPROTO_RTMPTS,
5265 #else
5267 #endif
5268 #if defined(CURLPROTO_GOPHER)
5269 CURLPROTO_GOPHER,
5270 #else
5272 #endif
5275 static void handleProtocolsOption(CURLoption curlopt, Connection *conn, value option)
5277 CAMLparam1(option);
5278 CURLcode result = CURLE_OK;
5279 long protocols = 0;
5280 int index;
5282 while (Val_emptylist != option)
5284 index = Int_val(Field(option, 0));
5285 if ((index < 0) || ((size_t)index >= sizeof(protoMap) / sizeof(protoMap[0])))
5286 failwith("Invalid curl protocol");
5288 protocols = protocols | protoMap[index];
5290 option = Field(option, 1);
5293 result = curl_easy_setopt(conn->connection,
5294 curlopt,
5295 protocols);
5297 if (result != CURLE_OK)
5298 raiseError(conn, result);
5300 CAMLreturn0;
5302 #endif
5304 #if HAVE_DECL_CURLOPT_PROTOCOLS
5305 static void handleProtocols(Connection *conn, value option)
5307 handleProtocolsOption(CURLOPT_PROTOCOLS, conn, option);
5309 #endif
5311 #if HAVE_DECL_CURLOPT_PROTOCOLS
5312 static void handleRedirProtocols(Connection *conn, value option)
5314 handleProtocolsOption(CURLOPT_REDIR_PROTOCOLS, conn, option);
5316 #endif
5318 #if HAVE_DECL_CURLOPT_RESOLVE
5319 static void handleResolve(Connection *conn, value option)
5321 CAMLparam1(option);
5322 CAMLlocal1(head);
5324 CURLcode result = CURLE_OK;
5326 free_curl_slist(conn->resolve);
5327 conn->resolve = NULL;
5329 head = option;
5331 while (head != Val_emptylist)
5333 conn->resolve = curl_slist_append(conn->resolve, String_val(Field(head,0)));
5334 head = Field(head, 1);
5337 result = curl_easy_setopt(conn->connection,
5338 CURLOPT_RESOLVE,
5339 conn->resolve);
5341 if (result != CURLE_OK)
5342 raiseError(conn, result);
5344 CAMLreturn0;
5346 #endif
5348 #if HAVE_DECL_CURLOPT_DNS_SERVERS
5349 static void handleDnsServers(Connection *conn, value option)
5351 CAMLparam1(option);
5353 Store_field(conn->ocamlValues, OcamlDNSServers, option);
5355 CURLcode result = CURLE_OK;
5356 free_if(conn->dns_servers);
5358 conn->dns_servers = strdup(String_val(option));
5360 result = curl_easy_setopt(conn->connection,
5361 CURLOPT_DNS_SERVERS,
5362 conn->dns_servers);
5364 if (result != CURLE_OK)
5365 raiseError(conn, result);
5367 CAMLreturn0;
5369 #endif
5371 #if HAVE_DECL_CURLOPT_MAIL_FROM
5372 static void handleMailFrom(Connection *conn, value option)
5374 CAMLparam1(option);
5375 CURLcode result = CURLE_OK;
5377 Store_field(conn->ocamlValues, OcamlMailFrom, option);
5379 if (conn->mailFrom != NULL)
5380 free(conn->mailFrom);
5382 conn->mailFrom = strdup(String_val(option));
5384 result = curl_easy_setopt(conn->connection,
5385 CURLOPT_MAIL_FROM,
5386 conn->mailFrom);
5388 if (result != CURLE_OK)
5389 raiseError(conn, result);
5391 CAMLreturn0;
5393 #endif
5395 #if HAVE_DECL_CURLOPT_MAIL_RCPT
5396 static void handleMailRcpt(Connection *conn, value option)
5398 CAMLparam1(option);
5399 CAMLlocal1(listIter);
5400 CURLcode result = CURLE_OK;
5402 Store_field(conn->ocamlValues, OcamlMailRcpt, option);
5404 free_curl_slist(conn->mailRcpt);
5405 conn->mailRcpt = NULL;
5407 listIter = option;
5409 while (Val_emptylist != listIter)
5411 conn->mailRcpt = curl_slist_append(conn->mailRcpt, String_val(Field(listIter, 0)));
5413 listIter = Field(listIter, 1);
5416 result = curl_easy_setopt(conn->connection,
5417 CURLOPT_MAIL_RCPT,
5418 conn->mailRcpt);
5420 if (result != CURLE_OK)
5421 raiseError(conn, result);
5423 CAMLreturn0;
5425 #endif
5428 ** curl_easy_setopt helper function
5431 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5433 CAMLparam2(conn, option);
5434 CAMLlocal1(data);
5435 Connection *connection = Connection_val(conn);
5436 CURLOptionMapping* thisOption = NULL;
5438 checkConnection(connection);
5440 if (!Is_block(option))
5441 failwith("Not a block");
5443 if (Wosize_val(option) < 1)
5444 failwith("Insufficient data in block");
5446 data = Field(option, 0);
5448 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5450 thisOption = &implementedOptionMap[Tag_val(option)];
5451 if (thisOption->optionHandler)
5452 thisOption->optionHandler(connection, data);
5453 else
5454 failwith(thisOption->name);
5456 else
5457 failwith("Invalid CURLOPT Option");
5459 CAMLreturn(Val_unit);
5463 ** curl_easy_perform helper function
5466 CAMLprim value helper_curl_easy_perform(value conn)
5468 CAMLparam1(conn);
5469 CURLcode result = CURLE_OK;
5470 Connection *connection = Connection_val(conn);
5472 checkConnection(connection);
5474 enter_blocking_section();
5475 result = curl_easy_perform(connection->connection);
5476 leave_blocking_section();
5478 if (result != CURLE_OK)
5479 raiseError(connection, result);
5481 CAMLreturn(Val_unit);
5485 ** curl_easy_cleanup helper function
5488 CAMLprim value helper_curl_easy_cleanup(value conn)
5490 CAMLparam1(conn);
5491 Connection *connection = Connection_val(conn);
5493 checkConnection(connection);
5495 removeConnection(connection, 0);
5497 CAMLreturn(Val_unit);
5501 ** curl_easy_duphandle helper function
5504 CAMLprim value helper_curl_easy_duphandle(value conn)
5506 CAMLparam1(conn);
5507 CAMLlocal1(result);
5508 Connection *connection = Connection_val(conn);
5510 checkConnection(connection);
5512 result = caml_curl_alloc(duplicateConnection(connection));
5514 CAMLreturn(result);
5518 ** curl_easy_getinfo helper function
5521 enum GetInfoResultType {
5522 StringValue, LongValue, DoubleValue, StringListValue
5525 value convertStringList(struct curl_slist *slist)
5527 CAMLparam0();
5528 CAMLlocal3(result, current, next);
5529 struct curl_slist *p = slist;
5531 result = Val_int(0);
5532 current = Val_int(0);
5533 next = Val_int(0);
5535 while (p != NULL)
5537 next = alloc_tuple(2);
5538 Store_field(next, 0, copy_string(p->data));
5539 Store_field(next, 1, Val_int(0));
5541 if (result == Val_int(0))
5542 result = next;
5544 if (current != Val_int(0))
5545 Store_field(current, 1, next);
5547 current = next;
5549 p = p->next;
5552 curl_slist_free_all(slist);
5554 CAMLreturn(result);
5557 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5559 CAMLparam2(conn, option);
5560 CAMLlocal1(result);
5561 CURLcode curlResult;
5562 Connection *connection = Connection_val(conn);
5563 enum GetInfoResultType resultType;
5564 char *strValue = NULL;
5565 double doubleValue;
5566 long longValue;
5567 struct curl_slist *stringListValue = NULL;
5569 checkConnection(connection);
5571 switch(Long_val(option))
5573 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5574 case 0: /* CURLINFO_EFFECTIVE_URL */
5575 resultType = StringValue;
5577 curlResult = curl_easy_getinfo(connection->connection,
5578 CURLINFO_EFFECTIVE_URL,
5579 &strValue);
5580 break;
5581 #else
5582 #pragma message("libcurl does not provide CURLINFO_EFFECTIVE_URL")
5583 #endif
5585 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5586 case 1: /* CURLINFO_HTTP_CODE */
5587 case 2: /* CURLINFO_RESPONSE_CODE */
5588 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5589 resultType = LongValue;
5591 curlResult = curl_easy_getinfo(connection->connection,
5592 CURLINFO_RESPONSE_CODE,
5593 &longValue);
5594 #else
5595 resultType = LongValue;
5597 curlResult = curl_easy_getinfo(connection->connection,
5598 CURLINFO_HTTP_CODE,
5599 &longValue);
5600 #endif
5601 break;
5602 #endif
5604 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5605 case 3: /* CURLINFO_TOTAL_TIME */
5606 resultType = DoubleValue;
5608 curlResult = curl_easy_getinfo(connection->connection,
5609 CURLINFO_TOTAL_TIME,
5610 &doubleValue);
5611 break;
5612 #endif
5614 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5615 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5616 resultType = DoubleValue;
5618 curlResult = curl_easy_getinfo(connection->connection,
5619 CURLINFO_NAMELOOKUP_TIME,
5620 &doubleValue);
5621 break;
5622 #endif
5624 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5625 case 5: /* CURLINFO_CONNECT_TIME */
5626 resultType = DoubleValue;
5628 curlResult = curl_easy_getinfo(connection->connection,
5629 CURLINFO_CONNECT_TIME,
5630 &doubleValue);
5631 break;
5632 #endif
5634 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5635 case 6: /* CURLINFO_PRETRANSFER_TIME */
5636 resultType = DoubleValue;
5638 curlResult = curl_easy_getinfo(connection->connection,
5639 CURLINFO_PRETRANSFER_TIME,
5640 &doubleValue);
5641 break;
5642 #endif
5644 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5645 case 7: /* CURLINFO_SIZE_UPLOAD */
5646 resultType = DoubleValue;
5648 curlResult = curl_easy_getinfo(connection->connection,
5649 CURLINFO_SIZE_UPLOAD,
5650 &doubleValue);
5651 break;
5652 #endif
5654 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5655 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5656 resultType = DoubleValue;
5658 curlResult = curl_easy_getinfo(connection->connection,
5659 CURLINFO_SIZE_DOWNLOAD,
5660 &doubleValue);
5661 break;
5662 #endif
5664 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5665 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5666 resultType = DoubleValue;
5668 curlResult = curl_easy_getinfo(connection->connection,
5669 CURLINFO_SPEED_DOWNLOAD,
5670 &doubleValue);
5671 break;
5672 #endif
5674 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5675 case 10: /* CURLINFO_SPEED_UPLOAD */
5676 resultType = DoubleValue;
5678 curlResult = curl_easy_getinfo(connection->connection,
5679 CURLINFO_SPEED_UPLOAD,
5680 &doubleValue);
5681 break;
5683 #endif
5685 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5686 case 11: /* CURLINFO_HEADER_SIZE */
5687 resultType = LongValue;
5689 curlResult = curl_easy_getinfo(connection->connection,
5690 CURLINFO_HEADER_SIZE,
5691 &longValue);
5692 break;
5693 #endif
5695 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5696 case 12: /* CURLINFO_REQUEST_SIZE */
5697 resultType = LongValue;
5699 curlResult = curl_easy_getinfo(connection->connection,
5700 CURLINFO_REQUEST_SIZE,
5701 &longValue);
5702 break;
5703 #endif
5705 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5706 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5707 resultType = LongValue;
5709 curlResult = curl_easy_getinfo(connection->connection,
5710 CURLINFO_SSL_VERIFYRESULT,
5711 &longValue);
5712 break;
5713 #endif
5715 #if HAVE_DECL_CURLINFO_FILETIME
5716 case 14: /* CURLINFO_FILETIME */
5717 resultType = DoubleValue;
5719 curlResult = curl_easy_getinfo(connection->connection,
5720 CURLINFO_FILETIME,
5721 &longValue);
5723 doubleValue = longValue;
5724 break;
5725 #endif
5727 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5728 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5729 resultType = DoubleValue;
5731 curlResult = curl_easy_getinfo(connection->connection,
5732 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5733 &doubleValue);
5734 break;
5735 #endif
5737 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5738 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5739 resultType = DoubleValue;
5741 curlResult = curl_easy_getinfo(connection->connection,
5742 CURLINFO_CONTENT_LENGTH_UPLOAD,
5743 &doubleValue);
5744 break;
5745 #endif
5747 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5748 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5749 resultType = DoubleValue;
5751 curlResult = curl_easy_getinfo(connection->connection,
5752 CURLINFO_STARTTRANSFER_TIME,
5753 &doubleValue);
5754 break;
5755 #endif
5757 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5758 case 18: /* CURLINFO_CONTENT_TYPE */
5759 resultType = StringValue;
5761 curlResult = curl_easy_getinfo(connection->connection,
5762 CURLINFO_CONTENT_TYPE,
5763 &strValue);
5764 break;
5765 #endif
5767 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5768 case 19: /* CURLINFO_REDIRECT_TIME */
5769 resultType = DoubleValue;
5771 curlResult = curl_easy_getinfo(connection->connection,
5772 CURLINFO_REDIRECT_TIME,
5773 &doubleValue);
5774 break;
5775 #endif
5777 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5778 case 20: /* CURLINFO_REDIRECT_COUNT */
5779 resultType = LongValue;
5781 curlResult = curl_easy_getinfo(connection->connection,
5782 CURLINFO_REDIRECT_COUNT,
5783 &longValue);
5784 break;
5785 #endif
5787 #if HAVE_DECL_CURLINFO_PRIVATE
5788 case 21: /* CURLINFO_PRIVATE */
5789 resultType = StringValue;
5791 curlResult = curl_easy_getinfo(connection->connection,
5792 CURLINFO_PRIVATE,
5793 &strValue);
5794 break;
5795 #endif
5797 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5798 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5799 resultType = LongValue;
5801 curlResult = curl_easy_getinfo(connection->connection,
5802 CURLINFO_HTTP_CONNECTCODE,
5803 &longValue);
5804 break;
5805 #endif
5807 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5808 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5809 resultType = LongValue;
5811 curlResult = curl_easy_getinfo(connection->connection,
5812 CURLINFO_HTTPAUTH_AVAIL,
5813 &longValue);
5814 break;
5815 #endif
5817 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5818 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5819 resultType = LongValue;
5821 curlResult = curl_easy_getinfo(connection->connection,
5822 CURLINFO_PROXYAUTH_AVAIL,
5823 &longValue);
5824 break;
5825 #endif
5827 #if HAVE_DECL_CURLINFO_OS_ERRNO
5828 case 25: /* CURLINFO_OS_ERRNO */
5829 resultType = LongValue;
5831 curlResult = curl_easy_getinfo(connection->connection,
5832 CURLINFO_OS_ERRNO,
5833 &longValue);
5834 break;
5835 #endif
5837 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5838 case 26: /* CURLINFO_NUM_CONNECTS */
5839 resultType = LongValue;
5841 curlResult = curl_easy_getinfo(connection->connection,
5842 CURLINFO_NUM_CONNECTS,
5843 &longValue);
5844 break;
5845 #endif
5847 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5848 case 27: /* CURLINFO_SSL_ENGINES */
5849 resultType = StringListValue;
5851 curlResult = curl_easy_getinfo(connection->connection,
5852 CURLINFO_SSL_ENGINES,
5853 &stringListValue);
5854 break;
5855 #endif
5857 #if HAVE_DECL_CURLINFO_COOKIELIST
5858 case 28: /* CURLINFO_COOKIELIST */
5859 resultType = StringListValue;
5861 curlResult = curl_easy_getinfo(connection->connection,
5862 CURLINFO_COOKIELIST,
5863 &stringListValue);
5864 break;
5865 #endif
5867 #if HAVE_DECL_CURLINFO_LASTSOCKET
5868 case 29: /* CURLINFO_LASTSOCKET */
5869 resultType = LongValue;
5871 curlResult = curl_easy_getinfo(connection->connection,
5872 CURLINFO_LASTSOCKET,
5873 &longValue);
5874 break;
5875 #endif
5877 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5878 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5879 resultType = StringValue;
5881 curlResult = curl_easy_getinfo(connection->connection,
5882 CURLINFO_FTP_ENTRY_PATH,
5883 &strValue);
5884 break;
5885 #endif
5887 #if HAVE_DECL_CURLINFO_REDIRECT_URL
5888 case 31: /* CURLINFO_REDIRECT_URL */
5889 resultType = StringValue;
5891 curlResult = curl_easy_getinfo(connection->connection,
5892 CURLINFO_REDIRECT_URL,
5893 &strValue);
5894 break;
5895 #else
5896 #pragma message("libcurl does not provide CURLINFO_REDIRECT_URL")
5897 #endif
5899 #if HAVE_DECL_CURLINFO_PRIMARY_IP
5900 case 32: /* CURLINFO_PRIMARY_IP */
5901 resultType = StringValue;
5903 curlResult = curl_easy_getinfo(connection->connection,
5904 CURLINFO_PRIMARY_IP,
5905 &strValue);
5906 break;
5907 #else
5908 #pragma message("libcurl does not provide CURLINFO_PRIMARY_IP")
5909 #endif
5911 #if HAVE_DECL_CURLINFO_LOCAL_IP
5912 case 33: /* CURLINFO_LOCAL_IP */
5913 resultType = StringValue;
5915 curlResult = curl_easy_getinfo(connection->connection,
5916 CURLINFO_LOCAL_IP,
5917 &strValue);
5918 break;
5919 #else
5920 #pragma message("libcurl does not provide CURLINFO_LOCAL_IP")
5921 #endif
5923 #if HAVE_DECL_CURLINFO_LOCAL_PORT
5924 case 34: /* CURLINFO_LOCAL_PORT */
5925 resultType = LongValue;
5927 curlResult = curl_easy_getinfo(connection->connection,
5928 CURLINFO_LOCAL_PORT,
5929 &longValue);
5930 break;
5931 #else
5932 #pragma message("libcurl does not provide CURLINFO_LOCAL_PORT")
5933 #endif
5935 #if HAVE_DECL_CURLINFO_CONDITION_UNMET
5936 case 35: /* CURLINFO_CONDITION_UNMET */
5937 resultType = LongValue;
5939 curlResult = curl_easy_getinfo(connection->connection,
5940 CURLINFO_CONDITION_UNMET,
5941 &longValue);
5942 break;
5943 #else
5944 #pragma message("libcurl does not provide CURLINFO_CONDITION_UNMET")
5945 #endif
5947 default:
5948 failwith("Invalid CURLINFO Option");
5949 break;
5952 if (curlResult != CURLE_OK)
5953 raiseError(connection, curlResult);
5955 switch (resultType)
5957 case StringValue:
5958 result = alloc(1, StringValue);
5959 Store_field(result, 0, copy_string(strValue?strValue:""));
5960 break;
5962 case LongValue:
5963 result = alloc(1, LongValue);
5964 Store_field(result, 0, Val_long(longValue));
5965 break;
5967 case DoubleValue:
5968 result = alloc(1, DoubleValue);
5969 Store_field(result, 0, copy_double(doubleValue));
5970 break;
5972 case StringListValue:
5973 result = alloc(1, StringListValue);
5974 Store_field(result, 0, convertStringList(stringListValue));
5975 break;
5978 CAMLreturn(result);
5982 ** curl_escape helper function
5985 CAMLprim value helper_curl_escape(value str)
5987 CAMLparam1(str);
5988 CAMLlocal1(result);
5989 char *curlResult;
5991 curlResult = curl_escape(String_val(str), string_length(str));
5992 result = copy_string(curlResult);
5993 free(curlResult);
5995 CAMLreturn(result);
5999 ** curl_unescape helper function
6002 CAMLprim value helper_curl_unescape(value str)
6004 CAMLparam1(str);
6005 CAMLlocal1(result);
6006 char *curlResult;
6008 curlResult = curl_unescape(String_val(str), string_length(str));
6009 result = copy_string(curlResult);
6010 free(curlResult);
6012 CAMLreturn(result);
6016 ** curl_getdate helper function
6019 CAMLprim value helper_curl_getdate(value str, value now)
6021 CAMLparam2(str, now);
6022 CAMLlocal1(result);
6023 time_t curlResult;
6024 time_t curlNow;
6026 curlNow = (time_t)Double_val(now);
6027 curlResult = curl_getdate(String_val(str), &curlNow);
6028 result = copy_double((double)curlResult);
6030 CAMLreturn(result);
6034 ** curl_version helper function
6037 CAMLprim value helper_curl_version(void)
6039 CAMLparam0();
6040 CAMLlocal1(result);
6041 char *str;
6043 str = curl_version();
6044 result = copy_string(str);
6046 CAMLreturn(result);
6049 struct CURLVersionBitsMapping
6051 int code;
6052 char *name;
6055 struct CURLVersionBitsMapping versionBitsMap[] =
6057 {CURL_VERSION_IPV6, "ipv6"},
6058 {CURL_VERSION_KERBEROS4, "kerberos4"},
6059 {CURL_VERSION_SSL, "ssl"},
6060 {CURL_VERSION_LIBZ, "libz"},
6061 {CURL_VERSION_NTLM, "ntlm"},
6062 {CURL_VERSION_GSSNEGOTIATE, "gssnegotiate"},
6063 {CURL_VERSION_DEBUG, "debug"},
6064 {CURL_VERSION_CURLDEBUG, "curldebug"},
6065 {CURL_VERSION_ASYNCHDNS, "asynchdns"},
6066 {CURL_VERSION_SPNEGO, "spnego"},
6067 {CURL_VERSION_LARGEFILE, "largefile"},
6068 {CURL_VERSION_IDN, "idn"},
6069 {CURL_VERSION_SSPI, "sspi"},
6070 {CURL_VERSION_CONV, "conv"},
6071 #if HAVE_DECL_CURL_VERSION_TLSAUTH_SRP
6072 {CURL_VERSION_TLSAUTH_SRP, "srp"},
6073 #endif
6074 #if HAVE_DECL_CURL_VERSION_NTLM_WB
6075 {CURL_VERSION_NTLM_WB, "wb"},
6076 #endif
6079 CAMLprim value caml_curl_version_info(value unit)
6081 CAMLparam1(unit);
6082 CAMLlocal4(v, vlist, vnum, vfeatures);
6083 const char* const* p = NULL;
6084 size_t i = 0;
6086 curl_version_info_data* data = curl_version_info(CURLVERSION_NOW);
6087 if (NULL == data) caml_failwith("curl_version_info");
6089 vlist = Val_emptylist;
6090 for (p = data->protocols; NULL != *p; p++)
6092 vlist = Val_cons(vlist, caml_copy_string(*p));
6095 vfeatures = Val_emptylist;
6096 for (i = 0; i < sizeof(versionBitsMap)/sizeof(versionBitsMap[0]); i++)
6098 if (0 != (versionBitsMap[i].code & data->features))
6099 vfeatures = Val_cons(vfeatures, caml_copy_string(versionBitsMap[i].name));
6102 vnum = caml_alloc_tuple(3);
6103 Store_field(vnum,0,Val_int(0xFF & (data->version_num >> 16)));
6104 Store_field(vnum,1,Val_int(0xFF & (data->version_num >> 8)));
6105 Store_field(vnum,2,Val_int(0xFF & (data->version_num)));
6107 v = caml_alloc_tuple(12);
6108 Store_field(v,0,caml_copy_string(data->version));
6109 Store_field(v,1,vnum);
6110 Store_field(v,2,caml_copy_string(data->host));
6111 Store_field(v,3,vfeatures);
6112 Store_field(v,4,data->ssl_version ? Val_some(caml_copy_string(data->ssl_version)) : Val_none);
6113 Store_field(v,5,data->libz_version ? Val_some(caml_copy_string(data->libz_version)) : Val_none);
6114 Store_field(v,6,vlist);
6115 Store_field(v,7,caml_copy_string((data->age >= 1 && data->ares) ? data->ares : ""));
6116 Store_field(v,8,Val_int((data->age >= 1) ? data->ares_num : 0));
6117 Store_field(v,9,caml_copy_string((data->age >= 2 && data->libidn) ? data->libidn : ""));
6118 Store_field(v,10,Val_int((data->age >= 3) ? data->iconv_ver_num : 0));
6119 Store_field(v,11,caml_copy_string((data->age >= 3 && data->libssh_version) ? data->libssh_version : ""));
6121 CAMLreturn(v);
6124 CAMLprim value caml_curl_pause(value conn, value opts)
6126 CAMLparam2(conn, opts);
6127 CAMLlocal4(v, vlist, vnum, vfeatures);
6128 Connection *connection = Connection_val(conn);
6129 int bitmask = 0;
6130 CURLcode result;
6132 while (Val_emptylist != opts)
6134 switch (Int_val(Field(opts,0)))
6136 case 0: bitmask |= CURLPAUSE_SEND; break;
6137 case 1: bitmask |= CURLPAUSE_RECV; break;
6138 case 2: bitmask |= CURLPAUSE_ALL; break;
6139 default: caml_failwith("wrong pauseOption");
6141 opts = Field(opts,1);
6144 result = curl_easy_pause(connection->connection,bitmask);
6145 if (result != CURLE_OK)
6146 raiseError(connection, result);
6148 CAMLreturn(Val_unit);
6152 * Curl multi stack support
6154 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
6155 * Other exported functions are prefixed with caml_curlm_, some of them
6156 * can/should be decomposed into smaller parts.
6159 struct ml_multi_handle
6161 CURLM* handle;
6162 value values; /* callbacks */
6165 enum
6167 curlmopt_socket_function,
6168 curlmopt_timer_function,
6170 /* last, not used */
6171 multi_values_total
6174 typedef struct ml_multi_handle ml_multi_handle;
6176 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
6177 #define CURLM_val(v) (Multi_val(v)->handle)
6179 static struct custom_operations curl_multi_ops = {
6180 "ygrek.curl_multi",
6181 custom_finalize_default,
6182 custom_compare_default,
6183 custom_hash_default,
6184 custom_serialize_default,
6185 custom_deserialize_default,
6186 #if defined(custom_compare_ext_default)
6187 custom_compare_ext_default,
6188 #endif
6191 CAMLprim value caml_curl_multi_init(value unit)
6193 CAMLparam1(unit);
6194 CAMLlocal1(v);
6195 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
6196 CURLM* h = curl_multi_init();
6198 if (!h)
6200 caml_stat_free(multi);
6201 failwith("caml_curl_multi_init");
6204 multi->handle = h;
6205 multi->values = caml_alloc(multi_values_total, 0);
6206 caml_register_generational_global_root(&multi->values);
6208 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
6209 Multi_val(v) = multi;
6211 CAMLreturn(v);
6214 CAMLprim value caml_curl_multi_cleanup(value handle)
6216 CAMLparam1(handle);
6217 ml_multi_handle* h = Multi_val(handle);
6219 if (NULL == h)
6220 CAMLreturn(Val_unit);
6222 caml_remove_generational_global_root(&h->values);
6224 if (CURLM_OK != curl_multi_cleanup(h->handle))
6225 failwith("caml_curl_multi_cleanup");
6227 Multi_val(handle) = (ml_multi_handle*)NULL;
6229 CAMLreturn(Val_unit);
6232 static CURL* curlm_remove_finished(CURLM* multi_handle, CURLcode* result)
6234 int msgs_in_queue = 0;
6236 while (1)
6238 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
6239 if (NULL == msg) return NULL;
6240 if (CURLMSG_DONE == msg->msg)
6242 CURL* easy_handle = msg->easy_handle;
6243 if (result) *result = msg->data.result;
6244 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
6246 /*failwith("curlm_remove_finished");*/
6248 return easy_handle;
6253 CAMLprim value caml_curlm_remove_finished(value v_multi)
6255 CAMLparam1(v_multi);
6256 CAMLlocal2(v_easy, v_tuple);
6257 CURL* handle;
6258 CURLM* multi_handle;
6259 CURLcode result;
6260 Connection* conn = NULL;
6262 multi_handle = CURLM_val(v_multi);
6264 caml_enter_blocking_section();
6265 handle = curlm_remove_finished(multi_handle,&result);
6266 caml_leave_blocking_section();
6268 if (NULL == handle)
6270 CAMLreturn(Val_none);
6272 else
6274 conn = findConnection(handle);
6275 if (conn->errorBuffer != NULL)
6277 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0, caml_copy_string(conn->errorBuffer));
6279 conn->refcount--;
6280 /* NB: same handle, but different block */
6281 v_easy = caml_curl_alloc(conn);
6282 v_tuple = caml_alloc(2, 0);
6283 Store_field(v_tuple,0,v_easy);
6284 Store_field(v_tuple,1,Val_int(result)); /* CURLcode */
6285 CAMLreturn(Val_some(v_tuple));
6289 static int curlm_wait_data(CURLM* multi_handle)
6291 struct timeval timeout;
6292 CURLMcode ret;
6294 fd_set fdread;
6295 fd_set fdwrite;
6296 fd_set fdexcep;
6297 int maxfd = -1;
6299 FD_ZERO(&fdread);
6300 FD_ZERO(&fdwrite);
6301 FD_ZERO(&fdexcep);
6303 /* set a suitable timeout */
6304 timeout.tv_sec = 1;
6305 timeout.tv_usec = 0;
6307 /* get file descriptors from the transfers */
6308 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
6310 if (ret == CURLM_OK && maxfd >= 0)
6312 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
6313 if (-1 != rc) return 0;
6315 return 1;
6318 CAMLprim value caml_curlm_wait_data(value v_multi)
6320 CAMLparam1(v_multi);
6321 int ret;
6322 CURLM* h = CURLM_val(v_multi);
6324 caml_enter_blocking_section();
6325 ret = curlm_wait_data(h);
6326 caml_leave_blocking_section();
6328 CAMLreturn(Val_bool(0 == ret));
6331 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
6333 CAMLparam2(v_multi,v_easy);
6334 CURLM* multi = CURLM_val(v_multi);
6335 Connection* conn = Connection_val(v_easy);
6337 /* prevent collection of OCaml value while the easy handle is used
6338 and may invoke callbacks registered on OCaml side */
6339 conn->refcount++;
6341 /* may invoke callbacks so need to be consistent with locks */
6342 caml_enter_blocking_section();
6343 if (CURLM_OK != curl_multi_add_handle(multi, conn->connection))
6345 conn->refcount--; /* not added, revert */
6346 caml_leave_blocking_section();
6347 failwith("caml_curl_multi_add_handle");
6349 caml_leave_blocking_section();
6351 CAMLreturn(Val_unit);
6354 CAMLprim value caml_curl_multi_remove_handle(value v_multi, value v_easy)
6356 CAMLparam2(v_multi,v_easy);
6357 CURLM* multi = CURLM_val(v_multi);
6358 Connection* conn = Connection_val(v_easy);
6360 /* may invoke callbacks so need to be consistent with locks */
6361 caml_enter_blocking_section();
6362 if (CURLM_OK != curl_multi_remove_handle(multi, conn->connection))
6364 caml_leave_blocking_section();
6365 failwith("caml_curl_multi_remove_handle");
6367 conn->refcount--;
6368 caml_leave_blocking_section();
6370 CAMLreturn(Val_unit);
6373 CAMLprim value caml_curl_multi_perform_all(value v_multi)
6375 CAMLparam1(v_multi);
6376 int still_running = 0;
6377 CURLM* h = CURLM_val(v_multi);
6379 caml_enter_blocking_section();
6380 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
6381 caml_leave_blocking_section();
6383 CAMLreturn(Val_int(still_running));
6386 CAMLprim value helper_curl_easy_strerror(value v_code)
6388 CAMLparam1(v_code);
6389 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code))));
6393 * Wrappers for the curl_multi_socket_action infrastructure
6394 * Based on curl hiperfifo.c example
6397 #ifdef _WIN32
6398 #ifndef Val_socket
6399 #define Val_socket(v) win_alloc_socket(v)
6400 #endif
6401 #ifndef Socket_val
6402 #error Socket_val not defined in unixsupport.h
6403 #endif
6404 #else /* _WIN32 */
6405 #ifndef Socket_val
6406 #define Socket_val(v) Long_val(v)
6407 #endif
6408 #ifndef Val_socket
6409 #define Val_socket(v) Val_int(v)
6410 #endif
6411 #endif /* _WIN32 */
6413 static void raise_error(char const* msg)
6415 static value* exception = NULL;
6417 if (NULL == exception)
6419 exception = caml_named_value("Curl.Multi.Error");
6420 if (NULL == exception) caml_invalid_argument("Curl.Multi.Error");
6423 caml_raise_with_string(*exception, msg);
6426 static void check_mcode(CURLMcode code)
6428 char const *s = NULL;
6429 switch (code)
6431 case CURLM_OK : return;
6432 case CURLM_CALL_MULTI_PERFORM : s="CURLM_CALL_MULTI_PERFORM"; break;
6433 case CURLM_BAD_HANDLE : s="CURLM_BAD_HANDLE"; break;
6434 case CURLM_BAD_EASY_HANDLE : s="CURLM_BAD_EASY_HANDLE"; break;
6435 case CURLM_OUT_OF_MEMORY : s="CURLM_OUT_OF_MEMORY"; break;
6436 case CURLM_INTERNAL_ERROR : s="CURLM_INTERNAL_ERROR"; break;
6437 case CURLM_UNKNOWN_OPTION : s="CURLM_UNKNOWN_OPTION"; break;
6438 case CURLM_LAST : s="CURLM_LAST"; break;
6439 case CURLM_BAD_SOCKET : s="CURLM_BAD_SOCKET"; break;
6440 default : s="CURLM_unknown"; break;
6442 raise_error(s);
6445 CAMLprim value caml_curl_multi_socket_action(value v_multi, value v_fd, value v_kind)
6447 CAMLparam3(v_multi, v_fd, v_kind);
6448 CURLM* h = CURLM_val(v_multi);
6449 int still_running = 0;
6450 CURLMcode rc = CURLM_OK;
6451 curl_socket_t socket;
6452 int kind = 0;
6454 if (Val_none == v_fd)
6456 socket = CURL_SOCKET_TIMEOUT;
6458 else
6460 socket = Socket_val(Field(v_fd, 0));
6463 switch (Int_val(v_kind))
6465 case 0 : break;
6466 case 1 : kind |= CURL_CSELECT_IN; break;
6467 case 2 : kind |= CURL_CSELECT_OUT; break;
6468 case 3 : kind |= CURL_CSELECT_IN | CURL_CSELECT_OUT; break;
6469 default:
6470 raise_error("caml_curl_multi_socket_action");
6473 /* fprintf(stdout,"fd %u kind %u\n",socket, kind); fflush(stdout); */
6475 caml_enter_blocking_section();
6476 do {
6477 rc = curl_multi_socket_action(h, socket, kind, &still_running);
6478 } while (rc == CURLM_CALL_MULTI_PERFORM);
6479 caml_leave_blocking_section();
6481 check_mcode(rc);
6483 CAMLreturn(Val_int(still_running));
6486 CAMLprim value caml_curl_multi_socket_all(value v_multi)
6488 CAMLparam1(v_multi);
6489 int still_running = 0;
6490 CURLMcode rc = CURLM_OK;
6491 CURLM* h = CURLM_val(v_multi);
6493 caml_enter_blocking_section();
6494 do {
6495 rc = curl_multi_socket_all(h, &still_running);
6496 } while (rc == CURLM_CALL_MULTI_PERFORM);
6497 caml_leave_blocking_section();
6499 check_mcode(rc);
6501 CAMLreturn(Val_int(still_running));
6504 static int curlm_sock_cb_nolock(CURL *e, curl_socket_t sock, int what, ml_multi_handle* multi, void *sockp)
6506 CAMLparam0();
6507 CAMLlocal2(v_what,csock);
6508 (void)e;
6509 (void)sockp; /* not used */
6511 /* v_what = Val_int(what); */
6512 switch (what)
6514 case CURL_POLL_NONE : v_what = Val_int(0); break;
6515 case CURL_POLL_IN : v_what = Val_int(1); break;
6516 case CURL_POLL_OUT : v_what = Val_int(2); break;
6517 case CURL_POLL_INOUT : v_what = Val_int(3); break;
6518 case CURL_POLL_REMOVE : v_what = Val_int(4); break;
6519 default:
6520 fprintf(stderr, "curlm_sock_cb sock=%d what=%d\n", sock, what);
6521 fflush(stderr);
6522 raise_error("curlm_sock_cb"); /* FIXME exception from callback */
6524 csock=Val_socket(sock);
6525 caml_callback2(Field(multi->values,curlmopt_socket_function),
6526 csock, v_what);
6528 CAMLreturn(0);
6531 static int curlm_sock_cb(CURL *e, curl_socket_t sock, int what, void *cbp, void *sockp)
6533 int ret;
6534 caml_leave_blocking_section();
6535 ret = curlm_sock_cb_nolock(e, sock, what, (ml_multi_handle*)cbp, sockp);
6536 caml_enter_blocking_section();
6537 return ret;
6540 CAMLprim value caml_curl_multi_socketfunction(value v_multi, value v_cb)
6542 CAMLparam2(v_multi, v_cb);
6543 ml_multi_handle* multi = Multi_val(v_multi);
6545 Store_field(multi->values, curlmopt_socket_function, v_cb);
6547 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETFUNCTION, curlm_sock_cb);
6548 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETDATA, multi);
6550 CAMLreturn(Val_unit);
6553 static void curlm_timer_cb_nolock(ml_multi_handle *multi, long timeout_ms)
6555 CAMLparam0();
6556 caml_callback(Field(multi->values,curlmopt_timer_function), Val_long(timeout_ms));
6557 CAMLreturn0;
6560 static int curlm_timer_cb(CURLM *multi, long timeout_ms, void *userp)
6562 (void)multi;
6564 caml_leave_blocking_section();
6565 curlm_timer_cb_nolock((ml_multi_handle*)userp, timeout_ms);
6566 caml_enter_blocking_section();
6567 return 0;
6570 CAMLprim value caml_curl_multi_timerfunction(value v_multi, value v_cb)
6572 CAMLparam2(v_multi, v_cb);
6573 ml_multi_handle* multi = Multi_val(v_multi);
6575 Store_field(multi->values, curlmopt_timer_function, v_cb);
6577 curl_multi_setopt(multi->handle, CURLMOPT_TIMERFUNCTION, curlm_timer_cb);
6578 curl_multi_setopt(multi->handle, CURLMOPT_TIMERDATA, multi);
6580 CAMLreturn(Val_unit);
6583 CAMLprim value caml_curl_multi_timeout(value v_multi)
6585 CAMLparam1(v_multi);
6586 long ms = 0;
6587 CURLMcode rc = CURLM_OK;
6588 ml_multi_handle* multi = Multi_val(v_multi);
6590 rc = curl_multi_timeout(multi->handle, &ms);
6592 check_mcode(rc);
6594 CAMLreturn(Val_long(ms));