00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifdef HAVE_NETINET_IN_H
00026 #include <netinet/in.h>
00027 #endif
00028 #ifdef HAVE_NETDB_H
00029 #include <netdb.h>
00030 #endif
00031 #ifdef HAVE_ARPA_INET_H
00032 #include <arpa/inet.h>
00033 #endif
00034 #ifdef HAVE_NET_IF_H
00035 #include <net/if.h>
00036 #endif
00037 #ifdef HAVE_SYS_IOCTL_H
00038 #include <sys/ioctl.h>
00039 #endif
00040
00041 #ifdef HAVE_SYS_PARAM_H
00042 #include <sys/param.h>
00043 #endif
00044
00045 #ifdef __VMS
00046 #include <in.h>
00047 #include <inet.h>
00048 #endif
00049
00050 #ifdef HAVE_SYS_UN_H
00051 #include <sys/un.h>
00052 #endif
00053
00054 #ifndef HAVE_SOCKET
00055 #error "We can't compile without socket() support!"
00056 #endif
00057
00058 #ifdef HAVE_LIMITS_H
00059 #include <limits.h>
00060 #endif
00061
00062 #ifdef USE_LIBIDN2
00063 #include <idn2.h>
00064
00065 #elif defined(USE_WIN32_IDN)
00066
00067 bool curl_win32_idn_to_ascii(const char *in, char **out);
00068 #endif
00069
00070 #include "urldata.h"
00071 #include "netrc.h"
00072
00073 #include "formdata.h"
00074 #include "vtls/vtls.h"
00075 #include "hostip.h"
00076 #include "transfer.h"
00077 #include "sendf.h"
00078 #include "progress.h"
00079 #include "cookie.h"
00080 #include "strcase.h"
00081 #include "strerror.h"
00082 #include "escape.h"
00083 #include "strtok.h"
00084 #include "share.h"
00085 #include "content_encoding.h"
00086 #include "http_digest.h"
00087 #include "http_negotiate.h"
00088 #include "select.h"
00089 #include "multiif.h"
00090 #include "easyif.h"
00091 #include "speedcheck.h"
00092 #include "warnless.h"
00093 #include "non-ascii.h"
00094 #include "inet_pton.h"
00095 #include "getinfo.h"
00096
00097
00098 #include "ftp.h"
00099 #include "dict.h"
00100 #include "telnet.h"
00101 #include "tftp.h"
00102 #include "http.h"
00103 #include "http2.h"
00104 #include "file.h"
00105 #include "curl_ldap.h"
00106 #include "ssh.h"
00107 #include "imap.h"
00108 #include "url.h"
00109 #include "connect.h"
00110 #include "inet_ntop.h"
00111 #include "http_ntlm.h"
00112 #include "curl_ntlm_wb.h"
00113 #include "socks.h"
00114 #include "curl_rtmp.h"
00115 #include "gopher.h"
00116 #include "http_proxy.h"
00117 #include "conncache.h"
00118 #include "multihandle.h"
00119 #include "pipeline.h"
00120 #include "dotdot.h"
00121 #include "strdup.h"
00122
00123 #include "curl_printf.h"
00124 #include "curl_memory.h"
00125 #include "memdebug.h"
00126
00127
00128 static struct connectdata *
00129 find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
00130 struct connectbundle *bundle);
00131 static void conn_free(struct connectdata *conn);
00132 static void free_fixed_hostname(struct hostname *host);
00133 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
00134 static CURLcode parse_url_login(struct Curl_easy *data,
00135 struct connectdata *conn,
00136 char **userptr, char **passwdptr,
00137 char **optionsptr);
00138 static CURLcode parse_login_details(const char *login, const size_t len,
00139 char **userptr, char **passwdptr,
00140 char **optionsptr);
00141 static unsigned int get_protocol_family(unsigned int protocol);
00142
00143
00144
00145
00146
00147 static const struct Curl_handler * const protocols[] = {
00148
00149 #ifndef CURL_DISABLE_HTTP
00150 &Curl_handler_http,
00151 #endif
00152
00153 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
00154 &Curl_handler_https,
00155 #endif
00156
00157 #ifndef CURL_DISABLE_FTP
00158 &Curl_handler_ftp,
00159 #endif
00160
00161 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
00162 &Curl_handler_ftps,
00163 #endif
00164
00165 #ifndef CURL_DISABLE_TELNET
00166 &Curl_handler_telnet,
00167 #endif
00168
00169 #ifndef CURL_DISABLE_DICT
00170 &Curl_handler_dict,
00171 #endif
00172
00173 #ifndef CURL_DISABLE_LDAP
00174 &Curl_handler_ldap,
00175 #if !defined(CURL_DISABLE_LDAPS) && \
00176 ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
00177 (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
00178 &Curl_handler_ldaps,
00179 #endif
00180 #endif
00181
00182 #ifndef CURL_DISABLE_FILE
00183 &Curl_handler_file,
00184 #endif
00185
00186 #ifndef CURL_DISABLE_TFTP
00187 &Curl_handler_tftp,
00188 #endif
00189
00190 #ifdef USE_LIBSSH2
00191 &Curl_handler_scp,
00192 &Curl_handler_sftp,
00193 #endif
00194
00195 #ifndef CURL_DISABLE_IMAP
00196 &Curl_handler_imap,
00197 #ifdef USE_SSL
00198 &Curl_handler_imaps,
00199 #endif
00200 #endif
00201
00202 #ifndef CURL_DISABLE_POP3
00203 &Curl_handler_pop3,
00204 #ifdef USE_SSL
00205 &Curl_handler_pop3s,
00206 #endif
00207 #endif
00208
00209 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
00210 (CURL_SIZEOF_CURL_OFF_T > 4) && \
00211 (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
00212 &Curl_handler_smb,
00213 #ifdef USE_SSL
00214 &Curl_handler_smbs,
00215 #endif
00216 #endif
00217
00218 #ifndef CURL_DISABLE_SMTP
00219 &Curl_handler_smtp,
00220 #ifdef USE_SSL
00221 &Curl_handler_smtps,
00222 #endif
00223 #endif
00224
00225 #ifndef CURL_DISABLE_RTSP
00226 &Curl_handler_rtsp,
00227 #endif
00228
00229 #ifndef CURL_DISABLE_GOPHER
00230 &Curl_handler_gopher,
00231 #endif
00232
00233 #ifdef USE_LIBRTMP
00234 &Curl_handler_rtmp,
00235 &Curl_handler_rtmpt,
00236 &Curl_handler_rtmpe,
00237 &Curl_handler_rtmpte,
00238 &Curl_handler_rtmps,
00239 &Curl_handler_rtmpts,
00240 #endif
00241
00242 (struct Curl_handler *) NULL
00243 };
00244
00245
00246
00247
00248
00249 static const struct Curl_handler Curl_handler_dummy = {
00250 "<no protocol>",
00251 ZERO_NULL,
00252 ZERO_NULL,
00253 ZERO_NULL,
00254 ZERO_NULL,
00255 ZERO_NULL,
00256 ZERO_NULL,
00257 ZERO_NULL,
00258 ZERO_NULL,
00259 ZERO_NULL,
00260 ZERO_NULL,
00261 ZERO_NULL,
00262 ZERO_NULL,
00263 ZERO_NULL,
00264 0,
00265 0,
00266 PROTOPT_NONE
00267 };
00268
00269 void Curl_freeset(struct Curl_easy *data)
00270 {
00271
00272 enum dupstring i;
00273 for(i=(enum dupstring)0; i < STRING_LAST; i++) {
00274 Curl_safefree(data->set.str[i]);
00275 }
00276
00277 if(data->change.referer_alloc) {
00278 Curl_safefree(data->change.referer);
00279 data->change.referer_alloc = FALSE;
00280 }
00281 data->change.referer = NULL;
00282 if(data->change.url_alloc) {
00283 Curl_safefree(data->change.url);
00284 data->change.url_alloc = FALSE;
00285 }
00286 data->change.url = NULL;
00287 }
00288
00289 static CURLcode setstropt(char **charp, const char *s)
00290 {
00291
00292
00293
00294 Curl_safefree(*charp);
00295
00296 if(s) {
00297 char *str = strdup(s);
00298
00299 if(!str)
00300 return CURLE_OUT_OF_MEMORY;
00301
00302 *charp = str;
00303 }
00304
00305 return CURLE_OK;
00306 }
00307
00308 static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
00309 {
00310 CURLcode result = CURLE_OK;
00311 char *user = NULL;
00312 char *passwd = NULL;
00313
00314
00315
00316 if(option) {
00317 result = parse_login_details(option, strlen(option),
00318 (userp ? &user : NULL),
00319 (passwdp ? &passwd : NULL),
00320 NULL);
00321 }
00322
00323 if(!result) {
00324
00325 if(userp) {
00326 if(!user && option && option[0] == ':') {
00327
00328 user = strdup("");
00329 if(!user)
00330 result = CURLE_OUT_OF_MEMORY;
00331 }
00332
00333 Curl_safefree(*userp);
00334 *userp = user;
00335 }
00336
00337
00338 if(passwdp) {
00339 Curl_safefree(*passwdp);
00340 *passwdp = passwd;
00341 }
00342 }
00343
00344 return result;
00345 }
00346
00347 CURLcode Curl_dupset(struct Curl_easy *dst, struct Curl_easy *src)
00348 {
00349 CURLcode result = CURLE_OK;
00350 enum dupstring i;
00351
00352
00353
00354 dst->set = src->set;
00355
00356
00357 memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
00358
00359
00360 for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
00361 result = setstropt(&dst->set.str[i], src->set.str[i]);
00362 if(result)
00363 return result;
00364 }
00365
00366
00367 i = STRING_COPYPOSTFIELDS;
00368 if(src->set.postfieldsize && src->set.str[i]) {
00369
00370 dst->set.str[i] = Curl_memdup(src->set.str[i],
00371 curlx_sotouz(src->set.postfieldsize));
00372 if(!dst->set.str[i])
00373 return CURLE_OUT_OF_MEMORY;
00374
00375 dst->set.postfields = dst->set.str[i];
00376 }
00377
00378 return CURLE_OK;
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 CURLcode Curl_close(struct Curl_easy *data)
00391 {
00392 struct Curl_multi *m;
00393
00394 if(!data)
00395 return CURLE_OK;
00396
00397 Curl_expire_clear(data);
00398
00399 m = data->multi;
00400
00401 if(m)
00402
00403
00404 curl_multi_remove_handle(data->multi, data);
00405
00406 if(data->multi_easy)
00407
00408
00409 curl_multi_cleanup(data->multi_easy);
00410
00411
00412
00413
00414 if(data->state.timeoutlist) {
00415 Curl_llist_destroy(data->state.timeoutlist, NULL);
00416 data->state.timeoutlist = NULL;
00417 }
00418
00419 data->magic = 0;
00420
00421
00422
00423 if(data->state.rangestringalloc)
00424 free(data->state.range);
00425
00426
00427 Curl_safefree(data->state.pathbuffer);
00428 data->state.path = NULL;
00429
00430
00431 Curl_free_request_state(data);
00432
00433
00434 Curl_ssl_close_all(data);
00435 Curl_safefree(data->state.first_host);
00436 Curl_safefree(data->state.scratch);
00437 Curl_ssl_free_certinfo(data);
00438
00439
00440 free(data->req.newurl);
00441 data->req.newurl = NULL;
00442
00443 if(data->change.referer_alloc) {
00444 Curl_safefree(data->change.referer);
00445 data->change.referer_alloc = FALSE;
00446 }
00447 data->change.referer = NULL;
00448
00449 if(data->change.url_alloc) {
00450 Curl_safefree(data->change.url);
00451 data->change.url_alloc = FALSE;
00452 }
00453 data->change.url = NULL;
00454
00455 Curl_safefree(data->state.headerbuff);
00456
00457 Curl_flush_cookies(data, 1);
00458
00459 Curl_digest_cleanup(data);
00460
00461 Curl_safefree(data->info.contenttype);
00462 Curl_safefree(data->info.wouldredirect);
00463
00464
00465 Curl_resolver_cleanup(data->state.resolver);
00466
00467 Curl_http2_cleanup_dependencies(data);
00468 Curl_convert_close(data);
00469
00470
00471 if(data->share) {
00472 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
00473 data->share->dirty--;
00474 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
00475 }
00476
00477 if(data->set.wildcardmatch) {
00478
00479 struct WildcardData *wc = &data->wildcard;
00480 Curl_wildcard_dtor(wc);
00481 }
00482
00483 Curl_freeset(data);
00484 free(data);
00485 return CURLE_OK;
00486 }
00487
00488
00489
00490
00491
00492 CURLcode Curl_init_userdefined(struct UserDefined *set)
00493 {
00494 CURLcode result = CURLE_OK;
00495
00496 set->out = stdout;
00497 set->in_set = stdin;
00498 set->err = stderr;
00499
00500
00501 set->fwrite_func = (curl_write_callback)fwrite;
00502
00503
00504 set->fread_func_set = (curl_read_callback)fread;
00505 set->is_fread_set = 0;
00506 set->is_fwrite_set = 0;
00507
00508 set->seek_func = ZERO_NULL;
00509 set->seek_client = ZERO_NULL;
00510
00511
00512 set->convfromnetwork = ZERO_NULL;
00513 set->convtonetwork = ZERO_NULL;
00514 set->convfromutf8 = ZERO_NULL;
00515
00516 set->filesize = -1;
00517 set->postfieldsize = -1;
00518 set->maxredirs = -1;
00519
00520 set->httpreq = HTTPREQ_GET;
00521 set->rtspreq = RTSPREQ_OPTIONS;
00522 set->ftp_use_epsv = TRUE;
00523 set->ftp_use_eprt = TRUE;
00524 set->ftp_use_pret = FALSE;
00525 set->ftp_filemethod = FTPFILE_MULTICWD;
00526
00527 set->dns_cache_timeout = 60;
00528
00529
00530 set->general_ssl.max_ssl_sessions = 5;
00531
00532 set->proxyport = 0;
00533 set->proxytype = CURLPROXY_HTTP;
00534 set->httpauth = CURLAUTH_BASIC;
00535 set->proxyauth = CURLAUTH_BASIC;
00536
00537
00538 set->hide_progress = TRUE;
00539
00540
00541
00542
00543
00544 set->ssl.primary.verifypeer = TRUE;
00545 set->ssl.primary.verifyhost = TRUE;
00546 #ifdef USE_TLS_SRP
00547 set->ssl.authtype = CURL_TLSAUTH_NONE;
00548 #endif
00549 set->ssh_auth_types = CURLSSH_AUTH_DEFAULT;
00550
00551 set->general_ssl.sessionid = TRUE;
00552
00553 set->proxy_ssl = set->ssl;
00554
00555 set->new_file_perms = 0644;
00556 set->new_directory_perms = 0755;
00557
00558
00559
00560
00561 set->allowed_protocols = CURLPROTO_ALL;
00562 set->redir_protocols = CURLPROTO_ALL &
00563 ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
00564 CURLPROTO_SMBS);
00565
00566 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
00567
00568
00569
00570
00571 set->socks5_gssapi_nec = FALSE;
00572 #endif
00573
00574
00575 #if defined(CURL_CA_BUNDLE)
00576 result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
00577 if(result)
00578 return result;
00579 #endif
00580 #if defined(CURL_CA_PATH)
00581 result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
00582 if(result)
00583 return result;
00584
00585 result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
00586 (char *) CURL_CA_PATH);
00587 #endif
00588
00589 set->wildcardmatch = FALSE;
00590 set->chunk_bgn = ZERO_NULL;
00591 set->chunk_end = ZERO_NULL;
00592
00593
00594
00595
00596 set->tcp_keepalive = FALSE;
00597 set->tcp_keepintvl = 60;
00598 set->tcp_keepidle = 60;
00599 set->tcp_fastopen = FALSE;
00600 set->tcp_nodelay = TRUE;
00601
00602 set->ssl_enable_npn = TRUE;
00603 set->ssl_enable_alpn = TRUE;
00604
00605 set->expect_100_timeout = 1000L;
00606 set->sep_headers = TRUE;
00607
00608 Curl_http2_init_userset(set);
00609 return result;
00610 }
00611
00620 CURLcode Curl_open(struct Curl_easy **curl)
00621 {
00622 CURLcode result;
00623 struct Curl_easy *data;
00624
00625
00626 data = calloc(1, sizeof(struct Curl_easy));
00627 if(!data) {
00628
00629 DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
00630 return CURLE_OUT_OF_MEMORY;
00631 }
00632
00633 data->magic = CURLEASY_MAGIC_NUMBER;
00634
00635 result = Curl_resolver_init(&data->state.resolver);
00636 if(result) {
00637 DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
00638 free(data);
00639 return result;
00640 }
00641
00642
00643
00644 data->state.headerbuff = malloc(HEADERSIZE);
00645 if(!data->state.headerbuff) {
00646 DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
00647 result = CURLE_OUT_OF_MEMORY;
00648 }
00649 else {
00650 result = Curl_init_userdefined(&data->set);
00651
00652 data->state.headersize=HEADERSIZE;
00653
00654 Curl_convert_init(data);
00655
00656 Curl_initinfo(data);
00657
00658
00659 data->state.lastconnect = NULL;
00660
00661 data->progress.flags |= PGRS_HIDE;
00662 data->state.current_speed = -1;
00663
00664 data->wildcard.state = CURLWC_INIT;
00665 data->wildcard.filelist = NULL;
00666 data->set.fnmatch = ZERO_NULL;
00667 data->set.maxconnects = DEFAULT_CONNCACHE_SIZE;
00668
00669 Curl_http2_init_state(&data->state);
00670 }
00671
00672 if(result) {
00673 Curl_resolver_cleanup(data->state.resolver);
00674 free(data->state.headerbuff);
00675 Curl_freeset(data);
00676 free(data);
00677 data = NULL;
00678 }
00679 else
00680 *curl = data;
00681
00682 return result;
00683 }
00684
00685 CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
00686 va_list param)
00687 {
00688 char *argptr;
00689 CURLcode result = CURLE_OK;
00690 long arg;
00691 #ifndef CURL_DISABLE_HTTP
00692 curl_off_t bigsize;
00693 #endif
00694
00695 switch(option) {
00696 case CURLOPT_DNS_CACHE_TIMEOUT:
00697 data->set.dns_cache_timeout = va_arg(param, long);
00698 break;
00699 case CURLOPT_DNS_USE_GLOBAL_CACHE:
00700
00701 arg = va_arg(param, long);
00702 data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
00703 break;
00704 case CURLOPT_SSL_CIPHER_LIST:
00705
00706 result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
00707 va_arg(param, char *));
00708 break;
00709 case CURLOPT_PROXY_SSL_CIPHER_LIST:
00710
00711 result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
00712 va_arg(param, char *));
00713 break;
00714
00715 case CURLOPT_RANDOM_FILE:
00716
00717
00718
00719
00720 result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
00721 va_arg(param, char *));
00722 break;
00723 case CURLOPT_EGDSOCKET:
00724
00725
00726
00727 result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
00728 va_arg(param, char *));
00729 break;
00730 case CURLOPT_MAXCONNECTS:
00731
00732
00733
00734
00735 data->set.maxconnects = va_arg(param, long);
00736 break;
00737 case CURLOPT_FORBID_REUSE:
00738
00739
00740
00741
00742 data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
00743 break;
00744 case CURLOPT_FRESH_CONNECT:
00745
00746
00747
00748
00749 data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
00750 break;
00751 case CURLOPT_VERBOSE:
00752
00753
00754
00755
00756 data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
00757 break;
00758 case CURLOPT_HEADER:
00759
00760
00761
00762 data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
00763 break;
00764 case CURLOPT_NOPROGRESS:
00765
00766
00767
00768 data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
00769 if(data->set.hide_progress)
00770 data->progress.flags |= PGRS_HIDE;
00771 else
00772 data->progress.flags &= ~PGRS_HIDE;
00773 break;
00774 case CURLOPT_NOBODY:
00775
00776
00777
00778 data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
00779 break;
00780 case CURLOPT_FAILONERROR:
00781
00782
00783
00784
00785 data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
00786 break;
00787 case CURLOPT_KEEP_SENDING_ON_ERROR:
00788 data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
00789 TRUE : FALSE;
00790 break;
00791 case CURLOPT_UPLOAD:
00792 case CURLOPT_PUT:
00793
00794
00795
00796
00797 data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
00798 if(data->set.upload) {
00799
00800 data->set.httpreq = HTTPREQ_PUT;
00801 data->set.opt_no_body = FALSE;
00802 }
00803 else
00804
00805
00806 data->set.httpreq = HTTPREQ_GET;
00807 break;
00808 case CURLOPT_FILETIME:
00809
00810
00811
00812
00813 data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
00814 break;
00815 case CURLOPT_FTP_CREATE_MISSING_DIRS:
00816
00817
00818
00819
00820 switch(va_arg(param, long)) {
00821 case 0:
00822 data->set.ftp_create_missing_dirs = 0;
00823 break;
00824 case 1:
00825 data->set.ftp_create_missing_dirs = 1;
00826 break;
00827 case 2:
00828 data->set.ftp_create_missing_dirs = 2;
00829 break;
00830 default:
00831
00832 result = CURLE_UNKNOWN_OPTION;
00833 break;
00834 }
00835 break;
00836 case CURLOPT_SERVER_RESPONSE_TIMEOUT:
00837
00838
00839
00840
00841 data->set.server_response_timeout = va_arg(param, long) * 1000;
00842 break;
00843 case CURLOPT_TFTP_NO_OPTIONS:
00844
00845
00846
00847
00848 data->set.tftp_no_options = va_arg(param, long) != 0;
00849 break;
00850 case CURLOPT_TFTP_BLKSIZE:
00851
00852
00853
00854 data->set.tftp_blksize = va_arg(param, long);
00855 break;
00856 case CURLOPT_DIRLISTONLY:
00857
00858
00859
00860
00861 data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
00862 break;
00863 case CURLOPT_APPEND:
00864
00865
00866
00867 data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
00868 break;
00869 case CURLOPT_FTP_FILEMETHOD:
00870
00871
00872
00873 data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
00874 break;
00875 case CURLOPT_NETRC:
00876
00877
00878
00879 data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
00880 break;
00881 case CURLOPT_NETRC_FILE:
00882
00883
00884
00885 result = setstropt(&data->set.str[STRING_NETRC_FILE],
00886 va_arg(param, char *));
00887 break;
00888 case CURLOPT_TRANSFERTEXT:
00889
00890
00891
00892
00893
00894
00895 data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
00896 break;
00897 case CURLOPT_TIMECONDITION:
00898
00899
00900
00901
00902 data->set.timecondition = (curl_TimeCond)va_arg(param, long);
00903 break;
00904 case CURLOPT_TIMEVALUE:
00905
00906
00907
00908
00909 data->set.timevalue = (time_t)va_arg(param, long);
00910 break;
00911 case CURLOPT_SSLVERSION:
00912
00913
00914
00915
00916 #ifdef USE_SSL
00917 data->set.ssl.primary.version = va_arg(param, long);
00918 #else
00919 result = CURLE_UNKNOWN_OPTION;
00920 #endif
00921 break;
00922 case CURLOPT_PROXY_SSLVERSION:
00923
00924
00925
00926
00927 #ifdef USE_SSL
00928 data->set.proxy_ssl.primary.version = va_arg(param, long);
00929 #else
00930 result = CURLE_UNKNOWN_OPTION;
00931 #endif
00932 break;
00933
00934 #ifndef CURL_DISABLE_HTTP
00935 case CURLOPT_AUTOREFERER:
00936
00937
00938
00939 data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
00940 break;
00941
00942 case CURLOPT_ACCEPT_ENCODING:
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 argptr = va_arg(param, char *);
00953 result = setstropt(&data->set.str[STRING_ENCODING],
00954 (argptr && !*argptr)?
00955 ALL_CONTENT_ENCODINGS: argptr);
00956 break;
00957
00958 case CURLOPT_TRANSFER_ENCODING:
00959 data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
00960 TRUE : FALSE;
00961 break;
00962
00963 case CURLOPT_FOLLOWLOCATION:
00964
00965
00966
00967 data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
00968 break;
00969
00970 case CURLOPT_UNRESTRICTED_AUTH:
00971
00972
00973
00974
00975 data->set.http_disable_hostname_check_before_authentication =
00976 (0 != va_arg(param, long)) ? TRUE : FALSE;
00977 break;
00978
00979 case CURLOPT_MAXREDIRS:
00980
00981
00982
00983
00984 data->set.maxredirs = va_arg(param, long);
00985 break;
00986
00987 case CURLOPT_POSTREDIR:
00988 {
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 int postRedir = curlx_sltosi(va_arg(param, long));
00999 data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
01000 }
01001 break;
01002
01003 case CURLOPT_POST:
01004
01005
01006
01007 if(va_arg(param, long)) {
01008 data->set.httpreq = HTTPREQ_POST;
01009 data->set.opt_no_body = FALSE;
01010 }
01011 else
01012 data->set.httpreq = HTTPREQ_GET;
01013 break;
01014
01015 case CURLOPT_COPYPOSTFIELDS:
01016
01017
01018
01019
01020
01021 argptr = va_arg(param, char *);
01022
01023 if(!argptr || data->set.postfieldsize == -1)
01024 result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
01025 else {
01026
01027
01028
01029
01030 if((data->set.postfieldsize < 0) ||
01031 ((sizeof(curl_off_t) != sizeof(size_t)) &&
01032 (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
01033 result = CURLE_OUT_OF_MEMORY;
01034 else {
01035 char *p;
01036
01037 (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
01038
01039
01040
01041
01042
01043
01044 p = malloc((size_t)(data->set.postfieldsize?
01045 data->set.postfieldsize:1));
01046
01047 if(!p)
01048 result = CURLE_OUT_OF_MEMORY;
01049 else {
01050 if(data->set.postfieldsize)
01051 memcpy(p, argptr, (size_t)data->set.postfieldsize);
01052
01053 data->set.str[STRING_COPYPOSTFIELDS] = p;
01054 }
01055 }
01056 }
01057
01058 data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
01059 data->set.httpreq = HTTPREQ_POST;
01060 break;
01061
01062 case CURLOPT_POSTFIELDS:
01063
01064
01065
01066 data->set.postfields = va_arg(param, void *);
01067
01068 (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
01069 data->set.httpreq = HTTPREQ_POST;
01070 break;
01071
01072 case CURLOPT_POSTFIELDSIZE:
01073
01074
01075
01076
01077 bigsize = va_arg(param, long);
01078
01079 if(data->set.postfieldsize < bigsize &&
01080 data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
01081
01082 (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
01083 data->set.postfields = NULL;
01084 }
01085
01086 data->set.postfieldsize = bigsize;
01087 break;
01088
01089 case CURLOPT_POSTFIELDSIZE_LARGE:
01090
01091
01092
01093
01094 bigsize = va_arg(param, curl_off_t);
01095
01096 if(data->set.postfieldsize < bigsize &&
01097 data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
01098
01099 (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
01100 data->set.postfields = NULL;
01101 }
01102
01103 data->set.postfieldsize = bigsize;
01104 break;
01105
01106 case CURLOPT_HTTPPOST:
01107
01108
01109
01110 data->set.httppost = va_arg(param, struct curl_httppost *);
01111 data->set.httpreq = HTTPREQ_POST_FORM;
01112 data->set.opt_no_body = FALSE;
01113 break;
01114
01115 case CURLOPT_REFERER:
01116
01117
01118
01119 if(data->change.referer_alloc) {
01120 Curl_safefree(data->change.referer);
01121 data->change.referer_alloc = FALSE;
01122 }
01123 result = setstropt(&data->set.str[STRING_SET_REFERER],
01124 va_arg(param, char *));
01125 data->change.referer = data->set.str[STRING_SET_REFERER];
01126 break;
01127
01128 case CURLOPT_USERAGENT:
01129
01130
01131
01132 result = setstropt(&data->set.str[STRING_USERAGENT],
01133 va_arg(param, char *));
01134 break;
01135
01136 case CURLOPT_HTTPHEADER:
01137
01138
01139
01140 data->set.headers = va_arg(param, struct curl_slist *);
01141 break;
01142
01143 case CURLOPT_PROXYHEADER:
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154 data->set.proxyheaders = va_arg(param, struct curl_slist *);
01155 break;
01156
01157 case CURLOPT_HEADEROPT:
01158
01159
01160
01161 arg = va_arg(param, long);
01162 data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
01163 break;
01164
01165 case CURLOPT_HTTP200ALIASES:
01166
01167
01168
01169 data->set.http200aliases = va_arg(param, struct curl_slist *);
01170 break;
01171
01172 #if !defined(CURL_DISABLE_COOKIES)
01173 case CURLOPT_COOKIE:
01174
01175
01176
01177 result = setstropt(&data->set.str[STRING_COOKIE],
01178 va_arg(param, char *));
01179 break;
01180
01181 case CURLOPT_COOKIEFILE:
01182
01183
01184
01185 argptr = (char *)va_arg(param, void *);
01186 if(argptr) {
01187 struct curl_slist *cl;
01188
01189
01190 cl = curl_slist_append(data->change.cookielist, argptr);
01191 if(!cl) {
01192 curl_slist_free_all(data->change.cookielist);
01193 data->change.cookielist = NULL;
01194 return CURLE_OUT_OF_MEMORY;
01195 }
01196 data->change.cookielist = cl;
01197 }
01198 break;
01199
01200 case CURLOPT_COOKIEJAR:
01201
01202
01203
01204 {
01205 struct CookieInfo *newcookies;
01206 result = setstropt(&data->set.str[STRING_COOKIEJAR],
01207 va_arg(param, char *));
01208
01209
01210
01211
01212
01213 newcookies = Curl_cookie_init(data, NULL, data->cookies,
01214 data->set.cookiesession);
01215 if(!newcookies)
01216 result = CURLE_OUT_OF_MEMORY;
01217 data->cookies = newcookies;
01218 }
01219 break;
01220
01221 case CURLOPT_COOKIESESSION:
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237 data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
01238 break;
01239
01240 case CURLOPT_COOKIELIST:
01241 argptr = va_arg(param, char *);
01242
01243 if(argptr == NULL)
01244 break;
01245
01246 if(strcasecompare(argptr, "ALL")) {
01247
01248 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
01249 Curl_cookie_clearall(data->cookies);
01250 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
01251 }
01252 else if(strcasecompare(argptr, "SESS")) {
01253
01254 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
01255 Curl_cookie_clearsess(data->cookies);
01256 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
01257 }
01258 else if(strcasecompare(argptr, "FLUSH")) {
01259
01260 Curl_flush_cookies(data, 0);
01261 }
01262 else if(strcasecompare(argptr, "RELOAD")) {
01263
01264 Curl_cookie_loadfiles(data);
01265 break;
01266 }
01267 else {
01268 if(!data->cookies)
01269
01270 data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
01271
01272 argptr = strdup(argptr);
01273 if(!argptr || !data->cookies) {
01274 result = CURLE_OUT_OF_MEMORY;
01275 free(argptr);
01276 }
01277 else {
01278 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
01279
01280 if(checkprefix("Set-Cookie:", argptr))
01281
01282 Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
01283
01284 else
01285
01286 Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
01287
01288 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
01289 free(argptr);
01290 }
01291 }
01292
01293 break;
01294 #endif
01295
01296 case CURLOPT_HTTPGET:
01297
01298
01299
01300 if(va_arg(param, long)) {
01301 data->set.httpreq = HTTPREQ_GET;
01302 data->set.upload = FALSE;
01303 data->set.opt_no_body = FALSE;
01304 }
01305 break;
01306
01307 case CURLOPT_HTTP_VERSION:
01308
01309
01310
01311
01312 arg = va_arg(param, long);
01313 #ifndef USE_NGHTTP2
01314 if(arg >= CURL_HTTP_VERSION_2)
01315 return CURLE_UNSUPPORTED_PROTOCOL;
01316 #endif
01317 data->set.httpversion = arg;
01318 break;
01319
01320 case CURLOPT_HTTPAUTH:
01321
01322
01323
01324 {
01325 int bitcheck;
01326 bool authbits;
01327 unsigned long auth = va_arg(param, unsigned long);
01328
01329 if(auth == CURLAUTH_NONE) {
01330 data->set.httpauth = auth;
01331 break;
01332 }
01333
01334
01335
01336 data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
01337
01338 if(auth & CURLAUTH_DIGEST_IE) {
01339 auth |= CURLAUTH_DIGEST;
01340 auth &= ~CURLAUTH_DIGEST_IE;
01341 }
01342
01343
01344 #ifndef USE_NTLM
01345 auth &= ~CURLAUTH_NTLM;
01346 auth &= ~CURLAUTH_NTLM_WB;
01347 #elif !defined(NTLM_WB_ENABLED)
01348 auth &= ~CURLAUTH_NTLM_WB;
01349 #endif
01350 #ifndef USE_SPNEGO
01351 auth &= ~CURLAUTH_NEGOTIATE;
01352
01353 #endif
01354
01355
01356 bitcheck = 0;
01357 authbits = FALSE;
01358 while(bitcheck < 31) {
01359 if(auth & (1UL << bitcheck++)) {
01360 authbits = TRUE;
01361 break;
01362 }
01363 }
01364 if(!authbits)
01365 return CURLE_NOT_BUILT_IN;
01366
01367 data->set.httpauth = auth;
01368 }
01369 break;
01370
01371 case CURLOPT_EXPECT_100_TIMEOUT_MS:
01372
01373
01374
01375
01376 data->set.expect_100_timeout = va_arg(param, long);
01377 break;
01378
01379 #endif
01380
01381 case CURLOPT_CUSTOMREQUEST:
01382
01383
01384
01385 result = setstropt(&data->set.str[STRING_CUSTOMREQUEST],
01386 va_arg(param, char *));
01387
01388
01389
01390
01391
01392 break;
01393
01394 #ifndef CURL_DISABLE_PROXY
01395 case CURLOPT_HTTPPROXYTUNNEL:
01396
01397
01398
01399 data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
01400 TRUE : FALSE;
01401 break;
01402
01403 case CURLOPT_PROXYPORT:
01404
01405
01406
01407 data->set.proxyport = va_arg(param, long);
01408 break;
01409
01410 case CURLOPT_PROXYAUTH:
01411
01412
01413
01414 {
01415 int bitcheck;
01416 bool authbits;
01417 unsigned long auth = va_arg(param, unsigned long);
01418
01419 if(auth == CURLAUTH_NONE) {
01420 data->set.proxyauth = auth;
01421 break;
01422 }
01423
01424
01425
01426 data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
01427
01428 if(auth & CURLAUTH_DIGEST_IE) {
01429 auth |= CURLAUTH_DIGEST;
01430 auth &= ~CURLAUTH_DIGEST_IE;
01431 }
01432
01433 #ifndef USE_NTLM
01434 auth &= ~CURLAUTH_NTLM;
01435 auth &= ~CURLAUTH_NTLM_WB;
01436 #elif !defined(NTLM_WB_ENABLED)
01437 auth &= ~CURLAUTH_NTLM_WB;
01438 #endif
01439 #ifndef USE_SPNEGO
01440 auth &= ~CURLAUTH_NEGOTIATE;
01441
01442 #endif
01443
01444
01445 bitcheck = 0;
01446 authbits = FALSE;
01447 while(bitcheck < 31) {
01448 if(auth & (1UL << bitcheck++)) {
01449 authbits = TRUE;
01450 break;
01451 }
01452 }
01453 if(!authbits)
01454 return CURLE_NOT_BUILT_IN;
01455
01456 data->set.proxyauth = auth;
01457 }
01458 break;
01459
01460 case CURLOPT_PROXY:
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 result = setstropt(&data->set.str[STRING_PROXY],
01472 va_arg(param, char *));
01473 break;
01474
01475 case CURLOPT_PRE_PROXY:
01476
01477
01478
01479
01480
01481
01482 result = setstropt(&data->set.str[STRING_PRE_PROXY],
01483 va_arg(param, char *));
01484 break;
01485
01486 case CURLOPT_PROXYTYPE:
01487
01488
01489
01490 data->set.proxytype = (curl_proxytype)va_arg(param, long);
01491 break;
01492
01493 case CURLOPT_PROXY_TRANSFER_MODE:
01494
01495
01496
01497 switch(va_arg(param, long)) {
01498 case 0:
01499 data->set.proxy_transfer_mode = FALSE;
01500 break;
01501 case 1:
01502 data->set.proxy_transfer_mode = TRUE;
01503 break;
01504 default:
01505
01506 result = CURLE_UNKNOWN_OPTION;
01507 break;
01508 }
01509 break;
01510 #endif
01511
01512 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
01513 case CURLOPT_SOCKS5_GSSAPI_NEC:
01514
01515
01516
01517 data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
01518 break;
01519
01520 case CURLOPT_SOCKS5_GSSAPI_SERVICE:
01521 case CURLOPT_PROXY_SERVICE_NAME:
01522
01523
01524
01525 result = setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
01526 va_arg(param, char *));
01527 break;
01528 #endif
01529
01530 #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
01531 defined(USE_SPNEGO)
01532 case CURLOPT_SERVICE_NAME:
01533
01534
01535
01536 result = setstropt(&data->set.str[STRING_SERVICE_NAME],
01537 va_arg(param, char *));
01538 break;
01539
01540 #endif
01541
01542 case CURLOPT_HEADERDATA:
01543
01544
01545
01546 data->set.writeheader = (void *)va_arg(param, void *);
01547 break;
01548 case CURLOPT_ERRORBUFFER:
01549
01550
01551
01552
01553 data->set.errorbuffer = va_arg(param, char *);
01554 break;
01555 case CURLOPT_WRITEDATA:
01556
01557
01558
01559
01560 data->set.out = va_arg(param, void *);
01561 break;
01562 case CURLOPT_FTPPORT:
01563
01564
01565
01566 result = setstropt(&data->set.str[STRING_FTPPORT],
01567 va_arg(param, char *));
01568 data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
01569 break;
01570
01571 case CURLOPT_FTP_USE_EPRT:
01572 data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
01573 break;
01574
01575 case CURLOPT_FTP_USE_EPSV:
01576 data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
01577 break;
01578
01579 case CURLOPT_FTP_USE_PRET:
01580 data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
01581 break;
01582
01583 case CURLOPT_FTP_SSL_CCC:
01584 data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
01585 break;
01586
01587 case CURLOPT_FTP_SKIP_PASV_IP:
01588
01589
01590
01591
01592 data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
01593 break;
01594
01595 case CURLOPT_READDATA:
01596
01597
01598
01599
01600 data->set.in_set = va_arg(param, void *);
01601 break;
01602 case CURLOPT_INFILESIZE:
01603
01604
01605
01606
01607 data->set.filesize = va_arg(param, long);
01608 break;
01609 case CURLOPT_INFILESIZE_LARGE:
01610
01611
01612
01613
01614 data->set.filesize = va_arg(param, curl_off_t);
01615 break;
01616 case CURLOPT_LOW_SPEED_LIMIT:
01617
01618
01619
01620
01621 data->set.low_speed_limit=va_arg(param, long);
01622 break;
01623 case CURLOPT_MAX_SEND_SPEED_LARGE:
01624
01625
01626
01627
01628 data->set.max_send_speed=va_arg(param, curl_off_t);
01629 break;
01630 case CURLOPT_MAX_RECV_SPEED_LARGE:
01631
01632
01633
01634
01635 data->set.max_recv_speed=va_arg(param, curl_off_t);
01636 break;
01637 case CURLOPT_LOW_SPEED_TIME:
01638
01639
01640
01641
01642 data->set.low_speed_time=va_arg(param, long);
01643 break;
01644 case CURLOPT_URL:
01645
01646
01647
01648 if(data->change.url_alloc) {
01649
01650 Curl_safefree(data->change.url);
01651 data->change.url_alloc = FALSE;
01652 }
01653 result = setstropt(&data->set.str[STRING_SET_URL],
01654 va_arg(param, char *));
01655 data->change.url = data->set.str[STRING_SET_URL];
01656 break;
01657 case CURLOPT_PORT:
01658
01659
01660
01661 data->set.use_port = va_arg(param, long);
01662 break;
01663 case CURLOPT_TIMEOUT:
01664
01665
01666
01667
01668 data->set.timeout = va_arg(param, long) * 1000L;
01669 break;
01670
01671 case CURLOPT_TIMEOUT_MS:
01672 data->set.timeout = va_arg(param, long);
01673 break;
01674
01675 case CURLOPT_CONNECTTIMEOUT:
01676
01677
01678
01679 data->set.connecttimeout = va_arg(param, long) * 1000L;
01680 break;
01681
01682 case CURLOPT_CONNECTTIMEOUT_MS:
01683 data->set.connecttimeout = va_arg(param, long);
01684 break;
01685
01686 case CURLOPT_ACCEPTTIMEOUT_MS:
01687
01688
01689
01690 data->set.accepttimeout = va_arg(param, long);
01691 break;
01692
01693 case CURLOPT_USERPWD:
01694
01695
01696
01697 result = setstropt_userpwd(va_arg(param, char *),
01698 &data->set.str[STRING_USERNAME],
01699 &data->set.str[STRING_PASSWORD]);
01700 break;
01701
01702 case CURLOPT_USERNAME:
01703
01704
01705
01706 result = setstropt(&data->set.str[STRING_USERNAME],
01707 va_arg(param, char *));
01708 break;
01709
01710 case CURLOPT_PASSWORD:
01711
01712
01713
01714 result = setstropt(&data->set.str[STRING_PASSWORD],
01715 va_arg(param, char *));
01716 break;
01717
01718 case CURLOPT_LOGIN_OPTIONS:
01719
01720
01721
01722 result = setstropt(&data->set.str[STRING_OPTIONS],
01723 va_arg(param, char *));
01724 break;
01725
01726 case CURLOPT_XOAUTH2_BEARER:
01727
01728
01729
01730 result = setstropt(&data->set.str[STRING_BEARER],
01731 va_arg(param, char *));
01732 break;
01733
01734 case CURLOPT_POSTQUOTE:
01735
01736
01737
01738 data->set.postquote = va_arg(param, struct curl_slist *);
01739 break;
01740 case CURLOPT_PREQUOTE:
01741
01742
01743
01744 data->set.prequote = va_arg(param, struct curl_slist *);
01745 break;
01746 case CURLOPT_QUOTE:
01747
01748
01749
01750 data->set.quote = va_arg(param, struct curl_slist *);
01751 break;
01752 case CURLOPT_RESOLVE:
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763 data->set.resolve = va_arg(param, struct curl_slist *);
01764 data->change.resolve = data->set.resolve;
01765 break;
01766 case CURLOPT_PROGRESSFUNCTION:
01767
01768
01769
01770 data->set.fprogress = va_arg(param, curl_progress_callback);
01771 if(data->set.fprogress)
01772 data->progress.callback = TRUE;
01773 else
01774 data->progress.callback = FALSE;
01775 break;
01776
01777 case CURLOPT_XFERINFOFUNCTION:
01778
01779
01780
01781 data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
01782 if(data->set.fxferinfo)
01783 data->progress.callback = TRUE;
01784 else
01785 data->progress.callback = FALSE;
01786
01787 break;
01788
01789 case CURLOPT_PROGRESSDATA:
01790
01791
01792
01793 data->set.progress_client = va_arg(param, void *);
01794 break;
01795
01796 #ifndef CURL_DISABLE_PROXY
01797 case CURLOPT_PROXYUSERPWD:
01798
01799
01800
01801 result = setstropt_userpwd(va_arg(param, char *),
01802 &data->set.str[STRING_PROXYUSERNAME],
01803 &data->set.str[STRING_PROXYPASSWORD]);
01804 break;
01805 case CURLOPT_PROXYUSERNAME:
01806
01807
01808
01809 result = setstropt(&data->set.str[STRING_PROXYUSERNAME],
01810 va_arg(param, char *));
01811 break;
01812 case CURLOPT_PROXYPASSWORD:
01813
01814
01815
01816 result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
01817 va_arg(param, char *));
01818 break;
01819 case CURLOPT_NOPROXY:
01820
01821
01822
01823 result = setstropt(&data->set.str[STRING_NOPROXY],
01824 va_arg(param, char *));
01825 break;
01826 #endif
01827
01828 case CURLOPT_RANGE:
01829
01830
01831
01832 result = setstropt(&data->set.str[STRING_SET_RANGE],
01833 va_arg(param, char *));
01834 break;
01835 case CURLOPT_RESUME_FROM:
01836
01837
01838
01839 data->set.set_resume_from = va_arg(param, long);
01840 break;
01841 case CURLOPT_RESUME_FROM_LARGE:
01842
01843
01844
01845 data->set.set_resume_from = va_arg(param, curl_off_t);
01846 break;
01847 case CURLOPT_DEBUGFUNCTION:
01848
01849
01850
01851 data->set.fdebug = va_arg(param, curl_debug_callback);
01852
01853
01854
01855 break;
01856 case CURLOPT_DEBUGDATA:
01857
01858
01859
01860
01861 data->set.debugdata = va_arg(param, void *);
01862 break;
01863 case CURLOPT_STDERR:
01864
01865
01866
01867
01868 data->set.err = va_arg(param, FILE *);
01869 if(!data->set.err)
01870 data->set.err = stderr;
01871 break;
01872 case CURLOPT_HEADERFUNCTION:
01873
01874
01875
01876 data->set.fwrite_header = va_arg(param, curl_write_callback);
01877 break;
01878 case CURLOPT_WRITEFUNCTION:
01879
01880
01881
01882 data->set.fwrite_func = va_arg(param, curl_write_callback);
01883 if(!data->set.fwrite_func) {
01884 data->set.is_fwrite_set = 0;
01885
01886 data->set.fwrite_func = (curl_write_callback)fwrite;
01887 }
01888 else
01889 data->set.is_fwrite_set = 1;
01890 break;
01891 case CURLOPT_READFUNCTION:
01892
01893
01894
01895 data->set.fread_func_set = va_arg(param, curl_read_callback);
01896 if(!data->set.fread_func_set) {
01897 data->set.is_fread_set = 0;
01898
01899 data->set.fread_func_set = (curl_read_callback)fread;
01900 }
01901 else
01902 data->set.is_fread_set = 1;
01903 break;
01904 case CURLOPT_SEEKFUNCTION:
01905
01906
01907
01908 data->set.seek_func = va_arg(param, curl_seek_callback);
01909 break;
01910 case CURLOPT_SEEKDATA:
01911
01912
01913
01914 data->set.seek_client = va_arg(param, void *);
01915 break;
01916 case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
01917
01918
01919
01920 data->set.convfromnetwork = va_arg(param, curl_conv_callback);
01921 break;
01922 case CURLOPT_CONV_TO_NETWORK_FUNCTION:
01923
01924
01925
01926 data->set.convtonetwork = va_arg(param, curl_conv_callback);
01927 break;
01928 case CURLOPT_CONV_FROM_UTF8_FUNCTION:
01929
01930
01931
01932 data->set.convfromutf8 = va_arg(param, curl_conv_callback);
01933 break;
01934 case CURLOPT_IOCTLFUNCTION:
01935
01936
01937
01938 data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
01939 break;
01940 case CURLOPT_IOCTLDATA:
01941
01942
01943
01944 data->set.ioctl_client = va_arg(param, void *);
01945 break;
01946 case CURLOPT_SSLCERT:
01947
01948
01949
01950 result = setstropt(&data->set.str[STRING_CERT_ORIG],
01951 va_arg(param, char *));
01952 break;
01953 case CURLOPT_PROXY_SSLCERT:
01954
01955
01956
01957 result = setstropt(&data->set.str[STRING_CERT_PROXY],
01958 va_arg(param, char *));
01959 break;
01960 case CURLOPT_SSLCERTTYPE:
01961
01962
01963
01964 result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
01965 va_arg(param, char *));
01966 break;
01967 case CURLOPT_PROXY_SSLCERTTYPE:
01968
01969
01970
01971 result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
01972 va_arg(param, char *));
01973 break;
01974 case CURLOPT_SSLKEY:
01975
01976
01977
01978 result = setstropt(&data->set.str[STRING_KEY_ORIG],
01979 va_arg(param, char *));
01980 break;
01981 case CURLOPT_PROXY_SSLKEY:
01982
01983
01984
01985 result = setstropt(&data->set.str[STRING_KEY_PROXY],
01986 va_arg(param, char *));
01987 break;
01988 case CURLOPT_SSLKEYTYPE:
01989
01990
01991
01992 result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
01993 va_arg(param, char *));
01994 break;
01995 case CURLOPT_PROXY_SSLKEYTYPE:
01996
01997
01998
01999 result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
02000 va_arg(param, char *));
02001 break;
02002 case CURLOPT_KEYPASSWD:
02003
02004
02005
02006 result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
02007 va_arg(param, char *));
02008 break;
02009 case CURLOPT_PROXY_KEYPASSWD:
02010
02011
02012
02013 result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
02014 va_arg(param, char *));
02015 break;
02016 case CURLOPT_SSLENGINE:
02017
02018
02019
02020 argptr = va_arg(param, char *);
02021 if(argptr && argptr[0])
02022 result = Curl_ssl_set_engine(data, argptr);
02023 break;
02024
02025 case CURLOPT_SSLENGINE_DEFAULT:
02026
02027
02028
02029 result = Curl_ssl_set_engine_default(data);
02030 break;
02031 case CURLOPT_CRLF:
02032
02033
02034
02035 data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
02036 break;
02037
02038 case CURLOPT_INTERFACE:
02039
02040
02041
02042
02043 result = setstropt(&data->set.str[STRING_DEVICE],
02044 va_arg(param, char *));
02045 break;
02046 case CURLOPT_LOCALPORT:
02047
02048
02049
02050 data->set.localport = curlx_sltous(va_arg(param, long));
02051 break;
02052 case CURLOPT_LOCALPORTRANGE:
02053
02054
02055
02056 data->set.localportrange = curlx_sltosi(va_arg(param, long));
02057 break;
02058 case CURLOPT_KRBLEVEL:
02059
02060
02061
02062 result = setstropt(&data->set.str[STRING_KRB_LEVEL],
02063 va_arg(param, char *));
02064 data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
02065 break;
02066 case CURLOPT_GSSAPI_DELEGATION:
02067
02068
02069
02070 data->set.gssapi_delegation = va_arg(param, long);
02071 break;
02072 case CURLOPT_SSL_VERIFYPEER:
02073
02074
02075
02076 data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
02077 TRUE : FALSE;
02078 break;
02079 case CURLOPT_PROXY_SSL_VERIFYPEER:
02080
02081
02082
02083 data->set.proxy_ssl.primary.verifypeer =
02084 (0 != va_arg(param, long))?TRUE:FALSE;
02085 break;
02086 case CURLOPT_SSL_VERIFYHOST:
02087
02088
02089
02090 arg = va_arg(param, long);
02091
02092
02093
02094
02095
02096
02097 if(1 == arg) {
02098 failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
02099 return CURLE_BAD_FUNCTION_ARGUMENT;
02100 }
02101
02102 data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
02103 break;
02104 case CURLOPT_PROXY_SSL_VERIFYHOST:
02105
02106
02107
02108 arg = va_arg(param, long);
02109
02110
02111
02112
02113
02114
02115 if(1 == arg) {
02116 failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
02117 return CURLE_BAD_FUNCTION_ARGUMENT;
02118 }
02119
02120 data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
02121 break;
02122 case CURLOPT_SSL_VERIFYSTATUS:
02123
02124
02125
02126 if(!Curl_ssl_cert_status_request()) {
02127 result = CURLE_NOT_BUILT_IN;
02128 break;
02129 }
02130
02131 data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
02132 TRUE : FALSE;
02133 break;
02134 case CURLOPT_SSL_CTX_FUNCTION:
02135 #ifdef have_curlssl_ssl_ctx
02136
02137
02138
02139 data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
02140 #else
02141 result = CURLE_NOT_BUILT_IN;
02142 #endif
02143 break;
02144 case CURLOPT_SSL_CTX_DATA:
02145 #ifdef have_curlssl_ssl_ctx
02146
02147
02148
02149 data->set.ssl.fsslctxp = va_arg(param, void *);
02150 #else
02151 result = CURLE_NOT_BUILT_IN;
02152 #endif
02153 break;
02154 case CURLOPT_SSL_FALSESTART:
02155
02156
02157
02158 if(!Curl_ssl_false_start()) {
02159 result = CURLE_NOT_BUILT_IN;
02160 break;
02161 }
02162
02163 data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
02164 break;
02165 case CURLOPT_CERTINFO:
02166 #ifdef have_curlssl_certinfo
02167 data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
02168 #else
02169 result = CURLE_NOT_BUILT_IN;
02170 #endif
02171 break;
02172 case CURLOPT_PINNEDPUBLICKEY:
02173 #ifdef have_curlssl_pinnedpubkey
02174
02175
02176
02177
02178 result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
02179 va_arg(param, char *));
02180 #else
02181 result = CURLE_NOT_BUILT_IN;
02182 #endif
02183 break;
02184 case CURLOPT_PROXY_PINNEDPUBLICKEY:
02185 #ifdef have_curlssl_pinnedpubkey
02186
02187
02188
02189
02190 result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
02191 va_arg(param, char *));
02192 #else
02193 result = CURLE_NOT_BUILT_IN;
02194 #endif
02195 break;
02196 case CURLOPT_CAINFO:
02197
02198
02199
02200 result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
02201 va_arg(param, char *));
02202 break;
02203 case CURLOPT_PROXY_CAINFO:
02204
02205
02206
02207
02208 result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
02209 va_arg(param, char *));
02210 break;
02211 case CURLOPT_CAPATH:
02212 #ifdef have_curlssl_ca_path
02213
02214
02215
02216
02217
02218 result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
02219 va_arg(param, char *));
02220 break;
02221 case CURLOPT_PROXY_CAPATH:
02222
02223
02224
02225
02226
02227 result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
02228 va_arg(param, char *));
02229 #else
02230 result = CURLE_NOT_BUILT_IN;
02231 #endif
02232 break;
02233 case CURLOPT_CRLFILE:
02234
02235
02236
02237
02238 result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
02239 va_arg(param, char *));
02240 break;
02241 case CURLOPT_PROXY_CRLFILE:
02242
02243
02244
02245
02246 result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
02247 va_arg(param, char *));
02248 break;
02249 case CURLOPT_ISSUERCERT:
02250
02251
02252
02253
02254 result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
02255 va_arg(param, char *));
02256 break;
02257 case CURLOPT_TELNETOPTIONS:
02258
02259
02260
02261 data->set.telnet_options = va_arg(param, struct curl_slist *);
02262 break;
02263
02264 case CURLOPT_BUFFERSIZE:
02265
02266
02267
02268
02269 data->set.buffer_size = va_arg(param, long);
02270
02271 if((data->set.buffer_size> (BUFSIZE -1)) ||
02272 (data->set.buffer_size < 1))
02273 data->set.buffer_size = 0;
02274
02275 break;
02276
02277 case CURLOPT_NOSIGNAL:
02278
02279
02280
02281
02282 data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
02283 break;
02284
02285 case CURLOPT_SHARE:
02286 {
02287 struct Curl_share *set;
02288 set = va_arg(param, struct Curl_share *);
02289
02290
02291 if(data->share) {
02292 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
02293
02294 if(data->dns.hostcachetype == HCACHE_SHARED) {
02295 data->dns.hostcache = NULL;
02296 data->dns.hostcachetype = HCACHE_NONE;
02297 }
02298
02299 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
02300 if(data->share->cookies == data->cookies)
02301 data->cookies = NULL;
02302 #endif
02303
02304 if(data->share->sslsession == data->state.session)
02305 data->state.session = NULL;
02306
02307 data->share->dirty--;
02308
02309 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
02310 data->share = NULL;
02311 }
02312
02313
02314 data->share = set;
02315 if(data->share) {
02316
02317 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
02318
02319 data->share->dirty++;
02320
02321 if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
02322
02323 data->dns.hostcache = &data->share->hostcache;
02324 data->dns.hostcachetype = HCACHE_SHARED;
02325 }
02326 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
02327 if(data->share->cookies) {
02328
02329 Curl_cookie_cleanup(data->cookies);
02330
02331 data->cookies = data->share->cookies;
02332 }
02333 #endif
02334 if(data->share->sslsession) {
02335 data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
02336 data->state.session = data->share->sslsession;
02337 }
02338 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
02339
02340 }
02341
02342
02343 }
02344 break;
02345
02346 case CURLOPT_PRIVATE:
02347
02348
02349
02350 data->set.private_data = va_arg(param, void *);
02351 break;
02352
02353 case CURLOPT_MAXFILESIZE:
02354
02355
02356
02357 data->set.max_filesize = va_arg(param, long);
02358 break;
02359
02360 #ifdef USE_SSL
02361 case CURLOPT_USE_SSL:
02362
02363
02364
02365 data->set.use_ssl = (curl_usessl)va_arg(param, long);
02366 break;
02367
02368 case CURLOPT_SSL_OPTIONS:
02369 arg = va_arg(param, long);
02370 data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
02371 data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
02372 break;
02373
02374 case CURLOPT_PROXY_SSL_OPTIONS:
02375 arg = va_arg(param, long);
02376 data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
02377 data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
02378 break;
02379
02380 #endif
02381 case CURLOPT_FTPSSLAUTH:
02382
02383
02384
02385 data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
02386 break;
02387
02388 case CURLOPT_IPRESOLVE:
02389 data->set.ipver = va_arg(param, long);
02390 break;
02391
02392 case CURLOPT_MAXFILESIZE_LARGE:
02393
02394
02395
02396 data->set.max_filesize = va_arg(param, curl_off_t);
02397 break;
02398
02399 case CURLOPT_TCP_NODELAY:
02400
02401
02402
02403
02404 data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
02405 break;
02406
02407 case CURLOPT_FTP_ACCOUNT:
02408 result = setstropt(&data->set.str[STRING_FTP_ACCOUNT],
02409 va_arg(param, char *));
02410 break;
02411
02412 case CURLOPT_IGNORE_CONTENT_LENGTH:
02413 data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
02414 break;
02415
02416 case CURLOPT_CONNECT_ONLY:
02417
02418
02419
02420 data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
02421 break;
02422
02423 case CURLOPT_FTP_ALTERNATIVE_TO_USER:
02424 result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
02425 va_arg(param, char *));
02426 break;
02427
02428 case CURLOPT_SOCKOPTFUNCTION:
02429
02430
02431
02432 data->set.fsockopt = va_arg(param, curl_sockopt_callback);
02433 break;
02434
02435 case CURLOPT_SOCKOPTDATA:
02436
02437
02438
02439 data->set.sockopt_client = va_arg(param, void *);
02440 break;
02441
02442 case CURLOPT_OPENSOCKETFUNCTION:
02443
02444
02445
02446
02447 data->set.fopensocket = va_arg(param, curl_opensocket_callback);
02448 break;
02449
02450 case CURLOPT_OPENSOCKETDATA:
02451
02452
02453
02454 data->set.opensocket_client = va_arg(param, void *);
02455 break;
02456
02457 case CURLOPT_CLOSESOCKETFUNCTION:
02458
02459
02460
02461
02462 data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
02463 break;
02464
02465 case CURLOPT_CLOSESOCKETDATA:
02466
02467
02468
02469 data->set.closesocket_client = va_arg(param, void *);
02470 break;
02471
02472 case CURLOPT_SSL_SESSIONID_CACHE:
02473 data->set.general_ssl.sessionid = (0 != va_arg(param, long)) ?
02474 TRUE : FALSE;
02475 break;
02476
02477 #ifdef USE_LIBSSH2
02478
02479 case CURLOPT_SSH_AUTH_TYPES:
02480 data->set.ssh_auth_types = va_arg(param, long);
02481 break;
02482
02483 case CURLOPT_SSH_PUBLIC_KEYFILE:
02484
02485
02486
02487 result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
02488 va_arg(param, char *));
02489 break;
02490
02491 case CURLOPT_SSH_PRIVATE_KEYFILE:
02492
02493
02494
02495 result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
02496 va_arg(param, char *));
02497 break;
02498 case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
02499
02500
02501
02502
02503 result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
02504 va_arg(param, char *));
02505 break;
02506 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
02507 case CURLOPT_SSH_KNOWNHOSTS:
02508
02509
02510
02511 result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
02512 va_arg(param, char *));
02513 break;
02514
02515 case CURLOPT_SSH_KEYFUNCTION:
02516
02517
02518 data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
02519 break;
02520
02521 case CURLOPT_SSH_KEYDATA:
02522
02523
02524
02525 data->set.ssh_keyfunc_userp = va_arg(param, void *);
02526 break;
02527 #endif
02528
02529 #endif
02530
02531 case CURLOPT_HTTP_TRANSFER_DECODING:
02532
02533
02534
02535 data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
02536 break;
02537
02538 case CURLOPT_HTTP_CONTENT_DECODING:
02539
02540
02541
02542 data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
02543 break;
02544
02545 case CURLOPT_NEW_FILE_PERMS:
02546
02547
02548
02549 data->set.new_file_perms = va_arg(param, long);
02550 break;
02551
02552 case CURLOPT_NEW_DIRECTORY_PERMS:
02553
02554
02555
02556 data->set.new_directory_perms = va_arg(param, long);
02557 break;
02558
02559 case CURLOPT_ADDRESS_SCOPE:
02560
02561
02562
02563
02564
02565 data->set.scope_id = curlx_sltoui(va_arg(param, long));
02566 break;
02567
02568 case CURLOPT_PROTOCOLS:
02569
02570
02571
02572
02573 data->set.allowed_protocols = va_arg(param, long);
02574 break;
02575
02576 case CURLOPT_REDIR_PROTOCOLS:
02577
02578
02579
02580
02581 data->set.redir_protocols = va_arg(param, long);
02582 break;
02583
02584 case CURLOPT_DEFAULT_PROTOCOL:
02585
02586 result = setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
02587 va_arg(param, char *));
02588 break;
02589
02590 case CURLOPT_MAIL_FROM:
02591
02592 result = setstropt(&data->set.str[STRING_MAIL_FROM],
02593 va_arg(param, char *));
02594 break;
02595
02596 case CURLOPT_MAIL_AUTH:
02597
02598 result = setstropt(&data->set.str[STRING_MAIL_AUTH],
02599 va_arg(param, char *));
02600 break;
02601
02602 case CURLOPT_MAIL_RCPT:
02603
02604 data->set.mail_rcpt = va_arg(param, struct curl_slist *);
02605 break;
02606
02607 case CURLOPT_SASL_IR:
02608
02609 data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
02610 break;
02611
02612 case CURLOPT_RTSP_REQUEST:
02613 {
02614
02615
02616
02617
02618 long curl_rtspreq = va_arg(param, long);
02619 Curl_RtspReq rtspreq = RTSPREQ_NONE;
02620 switch(curl_rtspreq) {
02621 case CURL_RTSPREQ_OPTIONS:
02622 rtspreq = RTSPREQ_OPTIONS;
02623 break;
02624
02625 case CURL_RTSPREQ_DESCRIBE:
02626 rtspreq = RTSPREQ_DESCRIBE;
02627 break;
02628
02629 case CURL_RTSPREQ_ANNOUNCE:
02630 rtspreq = RTSPREQ_ANNOUNCE;
02631 break;
02632
02633 case CURL_RTSPREQ_SETUP:
02634 rtspreq = RTSPREQ_SETUP;
02635 break;
02636
02637 case CURL_RTSPREQ_PLAY:
02638 rtspreq = RTSPREQ_PLAY;
02639 break;
02640
02641 case CURL_RTSPREQ_PAUSE:
02642 rtspreq = RTSPREQ_PAUSE;
02643 break;
02644
02645 case CURL_RTSPREQ_TEARDOWN:
02646 rtspreq = RTSPREQ_TEARDOWN;
02647 break;
02648
02649 case CURL_RTSPREQ_GET_PARAMETER:
02650 rtspreq = RTSPREQ_GET_PARAMETER;
02651 break;
02652
02653 case CURL_RTSPREQ_SET_PARAMETER:
02654 rtspreq = RTSPREQ_SET_PARAMETER;
02655 break;
02656
02657 case CURL_RTSPREQ_RECORD:
02658 rtspreq = RTSPREQ_RECORD;
02659 break;
02660
02661 case CURL_RTSPREQ_RECEIVE:
02662 rtspreq = RTSPREQ_RECEIVE;
02663 break;
02664 default:
02665 rtspreq = RTSPREQ_NONE;
02666 }
02667
02668 data->set.rtspreq = rtspreq;
02669 break;
02670 }
02671
02672
02673 case CURLOPT_RTSP_SESSION_ID:
02674
02675
02676
02677
02678 result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
02679 va_arg(param, char *));
02680 break;
02681
02682 case CURLOPT_RTSP_STREAM_URI:
02683
02684
02685
02686
02687 result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
02688 va_arg(param, char *));
02689 break;
02690
02691 case CURLOPT_RTSP_TRANSPORT:
02692
02693
02694
02695 result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
02696 va_arg(param, char *));
02697 break;
02698
02699 case CURLOPT_RTSP_CLIENT_CSEQ:
02700
02701
02702
02703
02704
02705 data->state.rtsp_next_client_CSeq = va_arg(param, long);
02706 break;
02707
02708 case CURLOPT_RTSP_SERVER_CSEQ:
02709
02710 data->state.rtsp_next_client_CSeq = va_arg(param, long);
02711 break;
02712
02713 case CURLOPT_INTERLEAVEDATA:
02714 data->set.rtp_out = va_arg(param, void *);
02715 break;
02716 case CURLOPT_INTERLEAVEFUNCTION:
02717
02718 data->set.fwrite_rtp = va_arg(param, curl_write_callback);
02719 break;
02720
02721 case CURLOPT_WILDCARDMATCH:
02722 data->set.wildcardmatch = (0 != va_arg(param, long)) ? TRUE : FALSE;
02723 break;
02724 case CURLOPT_CHUNK_BGN_FUNCTION:
02725 data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
02726 break;
02727 case CURLOPT_CHUNK_END_FUNCTION:
02728 data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
02729 break;
02730 case CURLOPT_FNMATCH_FUNCTION:
02731 data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
02732 break;
02733 case CURLOPT_CHUNK_DATA:
02734 data->wildcard.customptr = va_arg(param, void *);
02735 break;
02736 case CURLOPT_FNMATCH_DATA:
02737 data->set.fnmatch_data = va_arg(param, void *);
02738 break;
02739 #ifdef USE_TLS_SRP
02740 case CURLOPT_TLSAUTH_USERNAME:
02741 result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
02742 va_arg(param, char *));
02743 if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
02744 data->set.ssl.authtype = CURL_TLSAUTH_SRP;
02745 break;
02746 case CURLOPT_PROXY_TLSAUTH_USERNAME:
02747 result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
02748 va_arg(param, char *));
02749 if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
02750 !data->set.proxy_ssl.authtype)
02751 data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
02752 break;
02753 case CURLOPT_TLSAUTH_PASSWORD:
02754 result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
02755 va_arg(param, char *));
02756 if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
02757 data->set.ssl.authtype = CURL_TLSAUTH_SRP;
02758 break;
02759 case CURLOPT_PROXY_TLSAUTH_PASSWORD:
02760 result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
02761 va_arg(param, char *));
02762 if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
02763 !data->set.proxy_ssl.authtype)
02764 data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
02765 break;
02766 case CURLOPT_TLSAUTH_TYPE:
02767 if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
02768 data->set.ssl.authtype = CURL_TLSAUTH_SRP;
02769 else
02770 data->set.ssl.authtype = CURL_TLSAUTH_NONE;
02771 break;
02772 case CURLOPT_PROXY_TLSAUTH_TYPE:
02773 if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
02774 data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
02775 else
02776 data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
02777 break;
02778 #endif
02779 case CURLOPT_DNS_SERVERS:
02780 result = Curl_set_dns_servers(data, va_arg(param, char *));
02781 break;
02782 case CURLOPT_DNS_INTERFACE:
02783 result = Curl_set_dns_interface(data, va_arg(param, char *));
02784 break;
02785 case CURLOPT_DNS_LOCAL_IP4:
02786 result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
02787 break;
02788 case CURLOPT_DNS_LOCAL_IP6:
02789 result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
02790 break;
02791
02792 case CURLOPT_TCP_KEEPALIVE:
02793 data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
02794 break;
02795 case CURLOPT_TCP_KEEPIDLE:
02796 data->set.tcp_keepidle = va_arg(param, long);
02797 break;
02798 case CURLOPT_TCP_KEEPINTVL:
02799 data->set.tcp_keepintvl = va_arg(param, long);
02800 break;
02801 case CURLOPT_TCP_FASTOPEN:
02802 #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
02803 data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
02804 #else
02805 result = CURLE_NOT_BUILT_IN;
02806 #endif
02807 break;
02808 case CURLOPT_SSL_ENABLE_NPN:
02809 data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
02810 break;
02811 case CURLOPT_SSL_ENABLE_ALPN:
02812 data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
02813 break;
02814
02815 #ifdef USE_UNIX_SOCKETS
02816 case CURLOPT_UNIX_SOCKET_PATH:
02817 result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
02818 va_arg(param, char *));
02819 break;
02820 #endif
02821
02822 case CURLOPT_PATH_AS_IS:
02823 data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
02824 break;
02825 case CURLOPT_PIPEWAIT:
02826 data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
02827 break;
02828 case CURLOPT_STREAM_WEIGHT:
02829 #ifndef USE_NGHTTP2
02830 return CURLE_NOT_BUILT_IN;
02831 #else
02832 arg = va_arg(param, long);
02833 if((arg>=1) && (arg <= 256))
02834 data->set.stream_weight = (int)arg;
02835 break;
02836 #endif
02837 case CURLOPT_STREAM_DEPENDS:
02838 case CURLOPT_STREAM_DEPENDS_E:
02839 {
02840 #ifndef USE_NGHTTP2
02841 return CURLE_NOT_BUILT_IN;
02842 #else
02843 struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
02844 if(!dep || GOOD_EASY_HANDLE(dep)) {
02845 if(data->set.stream_depends_on) {
02846 Curl_http2_remove_child(data->set.stream_depends_on, data);
02847 }
02848 Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
02849 }
02850 break;
02851 #endif
02852 }
02853 case CURLOPT_CONNECT_TO:
02854 data->set.connect_to = va_arg(param, struct curl_slist *);
02855 break;
02856 default:
02857
02858 result = CURLE_UNKNOWN_OPTION;
02859 break;
02860 }
02861
02862 return result;
02863 }
02864
02865 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
02866 static void conn_reset_postponed_data(struct connectdata *conn, int num)
02867 {
02868 struct postponed_data * const psnd = &(conn->postponed[num]);
02869 if(psnd->buffer) {
02870 DEBUGASSERT(psnd->allocated_size > 0);
02871 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
02872 DEBUGASSERT(psnd->recv_size ?
02873 (psnd->recv_processed < psnd->recv_size) :
02874 (psnd->recv_processed == 0));
02875 DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
02876 free(psnd->buffer);
02877 psnd->buffer = NULL;
02878 psnd->allocated_size = 0;
02879 psnd->recv_size = 0;
02880 psnd->recv_processed = 0;
02881 #ifdef DEBUGBUILD
02882 psnd->bindsock = CURL_SOCKET_BAD;
02883 #endif
02884 }
02885 else {
02886 DEBUGASSERT(psnd->allocated_size == 0);
02887 DEBUGASSERT(psnd->recv_size == 0);
02888 DEBUGASSERT(psnd->recv_processed == 0);
02889 DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
02890 }
02891 }
02892
02893 static void conn_reset_all_postponed_data(struct connectdata *conn)
02894 {
02895 conn_reset_postponed_data(conn, 0);
02896 conn_reset_postponed_data(conn, 1);
02897 }
02898 #else
02899
02900 #define conn_reset_postponed_data(c,n) do {} WHILE_FALSE
02901 #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
02902 #endif
02903
02904 static void conn_free(struct connectdata *conn)
02905 {
02906 if(!conn)
02907 return;
02908
02909
02910 Curl_resolver_cancel(conn);
02911
02912
02913
02914 Curl_ssl_close(conn, FIRSTSOCKET);
02915 Curl_ssl_close(conn, SECONDARYSOCKET);
02916
02917
02918 if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
02919 Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
02920 if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
02921 Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
02922 if(CURL_SOCKET_BAD != conn->tempsock[0])
02923 Curl_closesocket(conn, conn->tempsock[0]);
02924 if(CURL_SOCKET_BAD != conn->tempsock[1])
02925 Curl_closesocket(conn, conn->tempsock[1]);
02926
02927 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
02928 defined(NTLM_WB_ENABLED)
02929 Curl_ntlm_wb_cleanup(conn);
02930 #endif
02931
02932 Curl_safefree(conn->user);
02933 Curl_safefree(conn->passwd);
02934 Curl_safefree(conn->oauth_bearer);
02935 Curl_safefree(conn->options);
02936 Curl_safefree(conn->http_proxy.user);
02937 Curl_safefree(conn->socks_proxy.user);
02938 Curl_safefree(conn->http_proxy.passwd);
02939 Curl_safefree(conn->socks_proxy.passwd);
02940 Curl_safefree(conn->allocptr.proxyuserpwd);
02941 Curl_safefree(conn->allocptr.uagent);
02942 Curl_safefree(conn->allocptr.userpwd);
02943 Curl_safefree(conn->allocptr.accept_encoding);
02944 Curl_safefree(conn->allocptr.te);
02945 Curl_safefree(conn->allocptr.rangeline);
02946 Curl_safefree(conn->allocptr.ref);
02947 Curl_safefree(conn->allocptr.host);
02948 Curl_safefree(conn->allocptr.cookiehost);
02949 Curl_safefree(conn->allocptr.rtsp_transport);
02950 Curl_safefree(conn->trailer);
02951 Curl_safefree(conn->host.rawalloc);
02952 Curl_safefree(conn->conn_to_host.rawalloc);
02953 Curl_safefree(conn->secondaryhostname);
02954 Curl_safefree(conn->http_proxy.host.rawalloc);
02955 Curl_safefree(conn->socks_proxy.host.rawalloc);
02956 Curl_safefree(conn->master_buffer);
02957
02958 conn_reset_all_postponed_data(conn);
02959
02960 Curl_llist_destroy(conn->send_pipe, NULL);
02961 Curl_llist_destroy(conn->recv_pipe, NULL);
02962
02963 conn->send_pipe = NULL;
02964 conn->recv_pipe = NULL;
02965
02966 Curl_safefree(conn->localdev);
02967 Curl_free_primary_ssl_config(&conn->ssl_config);
02968 Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
02969
02970 #ifdef USE_UNIX_SOCKETS
02971 Curl_safefree(conn->unix_domain_socket);
02972 #endif
02973
02974 free(conn);
02975 }
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987 CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
02988 {
02989 struct Curl_easy *data;
02990 if(!conn)
02991 return CURLE_OK;
02992 data = conn->data;
02993
02994 if(!data) {
02995 DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
02996 return CURLE_OK;
02997 }
02998
02999
03000
03001
03002
03003 if(!conn->bits.close &&
03004 (conn->send_pipe->size + conn->recv_pipe->size)) {
03005 DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n",
03006 conn->send_pipe->size + conn->recv_pipe->size));
03007 return CURLE_OK;
03008 }
03009
03010 if(conn->dns_entry != NULL) {
03011 Curl_resolv_unlock(data, conn->dns_entry);
03012 conn->dns_entry = NULL;
03013 }
03014
03015 Curl_hostcache_prune(data);
03016
03017 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
03018
03019 Curl_http_ntlm_cleanup(conn);
03020 #endif
03021
03022 if(conn->handler->disconnect)
03023
03024 conn->handler->disconnect(conn, dead_connection);
03025
03026
03027 infof(data, "Closing connection %ld\n", conn->connection_id);
03028 Curl_conncache_remove_conn(data->state.conn_cache, conn);
03029
03030 free_fixed_hostname(&conn->host);
03031 free_fixed_hostname(&conn->conn_to_host);
03032 free_fixed_hostname(&conn->proxy);
03033 free_fixed_hostname(&conn->http_proxy.host);
03034 free_fixed_hostname(&conn->socks_proxy.host);
03035
03036 Curl_ssl_close(conn, FIRSTSOCKET);
03037
03038
03039 if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) {
03040 signalPipeClose(conn->send_pipe, TRUE);
03041 signalPipeClose(conn->recv_pipe, TRUE);
03042 }
03043
03044 conn_free(conn);
03045
03046 return CURLE_OK;
03047 }
03048
03049
03050
03051
03052
03053
03054 static bool SocketIsDead(curl_socket_t sock)
03055 {
03056 int sval;
03057 bool ret_val = TRUE;
03058
03059 sval = SOCKET_READABLE(sock, 0);
03060 if(sval == 0)
03061
03062 ret_val = FALSE;
03063
03064 return ret_val;
03065 }
03066
03067
03068
03069
03070
03071 static bool IsPipeliningPossible(const struct Curl_easy *handle,
03072 const struct connectdata *conn)
03073 {
03074
03075 if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
03076 (!conn->bits.protoconnstart || !conn->bits.close)) {
03077
03078 if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
03079 (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
03080 (handle->set.httpreq == HTTPREQ_GET ||
03081 handle->set.httpreq == HTTPREQ_HEAD))
03082
03083 return TRUE;
03084
03085 if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
03086 (handle->set.httpversion >= CURL_HTTP_VERSION_2))
03087
03088 return TRUE;
03089 }
03090 return FALSE;
03091 }
03092
03093 int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
03094 struct curl_llist *pipeline)
03095 {
03096 if(pipeline) {
03097 struct curl_llist_element *curr;
03098
03099 curr = pipeline->head;
03100 while(curr) {
03101 if(curr->ptr == handle) {
03102 Curl_llist_remove(pipeline, curr, NULL);
03103 return 1;
03104 }
03105 curr = curr->next;
03106 }
03107 }
03108
03109 return 0;
03110 }
03111
03112 #if 0
03113 static void Curl_printPipeline(struct curl_llist *pipeline)
03114 {
03115 struct curl_llist_element *curr;
03116
03117 curr = pipeline->head;
03118 while(curr) {
03119 struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
03120 infof(data, "Handle in pipeline: %s\n", data->state.path);
03121 curr = curr->next;
03122 }
03123 }
03124 #endif
03125
03126 static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
03127 {
03128 struct curl_llist_element *curr = pipeline->head;
03129 if(curr) {
03130 return (struct Curl_easy *) curr->ptr;
03131 }
03132
03133 return NULL;
03134 }
03135
03136
03137
03138 void Curl_getoff_all_pipelines(struct Curl_easy *data,
03139 struct connectdata *conn)
03140 {
03141 bool recv_head = (conn->readchannel_inuse &&
03142 Curl_recvpipe_head(data, conn));
03143 bool send_head = (conn->writechannel_inuse &&
03144 Curl_sendpipe_head(data, conn));
03145
03146 if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
03147 Curl_pipeline_leave_read(conn);
03148 if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head)
03149 Curl_pipeline_leave_write(conn);
03150 }
03151
03152 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
03153 {
03154 struct curl_llist_element *curr;
03155
03156 if(!pipeline)
03157 return;
03158
03159 curr = pipeline->head;
03160 while(curr) {
03161 struct curl_llist_element *next = curr->next;
03162 struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
03163
03164 #ifdef DEBUGBUILD
03165 if(data->magic != CURLEASY_MAGIC_NUMBER) {
03166
03167 infof(data, "signalPipeClose() found BAAD easy handle\n");
03168 }
03169 #endif
03170
03171 if(pipe_broke)
03172 data->state.pipe_broke = TRUE;
03173 Curl_multi_handlePipeBreak(data);
03174 Curl_llist_remove(pipeline, curr, NULL);
03175 curr = next;
03176 }
03177 }
03178
03179
03180
03181
03182
03183
03184
03185
03186 struct connectdata *
03187 Curl_oldest_idle_connection(struct Curl_easy *data)
03188 {
03189 struct conncache *bc = data->state.conn_cache;
03190 struct curl_hash_iterator iter;
03191 struct curl_llist_element *curr;
03192 struct curl_hash_element *he;
03193 time_t highscore=-1;
03194 time_t score;
03195 struct timeval now;
03196 struct connectdata *conn_candidate = NULL;
03197 struct connectbundle *bundle;
03198
03199 now = Curl_tvnow();
03200
03201 Curl_hash_start_iterate(&bc->hash, &iter);
03202
03203 he = Curl_hash_next_element(&iter);
03204 while(he) {
03205 struct connectdata *conn;
03206
03207 bundle = he->ptr;
03208
03209 curr = bundle->conn_list->head;
03210 while(curr) {
03211 conn = curr->ptr;
03212
03213 if(!conn->inuse) {
03214
03215 score = Curl_tvdiff(now, conn->now);
03216
03217 if(score > highscore) {
03218 highscore = score;
03219 conn_candidate = conn;
03220 }
03221 }
03222 curr = curr->next;
03223 }
03224
03225 he = Curl_hash_next_element(&iter);
03226 }
03227
03228 return conn_candidate;
03229 }
03230
03231 static bool
03232 proxy_info_matches(const struct proxy_info* data,
03233 const struct proxy_info* needle)
03234 {
03235 if((data->proxytype == needle->proxytype) &&
03236 (data->port == needle->port) &&
03237 Curl_safe_strcasecompare(data->host.name, needle->host.name) &&
03238 Curl_safe_strcasecompare(data->user, needle->user) &&
03239 Curl_safe_strcasecompare(data->passwd, needle->passwd))
03240 return TRUE;
03241
03242 return FALSE;
03243 }
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253 static struct connectdata *
03254 find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
03255 struct connectbundle *bundle)
03256 {
03257 struct curl_llist_element *curr;
03258 time_t highscore=-1;
03259 time_t score;
03260 struct timeval now;
03261 struct connectdata *conn_candidate = NULL;
03262 struct connectdata *conn;
03263
03264 (void)data;
03265
03266 now = Curl_tvnow();
03267
03268 curr = bundle->conn_list->head;
03269 while(curr) {
03270 conn = curr->ptr;
03271
03272 if(!conn->inuse) {
03273
03274 score = Curl_tvdiff(now, conn->now);
03275
03276 if(score > highscore) {
03277 highscore = score;
03278 conn_candidate = conn;
03279 }
03280 }
03281 curr = curr->next;
03282 }
03283
03284 return conn_candidate;
03285 }
03286
03287
03288
03289
03290
03291
03292
03293 static bool disconnect_if_dead(struct connectdata *conn,
03294 struct Curl_easy *data)
03295 {
03296 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
03297 if(!pipeLen && !conn->inuse) {
03298
03299
03300
03301 bool dead;
03302 if(conn->handler->protocol & CURLPROTO_RTSP)
03303
03304 dead = Curl_rtsp_connisdead(conn);
03305 else
03306 dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
03307
03308 if(dead) {
03309 conn->data = data;
03310 infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
03311
03312
03313 Curl_disconnect(conn, TRUE);
03314 return TRUE;
03315 }
03316 }
03317 return FALSE;
03318 }
03319
03320
03321
03322
03323
03324
03325 static int call_disconnect_if_dead(struct connectdata *conn,
03326 void *param)
03327 {
03328 struct Curl_easy* data = (struct Curl_easy*)param;
03329 disconnect_if_dead(conn, data);
03330 return 0;
03331 }
03332
03333
03334
03335
03336
03337
03338 static void prune_dead_connections(struct Curl_easy *data)
03339 {
03340 struct timeval now = Curl_tvnow();
03341 time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
03342
03343 if(elapsed >= 1000L) {
03344 Curl_conncache_foreach(data->state.conn_cache, data,
03345 call_disconnect_if_dead);
03346 data->state.conn_cache->last_cleanup = now;
03347 }
03348 }
03349
03350
03351 static size_t max_pipeline_length(struct Curl_multi *multi)
03352 {
03353 return multi ? multi->max_pipeline_length : 0;
03354 }
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369 static bool
03370 ConnectionExists(struct Curl_easy *data,
03371 struct connectdata *needle,
03372 struct connectdata **usethis,
03373 bool *force_reuse,
03374 bool *waitpipe)
03375 {
03376 struct connectdata *check;
03377 struct connectdata *chosen = 0;
03378 bool foundPendingCandidate = FALSE;
03379 bool canPipeline = IsPipeliningPossible(data, needle);
03380 struct connectbundle *bundle;
03381
03382 #ifdef USE_NTLM
03383 bool wantNTLMhttp = ((data->state.authhost.want &
03384 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
03385 (needle->handler->protocol & PROTO_FAMILY_HTTP));
03386 bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
03387 ((data->state.authproxy.want &
03388 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
03389 (needle->handler->protocol & PROTO_FAMILY_HTTP)));
03390 #endif
03391
03392 *force_reuse = FALSE;
03393 *waitpipe = FALSE;
03394
03395
03396 if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
03397 canPipeline = FALSE;
03398 }
03399
03400
03401
03402 bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
03403 if(bundle) {
03404
03405 size_t max_pipe_len = (bundle->multiuse != BUNDLE_MULTIPLEX)?
03406 max_pipeline_length(data->multi):0;
03407 size_t best_pipe_len = max_pipe_len;
03408 struct curl_llist_element *curr;
03409 const char *hostname;
03410
03411 if(needle->bits.conn_to_host)
03412 hostname = needle->conn_to_host.name;
03413 else
03414 hostname = needle->host.name;
03415
03416 infof(data, "Found bundle for host %s: %p [%s]\n",
03417 hostname, (void *)bundle,
03418 (bundle->multiuse== BUNDLE_PIPELINING?
03419 "can pipeline":
03420 (bundle->multiuse== BUNDLE_MULTIPLEX?
03421 "can multiplex":"serially")));
03422
03423
03424 if(canPipeline) {
03425 if(bundle->multiuse <= BUNDLE_UNKNOWN) {
03426 if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
03427 infof(data, "Server doesn't support multi-use yet, wait\n");
03428 *waitpipe = TRUE;
03429 return FALSE;
03430 }
03431
03432 infof(data, "Server doesn't support multi-use (yet)\n");
03433 canPipeline = FALSE;
03434 }
03435 if((bundle->multiuse == BUNDLE_PIPELINING) &&
03436 !Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
03437
03438 infof(data, "Could pipeline, but not asked to!\n");
03439 canPipeline = FALSE;
03440 }
03441 else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
03442 !Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
03443 infof(data, "Could multiplex, but not asked to!\n");
03444 canPipeline = FALSE;
03445 }
03446 }
03447
03448 curr = bundle->conn_list->head;
03449 while(curr) {
03450 bool match = FALSE;
03451 size_t pipeLen;
03452
03453
03454
03455
03456
03457 check = curr->ptr;
03458 curr = curr->next;
03459
03460 if(disconnect_if_dead(check, data))
03461 continue;
03462
03463 pipeLen = check->send_pipe->size + check->recv_pipe->size;
03464
03465 if(canPipeline) {
03466 if(check->bits.protoconnstart && check->bits.close)
03467 continue;
03468
03469 if(!check->bits.multiplex) {
03470
03471 struct Curl_easy* sh = gethandleathead(check->send_pipe);
03472 struct Curl_easy* rh = gethandleathead(check->recv_pipe);
03473 if(sh) {
03474 if(!IsPipeliningPossible(sh, check))
03475 continue;
03476 }
03477 else if(rh) {
03478 if(!IsPipeliningPossible(rh, check))
03479 continue;
03480 }
03481 }
03482 }
03483 else {
03484 if(pipeLen > 0) {
03485
03486
03487 continue;
03488 }
03489
03490 if(Curl_resolver_asynch()) {
03491
03492
03493 if(!check->ip_addr_str[0]) {
03494 infof(data,
03495 "Connection #%ld is still name resolving, can't reuse\n",
03496 check->connection_id);
03497 continue;
03498 }
03499 }
03500
03501 if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) ||
03502 check->bits.close) {
03503 if(!check->bits.close)
03504 foundPendingCandidate = TRUE;
03505
03506
03507 infof(data, "Connection #%ld isn't open enough, can't reuse\n",
03508 check->connection_id);
03509 #ifdef DEBUGBUILD
03510 if(check->recv_pipe->size > 0) {
03511 infof(data,
03512 "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
03513 check->connection_id);
03514 }
03515 #endif
03516 continue;
03517 }
03518 }
03519
03520 #ifdef USE_UNIX_SOCKETS
03521 if(needle->unix_domain_socket) {
03522 if(!check->unix_domain_socket)
03523 continue;
03524 if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
03525 continue;
03526 }
03527 else if(check->unix_domain_socket)
03528 continue;
03529 #endif
03530
03531 if((needle->handler->flags&PROTOPT_SSL) !=
03532 (check->handler->flags&PROTOPT_SSL))
03533
03534 if(get_protocol_family(check->handler->protocol) !=
03535 needle->handler->protocol || !check->tls_upgraded)
03536
03537 continue;
03538
03539 if(needle->bits.httpproxy != check->bits.httpproxy ||
03540 needle->bits.socksproxy != check->bits.socksproxy)
03541 continue;
03542
03543 if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
03544 &check->socks_proxy))
03545 continue;
03546
03547 if(needle->bits.conn_to_host != check->bits.conn_to_host)
03548
03549
03550 continue;
03551
03552 if(needle->bits.conn_to_port != check->bits.conn_to_port)
03553
03554
03555 continue;
03556
03557 if(needle->bits.httpproxy) {
03558 if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
03559 continue;
03560
03561 if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
03562 continue;
03563
03564 if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
03565
03566 if(needle->handler->flags&PROTOPT_SSL) {
03567
03568 if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
03569 &check->proxy_ssl_config))
03570 continue;
03571 if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
03572 continue;
03573 }
03574 else {
03575 if(!Curl_ssl_config_matches(&needle->ssl_config,
03576 &check->ssl_config))
03577 continue;
03578 if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
03579 continue;
03580 }
03581 }
03582 }
03583
03584 if(!canPipeline && check->inuse)
03585
03586
03587 continue;
03588
03589 if(needle->localdev || needle->localport) {
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601 if((check->localport != needle->localport) ||
03602 (check->localportrange != needle->localportrange) ||
03603 (needle->localdev &&
03604 (!check->localdev || strcmp(check->localdev, needle->localdev))))
03605 continue;
03606 }
03607
03608 if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
03609
03610
03611 if(strcmp(needle->user, check->user) ||
03612 strcmp(needle->passwd, check->passwd)) {
03613
03614 continue;
03615 }
03616 }
03617
03618 if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
03619 needle->bits.tunnel_proxy) {
03620
03621
03622
03623
03624 if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
03625 (get_protocol_family(check->handler->protocol) ==
03626 needle->handler->protocol && check->tls_upgraded)) &&
03627 (!needle->bits.conn_to_host || strcasecompare(
03628 needle->conn_to_host.name, check->conn_to_host.name)) &&
03629 (!needle->bits.conn_to_port ||
03630 needle->conn_to_port == check->conn_to_port) &&
03631 strcasecompare(needle->host.name, check->host.name) &&
03632 needle->remote_port == check->remote_port) {
03633
03634
03635
03636 if(needle->handler->flags & PROTOPT_SSL) {
03637
03638
03639 if(!Curl_ssl_config_matches(&needle->ssl_config,
03640 &check->ssl_config)) {
03641 DEBUGF(infof(data,
03642 "Connection #%ld has different SSL parameters, "
03643 "can't reuse\n",
03644 check->connection_id));
03645 continue;
03646 }
03647 else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
03648 foundPendingCandidate = TRUE;
03649 DEBUGF(infof(data,
03650 "Connection #%ld has not started SSL connect, "
03651 "can't reuse\n",
03652 check->connection_id));
03653 continue;
03654 }
03655 }
03656 match = TRUE;
03657 }
03658 }
03659 else {
03660
03661
03662 match = TRUE;
03663 }
03664
03665 if(match) {
03666 #if defined(USE_NTLM)
03667
03668
03669
03670
03671
03672 if(wantNTLMhttp) {
03673 if(strcmp(needle->user, check->user) ||
03674 strcmp(needle->passwd, check->passwd))
03675 continue;
03676 }
03677 else if(check->ntlm.state != NTLMSTATE_NONE) {
03678
03679 continue;
03680 }
03681
03682
03683 if(wantProxyNTLMhttp) {
03684
03685
03686 if(!check->http_proxy.user || !check->http_proxy.passwd)
03687 continue;
03688
03689 if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
03690 strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
03691 continue;
03692 }
03693 else if(check->proxyntlm.state != NTLMSTATE_NONE) {
03694
03695 continue;
03696 }
03697
03698 if(wantNTLMhttp || wantProxyNTLMhttp) {
03699
03700 chosen = check;
03701
03702 if((wantNTLMhttp &&
03703 (check->ntlm.state != NTLMSTATE_NONE)) ||
03704 (wantProxyNTLMhttp &&
03705 (check->proxyntlm.state != NTLMSTATE_NONE))) {
03706
03707 *force_reuse = TRUE;
03708 break;
03709 }
03710
03711
03712 continue;
03713 }
03714 #endif
03715 if(canPipeline) {
03716
03717
03718
03719
03720 if(pipeLen == 0) {
03721
03722 chosen = check;
03723 break;
03724 }
03725
03726
03727 if(max_pipe_len && (pipeLen >= max_pipe_len)) {
03728 infof(data, "Pipe is full, skip (%zu)\n", pipeLen);
03729 continue;
03730 }
03731 #ifdef USE_NGHTTP2
03732
03733 if(check->bits.multiplex) {
03734
03735 struct http_conn *httpc = &check->proto.httpc;
03736 if(pipeLen >= httpc->settings.max_concurrent_streams) {
03737 infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
03738 pipeLen);
03739 continue;
03740 }
03741 }
03742 #endif
03743
03744 if(Curl_pipeline_penalized(data, check)) {
03745 infof(data, "Penalized, skip\n");
03746 continue;
03747 }
03748
03749 if(max_pipe_len) {
03750 if(pipeLen < best_pipe_len) {
03751
03752
03753 chosen = check;
03754 best_pipe_len = pipeLen;
03755 continue;
03756 }
03757 }
03758 else {
03759
03760 chosen = check;
03761 infof(data, "Multiplexed connection found!\n");
03762 break;
03763 }
03764 }
03765 else {
03766
03767 chosen = check;
03768 break;
03769 }
03770 }
03771 }
03772 }
03773
03774 if(chosen) {
03775 *usethis = chosen;
03776 return TRUE;
03777 }
03778
03779 if(foundPendingCandidate && data->set.pipewait) {
03780 infof(data,
03781 "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
03782 *waitpipe = TRUE;
03783 }
03784
03785 return FALSE;
03786 }
03787
03788
03789
03790
03791
03792
03793
03794 CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
03795 {
03796 CURLcode result = CURLE_OK;
03797
03798 if(conn->bits.socksproxy) {
03799 #ifndef CURL_DISABLE_PROXY
03800 const char * const host = conn->bits.conn_to_host ?
03801 conn->conn_to_host.name :
03802 conn->bits.httpproxy ?
03803 conn->http_proxy.host.name :
03804 sockindex == SECONDARYSOCKET ?
03805 conn->secondaryhostname : conn->host.name;
03806 const int port = conn->bits.conn_to_port ? conn->conn_to_port :
03807 conn->bits.httpproxy ?
03808 (int)conn->http_proxy.port :
03809 sockindex == SECONDARYSOCKET ?
03810 conn->secondary_port : conn->remote_port;
03811 conn->bits.socksproxy_connecting = TRUE;
03812 switch(conn->socks_proxy.proxytype) {
03813 case CURLPROXY_SOCKS5:
03814 case CURLPROXY_SOCKS5_HOSTNAME:
03815 result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
03816 host, port, sockindex, conn);
03817 break;
03818
03819 case CURLPROXY_SOCKS4:
03820 case CURLPROXY_SOCKS4A:
03821 result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
03822 conn);
03823 break;
03824
03825 default:
03826 failf(conn->data, "unknown proxytype option given");
03827 result = CURLE_COULDNT_CONNECT;
03828 }
03829 conn->bits.socksproxy_connecting = FALSE;
03830 #else
03831 (void)sockindex;
03832 #endif
03833 }
03834
03835 return result;
03836 }
03837
03838
03839
03840
03841 #ifndef CURL_DISABLE_VERBOSE_STRINGS
03842 void Curl_verboseconnect(struct connectdata *conn)
03843 {
03844 if(conn->data->set.verbose)
03845 infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
03846 conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
03847 conn->bits.httpproxy ? conn->http_proxy.host.dispname :
03848 conn->host.dispname,
03849 conn->ip_addr_str, conn->port, conn->connection_id);
03850 }
03851 #endif
03852
03853 int Curl_protocol_getsock(struct connectdata *conn,
03854 curl_socket_t *socks,
03855 int numsocks)
03856 {
03857 if(conn->handler->proto_getsock)
03858 return conn->handler->proto_getsock(conn, socks, numsocks);
03859 return GETSOCK_BLANK;
03860 }
03861
03862 int Curl_doing_getsock(struct connectdata *conn,
03863 curl_socket_t *socks,
03864 int numsocks)
03865 {
03866 if(conn && conn->handler->doing_getsock)
03867 return conn->handler->doing_getsock(conn, socks, numsocks);
03868 return GETSOCK_BLANK;
03869 }
03870
03871
03872
03873
03874
03875
03876
03877 CURLcode Curl_protocol_connecting(struct connectdata *conn,
03878 bool *done)
03879 {
03880 CURLcode result=CURLE_OK;
03881
03882 if(conn && conn->handler->connecting) {
03883 *done = FALSE;
03884 result = conn->handler->connecting(conn, done);
03885 }
03886 else
03887 *done = TRUE;
03888
03889 return result;
03890 }
03891
03892
03893
03894
03895
03896
03897 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
03898 {
03899 CURLcode result=CURLE_OK;
03900
03901 if(conn && conn->handler->doing) {
03902 *done = FALSE;
03903 result = conn->handler->doing(conn, done);
03904 }
03905 else
03906 *done = TRUE;
03907
03908 return result;
03909 }
03910
03911
03912
03913
03914
03915
03916 CURLcode Curl_protocol_connect(struct connectdata *conn,
03917 bool *protocol_done)
03918 {
03919 CURLcode result=CURLE_OK;
03920
03921 *protocol_done = FALSE;
03922
03923 if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
03924
03925
03926
03927
03928
03929
03930 if(!conn->handler->connecting)
03931 *protocol_done = TRUE;
03932
03933 return CURLE_OK;
03934 }
03935
03936 if(!conn->bits.protoconnstart) {
03937
03938 result = Curl_proxy_connect(conn, FIRSTSOCKET);
03939 if(result)
03940 return result;
03941
03942 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
03943
03944 return CURLE_OK;
03945
03946 if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
03947 (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
03948
03949
03950 return CURLE_OK;
03951
03952 if(conn->handler->connect_it) {
03953
03954
03955
03956 result = conn->handler->connect_it(conn, protocol_done);
03957 }
03958 else
03959 *protocol_done = TRUE;
03960
03961
03962
03963 if(!result)
03964 conn->bits.protoconnstart = TRUE;
03965 }
03966
03967 return result;
03968 }
03969
03970
03971
03972
03973 static bool is_ASCII_name(const char *hostname)
03974 {
03975 const unsigned char *ch = (const unsigned char *)hostname;
03976
03977 while(*ch) {
03978 if(*ch++ & 0x80)
03979 return FALSE;
03980 }
03981 return TRUE;
03982 }
03983
03984
03985
03986
03987 static void fix_hostname(struct connectdata *conn, struct hostname *host)
03988 {
03989 size_t len;
03990 struct Curl_easy *data = conn->data;
03991
03992 #ifndef USE_LIBIDN2
03993 (void)data;
03994 (void)conn;
03995 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
03996 (void)conn;
03997 #endif
03998
03999
04000 host->dispname = host->name;
04001
04002 len = strlen(host->name);
04003 if(len && (host->name[len-1] == '.'))
04004
04005
04006 host->name[len-1]=0;
04007
04008
04009 if(!is_ASCII_name(host->name)) {
04010 #ifdef USE_LIBIDN2
04011 if(idn2_check_version(IDN2_VERSION)) {
04012 char *ace_hostname = NULL;
04013 int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, 0);
04014 if(rc == IDN2_OK) {
04015 host->encalloc = (char *)ace_hostname;
04016
04017 host->name = host->encalloc;
04018 }
04019 else
04020 infof(data, "Failed to convert %s to ACE; %s\n", host->name,
04021 idn2_strerror(rc));
04022 }
04023 #elif defined(USE_WIN32_IDN)
04024 char *ace_hostname = NULL;
04025
04026 if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
04027 host->encalloc = ace_hostname;
04028
04029 host->name = host->encalloc;
04030 }
04031 else
04032 infof(data, "Failed to convert %s to ACE;\n", host->name);
04033 #else
04034 infof(data, "IDN support not present, can't parse Unicode domains\n");
04035 #endif
04036 }
04037 }
04038
04039
04040
04041
04042 static void free_fixed_hostname(struct hostname *host)
04043 {
04044 #if defined(USE_LIBIDN2)
04045 if(host->encalloc) {
04046 idn2_free(host->encalloc);
04047
04048 host->encalloc = NULL;
04049 }
04050 #elif defined(USE_WIN32_IDN)
04051 free(host->encalloc);
04052
04053 host->encalloc = NULL;
04054 #else
04055 (void)host;
04056 #endif
04057 }
04058
04059 static void llist_dtor(void *user, void *element)
04060 {
04061 (void)user;
04062 (void)element;
04063
04064 }
04065
04066
04067
04068
04069 static struct connectdata *allocate_conn(struct Curl_easy *data)
04070 {
04071 struct connectdata *conn = calloc(1, sizeof(struct connectdata));
04072 if(!conn)
04073 return NULL;
04074
04075 conn->handler = &Curl_handler_dummy;
04076
04077
04078
04079
04080
04081 conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
04082 conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
04083 conn->tempsock[0] = CURL_SOCKET_BAD;
04084 conn->tempsock[1] = CURL_SOCKET_BAD;
04085 conn->connection_id = -1;
04086 conn->port = -1;
04087 conn->remote_port = -1;
04088 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
04089 conn->postponed[0].bindsock = CURL_SOCKET_BAD;
04090 conn->postponed[1].bindsock = CURL_SOCKET_BAD;
04091 #endif
04092
04093
04094
04095
04096 connclose(conn, "Default to force-close");
04097
04098
04099 conn->created = Curl_tvnow();
04100
04101 conn->data = data;
04102
04103
04104 conn->http_proxy.proxytype = data->set.proxytype;
04105 conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
04106
04107 #ifdef CURL_DISABLE_PROXY
04108
04109 conn->bits.proxy = FALSE;
04110 conn->bits.httpproxy = FALSE;
04111 conn->bits.socksproxy = FALSE;
04112 conn->bits.proxy_user_passwd = FALSE;
04113 conn->bits.tunnel_proxy = FALSE;
04114
04115 #else
04116
04117
04118
04119 conn->bits.proxy = (data->set.str[STRING_PROXY] &&
04120 *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
04121 conn->bits.httpproxy = (conn->bits.proxy &&
04122 (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
04123 conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
04124 conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
04125 TRUE : FALSE;
04126 conn->bits.socksproxy = (conn->bits.proxy &&
04127 !conn->bits.httpproxy) ? TRUE : FALSE;
04128
04129 if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
04130 conn->bits.proxy = TRUE;
04131 conn->bits.socksproxy = TRUE;
04132 }
04133
04134 conn->bits.proxy_user_passwd =
04135 (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
04136 conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
04137
04138 #endif
04139
04140 conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
04141 conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
04142 conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
04143
04144 conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
04145 conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
04146 conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
04147 conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
04148
04149 conn->ip_version = data->set.ipver;
04150
04151 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
04152 defined(NTLM_WB_ENABLED)
04153 conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
04154 conn->ntlm_auth_hlpr_pid = 0;
04155 conn->challenge_header = NULL;
04156 conn->response_header = NULL;
04157 #endif
04158
04159 if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
04160 !conn->master_buffer) {
04161
04162 conn->master_buffer = calloc(BUFSIZE, sizeof(char));
04163 if(!conn->master_buffer)
04164 goto error;
04165 }
04166
04167
04168 conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
04169 conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
04170 if(!conn->send_pipe || !conn->recv_pipe)
04171 goto error;
04172
04173 #ifdef HAVE_GSSAPI
04174 conn->data_prot = PROT_CLEAR;
04175 #endif
04176
04177
04178 if(data->set.str[STRING_DEVICE]) {
04179 conn->localdev = strdup(data->set.str[STRING_DEVICE]);
04180 if(!conn->localdev)
04181 goto error;
04182 }
04183 conn->localportrange = data->set.localportrange;
04184 conn->localport = data->set.localport;
04185
04186
04187
04188 conn->fclosesocket = data->set.fclosesocket;
04189 conn->closesocket_client = data->set.closesocket_client;
04190
04191 return conn;
04192 error:
04193
04194 Curl_llist_destroy(conn->send_pipe, NULL);
04195 Curl_llist_destroy(conn->recv_pipe, NULL);
04196
04197 conn->send_pipe = NULL;
04198 conn->recv_pipe = NULL;
04199
04200 free(conn->master_buffer);
04201 free(conn->localdev);
04202 free(conn);
04203 return NULL;
04204 }
04205
04206 static CURLcode findprotocol(struct Curl_easy *data,
04207 struct connectdata *conn,
04208 const char *protostr)
04209 {
04210 const struct Curl_handler * const *pp;
04211 const struct Curl_handler *p;
04212
04213
04214
04215
04216 for(pp = protocols; (p = *pp) != NULL; pp++) {
04217 if(strcasecompare(p->scheme, protostr)) {
04218
04219 if(!(data->set.allowed_protocols & p->protocol))
04220
04221 break;
04222
04223
04224
04225 if(data->state.this_is_a_follow &&
04226 !(data->set.redir_protocols & p->protocol))
04227
04228 break;
04229
04230
04231 conn->handler = conn->given = p;
04232
04233
04234 return CURLE_OK;
04235 }
04236 }
04237
04238
04239
04240
04241
04242 failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
04243 protostr);
04244
04245 return CURLE_UNSUPPORTED_PROTOCOL;
04246 }
04247
04248
04249
04250
04251 static CURLcode parseurlandfillconn(struct Curl_easy *data,
04252 struct connectdata *conn,
04253 bool *prot_missing,
04254 char **userp, char **passwdp,
04255 char **optionsp)
04256 {
04257 char *at;
04258 char *fragment;
04259 char *path = data->state.path;
04260 char *query;
04261 int rc;
04262 char protobuf[16] = "";
04263 const char *protop = "";
04264 CURLcode result;
04265 bool rebuild_url = FALSE;
04266
04267 *prot_missing = FALSE;
04268
04269
04270
04271 if(strpbrk(data->change.url, "\r\n")) {
04272 failf(data, "Illegal characters found in URL");
04273 return CURLE_URL_MALFORMAT;
04274 }
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284 if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
04285 protobuf, path)) &&
04286 strcasecompare(protobuf, "file")) {
04287 if(path[0] == '/' && path[1] == '/') {
04288
04289
04290
04291
04292
04293
04294
04295 memmove(path, path + 2, strlen(path + 2)+1);
04296 }
04297
04298
04299
04300
04301
04302 if(path[0] != '/') {
04303
04304
04305 char *ptr;
04306 if(!checkprefix("localhost/", path) &&
04307 !checkprefix("127.0.0.1/", path)) {
04308 failf(data, "Valid host name with slash missing in URL");
04309 return CURLE_URL_MALFORMAT;
04310 }
04311 ptr = &path[9];
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328 if('/' == ptr[1])
04329
04330
04331 ptr++;
04332
04333
04334 memmove(path, ptr, strlen(ptr)+1);
04335 }
04336
04337 protop = "file";
04338 }
04339 else {
04340
04341 char slashbuf[4];
04342 path[0]=0;
04343
04344 rc = sscanf(data->change.url,
04345 "%15[^\n:]:%3[/]%[^\n/?#]%[^\n]",
04346 protobuf, slashbuf, conn->host.name, path);
04347 if(2 == rc) {
04348 failf(data, "Bad URL");
04349 return CURLE_URL_MALFORMAT;
04350 }
04351 if(3 > rc) {
04352
04353
04354
04355
04356
04357 rc = sscanf(data->change.url, "%[^\n/?#]%[^\n]", conn->host.name, path);
04358 if(1 > rc) {
04359
04360
04361
04362
04363
04364 #if defined(__DJGPP__) && (DJGPP_MINOR == 4)
04365 if(!(rc == -1 && *conn->host.name))
04366 #endif
04367 {
04368 failf(data, "<url> malformed");
04369 return CURLE_URL_MALFORMAT;
04370 }
04371 }
04372
04373
04374
04375
04376
04377
04378
04379
04380 protop = data->set.str[STRING_DEFAULT_PROTOCOL];
04381 if(!protop) {
04382
04383
04384 if(checkprefix("FTP.", conn->host.name))
04385 protop = "ftp";
04386 else if(checkprefix("DICT.", conn->host.name))
04387 protop = "DICT";
04388 else if(checkprefix("LDAP.", conn->host.name))
04389 protop = "LDAP";
04390 else if(checkprefix("IMAP.", conn->host.name))
04391 protop = "IMAP";
04392 else if(checkprefix("SMTP.", conn->host.name))
04393 protop = "smtp";
04394 else if(checkprefix("POP3.", conn->host.name))
04395 protop = "pop3";
04396 else
04397 protop = "http";
04398 }
04399
04400 *prot_missing = TRUE;
04401 }
04402 else {
04403 size_t s = strlen(slashbuf);
04404 protop = protobuf;
04405 if(s != 2) {
04406 infof(data, "Unwillingly accepted illegal URL using %d slash%s!\n",
04407 s, s>1?"es":"");
04408
04409 if(data->change.url_alloc)
04410 free(data->change.url);
04411
04412 data->change.url = aprintf("%s://%s%s",
04413 protobuf, conn->host.name, path);
04414 if(!data->change.url)
04415 return CURLE_OUT_OF_MEMORY;
04416 data->change.url_alloc = TRUE;
04417 }
04418 }
04419 }
04420
04421
04422
04423
04424
04425 at = strchr(conn->host.name, '@');
04426 if(at)
04427 query = strchr(at+1, '?');
04428 else
04429 query = strchr(conn->host.name, '?');
04430
04431 if(query) {
04432
04433
04434
04435
04436
04437
04438
04439
04440 size_t hostlen = strlen(query);
04441 size_t pathlen = strlen(path);
04442
04443
04444
04445 memmove(path+hostlen+1, path, pathlen+1);
04446
04447
04448 memcpy(path+1, query, hostlen);
04449
04450 path[0]='/';
04451 rebuild_url = TRUE;
04452
04453 *query=0;
04454 }
04455 else if(!path[0]) {
04456
04457 strcpy(path, "/");
04458 rebuild_url = TRUE;
04459 }
04460
04461
04462
04463
04464
04465 if(path[0] != '/') {
04466
04467
04468
04469 memmove(&path[1], path, strlen(path)+1);
04470 path[0] = '/';
04471 rebuild_url = TRUE;
04472 }
04473 else if(!data->set.path_as_is) {
04474
04475 char *newp = Curl_dedotdotify(path);
04476 if(!newp)
04477 return CURLE_OUT_OF_MEMORY;
04478
04479 if(strcmp(newp, path)) {
04480 rebuild_url = TRUE;
04481 free(data->state.pathbuffer);
04482 data->state.pathbuffer = newp;
04483 data->state.path = newp;
04484 path = newp;
04485 }
04486 else
04487 free(newp);
04488 }
04489
04490
04491
04492
04493
04494
04495
04496 if(rebuild_url) {
04497 char *reurl;
04498
04499 size_t plen = strlen(path);
04500
04501 size_t urllen = strlen(data->change.url);
04502
04503 size_t prefixlen = strlen(conn->host.name);
04504
04505 if(!*prot_missing)
04506 prefixlen += strlen(protop) + strlen("://");
04507
04508 reurl = malloc(urllen + 2);
04509 if(!reurl)
04510 return CURLE_OUT_OF_MEMORY;
04511
04512
04513 memcpy(reurl, data->change.url, prefixlen);
04514
04515
04516 memcpy(&reurl[prefixlen], path, plen + 1);
04517
04518
04519 if(data->change.url_alloc) {
04520 Curl_safefree(data->change.url);
04521 data->change.url_alloc = FALSE;
04522 }
04523
04524 infof(data, "Rebuilt URL to: %s\n", reurl);
04525
04526 data->change.url = reurl;
04527 data->change.url_alloc = TRUE;
04528 }
04529
04530
04531
04532
04533
04534 result = parse_url_login(data, conn, userp, passwdp, optionsp);
04535 if(result)
04536 return result;
04537
04538 if(conn->host.name[0] == '[') {
04539
04540
04541 char *percent = strchr(conn->host.name, '%');
04542 if(percent) {
04543 unsigned int identifier_offset = 3;
04544 char *endp;
04545 unsigned long scope;
04546 if(strncmp("%25", percent, 3) != 0) {
04547 infof(data,
04548 "Please URL encode %% as %%25, see RFC 6874.\n");
04549 identifier_offset = 1;
04550 }
04551 scope = strtoul(percent + identifier_offset, &endp, 10);
04552 if(*endp == ']') {
04553
04554
04555 memmove(percent, endp, strlen(endp)+1);
04556 conn->scope_id = (unsigned int)scope;
04557 }
04558 else {
04559
04560 #if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX)
04561 char ifname[IFNAMSIZ + 2];
04562 char *square_bracket;
04563 unsigned int scopeidx = 0;
04564 strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2);
04565
04566 ifname[IFNAMSIZ + 1] = '\0';
04567 square_bracket = strchr(ifname, ']');
04568 if(square_bracket) {
04569
04570 *square_bracket = '\0';
04571 scopeidx = if_nametoindex(ifname);
04572 if(scopeidx == 0) {
04573 infof(data, "Invalid network interface: %s; %s\n", ifname,
04574 strerror(errno));
04575 }
04576 }
04577 if(scopeidx > 0) {
04578 char *p = percent + identifier_offset + strlen(ifname);
04579
04580
04581 memmove(percent, p, strlen(p) + 1);
04582 conn->scope_id = scopeidx;
04583 }
04584 else
04585 #endif
04586 infof(data, "Invalid IPv6 address format\n");
04587 }
04588 }
04589 }
04590
04591 if(data->set.scope_id)
04592
04593 conn->scope_id = data->set.scope_id;
04594
04595
04596
04597
04598 fragment = strchr(path, '#');
04599 if(fragment) {
04600 *fragment = 0;
04601
04602
04603
04604
04605 fragment = strchr(data->change.url, '#');
04606 if(fragment)
04607 *fragment = 0;
04608 }
04609
04610
04611
04612
04613
04614
04615
04616
04617 return findprotocol(data, conn, protop);
04618 }
04619
04620
04621
04622
04623
04624 static CURLcode setup_range(struct Curl_easy *data)
04625 {
04626 struct UrlState *s = &data->state;
04627 s->resume_from = data->set.set_resume_from;
04628 if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
04629 if(s->rangestringalloc)
04630 free(s->range);
04631
04632 if(s->resume_from)
04633 s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
04634 else
04635 s->range = strdup(data->set.str[STRING_SET_RANGE]);
04636
04637 s->rangestringalloc = (s->range) ? TRUE : FALSE;
04638
04639 if(!s->range)
04640 return CURLE_OUT_OF_MEMORY;
04641
04642
04643 s->use_range = TRUE;
04644 }
04645 else
04646 s->use_range = FALSE;
04647
04648 return CURLE_OK;
04649 }
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661 static CURLcode setup_connection_internals(struct connectdata *conn)
04662 {
04663 const struct Curl_handler * p;
04664 CURLcode result;
04665 struct Curl_easy *data = conn->data;
04666
04667
04668
04669
04670
04671
04672 Curl_free_request_state(data);
04673
04674 memset(&data->req, 0, sizeof(struct SingleRequest));
04675 data->req.maxdownload = -1;
04676
04677 conn->socktype = SOCK_STREAM;
04678
04679
04680 p = conn->handler;
04681
04682 if(p->setup_connection) {
04683 result = (*p->setup_connection)(conn);
04684
04685 if(result)
04686 return result;
04687
04688 p = conn->handler;
04689 }
04690
04691 if(conn->port < 0)
04692
04693
04694 conn->port = p->defport;
04695
04696 return CURLE_OK;
04697 }
04698
04699
04700
04701
04702
04703
04704 void Curl_free_request_state(struct Curl_easy *data)
04705 {
04706 Curl_safefree(data->req.protop);
04707 Curl_safefree(data->req.newurl);
04708 }
04709
04710
04711 #ifndef CURL_DISABLE_PROXY
04712
04713
04714
04715
04716 static bool check_noproxy(const char *name, const char *no_proxy)
04717 {
04718
04719
04720
04721
04722
04723 size_t tok_start;
04724 size_t tok_end;
04725 const char *separator = ", ";
04726 size_t no_proxy_len;
04727 size_t namelen;
04728 char *endptr;
04729
04730 if(no_proxy && no_proxy[0]) {
04731 if(strcasecompare("*", no_proxy)) {
04732 return TRUE;
04733 }
04734
04735
04736
04737 no_proxy_len = strlen(no_proxy);
04738 endptr = strchr(name, ':');
04739 if(endptr)
04740 namelen = endptr - name;
04741 else
04742 namelen = strlen(name);
04743
04744 for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
04745 while(tok_start < no_proxy_len &&
04746 strchr(separator, no_proxy[tok_start]) != NULL) {
04747
04748 ++tok_start;
04749 }
04750
04751 if(tok_start == no_proxy_len)
04752 break;
04753
04754 for(tok_end = tok_start; tok_end < no_proxy_len &&
04755 strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
04756
04757 ;
04758
04759
04760
04761
04762
04763 if(no_proxy[tok_start] == '.')
04764 ++tok_start;
04765
04766 if((tok_end - tok_start) <= namelen) {
04767
04768 const char *checkn = name + namelen - (tok_end - tok_start);
04769 if(strncasecompare(no_proxy + tok_start, checkn,
04770 tok_end - tok_start)) {
04771 if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
04772
04773
04774
04775 return TRUE;
04776 }
04777 }
04778 }
04779 }
04780
04781 }
04782
04783 return FALSE;
04784 }
04785
04786
04787
04788
04789
04790
04791 static char *detect_proxy(struct connectdata *conn)
04792 {
04793 char *proxy = NULL;
04794
04795 #ifndef CURL_DISABLE_HTTP
04796
04797
04798
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813 char *no_proxy=NULL;
04814 char proxy_env[128];
04815
04816 no_proxy=curl_getenv("no_proxy");
04817 if(!no_proxy)
04818 no_proxy=curl_getenv("NO_PROXY");
04819
04820 if(!check_noproxy(conn->host.name, no_proxy)) {
04821
04822 const char *protop = conn->handler->scheme;
04823 char *envp = proxy_env;
04824 char *prox;
04825
04826
04827 while(*protop)
04828 *envp++ = (char)tolower((int)*protop++);
04829
04830
04831 strcpy(envp, "_proxy");
04832
04833
04834 prox=curl_getenv(proxy_env);
04835
04836
04837
04838
04839
04840
04841
04842
04843
04844
04845
04846
04847
04848 if(!prox && !strcasecompare("http_proxy", proxy_env)) {
04849
04850 Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
04851 prox=curl_getenv(proxy_env);
04852 }
04853
04854 if(prox)
04855 proxy = prox;
04856 else {
04857 proxy = curl_getenv("all_proxy");
04858 if(!proxy)
04859 proxy=curl_getenv("ALL_PROXY");
04860 }
04861 }
04862
04863 free(no_proxy);
04864
04865 #else
04866
04867 (void)conn;
04868 #endif
04869
04870 return proxy;
04871 }
04872
04873
04874
04875
04876
04877
04878 static CURLcode parse_proxy(struct Curl_easy *data,
04879 struct connectdata *conn, char *proxy,
04880 curl_proxytype proxytype)
04881 {
04882 char *prox_portno;
04883 char *endofprot;
04884
04885
04886 char *proxyptr;
04887 char *portptr;
04888 char *atsign;
04889 long port = -1;
04890 char *proxyuser = NULL;
04891 char *proxypasswd = NULL;
04892 bool sockstype;
04893
04894
04895
04896
04897
04898
04899 endofprot = strstr(proxy, "://");
04900 if(endofprot) {
04901 proxyptr = endofprot+3;
04902 if(checkprefix("https", proxy))
04903 proxytype = CURLPROXY_HTTPS;
04904 else if(checkprefix("socks5h", proxy))
04905 proxytype = CURLPROXY_SOCKS5_HOSTNAME;
04906 else if(checkprefix("socks5", proxy))
04907 proxytype = CURLPROXY_SOCKS5;
04908 else if(checkprefix("socks4a", proxy))
04909 proxytype = CURLPROXY_SOCKS4A;
04910 else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
04911 proxytype = CURLPROXY_SOCKS4;
04912 else if(checkprefix("http:", proxy))
04913 ;
04914 else {
04915
04916 failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
04917 return CURLE_COULDNT_CONNECT;
04918 }
04919 }
04920 else
04921 proxyptr = proxy;
04922
04923 #ifndef HTTPS_PROXY_SUPPORT
04924 if(proxytype == CURLPROXY_HTTPS) {
04925 failf(data, "Unsupported proxy \'%s\'"
04926 ", libcurl is built without the HTTPS-proxy support.", proxy);
04927 return CURLE_NOT_BUILT_IN;
04928 }
04929 #endif
04930
04931 sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
04932 proxytype == CURLPROXY_SOCKS5 ||
04933 proxytype == CURLPROXY_SOCKS4A ||
04934 proxytype == CURLPROXY_SOCKS4;
04935
04936
04937 atsign = strchr(proxyptr, '@');
04938 if(atsign) {
04939 CURLcode result =
04940 parse_login_details(proxyptr, atsign - proxyptr,
04941 &proxyuser, &proxypasswd, NULL);
04942 if(result)
04943 return result;
04944 proxyptr = atsign + 1;
04945 }
04946
04947
04948 portptr = proxyptr;
04949
04950
04951 if(*proxyptr == '[') {
04952 char *ptr = ++proxyptr;
04953 while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
04954 ptr++;
04955 if(*ptr == '%') {
04956
04957 if(strncmp("%25", ptr, 3))
04958 infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
04959 ptr++;
04960
04961 while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
04962 (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
04963 ptr++;
04964 }
04965 if(*ptr == ']')
04966
04967 *ptr++ = 0;
04968 else
04969 infof(data, "Invalid IPv6 address format\n");
04970 portptr = ptr;
04971
04972
04973
04974
04975 }
04976
04977
04978 prox_portno = strchr(portptr, ':');
04979 if(prox_portno) {
04980 char *endp = NULL;
04981
04982 *prox_portno = 0x0;
04983 prox_portno ++;
04984
04985 port = strtol(prox_portno, &endp, 10);
04986 if((endp && *endp && (*endp != '/') && (*endp != ' ')) ||
04987 (port < 0) || (port > 65535)) {
04988
04989
04990
04991
04992
04993 infof(data, "No valid port number in proxy string (%s)\n",
04994 prox_portno);
04995 }
04996 else
04997 conn->port = port;
04998 }
04999 else {
05000 if(proxyptr[0]=='/')
05001
05002
05003
05004 return CURLE_COULDNT_RESOLVE_PROXY;
05005
05006
05007
05008 atsign = strchr(proxyptr, '/');
05009 if(atsign)
05010 *atsign = '\0';
05011
05012 if(data->set.proxyport)
05013
05014
05015 port = data->set.proxyport;
05016 else {
05017 if(proxytype == CURLPROXY_HTTPS)
05018 port = CURL_DEFAULT_HTTPS_PROXY_PORT;
05019 else
05020 port = CURL_DEFAULT_PROXY_PORT;
05021 }
05022 }
05023
05024 if(*proxyptr) {
05025 struct proxy_info *proxyinfo =
05026 sockstype ? &conn->socks_proxy : &conn->http_proxy;
05027 proxyinfo->proxytype = proxytype;
05028
05029 if(proxyuser) {
05030
05031
05032
05033 Curl_safefree(proxyinfo->user);
05034 proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
05035
05036 if(!proxyinfo->user)
05037 return CURLE_OUT_OF_MEMORY;
05038
05039 Curl_safefree(proxyinfo->passwd);
05040 if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
05041 proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
05042 else
05043 proxyinfo->passwd = strdup("");
05044
05045 if(!proxyinfo->passwd)
05046 return CURLE_OUT_OF_MEMORY;
05047
05048 conn->bits.proxy_user_passwd = TRUE;
05049 }
05050
05051 if(port >= 0) {
05052 proxyinfo->port = port;
05053 if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
05054 conn->port = port;
05055 }
05056
05057
05058 Curl_safefree(proxyinfo->host.rawalloc);
05059 proxyinfo->host.rawalloc = strdup(proxyptr);
05060 proxyinfo->host.name = proxyinfo->host.rawalloc;
05061
05062 if(!proxyinfo->host.rawalloc)
05063 return CURLE_OUT_OF_MEMORY;
05064 }
05065
05066 Curl_safefree(proxyuser);
05067 Curl_safefree(proxypasswd);
05068
05069 return CURLE_OK;
05070 }
05071
05072
05073
05074
05075 static CURLcode parse_proxy_auth(struct Curl_easy *data,
05076 struct connectdata *conn)
05077 {
05078 char proxyuser[MAX_CURL_USER_LENGTH]="";
05079 char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
05080 CURLcode result;
05081
05082 if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
05083 strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
05084 MAX_CURL_USER_LENGTH);
05085 proxyuser[MAX_CURL_USER_LENGTH-1] = '\0';
05086 }
05087 if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
05088 strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
05089 MAX_CURL_PASSWORD_LENGTH);
05090 proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0';
05091 }
05092
05093 result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
05094 FALSE);
05095 if(!result)
05096 result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
05097 NULL, FALSE);
05098 return result;
05099 }
05100 #endif
05101
05102
05103
05104
05105
05106
05107
05108
05109
05110
05111
05112
05113
05114
05115
05116
05117
05118 static CURLcode parse_url_login(struct Curl_easy *data,
05119 struct connectdata *conn,
05120 char **user, char **passwd, char **options)
05121 {
05122 CURLcode result = CURLE_OK;
05123 char *userp = NULL;
05124 char *passwdp = NULL;
05125 char *optionsp = NULL;
05126
05127
05128
05129
05130
05131
05132
05133
05134 char *ptr = strchr(conn->host.name, '@');
05135 char *login = conn->host.name;
05136
05137 DEBUGASSERT(!**user);
05138 DEBUGASSERT(!**passwd);
05139 DEBUGASSERT(!**options);
05140
05141 if(!ptr)
05142 goto out;
05143
05144
05145
05146
05147 conn->host.name = ++ptr;
05148
05149
05150
05151
05152
05153
05154
05155 if(data->set.use_netrc == CURL_NETRC_REQUIRED)
05156 goto out;
05157
05158
05159 result = parse_login_details(login, ptr - login - 1,
05160 &userp, &passwdp, &optionsp);
05161 if(result)
05162 goto out;
05163
05164 if(userp) {
05165 char *newname;
05166
05167
05168 conn->bits.userpwd_in_url = TRUE;
05169 conn->bits.user_passwd = TRUE;
05170
05171
05172 result = Curl_urldecode(data, userp, 0, &newname, NULL, FALSE);
05173 if(result) {
05174 goto out;
05175 }
05176
05177 free(*user);
05178 *user = newname;
05179 }
05180
05181 if(passwdp) {
05182
05183 char *newpasswd;
05184 result = Curl_urldecode(data, passwdp, 0, &newpasswd, NULL, FALSE);
05185 if(result) {
05186 goto out;
05187 }
05188
05189 free(*passwd);
05190 *passwd = newpasswd;
05191 }
05192
05193 if(optionsp) {
05194
05195 char *newoptions;
05196 result = Curl_urldecode(data, optionsp, 0, &newoptions, NULL, FALSE);
05197 if(result) {
05198 goto out;
05199 }
05200
05201 free(*options);
05202 *options = newoptions;
05203 }
05204
05205
05206 out:
05207
05208 free(userp);
05209 free(passwdp);
05210 free(optionsp);
05211
05212 return result;
05213 }
05214
05215
05216
05217
05218
05219
05220
05221
05222
05223
05224
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241
05242
05243
05244 static CURLcode parse_login_details(const char *login, const size_t len,
05245 char **userp, char **passwdp,
05246 char **optionsp)
05247 {
05248 CURLcode result = CURLE_OK;
05249 char *ubuf = NULL;
05250 char *pbuf = NULL;
05251 char *obuf = NULL;
05252 const char *psep = NULL;
05253 const char *osep = NULL;
05254 size_t ulen;
05255 size_t plen;
05256 size_t olen;
05257
05258
05259 if(passwdp) {
05260 psep = strchr(login, ':');
05261
05262
05263 if(psep >= login + len)
05264 psep = NULL;
05265 }
05266
05267
05268 if(optionsp) {
05269 osep = strchr(login, ';');
05270
05271
05272 if(osep >= login + len)
05273 osep = NULL;
05274 }
05275
05276
05277 ulen = (psep ?
05278 (size_t)(osep && psep > osep ? osep - login : psep - login) :
05279 (osep ? (size_t)(osep - login) : len));
05280 plen = (psep ?
05281 (osep && osep > psep ? (size_t)(osep - psep) :
05282 (size_t)(login + len - psep)) - 1 : 0);
05283 olen = (osep ?
05284 (psep && psep > osep ? (size_t)(psep - osep) :
05285 (size_t)(login + len - osep)) - 1 : 0);
05286
05287
05288 if(userp && ulen) {
05289 ubuf = malloc(ulen + 1);
05290 if(!ubuf)
05291 result = CURLE_OUT_OF_MEMORY;
05292 }
05293
05294
05295 if(!result && passwdp && plen) {
05296 pbuf = malloc(plen + 1);
05297 if(!pbuf) {
05298 free(ubuf);
05299 result = CURLE_OUT_OF_MEMORY;
05300 }
05301 }
05302
05303
05304 if(!result && optionsp && olen) {
05305 obuf = malloc(olen + 1);
05306 if(!obuf) {
05307 free(pbuf);
05308 free(ubuf);
05309 result = CURLE_OUT_OF_MEMORY;
05310 }
05311 }
05312
05313 if(!result) {
05314
05315 if(ubuf) {
05316 memcpy(ubuf, login, ulen);
05317 ubuf[ulen] = '\0';
05318 Curl_safefree(*userp);
05319 *userp = ubuf;
05320 }
05321
05322
05323 if(pbuf) {
05324 memcpy(pbuf, psep + 1, plen);
05325 pbuf[plen] = '\0';
05326 Curl_safefree(*passwdp);
05327 *passwdp = pbuf;
05328 }
05329
05330
05331 if(obuf) {
05332 memcpy(obuf, osep + 1, olen);
05333 obuf[olen] = '\0';
05334 Curl_safefree(*optionsp);
05335 *optionsp = obuf;
05336 }
05337 }
05338
05339 return result;
05340 }
05341
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355
05356 static CURLcode parse_remote_port(struct Curl_easy *data,
05357 struct connectdata *conn)
05358 {
05359 char *portptr;
05360 char endbracket;
05361
05362
05363
05364
05365 if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
05366 &endbracket)) &&
05367 (']' == endbracket)) {
05368
05369 conn->bits.ipv6_ip = TRUE;
05370
05371 conn->host.name++;
05372 portptr = strchr(conn->host.name, ']');
05373 if(portptr) {
05374 *portptr++ = '\0';
05375 if(':' != *portptr)
05376 portptr = NULL;
05377 }
05378 }
05379 else {
05380 #ifdef ENABLE_IPV6
05381 struct in6_addr in6;
05382 if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) {
05383
05384
05385 failf(data, "IPv6 numerical address used in URL without brackets");
05386 return CURLE_URL_MALFORMAT;
05387 }
05388 #endif
05389
05390 portptr = strrchr(conn->host.name, ':');
05391 }
05392
05393 if(data->set.use_port && data->state.allow_port) {
05394
05395 conn->remote_port = (unsigned short)data->set.use_port;
05396 if(portptr)
05397 *portptr = '\0';
05398
05399 if(conn->bits.httpproxy) {
05400
05401 char *url;
05402 char type[12]="";
05403
05404 if(conn->bits.type_set)
05405 snprintf(type, sizeof(type), ";type=%c",
05406 data->set.prefer_ascii?'A':
05407 (data->set.ftp_list_only?'D':'I'));
05408
05409
05410
05411
05412
05413
05414 url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
05415 conn->bits.ipv6_ip?"[":"", conn->host.name,
05416 conn->bits.ipv6_ip?"]":"", conn->remote_port,
05417 data->state.slash_removed?"/":"", data->state.path,
05418 type);
05419 if(!url)
05420 return CURLE_OUT_OF_MEMORY;
05421
05422 if(data->change.url_alloc) {
05423 Curl_safefree(data->change.url);
05424 data->change.url_alloc = FALSE;
05425 }
05426
05427 data->change.url = url;
05428 data->change.url_alloc = TRUE;
05429 }
05430 }
05431 else if(portptr) {
05432
05433
05434 char *rest;
05435 long port;
05436
05437 port=strtol(portptr+1, &rest, 10);
05438
05439 if((port < 0) || (port > 0xffff)) {
05440
05441 failf(data, "Port number out of range");
05442 return CURLE_URL_MALFORMAT;
05443 }
05444
05445 else if(rest != &portptr[1]) {
05446 *portptr = '\0';
05447 conn->remote_port = curlx_ultous(port);
05448 }
05449 else {
05450 if(rest[0]) {
05451 failf(data, "Illegal port number");
05452 return CURLE_URL_MALFORMAT;
05453 }
05454
05455
05456
05457 *portptr = '\0';
05458 }
05459 }
05460
05461
05462
05463 if(conn->remote_port < 0)
05464 conn->remote_port = (unsigned short)conn->given->defport;
05465
05466 return CURLE_OK;
05467 }
05468
05469
05470
05471
05472
05473 static CURLcode override_login(struct Curl_easy *data,
05474 struct connectdata *conn,
05475 char **userp, char **passwdp, char **optionsp)
05476 {
05477 if(data->set.str[STRING_USERNAME]) {
05478 free(*userp);
05479 *userp = strdup(data->set.str[STRING_USERNAME]);
05480 if(!*userp)
05481 return CURLE_OUT_OF_MEMORY;
05482 }
05483
05484 if(data->set.str[STRING_PASSWORD]) {
05485 free(*passwdp);
05486 *passwdp = strdup(data->set.str[STRING_PASSWORD]);
05487 if(!*passwdp)
05488 return CURLE_OUT_OF_MEMORY;
05489 }
05490
05491 if(data->set.str[STRING_OPTIONS]) {
05492 free(*optionsp);
05493 *optionsp = strdup(data->set.str[STRING_OPTIONS]);
05494 if(!*optionsp)
05495 return CURLE_OUT_OF_MEMORY;
05496 }
05497
05498 conn->bits.netrc = FALSE;
05499 if(data->set.use_netrc != CURL_NETRC_IGNORED) {
05500 int ret = Curl_parsenetrc(conn->host.name,
05501 userp, passwdp,
05502 data->set.str[STRING_NETRC_FILE]);
05503 if(ret > 0) {
05504 infof(data, "Couldn't find host %s in the "
05505 DOT_CHAR "netrc file; using defaults\n",
05506 conn->host.name);
05507 }
05508 else if(ret < 0) {
05509 return CURLE_OUT_OF_MEMORY;
05510 }
05511 else {
05512
05513
05514
05515 conn->bits.netrc = TRUE;
05516
05517 conn->bits.user_passwd = TRUE;
05518 }
05519 }
05520
05521 return CURLE_OK;
05522 }
05523
05524
05525
05526
05527 static CURLcode set_login(struct connectdata *conn,
05528 const char *user, const char *passwd,
05529 const char *options)
05530 {
05531 CURLcode result = CURLE_OK;
05532
05533
05534 if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
05535
05536 conn->user = strdup(CURL_DEFAULT_USER);
05537
05538
05539 if(conn->user)
05540 conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
05541 else
05542 conn->passwd = NULL;
05543
05544
05545 }
05546 else {
05547
05548 conn->user = strdup(user);
05549
05550
05551 if(conn->user)
05552 conn->passwd = strdup(passwd);
05553 else
05554 conn->passwd = NULL;
05555 }
05556
05557 if(!conn->user || !conn->passwd)
05558 result = CURLE_OUT_OF_MEMORY;
05559
05560
05561 if(!result && options[0]) {
05562 conn->options = strdup(options);
05563
05564 if(!conn->options)
05565 result = CURLE_OUT_OF_MEMORY;
05566 }
05567
05568 return result;
05569 }
05570
05571
05572
05573
05574
05575
05576 static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
05577 const char *host,
05578 char **hostname_result,
05579 int *port_result)
05580 {
05581 char *host_dup;
05582 char *hostptr;
05583 char *host_portno;
05584 char *portptr;
05585 int port = -1;
05586
05587 *hostname_result = NULL;
05588 *port_result = -1;
05589
05590 if(!host || !*host)
05591 return CURLE_OK;
05592
05593 host_dup = strdup(host);
05594 if(!host_dup)
05595 return CURLE_OUT_OF_MEMORY;
05596
05597 hostptr = host_dup;
05598
05599
05600 portptr = hostptr;
05601
05602
05603 if(*hostptr == '[') {
05604 char *ptr = ++hostptr;
05605 while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
05606 ptr++;
05607 if(*ptr == '%') {
05608
05609 if(strncmp("%25", ptr, 3))
05610 infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
05611 ptr++;
05612
05613 while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
05614 (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
05615 ptr++;
05616 }
05617 if(*ptr == ']')
05618
05619 *ptr++ = '\0';
05620 else
05621 infof(data, "Invalid IPv6 address format\n");
05622 portptr = ptr;
05623
05624
05625
05626
05627 }
05628
05629
05630 host_portno = strchr(portptr, ':');
05631 if(host_portno) {
05632 char *endp = NULL;
05633 *host_portno = '\0';
05634 host_portno++;
05635 if(*host_portno) {
05636 long portparse = strtol(host_portno, &endp, 10);
05637 if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
05638 infof(data, "No valid port number in connect to host string (%s)\n",
05639 host_portno);
05640 hostptr = NULL;
05641 port = -1;
05642 }
05643 else
05644 port = (int)portparse;
05645 }
05646 }
05647
05648
05649 if(hostptr) {
05650 *hostname_result = strdup(hostptr);
05651 if(!*hostname_result) {
05652 free(host_dup);
05653 return CURLE_OUT_OF_MEMORY;
05654 }
05655 }
05656
05657 *port_result = port;
05658
05659 free(host_dup);
05660 return CURLE_OK;
05661 }
05662
05663
05664
05665
05666
05667 static CURLcode parse_connect_to_string(struct Curl_easy *data,
05668 struct connectdata *conn,
05669 const char *conn_to_host,
05670 char **host_result,
05671 int *port_result)
05672 {
05673 CURLcode result = CURLE_OK;
05674 const char *ptr = conn_to_host;
05675 int host_match = FALSE;
05676 int port_match = FALSE;
05677
05678 *host_result = NULL;
05679 *port_result = -1;
05680
05681 if(*ptr == ':') {
05682
05683 host_match = TRUE;
05684 ptr++;
05685 }
05686 else {
05687
05688 size_t hostname_to_match_len;
05689 char *hostname_to_match = aprintf("%s%s%s",
05690 conn->bits.ipv6_ip ? "[" : "",
05691 conn->host.name,
05692 conn->bits.ipv6_ip ? "]" : "");
05693 if(!hostname_to_match)
05694 return CURLE_OUT_OF_MEMORY;
05695 hostname_to_match_len = strlen(hostname_to_match);
05696 host_match = strncasecompare(ptr, hostname_to_match,
05697 hostname_to_match_len);
05698 free(hostname_to_match);
05699 ptr += hostname_to_match_len;
05700
05701 host_match = host_match && *ptr == ':';
05702 ptr++;
05703 }
05704
05705 if(host_match) {
05706 if(*ptr == ':') {
05707
05708 port_match = TRUE;
05709 ptr++;
05710 }
05711 else {
05712
05713 char *ptr_next = strchr(ptr, ':');
05714 if(ptr_next) {
05715 char *endp = NULL;
05716 long port_to_match = strtol(ptr, &endp, 10);
05717 if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
05718 port_match = TRUE;
05719 ptr = ptr_next + 1;
05720 }
05721 }
05722 }
05723 }
05724
05725 if(host_match && port_match) {
05726
05727 result = parse_connect_to_host_port(data, ptr, host_result, port_result);
05728 }
05729
05730 return result;
05731 }
05732
05733
05734
05735
05736
05737 static CURLcode parse_connect_to_slist(struct Curl_easy *data,
05738 struct connectdata *conn,
05739 struct curl_slist *conn_to_host)
05740 {
05741 CURLcode result = CURLE_OK;
05742 char *host = NULL;
05743 int port = -1;
05744
05745 while(conn_to_host && !host && port == -1) {
05746 result = parse_connect_to_string(data, conn, conn_to_host->data,
05747 &host, &port);
05748 if(result)
05749 return result;
05750
05751 if(host && *host) {
05752 bool ipv6host;
05753 conn->conn_to_host.rawalloc = host;
05754 conn->conn_to_host.name = host;
05755 conn->bits.conn_to_host = TRUE;
05756
05757 ipv6host = strchr(host, ':') != NULL;
05758 infof(data, "Connecting to hostname: %s%s%s\n",
05759 ipv6host ? "[" : "", host, ipv6host ? "]" : "");
05760 }
05761 else {
05762
05763 conn->bits.conn_to_host = FALSE;
05764 Curl_safefree(host);
05765 }
05766
05767 if(port >= 0) {
05768 conn->conn_to_port = port;
05769 conn->bits.conn_to_port = TRUE;
05770 infof(data, "Connecting to port: %d\n", port);
05771 }
05772 else {
05773
05774 conn->bits.conn_to_port = FALSE;
05775 port = -1;
05776 }
05777
05778 conn_to_host = conn_to_host->next;
05779 }
05780
05781 return result;
05782 }
05783
05784
05785
05786
05787 static CURLcode resolve_server(struct Curl_easy *data,
05788 struct connectdata *conn,
05789 bool *async)
05790 {
05791 CURLcode result=CURLE_OK;
05792 time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
05793
05794
05795
05796
05797 if(conn->bits.reuse)
05798
05799
05800
05801 *async = FALSE;
05802
05803 else {
05804
05805 int rc;
05806 struct Curl_dns_entry *hostaddr;
05807
05808 #ifdef USE_UNIX_SOCKETS
05809 if(conn->unix_domain_socket) {
05810
05811
05812
05813 const char *path = conn->unix_domain_socket;
05814
05815 hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
05816 if(!hostaddr)
05817 result = CURLE_OUT_OF_MEMORY;
05818 else {
05819 int longpath=0;
05820 hostaddr->addr = Curl_unix2addr(path, &longpath);
05821 if(hostaddr->addr)
05822 hostaddr->inuse++;
05823 else {
05824
05825 if(longpath) {
05826 failf(data, "Unix socket path too long: '%s'", path);
05827 result = CURLE_COULDNT_RESOLVE_HOST;
05828 }
05829 else
05830 result = CURLE_OUT_OF_MEMORY;
05831 free(hostaddr);
05832 hostaddr = NULL;
05833 }
05834 }
05835 }
05836 else
05837 #endif
05838 if(!conn->bits.proxy) {
05839 struct hostname *connhost;
05840 if(conn->bits.conn_to_host)
05841 connhost = &conn->conn_to_host;
05842 else
05843 connhost = &conn->host;
05844
05845
05846
05847 if(conn->bits.conn_to_port)
05848 conn->port = conn->conn_to_port;
05849 else
05850 conn->port = conn->remote_port;
05851
05852
05853 rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
05854 &hostaddr, timeout_ms);
05855 if(rc == CURLRESOLV_PENDING)
05856 *async = TRUE;
05857
05858 else if(rc == CURLRESOLV_TIMEDOUT)
05859 result = CURLE_OPERATION_TIMEDOUT;
05860
05861 else if(!hostaddr) {
05862 failf(data, "Couldn't resolve host '%s'", connhost->dispname);
05863 result = CURLE_COULDNT_RESOLVE_HOST;
05864
05865 }
05866 }
05867 else {
05868
05869
05870 struct hostname * const host = conn->bits.socksproxy ?
05871 &conn->socks_proxy.host : &conn->http_proxy.host;
05872
05873
05874 rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
05875 &hostaddr, timeout_ms);
05876
05877 if(rc == CURLRESOLV_PENDING)
05878 *async = TRUE;
05879
05880 else if(rc == CURLRESOLV_TIMEDOUT)
05881 result = CURLE_OPERATION_TIMEDOUT;
05882
05883 else if(!hostaddr) {
05884 failf(data, "Couldn't resolve proxy '%s'", host->dispname);
05885 result = CURLE_COULDNT_RESOLVE_PROXY;
05886
05887 }
05888 }
05889 DEBUGASSERT(conn->dns_entry == NULL);
05890 conn->dns_entry = hostaddr;
05891 }
05892
05893 return result;
05894 }
05895
05896
05897
05898
05899
05900
05901 static void reuse_conn(struct connectdata *old_conn,
05902 struct connectdata *conn)
05903 {
05904 free_fixed_hostname(&old_conn->http_proxy.host);
05905 free_fixed_hostname(&old_conn->socks_proxy.host);
05906 free_fixed_hostname(&old_conn->proxy);
05907
05908 free(old_conn->http_proxy.host.rawalloc);
05909 free(old_conn->socks_proxy.host.rawalloc);
05910 free(old_conn->proxy.rawalloc);
05911
05912
05913
05914 Curl_free_primary_ssl_config(&old_conn->ssl_config);
05915 Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
05916
05917 conn->data = old_conn->data;
05918
05919
05920
05921 conn->bits.user_passwd = old_conn->bits.user_passwd;
05922 if(conn->bits.user_passwd) {
05923
05924 Curl_safefree(conn->user);
05925 Curl_safefree(conn->passwd);
05926 conn->user = old_conn->user;
05927 conn->passwd = old_conn->passwd;
05928 old_conn->user = NULL;
05929 old_conn->passwd = NULL;
05930 }
05931
05932 conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
05933 if(conn->bits.proxy_user_passwd) {
05934
05935 Curl_safefree(conn->http_proxy.user);
05936 Curl_safefree(conn->socks_proxy.user);
05937 Curl_safefree(conn->http_proxy.passwd);
05938 Curl_safefree(conn->socks_proxy.passwd);
05939 conn->http_proxy.user = old_conn->http_proxy.user;
05940 conn->socks_proxy.user = old_conn->socks_proxy.user;
05941 conn->http_proxy.passwd = old_conn->http_proxy.passwd;
05942 conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
05943 old_conn->http_proxy.user = NULL;
05944 old_conn->socks_proxy.user = NULL;
05945 old_conn->http_proxy.passwd = NULL;
05946 old_conn->socks_proxy.passwd = NULL;
05947 }
05948
05949
05950
05951 free_fixed_hostname(&conn->host);
05952 free_fixed_hostname(&conn->conn_to_host);
05953 Curl_safefree(conn->host.rawalloc);
05954 Curl_safefree(conn->conn_to_host.rawalloc);
05955 conn->host=old_conn->host;
05956 conn->bits.conn_to_host = old_conn->bits.conn_to_host;
05957 conn->conn_to_host = old_conn->conn_to_host;
05958 conn->bits.conn_to_port = old_conn->bits.conn_to_port;
05959 conn->conn_to_port = old_conn->conn_to_port;
05960
05961
05962 Curl_persistconninfo(conn);
05963
05964 conn_reset_all_postponed_data(old_conn);
05965 conn_reset_all_postponed_data(conn);
05966
05967
05968 conn->bits.reuse = TRUE;
05969
05970 Curl_safefree(old_conn->user);
05971 Curl_safefree(old_conn->passwd);
05972 Curl_safefree(old_conn->http_proxy.user);
05973 Curl_safefree(old_conn->socks_proxy.user);
05974 Curl_safefree(old_conn->http_proxy.passwd);
05975 Curl_safefree(old_conn->socks_proxy.passwd);
05976 Curl_safefree(old_conn->localdev);
05977
05978 Curl_llist_destroy(old_conn->send_pipe, NULL);
05979 Curl_llist_destroy(old_conn->recv_pipe, NULL);
05980
05981 old_conn->send_pipe = NULL;
05982 old_conn->recv_pipe = NULL;
05983
05984 Curl_safefree(old_conn->master_buffer);
05985
05986 #ifdef USE_UNIX_SOCKETS
05987 Curl_safefree(old_conn->unix_domain_socket);
05988 #endif
05989 }
05990
06007 static CURLcode create_conn(struct Curl_easy *data,
06008 struct connectdata **in_connect,
06009 bool *async)
06010 {
06011 CURLcode result = CURLE_OK;
06012 struct connectdata *conn;
06013 struct connectdata *conn_temp = NULL;
06014 size_t urllen;
06015 char *user = NULL;
06016 char *passwd = NULL;
06017 char *options = NULL;
06018 bool reuse;
06019 char *proxy = NULL;
06020 char *socksproxy = NULL;
06021 bool prot_missing = FALSE;
06022 bool connections_available = TRUE;
06023 bool force_reuse = FALSE;
06024 bool waitpipe = FALSE;
06025 size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
06026 size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
06027
06028 *async = FALSE;
06029
06030
06031
06032
06033
06034 if(!data->change.url) {
06035 result = CURLE_URL_MALFORMAT;
06036 goto out;
06037 }
06038
06039
06040
06041
06042
06043 conn = allocate_conn(data);
06044
06045 if(!conn) {
06046 result = CURLE_OUT_OF_MEMORY;
06047 goto out;
06048 }
06049
06050
06051
06052
06053 *in_connect = conn;
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063 #define LEAST_PATH_ALLOC 256
06064 urllen=strlen(data->change.url);
06065 if(urllen < LEAST_PATH_ALLOC)
06066 urllen=LEAST_PATH_ALLOC;
06067
06068
06069
06070
06071
06072
06073
06074 Curl_safefree(data->state.pathbuffer);
06075 data->state.path = NULL;
06076
06077 data->state.pathbuffer = malloc(urllen+2);
06078 if(NULL == data->state.pathbuffer) {
06079 result = CURLE_OUT_OF_MEMORY;
06080 goto out;
06081 }
06082 data->state.path = data->state.pathbuffer;
06083
06084 conn->host.rawalloc = malloc(urllen+2);
06085 if(NULL == conn->host.rawalloc) {
06086 Curl_safefree(data->state.pathbuffer);
06087 data->state.path = NULL;
06088 result = CURLE_OUT_OF_MEMORY;
06089 goto out;
06090 }
06091
06092 conn->host.name = conn->host.rawalloc;
06093 conn->host.name[0] = 0;
06094
06095 user = strdup("");
06096 passwd = strdup("");
06097 options = strdup("");
06098 if(!user || !passwd || !options) {
06099 result = CURLE_OUT_OF_MEMORY;
06100 goto out;
06101 }
06102
06103 result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
06104 &options);
06105 if(result)
06106 goto out;
06107
06108
06109
06110
06111 if(prot_missing) {
06112
06113
06114
06115 char *reurl;
06116 char *ch_lower;
06117
06118 reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
06119
06120 if(!reurl) {
06121 result = CURLE_OUT_OF_MEMORY;
06122 goto out;
06123 }
06124
06125
06126 for(ch_lower = reurl; *ch_lower != ':'; ch_lower++)
06127 *ch_lower = (char)TOLOWER(*ch_lower);
06128
06129 if(data->change.url_alloc) {
06130 Curl_safefree(data->change.url);
06131 data->change.url_alloc = FALSE;
06132 }
06133
06134 data->change.url = reurl;
06135 data->change.url_alloc = TRUE;
06136 }
06137
06138
06139
06140
06141
06142 if((conn->given->flags&PROTOPT_NOURLQUERY)) {
06143 char *path_q_sep = strchr(conn->data->state.path, '?');
06144 if(path_q_sep) {
06145
06146
06147
06148
06149
06150
06151
06152 path_q_sep[0] = 0;
06153 }
06154 }
06155
06156 if(data->set.str[STRING_BEARER]) {
06157 conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
06158 if(!conn->oauth_bearer) {
06159 result = CURLE_OUT_OF_MEMORY;
06160 goto out;
06161 }
06162 }
06163
06164 #ifndef CURL_DISABLE_PROXY
06165
06166
06167
06168 if(conn->bits.proxy_user_passwd) {
06169 result = parse_proxy_auth(data, conn);
06170 if(result)
06171 goto out;
06172 }
06173
06174
06175
06176
06177 if(data->set.str[STRING_PROXY]) {
06178 proxy = strdup(data->set.str[STRING_PROXY]);
06179
06180 if(NULL == proxy) {
06181 failf(data, "memory shortage");
06182 result = CURLE_OUT_OF_MEMORY;
06183 goto out;
06184 }
06185 }
06186
06187 if(data->set.str[STRING_PRE_PROXY]) {
06188 socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
06189
06190 if(NULL == socksproxy) {
06191 failf(data, "memory shortage");
06192 result = CURLE_OUT_OF_MEMORY;
06193 goto out;
06194 }
06195 }
06196
06197 if(data->set.str[STRING_NOPROXY] &&
06198 check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
06199 Curl_safefree(proxy);
06200 Curl_safefree(socksproxy);
06201 }
06202 else if(!proxy && !socksproxy)
06203 proxy = detect_proxy(conn);
06204
06205 #ifdef USE_UNIX_SOCKETS
06206 if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
06207 if(proxy) {
06208 free(proxy);
06209 proxy = NULL;
06210 }
06211 conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
06212 if(conn->unix_domain_socket == NULL) {
06213 result = CURLE_OUT_OF_MEMORY;
06214 goto out;
06215 }
06216 }
06217 #endif
06218
06219 if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
06220 free(proxy);
06221
06222 proxy = NULL;
06223 }
06224 if(socksproxy && (!*socksproxy ||
06225 (conn->handler->flags & PROTOPT_NONETWORK))) {
06226 free(socksproxy);
06227
06228 socksproxy = NULL;
06229 }
06230
06231
06232
06233
06234
06235
06236 if(proxy || socksproxy) {
06237 if(proxy) {
06238 result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
06239 Curl_safefree(proxy);
06240 if(result)
06241 goto out;
06242 }
06243
06244 if(socksproxy) {
06245 result = parse_proxy(data, conn, socksproxy,
06246 conn->socks_proxy.proxytype);
06247
06248 Curl_safefree(socksproxy);
06249 if(result)
06250 goto out;
06251 }
06252
06253 if(conn->http_proxy.host.rawalloc) {
06254 #ifdef CURL_DISABLE_HTTP
06255
06256 result = CURLE_UNSUPPORTED_PROTOCOL;
06257 goto out;
06258 #else
06259
06260
06261 if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
06262 !conn->bits.tunnel_proxy)
06263 conn->handler = &Curl_handler_http;
06264
06265 conn->bits.httpproxy = TRUE;
06266 #endif
06267 }
06268 else {
06269 conn->bits.httpproxy = FALSE;
06270 conn->bits.tunnel_proxy = FALSE;
06271 }
06272
06273 if(conn->socks_proxy.host.rawalloc) {
06274 if(!conn->http_proxy.host.rawalloc) {
06275
06276 if(!conn->socks_proxy.user) {
06277 conn->socks_proxy.user = conn->http_proxy.user;
06278 conn->http_proxy.user = NULL;
06279 Curl_safefree(conn->socks_proxy.passwd);
06280 conn->socks_proxy.passwd = conn->http_proxy.passwd;
06281 conn->http_proxy.passwd = NULL;
06282 }
06283 }
06284 conn->bits.socksproxy = TRUE;
06285 }
06286 else
06287 conn->bits.socksproxy = FALSE;
06288 }
06289 else {
06290 conn->bits.socksproxy = FALSE;
06291 conn->bits.httpproxy = FALSE;
06292 }
06293 conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
06294
06295 if(!conn->bits.proxy) {
06296
06297 conn->bits.proxy = FALSE;
06298 conn->bits.httpproxy = FALSE;
06299 conn->bits.socksproxy = FALSE;
06300 conn->bits.proxy_user_passwd = FALSE;
06301 conn->bits.tunnel_proxy = FALSE;
06302 }
06303
06304 #endif
06305
06306
06307
06308
06309
06310 if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
06311 conn->bits.tunnel_proxy = TRUE;
06312
06313
06314
06315
06316 result = parse_remote_port(data, conn);
06317 if(result)
06318 goto out;
06319
06320
06321
06322 result = override_login(data, conn, &user, &passwd, &options);
06323 if(result)
06324 goto out;
06325 result = set_login(conn, user, passwd, options);
06326 if(result)
06327 goto out;
06328
06329
06330
06331
06332
06333 result = parse_connect_to_slist(data, conn, data->set.connect_to);
06334 if(result)
06335 goto out;
06336
06337
06338
06339
06340 fix_hostname(conn, &conn->host);
06341 if(conn->bits.conn_to_host)
06342 fix_hostname(conn, &conn->conn_to_host);
06343 if(conn->proxy.name && *conn->proxy.name)
06344 fix_hostname(conn, &conn->proxy);
06345
06346
06347
06348
06349
06350 if(conn->bits.conn_to_host &&
06351 strcasecompare(conn->conn_to_host.name, conn->host.name)) {
06352 conn->bits.conn_to_host = FALSE;
06353 }
06354
06355
06356
06357
06358
06359 if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
06360 conn->bits.conn_to_port = FALSE;
06361 }
06362
06363
06364
06365
06366
06367 if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
06368 conn->bits.httpproxy)
06369 conn->bits.tunnel_proxy = TRUE;
06370
06371
06372
06373
06374
06375 result = setup_connection_internals(conn);
06376 if(result)
06377 goto out;
06378
06379 conn->recv[FIRSTSOCKET] = Curl_recv_plain;
06380 conn->send[FIRSTSOCKET] = Curl_send_plain;
06381 conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
06382 conn->send[SECONDARYSOCKET] = Curl_send_plain;
06383
06384 conn->bits.tcp_fastopen = data->set.tcp_fastopen;
06385
06386
06387
06388
06389 #ifndef CURL_DISABLE_FILE
06390 if(conn->handler->flags & PROTOPT_NONETWORK) {
06391 bool done;
06392
06393
06394 DEBUGASSERT(conn->handler->connect_it);
06395 result = conn->handler->connect_it(conn, &done);
06396
06397
06398 if(!result) {
06399 conn->data = data;
06400 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
06401
06402 Curl_conncache_add_conn(data->state.conn_cache, conn);
06403
06404
06405
06406
06407 result = setup_range(data);
06408 if(result) {
06409 DEBUGASSERT(conn->handler->done);
06410
06411 (void)conn->handler->done(conn, result, FALSE);
06412 goto out;
06413 }
06414
06415 Curl_setup_transfer(conn, -1, -1, FALSE, NULL,
06416 -1, NULL);
06417 }
06418
06419
06420 Curl_init_do(data, conn);
06421
06422 goto out;
06423 }
06424 #endif
06425
06426
06427
06428
06429
06430
06431
06432
06433
06434
06435 data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
06436 data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
06437 data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
06438 data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
06439 data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
06440 data->set.proxy_ssl.primary.random_file =
06441 data->set.str[STRING_SSL_RANDOM_FILE];
06442 data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
06443 data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
06444 data->set.ssl.primary.cipher_list =
06445 data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
06446 data->set.proxy_ssl.primary.cipher_list =
06447 data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
06448
06449 data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
06450 data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
06451 data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
06452 data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
06453 data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
06454 data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
06455 data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
06456 data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
06457 data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
06458 data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
06459 data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
06460 data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
06461 data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
06462 data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
06463 data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
06464 data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
06465 #ifdef USE_TLS_SRP
06466 data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
06467 data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
06468 data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
06469 data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
06470 #endif
06471
06472 if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
06473 &conn->ssl_config)) {
06474 result = CURLE_OUT_OF_MEMORY;
06475 goto out;
06476 }
06477
06478 if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
06479 &conn->proxy_ssl_config)) {
06480 result = CURLE_OUT_OF_MEMORY;
06481 goto out;
06482 }
06483
06484 prune_dead_connections(data);
06485
06486
06487
06488
06489
06490
06491
06492
06493
06494
06495
06496 if(data->set.reuse_fresh && !data->state.this_is_a_follow)
06497 reuse = FALSE;
06498 else
06499 reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
06500
06501
06502
06503 if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
06504 size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size;
06505 if(pipelen > 0) {
06506 infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
06507 conn_temp->connection_id, pipelen);
06508
06509 if(conn_temp->bundle->num_connections < max_host_connections &&
06510 data->state.conn_cache->num_connections < max_total_connections) {
06511
06512 reuse = FALSE;
06513
06514 infof(data, "We can reuse, but we want a new connection anyway\n");
06515 }
06516 }
06517 }
06518
06519 if(reuse) {
06520
06521
06522
06523
06524
06525
06526 conn_temp->inuse = TRUE;
06527
06528 reuse_conn(conn, conn_temp);
06529 free(conn);
06530 conn = conn_temp;
06531 *in_connect = conn;
06532
06533 infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
06534 conn->connection_id,
06535 conn->bits.proxy?"proxy":"host",
06536 conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
06537 conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
06538 conn->host.dispname);
06539 }
06540 else {
06541
06542
06543
06544 struct connectbundle *bundle = NULL;
06545
06546 if(conn->handler->flags & PROTOPT_ALPN_NPN) {
06547
06548
06549 if(data->set.ssl_enable_alpn)
06550 conn->bits.tls_enable_alpn = TRUE;
06551 if(data->set.ssl_enable_npn)
06552 conn->bits.tls_enable_npn = TRUE;
06553 }
06554
06555 if(waitpipe)
06556
06557
06558 connections_available = FALSE;
06559 else
06560 bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
06561
06562 if(max_host_connections > 0 && bundle &&
06563 (bundle->num_connections >= max_host_connections)) {
06564 struct connectdata *conn_candidate;
06565
06566
06567 conn_candidate = find_oldest_idle_connection_in_bundle(data, bundle);
06568
06569 if(conn_candidate) {
06570
06571 conn_candidate->data = data;
06572 (void)Curl_disconnect(conn_candidate, FALSE);
06573 }
06574 else {
06575 infof(data, "No more connections allowed to host: %d\n",
06576 max_host_connections);
06577 connections_available = FALSE;
06578 }
06579 }
06580
06581 if(connections_available &&
06582 (max_total_connections > 0) &&
06583 (data->state.conn_cache->num_connections >= max_total_connections)) {
06584 struct connectdata *conn_candidate;
06585
06586
06587 conn_candidate = Curl_oldest_idle_connection(data);
06588
06589 if(conn_candidate) {
06590
06591 conn_candidate->data = data;
06592 (void)Curl_disconnect(conn_candidate, FALSE);
06593 }
06594 else {
06595 infof(data, "No connections available in cache\n");
06596 connections_available = FALSE;
06597 }
06598 }
06599
06600 if(!connections_available) {
06601 infof(data, "No connections available.\n");
06602
06603 conn_free(conn);
06604 *in_connect = NULL;
06605
06606 result = CURLE_NO_CONNECTION_AVAILABLE;
06607 goto out;
06608 }
06609 else {
06610
06611
06612
06613
06614 Curl_conncache_add_conn(data->state.conn_cache, conn);
06615 }
06616
06617 #if defined(USE_NTLM)
06618
06619
06620
06621 if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
06622 data->state.authhost.done) {
06623 infof(data, "NTLM picked AND auth done set, clear picked!\n");
06624 data->state.authhost.picked = CURLAUTH_NONE;
06625 data->state.authhost.done = FALSE;
06626 }
06627
06628 if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
06629 data->state.authproxy.done) {
06630 infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
06631 data->state.authproxy.picked = CURLAUTH_NONE;
06632 data->state.authproxy.done = FALSE;
06633 }
06634 #endif
06635 }
06636
06637
06638 conn->inuse = TRUE;
06639
06640
06641 Curl_init_do(data, conn);
06642
06643
06644
06645
06646 result = setup_range(data);
06647 if(result)
06648 goto out;
06649
06650
06651
06652
06653
06654
06655
06656 conn->seek_func = data->set.seek_func;
06657 conn->seek_client = data->set.seek_client;
06658
06659
06660
06661
06662 result = resolve_server(data, conn, async);
06663
06664 out:
06665
06666 free(options);
06667 free(passwd);
06668 free(user);
06669 free(socksproxy);
06670 free(proxy);
06671 return result;
06672 }
06673
06674
06675
06676
06677
06678
06679
06680
06681
06682 CURLcode Curl_setup_conn(struct connectdata *conn,
06683 bool *protocol_done)
06684 {
06685 CURLcode result = CURLE_OK;
06686 struct Curl_easy *data = conn->data;
06687
06688 Curl_pgrsTime(data, TIMER_NAMELOOKUP);
06689
06690 if(conn->handler->flags & PROTOPT_NONETWORK) {
06691
06692 *protocol_done = TRUE;
06693 return result;
06694 }
06695 *protocol_done = FALSE;
06696
06697
06698
06699
06700
06701 conn->bits.proxy_connect_closed = FALSE;
06702
06703
06704
06705
06706
06707
06708 if(data->set.str[STRING_USERAGENT]) {
06709 Curl_safefree(conn->allocptr.uagent);
06710 conn->allocptr.uagent =
06711 aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
06712 if(!conn->allocptr.uagent)
06713 return CURLE_OUT_OF_MEMORY;
06714 }
06715
06716 data->req.headerbytecount = 0;
06717
06718 #ifdef CURL_DO_LINEEND_CONV
06719 data->state.crlf_conversions = 0;
06720 #endif
06721
06722
06723
06724 conn->now = Curl_tvnow();
06725
06726 if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
06727 conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
06728 result = Curl_connecthost(conn, conn->dns_entry);
06729 if(result)
06730 return result;
06731 }
06732 else {
06733 Curl_pgrsTime(data, TIMER_CONNECT);
06734 Curl_pgrsTime(data, TIMER_APPCONNECT);
06735 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
06736 *protocol_done = TRUE;
06737 Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
06738 Curl_verboseconnect(conn);
06739 }
06740
06741 conn->now = Curl_tvnow();
06742
06743
06744 #ifdef __EMX__
06745
06746
06747
06748
06749
06750
06751
06752 if((data->set.out)->_handle == NULL) {
06753 _fsetmode(stdout, "b");
06754 }
06755 #endif
06756
06757 return result;
06758 }
06759
06760 CURLcode Curl_connect(struct Curl_easy *data,
06761 struct connectdata **in_connect,
06762 bool *asyncp,
06763 bool *protocol_done)
06764 {
06765 CURLcode result;
06766
06767 *asyncp = FALSE;
06768
06769
06770 result = create_conn(data, in_connect, asyncp);
06771
06772 if(!result) {
06773
06774 if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size)
06775
06776 *protocol_done = TRUE;
06777 else if(!*asyncp) {
06778
06779
06780
06781 result = Curl_setup_conn(*in_connect, protocol_done);
06782 }
06783 }
06784
06785 if(result == CURLE_NO_CONNECTION_AVAILABLE) {
06786 *in_connect = NULL;
06787 return result;
06788 }
06789
06790 if(result && *in_connect) {
06791
06792
06793 Curl_disconnect(*in_connect, FALSE);
06794 *in_connect = NULL;
06795 }
06796
06797 return result;
06798 }
06799
06800
06801
06802
06803
06804
06805
06806
06807
06808
06809
06810 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
06811 {
06812 struct SingleRequest *k = &data->req;
06813
06814 if(conn)
06815 conn->bits.do_more = FALSE;
06816
06817
06818 data->state.done = FALSE;
06819 data->state.expect100header = FALSE;
06820
06821 if(data->set.opt_no_body)
06822
06823 data->set.httpreq = HTTPREQ_HEAD;
06824 else if(HTTPREQ_HEAD == data->set.httpreq)
06825
06826
06827
06828
06829
06830 data->set.httpreq = HTTPREQ_GET;
06831
06832 k->start = Curl_tvnow();
06833 k->now = k->start;
06834 k->header = TRUE;
06835
06836 k->bytecount = 0;
06837
06838 k->buf = data->state.buffer;
06839 k->uploadbuf = data->state.uploadbuffer;
06840 k->hbufp = data->state.headerbuff;
06841 k->ignorebody=FALSE;
06842
06843 Curl_speedinit(data);
06844
06845 Curl_pgrsSetUploadCounter(data, 0);
06846 Curl_pgrsSetDownloadCounter(data, 0);
06847
06848 return CURLE_OK;
06849 }
06850
06851
06852
06853
06854
06855
06856
06857
06858
06859
06860
06861
06862
06863 unsigned int get_protocol_family(unsigned int protocol)
06864 {
06865 unsigned int family;
06866
06867 switch(protocol) {
06868 case CURLPROTO_HTTP:
06869 case CURLPROTO_HTTPS:
06870 family = CURLPROTO_HTTP;
06871 break;
06872
06873 case CURLPROTO_FTP:
06874 case CURLPROTO_FTPS:
06875 family = CURLPROTO_FTP;
06876 break;
06877
06878 case CURLPROTO_SCP:
06879 family = CURLPROTO_SCP;
06880 break;
06881
06882 case CURLPROTO_SFTP:
06883 family = CURLPROTO_SFTP;
06884 break;
06885
06886 case CURLPROTO_TELNET:
06887 family = CURLPROTO_TELNET;
06888 break;
06889
06890 case CURLPROTO_LDAP:
06891 case CURLPROTO_LDAPS:
06892 family = CURLPROTO_LDAP;
06893 break;
06894
06895 case CURLPROTO_DICT:
06896 family = CURLPROTO_DICT;
06897 break;
06898
06899 case CURLPROTO_FILE:
06900 family = CURLPROTO_FILE;
06901 break;
06902
06903 case CURLPROTO_TFTP:
06904 family = CURLPROTO_TFTP;
06905 break;
06906
06907 case CURLPROTO_IMAP:
06908 case CURLPROTO_IMAPS:
06909 family = CURLPROTO_IMAP;
06910 break;
06911
06912 case CURLPROTO_POP3:
06913 case CURLPROTO_POP3S:
06914 family = CURLPROTO_POP3;
06915 break;
06916
06917 case CURLPROTO_SMTP:
06918 case CURLPROTO_SMTPS:
06919 family = CURLPROTO_SMTP;
06920 break;
06921
06922 case CURLPROTO_RTSP:
06923 family = CURLPROTO_RTSP;
06924 break;
06925
06926 case CURLPROTO_RTMP:
06927 case CURLPROTO_RTMPS:
06928 family = CURLPROTO_RTMP;
06929 break;
06930
06931 case CURLPROTO_RTMPT:
06932 case CURLPROTO_RTMPTS:
06933 family = CURLPROTO_RTMPT;
06934 break;
06935
06936 case CURLPROTO_RTMPE:
06937 family = CURLPROTO_RTMPE;
06938 break;
06939
06940 case CURLPROTO_RTMPTE:
06941 family = CURLPROTO_RTMPTE;
06942 break;
06943
06944 case CURLPROTO_GOPHER:
06945 family = CURLPROTO_GOPHER;
06946 break;
06947
06948 case CURLPROTO_SMB:
06949 case CURLPROTO_SMBS:
06950 family = CURLPROTO_SMB;
06951 break;
06952
06953 default:
06954 family = 0;
06955 break;
06956 }
06957
06958 return family;
06959 }