4 *** Copyright (c) 2003-2008, Lars Nilsson, <lars@quantumchamaeleon.com>
5 *** Copyright (c) 2009, ygrek, <ygrek@autistici.org>
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>
28 #pragma message("No config file given.")
31 void leave_blocking_section(void);
32 void enter_blocking_section(void);
34 #define Val_none Val_int(0)
41 some
= caml_alloc(1, 0);
42 Store_field( some
, 0, v
);
46 static value
Val_pair(value v1
, value v2
)
50 pair
= caml_alloc_small(2,0);
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))
74 OcamlProgressCallback
,
78 OcamlSeekFunctionCallback
,
79 OcamlOpenSocketFunctionCallback
,
111 OcamlFTPAlternativeToUser
,
112 OcamlSSHPublicKeyFile
,
113 OcamlSSHPrivateKeyFile
,
114 OcamlSSHHostPublicKeyMD5
,
122 /* Not used, last for size */
134 size_t refcount
; /* number of references to this structure */
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
;
160 struct curl_slist
*quote
;
161 struct curl_slist
*postQuote
;
164 char *interface_
; /* `interface` gives problems on windows */
172 struct curl_slist
*http200Aliases
;
176 char *ftpAlternativeToUser
;
177 char *sshPublicKeyFile
;
178 char *sshPrivateKeyFile
;
179 char *sshHostPublicKeyMD5
;
180 char *copyPostFields
;
183 struct curl_slist
*mailRcpt
;
186 struct ConnectionList
192 static ConnectionList connectionList
= {NULL
, NULL
};
194 typedef struct CURLErrorMapping CURLErrorMapping
;
196 struct CURLErrorMapping
202 CURLErrorMapping errorMap
[] =
204 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
205 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL
},
207 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
209 #if HAVE_DECL_CURLE_FAILED_INIT
210 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT
},
212 {"CURLE_FAILED_INIT", -1},
214 #if HAVE_DECL_CURLE_URL_MALFORMAT
215 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT
},
217 {"CURLE_URL_MALFORMAT", -1},
219 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
220 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER
},
222 {"CURLE_URL_MALFORMAT_USER", -1},
224 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
225 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY
},
227 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
229 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
230 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST
},
232 {"CURLE_COULDNT_RESOLVE_HOST", -1},
234 #if HAVE_DECL_CURLE_COULDNT_CONNECT
235 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT
},
237 {"CURLE_COULDNT_CONNECT", -1},
239 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
240 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY
},
242 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
244 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
245 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED
},
247 {"CURLE_FTP_ACCESS_DENIED", -1},
249 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
250 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT
},
252 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
254 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
255 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY
},
257 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
259 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
260 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY
},
262 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
264 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
265 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY
},
267 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
269 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
270 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT
},
272 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
274 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
275 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST
},
277 {"CURLE_FTP_CANT_GET_HOST", -1},
279 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
280 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT
},
282 {"CURLE_FTP_CANT_RECONNECT", -1},
284 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
285 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY
},
287 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
289 #if HAVE_DECL_CURLE_PARTIAL_FILE
290 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE
},
292 {"CURLE_PARTIAL_FILE", -1},
294 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
295 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE
},
297 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
299 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
300 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR
},
302 {"CURLE_FTP_WRITE_ERROR", -1},
304 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
305 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR
},
307 {"CURLE_FTP_QUOTE_ERROR", -1},
309 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
310 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND
},
312 {"CURLE_HTTP_NOT_FOUND", -1},
314 #if HAVE_DECL_CURLE_WRITE_ERROR
315 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR
},
317 {"CURLE_WRITE_ERROR", -1},
319 #if HAVE_DECL_CURLE_MALFORMAT_USER
320 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER
},
322 {"CURLE_MALFORMAT_USER", -1},
324 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
325 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE
},
327 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
329 #if HAVE_DECL_CURLE_READ_ERROR
330 {"CURLE_READ_ERROR", CURLE_READ_ERROR
},
332 {"CURLE_READ_ERROR", -1},
334 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
335 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY
},
337 {"CURLE_OUT_OF_MEMORY", -1},
339 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
340 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED
},
342 {"CURLE_OPERATION_TIMEOUTED", -1},
344 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
345 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII
},
347 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
349 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
350 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED
},
352 {"CURLE_FTP_PORT_FAILED", -1},
354 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
355 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST
},
357 {"CURLE_FTP_COULDNT_USE_REST", -1},
359 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
360 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE
},
362 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
364 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
365 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR
},
367 {"CURLE_HTTP_RANGE_ERROR", -1},
369 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
370 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR
},
372 {"CURLE_HTTP_POST_ERROR", -1},
374 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
375 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR
},
377 {"CURLE_SSL_CONNECT_ERROR", -1},
379 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
380 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME
},
382 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
384 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
385 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE
},
387 {"CURLE_FILE_COULDNT_READ_FILE", -1},
389 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
390 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND
},
392 {"CURLE_LDAP_CANNOT_BIND", -1},
394 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
395 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED
},
397 {"CURLE_LDAP_SEARCH_FAILED", -1},
399 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
400 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND
},
402 {"CURLE_LIBRARY_NOT_FOUND", -1},
404 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
405 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND
},
407 {"CURLE_FUNCTION_NOT_FOUND", -1},
409 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
410 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK
},
412 {"CURLE_ABORTED_BY_CALLBACK", -1},
414 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
415 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT
},
417 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
419 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
420 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER
},
422 {"CURLE_BAD_CALLING_ORDER", -1},
424 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
425 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED
},
427 {"CURLE_HTTP_PORT_FAILED", -1},
429 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
430 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED
},
432 {"CURLE_BAD_PASSWORD_ENTERED", -1},
434 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
435 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS
},
437 {"CURLE_TOO_MANY_REDIRECTS", -1},
439 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
440 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION
},
442 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
444 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
445 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX
},
447 {"CURLE_TELNET_OPTION_SYNTAX", -1},
449 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
450 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE
},
452 {"CURLE_SSL_PEER_CERTIFICATE", -1},
454 #if HAVE_DECL_CURLE_GOT_NOTHING
455 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING
},
457 {"CURLE_GOT_NOTHING", -1},
459 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
460 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND
},
462 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
464 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
465 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED
},
467 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
469 #if HAVE_DECL_CURLE_SEND_ERROR
470 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR
},
472 {"CURLE_SEND_ERROR", -1},
474 #if HAVE_DECL_CURLE_RECV_ERROR
475 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR
},
477 {"CURLE_RECV_ERROR", -1},
479 #if HAVE_DECL_CURLE_SHARE_IN_USE
480 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE
},
482 {"CURLE_SHARE_IN_USE", -1},
484 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
485 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM
},
487 {"CURLE_SSL_CERTPROBLEN", -1},
489 #if HAVE_DECL_CURLE_SSL_CIPHER
490 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER
},
492 {"CURLE_SSL_CIPHER", -1},
494 #if HAVE_DECL_CURLE_SSL_CACERT
495 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT
},
497 {"CURLE_SSL_CACERT", -1},
499 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
500 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING
},
502 {"CURLE_BAD_CONTENT_ENCODING", -1},
504 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
505 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL
},
507 {"CURLE_LDAP_INVALID_URL", -1},
509 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
510 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED
},
512 {"CURLE_FILESIZE_EXCEEDED", -1},
514 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
515 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED
},
517 {"CURLE_FTP_SSL_FAILED", -1},
519 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
520 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND
},
522 {"CURLE_SEND_FAIL_REWIND", -1},
524 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
525 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED
},
527 {"CURLE_SSL_ENGINE_INITFAILED", -1},
529 #if HAVE_DECL_CURLE_LOGIN_DENIED
530 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED
},
532 {"CURLE_LOGIN_DENIED", -1},
534 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
535 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND
},
537 {"CURLE_TFTP_NOTFOUND", -1},
539 #if HAVE_DECL_CURLE_TFTP_PERM
540 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM
},
542 {"CURLE_TFTP_PERM", -1},
544 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
545 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL
},
547 {"CURLE_REMOTE_DISK_FULL", -1},
549 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
550 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL
},
552 {"CURLE_TFTP_ILLEGAL", -1},
554 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
555 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID
},
557 {"CURLE_TFTP_UNKNOWNID", -1},
559 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
560 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS
},
562 {"CURLE_REMOTE_FILE_EXISTS", -1},
564 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
565 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER
},
567 {"CURLE_TFTP_NOSUCHUSER", -1},
569 #if HAVE_DECL_CURLE_CONV_FAILED
570 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED
},
572 {"CURLE_CONV_FAILED", -1},
574 #if HAVE_DECL_CURLE_CONV_REQUIRED
575 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED
},
577 {"CURLE_CONV_REQUIRED", -1},
579 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
580 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE
},
582 {"CURLE_SSL_CACERT_BADFILE", -1},
584 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
585 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND
},
587 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
589 #if HAVE_DECL_CURLE_SSH
590 {"CURLE_SSH", CURLE_SSH
},
594 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
595 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED
},
597 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
599 #if HAVE_DECL_CURLE_AGAIN
600 {"CURLE_AGAIN", CURLE_AGAIN
},
604 {"CURLE_OK", CURLE_OK
},
608 typedef struct CURLOptionMapping CURLOptionMapping
;
610 struct CURLOptionMapping
612 void (*optionHandler
)(Connection
*, value
);
614 /* CURLoption option; */
617 static void free_curl_slist(struct curl_slist
*slist
)
622 curl_slist_free_all(slist
);
625 static void raiseError(Connection
*conn
, CURLcode code
)
628 CAMLlocal1(exceptionData
);
630 char *errorString
= "Unknown Error";
633 for (i
= 0; errorMap
[i
].name
!= NULL
; i
++)
635 if (errorMap
[i
].error
== code
)
637 errorString
= errorMap
[i
].name
;
642 exceptionData
= caml_alloc(3, 0);
644 Store_field(exceptionData
, 0, Val_int(code
));
645 Store_field(exceptionData
, 1, Val_int(code
));
646 Store_field(exceptionData
, 2, copy_string(errorString
));
648 if (conn
!= NULL
&& conn
->errorBuffer
!= NULL
)
650 Store_field(Field(conn
->ocamlValues
, OcamlErrorBuffer
), 0,
651 copy_string(conn
->errorBuffer
));
654 exception
= caml_named_value("CurlException");
656 if (exception
== NULL
)
657 caml_failwith("CurlException not registered");
659 raise_with_arg(*exception
, exceptionData
);
664 static void resetOcamlValues(Connection
* connection
)
668 for (i
= 0; i
< OcamlValuesSize
; i
++)
669 Store_field(connection
->ocamlValues
, i
, Val_unit
);
672 static Connection
* allocConnection(CURL
* h
)
674 Connection
* connection
= (Connection
*)malloc(sizeof(Connection
));
676 connection
->ocamlValues
= caml_alloc(OcamlValuesSize
, 0);
677 resetOcamlValues(connection
);
678 register_global_root(&connection
->ocamlValues
);
680 connection
->connection
= h
;
682 connection
->next
= NULL
;
683 connection
->prev
= NULL
;
685 if (connectionList
.tail
== NULL
)
687 connectionList
.tail
= connection
;
688 connectionList
.head
= connection
;
692 connection
->prev
= connectionList
.head
;
693 connectionList
.head
->next
= connection
;
694 connectionList
.head
= connection
;
697 connection
->refcount
= 0;
699 connection
->url
= NULL
;
700 connection
->proxy
= NULL
;
701 connection
->userPwd
= NULL
;
702 connection
->proxyUserPwd
= NULL
;
703 connection
->range
= NULL
;
704 connection
->errorBuffer
= NULL
;
705 connection
->postFields
= NULL
;
706 connection
->postFieldSize
= -1;
707 connection
->referer
= NULL
;
708 connection
->userAgent
= NULL
;
709 connection
->ftpPort
= NULL
;
710 connection
->cookie
= NULL
;
711 connection
->httpHeader
= NULL
;
712 connection
->httpPostFirst
= NULL
;
713 connection
->httpPostLast
= NULL
;
714 connection
->httpPostStrings
= NULL
;
715 connection
->sslCert
= NULL
;
716 connection
->sslCertType
= NULL
;
717 connection
->sslCertPasswd
= NULL
;
718 connection
->sslKey
= NULL
;
719 connection
->sslKeyType
= NULL
;
720 connection
->sslKeyPasswd
= NULL
;
721 connection
->sslEngine
= NULL
;
722 connection
->quote
= NULL
;
723 connection
->postQuote
= NULL
;
724 connection
->cookieFile
= NULL
;
725 connection
->customRequest
= NULL
;
726 connection
->interface_
= NULL
;
727 connection
->caInfo
= NULL
;
728 connection
->caPath
= NULL
;
729 connection
->randomFile
= NULL
;
730 connection
->egdSocket
= NULL
;
731 connection
->cookieJar
= NULL
;
732 connection
->sslCipherList
= NULL
;
733 connection
->private = NULL
;
734 connection
->http200Aliases
= NULL
;
735 connection
->netrcFile
= NULL
;
736 connection
->ftpaccount
= NULL
;
737 connection
->cookielist
= NULL
;
738 connection
->ftpAlternativeToUser
= NULL
;
739 connection
->sshPublicKeyFile
= NULL
;
740 connection
->sshPrivateKeyFile
= NULL
;
741 connection
->copyPostFields
= NULL
;
742 connection
->resolve
= NULL
;
743 connection
->dns_servers
= NULL
;
744 connection
->mailFrom
= NULL
;
745 connection
->mailRcpt
= NULL
;
750 static Connection
*newConnection(void)
754 caml_enter_blocking_section();
755 h
= curl_easy_init();
756 caml_leave_blocking_section();
758 return allocConnection(h
);
761 static void free_if(void* p
) { if (NULL
!= p
) free(p
); }
763 static void removeConnection(Connection
*connection
, int finalization
)
765 const char* fin_url
= NULL
;
767 if (!connection
->connection
)
769 return; /* already cleaned up */
774 /* cannot engage OCaml runtime at finalization, just report leak */
775 if (CURLE_OK
!= curl_easy_getinfo(connection
->connection
, CURLINFO_EFFECTIVE_URL
, &fin_url
) || NULL
== fin_url
)
779 fprintf(stderr
,"Curl: handle %p leaked, conn %p, url %s\n", connection
->connection
, connection
, fin_url
);
784 enter_blocking_section();
785 curl_easy_cleanup(connection
->connection
);
786 leave_blocking_section();
789 connection
->connection
= NULL
;
791 if (connectionList
.tail
== connection
)
792 connectionList
.tail
= connectionList
.tail
->next
;
793 if (connectionList
.head
== connection
)
794 connectionList
.head
= connectionList
.head
->prev
;
796 if (connection
->next
!= NULL
)
797 connection
->next
->prev
= connection
->prev
;
798 if (connection
->prev
!= NULL
)
799 connection
->prev
->next
= connection
->next
;
801 remove_global_root(&connection
->ocamlValues
);
803 free_if(connection
->url
);
804 free_if(connection
->proxy
);
805 free_if(connection
->userPwd
);
806 free_if(connection
->proxyUserPwd
);
807 free_if(connection
->range
);
808 free_if(connection
->errorBuffer
);
809 free_if(connection
->postFields
);
810 free_if(connection
->referer
);
811 free_if(connection
->userAgent
);
812 free_if(connection
->ftpPort
);
813 free_if(connection
->cookie
);
814 free_curl_slist(connection
->httpHeader
);
815 if (connection
->httpPostFirst
!= NULL
)
816 curl_formfree(connection
->httpPostFirst
);
817 free_curl_slist(connection
->httpPostStrings
);
818 free_curl_slist(connection
->resolve
);
819 free_if(connection
->sslCert
);
820 free_if(connection
->sslCertType
);
821 free_if(connection
->sslCertPasswd
);
822 free_if(connection
->sslKey
);
823 free_if(connection
->sslKeyType
);
824 free_if(connection
->sslKeyPasswd
);
825 free_if(connection
->sslEngine
);
826 free_curl_slist(connection
->quote
);
827 free_curl_slist(connection
->postQuote
);
828 free_if(connection
->cookieFile
);
829 free_if(connection
->customRequest
);
830 free_if(connection
->interface_
);
831 free_if(connection
->caInfo
);
832 free_if(connection
->caPath
);
833 free_if(connection
->randomFile
);
834 free_if(connection
->egdSocket
);
835 free_if(connection
->cookieJar
);
836 free_if(connection
->sslCipherList
);
837 free_if(connection
->private);
838 free_curl_slist(connection
->http200Aliases
);
839 free_if(connection
->netrcFile
);
840 free_if(connection
->ftpaccount
);
841 free_if(connection
->cookielist
);
842 free_if(connection
->ftpAlternativeToUser
);
843 free_if(connection
->sshPublicKeyFile
);
844 free_if(connection
->sshPrivateKeyFile
);
845 free_if(connection
->copyPostFields
);
846 free_if(connection
->dns_servers
);
847 free_if(connection
->mailFrom
);
848 free_curl_slist(connection
->mailRcpt
);
852 static void checkConnection(Connection
* connection
)
857 static void checkConnection(Connection
*connection
)
859 Connection
*listIter
;
861 listIter
= connectionList
.tail
;
863 while (listIter
!= NULL
)
865 if (listIter
== connection
)
868 listIter
= listIter
->next
;
871 failwith("Invalid Connection");
875 static Connection
* findConnection(CURL
* h
)
877 Connection
*listIter
;
879 listIter
= connectionList
.tail
;
881 while (listIter
!= NULL
)
883 if (listIter
->connection
== h
)
886 listIter
= listIter
->next
;
889 failwith("Unknown handle");
892 void op_curl_easy_finalize(value v
)
894 Connection
* conn
= Connection_val(v
);
895 /* same connection may be referenced by several different
896 OCaml values, see e.g. caml_curl_multi_remove_finished */
898 if (0 == conn
->refcount
)
900 removeConnection(conn
, 1);
905 int op_curl_easy_compare(value v1
, value v2
)
907 size_t p1
= (size_t)Connection_val(v1
);
908 size_t p2
= (size_t)Connection_val(v2
);
909 return (p1
== p2
? 0 : (p1
> p2
? 1 : -1)); /* compare addresses */
912 intnat
op_curl_easy_hash(value v
)
914 return (size_t)Connection_val(v
); /* address */
917 static struct custom_operations curl_easy_ops
= {
919 op_curl_easy_finalize
,
920 op_curl_easy_compare
,
922 custom_serialize_default
,
923 custom_deserialize_default
,
924 #if defined(custom_compare_ext_default)
925 custom_compare_ext_default
,
929 value
caml_curl_alloc(Connection
* conn
)
931 value v
= caml_alloc_custom(&curl_easy_ops
, sizeof(Connection
*), 0, 1);
932 Connection_val(v
) = conn
;
937 #define WRAP_DATA_CALLBACK(f) \
938 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
941 leave_blocking_section();\
942 result = f##_nolock(ptr,size,nmemb,data);\
943 enter_blocking_section();\
947 static size_t writeFunction_nolock(char *ptr
, size_t size
, size_t nmemb
, void *data
)
950 CAMLlocal2(result
, str
);
951 Connection
*conn
= (Connection
*)data
;
954 checkConnection(conn
);
956 str
= alloc_string(size
*nmemb
);
958 for (i
= 0; i
< size
*nmemb
; i
++)
959 Byte(str
, i
) = ptr
[i
];
961 result
= callback_exn(Field(conn
->ocamlValues
, OcamlWriteCallback
), str
);
963 CAMLreturnT(size_t, Is_exception_result(result
) ? 0 : Int_val(result
));
966 WRAP_DATA_CALLBACK(writeFunction
)
968 static size_t readFunction_nolock(void *ptr
, size_t size
, size_t nmemb
, void *data
)
972 Connection
*conn
= (Connection
*)data
;
975 checkConnection(conn
);
977 result
= callback_exn(Field(conn
->ocamlValues
, OcamlReadCallback
),
978 Val_int(size
*nmemb
));
980 if (Is_exception_result(result
))
982 CAMLreturnT(size_t,CURL_READFUNC_ABORT
);
985 length
= string_length(result
);
987 if (length
<= size
*nmemb
)
989 memcpy(ptr
, String_val(result
), length
);
991 CAMLreturnT(size_t,length
);
995 CAMLreturnT(size_t,CURL_READFUNC_ABORT
);
999 WRAP_DATA_CALLBACK(readFunction
)
1001 static size_t headerFunction_nolock(char *ptr
, size_t size
, size_t nmemb
, void *data
)
1004 CAMLlocal2(result
,str
);
1005 Connection
*conn
= (Connection
*)data
;
1008 checkConnection(conn
);
1010 str
= alloc_string(size
*nmemb
);
1012 for (i
= 0; i
< size
*nmemb
; i
++)
1013 Byte(str
, i
) = ptr
[i
];
1015 result
= callback_exn(Field(conn
->ocamlValues
, OcamlHeaderCallback
), str
);
1017 CAMLreturnT(size_t, Is_exception_result(result
) ? 0 : Int_val(result
));
1020 WRAP_DATA_CALLBACK(headerFunction
)
1022 static int progressFunction_nolock(void *data
,
1030 CAMLlocalN(callbackData
, 4);
1031 Connection
*conn
= (Connection
*)data
;
1033 checkConnection(conn
);
1035 callbackData
[0] = copy_double(dlTotal
);
1036 callbackData
[1] = copy_double(dlNow
);
1037 callbackData
[2] = copy_double(ulTotal
);
1038 callbackData
[3] = copy_double(ulNow
);
1040 result
= callbackN_exn(Field(conn
->ocamlValues
, OcamlProgressCallback
),
1043 CAMLreturnT(int, Is_exception_result(result
) ? 1 : Bool_val(result
));
1046 static int progressFunction(void *data
,
1053 leave_blocking_section();
1054 r
= progressFunction_nolock(data
,dlTotal
,dlNow
,ulTotal
,ulNow
);
1055 enter_blocking_section();
1059 static int debugFunction_nolock(CURL
*debugConnection
,
1060 curl_infotype infoType
,
1062 size_t bufferLength
,
1066 CAMLlocal3(camlDebugConnection
, camlInfoType
, camlMessage
);
1068 Connection
*conn
= (Connection
*)data
;
1069 (void)debugConnection
; /* not used */
1071 checkConnection(conn
);
1073 camlDebugConnection
= (value
)conn
;
1074 camlInfoType
= Val_long(infoType
);
1075 camlMessage
= alloc_string(bufferLength
);
1077 for (i
= 0; i
< bufferLength
; i
++)
1078 Byte(camlMessage
, i
) = buffer
[i
];
1080 callback3_exn(Field(conn
->ocamlValues
, OcamlDebugCallback
),
1081 camlDebugConnection
,
1085 CAMLreturnT(int, 0);
1088 static int debugFunction(CURL
*debugConnection
,
1089 curl_infotype infoType
,
1091 size_t bufferLength
,
1095 leave_blocking_section();
1096 r
= debugFunction_nolock(debugConnection
, infoType
, buffer
, bufferLength
, data
);
1097 enter_blocking_section();
1101 static curlioerr
ioctlFunction_nolock(CURL
*ioctl
,
1106 CAMLlocal3(camlResult
, camlConnection
, camlCmd
);
1107 Connection
*conn
= (Connection
*)data
;
1108 curlioerr result
= CURLIOE_OK
;
1109 (void)ioctl
; /* not used */
1111 checkConnection(conn
);
1113 if (cmd
== CURLIOCMD_NOP
)
1114 camlCmd
= Val_long(0);
1115 else if (cmd
== CURLIOCMD_RESTARTREAD
)
1116 camlCmd
= Val_long(1);
1118 failwith("Invalid IOCTL Cmd!");
1120 camlConnection
= caml_curl_alloc(conn
);
1122 camlResult
= callback2_exn(Field(conn
->ocamlValues
, OcamlIOCTLCallback
),
1126 if (Is_exception_result(camlResult
))
1128 result
= CURLIOE_FAILRESTART
;
1131 switch (Long_val(camlResult
))
1133 case 0: /* CURLIOE_OK */
1134 result
= CURLIOE_OK
;
1137 case 1: /* CURLIOE_UNKNOWNCMD */
1138 result
= CURLIOE_UNKNOWNCMD
;
1141 case 2: /* CURLIOE_FAILRESTART */
1142 result
= CURLIOE_FAILRESTART
;
1145 default: /* Incorrect return value, but let's handle it */
1146 result
= CURLIOE_FAILRESTART
;
1150 CAMLreturnT(curlioerr
, result
);
1153 static curlioerr
ioctlFunction(CURL
*ioctl
,
1158 leave_blocking_section();
1159 r
= ioctlFunction_nolock(ioctl
, cmd
, data
);
1160 enter_blocking_section();
1164 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1165 static int seekFunction_nolock(void *data
,
1170 CAMLlocal3(camlResult
, camlOffset
, camlOrigin
);
1171 Connection
*conn
= (Connection
*)data
;
1173 camlOffset
= copy_int64(offset
);
1175 if (origin
== SEEK_SET
)
1176 camlOrigin
= Val_long(0);
1177 else if (origin
== SEEK_CUR
)
1178 camlOrigin
= Val_long(1);
1179 else if (origin
== SEEK_END
)
1180 camlOrigin
= Val_long(2);
1182 failwith("Invalid seek code");
1184 camlResult
= callback2_exn(Field(conn
->ocamlValues
,
1185 OcamlSeekFunctionCallback
),
1190 if (Is_exception_result(camlResult
))
1191 result
= CURL_SEEKFUNC_FAIL
;
1193 switch (Int_val(camlResult
))
1195 case 0: result
= CURL_SEEKFUNC_OK
; break;
1196 case 1: result
= CURL_SEEKFUNC_FAIL
; break;
1197 case 2: result
= CURL_SEEKFUNC_CANTSEEK
; break;
1198 default: failwith("Invalid seek result");
1201 CAMLreturnT(int, result
);
1204 static int seekFunction(void *data
,
1209 leave_blocking_section();
1210 r
= seekFunction_nolock(data
,offset
,origin
);
1211 enter_blocking_section();
1217 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1218 static int openSocketFunction_nolock(void *data
,
1219 curlsocktype purpose
,
1220 struct curl_sockaddr
*addr
)
1224 Connection
*conn
= (Connection
*)data
;
1226 (void)purpose
; /* not used */
1228 sock
= socket(addr
->family
, addr
->socktype
, addr
->protocol
);
1233 result
= callback_exn(Field(conn
->ocamlValues
, OcamlOpenSocketFunctionCallback
), Val_int(sock
));
1234 if (Is_exception_result(result
))
1241 CAMLreturnT(int, (sock
== -1) ? CURL_SOCKET_BAD
: sock
);
1244 static int openSocketFunction(void *data
,
1245 curlsocktype purpose
,
1246 struct curl_sockaddr
*address
)
1249 leave_blocking_section();
1250 r
= openSocketFunction_nolock(data
,purpose
,address
);
1251 enter_blocking_section();
1258 ** curl_global_init helper function
1261 CAMLprim value
helper_curl_global_init(value initOption
)
1263 CAMLparam1(initOption
);
1265 switch (Long_val(initOption
))
1267 case 0: /* CURLINIT_GLOBALALL */
1268 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL
)));
1271 case 1: /* CURLINIT_GLOBALSSL */
1272 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL
)));
1275 case 2: /* CURLINIT_GLOBALWIN32 */
1276 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32
)));
1279 case 3: /* CURLINIT_GLOBALNOTHING */
1280 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING
)));
1284 failwith("Invalid Initialization Option");
1288 /* Keep compiler happy, we should never get here due to failwith() */
1289 CAMLreturn(Val_unit
);
1293 ** curl_global_cleanup helper function
1296 CAMLprim value
helper_curl_global_cleanup(void)
1300 curl_global_cleanup();
1302 CAMLreturn(Val_unit
);
1306 ** curl_easy_init helper function
1308 CAMLprim value
helper_curl_easy_init(void)
1313 result
= caml_curl_alloc(newConnection());
1318 CAMLprim value
helper_curl_easy_reset(value conn
)
1321 Connection
*connection
= Connection_val(conn
);
1323 checkConnection(connection
);
1324 curl_easy_reset(connection
->connection
);
1325 resetOcamlValues(connection
);
1327 CAMLreturn(Val_unit
);
1331 ** curl_easy_setopt helper utility functions
1334 static void handle_WRITEFUNCTION(Connection
*conn
, value option
)
1337 CURLcode result
= CURLE_OK
;
1339 if (Tag_val(option
) == Closure_tag
)
1340 Store_field(conn
->ocamlValues
, OcamlWriteCallback
, option
);
1342 failwith("Not a proper closure");
1344 result
= curl_easy_setopt(conn
->connection
,
1345 CURLOPT_WRITEFUNCTION
,
1348 if (result
!= CURLE_OK
)
1349 raiseError(conn
, result
);
1351 result
= curl_easy_setopt(conn
->connection
,
1355 if (result
!= CURLE_OK
)
1356 raiseError(conn
, result
);
1361 static void handle_READFUNCTION(Connection
*conn
, value option
)
1364 CURLcode result
= CURLE_OK
;
1366 if (Tag_val(option
) == Closure_tag
)
1367 Store_field(conn
->ocamlValues
, OcamlReadCallback
, option
);
1369 failwith("Not a proper closure");
1371 result
= curl_easy_setopt(conn
->connection
,
1372 CURLOPT_READFUNCTION
,
1375 if (result
!= CURLE_OK
)
1376 raiseError(conn
, result
);
1378 result
= curl_easy_setopt(conn
->connection
,
1382 if (result
!= CURLE_OK
)
1383 raiseError(conn
, result
);
1388 static void handle_URL(Connection
*conn
, value option
)
1391 CURLcode result
= CURLE_OK
;
1393 Store_field(conn
->ocamlValues
, OcamlURL
, option
);
1395 if (conn
->url
!= NULL
)
1398 conn
->url
= strdup(String_val(option
));
1400 result
= curl_easy_setopt(conn
->connection
,
1404 if (result
!= CURLE_OK
)
1405 raiseError(conn
, result
);
1410 static void handle_INFILESIZE(Connection
*conn
, value option
)
1413 CURLcode result
= CURLE_OK
;
1415 result
= curl_easy_setopt(conn
->connection
,
1419 if (result
!= CURLE_OK
)
1420 raiseError(conn
, result
);
1425 static void handle_PROXY(Connection
*conn
, value option
)
1428 CURLcode result
= CURLE_OK
;
1430 Store_field(conn
->ocamlValues
, OcamlProxy
, option
);
1432 if (conn
->proxy
!= NULL
)
1435 conn
->proxy
= strdup(String_val(option
));
1437 result
= curl_easy_setopt(conn
->connection
,
1441 if (result
!= CURLE_OK
)
1442 raiseError(conn
, result
);
1447 static void handle_PROXYPORT(Connection
*conn
, value option
)
1450 CURLcode result
= CURLE_OK
;
1452 result
= curl_easy_setopt(conn
->connection
,
1456 if (result
!= CURLE_OK
)
1457 raiseError(conn
, result
);
1462 static void handle_HTTPPROXYTUNNEL(Connection
*conn
, value option
)
1465 CURLcode result
= CURLE_OK
;
1467 result
= curl_easy_setopt(conn
->connection
,
1468 CURLOPT_HTTPPROXYTUNNEL
,
1471 if (result
!= CURLE_OK
)
1472 raiseError(conn
, result
);
1477 static void handle_VERBOSE(Connection
*conn
, value option
)
1480 CURLcode result
= CURLE_OK
;
1482 result
= curl_easy_setopt(conn
->connection
,
1486 if (result
!= CURLE_OK
)
1487 raiseError(conn
, result
);
1492 static void handle_HEADER(Connection
*conn
, value option
)
1495 CURLcode result
= CURLE_OK
;
1497 result
= curl_easy_setopt(conn
->connection
,
1501 if (result
!= CURLE_OK
)
1502 raiseError(conn
, result
);
1507 static void handle_NOPROGRESS(Connection
*conn
, value option
)
1510 CURLcode result
= CURLE_OK
;
1512 result
= curl_easy_setopt(conn
->connection
,
1516 if (result
!= CURLE_OK
)
1517 raiseError(conn
, result
);
1522 #if HAVE_DECL_CURLOPT_NOSIGNAL
1523 static void handle_NOSIGNAL(Connection
*conn
, value option
)
1526 CURLcode result
= CURLE_OK
;
1528 result
= curl_easy_setopt(conn
->connection
,
1532 if (result
!= CURLE_OK
)
1533 raiseError(conn
, result
);
1539 static void handle_NOBODY(Connection
*conn
, value option
)
1542 CURLcode result
= CURLE_OK
;
1544 result
= curl_easy_setopt(conn
->connection
,
1548 if (result
!= CURLE_OK
)
1549 raiseError(conn
, result
);
1554 static void handle_FAILONERROR(Connection
*conn
, value option
)
1557 CURLcode result
= CURLE_OK
;
1559 result
= curl_easy_setopt(conn
->connection
,
1560 CURLOPT_FAILONERROR
,
1563 if (result
!= CURLE_OK
)
1564 raiseError(conn
, result
);
1569 static void handle_UPLOAD(Connection
*conn
, value option
)
1572 CURLcode result
= CURLE_OK
;
1574 result
= curl_easy_setopt(conn
->connection
,
1578 if (result
!= CURLE_OK
)
1579 raiseError(conn
, result
);
1584 static void handle_POST(Connection
*conn
, value option
)
1587 CURLcode result
= CURLE_OK
;
1589 result
= curl_easy_setopt(conn
->connection
,
1593 if (result
!= CURLE_OK
)
1594 raiseError(conn
, result
);
1599 static void handle_FTPLISTONLY(Connection
*conn
, value option
)
1602 CURLcode result
= CURLE_OK
;
1604 result
= curl_easy_setopt(conn
->connection
,
1605 CURLOPT_FTPLISTONLY
,
1608 if (result
!= CURLE_OK
)
1609 raiseError(conn
, result
);
1614 static void handle_FTPAPPEND(Connection
*conn
, value option
)
1617 CURLcode result
= CURLE_OK
;
1619 result
= curl_easy_setopt(conn
->connection
,
1623 if (result
!= CURLE_OK
)
1624 raiseError(conn
, result
);
1629 static void handle_NETRC(Connection
*conn
, value option
)
1632 CURLcode result
= CURLE_OK
;
1635 switch (Long_val(option
))
1637 case 0: /* CURL_NETRC_OPTIONAL */
1638 netrc
= CURL_NETRC_OPTIONAL
;
1641 case 1:/* CURL_NETRC_IGNORED */
1642 netrc
= CURL_NETRC_IGNORED
;
1645 case 2: /* CURL_NETRC_REQUIRED */
1646 netrc
= CURL_NETRC_REQUIRED
;
1650 failwith("Invalid NETRC Option");
1654 result
= curl_easy_setopt(conn
->connection
,
1658 if (result
!= CURLE_OK
)
1659 raiseError(conn
, result
);
1664 #if HAVE_DECL_CURLOPT_ENCODING
1665 static void handle_ENCODING(Connection
*conn
, value option
)
1668 CURLcode result
= CURLE_OK
;
1670 switch (Long_val(option
))
1672 case 0: /* CURL_ENCODING_NONE */
1673 result
= curl_easy_setopt(conn
->connection
,
1678 case 1: /* CURL_ENCODING_DEFLATE */
1679 result
= curl_easy_setopt(conn
->connection
,
1684 case 2: /* CURL_ENCODING_GZIP */
1685 result
= curl_easy_setopt(conn
->connection
,
1690 case 3: /* CURL_ENCODING_ANY */
1691 result
= curl_easy_setopt(conn
->connection
,
1697 failwith("Invalid Encoding Option");
1701 if (result
!= CURLE_OK
)
1702 raiseError(conn
, result
);
1708 static void handle_FOLLOWLOCATION(Connection
*conn
, value option
)
1711 CURLcode result
= CURLE_OK
;
1713 result
= curl_easy_setopt(conn
->connection
,
1714 CURLOPT_FOLLOWLOCATION
,
1717 if (result
!= CURLE_OK
)
1718 raiseError(conn
, result
);
1723 static void handle_TRANSFERTEXT(Connection
*conn
, value option
)
1726 CURLcode result
= CURLE_OK
;
1728 result
= curl_easy_setopt(conn
->connection
,
1729 CURLOPT_TRANSFERTEXT
,
1732 if (result
!= CURLE_OK
)
1733 raiseError(conn
, result
);
1738 static void handle_PUT(Connection
*conn
, value option
)
1741 CURLcode result
= CURLE_OK
;
1743 result
= curl_easy_setopt(conn
->connection
,
1747 if (result
!= CURLE_OK
)
1748 raiseError(conn
, result
);
1753 static void handle_USERPWD(Connection
*conn
, value option
)
1756 CURLcode result
= CURLE_OK
;
1758 Store_field(conn
->ocamlValues
, OcamlUserPWD
, option
);
1760 if (conn
->userPwd
!= NULL
)
1761 free(conn
->userPwd
);
1763 conn
->userPwd
= strdup(String_val(option
));
1765 result
= curl_easy_setopt(conn
->connection
,
1769 if (result
!= CURLE_OK
)
1770 raiseError(conn
, result
);
1775 static void handle_PROXYUSERPWD(Connection
*conn
, value option
)
1778 CURLcode result
= CURLE_OK
;
1780 Store_field(conn
->ocamlValues
, OcamlProxyUserPWD
, option
);
1782 if (conn
->proxyUserPwd
!= NULL
)
1783 free(conn
->proxyUserPwd
);
1785 conn
->proxyUserPwd
= strdup(String_val(option
));
1787 result
= curl_easy_setopt(conn
->connection
,
1788 CURLOPT_PROXYUSERPWD
,
1789 conn
->proxyUserPwd
);
1791 if (result
!= CURLE_OK
)
1792 raiseError(conn
, result
);
1797 static void handle_RANGE(Connection
*conn
, value option
)
1800 CURLcode result
= CURLE_OK
;
1802 Store_field(conn
->ocamlValues
, OcamlRange
, option
);
1804 if (conn
->range
!= NULL
)
1807 conn
->range
= strdup(String_val(option
));
1809 result
= curl_easy_setopt(conn
->connection
,
1813 if (result
!= CURLE_OK
)
1814 raiseError(conn
, result
);
1819 static void handle_ERRORBUFFER(Connection
*conn
, value option
)
1822 CURLcode result
= CURLE_OK
;
1824 Store_field(conn
->ocamlValues
, OcamlErrorBuffer
, option
);
1826 if (conn
->errorBuffer
!= NULL
)
1827 free(conn
->errorBuffer
);
1829 conn
->errorBuffer
= malloc(sizeof(char) * CURL_ERROR_SIZE
);
1831 result
= curl_easy_setopt(conn
->connection
,
1832 CURLOPT_ERRORBUFFER
,
1835 if (result
!= CURLE_OK
)
1836 raiseError(conn
, result
);
1841 static void handle_TIMEOUT(Connection
*conn
, value option
)
1844 CURLcode result
= CURLE_OK
;
1846 result
= curl_easy_setopt(conn
->connection
,
1850 if (result
!= CURLE_OK
)
1851 raiseError(conn
, result
);
1856 static void handle_POSTFIELDS(Connection
*conn
, value option
)
1859 CURLcode result
= CURLE_OK
;
1861 Store_field(conn
->ocamlValues
, OcamlPostFields
, option
);
1863 if (conn
->postFields
!= NULL
)
1864 free(conn
->postFields
);
1866 conn
->postFields
= malloc(string_length(option
)+1);
1867 memcpy(conn
->postFields
, String_val(option
), string_length(option
)+1);
1869 result
= curl_easy_setopt(conn
->connection
,
1873 if (result
!= CURLE_OK
)
1874 raiseError(conn
, result
);
1879 static void handle_POSTFIELDSIZE(Connection
*conn
, value option
)
1882 CURLcode result
= CURLE_OK
;
1884 result
= curl_easy_setopt(conn
->connection
,
1885 CURLOPT_POSTFIELDSIZE
,
1888 if (result
!= CURLE_OK
)
1889 raiseError(conn
, result
);
1894 static void handle_REFERER(Connection
*conn
, value option
)
1897 CURLcode result
= CURLE_OK
;
1899 Store_field(conn
->ocamlValues
, OcamlReferer
, option
);
1901 if (conn
->referer
!= NULL
)
1902 free(conn
->referer
);
1904 conn
->referer
= strdup(String_val(option
));
1906 result
= curl_easy_setopt(conn
->connection
,
1910 if (result
!= CURLE_OK
)
1911 raiseError(conn
, result
);
1916 static void handle_USERAGENT(Connection
*conn
, value option
)
1919 CURLcode result
= CURLE_OK
;
1921 Store_field(conn
->ocamlValues
, OcamlUserAgent
, option
);
1923 if (conn
->userAgent
!= NULL
)
1924 free(conn
->userAgent
);
1926 conn
->userAgent
= strdup(String_val(option
));
1928 result
= curl_easy_setopt(conn
->connection
,
1932 if (result
!= CURLE_OK
)
1933 raiseError(conn
, result
);
1938 static void handle_FTPPORT(Connection
*conn
, value option
)
1941 CURLcode result
= CURLE_OK
;
1943 Store_field(conn
->ocamlValues
, OcamlFTPPort
, option
);
1945 if (conn
->ftpPort
!= NULL
)
1946 free(conn
->ftpPort
);
1948 conn
->ftpPort
= strdup(String_val(option
));
1950 result
= curl_easy_setopt(conn
->connection
,
1954 if (result
!= CURLE_OK
)
1955 raiseError(conn
, result
);
1960 static void handle_LOW_SPEED_LIMIT(Connection
*conn
, value option
)
1963 CURLcode result
= CURLE_OK
;
1965 result
= curl_easy_setopt(conn
->connection
,
1966 CURLOPT_LOW_SPEED_LIMIT
,
1969 if (result
!= CURLE_OK
)
1970 raiseError(conn
, result
);
1975 static void handle_LOW_SPEED_TIME(Connection
*conn
, value option
)
1978 CURLcode result
= CURLE_OK
;
1980 result
= curl_easy_setopt(conn
->connection
,
1981 CURLOPT_LOW_SPEED_TIME
,
1984 if (result
!= CURLE_OK
)
1985 raiseError(conn
, result
);
1990 static void handle_RESUME_FROM(Connection
*conn
, value option
)
1993 CURLcode result
= CURLE_OK
;
1995 result
= curl_easy_setopt(conn
->connection
,
1996 CURLOPT_RESUME_FROM
,
1999 if (result
!= CURLE_OK
)
2000 raiseError(conn
, result
);
2005 static void handle_COOKIE(Connection
*conn
, value option
)
2008 CURLcode result
= CURLE_OK
;
2010 Store_field(conn
->ocamlValues
, OcamlCookie
, option
);
2012 if (conn
->cookie
!= NULL
)
2015 conn
->cookie
= strdup(String_val(option
));
2017 result
= curl_easy_setopt(conn
->connection
,
2021 if (result
!= CURLE_OK
)
2022 raiseError(conn
, result
);
2027 static void handle_HTTPHEADER(Connection
*conn
, value option
)
2030 CAMLlocal1(listIter
);
2031 CURLcode result
= CURLE_OK
;
2033 Store_field(conn
->ocamlValues
, OcamlHTTPHeader
, option
);
2035 free_curl_slist(conn
->httpHeader
);
2036 conn
->httpHeader
= NULL
;
2040 while (!Is_long(listIter
))
2042 conn
->httpHeader
= curl_slist_append(conn
->httpHeader
, String_val(Field(listIter
, 0)));
2044 listIter
= Field(listIter
, 1);
2047 result
= curl_easy_setopt(conn
->connection
,
2051 if (result
!= CURLE_OK
)
2052 raiseError(conn
, result
);
2057 static void handle_HTTPPOST(Connection
*conn
, value option
)
2060 CAMLlocal3(listIter
, formItem
, contentType
);
2061 CURLcode result
= CURLE_OK
;
2062 char *str1
, *str2
, *str3
, *str4
;
2066 Store_field(conn
->ocamlValues
, OcamlHTTPPost
, option
);
2068 if (conn
->httpPostFirst
!= NULL
)
2069 curl_formfree(conn
->httpPostFirst
);
2071 conn
->httpPostFirst
= NULL
;
2072 conn
->httpPostLast
= NULL
;
2074 free_curl_slist(conn
->httpPostStrings
);
2075 conn
->httpPostStrings
= NULL
;
2077 while (!Is_long(listIter
))
2079 formItem
= Field(listIter
, 0);
2081 switch (Tag_val(formItem
))
2083 case 0: /* CURLFORM_CONTENT */
2084 if (Wosize_val(formItem
) < 3)
2086 failwith("Incorrect CURLFORM_CONTENT parameters");
2089 if (Is_long(Field(formItem
, 2)) &&
2090 Long_val(Field(formItem
, 2)) == 0)
2092 str1
= (char *)malloc(string_length(Field(formItem
, 0))+1);
2094 String_val(Field(formItem
, 0)),
2095 string_length(Field(formItem
, 0)));
2096 str1
[string_length(Field(formItem
, 0))] = 0;
2097 conn
->httpPostStrings
=
2098 curl_slist_append(conn
->httpPostStrings
, str1
);
2100 str2
= (char *)malloc(string_length(Field(formItem
, 1))+1);
2102 String_val(Field(formItem
, 1)),
2103 string_length(Field(formItem
, 1)));
2104 str2
[string_length(Field(formItem
, 1))] = 0;
2105 conn
->httpPostStrings
=
2106 curl_slist_append(conn
->httpPostStrings
, str2
);
2108 curl_formadd(&conn
->httpPostFirst
,
2109 &conn
->httpPostLast
,
2112 CURLFORM_NAMELENGTH
,
2113 string_length(Field(formItem
, 0)),
2114 CURLFORM_PTRCONTENTS
,
2116 CURLFORM_CONTENTSLENGTH
,
2117 string_length(Field(formItem
, 1)),
2120 else if (Is_block(Field(formItem
, 2)))
2122 str1
= (char *)malloc(string_length(Field(formItem
, 0))+1);
2124 String_val(Field(formItem
, 0)),
2125 string_length(Field(formItem
, 0)));
2126 str1
[string_length(Field(formItem
, 0))] = 0;
2127 conn
->httpPostStrings
=
2128 curl_slist_append(conn
->httpPostStrings
, str1
);
2130 str2
= (char *)malloc(string_length(Field(formItem
, 1))+1);
2132 String_val(Field(formItem
, 1)),
2133 string_length(Field(formItem
, 1)));
2134 str2
[string_length(Field(formItem
, 1))] = 0;
2135 conn
->httpPostStrings
=
2136 curl_slist_append(conn
->httpPostStrings
, str2
);
2138 contentType
= Field(formItem
, 2);
2140 str3
= (char *)malloc(string_length(Field(contentType
, 0))+1);
2142 String_val(Field(contentType
, 0)),
2143 string_length(Field(contentType
, 0)));
2144 str3
[string_length(Field(contentType
, 0))] = 0;
2145 conn
->httpPostStrings
=
2146 curl_slist_append(conn
->httpPostStrings
, str3
);
2148 curl_formadd(&conn
->httpPostFirst
,
2149 &conn
->httpPostLast
,
2152 CURLFORM_NAMELENGTH
,
2153 string_length(Field(formItem
, 0)),
2154 CURLFORM_PTRCONTENTS
,
2156 CURLFORM_CONTENTSLENGTH
,
2157 string_length(Field(formItem
, 1)),
2158 CURLFORM_CONTENTTYPE
,
2164 failwith("Incorrect CURLFORM_CONTENT parameters");
2168 case 1: /* CURLFORM_FILECONTENT */
2169 if (Wosize_val(formItem
) < 3)
2171 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2174 if (Is_long(Field(formItem
, 2)) &&
2175 Long_val(Field(formItem
, 2)) == 0)
2177 str1
= (char *)malloc(string_length(Field(formItem
, 0))+1);
2179 String_val(Field(formItem
, 0)),
2180 string_length(Field(formItem
, 0)));
2181 str1
[string_length(Field(formItem
, 0))] = 0;
2182 conn
->httpPostStrings
=
2183 curl_slist_append(conn
->httpPostStrings
, str1
);
2185 str2
= (char *)malloc(string_length(Field(formItem
, 1))+1);
2187 String_val(Field(formItem
, 1)),
2188 string_length(Field(formItem
, 1)));
2189 str2
[string_length(Field(formItem
, 1))] = 0;
2190 conn
->httpPostStrings
=
2191 curl_slist_append(conn
->httpPostStrings
, str2
);
2193 curl_formadd(&conn
->httpPostFirst
,
2194 &conn
->httpPostLast
,
2197 CURLFORM_NAMELENGTH
,
2198 string_length(Field(formItem
, 0)),
2199 CURLFORM_FILECONTENT
,
2203 else if (Is_block(Field(formItem
, 2)))
2205 str1
= (char *)malloc(string_length(Field(formItem
, 0))+1);
2207 String_val(Field(formItem
, 0)),
2208 string_length(Field(formItem
, 0)));
2209 str1
[string_length(Field(formItem
, 0))] = 0;
2210 conn
->httpPostStrings
=
2211 curl_slist_append(conn
->httpPostStrings
, str1
);
2213 str2
= (char *)malloc(string_length(Field(formItem
, 1))+1);
2215 String_val(Field(formItem
, 1)),
2216 string_length(Field(formItem
, 1)));
2217 str2
[string_length(Field(formItem
, 1))] = 0;
2218 conn
->httpPostStrings
=
2219 curl_slist_append(conn
->httpPostStrings
, str2
);
2221 contentType
= Field(formItem
, 2);
2223 str3
= (char *)malloc(string_length(Field(contentType
, 0))+1);
2225 String_val(Field(contentType
, 0)),
2226 string_length(Field(contentType
, 0)));
2227 str3
[string_length(Field(contentType
, 0))] = 0;
2228 conn
->httpPostStrings
=
2229 curl_slist_append(conn
->httpPostStrings
, str3
);
2231 curl_formadd(&conn
->httpPostFirst
,
2232 &conn
->httpPostLast
,
2235 CURLFORM_NAMELENGTH
,
2236 string_length(Field(formItem
, 0)),
2237 CURLFORM_FILECONTENT
,
2239 CURLFORM_CONTENTTYPE
,
2245 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2249 case 2: /* CURLFORM_FILE */
2250 if (Wosize_val(formItem
) < 3)
2252 failwith("Incorrect CURLFORM_FILE parameters");
2255 if (Is_long(Field(formItem
, 2)) &&
2256 Long_val(Field(formItem
, 2)) == 0)
2258 str1
= (char *)malloc(string_length(Field(formItem
, 0))+1);
2260 String_val(Field(formItem
, 0)),
2261 string_length(Field(formItem
, 0)));
2262 str1
[string_length(Field(formItem
, 0))] = 0;
2263 conn
->httpPostStrings
=
2264 curl_slist_append(conn
->httpPostStrings
, str1
);
2266 str2
= (char *)malloc(string_length(Field(formItem
, 1))+1);
2268 String_val(Field(formItem
, 1)),
2269 string_length(Field(formItem
, 1)));
2270 str2
[string_length(Field(formItem
, 1))] = 0;
2271 conn
->httpPostStrings
=
2272 curl_slist_append(conn
->httpPostStrings
, str2
);
2274 curl_formadd(&conn
->httpPostFirst
,
2275 &conn
->httpPostLast
,
2278 CURLFORM_NAMELENGTH
,
2279 string_length(Field(formItem
, 0)),
2284 else if (Is_block(Field(formItem
, 2)))
2286 str1
= (char *)malloc(string_length(Field(formItem
, 0))+1);
2288 String_val(Field(formItem
, 0)),
2289 string_length(Field(formItem
, 0)));
2290 str1
[string_length(Field(formItem
, 0))] = 0;
2291 conn
->httpPostStrings
=
2292 curl_slist_append(conn
->httpPostStrings
, str1
);
2294 str2
= (char *)malloc(string_length(Field(formItem
, 1))+1);
2296 String_val(Field(formItem
, 1)),
2297 string_length(Field(formItem
, 1)));
2298 str2
[string_length(Field(formItem
, 1))] = 0;
2299 conn
->httpPostStrings
=
2300 curl_slist_append(conn
->httpPostStrings
, str2
);
2302 contentType
= Field(formItem
, 2);
2304 str3
= (char *)malloc(string_length(Field(contentType
, 0))+1);
2306 String_val(Field(contentType
, 0)),
2307 string_length(Field(contentType
, 0)));
2308 str3
[string_length(Field(contentType
, 0))] = 0;
2309 conn
->httpPostStrings
=
2310 curl_slist_append(conn
->httpPostStrings
, str3
);
2312 curl_formadd(&conn
->httpPostFirst
,
2313 &conn
->httpPostLast
,
2316 CURLFORM_NAMELENGTH
,
2317 string_length(Field(formItem
, 0)),
2320 CURLFORM_CONTENTTYPE
,
2326 failwith("Incorrect CURLFORM_FILE parameters");
2330 case 3: /* CURLFORM_BUFFER */
2331 if (Wosize_val(formItem
) < 4)
2333 failwith("Incorrect CURLFORM_BUFFER parameters");
2336 if (Is_long(Field(formItem
, 3)) &&
2337 Long_val(Field(formItem
, 3)) == 0)
2339 str1
= (char *)malloc(string_length(Field(formItem
, 0))+1);
2341 String_val(Field(formItem
, 0)),
2342 string_length(Field(formItem
, 0)));
2343 str1
[string_length(Field(formItem
, 0))] = 0;
2344 conn
->httpPostStrings
=
2345 curl_slist_append(conn
->httpPostStrings
, str1
);
2347 str2
= (char *)malloc(string_length(Field(formItem
, 1))+1);
2349 String_val(Field(formItem
, 1)),
2350 string_length(Field(formItem
, 1)));
2351 str2
[string_length(Field(formItem
, 1))] = 0;
2352 conn
->httpPostStrings
=
2353 curl_slist_append(conn
->httpPostStrings
, str2
);
2355 str3
= (char *)malloc(string_length(Field(formItem
, 2))+1);
2357 String_val(Field(formItem
, 2)),
2358 string_length(Field(formItem
, 2)));
2359 str3
[string_length(Field(formItem
, 2))] = 0;
2360 conn
->httpPostStrings
=
2361 curl_slist_append(conn
->httpPostStrings
, str3
);
2363 curl_formadd(&conn
->httpPostFirst
,
2364 &conn
->httpPostLast
,
2367 CURLFORM_NAMELENGTH
,
2368 string_length(Field(formItem
, 0)),
2373 CURLFORM_BUFFERLENGTH
,
2374 string_length(Field(formItem
, 2)),
2377 else if (Is_block(Field(formItem
, 3)))
2379 str1
= (char *)malloc(string_length(Field(formItem
, 0))+1);
2381 String_val(Field(formItem
, 0)),
2382 string_length(Field(formItem
, 0)));
2383 str1
[string_length(Field(formItem
, 0))] = 0;
2384 conn
->httpPostStrings
=
2385 curl_slist_append(conn
->httpPostStrings
, str1
);
2387 str2
= (char *)malloc(string_length(Field(formItem
, 1))+1);
2389 String_val(Field(formItem
, 1)),
2390 string_length(Field(formItem
, 1)));
2391 str2
[string_length(Field(formItem
, 1))] = 0;
2392 conn
->httpPostStrings
=
2393 curl_slist_append(conn
->httpPostStrings
, str2
);
2395 str3
= (char *)malloc(string_length(Field(formItem
, 2))+1);
2397 String_val(Field(formItem
, 2)),
2398 string_length(Field(formItem
, 2)));
2399 str3
[string_length(Field(formItem
, 2))] = 0;
2400 conn
->httpPostStrings
=
2401 curl_slist_append(conn
->httpPostStrings
, str3
);
2403 contentType
= Field(formItem
, 3);
2405 str4
= (char *)malloc(string_length(Field(contentType
, 0))+1);
2407 String_val(Field(contentType
, 0)),
2408 string_length(Field(contentType
, 0)));
2409 str4
[string_length(Field(contentType
, 0))] = 0;
2410 conn
->httpPostStrings
=
2411 curl_slist_append(conn
->httpPostStrings
, str4
);
2413 curl_formadd(&conn
->httpPostFirst
,
2414 &conn
->httpPostLast
,
2417 CURLFORM_NAMELENGTH
,
2418 string_length(Field(formItem
, 0)),
2423 CURLFORM_BUFFERLENGTH
,
2424 string_length(Field(formItem
, 2)),
2425 CURLFORM_CONTENTTYPE
,
2431 failwith("Incorrect CURLFORM_BUFFER parameters");
2436 listIter
= Field(listIter
, 1);
2439 result
= curl_easy_setopt(conn
->connection
,
2441 conn
->httpPostFirst
);
2443 if (result
!= CURLE_OK
)
2444 raiseError(conn
, result
);
2449 static void handle_SSLCERT(Connection
*conn
, value option
)
2452 CURLcode result
= CURLE_OK
;
2454 Store_field(conn
->ocamlValues
, OcamlSSLCert
, option
);
2456 if (conn
->sslCert
!= NULL
)
2457 free(conn
->sslCert
);
2459 conn
->sslCert
= strdup(String_val(option
));
2461 result
= curl_easy_setopt(conn
->connection
,
2465 if (result
!= CURLE_OK
)
2466 raiseError(conn
, result
);
2471 static void handle_SSLCERTTYPE(Connection
*conn
, value option
)
2474 CURLcode result
= CURLE_OK
;
2476 Store_field(conn
->ocamlValues
, OcamlSSLCertType
, option
);
2478 if (conn
->sslCertType
!= NULL
)
2479 free(conn
->sslCertType
);
2481 conn
->sslCertType
= strdup(String_val(option
));
2483 result
= curl_easy_setopt(conn
->connection
,
2484 CURLOPT_SSLCERTTYPE
,
2487 if (result
!= CURLE_OK
)
2488 raiseError(conn
, result
);
2493 static void handle_SSLCERTPASSWD(Connection
*conn
, value option
)
2496 CURLcode result
= CURLE_OK
;
2498 Store_field(conn
->ocamlValues
, OcamlSSLCertPasswd
, option
);
2500 if (conn
->sslCertPasswd
!= NULL
)
2501 free(conn
->sslCertPasswd
);
2503 conn
->sslCertPasswd
= strdup(String_val(option
));
2505 result
= curl_easy_setopt(conn
->connection
,
2506 CURLOPT_SSLCERTPASSWD
,
2507 conn
->sslCertPasswd
);
2509 if (result
!= CURLE_OK
)
2510 raiseError(conn
, result
);
2515 static void handle_SSLKEY(Connection
*conn
, value option
)
2518 CURLcode result
= CURLE_OK
;
2520 Store_field(conn
->ocamlValues
, OcamlSSLKey
, option
);
2522 if (conn
->sslKey
!= NULL
)
2525 conn
->sslKey
= strdup(String_val(option
));
2527 result
= curl_easy_setopt(conn
->connection
,
2531 if (result
!= CURLE_OK
)
2532 raiseError(conn
, result
);
2537 static void handle_SSLKEYTYPE(Connection
*conn
, value option
)
2540 CURLcode result
= CURLE_OK
;
2542 Store_field(conn
->ocamlValues
, OcamlSSLKeyType
, option
);
2544 if (conn
->sslKeyType
!= NULL
)
2545 free(conn
->sslKeyType
);
2547 conn
->sslKeyType
= strdup(String_val(option
));
2549 result
= curl_easy_setopt(conn
->connection
,
2553 if (result
!= CURLE_OK
)
2554 raiseError(conn
, result
);
2559 static void handle_SSLKEYPASSWD(Connection
*conn
, value option
)
2562 CURLcode result
= CURLE_OK
;
2564 Store_field(conn
->ocamlValues
, OcamlSSLKeyPasswd
, option
);
2566 if (conn
->sslKeyPasswd
!= NULL
)
2567 free(conn
->sslKeyPasswd
);
2569 conn
->sslKeyPasswd
= strdup(String_val(option
));
2571 result
= curl_easy_setopt(conn
->connection
,
2572 CURLOPT_SSLKEYPASSWD
,
2573 conn
->sslKeyPasswd
);
2575 if (result
!= CURLE_OK
)
2576 raiseError(conn
, result
);
2581 static void handle_SSLENGINE(Connection
*conn
, value option
)
2584 CURLcode result
= CURLE_OK
;
2586 Store_field(conn
->ocamlValues
, OcamlSSLEngine
, option
);
2588 if (conn
->sslEngine
!= NULL
)
2589 free(conn
->sslEngine
);
2591 conn
->sslEngine
= strdup(String_val(option
));
2593 result
= curl_easy_setopt(conn
->connection
,
2597 if (result
!= CURLE_OK
)
2598 raiseError(conn
, result
);
2603 static void handle_SSLENGINE_DEFAULT(Connection
*conn
, value option
)
2606 CURLcode result
= CURLE_OK
;
2608 result
= curl_easy_setopt(conn
->connection
,
2609 CURLOPT_SSLENGINE_DEFAULT
,
2612 if (result
!= CURLE_OK
)
2613 raiseError(conn
, result
);
2618 static void handle_CRLF(Connection
*conn
, value option
)
2621 CURLcode result
= CURLE_OK
;
2623 result
= curl_easy_setopt(conn
->connection
,
2627 if (result
!= CURLE_OK
)
2628 raiseError(conn
, result
);
2633 static void handle_QUOTE(Connection
*conn
, value option
)
2636 CAMLlocal1(listIter
);
2637 CURLcode result
= CURLE_OK
;
2639 Store_field(conn
->ocamlValues
, OcamlQuote
, option
);
2641 free_curl_slist(conn
->quote
);
2646 while (!Is_long(listIter
))
2648 conn
->quote
= curl_slist_append(conn
->quote
, String_val(Field(listIter
, 0)));
2650 listIter
= Field(listIter
, 1);
2653 result
= curl_easy_setopt(conn
->connection
,
2657 if (result
!= CURLE_OK
)
2658 raiseError(conn
, result
);
2663 static void handle_POSTQUOTE(Connection
*conn
, value option
)
2666 CAMLlocal1(listIter
);
2667 CURLcode result
= CURLE_OK
;
2669 Store_field(conn
->ocamlValues
, OcamlPostQuote
, option
);
2671 free_curl_slist(conn
->postQuote
);
2672 conn
->postQuote
= NULL
;
2676 while (!Is_long(listIter
))
2678 conn
->postQuote
= curl_slist_append(conn
->postQuote
, String_val(Field(listIter
, 0)));
2680 listIter
= Field(listIter
, 1);
2683 result
= curl_easy_setopt(conn
->connection
,
2687 if (result
!= CURLE_OK
)
2688 raiseError(conn
, result
);
2693 static void handle_HEADERFUNCTION(Connection
*conn
, value option
)
2696 CURLcode result
= CURLE_OK
;
2698 if (Tag_val(option
) == Closure_tag
)
2699 Store_field(conn
->ocamlValues
, OcamlHeaderCallback
, option
);
2701 failwith("Not a proper closure");
2703 result
= curl_easy_setopt(conn
->connection
,
2704 CURLOPT_HEADERFUNCTION
,
2707 if (result
!= CURLE_OK
)
2708 raiseError(conn
, result
);
2710 result
= curl_easy_setopt(conn
->connection
,
2711 CURLOPT_WRITEHEADER
,
2714 if (result
!= CURLE_OK
)
2715 raiseError(conn
, result
);
2720 static void handle_COOKIEFILE(Connection
*conn
, value option
)
2723 CURLcode result
= CURLE_OK
;
2725 Store_field(conn
->ocamlValues
, OcamlCookieFile
, option
);
2727 if (conn
->cookieFile
!= NULL
)
2728 free(conn
->cookieFile
);
2730 conn
->cookieFile
= strdup(String_val(option
));
2732 result
= curl_easy_setopt(conn
->connection
,
2736 if (result
!= CURLE_OK
)
2737 raiseError(conn
, result
);
2742 static void handle_SSLVERSION(Connection
*conn
, value option
)
2745 CURLcode result
= CURLE_OK
;
2747 result
= curl_easy_setopt(conn
->connection
,
2751 if (result
!= CURLE_OK
)
2752 raiseError(conn
, result
);
2757 static void handle_TIMECONDITION(Connection
*conn
, value option
)
2760 CURLcode result
= CURLE_OK
;
2761 int timecond
= CURL_TIMECOND_NONE
;
2763 switch (Long_val(option
))
2765 case 0: timecond
= CURL_TIMECOND_NONE
; break;
2766 case 1: timecond
= CURL_TIMECOND_IFMODSINCE
; break;
2767 case 2: timecond
= CURL_TIMECOND_IFUNMODSINCE
; break;
2768 case 3: timecond
= CURL_TIMECOND_LASTMOD
; break;
2770 failwith("Invalid TIMECOND Option");
2774 result
= curl_easy_setopt(conn
->connection
, CURLOPT_TIMECONDITION
, timecond
);
2776 if (result
!= CURLE_OK
)
2777 raiseError(conn
, result
);
2782 static void handle_TIMEVALUE(Connection
*conn
, value option
)
2785 CURLcode result
= CURLE_OK
;
2787 result
= curl_easy_setopt(conn
->connection
,
2791 if (result
!= CURLE_OK
)
2792 raiseError(conn
, result
);
2797 static void handle_CUSTOMREQUEST(Connection
*conn
, value option
)
2800 CURLcode result
= CURLE_OK
;
2802 Store_field(conn
->ocamlValues
, OcamlCustomRequest
, option
);
2804 if (conn
->customRequest
!= NULL
)
2805 free(conn
->customRequest
);
2807 conn
->customRequest
= strdup(String_val(option
));
2809 result
= curl_easy_setopt(conn
->connection
,
2810 CURLOPT_CUSTOMREQUEST
,
2811 conn
->customRequest
);
2813 if (result
!= CURLE_OK
)
2814 raiseError(conn
, result
);
2819 static void handle_INTERFACE(Connection
*conn
, value option
)
2822 CURLcode result
= CURLE_OK
;
2824 Store_field(conn
->ocamlValues
, OcamlInterface
, option
);
2826 if (conn
->interface_
!= NULL
)
2827 free(conn
->interface_
);
2829 conn
->interface_
= strdup(String_val(option
));
2831 result
= curl_easy_setopt(conn
->connection
,
2835 if (result
!= CURLE_OK
)
2836 raiseError(conn
, result
);
2841 static void handle_KRB4LEVEL(Connection
*conn
, value option
)
2844 CURLcode result
= CURLE_OK
;
2846 switch (Long_val(option
))
2848 case 0: /* KRB4_NONE */
2849 result
= curl_easy_setopt(conn
->connection
,
2854 case 1: /* KRB4_CLEAR */
2855 result
= curl_easy_setopt(conn
->connection
,
2860 case 2: /* KRB4_SAFE */
2861 result
= curl_easy_setopt(conn
->connection
,
2866 case 3: /* KRB4_CONFIDENTIAL */
2867 result
= curl_easy_setopt(conn
->connection
,
2872 case 4: /* KRB4_PRIVATE */
2873 result
= curl_easy_setopt(conn
->connection
,
2879 failwith("Invalid KRB4 Option");
2883 if (result
!= CURLE_OK
)
2884 raiseError(conn
, result
);
2889 static void handle_PROGRESSFUNCTION(Connection
*conn
, value option
)
2892 CURLcode result
= CURLE_OK
;
2894 if (Tag_val(option
) == Closure_tag
)
2895 Store_field(conn
->ocamlValues
, OcamlProgressCallback
, option
);
2897 failwith("Not a proper closure");
2899 result
= curl_easy_setopt(conn
->connection
,
2900 CURLOPT_PROGRESSFUNCTION
,
2902 if (result
!= CURLE_OK
)
2903 raiseError(conn
, result
);
2905 result
= curl_easy_setopt(conn
->connection
,
2906 CURLOPT_PROGRESSDATA
,
2909 if (result
!= CURLE_OK
)
2910 raiseError(conn
, result
);
2915 static void handle_SSL_VERIFYPEER(Connection
*conn
, value option
)
2918 CURLcode result
= CURLE_OK
;
2920 result
= curl_easy_setopt(conn
->connection
,
2921 CURLOPT_SSL_VERIFYPEER
,
2924 if (result
!= CURLE_OK
)
2925 raiseError(conn
, result
);
2930 static void handle_CAINFO(Connection
*conn
, value option
)
2933 CURLcode result
= CURLE_OK
;
2935 Store_field(conn
->ocamlValues
, OcamlCAInfo
, option
);
2937 if (conn
->caInfo
!= NULL
)
2940 conn
->caInfo
= strdup(String_val(option
));
2942 result
= curl_easy_setopt(conn
->connection
,
2946 if (result
!= CURLE_OK
)
2947 raiseError(conn
, result
);
2952 static void handle_CAPATH(Connection
*conn
, value option
)
2955 CURLcode result
= CURLE_OK
;
2957 Store_field(conn
->ocamlValues
, OcamlCAPath
, option
);
2959 if (conn
->caPath
!= NULL
)
2962 conn
->caPath
= strdup(String_val(option
));
2964 result
= curl_easy_setopt(conn
->connection
,
2968 if (result
!= CURLE_OK
)
2969 raiseError(conn
, result
);
2974 static void handle_FILETIME(Connection
*conn
, value option
)
2977 CURLcode result
= CURLE_OK
;
2979 result
= curl_easy_setopt(conn
->connection
,
2983 if (result
!= CURLE_OK
)
2984 raiseError(conn
, result
);
2989 static void handle_MAXREDIRS(Connection
*conn
, value option
)
2992 CURLcode result
= CURLE_OK
;
2994 result
= curl_easy_setopt(conn
->connection
,
2998 if (result
!= CURLE_OK
)
2999 raiseError(conn
, result
);
3004 static void handle_MAXCONNECTS(Connection
*conn
, value option
)
3007 CURLcode result
= CURLE_OK
;
3009 result
= curl_easy_setopt(conn
->connection
,
3010 CURLOPT_MAXCONNECTS
,
3013 if (result
!= CURLE_OK
)
3014 raiseError(conn
, result
);
3019 static void handle_CLOSEPOLICY(Connection
*conn
, value option
)
3022 CURLcode result
= CURLE_OK
;
3024 switch (Long_val(option
))
3026 case 0: /* CLOSEPOLICY_OLDEST */
3027 result
= curl_easy_setopt(conn
->connection
,
3028 CURLOPT_CLOSEPOLICY
,
3029 CURLCLOSEPOLICY_OLDEST
);
3032 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3033 result
= curl_easy_setopt(conn
->connection
,
3034 CURLOPT_CLOSEPOLICY
,
3035 CURLCLOSEPOLICY_LEAST_RECENTLY_USED
);
3039 failwith("Invalid CLOSEPOLICY Option");
3043 if (result
!= CURLE_OK
)
3044 raiseError(conn
, result
);
3049 static void handle_FRESH_CONNECT(Connection
*conn
, value option
)
3052 CURLcode result
= CURLE_OK
;
3054 result
= curl_easy_setopt(conn
->connection
,
3055 CURLOPT_FRESH_CONNECT
,
3058 if (result
!= CURLE_OK
)
3059 raiseError(conn
, result
);
3064 static void handle_FORBID_REUSE(Connection
*conn
, value option
)
3067 CURLcode result
= CURLE_OK
;
3069 result
= curl_easy_setopt(conn
->connection
,
3070 CURLOPT_FORBID_REUSE
,
3073 if (result
!= CURLE_OK
)
3074 raiseError(conn
, result
);
3079 static void handle_RANDOM_FILE(Connection
*conn
, value option
)
3082 CURLcode result
= CURLE_OK
;
3084 Store_field(conn
->ocamlValues
, OcamlRandomFile
, option
);
3086 if (conn
->randomFile
!= NULL
)
3087 free(conn
->randomFile
);
3089 conn
->randomFile
= strdup(String_val(option
));
3091 result
= curl_easy_setopt(conn
->connection
,
3092 CURLOPT_RANDOM_FILE
,
3095 if (result
!= CURLE_OK
)
3096 raiseError(conn
, result
);
3101 static void handle_EGDSOCKET(Connection
*conn
, value option
)
3104 CURLcode result
= CURLE_OK
;
3106 Store_field(conn
->ocamlValues
, OcamlEGDSocket
, option
);
3108 if (conn
->egdSocket
!= NULL
)
3109 free(conn
->egdSocket
);
3111 conn
->egdSocket
= strdup(String_val(option
));
3113 result
= curl_easy_setopt(conn
->connection
,
3117 if (result
!= CURLE_OK
)
3118 raiseError(conn
, result
);
3123 static void handle_CONNECTTIMEOUT(Connection
*conn
, value option
)
3126 CURLcode result
= CURLE_OK
;
3128 result
= curl_easy_setopt(conn
->connection
,
3129 CURLOPT_CONNECTTIMEOUT
,
3132 if (result
!= CURLE_OK
)
3133 raiseError(conn
, result
);
3138 static void handle_HTTPGET(Connection
*conn
, value option
)
3141 CURLcode result
= CURLE_OK
;
3143 result
= curl_easy_setopt(conn
->connection
,
3147 if (result
!= CURLE_OK
)
3148 raiseError(conn
, result
);
3153 static void handle_SSL_VERIFYHOST(Connection
*conn
, value option
)
3156 CURLcode result
= CURLE_OK
;
3158 switch (Long_val(option
))
3160 case 0: /* SSLVERIFYHOST_NONE */
3161 case 1: /* SSLVERIFYHOST_EXISTENCE */
3162 case 2: /* SSLVERIFYHOST_HOSTNAME */
3163 result
= curl_easy_setopt(conn
->connection
,
3164 CURLOPT_SSL_VERIFYHOST
,
3165 /* map EXISTENCE to HOSTNAME */
3166 Long_val(option
) == 0 ? 0 : 2);
3170 failwith("Invalid SSLVERIFYHOST Option");
3174 if (result
!= CURLE_OK
)
3175 raiseError(conn
, result
);
3180 static void handle_COOKIEJAR(Connection
*conn
, value option
)
3183 CURLcode result
= CURLE_OK
;
3185 Store_field(conn
->ocamlValues
, OcamlCookieJar
, option
);
3187 if (conn
->cookieJar
!= NULL
)
3188 free(conn
->cookieJar
);
3190 conn
->cookieJar
= strdup(String_val(option
));
3192 result
= curl_easy_setopt(conn
->connection
,
3196 if (result
!= CURLE_OK
)
3197 raiseError(conn
, result
);
3202 static void handle_SSL_CIPHER_LIST(Connection
*conn
, value option
)
3205 CURLcode result
= CURLE_OK
;
3207 Store_field(conn
->ocamlValues
, OcamlSSLCipherList
, option
);
3209 if (conn
->sslCipherList
!= NULL
)
3210 free(conn
->sslCipherList
);
3212 conn
->sslCipherList
= strdup(String_val(option
));
3214 result
= curl_easy_setopt(conn
->connection
,
3215 CURLOPT_SSL_CIPHER_LIST
,
3216 conn
->sslCipherList
);
3218 if (result
!= CURLE_OK
)
3219 raiseError(conn
, result
);
3224 static void handle_HTTP_VERSION(Connection
*conn
, value option
)
3227 CURLcode result
= CURLE_OK
;
3229 switch (Long_val(option
))
3231 case 0: /* HTTP_VERSION_NONE */
3232 result
= curl_easy_setopt(conn
->connection
,
3233 CURLOPT_HTTP_VERSION
,
3234 CURL_HTTP_VERSION_NONE
);
3237 case 1: /* HTTP_VERSION_1_0 */
3238 result
= curl_easy_setopt(conn
->connection
,
3239 CURLOPT_HTTP_VERSION
,
3240 CURL_HTTP_VERSION_1_0
);
3243 case 2: /* HTTP_VERSION_1_1 */
3244 result
= curl_easy_setopt(conn
->connection
,
3245 CURLOPT_HTTP_VERSION
,
3246 CURL_HTTP_VERSION_1_1
);
3250 failwith("Invalid HTTP_VERSION Option");
3254 if (result
!= CURLE_OK
)
3255 raiseError(conn
, result
);
3260 static void handle_FTP_USE_EPSV(Connection
*conn
, value option
)
3263 CURLcode result
= CURLE_OK
;
3265 result
= curl_easy_setopt(conn
->connection
,
3266 CURLOPT_FTP_USE_EPSV
,
3269 if (result
!= CURLE_OK
)
3270 raiseError(conn
, result
);
3275 static void handle_DNS_CACHE_TIMEOUT(Connection
*conn
, value option
)
3278 CURLcode result
= CURLE_OK
;
3280 result
= curl_easy_setopt(conn
->connection
,
3281 CURLOPT_DNS_CACHE_TIMEOUT
,
3284 if (result
!= CURLE_OK
)
3285 raiseError(conn
, result
);
3290 static void handle_DNS_USE_GLOBAL_CACHE(Connection
*conn
, value option
)
3293 CURLcode result
= CURLE_OK
;
3295 result
= curl_easy_setopt(conn
->connection
,
3296 CURLOPT_DNS_USE_GLOBAL_CACHE
,
3299 if (result
!= CURLE_OK
)
3300 raiseError(conn
, result
);
3305 static void handle_DEBUGFUNCTION(Connection
*conn
, value option
)
3308 CURLcode result
= CURLE_OK
;
3310 if (Tag_val(option
) == Closure_tag
)
3311 Store_field(conn
->ocamlValues
, OcamlDebugCallback
, option
);
3313 failwith("Not a proper closure");
3315 result
= curl_easy_setopt(conn
->connection
,
3316 CURLOPT_DEBUGFUNCTION
,
3318 if (result
!= CURLE_OK
)
3319 raiseError(conn
, result
);
3321 result
= curl_easy_setopt(conn
->connection
,
3325 if (result
!= CURLE_OK
)
3326 raiseError(conn
, result
);
3331 #if HAVE_DECL_CURLOPT_PRIVATE
3332 static void handle_PRIVATE(Connection
*conn
, value option
)
3335 CURLcode result
= CURLE_OK
;
3337 Store_field(conn
->ocamlValues
, OcamlPrivate
, option
);
3339 if (conn
->private != NULL
)
3340 free(conn
->private);
3342 conn
->private = strdup(String_val(option
));
3344 result
= curl_easy_setopt(conn
->connection
,
3348 if (result
!= CURLE_OK
)
3349 raiseError(conn
, result
);
3355 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
3356 static void handle_HTTP200ALIASES(Connection
*conn
, value option
)
3359 CAMLlocal1(listIter
);
3360 CURLcode result
= CURLE_OK
;
3362 Store_field(conn
->ocamlValues
, OcamlHTTP200Aliases
, option
);
3364 free_curl_slist(conn
->http200Aliases
);
3365 conn
->http200Aliases
= NULL
;
3369 while (!Is_long(listIter
))
3371 conn
->http200Aliases
= curl_slist_append(conn
->http200Aliases
, String_val(Field(listIter
, 0)));
3373 listIter
= Field(listIter
, 1);
3376 result
= curl_easy_setopt(conn
->connection
,
3377 CURLOPT_HTTP200ALIASES
,
3378 conn
->http200Aliases
);
3380 if (result
!= CURLE_OK
)
3381 raiseError(conn
, result
);
3387 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
3388 static void handle_UNRESTRICTED_AUTH(Connection
*conn
, value option
)
3391 CURLcode result
= CURLE_OK
;
3393 result
= curl_easy_setopt(conn
->connection
,
3394 CURLOPT_UNRESTRICTED_AUTH
,
3397 if (result
!= CURLE_OK
)
3398 raiseError(conn
, result
);
3404 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
3405 static void handle_FTP_USE_EPRT(Connection
*conn
, value option
)
3408 CURLcode result
= CURLE_OK
;
3410 result
= curl_easy_setopt(conn
->connection
,
3411 CURLOPT_FTP_USE_EPRT
,
3414 if (result
!= CURLE_OK
)
3415 raiseError(conn
, result
);
3421 #if HAVE_DECL_CURLOPT_HTTPAUTH
3422 static void handle_HTTPAUTH(Connection
*conn
, value option
)
3425 CAMLlocal1(listIter
);
3426 CURLcode result
= CURLE_OK
;
3427 long auth
= CURLAUTH_NONE
;
3431 while (!Is_long(listIter
))
3433 switch (Long_val(Field(listIter
, 0)))
3435 case 0: /* CURLAUTH_BASIC */
3436 auth
|= CURLAUTH_BASIC
;
3439 case 1: /* CURLAUTH_DIGEST */
3440 auth
|= CURLAUTH_DIGEST
;
3443 case 2: /* CURLAUTH_GSSNEGOTIATE */
3444 auth
|= CURLAUTH_GSSNEGOTIATE
;
3447 case 3: /* CURLAUTH_NTLM */
3448 auth
|= CURLAUTH_NTLM
;
3451 case 4: /* CURLAUTH_ANY */
3452 auth
|= CURLAUTH_ANY
;
3455 case 5: /* CURLAUTH_ANYSAFE */
3456 auth
|= CURLAUTH_ANYSAFE
;
3460 failwith("Invalid HTTPAUTH Value");
3464 listIter
= Field(listIter
, 1);
3467 result
= curl_easy_setopt(conn
->connection
,
3471 if (result
!= CURLE_OK
)
3472 raiseError(conn
, result
);
3478 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
3479 static void handle_FTP_CREATE_MISSING_DIRS(Connection
*conn
, value option
)
3482 CURLcode result
= CURLE_OK
;
3484 result
= curl_easy_setopt(conn
->connection
,
3485 CURLOPT_FTP_CREATE_MISSING_DIRS
,
3488 if (result
!= CURLE_OK
)
3489 raiseError(conn
, result
);
3495 #if HAVE_DECL_CURLOPT_PROXYAUTH
3496 static void handle_PROXYAUTH(Connection
*conn
, value option
)
3499 CAMLlocal1(listIter
);
3500 CURLcode result
= CURLE_OK
;
3501 long auth
= CURLAUTH_NONE
;
3505 while (!Is_long(listIter
))
3507 switch (Long_val(Field(listIter
, 0)))
3509 case 0: /* CURLAUTH_BASIC */
3510 auth
|= CURLAUTH_BASIC
;
3513 case 1: /* CURLAUTH_DIGEST */
3514 auth
|= CURLAUTH_DIGEST
;
3517 case 2: /* CURLAUTH_GSSNEGOTIATE */
3518 auth
|= CURLAUTH_GSSNEGOTIATE
;
3521 case 3: /* CURLAUTH_NTLM */
3522 auth
|= CURLAUTH_NTLM
;
3525 case 4: /* CURLAUTH_ANY */
3526 auth
|= CURLAUTH_ANY
;
3529 case 5: /* CURLAUTH_ANYSAFE */
3530 auth
|= CURLAUTH_ANYSAFE
;
3534 failwith("Invalid HTTPAUTH Value");
3538 listIter
= Field(listIter
, 1);
3541 result
= curl_easy_setopt(conn
->connection
,
3545 if (result
!= CURLE_OK
)
3546 raiseError(conn
, result
);
3552 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
3553 static void handle_FTP_RESPONSE_TIMEOUT(Connection
*conn
, value option
)
3556 CURLcode result
= CURLE_OK
;
3558 result
= curl_easy_setopt(conn
->connection
,
3559 CURLOPT_FTP_RESPONSE_TIMEOUT
,
3562 if (result
!= CURLE_OK
)
3563 raiseError(conn
, result
);
3569 #if HAVE_DECL_CURLOPT_IPRESOLVE
3570 static void handle_IPRESOLVE(Connection
*conn
, value option
)
3573 CURLcode result
= CURLE_OK
;
3575 switch (Long_val(option
))
3577 case 0: /* CURL_IPRESOLVE_WHATEVER */
3578 result
= curl_easy_setopt(conn
->connection
,
3580 CURL_IPRESOLVE_WHATEVER
);
3583 case 1: /* CURL_IPRESOLVE_V4 */
3584 result
= curl_easy_setopt(conn
->connection
,
3589 case 2: /* CURL_IPRESOLVE_V6 */
3590 result
= curl_easy_setopt(conn
->connection
,
3596 failwith("Invalid IPRESOLVE Value");
3600 if (result
!= CURLE_OK
)
3601 raiseError(conn
, result
);
3607 #if HAVE_DECL_CURLOPT_MAXFILESIZE
3608 static void handle_MAXFILESIZE(Connection
*conn
, value option
)
3611 CURLcode result
= CURLE_OK
;
3613 result
= curl_easy_setopt(conn
->connection
,
3614 CURLOPT_MAXFILESIZE
,
3617 if (result
!= CURLE_OK
)
3618 raiseError(conn
, result
);
3624 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
3625 static void handle_INFILESIZE_LARGE(Connection
*conn
, value option
)
3628 CURLcode result
= CURLE_OK
;
3630 result
= curl_easy_setopt(conn
->connection
,
3631 CURLOPT_INFILESIZE_LARGE
,
3634 if (result
!= CURLE_OK
)
3635 raiseError(conn
, result
);
3641 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
3642 static void handle_RESUME_FROM_LARGE(Connection
*conn
, value option
)
3645 CURLcode result
= CURLE_OK
;
3647 result
= curl_easy_setopt(conn
->connection
,
3648 CURLOPT_RESUME_FROM_LARGE
,
3651 if (result
!= CURLE_OK
)
3652 raiseError(conn
, result
);
3658 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
3659 static void handle_MAXFILESIZE_LARGE(Connection
*conn
, value option
)
3662 CURLcode result
= CURLE_OK
;
3664 result
= curl_easy_setopt(conn
->connection
,
3665 CURLOPT_MAXFILESIZE_LARGE
,
3668 if (result
!= CURLE_OK
)
3669 raiseError(conn
, result
);
3675 #if HAVE_DECL_CURLOPT_NETRC_FILE
3676 static void handle_NETRC_FILE(Connection
*conn
, value option
)
3679 CURLcode result
= CURLE_OK
;
3681 Store_field(conn
->ocamlValues
, OcamlNETRCFile
, option
);
3683 if (conn
->netrcFile
!= NULL
)
3684 free(conn
->netrcFile
);
3686 conn
->netrcFile
= strdup(String_val(option
));
3688 result
= curl_easy_setopt(conn
->connection
,
3692 if (result
!= CURLE_OK
)
3693 raiseError(conn
, result
);
3699 #if HAVE_DECL_CURLOPT_FTP_SSL
3700 static void handle_FTP_SSL(Connection
*conn
, value option
)
3703 CURLcode result
= CURLE_OK
;
3705 switch (Long_val(option
))
3707 case 0: /* CURLFTPSSL_NONE */
3708 result
= curl_easy_setopt(conn
->connection
,
3713 case 1: /* CURLFTPSSL_TRY */
3714 result
= curl_easy_setopt(conn
->connection
,
3719 case 2: /* CURLFTPSSL_CONTROL */
3720 result
= curl_easy_setopt(conn
->connection
,
3722 CURLFTPSSL_CONTROL
);
3725 case 3: /* CURLFTPSSL_ALL */
3726 result
= curl_easy_setopt(conn
->connection
,
3732 failwith("Invalid FTP_SSL Value");
3736 if (result
!= CURLE_OK
)
3737 raiseError(conn
, result
);
3743 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
3744 static void handle_POSTFIELDSIZE_LARGE(Connection
*conn
, value option
)
3747 CURLcode result
= CURLE_OK
;
3749 result
= curl_easy_setopt(conn
->connection
,
3750 CURLOPT_POSTFIELDSIZE_LARGE
,
3753 if (result
!= CURLE_OK
)
3754 raiseError(conn
, result
);
3760 #if HAVE_DECL_CURLOPT_TCP_NODELAY
3761 static void handle_TCP_NODELAY(Connection
*conn
, value option
)
3764 CURLcode result
= CURLE_OK
;
3766 result
= curl_easy_setopt(conn
->connection
,
3767 CURLOPT_TCP_NODELAY
,
3770 if (result
!= CURLE_OK
)
3771 raiseError(conn
, result
);
3777 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
3778 static void handle_FTPSSLAUTH(Connection
*conn
, value option
)
3781 CURLcode result
= CURLE_OK
;
3783 switch (Long_val(option
))
3785 case 0: /* CURLFTPAUTH_DEFAULT */
3786 result
= curl_easy_setopt(conn
->connection
,
3788 CURLFTPAUTH_DEFAULT
);
3791 case 1: /* CURLFTPAUTH_SSL */
3792 result
= curl_easy_setopt(conn
->connection
,
3797 case 2: /* CURLFTPAUTH_TLS */
3798 result
= curl_easy_setopt(conn
->connection
,
3804 failwith("Invalid FTPSSLAUTH value");
3808 if (result
!= CURLE_OK
)
3809 raiseError(conn
, result
);
3815 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
3816 static void handle_IOCTLFUNCTION(Connection
*conn
, value option
)
3819 CURLcode result
= CURLE_OK
;
3821 if (Tag_val(option
) == Closure_tag
)
3822 Store_field(conn
->ocamlValues
, OcamlIOCTLCallback
, option
);
3824 failwith("Not a proper closure");
3826 result
= curl_easy_setopt(conn
->connection
,
3827 CURLOPT_IOCTLFUNCTION
,
3829 if (result
!= CURLE_OK
)
3830 raiseError(conn
, result
);
3832 result
= curl_easy_setopt(conn
->connection
,
3836 if (result
!= CURLE_OK
)
3837 raiseError(conn
, result
);
3843 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
3844 static void handle_FTP_ACCOUNT(Connection
*conn
, value option
)
3847 CURLcode result
= CURLE_OK
;
3849 Store_field(conn
->ocamlValues
, OcamlFTPAccount
, option
);
3851 if (conn
->ftpaccount
!= NULL
)
3852 free(conn
->ftpaccount
);
3854 conn
->ftpaccount
= strdup(String_val(option
));
3856 result
= curl_easy_setopt(conn
->connection
,
3857 CURLOPT_FTP_ACCOUNT
,
3860 if (result
!= CURLE_OK
)
3861 raiseError(conn
, result
);
3867 #if HAVE_DECL_CURLOPT_COOKIELIST
3868 static void handle_COOKIELIST(Connection
*conn
, value option
)
3871 CURLcode result
= CURLE_OK
;
3873 Store_field(conn
->ocamlValues
, OcamlCookieList
, option
);
3875 if (conn
->cookielist
!= NULL
)
3876 free(conn
->cookielist
);
3878 conn
->cookielist
= strdup(String_val(option
));
3880 result
= curl_easy_setopt(conn
->connection
,
3884 if (result
!= CURLE_OK
)
3885 raiseError(conn
, result
);
3891 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
3892 static void handle_IGNORE_CONTENT_LENGTH(Connection
*conn
, value option
)
3895 CURLcode result
= CURLE_OK
;
3897 result
= curl_easy_setopt(conn
->connection
,
3898 CURLOPT_IGNORE_CONTENT_LENGTH
,
3901 if (result
!= CURLE_OK
)
3902 raiseError(conn
, result
);
3908 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
3909 static void handle_FTP_SKIP_PASV_IP(Connection
*conn
, value option
)
3912 CURLcode result
= CURLE_OK
;
3914 result
= curl_easy_setopt(conn
->connection
,
3915 CURLOPT_FTP_SKIP_PASV_IP
,
3918 if (result
!= CURLE_OK
)
3919 raiseError(conn
, result
);
3925 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
3926 static void handle_FTP_FILEMETHOD(Connection
*conn
, value option
)
3929 CURLcode result
= CURLE_OK
;
3931 switch (Long_val(option
))
3933 case 0: /* CURLFTPMETHOD_DEFAULT */
3934 result
= curl_easy_setopt(conn
->connection
,
3935 CURLOPT_FTP_FILEMETHOD
,
3936 CURLFTPMETHOD_DEFAULT
);
3939 case 1: /* CURLFTMETHOD_MULTICWD */
3940 result
= curl_easy_setopt(conn
->connection
,
3941 CURLOPT_FTP_FILEMETHOD
,
3942 CURLFTPMETHOD_MULTICWD
);
3945 case 2: /* CURLFTPMETHOD_NOCWD */
3946 result
= curl_easy_setopt(conn
->connection
,
3947 CURLOPT_FTP_FILEMETHOD
,
3948 CURLFTPMETHOD_NOCWD
);
3951 case 3: /* CURLFTPMETHOD_SINGLECWD */
3952 result
= curl_easy_setopt(conn
->connection
,
3953 CURLOPT_FTP_FILEMETHOD
,
3954 CURLFTPMETHOD_SINGLECWD
);
3957 failwith("Invalid FTP_FILEMETHOD value");
3961 if (result
!= CURLE_OK
)
3962 raiseError(conn
, result
);
3968 #if HAVE_DECL_CURLOPT_LOCALPORT
3969 static void handle_LOCALPORT(Connection
*conn
, value option
)
3972 CURLcode result
= CURLE_OK
;
3974 result
= curl_easy_setopt(conn
->connection
,
3978 if (result
!= CURLE_OK
)
3979 raiseError(conn
, result
);
3985 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
3986 static void handle_LOCALPORTRANGE(Connection
*conn
, value option
)
3989 CURLcode result
= CURLE_OK
;
3991 result
= curl_easy_setopt(conn
->connection
,
3992 CURLOPT_LOCALPORTRANGE
,
3995 if (result
!= CURLE_OK
)
3996 raiseError(conn
, result
);
4002 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4003 static void handle_CONNECT_ONLY(Connection
*conn
, value option
)
4006 CURLcode result
= CURLE_OK
;
4008 result
= curl_easy_setopt(conn
->connection
,
4009 CURLOPT_CONNECT_ONLY
,
4012 if (result
!= CURLE_OK
)
4013 raiseError(conn
, result
);
4019 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4020 static void handle_MAX_SEND_SPEED_LARGE(Connection
*conn
, value option
)
4023 CURLcode result
= CURLE_OK
;
4025 result
= curl_easy_setopt(conn
->connection
,
4026 CURLOPT_MAX_SEND_SPEED_LARGE
,
4029 if (result
!= CURLE_OK
)
4030 raiseError(conn
, result
);
4036 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4037 static void handle_MAX_RECV_SPEED_LARGE(Connection
*conn
, value option
)
4040 CURLcode result
= CURLE_OK
;
4042 result
= curl_easy_setopt(conn
->connection
,
4043 CURLOPT_MAX_RECV_SPEED_LARGE
,
4046 if (result
!= CURLE_OK
)
4047 raiseError(conn
, result
);
4053 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4054 static void handle_FTP_ALTERNATIVE_TO_USER(Connection
*conn
, value option
)
4057 CURLcode result
= CURLE_OK
;
4059 Store_field(conn
->ocamlValues
, OcamlFTPAlternativeToUser
, option
);
4061 if (conn
->ftpAlternativeToUser
!= NULL
)
4062 free(conn
->ftpAlternativeToUser
);
4064 conn
->ftpAlternativeToUser
= strdup(String_val(option
));
4066 result
= curl_easy_setopt(conn
->connection
,
4067 CURLOPT_FTP_ALTERNATIVE_TO_USER
,
4068 conn
->ftpAlternativeToUser
);
4070 if (result
!= CURLE_OK
)
4071 raiseError(conn
, result
);
4077 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4078 static void handle_SSL_SESSIONID_CACHE(Connection
*conn
, value option
)
4081 CURLcode result
= CURLE_OK
;
4083 result
= curl_easy_setopt(conn
->connection
,
4084 CURLOPT_SSL_SESSIONID_CACHE
,
4087 if (result
!= CURLE_OK
)
4088 raiseError(conn
, result
);
4094 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4095 static void handle_SSH_AUTH_TYPES(Connection
*conn
, value option
)
4098 CAMLlocal1(listIter
);
4099 CURLcode result
= CURLE_OK
;
4100 long authTypes
= CURLSSH_AUTH_NONE
;
4104 while (!Is_long(listIter
))
4106 switch (Long_val(Field(listIter
, 0)))
4108 case 0: /* CURLSSH_AUTH_ANY */
4109 authTypes
|= CURLSSH_AUTH_ANY
;
4112 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4113 authTypes
|= CURLSSH_AUTH_PUBLICKEY
;
4116 case 2: /* CURLSSH_AUTH_PASSWORD */
4117 authTypes
|= CURLSSH_AUTH_PASSWORD
;
4120 case 3: /* CURLSSH_AUTH_HOST */
4121 authTypes
|= CURLSSH_AUTH_HOST
;
4124 case 4: /* CURLSSH_AUTH_KEYBOARD */
4125 authTypes
|= CURLSSH_AUTH_KEYBOARD
;
4129 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4133 listIter
= Field(listIter
, 1);
4136 result
= curl_easy_setopt(conn
->connection
,
4137 CURLOPT_SSH_AUTH_TYPES
,
4140 if (result
!= CURLE_OK
)
4141 raiseError(conn
, result
);
4147 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4148 static void handle_SSH_PUBLIC_KEYFILE(Connection
*conn
, value option
)
4151 CURLcode result
= CURLE_OK
;
4153 Store_field(conn
->ocamlValues
, OcamlSSHPublicKeyFile
, option
);
4155 if (conn
->sshPublicKeyFile
!= NULL
)
4156 free(conn
->sshPublicKeyFile
);
4158 conn
->sshPublicKeyFile
= strdup(String_val(option
));
4160 result
= curl_easy_setopt(conn
->connection
,
4161 CURLOPT_SSH_PUBLIC_KEYFILE
,
4162 conn
->sshPublicKeyFile
);
4164 if (result
!= CURLE_OK
)
4165 raiseError(conn
, result
);
4171 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4172 static void handle_SSH_PRIVATE_KEYFILE(Connection
*conn
, value option
)
4175 CURLcode result
= CURLE_OK
;
4177 Store_field(conn
->ocamlValues
, OcamlSSHPrivateKeyFile
, option
);
4179 if (conn
->sshPrivateKeyFile
!= NULL
)
4180 free(conn
->sshPrivateKeyFile
);
4182 conn
->sshPrivateKeyFile
= strdup(String_val(option
));
4184 result
= curl_easy_setopt(conn
->connection
,
4185 CURLOPT_SSH_PRIVATE_KEYFILE
,
4186 conn
->sshPrivateKeyFile
);
4188 if (result
!= CURLE_OK
)
4189 raiseError(conn
, result
);
4195 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4196 static void handle_FTP_SSL_CCC(Connection
*conn
, value option
)
4199 CURLcode result
= CURLE_OK
;
4201 switch (Long_val(option
))
4203 case 0: /* CURLFTPSSL_CCC_NONE */
4204 result
= curl_easy_setopt(conn
->connection
,
4205 CURLOPT_FTP_SSL_CCC
,
4206 CURLFTPSSL_CCC_NONE
);
4209 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4210 result
= curl_easy_setopt(conn
->connection
,
4211 CURLOPT_FTP_SSL_CCC
,
4212 CURLFTPSSL_CCC_PASSIVE
);
4215 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4216 result
= curl_easy_setopt(conn
->connection
,
4217 CURLOPT_FTP_SSL_CCC
,
4218 CURLFTPSSL_CCC_ACTIVE
);
4222 failwith("Invalid FTPSSL_CCC value");
4226 if (result
!= CURLE_OK
)
4227 raiseError(conn
, result
);
4233 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4234 static void handle_TIMEOUT_MS(Connection
*conn
, value option
)
4237 CURLcode result
= CURLE_OK
;
4239 result
= curl_easy_setopt(conn
->connection
,
4243 if (result
!= CURLE_OK
)
4244 raiseError(conn
, result
);
4250 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4251 static void handle_CONNECTTIMEOUT_MS(Connection
*conn
, value option
)
4254 CURLcode result
= CURLE_OK
;
4256 result
= curl_easy_setopt(conn
->connection
,
4257 CURLOPT_CONNECTTIMEOUT_MS
,
4260 if (result
!= CURLE_OK
)
4261 raiseError(conn
, result
);
4267 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
4268 static void handle_HTTP_TRANSFER_DECODING(Connection
*conn
, value option
)
4271 CURLcode result
= CURLE_OK
;
4273 result
= curl_easy_setopt(conn
->connection
,
4274 CURLOPT_HTTP_TRANSFER_DECODING
,
4277 if (result
!= CURLE_OK
)
4278 raiseError(conn
, result
);
4284 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
4285 static void handle_HTTP_CONTENT_DECODING(Connection
*conn
, value option
)
4288 CURLcode result
= CURLE_OK
;
4290 result
= curl_easy_setopt(conn
->connection
,
4291 CURLOPT_HTTP_CONTENT_DECODING
,
4294 if (result
!= CURLE_OK
)
4295 raiseError(conn
, result
);
4301 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
4302 static void handle_NEW_FILE_PERMS(Connection
*conn
, value option
)
4305 CURLcode result
= CURLE_OK
;
4307 result
= curl_easy_setopt(conn
->connection
,
4308 CURLOPT_NEW_FILE_PERMS
,
4311 if (result
!= CURLE_OK
)
4312 raiseError(conn
, result
);
4318 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
4319 static void handle_NEW_DIRECTORY_PERMS(Connection
*conn
, value option
)
4322 CURLcode result
= CURLE_OK
;
4324 result
= curl_easy_setopt(conn
->connection
,
4325 CURLOPT_NEW_DIRECTORY_PERMS
,
4328 if (result
!= CURLE_OK
)
4329 raiseError(conn
, result
);
4335 #if HAVE_DECL_CURLOPT_POST301
4336 static void handle_POST301(Connection
*conn
, value option
)
4339 CURLcode result
= CURLE_OK
;
4341 result
= curl_easy_setopt(conn
->connection
,
4345 if (result
!= CURLE_OK
)
4346 raiseError(conn
, result
);
4352 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
4353 static void handle_SSH_HOST_PUBLIC_KEY_MD5(Connection
*conn
, value option
)
4356 CURLcode result
= CURLE_OK
;
4358 Store_field(conn
->ocamlValues
, OcamlSSHHostPublicKeyMD5
, option
);
4360 if (conn
->sshHostPublicKeyMD5
!= NULL
)
4361 free(conn
->sshHostPublicKeyMD5
);
4363 conn
->sshHostPublicKeyMD5
= strdup(String_val(option
));
4365 result
= curl_easy_setopt(conn
->connection
,
4366 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
,
4367 conn
->sshHostPublicKeyMD5
);
4369 if (result
!= CURLE_OK
)
4370 raiseError(conn
, result
);
4376 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
4377 static void handle_COPYPOSTFIELDS(Connection
*conn
, value option
)
4380 CURLcode result
= CURLE_OK
;
4382 Store_field(conn
->ocamlValues
, OcamlCopyPostFields
, option
);
4384 if (conn
->copyPostFields
!= NULL
)
4385 free(conn
->copyPostFields
);
4387 conn
->copyPostFields
= strdup(String_val(option
));
4389 result
= curl_easy_setopt(conn
->connection
,
4390 CURLOPT_COPYPOSTFIELDS
,
4391 conn
->copyPostFields
);
4393 if (result
!= CURLE_OK
)
4394 raiseError(conn
, result
);
4400 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
4401 static void handle_PROXY_TRANSFER_MODE(Connection
*conn
, value option
)
4404 CURLcode result
= CURLE_OK
;
4406 result
= curl_easy_setopt(conn
->connection
,
4407 CURLOPT_PROXY_TRANSFER_MODE
,
4410 if (result
!= CURLE_OK
)
4411 raiseError(conn
, result
);
4417 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
4418 static void handle_SEEKFUNCTION(Connection
*conn
, value option
)
4421 CURLcode result
= CURLE_OK
;
4423 if (Tag_val(option
) == Closure_tag
)
4424 Store_field(conn
->ocamlValues
, OcamlSeekFunctionCallback
, option
);
4426 failwith("Not a proper closure");
4428 result
= curl_easy_setopt(conn
->connection
,
4429 CURLOPT_SEEKFUNCTION
,
4432 if (result
!= CURLE_OK
)
4433 raiseError(conn
, result
);
4435 result
= curl_easy_setopt(conn
->connection
,
4439 if (result
!= CURLE_OK
)
4440 raiseError(conn
, result
);
4446 #if HAVE_DECL_CURLOPT_AUTOREFERER
4447 static void handle_AUTOREFERER(Connection
*conn
, value option
)
4450 CURLcode result
= curl_easy_setopt(conn
->connection
,
4451 CURLOPT_AUTOREFERER
,
4454 if (result
!= CURLE_OK
)
4455 raiseError(conn
, result
);
4461 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
4462 static void handle_OPENSOCKETFUNCTION(Connection
*conn
, value option
)
4465 CURLcode result
= CURLE_OK
;
4467 Store_field(conn
->ocamlValues
, OcamlOpenSocketFunctionCallback
, option
);
4469 result
= curl_easy_setopt(conn
->connection
,
4470 CURLOPT_OPENSOCKETDATA
,
4473 if (result
!= CURLE_OK
)
4474 raiseError(conn
, result
);
4476 result
= curl_easy_setopt(conn
->connection
,
4477 CURLOPT_OPENSOCKETFUNCTION
,
4478 openSocketFunction
);
4480 if (result
!= CURLE_OK
)
4481 raiseError(conn
, result
);
4487 #if HAVE_DECL_CURLOPT_PROXYTYPE
4488 static void handle_PROXYTYPE(Connection
*conn
, value option
)
4491 CURLcode result
= CURLE_OK
;
4494 switch (Long_val(option
))
4496 case 0: proxy_type
= CURLPROXY_HTTP
; break;
4497 case 1: proxy_type
= CURLPROXY_HTTP_1_0
; break;
4498 case 2: proxy_type
= CURLPROXY_SOCKS4
; break;
4499 case 3: proxy_type
= CURLPROXY_SOCKS5
; break;
4500 case 4: proxy_type
= CURLPROXY_SOCKS4A
; break;
4501 case 5: proxy_type
= CURLPROXY_SOCKS5_HOSTNAME
; break;
4503 failwith("Invalid curl proxy type");
4506 result
= curl_easy_setopt(conn
->connection
,
4510 if (result
!= CURLE_OK
)
4511 raiseError(conn
, result
);
4517 #if HAVE_DECL_CURLOPT_PROTOCOLS || HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
4522 CURLPROTO_HTTP
, CURLPROTO_HTTPS
, CURLPROTO_FTP
, CURLPROTO_FTPS
, CURLPROTO_SCP
, CURLPROTO_SFTP
,
4523 CURLPROTO_TELNET
, CURLPROTO_LDAP
, CURLPROTO_LDAPS
, CURLPROTO_DICT
, CURLPROTO_FILE
, CURLPROTO_TFTP
,
4524 /* factor out with autoconf? */
4525 #if defined(CURLPROTO_IMAP)
4530 #if defined(CURLPROTO_IMAPS)
4535 #if defined(CURLPROTO_POP3)
4540 #if defined(CURLPROTO_POP3S)
4545 #if defined(CURLPROTO_SMTP)
4550 #if defined(CURLPROTO_SMTPS)
4555 #if defined(CURLPROTO_RTSP)
4560 #if defined(CURLPROTO_RTMP)
4565 #if defined(CURLPROTO_RTMPT)
4570 #if defined(CURLPROTO_RTMPE)
4575 #if defined(CURLPROTO_RTMPTE)
4580 #if defined(CURLPROTO_RTMPS)
4585 #if defined(CURLPROTO_RTMPTS)
4590 #if defined(CURLPROTO_GOPHER)
4597 static void handle_PROTOCOLSOPTION(CURLoption curlopt
, Connection
*conn
, value option
)
4600 CURLcode result
= CURLE_OK
;
4604 while (Val_emptylist
!= option
)
4606 index
= Int_val(Field(option
, 0));
4607 if ((index
< 0) || ((size_t)index
>= sizeof(protoMap
) / sizeof(protoMap
[0])))
4608 failwith("Invalid curl protocol");
4610 protocols
= protocols
| protoMap
[index
];
4612 option
= Field(option
, 1);
4615 result
= curl_easy_setopt(conn
->connection
,
4619 if (result
!= CURLE_OK
)
4620 raiseError(conn
, result
);
4626 #if HAVE_DECL_CURLOPT_PROTOCOLS
4627 static void handle_PROTOCOLS(Connection
*conn
, value option
)
4629 handle_PROTOCOLSOPTION(CURLOPT_PROTOCOLS
, conn
, option
);
4633 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
4634 static void handle_REDIR_PROTOCOLS(Connection
*conn
, value option
)
4636 handle_PROTOCOLSOPTION(CURLOPT_REDIR_PROTOCOLS
, conn
, option
);
4640 #if HAVE_DECL_CURLOPT_RESOLVE
4641 static void handle_RESOLVE(Connection
*conn
, value option
)
4646 CURLcode result
= CURLE_OK
;
4648 free_curl_slist(conn
->resolve
);
4649 conn
->resolve
= NULL
;
4653 while (head
!= Val_emptylist
)
4655 conn
->resolve
= curl_slist_append(conn
->resolve
, String_val(Field(head
,0)));
4656 head
= Field(head
, 1);
4659 result
= curl_easy_setopt(conn
->connection
,
4663 if (result
!= CURLE_OK
)
4664 raiseError(conn
, result
);
4670 #if HAVE_DECL_CURLOPT_DNS_SERVERS
4671 static void handle_DNS_SERVERS(Connection
*conn
, value option
)
4675 Store_field(conn
->ocamlValues
, OcamlDNSServers
, option
);
4677 CURLcode result
= CURLE_OK
;
4678 free_if(conn
->dns_servers
);
4680 conn
->dns_servers
= strdup(String_val(option
));
4682 result
= curl_easy_setopt(conn
->connection
,
4683 CURLOPT_DNS_SERVERS
,
4686 if (result
!= CURLE_OK
)
4687 raiseError(conn
, result
);
4693 #if HAVE_DECL_CURLOPT_MAIL_FROM
4694 static void handle_MAIL_FROM(Connection
*conn
, value option
)
4697 CURLcode result
= CURLE_OK
;
4699 Store_field(conn
->ocamlValues
, OcamlMailFrom
, option
);
4701 if (conn
->mailFrom
!= NULL
)
4702 free(conn
->mailFrom
);
4704 conn
->mailFrom
= strdup(String_val(option
));
4706 result
= curl_easy_setopt(conn
->connection
,
4710 if (result
!= CURLE_OK
)
4711 raiseError(conn
, result
);
4717 #if HAVE_DECL_CURLOPT_MAIL_RCPT
4718 static void handle_MAIL_RCPT(Connection
*conn
, value option
)
4721 CAMLlocal1(listIter
);
4722 CURLcode result
= CURLE_OK
;
4724 Store_field(conn
->ocamlValues
, OcamlMailRcpt
, option
);
4726 free_curl_slist(conn
->mailRcpt
);
4727 conn
->mailRcpt
= NULL
;
4731 while (Val_emptylist
!= listIter
)
4733 conn
->mailRcpt
= curl_slist_append(conn
->mailRcpt
, String_val(Field(listIter
, 0)));
4735 listIter
= Field(listIter
, 1);
4738 result
= curl_easy_setopt(conn
->connection
,
4742 if (result
!= CURLE_OK
)
4743 raiseError(conn
, result
);
4749 static Connection
*duplicateConnection(Connection
*original
)
4751 Connection
*connection
;
4754 caml_enter_blocking_section();
4755 h
= curl_easy_duphandle(original
->connection
);
4756 caml_leave_blocking_section();
4758 connection
= allocConnection(h
);
4760 Store_field(connection
->ocamlValues
, OcamlWriteCallback
,
4761 Field(original
->ocamlValues
, OcamlWriteCallback
));
4762 Store_field(connection
->ocamlValues
, OcamlReadCallback
,
4763 Field(original
->ocamlValues
, OcamlReadCallback
));
4764 Store_field(connection
->ocamlValues
, OcamlErrorBuffer
,
4765 Field(original
->ocamlValues
, OcamlErrorBuffer
));
4766 Store_field(connection
->ocamlValues
, OcamlPostFields
,
4767 Field(original
->ocamlValues
, OcamlPostFields
));
4768 Store_field(connection
->ocamlValues
, OcamlHTTPHeader
,
4769 Field(original
->ocamlValues
, OcamlHTTPHeader
));
4770 Store_field(connection
->ocamlValues
, OcamlQuote
,
4771 Field(original
->ocamlValues
, OcamlQuote
));
4772 Store_field(connection
->ocamlValues
, OcamlPostQuote
,
4773 Field(original
->ocamlValues
, OcamlPostQuote
));
4774 Store_field(connection
->ocamlValues
, OcamlHeaderCallback
,
4775 Field(original
->ocamlValues
, OcamlHeaderCallback
));
4776 Store_field(connection
->ocamlValues
, OcamlProgressCallback
,
4777 Field(original
->ocamlValues
, OcamlProgressCallback
));
4778 Store_field(connection
->ocamlValues
, OcamlDebugCallback
,
4779 Field(original
->ocamlValues
, OcamlDebugCallback
));
4780 Store_field(connection
->ocamlValues
, OcamlHTTP200Aliases
,
4781 Field(original
->ocamlValues
, OcamlHTTP200Aliases
));
4782 Store_field(connection
->ocamlValues
, OcamlIOCTLCallback
,
4783 Field(original
->ocamlValues
, OcamlIOCTLCallback
));
4784 Store_field(connection
->ocamlValues
, OcamlSeekFunctionCallback
,
4785 Field(original
->ocamlValues
, OcamlSeekFunctionCallback
));
4787 if (Field(original
->ocamlValues
, OcamlURL
) != Val_unit
)
4788 handle_URL(connection
, Field(original
->ocamlValues
,
4790 if (Field(original
->ocamlValues
, OcamlProxy
) != Val_unit
)
4791 handle_PROXY(connection
, Field(original
->ocamlValues
,
4793 if (Field(original
->ocamlValues
, OcamlUserPWD
) != Val_unit
)
4794 handle_USERPWD(connection
, Field(original
->ocamlValues
,
4796 if (Field(original
->ocamlValues
, OcamlProxyUserPWD
) != Val_unit
)
4797 handle_PROXYUSERPWD(connection
, Field(original
->ocamlValues
,
4798 OcamlProxyUserPWD
));
4799 if (Field(original
->ocamlValues
, OcamlRange
) != Val_unit
)
4800 handle_RANGE(connection
, Field(original
->ocamlValues
,
4802 if (Field(original
->ocamlValues
, OcamlErrorBuffer
) != Val_unit
)
4803 handle_ERRORBUFFER(connection
, Field(original
->ocamlValues
,
4805 if (Field(original
->ocamlValues
, OcamlPostFields
) != Val_unit
)
4806 handle_POSTFIELDS(connection
, Field(original
->ocamlValues
,
4808 if (Field(original
->ocamlValues
, OcamlReferer
) != Val_unit
)
4809 handle_REFERER(connection
, Field(original
->ocamlValues
,
4811 if (Field(original
->ocamlValues
, OcamlUserAgent
) != Val_unit
)
4812 handle_USERAGENT(connection
, Field(original
->ocamlValues
,
4814 if (Field(original
->ocamlValues
, OcamlFTPPort
) != Val_unit
)
4815 handle_FTPPORT(connection
, Field(original
->ocamlValues
,
4817 if (Field(original
->ocamlValues
, OcamlCookie
) != Val_unit
)
4818 handle_COOKIE(connection
, Field(original
->ocamlValues
,
4820 if (Field(original
->ocamlValues
, OcamlHTTPHeader
) != Val_unit
)
4821 handle_HTTPHEADER(connection
, Field(original
->ocamlValues
,
4823 if (Field(original
->ocamlValues
, OcamlHTTPPost
) != Val_unit
)
4824 handle_HTTPPOST(connection
, Field(original
->ocamlValues
,
4826 if (Field(original
->ocamlValues
, OcamlSSLCert
) != Val_unit
)
4827 handle_SSLCERT(connection
, Field(original
->ocamlValues
,
4829 if (Field(original
->ocamlValues
, OcamlSSLCertType
) != Val_unit
)
4830 handle_SSLCERTTYPE(connection
, Field(original
->ocamlValues
,
4832 if (Field(original
->ocamlValues
, OcamlSSLCertPasswd
) != Val_unit
)
4833 handle_SSLCERTPASSWD(connection
, Field(original
->ocamlValues
,
4834 OcamlSSLCertPasswd
));
4835 if (Field(original
->ocamlValues
, OcamlSSLKey
) != Val_unit
)
4836 handle_SSLKEY(connection
, Field(original
->ocamlValues
,
4838 if (Field(original
->ocamlValues
, OcamlSSLKeyType
) != Val_unit
)
4839 handle_SSLKEYTYPE(connection
, Field(original
->ocamlValues
,
4841 if (Field(original
->ocamlValues
, OcamlSSLKeyPasswd
) != Val_unit
)
4842 handle_SSLKEYPASSWD(connection
, Field(original
->ocamlValues
,
4843 OcamlSSLKeyPasswd
));
4844 if (Field(original
->ocamlValues
, OcamlSSLEngine
) != Val_unit
)
4845 handle_SSLENGINE(connection
, Field(original
->ocamlValues
,
4847 if (Field(original
->ocamlValues
, OcamlQuote
) != Val_unit
)
4848 handle_QUOTE(connection
, Field(original
->ocamlValues
,
4850 if (Field(original
->ocamlValues
, OcamlPostQuote
) != Val_unit
)
4851 handle_POSTQUOTE(connection
, Field(original
->ocamlValues
,
4853 if (Field(original
->ocamlValues
, OcamlCookieFile
) != Val_unit
)
4854 handle_COOKIEFILE(connection
, Field(original
->ocamlValues
,
4856 if (Field(original
->ocamlValues
, OcamlCustomRequest
) != Val_unit
)
4857 handle_CUSTOMREQUEST(connection
, Field(original
->ocamlValues
,
4858 OcamlCustomRequest
));
4859 if (Field(original
->ocamlValues
, OcamlInterface
) != Val_unit
)
4860 handle_INTERFACE(connection
, Field(original
->ocamlValues
,
4862 if (Field(original
->ocamlValues
, OcamlCAInfo
) != Val_unit
)
4863 handle_CAINFO(connection
, Field(original
->ocamlValues
,
4865 if (Field(original
->ocamlValues
, OcamlCAPath
) != Val_unit
)
4866 handle_CAPATH(connection
, Field(original
->ocamlValues
,
4868 if (Field(original
->ocamlValues
, OcamlRandomFile
) != Val_unit
)
4869 handle_RANDOM_FILE(connection
, Field(original
->ocamlValues
,
4871 if (Field(original
->ocamlValues
, OcamlEGDSocket
) != Val_unit
)
4872 handle_EGDSOCKET(connection
, Field(original
->ocamlValues
,
4874 if (Field(original
->ocamlValues
, OcamlCookieJar
) != Val_unit
)
4875 handle_COOKIEJAR(connection
, Field(original
->ocamlValues
,
4877 if (Field(original
->ocamlValues
, OcamlSSLCipherList
) != Val_unit
)
4878 handle_SSL_CIPHER_LIST(connection
, Field(original
->ocamlValues
,
4879 OcamlSSLCipherList
));
4880 if (Field(original
->ocamlValues
, OcamlPrivate
) != Val_unit
)
4881 handle_PRIVATE(connection
, Field(original
->ocamlValues
,
4883 if (Field(original
->ocamlValues
, OcamlHTTP200Aliases
) != Val_unit
)
4884 handle_HTTP200ALIASES(connection
, Field(original
->ocamlValues
,
4885 OcamlHTTP200Aliases
));
4886 if (Field(original
->ocamlValues
, OcamlNETRCFile
) != Val_unit
)
4887 handle_NETRC_FILE(connection
, Field(original
->ocamlValues
,
4889 if (Field(original
->ocamlValues
, OcamlFTPAccount
) != Val_unit
)
4890 handle_FTP_ACCOUNT(connection
, Field(original
->ocamlValues
,
4892 if (Field(original
->ocamlValues
, OcamlCookieList
) != Val_unit
)
4893 handle_COOKIELIST(connection
, Field(original
->ocamlValues
,
4895 if (Field(original
->ocamlValues
, OcamlFTPAlternativeToUser
) != Val_unit
)
4896 handle_FTP_ALTERNATIVE_TO_USER(connection
,
4897 Field(original
->ocamlValues
,
4898 OcamlFTPAlternativeToUser
));
4899 if (Field(original
->ocamlValues
, OcamlSSHPublicKeyFile
) != Val_unit
)
4900 handle_SSH_PUBLIC_KEYFILE(connection
,
4901 Field(original
->ocamlValues
,
4902 OcamlSSHPublicKeyFile
));
4903 if (Field(original
->ocamlValues
, OcamlSSHPrivateKeyFile
) != Val_unit
)
4904 handle_SSH_PRIVATE_KEYFILE(connection
,
4905 Field(original
->ocamlValues
,
4906 OcamlSSHPrivateKeyFile
));
4907 if (Field(original
->ocamlValues
, OcamlCopyPostFields
) != Val_unit
)
4908 handle_COPYPOSTFIELDS(connection
,
4909 Field(original
->ocamlValues
,
4910 OcamlCopyPostFields
));
4911 if (Field(original
->ocamlValues
, OcamlDNSServers
) != Val_unit
)
4912 handle_DNS_SERVERS(connection
,
4913 Field(original
->ocamlValues
,
4915 if (Field(original
->ocamlValues
, OcamlMailFrom
) != Val_unit
)
4916 handle_MAIL_FROM(connection
,
4917 Field(original
->ocamlValues
,
4919 if (Field(original
->ocamlValues
, OcamlMailRcpt
) != Val_unit
)
4920 handle_MAIL_RCPT(connection
,
4921 Field(original
->ocamlValues
,
4928 ** curl_easy_setopt helper function
4931 #define MAP(name) { handle_ ## name, "CURLOPT_"#name /*, CURLOPT_##name */ }
4932 #define MAP_NO(name) { NULL, "CURLOPT_"#name /*, CURLOPT_##name */ }
4934 CURLOptionMapping implementedOptionMap
[] =
4942 MAP(HTTPPROXYTUNNEL
),
4946 #if HAVE_DECL_CURLOPT_NOSIGNAL
4958 #if HAVE_DECL_CURLOPT_ENCODING
4963 MAP(FOLLOWLOCATION
),
4976 MAP(LOW_SPEED_LIMIT
),
4977 MAP(LOW_SPEED_TIME
),
4989 MAP(SSLENGINE_DEFAULT
),
4993 MAP(HEADERFUNCTION
),
5001 MAP(PROGRESSFUNCTION
),
5002 MAP(SSL_VERIFYPEER
),
5013 MAP(CONNECTTIMEOUT
),
5015 MAP(SSL_VERIFYHOST
),
5017 MAP(SSL_CIPHER_LIST
),
5020 MAP(DNS_CACHE_TIMEOUT
),
5021 MAP(DNS_USE_GLOBAL_CACHE
),
5023 #if HAVE_DECL_CURLOPT_PRIVATE
5028 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
5029 MAP(HTTP200ALIASES
),
5031 MAP_NO(HTTP200ALIASES
),
5033 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
5034 MAP(UNRESTRICTED_AUTH
),
5036 MAP_NO(UNRESTRICTED_AUTH
),
5038 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
5041 MAP_NO(FTP_USE_EPRT
),
5043 #if HAVE_DECL_CURLOPT_HTTPAUTH
5048 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
5049 MAP(FTP_CREATE_MISSING_DIRS
),
5051 MAP_NO(FTP_CREATE_MISSING_DIRS
),
5053 #if HAVE_DECL_CURLOPT_PROXYAUTH
5058 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
5059 MAP(FTP_RESPONSE_TIMEOUT
),
5061 MAP_NO(FTP_RESPONSE_TIMEOUT
),
5063 #if HAVE_DECL_CURLOPT_IPRESOLVE
5068 #if HAVE_DECL_CURLOPT_MAXFILESIZE
5071 MAP_NO(MAXFILESIZE
),
5073 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
5074 MAP(INFILESIZE_LARGE
),
5076 MAP_NO(INFILESIZE_LARGE
),
5078 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
5079 MAP(RESUME_FROM_LARGE
),
5081 MAP_NO(RESUME_FROM_LARGE
),
5083 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
5084 MAP(MAXFILESIZE_LARGE
),
5086 MAP_NO(MAXFILESIZE_LARGE
),
5088 #if HAVE_DECL_CURLOPT_NETRC_FILE
5093 #if HAVE_DECL_CURLOPT_FTP_SSL
5098 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
5099 MAP(POSTFIELDSIZE_LARGE
),
5101 MAP_NO(POSTFIELDSIZE_LARGE
),
5103 #if HAVE_DECL_CURLOPT_TCP_NODELAY
5106 MAP_NO(TCP_NODELAY
),
5108 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
5113 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
5116 MAP_NO(IOCTLFUNCTION
),
5118 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
5121 MAP_NO(FTP_ACCOUNT
),
5123 #if HAVE_DECL_CURLOPT_COOKIELIST
5128 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
5129 MAP(IGNORE_CONTENT_LENGTH
),
5131 MAP_NO(IGNORE_CONTENT_LENGTH
),
5133 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
5134 MAP(FTP_SKIP_PASV_IP
),
5136 MAP_NO(FTP_SKIP_PASV_IP
),
5138 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
5139 MAP(FTP_FILEMETHOD
),
5141 MAP_NO(FTP_FILEMETHOD
),
5143 #if HAVE_DECL_CURLOPT_LOCALPORT
5148 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
5149 MAP(LOCALPORTRANGE
),
5151 MAP_NO(LOCALPORTRANGE
),
5153 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
5156 MAP_NO(CONNECT_ONLY
),
5158 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
5159 MAP(MAX_SEND_SPEED_LARGE
),
5161 MAP_NO(MAX_SEND_SPEED_LARGE
),
5163 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
5164 MAP(MAX_RECV_SPEED_LARGE
),
5166 MAP_NO(MAX_RECV_SPEED_LARGE
),
5168 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
5169 MAP(FTP_ALTERNATIVE_TO_USER
),
5171 MAP_NO(FTP_ALTERNATIVE_TO_USER
),
5173 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
5174 MAP(SSL_SESSIONID_CACHE
),
5176 MAP_NO(SSL_SESSIONID_CACHE
),
5178 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
5179 MAP(SSH_AUTH_TYPES
),
5181 MAP_NO(SSH_AUTH_TYPES
),
5183 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
5184 MAP(SSH_PUBLIC_KEYFILE
),
5186 MAP_NO(SSH_PUBLIC_KEYFILE
),
5188 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
5189 MAP(SSH_PRIVATE_KEYFILE
),
5191 MAP_NO(SSH_PRIVATE_KEYFILE
),
5193 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
5196 MAP_NO(FTP_SSL_CCC
),
5198 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
5203 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
5204 MAP(CONNECTTIMEOUT_MS
),
5206 MAP_NO(CONNECTTIMEOUT_MS
),
5208 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
5209 MAP(HTTP_TRANSFER_DECODING
),
5211 MAP_NO(HTTP_TRANSFER_DECODING
),
5213 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
5214 MAP(HTTP_CONTENT_DECODING
),
5216 MAP_NO(HTTP_CONTENT_DECODING
),
5218 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5219 MAP(NEW_FILE_PERMS
),
5221 MAP_NO(NEW_FILE_PERMS
),
5223 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5224 MAP(NEW_DIRECTORY_PERMS
),
5226 MAP_NO(NEW_DIRECTORY_PERMS
),
5228 #if HAVE_DECL_CURLOPT_POST301
5233 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5234 MAP(SSH_HOST_PUBLIC_KEY_MD5
),
5236 MAP_NO(SSH_HOST_PUBLIC_KEY_MD5
),
5238 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5239 MAP(COPYPOSTFIELDS
),
5241 MAP_NO(COPYPOSTFIELDS
),
5243 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5244 MAP(PROXY_TRANSFER_MODE
),
5246 MAP_NO(PROXY_TRANSFER_MODE
),
5248 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5251 MAP_NO(SEEKFUNCTION
),
5253 #if HAVE_DECL_CURLOPT_AUTOREFERER
5256 MAP_NO(AUTOREFERER
),
5258 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
5259 MAP(OPENSOCKETFUNCTION
),
5261 MAP_NO(OPENSOCKETFUNCTION
),
5263 #if HAVE_DECL_CURLOPT_PROXYTYPE
5268 #if HAVE_DECL_CURLOPT_PROTOCOLS
5273 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
5274 MAP(REDIR_PROTOCOLS
),
5276 MAP_NO(REDIR_PROTOCOLS
),
5278 #if HAVE_DECL_CURLOPT_RESOLVE
5283 #if HAVE_DECL_CURLOPT_DNS_SERVERS
5286 MAP_NO(DNS_SERVERS
),
5288 #if HAVE_DECL_CURLOPT_MAIL_FROM
5293 #if HAVE_DECL_CURLOPT_MAIL_RCPT
5300 CAMLprim value
helper_curl_easy_setopt(value conn
, value option
)
5302 CAMLparam2(conn
, option
);
5304 Connection
*connection
= Connection_val(conn
);
5305 CURLOptionMapping
* thisOption
= NULL
;
5306 static value
* exception
= NULL
;
5308 checkConnection(connection
);
5310 if (!Is_block(option
))
5311 failwith("Not a block");
5313 if (Wosize_val(option
) < 1)
5314 failwith("Insufficient data in block");
5316 data
= Field(option
, 0);
5318 if (Tag_val(option
) < sizeof(implementedOptionMap
)/sizeof(CURLOptionMapping
))
5320 thisOption
= &implementedOptionMap
[Tag_val(option
)];
5321 if (thisOption
->optionHandler
)
5322 thisOption
->optionHandler(connection
, data
);
5325 if (NULL
== exception
)
5327 exception
= caml_named_value("Curl.NotImplemented");
5328 if (NULL
== exception
) caml_invalid_argument("Curl.NotImplemented");
5331 caml_raise_with_string(*exception
, thisOption
->name
);
5335 failwith("Invalid CURLOPT Option");
5337 CAMLreturn(Val_unit
);
5341 ** curl_easy_perform helper function
5344 CAMLprim value
helper_curl_easy_perform(value conn
)
5347 CURLcode result
= CURLE_OK
;
5348 Connection
*connection
= Connection_val(conn
);
5350 checkConnection(connection
);
5352 enter_blocking_section();
5353 result
= curl_easy_perform(connection
->connection
);
5354 leave_blocking_section();
5356 if (result
!= CURLE_OK
)
5357 raiseError(connection
, result
);
5359 CAMLreturn(Val_unit
);
5363 ** curl_easy_cleanup helper function
5366 CAMLprim value
helper_curl_easy_cleanup(value conn
)
5369 Connection
*connection
= Connection_val(conn
);
5371 checkConnection(connection
);
5373 removeConnection(connection
, 0);
5375 CAMLreturn(Val_unit
);
5379 ** curl_easy_duphandle helper function
5382 CAMLprim value
helper_curl_easy_duphandle(value conn
)
5386 Connection
*connection
= Connection_val(conn
);
5388 checkConnection(connection
);
5390 result
= caml_curl_alloc(duplicateConnection(connection
));
5396 ** curl_easy_getinfo helper function
5399 enum GetInfoResultType
{
5400 StringValue
, LongValue
, DoubleValue
, StringListValue
5403 value
convertStringList(struct curl_slist
*slist
)
5406 CAMLlocal3(result
, current
, next
);
5407 struct curl_slist
*p
= slist
;
5409 result
= Val_int(0);
5410 current
= Val_int(0);
5415 next
= alloc_tuple(2);
5416 Store_field(next
, 0, copy_string(p
->data
));
5417 Store_field(next
, 1, Val_int(0));
5419 if (result
== Val_int(0))
5422 if (current
!= Val_int(0))
5423 Store_field(current
, 1, next
);
5430 curl_slist_free_all(slist
);
5435 CAMLprim value
helper_curl_easy_getinfo(value conn
, value option
)
5437 CAMLparam2(conn
, option
);
5439 CURLcode curlResult
;
5440 Connection
*connection
= Connection_val(conn
);
5441 enum GetInfoResultType resultType
;
5442 char *strValue
= NULL
;
5445 struct curl_slist
*stringListValue
= NULL
;
5447 checkConnection(connection
);
5449 switch(Long_val(option
))
5451 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5452 case 0: /* CURLINFO_EFFECTIVE_URL */
5453 resultType
= StringValue
;
5455 curlResult
= curl_easy_getinfo(connection
->connection
,
5456 CURLINFO_EFFECTIVE_URL
,
5460 #pragma message("libcurl does not provide CURLINFO_EFFECTIVE_URL")
5463 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5464 case 1: /* CURLINFO_HTTP_CODE */
5465 case 2: /* CURLINFO_RESPONSE_CODE */
5466 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5467 resultType
= LongValue
;
5469 curlResult
= curl_easy_getinfo(connection
->connection
,
5470 CURLINFO_RESPONSE_CODE
,
5473 resultType
= LongValue
;
5475 curlResult
= curl_easy_getinfo(connection
->connection
,
5482 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5483 case 3: /* CURLINFO_TOTAL_TIME */
5484 resultType
= DoubleValue
;
5486 curlResult
= curl_easy_getinfo(connection
->connection
,
5487 CURLINFO_TOTAL_TIME
,
5492 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5493 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5494 resultType
= DoubleValue
;
5496 curlResult
= curl_easy_getinfo(connection
->connection
,
5497 CURLINFO_NAMELOOKUP_TIME
,
5502 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5503 case 5: /* CURLINFO_CONNECT_TIME */
5504 resultType
= DoubleValue
;
5506 curlResult
= curl_easy_getinfo(connection
->connection
,
5507 CURLINFO_CONNECT_TIME
,
5512 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5513 case 6: /* CURLINFO_PRETRANSFER_TIME */
5514 resultType
= DoubleValue
;
5516 curlResult
= curl_easy_getinfo(connection
->connection
,
5517 CURLINFO_PRETRANSFER_TIME
,
5522 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5523 case 7: /* CURLINFO_SIZE_UPLOAD */
5524 resultType
= DoubleValue
;
5526 curlResult
= curl_easy_getinfo(connection
->connection
,
5527 CURLINFO_SIZE_UPLOAD
,
5532 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5533 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5534 resultType
= DoubleValue
;
5536 curlResult
= curl_easy_getinfo(connection
->connection
,
5537 CURLINFO_SIZE_DOWNLOAD
,
5542 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5543 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5544 resultType
= DoubleValue
;
5546 curlResult
= curl_easy_getinfo(connection
->connection
,
5547 CURLINFO_SPEED_DOWNLOAD
,
5552 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5553 case 10: /* CURLINFO_SPEED_UPLOAD */
5554 resultType
= DoubleValue
;
5556 curlResult
= curl_easy_getinfo(connection
->connection
,
5557 CURLINFO_SPEED_UPLOAD
,
5563 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5564 case 11: /* CURLINFO_HEADER_SIZE */
5565 resultType
= LongValue
;
5567 curlResult
= curl_easy_getinfo(connection
->connection
,
5568 CURLINFO_HEADER_SIZE
,
5573 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5574 case 12: /* CURLINFO_REQUEST_SIZE */
5575 resultType
= LongValue
;
5577 curlResult
= curl_easy_getinfo(connection
->connection
,
5578 CURLINFO_REQUEST_SIZE
,
5583 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5584 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5585 resultType
= LongValue
;
5587 curlResult
= curl_easy_getinfo(connection
->connection
,
5588 CURLINFO_SSL_VERIFYRESULT
,
5593 #if HAVE_DECL_CURLINFO_FILETIME
5594 case 14: /* CURLINFO_FILETIME */
5595 resultType
= DoubleValue
;
5597 curlResult
= curl_easy_getinfo(connection
->connection
,
5601 doubleValue
= longValue
;
5605 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5606 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5607 resultType
= DoubleValue
;
5609 curlResult
= curl_easy_getinfo(connection
->connection
,
5610 CURLINFO_CONTENT_LENGTH_DOWNLOAD
,
5615 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5616 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5617 resultType
= DoubleValue
;
5619 curlResult
= curl_easy_getinfo(connection
->connection
,
5620 CURLINFO_CONTENT_LENGTH_UPLOAD
,
5625 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5626 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5627 resultType
= DoubleValue
;
5629 curlResult
= curl_easy_getinfo(connection
->connection
,
5630 CURLINFO_STARTTRANSFER_TIME
,
5635 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5636 case 18: /* CURLINFO_CONTENT_TYPE */
5637 resultType
= StringValue
;
5639 curlResult
= curl_easy_getinfo(connection
->connection
,
5640 CURLINFO_CONTENT_TYPE
,
5645 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5646 case 19: /* CURLINFO_REDIRECT_TIME */
5647 resultType
= DoubleValue
;
5649 curlResult
= curl_easy_getinfo(connection
->connection
,
5650 CURLINFO_REDIRECT_TIME
,
5655 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5656 case 20: /* CURLINFO_REDIRECT_COUNT */
5657 resultType
= LongValue
;
5659 curlResult
= curl_easy_getinfo(connection
->connection
,
5660 CURLINFO_REDIRECT_COUNT
,
5665 #if HAVE_DECL_CURLINFO_PRIVATE
5666 case 21: /* CURLINFO_PRIVATE */
5667 resultType
= StringValue
;
5669 curlResult
= curl_easy_getinfo(connection
->connection
,
5675 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5676 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5677 resultType
= LongValue
;
5679 curlResult
= curl_easy_getinfo(connection
->connection
,
5680 CURLINFO_HTTP_CONNECTCODE
,
5685 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5686 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5687 resultType
= LongValue
;
5689 curlResult
= curl_easy_getinfo(connection
->connection
,
5690 CURLINFO_HTTPAUTH_AVAIL
,
5695 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5696 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5697 resultType
= LongValue
;
5699 curlResult
= curl_easy_getinfo(connection
->connection
,
5700 CURLINFO_PROXYAUTH_AVAIL
,
5705 #if HAVE_DECL_CURLINFO_OS_ERRNO
5706 case 25: /* CURLINFO_OS_ERRNO */
5707 resultType
= LongValue
;
5709 curlResult
= curl_easy_getinfo(connection
->connection
,
5715 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5716 case 26: /* CURLINFO_NUM_CONNECTS */
5717 resultType
= LongValue
;
5719 curlResult
= curl_easy_getinfo(connection
->connection
,
5720 CURLINFO_NUM_CONNECTS
,
5725 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5726 case 27: /* CURLINFO_SSL_ENGINES */
5727 resultType
= StringListValue
;
5729 curlResult
= curl_easy_getinfo(connection
->connection
,
5730 CURLINFO_SSL_ENGINES
,
5735 #if HAVE_DECL_CURLINFO_COOKIELIST
5736 case 28: /* CURLINFO_COOKIELIST */
5737 resultType
= StringListValue
;
5739 curlResult
= curl_easy_getinfo(connection
->connection
,
5740 CURLINFO_COOKIELIST
,
5745 #if HAVE_DECL_CURLINFO_LASTSOCKET
5746 case 29: /* CURLINFO_LASTSOCKET */
5747 resultType
= LongValue
;
5749 curlResult
= curl_easy_getinfo(connection
->connection
,
5750 CURLINFO_LASTSOCKET
,
5755 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5756 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5757 resultType
= StringValue
;
5759 curlResult
= curl_easy_getinfo(connection
->connection
,
5760 CURLINFO_FTP_ENTRY_PATH
,
5765 #if HAVE_DECL_CURLINFO_REDIRECT_URL
5766 case 31: /* CURLINFO_REDIRECT_URL */
5767 resultType
= StringValue
;
5769 curlResult
= curl_easy_getinfo(connection
->connection
,
5770 CURLINFO_REDIRECT_URL
,
5774 #pragma message("libcurl does not provide CURLINFO_REDIRECT_URL")
5777 #if HAVE_DECL_CURLINFO_PRIMARY_IP
5778 case 32: /* CURLINFO_PRIMARY_IP */
5779 resultType
= StringValue
;
5781 curlResult
= curl_easy_getinfo(connection
->connection
,
5782 CURLINFO_PRIMARY_IP
,
5786 #pragma message("libcurl does not provide CURLINFO_PRIMARY_IP")
5789 #if HAVE_DECL_CURLINFO_LOCAL_IP
5790 case 33: /* CURLINFO_LOCAL_IP */
5791 resultType
= StringValue
;
5793 curlResult
= curl_easy_getinfo(connection
->connection
,
5798 #pragma message("libcurl does not provide CURLINFO_LOCAL_IP")
5801 #if HAVE_DECL_CURLINFO_LOCAL_PORT
5802 case 34: /* CURLINFO_LOCAL_PORT */
5803 resultType
= LongValue
;
5805 curlResult
= curl_easy_getinfo(connection
->connection
,
5806 CURLINFO_LOCAL_PORT
,
5810 #pragma message("libcurl does not provide CURLINFO_LOCAL_PORT")
5813 #if HAVE_DECL_CURLINFO_CONDITION_UNMET
5814 case 35: /* CURLINFO_CONDITION_UNMET */
5815 resultType
= LongValue
;
5817 curlResult
= curl_easy_getinfo(connection
->connection
,
5818 CURLINFO_CONDITION_UNMET
,
5822 #pragma message("libcurl does not provide CURLINFO_CONDITION_UNMET")
5826 failwith("Invalid CURLINFO Option");
5830 if (curlResult
!= CURLE_OK
)
5831 raiseError(connection
, curlResult
);
5836 result
= alloc(1, StringValue
);
5837 Store_field(result
, 0, copy_string(strValue
?strValue
:""));
5841 result
= alloc(1, LongValue
);
5842 Store_field(result
, 0, Val_long(longValue
));
5846 result
= alloc(1, DoubleValue
);
5847 Store_field(result
, 0, copy_double(doubleValue
));
5850 case StringListValue
:
5851 result
= alloc(1, StringListValue
);
5852 Store_field(result
, 0, convertStringList(stringListValue
));
5860 ** curl_escape helper function
5863 CAMLprim value
helper_curl_escape(value str
)
5869 curlResult
= curl_escape(String_val(str
), string_length(str
));
5870 result
= copy_string(curlResult
);
5877 ** curl_unescape helper function
5880 CAMLprim value
helper_curl_unescape(value str
)
5886 curlResult
= curl_unescape(String_val(str
), string_length(str
));
5887 result
= copy_string(curlResult
);
5894 ** curl_getdate helper function
5897 CAMLprim value
helper_curl_getdate(value str
, value now
)
5899 CAMLparam2(str
, now
);
5904 curlNow
= (time_t)Double_val(now
);
5905 curlResult
= curl_getdate(String_val(str
), &curlNow
);
5906 result
= copy_double((double)curlResult
);
5912 ** curl_version helper function
5915 CAMLprim value
helper_curl_version(void)
5921 str
= curl_version();
5922 result
= copy_string(str
);
5927 struct CURLVersionBitsMapping
5933 struct CURLVersionBitsMapping versionBitsMap
[] =
5935 {CURL_VERSION_IPV6
, "ipv6"},
5936 {CURL_VERSION_KERBEROS4
, "kerberos4"},
5937 {CURL_VERSION_SSL
, "ssl"},
5938 {CURL_VERSION_LIBZ
, "libz"},
5939 {CURL_VERSION_NTLM
, "ntlm"},
5940 {CURL_VERSION_GSSNEGOTIATE
, "gssnegotiate"},
5941 {CURL_VERSION_DEBUG
, "debug"},
5942 {CURL_VERSION_CURLDEBUG
, "curldebug"},
5943 {CURL_VERSION_ASYNCHDNS
, "asynchdns"},
5944 {CURL_VERSION_SPNEGO
, "spnego"},
5945 {CURL_VERSION_LARGEFILE
, "largefile"},
5946 {CURL_VERSION_IDN
, "idn"},
5947 {CURL_VERSION_SSPI
, "sspi"},
5948 {CURL_VERSION_CONV
, "conv"},
5949 #if HAVE_DECL_CURL_VERSION_TLSAUTH_SRP
5950 {CURL_VERSION_TLSAUTH_SRP
, "srp"},
5952 #if HAVE_DECL_CURL_VERSION_NTLM_WB
5953 {CURL_VERSION_NTLM_WB
, "wb"},
5957 CAMLprim value
caml_curl_version_info(value unit
)
5960 CAMLlocal4(v
, vlist
, vnum
, vfeatures
);
5961 const char* const* p
= NULL
;
5964 curl_version_info_data
* data
= curl_version_info(CURLVERSION_NOW
);
5965 if (NULL
== data
) caml_failwith("curl_version_info");
5967 vlist
= Val_emptylist
;
5968 for (p
= data
->protocols
; NULL
!= *p
; p
++)
5970 vlist
= Val_cons(vlist
, caml_copy_string(*p
));
5973 vfeatures
= Val_emptylist
;
5974 for (i
= 0; i
< sizeof(versionBitsMap
)/sizeof(versionBitsMap
[0]); i
++)
5976 if (0 != (versionBitsMap
[i
].code
& data
->features
))
5977 vfeatures
= Val_cons(vfeatures
, caml_copy_string(versionBitsMap
[i
].name
));
5980 vnum
= caml_alloc_tuple(3);
5981 Store_field(vnum
,0,Val_int(0xFF & (data
->version_num
>> 16)));
5982 Store_field(vnum
,1,Val_int(0xFF & (data
->version_num
>> 8)));
5983 Store_field(vnum
,2,Val_int(0xFF & (data
->version_num
)));
5985 v
= caml_alloc_tuple(12);
5986 Store_field(v
,0,caml_copy_string(data
->version
));
5987 Store_field(v
,1,vnum
);
5988 Store_field(v
,2,caml_copy_string(data
->host
));
5989 Store_field(v
,3,vfeatures
);
5990 Store_field(v
,4,data
->ssl_version
? Val_some(caml_copy_string(data
->ssl_version
)) : Val_none
);
5991 Store_field(v
,5,data
->libz_version
? Val_some(caml_copy_string(data
->libz_version
)) : Val_none
);
5992 Store_field(v
,6,vlist
);
5993 Store_field(v
,7,caml_copy_string((data
->age
>= 1 && data
->ares
) ? data
->ares
: ""));
5994 Store_field(v
,8,Val_int((data
->age
>= 1) ? data
->ares_num
: 0));
5995 Store_field(v
,9,caml_copy_string((data
->age
>= 2 && data
->libidn
) ? data
->libidn
: ""));
5996 Store_field(v
,10,Val_int((data
->age
>= 3) ? data
->iconv_ver_num
: 0));
5997 Store_field(v
,11,caml_copy_string((data
->age
>= 3 && data
->libssh_version
) ? data
->libssh_version
: ""));
6002 CAMLprim value
caml_curl_pause(value conn
, value opts
)
6004 CAMLparam2(conn
, opts
);
6005 CAMLlocal4(v
, vlist
, vnum
, vfeatures
);
6006 Connection
*connection
= Connection_val(conn
);
6010 while (Val_emptylist
!= opts
)
6012 switch (Int_val(Field(opts
,0)))
6014 case 0: bitmask
|= CURLPAUSE_SEND
; break;
6015 case 1: bitmask
|= CURLPAUSE_RECV
; break;
6016 case 2: bitmask
|= CURLPAUSE_ALL
; break;
6017 default: caml_failwith("wrong pauseOption");
6019 opts
= Field(opts
,1);
6022 result
= curl_easy_pause(connection
->connection
,bitmask
);
6023 if (result
!= CURLE_OK
)
6024 raiseError(connection
, result
);
6026 CAMLreturn(Val_unit
);
6030 * Curl multi stack support
6032 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
6033 * Other exported functions are prefixed with caml_curlm_, some of them
6034 * can/should be decomposed into smaller parts.
6037 struct ml_multi_handle
6040 value values
; /* callbacks */
6045 curlmopt_socket_function
,
6046 curlmopt_timer_function
,
6048 /* last, not used */
6052 typedef struct ml_multi_handle ml_multi_handle
;
6054 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
6055 #define CURLM_val(v) (Multi_val(v)->handle)
6057 static struct custom_operations curl_multi_ops
= {
6059 custom_finalize_default
,
6060 custom_compare_default
,
6061 custom_hash_default
,
6062 custom_serialize_default
,
6063 custom_deserialize_default
,
6064 #if defined(custom_compare_ext_default)
6065 custom_compare_ext_default
,
6069 CAMLprim value
caml_curl_multi_init(value unit
)
6073 ml_multi_handle
* multi
= (ml_multi_handle
*)caml_stat_alloc(sizeof(ml_multi_handle
));
6074 CURLM
* h
= curl_multi_init();
6078 caml_stat_free(multi
);
6079 failwith("caml_curl_multi_init");
6083 multi
->values
= caml_alloc(multi_values_total
, 0);
6084 caml_register_generational_global_root(&multi
->values
);
6086 v
= caml_alloc_custom(&curl_multi_ops
, sizeof(ml_multi_handle
*), 0, 1);
6087 Multi_val(v
) = multi
;
6092 CAMLprim value
caml_curl_multi_cleanup(value handle
)
6095 ml_multi_handle
* h
= Multi_val(handle
);
6098 CAMLreturn(Val_unit
);
6100 caml_remove_generational_global_root(&h
->values
);
6102 if (CURLM_OK
!= curl_multi_cleanup(h
->handle
))
6103 failwith("caml_curl_multi_cleanup");
6105 Multi_val(handle
) = (ml_multi_handle
*)NULL
;
6107 CAMLreturn(Val_unit
);
6110 static CURL
* curlm_remove_finished(CURLM
* multi_handle
, CURLcode
* result
)
6112 int msgs_in_queue
= 0;
6116 CURLMsg
* msg
= curl_multi_info_read(multi_handle
, &msgs_in_queue
);
6117 if (NULL
== msg
) return NULL
;
6118 if (CURLMSG_DONE
== msg
->msg
)
6120 CURL
* easy_handle
= msg
->easy_handle
;
6121 if (result
) *result
= msg
->data
.result
;
6122 if (CURLM_OK
!= curl_multi_remove_handle(multi_handle
, easy_handle
))
6124 /*failwith("curlm_remove_finished");*/
6131 CAMLprim value
caml_curlm_remove_finished(value v_multi
)
6133 CAMLparam1(v_multi
);
6134 CAMLlocal2(v_easy
, v_tuple
);
6136 CURLM
* multi_handle
;
6138 Connection
* conn
= NULL
;
6140 multi_handle
= CURLM_val(v_multi
);
6142 caml_enter_blocking_section();
6143 handle
= curlm_remove_finished(multi_handle
,&result
);
6144 caml_leave_blocking_section();
6148 CAMLreturn(Val_none
);
6152 conn
= findConnection(handle
);
6153 if (conn
->errorBuffer
!= NULL
)
6155 Store_field(Field(conn
->ocamlValues
, OcamlErrorBuffer
), 0, caml_copy_string(conn
->errorBuffer
));
6158 /* NB: same handle, but different block */
6159 v_easy
= caml_curl_alloc(conn
);
6160 v_tuple
= caml_alloc(2, 0);
6161 Store_field(v_tuple
,0,v_easy
);
6162 Store_field(v_tuple
,1,Val_int(result
)); /* CURLcode */
6163 CAMLreturn(Val_some(v_tuple
));
6167 static int curlm_wait_data(CURLM
* multi_handle
)
6169 struct timeval timeout
;
6181 /* set a suitable timeout */
6183 timeout
.tv_usec
= 0;
6185 /* get file descriptors from the transfers */
6186 ret
= curl_multi_fdset(multi_handle
, &fdread
, &fdwrite
, &fdexcep
, &maxfd
);
6188 if (ret
== CURLM_OK
&& maxfd
>= 0)
6190 int rc
= select(maxfd
+1, &fdread
, &fdwrite
, &fdexcep
, &timeout
);
6191 if (-1 != rc
) return 0;
6196 CAMLprim value
caml_curlm_wait_data(value v_multi
)
6198 CAMLparam1(v_multi
);
6200 CURLM
* h
= CURLM_val(v_multi
);
6202 caml_enter_blocking_section();
6203 ret
= curlm_wait_data(h
);
6204 caml_leave_blocking_section();
6206 CAMLreturn(Val_bool(0 == ret
));
6209 CAMLprim value
caml_curl_multi_add_handle(value v_multi
, value v_easy
)
6211 CAMLparam2(v_multi
,v_easy
);
6212 CURLM
* multi
= CURLM_val(v_multi
);
6213 Connection
* conn
= Connection_val(v_easy
);
6215 /* prevent collection of OCaml value while the easy handle is used
6216 and may invoke callbacks registered on OCaml side */
6219 /* may invoke callbacks so need to be consistent with locks */
6220 caml_enter_blocking_section();
6221 if (CURLM_OK
!= curl_multi_add_handle(multi
, conn
->connection
))
6223 conn
->refcount
--; /* not added, revert */
6224 caml_leave_blocking_section();
6225 failwith("caml_curl_multi_add_handle");
6227 caml_leave_blocking_section();
6229 CAMLreturn(Val_unit
);
6232 CAMLprim value
caml_curl_multi_remove_handle(value v_multi
, value v_easy
)
6234 CAMLparam2(v_multi
,v_easy
);
6235 CURLM
* multi
= CURLM_val(v_multi
);
6236 Connection
* conn
= Connection_val(v_easy
);
6238 /* may invoke callbacks so need to be consistent with locks */
6239 caml_enter_blocking_section();
6240 if (CURLM_OK
!= curl_multi_remove_handle(multi
, conn
->connection
))
6242 caml_leave_blocking_section();
6243 failwith("caml_curl_multi_remove_handle");
6246 caml_leave_blocking_section();
6248 CAMLreturn(Val_unit
);
6251 CAMLprim value
caml_curl_multi_perform_all(value v_multi
)
6253 CAMLparam1(v_multi
);
6254 int still_running
= 0;
6255 CURLM
* h
= CURLM_val(v_multi
);
6257 caml_enter_blocking_section();
6258 while (CURLM_CALL_MULTI_PERFORM
== curl_multi_perform(h
, &still_running
));
6259 caml_leave_blocking_section();
6261 CAMLreturn(Val_int(still_running
));
6264 CAMLprim value
helper_curl_easy_strerror(value v_code
)
6267 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code
))));
6271 * Wrappers for the curl_multi_socket_action infrastructure
6272 * Based on curl hiperfifo.c example
6277 #define Val_socket(v) win_alloc_socket(v)
6280 #error Socket_val not defined in unixsupport.h
6284 #define Socket_val(v) Long_val(v)
6287 #define Val_socket(v) Val_int(v)
6291 static void raise_multi_error(char const* msg
)
6293 static value
* exception
= NULL
;
6295 if (NULL
== exception
)
6297 exception
= caml_named_value("Curl.Multi.Error");
6298 if (NULL
== exception
) caml_invalid_argument("Curl.Multi.Error");
6301 caml_raise_with_string(*exception
, msg
);
6304 static void check_mcode(CURLMcode code
)
6306 char const *s
= NULL
;
6309 case CURLM_OK
: return;
6310 case CURLM_CALL_MULTI_PERFORM
: s
="CURLM_CALL_MULTI_PERFORM"; break;
6311 case CURLM_BAD_HANDLE
: s
="CURLM_BAD_HANDLE"; break;
6312 case CURLM_BAD_EASY_HANDLE
: s
="CURLM_BAD_EASY_HANDLE"; break;
6313 case CURLM_OUT_OF_MEMORY
: s
="CURLM_OUT_OF_MEMORY"; break;
6314 case CURLM_INTERNAL_ERROR
: s
="CURLM_INTERNAL_ERROR"; break;
6315 case CURLM_UNKNOWN_OPTION
: s
="CURLM_UNKNOWN_OPTION"; break;
6316 case CURLM_LAST
: s
="CURLM_LAST"; break;
6317 case CURLM_BAD_SOCKET
: s
="CURLM_BAD_SOCKET"; break;
6318 default : s
="CURLM_unknown"; break;
6320 raise_multi_error(s
);
6323 CAMLprim value
caml_curl_multi_socket_action(value v_multi
, value v_fd
, value v_kind
)
6325 CAMLparam3(v_multi
, v_fd
, v_kind
);
6326 CURLM
* h
= CURLM_val(v_multi
);
6327 int still_running
= 0;
6328 CURLMcode rc
= CURLM_OK
;
6329 curl_socket_t socket
;
6332 if (Val_none
== v_fd
)
6334 socket
= CURL_SOCKET_TIMEOUT
;
6338 socket
= Socket_val(Field(v_fd
, 0));
6341 switch (Int_val(v_kind
))
6344 case 1 : kind
|= CURL_CSELECT_IN
; break;
6345 case 2 : kind
|= CURL_CSELECT_OUT
; break;
6346 case 3 : kind
|= CURL_CSELECT_IN
| CURL_CSELECT_OUT
; break;
6348 raise_multi_error("caml_curl_multi_socket_action");
6351 /* fprintf(stdout,"fd %u kind %u\n",socket, kind); fflush(stdout); */
6353 caml_enter_blocking_section();
6355 rc
= curl_multi_socket_action(h
, socket
, kind
, &still_running
);
6356 } while (rc
== CURLM_CALL_MULTI_PERFORM
);
6357 caml_leave_blocking_section();
6361 CAMLreturn(Val_int(still_running
));
6364 CAMLprim value
caml_curl_multi_socket_all(value v_multi
)
6366 CAMLparam1(v_multi
);
6367 int still_running
= 0;
6368 CURLMcode rc
= CURLM_OK
;
6369 CURLM
* h
= CURLM_val(v_multi
);
6371 caml_enter_blocking_section();
6373 rc
= curl_multi_socket_all(h
, &still_running
);
6374 } while (rc
== CURLM_CALL_MULTI_PERFORM
);
6375 caml_leave_blocking_section();
6379 CAMLreturn(Val_int(still_running
));
6382 static int curlm_sock_cb_nolock(CURL
*e
, curl_socket_t sock
, int what
, ml_multi_handle
* multi
, void *sockp
)
6385 CAMLlocal2(v_what
,csock
);
6387 (void)sockp
; /* not used */
6389 /* v_what = Val_int(what); */
6392 case CURL_POLL_NONE
: v_what
= Val_int(0); break;
6393 case CURL_POLL_IN
: v_what
= Val_int(1); break;
6394 case CURL_POLL_OUT
: v_what
= Val_int(2); break;
6395 case CURL_POLL_INOUT
: v_what
= Val_int(3); break;
6396 case CURL_POLL_REMOVE
: v_what
= Val_int(4); break;
6398 fprintf(stderr
, "curlm_sock_cb sock=%d what=%d\n", sock
, what
);
6400 raise_multi_error("curlm_sock_cb"); /* FIXME exception from callback */
6402 csock
=Val_socket(sock
);
6403 caml_callback2(Field(multi
->values
,curlmopt_socket_function
),
6409 static int curlm_sock_cb(CURL
*e
, curl_socket_t sock
, int what
, void *cbp
, void *sockp
)
6412 caml_leave_blocking_section();
6413 ret
= curlm_sock_cb_nolock(e
, sock
, what
, (ml_multi_handle
*)cbp
, sockp
);
6414 caml_enter_blocking_section();
6418 CAMLprim value
caml_curl_multi_socketfunction(value v_multi
, value v_cb
)
6420 CAMLparam2(v_multi
, v_cb
);
6421 ml_multi_handle
* multi
= Multi_val(v_multi
);
6423 Store_field(multi
->values
, curlmopt_socket_function
, v_cb
);
6425 curl_multi_setopt(multi
->handle
, CURLMOPT_SOCKETFUNCTION
, curlm_sock_cb
);
6426 curl_multi_setopt(multi
->handle
, CURLMOPT_SOCKETDATA
, multi
);
6428 CAMLreturn(Val_unit
);
6431 static void curlm_timer_cb_nolock(ml_multi_handle
*multi
, long timeout_ms
)
6434 caml_callback(Field(multi
->values
,curlmopt_timer_function
), Val_long(timeout_ms
));
6438 static int curlm_timer_cb(CURLM
*multi
, long timeout_ms
, void *userp
)
6442 caml_leave_blocking_section();
6443 curlm_timer_cb_nolock((ml_multi_handle
*)userp
, timeout_ms
);
6444 caml_enter_blocking_section();
6448 CAMLprim value
caml_curl_multi_timerfunction(value v_multi
, value v_cb
)
6450 CAMLparam2(v_multi
, v_cb
);
6451 ml_multi_handle
* multi
= Multi_val(v_multi
);
6453 Store_field(multi
->values
, curlmopt_timer_function
, v_cb
);
6455 curl_multi_setopt(multi
->handle
, CURLMOPT_TIMERFUNCTION
, curlm_timer_cb
);
6456 curl_multi_setopt(multi
->handle
, CURLMOPT_TIMERDATA
, multi
);
6458 CAMLreturn(Val_unit
);
6461 CAMLprim value
caml_curl_multi_timeout(value v_multi
)
6463 CAMLparam1(v_multi
);
6465 CURLMcode rc
= CURLM_OK
;
6466 ml_multi_handle
* multi
= Multi_val(v_multi
);
6468 rc
= curl_multi_timeout(multi
->handle
, &ms
);
6472 CAMLreturn(Val_long(ms
));