00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "setup.h"
00027
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <stdarg.h>
00031 #include <stdlib.h>
00032 #include <ctype.h>
00033 #include <errno.h>
00034
00035 #ifdef WIN32
00036 #include <time.h>
00037 #include <io.h>
00038 #else
00039 #ifdef HAVE_SYS_SOCKET_H
00040 #include <sys/socket.h>
00041 #endif
00042 #ifdef HAVE_NETINET_IN_H
00043 #include <netinet/in.h>
00044 #endif
00045 #ifdef HAVE_SYS_TIME_H
00046 #include <sys/time.h>
00047 #endif
00048 #ifdef HAVE_UNISTD_H
00049 #include <unistd.h>
00050 #endif
00051 #ifdef HAVE_NETDB_H
00052 #include <netdb.h>
00053 #endif
00054 #ifdef HAVE_ARPA_INET_H
00055 #include <arpa/inet.h>
00056 #endif
00057 #ifdef HAVE_NET_IF_H
00058 #include <net/if.h>
00059 #endif
00060 #ifdef HAVE_SYS_IOCTL_H
00061 #include <sys/ioctl.h>
00062 #endif
00063 #if HAVE_SIGNAL_H
00064 #include <signal.h>
00065 #endif
00066
00067 #ifdef HAVE_SYS_PARAM_H
00068 #include <sys/param.h>
00069 #endif
00070
00071 #ifdef VMS
00072 #include <in.h>
00073 #include <inet.h>
00074 #endif
00075
00076 #ifdef HAVE_SETJMP_H
00077 #include <setjmp.h>
00078 #endif
00079
00080 #ifndef HAVE_SOCKET
00081 #error "We can't compile without socket() support!"
00082 #endif
00083
00084 #endif
00085
00086 #ifdef USE_LIBIDN
00087 #include <idna.h>
00088 #include <tld.h>
00089 #include <stringprep.h>
00090 #ifdef HAVE_IDN_FREE_H
00091 #include <idn-free.h>
00092 #else
00093 void idn_free (void *ptr);
00094
00095 #endif
00096 #ifndef HAVE_IDN_FREE
00097
00098
00099 #define idn_free(x) (free)(x)
00100 #endif
00101 #endif
00102
00103 #include "urldata.h"
00104 #include "netrc.h"
00105
00106 #include "formdata.h"
00107 #include "base64.h"
00108 #include "sslgen.h"
00109 #include "hostip.h"
00110 #include "transfer.h"
00111 #include "sendf.h"
00112 #include "progress.h"
00113 #include "cookie.h"
00114 #include "strequal.h"
00115 #include "strerror.h"
00116 #include "escape.h"
00117 #include "strtok.h"
00118 #include "share.h"
00119 #include "content_encoding.h"
00120 #include "http_digest.h"
00121 #include "http_negotiate.h"
00122 #include "select.h"
00123 #include "multiif.h"
00124 #include "easyif.h"
00125
00126
00127 #include "ftp.h"
00128 #include "dict.h"
00129 #include "telnet.h"
00130 #include "tftp.h"
00131 #include "http.h"
00132 #include "file.h"
00133 #include "ldap.h"
00134 #include "ssh.h"
00135 #include "url.h"
00136 #include "connect.h"
00137 #include "inet_ntop.h"
00138 #include "http_ntlm.h"
00139 #include "socks.h"
00140 #include "ca-bundle.h"
00141
00142 #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
00143 #include "inet_ntoa_r.h"
00144 #endif
00145
00146 #define _MPRINTF_REPLACE
00147 #include <curl/mprintf.h>
00148
00149 #include "memory.h"
00150
00151
00152 #include "memdebug.h"
00153
00154
00155 static long ConnectionKillOne(struct SessionHandle *data);
00156 static bool ConnectionExists(struct SessionHandle *data,
00157 struct connectdata *needle,
00158 struct connectdata **usethis);
00159 static long ConnectionStore(struct SessionHandle *data,
00160 struct connectdata *conn);
00161 static bool IsPipeliningPossible(struct SessionHandle *handle);
00162 static bool IsPipeliningEnabled(struct SessionHandle *handle);
00163 static void conn_free(struct connectdata *conn);
00164
00165 static void signalPipeClose(struct curl_llist *pipe);
00166
00167 static struct SessionHandle* gethandleathead(struct curl_llist *pipe);
00168
00169 #define MAX_PIPELINE_LENGTH 5
00170
00171
00172
00173
00174
00175
00176 #define ZERO_NULL 0
00177
00178 #ifndef USE_ARES
00179
00180
00181 #ifndef WIN32
00182
00183
00184 #ifdef HAVE_SIGSETJMP
00185 extern sigjmp_buf curl_jmpenv;
00186 #endif
00187
00188 #ifdef SIGALRM
00189 static
00190 RETSIGTYPE alarmfunc(int sig)
00191 {
00192
00193 (void)sig;
00194 #ifdef HAVE_SIGSETJMP
00195 siglongjmp(curl_jmpenv, 1);
00196 #endif
00197 return;
00198 }
00199 #endif
00200 #endif
00201 #endif
00202
00203 #ifdef CURL_DISABLE_VERBOSE_STRINGS
00204 #define verboseconnect(x) do { } while (0)
00205 #endif
00206
00207 void Curl_safefree(void *ptr)
00208 {
00209 if(ptr)
00210 free(ptr);
00211 }
00212
00213 static void close_connections(struct SessionHandle *data)
00214 {
00215
00216 while(-1 != ConnectionKillOne(data))
00217 ;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 CURLcode Curl_close(struct SessionHandle *data)
00230 {
00231 struct Curl_multi *m = data->multi;
00232
00233 #ifdef CURLDEBUG
00234
00235
00236
00237 if(data->state.is_in_pipeline)
00238 fprintf(stderr, "CLOSED when in pipeline!\n");
00239
00240 if(data->state.connc && data->state.connc->type == CONNCACHE_MULTI) {
00241 struct conncache *c = data->state.connc;
00242 int i;
00243 struct curl_llist *pipe;
00244 struct curl_llist_element *curr;
00245 struct connectdata *connptr;
00246
00247 for(i=0; i< c->num; i++) {
00248 connptr = c->connects[i];
00249 if(!connptr)
00250 continue;
00251
00252 pipe = connptr->send_pipe;
00253 if(pipe) {
00254 for (curr = pipe->head; curr; curr=curr->next) {
00255 if(data == (struct SessionHandle *) curr->ptr) {
00256 fprintf(stderr,
00257 "MAJOR problem we %p are still in send pipe for %p done %d\n",
00258 data, connptr, connptr->bits.done);
00259 }
00260 }
00261 }
00262 pipe = connptr->recv_pipe;
00263 if(pipe) {
00264 for (curr = pipe->head; curr; curr=curr->next) {
00265 if(data == (struct SessionHandle *) curr->ptr) {
00266 fprintf(stderr,
00267 "MAJOR problem we %p are still in recv pipe for %p done %d\n",
00268 data, connptr, connptr->bits.done);
00269 }
00270 }
00271 }
00272 }
00273 }
00274 #endif
00275
00276 if(m)
00277
00278
00279 Curl_multi_rmeasy(data->multi, data);
00280
00281 data->magic = 0;
00282
00283
00284
00285 if(data->state.connc) {
00286
00287 if(data->state.connc->type == CONNCACHE_PRIVATE) {
00288
00289
00290 close_connections(data);
00291
00292
00293 Curl_rm_connc(data->state.connc);
00294 }
00295 }
00296
00297 if(data->state.shared_conn) {
00298
00299
00300 data->state.closed = TRUE;
00301 return CURLE_OK;
00302 }
00303
00304 if ( ! (data->share && data->share->hostcache) ) {
00305 if ( !Curl_global_host_cache_use(data)) {
00306 Curl_hash_destroy(data->dns.hostcache);
00307 }
00308 }
00309
00310 if(data->reqdata.rangestringalloc)
00311 free(data->reqdata.range);
00312
00313
00314 Curl_safefree(data->reqdata.pathbuffer);
00315 Curl_safefree(data->reqdata.proto.generic);
00316
00317
00318 Curl_ssl_close_all(data);
00319 Curl_safefree(data->state.first_host);
00320 Curl_safefree(data->state.scratch);
00321
00322 if(data->change.referer_alloc)
00323 free(data->change.referer);
00324
00325 if(data->change.url_alloc)
00326 free(data->change.url);
00327
00328 Curl_safefree(data->state.headerbuff);
00329
00330 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
00331 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
00332 if(data->set.cookiejar) {
00333 if(data->change.cookielist) {
00334
00335
00336 Curl_cookie_loadfiles(data);
00337 }
00338
00339
00340 if(Curl_cookie_output(data->cookies, data->set.cookiejar))
00341 infof(data, "WARNING: failed to save cookies in %s\n",
00342 data->set.cookiejar);
00343 }
00344 else {
00345 if(data->change.cookielist)
00346
00347
00348 curl_slist_free_all(data->change.cookielist);
00349 }
00350
00351 if( !data->share || (data->cookies != data->share->cookies) ) {
00352 Curl_cookie_cleanup(data->cookies);
00353 }
00354 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
00355 #endif
00356
00357 Curl_digest_cleanup(data);
00358
00359 Curl_safefree(data->info.contenttype);
00360
00361
00362 ares_destroy(data->state.areschannel);
00363
00364 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
00365
00366 if (data->inbound_cd != (iconv_t)-1) {
00367 iconv_close(data->inbound_cd);
00368 }
00369 if (data->outbound_cd != (iconv_t)-1) {
00370 iconv_close(data->outbound_cd);
00371 }
00372 if (data->utf8_cd != (iconv_t)-1) {
00373 iconv_close(data->utf8_cd);
00374 }
00375 #endif
00376
00377
00378 if (data->share) {
00379 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
00380 data->share->dirty--;
00381 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
00382 }
00383
00384 free(data);
00385 return CURLE_OK;
00386 }
00387
00388
00389 struct conncache *Curl_mk_connc(int type,
00390 long amount)
00391 {
00392
00393
00394
00395 struct conncache *c;
00396 long default_amount;
00397
00398 if (type == CONNCACHE_PRIVATE) {
00399 default_amount = (amount < 0) ? 5 : amount;
00400 }
00401 else {
00402 default_amount = (amount < 0) ? 10 : amount;
00403 }
00404
00405 c= calloc(sizeof(struct conncache), 1);
00406 if(!c)
00407 return NULL;
00408
00409 if ((size_t)(default_amount) > ((size_t)-1) / sizeof(struct connectdata *))
00410 default_amount = ((size_t)-1) / sizeof(struct connectdata *);
00411
00412 c->connects = calloc(sizeof(struct connectdata *), (size_t)default_amount);
00413 if(!c->connects) {
00414 free(c);
00415 return NULL;
00416 }
00417
00418 c->num = default_amount;
00419
00420 return c;
00421 }
00422
00423
00424 CURLcode Curl_ch_connc(struct SessionHandle *data,
00425 struct conncache *c,
00426 long newamount)
00427 {
00428 long i;
00429 struct connectdata **newptr;
00430
00431 if(newamount < 1)
00432 newamount = 1;
00433
00434 if(!c) {
00435
00436
00437
00438
00439 data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, newamount);
00440 if(!data->state.connc)
00441 return CURLE_OUT_OF_MEMORY;
00442 return CURLE_OK;
00443 }
00444
00445 if(newamount < c->num) {
00446
00447
00448
00449
00450
00451
00452
00453 for(i=newamount; i< c->num; i++)
00454 Curl_disconnect(c->connects[i]);
00455
00456
00457
00458 if(data->state.lastconnect <= newamount)
00459 data->state.lastconnect = -1;
00460 }
00461 if(newamount > 0) {
00462 newptr= (struct connectdata **)
00463 realloc(c->connects, sizeof(struct connectdata *) * newamount);
00464 if(!newptr)
00465
00466 return CURLE_OUT_OF_MEMORY;
00467
00468
00469 for(i=c->num; i<newamount; i++)
00470 newptr[i] = NULL;
00471
00472 c->connects = newptr;
00473 c->num = newamount;
00474 }
00475
00476
00477 return CURLE_OK;
00478 }
00479
00480
00481
00482 void Curl_rm_connc(struct conncache *c)
00483 {
00484 if(c->connects) {
00485 int i;
00486 for(i = 0; i < c->num; ++i)
00487 conn_free(c->connects[i]);
00488
00489 free(c->connects);
00490 }
00491
00492 free(c);
00493 }
00494
00503 CURLcode Curl_open(struct SessionHandle **curl)
00504 {
00505 CURLcode res = CURLE_OK;
00506 struct SessionHandle *data;
00507 #ifdef USE_ARES
00508 int status;
00509 #endif
00510
00511
00512 data = (struct SessionHandle *)calloc(1, sizeof(struct SessionHandle));
00513 if(!data) {
00514
00515 DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n"));
00516 return CURLE_OUT_OF_MEMORY;
00517 }
00518
00519 data->magic = CURLEASY_MAGIC_NUMBER;
00520
00521 #ifdef USE_ARES
00522 if ((status = ares_init(&data->state.areschannel)) != ARES_SUCCESS) {
00523 DEBUGF(fprintf(stderr, "Error: ares_init failed\n"));
00524 free(data);
00525 if (status == ARES_ENOMEM)
00526 return CURLE_OUT_OF_MEMORY;
00527 else
00528 return CURLE_FAILED_INIT;
00529 }
00530
00531
00532 #endif
00533
00534
00535
00536 data->state.headerbuff=(char*)malloc(HEADERSIZE);
00537 if(!data->state.headerbuff) {
00538 DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
00539 res = CURLE_OUT_OF_MEMORY;
00540 }
00541 else {
00542 data->state.headersize=HEADERSIZE;
00543
00544 data->set.out = stdout;
00545 data->set.in = stdin;
00546 data->set.err = stderr;
00547
00548
00549 data->set.fwrite = (curl_write_callback)fwrite;
00550
00551
00552 data->set.fread = (curl_read_callback)fread;
00553
00554
00555 data->set.convfromnetwork = (curl_conv_callback)ZERO_NULL;
00556 data->set.convtonetwork = (curl_conv_callback)ZERO_NULL;
00557 data->set.convfromutf8 = (curl_conv_callback)ZERO_NULL;
00558
00559 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
00560
00561 data->outbound_cd = (iconv_t)-1;
00562 data->inbound_cd = (iconv_t)-1;
00563 data->utf8_cd = (iconv_t)-1;
00564 #endif
00565
00566 data->set.infilesize = -1;
00567 data->set.postfieldsize = -1;
00568 data->set.maxredirs = -1;
00569 data->state.current_speed = -1;
00570
00571 data->set.httpreq = HTTPREQ_GET;
00572 data->set.ftp_use_epsv = TRUE;
00573 data->set.ftp_use_eprt = TRUE;
00574 data->set.ftp_filemethod = FTPFILE_MULTICWD;
00575 data->set.dns_cache_timeout = 60;
00576
00577
00578 data->set.hide_progress = TRUE;
00579 data->progress.flags |= PGRS_HIDE;
00580
00581
00582 data->set.ssl.numsessions = 5;
00583
00584 data->set.proxyport = 1080;
00585 data->set.proxytype = CURLPROXY_HTTP;
00586 data->set.httpauth = CURLAUTH_BASIC;
00587 data->set.proxyauth = CURLAUTH_BASIC;
00588
00589
00590
00591
00592
00593 data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT;
00594
00595 data->set.new_file_perms = 0644;
00596 data->set.new_directory_perms = 0755;
00597
00598
00599 data->state.lastconnect = -1;
00600
00601 Curl_easy_initHandleData(data);
00602
00603
00604
00605
00606
00607 data->set.ssl.verifypeer = TRUE;
00608 data->set.ssl.verifyhost = 2;
00609 data->set.ssl.sessionid = TRUE;
00610 #ifdef CURL_CA_BUNDLE
00611
00612 data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
00613 #endif
00614 }
00615
00616 if(res) {
00617 ares_destroy(data->state.areschannel);
00618 if(data->state.headerbuff)
00619 free(data->state.headerbuff);
00620 free(data);
00621 data = NULL;
00622 }
00623 else
00624 *curl = data;
00625
00626 return res;
00627 }
00628
00629 CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
00630 va_list param)
00631 {
00632 char *argptr;
00633 CURLcode result = CURLE_OK;
00634
00635 switch(option) {
00636 case CURLOPT_DNS_CACHE_TIMEOUT:
00637 data->set.dns_cache_timeout = va_arg(param, int);
00638 break;
00639 case CURLOPT_DNS_USE_GLOBAL_CACHE:
00640 {
00641 int use_cache = va_arg(param, int);
00642 if (use_cache) {
00643 Curl_global_host_cache_init();
00644 }
00645
00646 data->set.global_dns_cache = (bool)(0 != use_cache);
00647 }
00648 break;
00649 case CURLOPT_SSL_CIPHER_LIST:
00650
00651 data->set.ssl.cipher_list = va_arg(param, char *);
00652 break;
00653
00654 case CURLOPT_RANDOM_FILE:
00655
00656
00657
00658
00659 data->set.ssl.random_file = va_arg(param, char *);
00660 break;
00661 case CURLOPT_EGDSOCKET:
00662
00663
00664
00665 data->set.ssl.egdsocket = va_arg(param, char *);
00666 break;
00667 case CURLOPT_MAXCONNECTS:
00668
00669
00670
00671
00672 result = Curl_ch_connc(data, data->state.connc, va_arg(param, long));
00673 break;
00674 case CURLOPT_FORBID_REUSE:
00675
00676
00677
00678
00679 data->set.reuse_forbid = (bool)(0 != va_arg(param, long));
00680 break;
00681 case CURLOPT_FRESH_CONNECT:
00682
00683
00684
00685
00686 data->set.reuse_fresh = (bool)(0 != va_arg(param, long));
00687 break;
00688 case CURLOPT_VERBOSE:
00689
00690
00691
00692
00693 data->set.verbose = (bool)(0 != va_arg(param, long));
00694 break;
00695 case CURLOPT_HEADER:
00696
00697
00698
00699 data->set.include_header = (bool)(0 != va_arg(param, long));
00700 break;
00701 case CURLOPT_NOPROGRESS:
00702
00703
00704
00705 data->set.hide_progress = (bool)(0 != va_arg(param, long));
00706 if(data->set.hide_progress)
00707 data->progress.flags |= PGRS_HIDE;
00708 else
00709 data->progress.flags &= ~PGRS_HIDE;
00710 break;
00711 case CURLOPT_NOBODY:
00712
00713
00714
00715 data->set.opt_no_body = (bool)(0 != va_arg(param, long));
00716 if(data->set.opt_no_body)
00717
00718 data->set.httpreq = HTTPREQ_HEAD;
00719 break;
00720 case CURLOPT_FAILONERROR:
00721
00722
00723
00724
00725 data->set.http_fail_on_error = (bool)(0 != va_arg(param, long));
00726 break;
00727 case CURLOPT_UPLOAD:
00728 case CURLOPT_PUT:
00729
00730
00731
00732
00733 data->set.upload = (bool)(0 != va_arg(param, long));
00734 if(data->set.upload)
00735
00736 data->set.httpreq = HTTPREQ_PUT;
00737 break;
00738 case CURLOPT_FILETIME:
00739
00740
00741
00742
00743 data->set.get_filetime = (bool)(0 != va_arg(param, long));
00744 break;
00745 case CURLOPT_FTP_CREATE_MISSING_DIRS:
00746
00747
00748
00749
00750 data->set.ftp_create_missing_dirs = (bool)(0 != va_arg(param, long));
00751 break;
00752 case CURLOPT_FTP_RESPONSE_TIMEOUT:
00753
00754
00755
00756
00757 data->set.ftp_response_timeout = va_arg( param , long ) * 1000;
00758 break;
00759 case CURLOPT_FTPLISTONLY:
00760
00761
00762
00763
00764 data->set.ftp_list_only = (bool)(0 != va_arg(param, long));
00765 break;
00766 case CURLOPT_FTPAPPEND:
00767
00768
00769
00770 data->set.ftp_append = (bool)(0 != va_arg(param, long));
00771 break;
00772 case CURLOPT_FTP_FILEMETHOD:
00773
00774
00775
00776 data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
00777 break;
00778 case CURLOPT_NETRC:
00779
00780
00781
00782 data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
00783 break;
00784 case CURLOPT_NETRC_FILE:
00785
00786
00787
00788 data->set.netrc_file = va_arg(param, char *);
00789 break;
00790 case CURLOPT_TRANSFERTEXT:
00791
00792
00793
00794
00795
00796
00797 data->set.prefer_ascii = (bool)(0 != va_arg(param, long));
00798 break;
00799 case CURLOPT_TIMECONDITION:
00800
00801
00802
00803
00804 data->set.timecondition = (curl_TimeCond)va_arg(param, long);
00805 break;
00806 case CURLOPT_TIMEVALUE:
00807
00808
00809
00810
00811 data->set.timevalue = (time_t)va_arg(param, long);
00812 break;
00813 case CURLOPT_SSLVERSION:
00814
00815
00816
00817
00818 data->set.ssl.version = va_arg(param, long);
00819 break;
00820
00821 #ifndef CURL_DISABLE_HTTP
00822 case CURLOPT_AUTOREFERER:
00823
00824
00825
00826 data->set.http_auto_referer = (bool)(0 != va_arg(param, long));
00827 break;
00828
00829 case CURLOPT_ENCODING:
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839 data->set.encoding = va_arg(param, char *);
00840 if(data->set.encoding && !*data->set.encoding)
00841 data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
00842 break;
00843
00844 case CURLOPT_FOLLOWLOCATION:
00845
00846
00847
00848 data->set.http_follow_location = (bool)(0 != va_arg(param, long));
00849 break;
00850
00851 case CURLOPT_UNRESTRICTED_AUTH:
00852
00853
00854
00855
00856 data->set.http_disable_hostname_check_before_authentication =
00857 (bool)(0 != va_arg(param, long));
00858 break;
00859
00860 case CURLOPT_MAXREDIRS:
00861
00862
00863
00864
00865 data->set.maxredirs = va_arg(param, long);
00866 break;
00867
00868 case CURLOPT_POST:
00869
00870
00871
00872 if(va_arg(param, long)) {
00873 data->set.httpreq = HTTPREQ_POST;
00874 data->set.opt_no_body = FALSE;
00875 }
00876 else
00877 data->set.httpreq = HTTPREQ_GET;
00878 break;
00879
00880 case CURLOPT_POSTFIELDS:
00881
00882
00883
00884 data->set.postfields = va_arg(param, char *);
00885 data->set.httpreq = HTTPREQ_POST;
00886 break;
00887
00888 case CURLOPT_POSTFIELDSIZE:
00889
00890
00891
00892
00893 data->set.postfieldsize = va_arg(param, long);
00894 break;
00895
00896 case CURLOPT_POSTFIELDSIZE_LARGE:
00897
00898
00899
00900
00901 data->set.postfieldsize = va_arg(param, curl_off_t);
00902 break;
00903
00904 case CURLOPT_HTTPPOST:
00905
00906
00907
00908 data->set.httppost = va_arg(param, struct curl_httppost *);
00909 data->set.httpreq = HTTPREQ_POST_FORM;
00910 data->set.opt_no_body = FALSE;
00911 break;
00912
00913 case CURLOPT_REFERER:
00914
00915
00916
00917 if(data->change.referer_alloc) {
00918 free(data->change.referer);
00919 data->change.referer_alloc = FALSE;
00920 }
00921 data->set.set_referer = va_arg(param, char *);
00922 data->change.referer = data->set.set_referer;
00923 break;
00924
00925 case CURLOPT_USERAGENT:
00926
00927
00928
00929 data->set.useragent = va_arg(param, char *);
00930 break;
00931
00932 case CURLOPT_HTTPHEADER:
00933
00934
00935
00936 data->set.headers = va_arg(param, struct curl_slist *);
00937 break;
00938
00939 case CURLOPT_HTTP200ALIASES:
00940
00941
00942
00943 data->set.http200aliases = va_arg(param, struct curl_slist *);
00944 break;
00945
00946 #if !defined(CURL_DISABLE_COOKIES)
00947 case CURLOPT_COOKIE:
00948
00949
00950
00951 data->set.cookie = va_arg(param, char *);
00952 break;
00953
00954 case CURLOPT_COOKIEFILE:
00955
00956
00957
00958 argptr = (char *)va_arg(param, void *);
00959 if(argptr) {
00960 struct curl_slist *cl;
00961
00962
00963 cl = curl_slist_append(data->change.cookielist, argptr);
00964
00965 if(!cl)
00966 return CURLE_OUT_OF_MEMORY;
00967
00968 data->change.cookielist = cl;
00969 }
00970 break;
00971
00972 case CURLOPT_COOKIEJAR:
00973
00974
00975
00976 data->set.cookiejar = (char *)va_arg(param, void *);
00977
00978
00979
00980
00981
00982 data->cookies = Curl_cookie_init(data, NULL, data->cookies,
00983 data->set.cookiesession);
00984 break;
00985
00986 case CURLOPT_COOKIESESSION:
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 data->set.cookiesession = (bool)(0 != va_arg(param, long));
01003 break;
01004
01005 case CURLOPT_COOKIELIST:
01006 argptr = va_arg(param, char *);
01007
01008 if(argptr == NULL)
01009 break;
01010
01011 if(strequal(argptr, "ALL")) {
01012
01013 Curl_cookie_clearall(data->cookies);
01014 break;
01015 }
01016 else if(strequal(argptr, "SESS")) {
01017
01018 Curl_cookie_clearsess(data->cookies);
01019 break;
01020 }
01021
01022 if(!data->cookies)
01023
01024 data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
01025
01026 argptr = strdup(argptr);
01027 if(!argptr) {
01028 result = CURLE_OUT_OF_MEMORY;
01029 break;
01030 }
01031
01032 if(checkprefix("Set-Cookie:", argptr))
01033
01034 Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
01035
01036 else
01037
01038 Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
01039
01040 free(argptr);
01041 break;
01042 #endif
01043
01044 case CURLOPT_HTTPGET:
01045
01046
01047
01048 if(va_arg(param, long)) {
01049 data->set.httpreq = HTTPREQ_GET;
01050 data->set.upload = FALSE;
01051 data->set.opt_no_body = FALSE;
01052 }
01053 break;
01054
01055 case CURLOPT_HTTP_VERSION:
01056
01057
01058
01059
01060 data->set.httpversion = va_arg(param, long);
01061 break;
01062
01063 case CURLOPT_HTTPPROXYTUNNEL:
01064
01065
01066
01067 data->set.tunnel_thru_httpproxy = (bool)(0 != va_arg(param, long));
01068 break;
01069
01070 case CURLOPT_CUSTOMREQUEST:
01071
01072
01073
01074 data->set.customrequest = va_arg(param, char *);
01075
01076
01077
01078
01079
01080 break;
01081
01082 case CURLOPT_PROXYPORT:
01083
01084
01085
01086 data->set.proxyport = va_arg(param, long);
01087 break;
01088
01089 case CURLOPT_HTTPAUTH:
01090
01091
01092
01093 {
01094 long auth = va_arg(param, long);
01095
01096 #ifndef USE_NTLM
01097 auth &= ~CURLAUTH_NTLM;
01098 #endif
01099 #ifndef HAVE_GSSAPI
01100 auth &= ~CURLAUTH_GSSNEGOTIATE;
01101 #endif
01102 if(!auth)
01103 return CURLE_FAILED_INIT;
01104
01105 data->set.httpauth = auth;
01106 }
01107 break;
01108
01109 case CURLOPT_PROXYAUTH:
01110
01111
01112
01113 {
01114 long auth = va_arg(param, long);
01115
01116 #ifndef USE_NTLM
01117 auth &= ~CURLAUTH_NTLM;
01118 #endif
01119 #ifndef HAVE_GSSAPI
01120 auth &= ~CURLAUTH_GSSNEGOTIATE;
01121 #endif
01122 if(!auth)
01123 return CURLE_FAILED_INIT;
01124
01125 data->set.proxyauth = auth;
01126 }
01127 break;
01128 #endif
01129
01130 case CURLOPT_PROXY:
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 data->set.proxy = va_arg(param, char *);
01141 break;
01142
01143 case CURLOPT_WRITEHEADER:
01144
01145
01146
01147 data->set.writeheader = (void *)va_arg(param, void *);
01148 break;
01149 case CURLOPT_ERRORBUFFER:
01150
01151
01152
01153
01154 data->set.errorbuffer = va_arg(param, char *);
01155 break;
01156 case CURLOPT_FILE:
01157
01158
01159
01160 data->set.out = va_arg(param, FILE *);
01161 break;
01162 case CURLOPT_FTPPORT:
01163
01164
01165
01166 data->set.ftpport = va_arg(param, char *);
01167 data->set.ftp_use_port = (bool)(NULL != data->set.ftpport);
01168 break;
01169
01170 case CURLOPT_FTP_USE_EPRT:
01171 data->set.ftp_use_eprt = (bool)(0 != va_arg(param, long));
01172 break;
01173
01174 case CURLOPT_FTP_USE_EPSV:
01175 data->set.ftp_use_epsv = (bool)(0 != va_arg(param, long));
01176 break;
01177
01178 case CURLOPT_FTP_SSL_CCC:
01179 data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
01180 break;
01181
01182 case CURLOPT_FTP_SKIP_PASV_IP:
01183
01184
01185
01186
01187 data->set.ftp_skip_ip = (bool)(0 != va_arg(param, long));
01188 break;
01189
01190 case CURLOPT_INFILE:
01191
01192
01193
01194
01195 data->set.in = va_arg(param, FILE *);
01196 break;
01197 case CURLOPT_INFILESIZE:
01198
01199
01200
01201
01202 data->set.infilesize = va_arg(param, long);
01203 break;
01204 case CURLOPT_INFILESIZE_LARGE:
01205
01206
01207
01208
01209 data->set.infilesize = va_arg(param, curl_off_t);
01210 break;
01211 case CURLOPT_LOW_SPEED_LIMIT:
01212
01213
01214
01215
01216 data->set.low_speed_limit=va_arg(param, long);
01217 break;
01218 case CURLOPT_MAX_SEND_SPEED_LARGE:
01219
01220
01221
01222
01223
01224 data->set.max_send_speed=va_arg(param, curl_off_t);
01225 break;
01226 case CURLOPT_MAX_RECV_SPEED_LARGE:
01227
01228
01229
01230
01231
01232 data->set.max_recv_speed=va_arg(param, curl_off_t);
01233 break;
01234 case CURLOPT_LOW_SPEED_TIME:
01235
01236
01237
01238
01239 data->set.low_speed_time=va_arg(param, long);
01240 break;
01241 case CURLOPT_URL:
01242
01243
01244
01245 if(data->change.url_alloc) {
01246
01247 free(data->change.url);
01248 data->change.url_alloc=FALSE;
01249 }
01250 data->set.set_url = va_arg(param, char *);
01251 data->change.url = data->set.set_url;
01252 data->change.url_changed = TRUE;
01253 break;
01254 case CURLOPT_PORT:
01255
01256
01257
01258 data->set.use_port = va_arg(param, long);
01259 break;
01260 case CURLOPT_TIMEOUT:
01261
01262
01263
01264
01265 data->set.timeout = va_arg(param, long) * 1000L;
01266 break;
01267
01268 case CURLOPT_TIMEOUT_MS:
01269 data->set.timeout = va_arg(param, long);
01270 break;
01271
01272 case CURLOPT_CONNECTTIMEOUT:
01273
01274
01275
01276 data->set.connecttimeout = va_arg(param, long) * 1000L;
01277 break;
01278
01279 case CURLOPT_CONNECTTIMEOUT_MS:
01280 data->set.connecttimeout = va_arg(param, long);
01281 break;
01282
01283 case CURLOPT_USERPWD:
01284
01285
01286
01287 data->set.userpwd = va_arg(param, char *);
01288 break;
01289 case CURLOPT_POSTQUOTE:
01290
01291
01292
01293 data->set.postquote = va_arg(param, struct curl_slist *);
01294 break;
01295 case CURLOPT_PREQUOTE:
01296
01297
01298
01299 data->set.prequote = va_arg(param, struct curl_slist *);
01300 break;
01301 case CURLOPT_QUOTE:
01302
01303
01304
01305 data->set.quote = va_arg(param, struct curl_slist *);
01306 break;
01307 case CURLOPT_PROGRESSFUNCTION:
01308
01309
01310
01311 data->set.fprogress = va_arg(param, curl_progress_callback);
01312 if(data->set.fprogress)
01313 data->progress.callback = TRUE;
01314 else
01315 data->progress.callback = FALSE;
01316
01317 break;
01318 case CURLOPT_PROGRESSDATA:
01319
01320
01321
01322 data->set.progress_client = va_arg(param, void *);
01323 break;
01324 case CURLOPT_PROXYUSERPWD:
01325
01326
01327
01328 data->set.proxyuserpwd = va_arg(param, char *);
01329 break;
01330 case CURLOPT_RANGE:
01331
01332
01333
01334 data->set.set_range = va_arg(param, char *);
01335 break;
01336 case CURLOPT_RESUME_FROM:
01337
01338
01339
01340 data->set.set_resume_from = va_arg(param, long);
01341 break;
01342 case CURLOPT_RESUME_FROM_LARGE:
01343
01344
01345
01346 data->set.set_resume_from = va_arg(param, curl_off_t);
01347 break;
01348 case CURLOPT_DEBUGFUNCTION:
01349
01350
01351
01352 data->set.fdebug = va_arg(param, curl_debug_callback);
01353
01354
01355
01356 break;
01357 case CURLOPT_DEBUGDATA:
01358
01359
01360
01361
01362 data->set.debugdata = va_arg(param, void *);
01363 break;
01364 case CURLOPT_STDERR:
01365
01366
01367
01368
01369 data->set.err = va_arg(param, FILE *);
01370 if(!data->set.err)
01371 data->set.err = stderr;
01372 break;
01373 case CURLOPT_HEADERFUNCTION:
01374
01375
01376
01377 data->set.fwrite_header = va_arg(param, curl_write_callback);
01378 break;
01379 case CURLOPT_WRITEFUNCTION:
01380
01381
01382
01383 data->set.fwrite = va_arg(param, curl_write_callback);
01384 if(!data->set.fwrite)
01385
01386 data->set.fwrite = (curl_write_callback)fwrite;
01387 break;
01388 case CURLOPT_READFUNCTION:
01389
01390
01391
01392 data->set.fread = va_arg(param, curl_read_callback);
01393 if(!data->set.fread)
01394
01395 data->set.fread = (curl_read_callback)fread;
01396 break;
01397 case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
01398
01399
01400
01401 data->set.convfromnetwork = va_arg(param, curl_conv_callback);
01402 break;
01403 case CURLOPT_CONV_TO_NETWORK_FUNCTION:
01404
01405
01406
01407 data->set.convtonetwork = va_arg(param, curl_conv_callback);
01408 break;
01409 case CURLOPT_CONV_FROM_UTF8_FUNCTION:
01410
01411
01412
01413 data->set.convfromutf8 = va_arg(param, curl_conv_callback);
01414 break;
01415 case CURLOPT_IOCTLFUNCTION:
01416
01417
01418
01419 data->set.ioctl = va_arg(param, curl_ioctl_callback);
01420 break;
01421 case CURLOPT_IOCTLDATA:
01422
01423
01424
01425 data->set.ioctl_client = va_arg(param, void *);
01426 break;
01427 case CURLOPT_SSLCERT:
01428
01429
01430
01431 data->set.cert = va_arg(param, char *);
01432 break;
01433 case CURLOPT_SSLCERTTYPE:
01434
01435
01436
01437 data->set.cert_type = va_arg(param, char *);
01438 break;
01439 case CURLOPT_SSLKEY:
01440
01441
01442
01443 data->set.key = va_arg(param, char *);
01444 break;
01445 case CURLOPT_SSLKEYTYPE:
01446
01447
01448
01449 data->set.key_type = va_arg(param, char *);
01450 break;
01451 case CURLOPT_SSLKEYPASSWD:
01452
01453
01454
01455 data->set.key_passwd = va_arg(param, char *);
01456 break;
01457 case CURLOPT_SSLENGINE:
01458
01459
01460
01461 argptr = va_arg(param, char *);
01462 if (argptr && argptr[0])
01463 result = Curl_ssl_set_engine(data, argptr);
01464 break;
01465
01466 case CURLOPT_SSLENGINE_DEFAULT:
01467
01468
01469
01470 result = Curl_ssl_set_engine_default(data);
01471 break;
01472 case CURLOPT_CRLF:
01473
01474
01475
01476 data->set.crlf = (bool)(0 != va_arg(param, long));
01477 break;
01478
01479 case CURLOPT_INTERFACE:
01480
01481
01482
01483
01484 data->set.device = va_arg(param, char *);
01485 break;
01486 case CURLOPT_LOCALPORT:
01487
01488
01489
01490 data->set.localport = (unsigned short) va_arg(param, long);
01491 break;
01492 case CURLOPT_LOCALPORTRANGE:
01493
01494
01495
01496 data->set.localportrange = (int) va_arg(param, long);
01497 break;
01498 case CURLOPT_KRBLEVEL:
01499
01500
01501
01502 data->set.krb_level = va_arg(param, char *);
01503 data->set.krb = (bool)(NULL != data->set.krb_level);
01504 break;
01505 case CURLOPT_SSL_VERIFYPEER:
01506
01507
01508
01509 data->set.ssl.verifypeer = va_arg(param, long);
01510 break;
01511 case CURLOPT_SSL_VERIFYHOST:
01512
01513
01514
01515 data->set.ssl.verifyhost = va_arg(param, long);
01516 break;
01517 case CURLOPT_SSL_CTX_FUNCTION:
01518
01519
01520
01521 data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
01522 break;
01523 case CURLOPT_SSL_CTX_DATA:
01524
01525
01526
01527 data->set.ssl.fsslctxp = va_arg(param, void *);
01528 break;
01529 case CURLOPT_CAINFO:
01530
01531
01532
01533 data->set.ssl.CAfile = va_arg(param, char *);
01534 break;
01535 case CURLOPT_CAPATH:
01536
01537
01538
01539
01540
01541 data->set.ssl.CApath = va_arg(param, char *);
01542 break;
01543 case CURLOPT_TELNETOPTIONS:
01544
01545
01546
01547 data->set.telnet_options = va_arg(param, struct curl_slist *);
01548 break;
01549
01550 case CURLOPT_BUFFERSIZE:
01551
01552
01553
01554
01555 data->set.buffer_size = va_arg(param, long);
01556
01557 if((data->set.buffer_size> (BUFSIZE -1 )) ||
01558 (data->set.buffer_size < 1))
01559 data->set.buffer_size = 0;
01560
01561 break;
01562
01563 case CURLOPT_NOSIGNAL:
01564
01565
01566
01567
01568 data->set.no_signal = (bool)(0 != va_arg(param, long));
01569 break;
01570
01571 case CURLOPT_SHARE:
01572 {
01573 struct Curl_share *set;
01574 set = va_arg(param, struct Curl_share *);
01575
01576
01577 if(data->share) {
01578 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
01579
01580 if(data->dns.hostcachetype == HCACHE_SHARED) {
01581 data->dns.hostcache = NULL;
01582 data->dns.hostcachetype = HCACHE_NONE;
01583 }
01584
01585 if(data->share->cookies == data->cookies)
01586 data->cookies = NULL;
01587
01588 data->share->dirty--;
01589
01590 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
01591 data->share = NULL;
01592 }
01593
01594
01595 data->share = set;
01596 if(data->share) {
01597
01598 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
01599
01600 data->share->dirty++;
01601
01602 if(data->share->hostcache) {
01603
01604 if(data->dns.hostcachetype == HCACHE_PRIVATE)
01605 Curl_hash_destroy(data->dns.hostcache);
01606
01607 data->dns.hostcache = data->share->hostcache;
01608 data->dns.hostcachetype = HCACHE_SHARED;
01609 }
01610 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
01611 if(data->share->cookies) {
01612
01613 if (data->cookies)
01614 Curl_cookie_cleanup(data->cookies);
01615 data->cookies = data->share->cookies;
01616 }
01617 #endif
01618 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
01619
01620 }
01621 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
01622
01623 if(!data->cookies)
01624 data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE );
01625 #endif
01626
01627
01628 }
01629 break;
01630
01631 case CURLOPT_PROXYTYPE:
01632
01633
01634
01635 data->set.proxytype = (curl_proxytype)va_arg(param, long);
01636 break;
01637
01638 case CURLOPT_PRIVATE:
01639
01640
01641
01642 data->set.private_data = va_arg(param, char *);
01643 break;
01644
01645 case CURLOPT_MAXFILESIZE:
01646
01647
01648
01649 data->set.max_filesize = va_arg(param, long);
01650 break;
01651
01652 case CURLOPT_FTP_SSL:
01653
01654
01655
01656 data->set.ftp_ssl = (curl_ftpssl)va_arg(param, long);
01657 break;
01658
01659 case CURLOPT_FTPSSLAUTH:
01660
01661
01662
01663 data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
01664 break;
01665
01666 case CURLOPT_IPRESOLVE:
01667 data->set.ip_version = va_arg(param, long);
01668 break;
01669
01670 case CURLOPT_MAXFILESIZE_LARGE:
01671
01672
01673
01674 data->set.max_filesize = va_arg(param, curl_off_t);
01675 break;
01676
01677 case CURLOPT_TCP_NODELAY:
01678
01679
01680
01681
01682 data->set.tcp_nodelay = (bool)(0 != va_arg(param, long));
01683 break;
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693 case CURLOPT_FTP_ACCOUNT:
01694 data->set.ftp_account = va_arg(param, char *);
01695 break;
01696
01697 case CURLOPT_IGNORE_CONTENT_LENGTH:
01698 data->set.ignorecl = (bool)(0 != va_arg(param, long));
01699 break;
01700
01701 case CURLOPT_CONNECT_ONLY:
01702
01703
01704
01705 data->set.connect_only = (bool)(0 != va_arg(param, long));
01706 break;
01707
01708 case CURLOPT_FTP_ALTERNATIVE_TO_USER:
01709 data->set.ftp_alternative_to_user = va_arg(param, char *);
01710 break;
01711
01712 case CURLOPT_SOCKOPTFUNCTION:
01713
01714
01715
01716 data->set.fsockopt = va_arg(param, curl_sockopt_callback);
01717 break;
01718
01719 case CURLOPT_SOCKOPTDATA:
01720
01721
01722
01723 data->set.sockopt_client = va_arg(param, void *);
01724 break;
01725
01726 case CURLOPT_SSL_SESSIONID_CACHE:
01727 data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
01728 break;
01729
01730 case CURLOPT_SSH_AUTH_TYPES:
01731 data->set.ssh_auth_types = va_arg(param, long);
01732 break;
01733
01734 case CURLOPT_SSH_PUBLIC_KEYFILE:
01735
01736
01737
01738 data->set.ssh_public_key = va_arg(param, char *);
01739 break;
01740
01741 case CURLOPT_SSH_PRIVATE_KEYFILE:
01742
01743
01744
01745 data->set.ssh_private_key = va_arg(param, char *);
01746 break;
01747
01748 case CURLOPT_HTTP_TRANSFER_DECODING:
01749
01750
01751
01752 data->set.http_te_skip = (bool)(0 == va_arg(param, long));
01753 break;
01754
01755 case CURLOPT_HTTP_CONTENT_DECODING:
01756
01757
01758
01759 data->set.http_ce_skip = (bool)(0 == va_arg(param, long));
01760 break;
01761
01762 case CURLOPT_NEW_FILE_PERMS:
01763
01764
01765
01766 data->set.new_file_perms = va_arg(param, long);
01767 break;
01768
01769 case CURLOPT_NEW_DIRECTORY_PERMS:
01770
01771
01772
01773 data->set.new_directory_perms = va_arg(param, long);
01774 break;
01775
01776 default:
01777
01778 result = CURLE_FAILED_INIT;
01779 break;
01780 }
01781
01782 return result;
01783 }
01784
01785 static void conn_free(struct connectdata *conn)
01786 {
01787 if (!conn)
01788 return;
01789
01790
01791 if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
01792 sclose(conn->sock[SECONDARYSOCKET]);
01793 if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
01794 sclose(conn->sock[FIRSTSOCKET]);
01795
01796 Curl_safefree(conn->user);
01797 Curl_safefree(conn->passwd);
01798 Curl_safefree(conn->proxyuser);
01799 Curl_safefree(conn->proxypasswd);
01800 Curl_safefree(conn->allocptr.proxyuserpwd);
01801 Curl_safefree(conn->allocptr.uagent);
01802 Curl_safefree(conn->allocptr.userpwd);
01803 Curl_safefree(conn->allocptr.accept_encoding);
01804 Curl_safefree(conn->allocptr.rangeline);
01805 Curl_safefree(conn->allocptr.ref);
01806 Curl_safefree(conn->allocptr.host);
01807 Curl_safefree(conn->allocptr.cookiehost);
01808 Curl_safefree(conn->ip_addr_str);
01809 Curl_safefree(conn->trailer);
01810 Curl_safefree(conn->host.rawalloc);
01811 Curl_safefree(conn->proxy.rawalloc);
01812 Curl_safefree(conn->master_buffer);
01813
01814 Curl_llist_destroy(conn->send_pipe, NULL);
01815 Curl_llist_destroy(conn->recv_pipe, NULL);
01816
01817
01818 #if defined(USE_ARES)
01819 Curl_safefree(conn->async.hostname);
01820 Curl_safefree(conn->async.os_specific);
01821 #elif defined(CURLRES_THREADED)
01822 Curl_destroy_thread_data(&conn->async);
01823 #endif
01824
01825 Curl_ssl_close(conn);
01826
01827 Curl_free_ssl_config(&conn->ssl_config);
01828
01829 free(conn);
01830 }
01831
01832 CURLcode Curl_disconnect(struct connectdata *conn)
01833 {
01834 struct SessionHandle *data;
01835 if(!conn)
01836 return CURLE_OK;
01837 data = conn->data;
01838
01839 if(!data) {
01840 DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
01841 return CURLE_OK;
01842 }
01843
01844 #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
01845
01846 Curl_hash_apply(data->hostcache,
01847 NULL, Curl_scan_cache_used);
01848 #endif
01849
01850 Curl_expire(data, 0);
01851 Curl_hostcache_prune(data);
01852
01853 if((conn->ntlm.state != NTLMSTATE_NONE) ||
01854 (conn->proxyntlm.state != NTLMSTATE_NONE)) {
01855
01856
01857
01858 data->state.authhost.done = FALSE;
01859 data->state.authhost.picked =
01860 data->state.authhost.want;
01861
01862 data->state.authproxy.done = FALSE;
01863 data->state.authproxy.picked =
01864 data->state.authproxy.want;
01865
01866 data->state.authproblem = FALSE;
01867
01868 Curl_ntlm_cleanup(conn);
01869 }
01870
01871 if(conn->curl_disconnect)
01872
01873 conn->curl_disconnect(conn);
01874
01875 if(-1 != conn->connectindex) {
01876
01877 infof(data, "Closing connection #%ld\n", conn->connectindex);
01878 if(data->state.connc)
01879
01880
01881 data->state.connc->connects[conn->connectindex] = NULL;
01882 }
01883
01884 #ifdef USE_LIBIDN
01885 if(conn->host.encalloc)
01886 idn_free(conn->host.encalloc);
01887
01888
01889 if(conn->proxy.encalloc)
01890 idn_free(conn->proxy.encalloc);
01891
01892
01893 #endif
01894
01895 Curl_ssl_close(conn);
01896
01897
01898 if (IsPipeliningEnabled(data)) {
01899 signalPipeClose(conn->send_pipe);
01900 signalPipeClose(conn->recv_pipe);
01901 }
01902
01903 conn_free(conn);
01904
01905 return CURLE_OK;
01906 }
01907
01908
01909
01910
01911
01912
01913 static bool SocketIsDead(curl_socket_t sock)
01914 {
01915 int sval;
01916 bool ret_val = TRUE;
01917
01918 sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
01919 if(sval == 0)
01920
01921 ret_val = FALSE;
01922
01923 return ret_val;
01924 }
01925
01926 static bool IsPipeliningPossible(struct SessionHandle *handle)
01927 {
01928 if (handle->multi && Curl_multi_canPipeline(handle->multi) &&
01929 (handle->set.httpreq == HTTPREQ_GET ||
01930 handle->set.httpreq == HTTPREQ_HEAD) &&
01931 handle->set.httpversion != CURL_HTTP_VERSION_1_0)
01932 return TRUE;
01933
01934 return FALSE;
01935 }
01936
01937 static bool IsPipeliningEnabled(struct SessionHandle *handle)
01938 {
01939 if (handle->multi && Curl_multi_canPipeline(handle->multi))
01940 return TRUE;
01941
01942 return FALSE;
01943 }
01944
01945 CURLcode Curl_addHandleToPipeline(struct SessionHandle *data,
01946 struct curl_llist *pipe)
01947 {
01948 #ifdef CURLDEBUG
01949 if(!IsPipeliningPossible(data)) {
01950
01951 if(pipe->head)
01952 infof(data, "PIPE when no PIPE supposed!\n");
01953 }
01954 #endif
01955 if (!Curl_llist_insert_next(pipe, pipe->tail, data))
01956 return CURLE_OUT_OF_MEMORY;
01957 return CURLE_OK;
01958 }
01959
01960
01961 int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
01962 struct curl_llist *pipe)
01963 {
01964 struct curl_llist_element *curr;
01965
01966 curr = pipe->head;
01967 while (curr) {
01968 if (curr->ptr == handle) {
01969 Curl_llist_remove(pipe, curr, NULL);
01970 return 1;
01971 }
01972 curr = curr->next;
01973 }
01974
01975 return 0;
01976 }
01977
01978 #if 0
01979 static void Curl_printPipeline(struct curl_llist *pipe)
01980 {
01981 struct curl_llist_element *curr;
01982
01983 curr = pipe->head;
01984 while (curr) {
01985 struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
01986 infof(data, "Handle in pipeline: %s\n", data->reqdata.path);
01987 curr = curr->next;
01988 }
01989 }
01990 #endif
01991
01992 bool Curl_isHandleAtHead(struct SessionHandle *handle,
01993 struct curl_llist *pipe)
01994 {
01995 struct curl_llist_element *curr = pipe->head;
01996 if (curr) {
01997 return (bool)(curr->ptr == handle);
01998 }
01999
02000 return FALSE;
02001 }
02002
02003 static struct SessionHandle* gethandleathead(struct curl_llist *pipe)
02004 {
02005 struct curl_llist_element *curr = pipe->head;
02006 if (curr) {
02007 return (struct SessionHandle *) curr->ptr;
02008 }
02009
02010 return NULL;
02011 }
02012
02013 static void signalPipeClose(struct curl_llist *pipe)
02014 {
02015 struct curl_llist_element *curr;
02016
02017 if (!pipe)
02018 return;
02019
02020 curr = pipe->head;
02021 while (curr) {
02022 struct curl_llist_element *next = curr->next;
02023 struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
02024
02025 #ifdef CURLDEBUG
02026 if(data->magic != CURLEASY_MAGIC_NUMBER) {
02027
02028 infof(data, "signalPipeClose() found BAAD easy handle\n");
02029 }
02030 #endif
02031
02032 data->state.pipe_broke = TRUE;
02033 Curl_multi_handlePipeBreak(data);
02034 Curl_llist_remove(pipe, curr, NULL);
02035 curr = next;
02036 }
02037 }
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049 static bool
02050 ConnectionExists(struct SessionHandle *data,
02051 struct connectdata *needle,
02052 struct connectdata **usethis)
02053 {
02054 long i;
02055 struct connectdata *check;
02056 bool canPipeline = IsPipeliningPossible(data);
02057
02058 for(i=0; i< data->state.connc->num; i++) {
02059 bool match = FALSE;
02060 size_t pipeLen = 0;
02061
02062
02063
02064
02065 check = data->state.connc->connects[i];
02066 if(!check)
02067
02068 continue;
02069
02070 pipeLen = check->send_pipe->size + check->recv_pipe->size;
02071
02072 if (check->connectindex == -1) {
02073 check->connectindex = i;
02074
02075
02076 }
02077
02078 if(pipeLen > 0 && !canPipeline) {
02079
02080
02081 continue;
02082 }
02083
02084 #ifdef CURLRES_ASYNCH
02085
02086
02087 if (!check->ip_addr_str) {
02088 infof(data,
02089 "Connection #%ld hasn't finished name resolve, can't reuse\n",
02090 check->connectindex);
02091 continue;
02092 }
02093 #endif
02094
02095 if ((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) || check->bits.close) {
02096
02097
02098 infof(data, "Connection #%ld isn't open enough, can't reuse\n",
02099 check->connectindex);
02100 #ifdef CURLDEBUG
02101 if (check->recv_pipe->size > 0) {
02102 infof(data, "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
02103 check->connectindex);
02104 }
02105 #endif
02106 continue;
02107 }
02108
02109 if (pipeLen >= MAX_PIPELINE_LENGTH) {
02110 infof(data, "Connection #%ld has its pipeline full, can't reuse\n",
02111 check->connectindex);
02112 continue;
02113 }
02114
02115 if (canPipeline) {
02116
02117 struct SessionHandle* sh = gethandleathead(check->send_pipe);
02118 struct SessionHandle* rh = gethandleathead(check->recv_pipe);
02119 if (sh) {
02120 if(!IsPipeliningPossible(sh))
02121 continue;
02122 }
02123 else if (rh) {
02124 if(!IsPipeliningPossible(rh))
02125 continue;
02126 }
02127 }
02128
02129 if((needle->protocol&PROT_SSL) != (check->protocol&PROT_SSL))
02130
02131 continue;
02132
02133 if(!needle->bits.httpproxy || needle->protocol&PROT_SSL) {
02134
02135
02136
02137 if(!(needle->protocol&PROT_SSL) && check->bits.httpproxy)
02138
02139
02140 continue;
02141
02142 if(strequal(needle->protostr, check->protostr) &&
02143 strequal(needle->host.name, check->host.name) &&
02144 (needle->remote_port == check->remote_port) ) {
02145 if(needle->protocol & PROT_SSL) {
02146
02147
02148 if(!Curl_ssl_config_matches(&needle->ssl_config,
02149 &check->ssl_config)) {
02150 infof(data,
02151 "Connection #%ld has different SSL parameters, "
02152 "can't reuse\n",
02153 check->connectindex );
02154 continue;
02155 }
02156 }
02157 if((needle->protocol & PROT_FTP) ||
02158 ((needle->protocol & PROT_HTTP) &&
02159 (data->state.authhost.want==CURLAUTH_NTLM))) {
02160
02161
02162 if(!strequal(needle->user, check->user) ||
02163 !strequal(needle->passwd, check->passwd)) {
02164
02165 continue;
02166 }
02167 }
02168 match = TRUE;
02169 }
02170 }
02171 else {
02172
02173 if(check->bits.proxy &&
02174 (needle->proxytype == check->proxytype) &&
02175 strequal(needle->proxy.name, check->proxy.name) &&
02176 needle->port == check->port) {
02177
02178 match = TRUE;
02179 }
02180 }
02181
02182 if(match) {
02183 if (!IsPipeliningEnabled(data)) {
02184
02185
02186 bool dead = SocketIsDead(check->sock[FIRSTSOCKET]);
02187 if(dead) {
02188 check->data = data;
02189 infof(data, "Connection #%d seems to be dead!\n", i);
02190
02191 Curl_disconnect(check);
02192 data->state.connc->connects[i]=NULL;
02193
02194 return FALSE;
02195 }
02196 }
02197
02198 check->inuse = TRUE;
02199
02200 if (canPipeline) {
02201
02202 check->is_in_pipeline = TRUE;
02203 }
02204
02205 *usethis = check;
02206 return TRUE;
02207 }
02208 }
02209
02210 return FALSE;
02211 }
02212
02213
02214
02215
02216
02217
02218
02219
02220 static long
02221 ConnectionKillOne(struct SessionHandle *data)
02222 {
02223 long i;
02224 struct connectdata *conn;
02225 long highscore=-1;
02226 long connindex=-1;
02227 long score;
02228 struct timeval now;
02229
02230 now = Curl_tvnow();
02231
02232 for(i=0; data->state.connc && (i< data->state.connc->num); i++) {
02233 conn = data->state.connc->connects[i];
02234
02235 if(!conn || conn->inuse)
02236 continue;
02237
02238
02239 score = Curl_tvdiff(now, conn->now);
02240
02241 if(score > highscore) {
02242 highscore = score;
02243 connindex = i;
02244 }
02245 }
02246 if(connindex >= 0) {
02247
02248 conn = data->state.connc->connects[connindex];
02249 conn->data = data;
02250
02251
02252 (void)Curl_disconnect(conn);
02253
02254
02255 data->state.connc->connects[connindex] = NULL;
02256 }
02257
02258 return connindex;
02259 }
02260
02261
02262 static void
02263 ConnectionDone(struct connectdata *conn)
02264 {
02265 conn->inuse = FALSE;
02266 if (!conn->send_pipe && !conn->recv_pipe)
02267 conn->is_in_pipeline = FALSE;
02268 }
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278 static long
02279 ConnectionStore(struct SessionHandle *data,
02280 struct connectdata *conn)
02281 {
02282 long i;
02283 for(i=0; i< data->state.connc->num; i++) {
02284 if(!data->state.connc->connects[i])
02285 break;
02286 }
02287 if(i == data->state.connc->num) {
02288
02289 i = ConnectionKillOne(data);
02290 if(-1 != i)
02291 infof(data, "Connection (#%d) was killed to make room (holds %d)\n",
02292 i, data->state.connc->num);
02293 else
02294 infof(data, "This connection did not fit in the connection cache\n");
02295 }
02296
02297 conn->connectindex = i;
02298
02299
02300
02301 conn->inuse = TRUE;
02302 if(-1 != i) {
02303
02304
02305
02306
02307
02308
02309
02310
02311 data->state.connc->connects[i] = conn;
02312 conn->data = data;
02313 }
02314
02315 return i;
02316 }
02317
02318 static CURLcode ConnectPlease(struct SessionHandle *data,
02319 struct connectdata *conn,
02320 struct Curl_dns_entry *hostaddr,
02321 bool *connected)
02322 {
02323 CURLcode result;
02324 Curl_addrinfo *addr;
02325 #ifndef CURL_DISABLE_VERBOSE_STRINGS
02326 char *hostname = conn->bits.proxy?conn->proxy.name:conn->host.name;
02327
02328 infof(data, "About to connect() to %s%s port %d (#%d)\n",
02329 conn->bits.proxy?"proxy ":"",
02330 hostname, conn->port, conn->connectindex);
02331 #endif
02332
02333
02334
02335
02336 result= Curl_connecthost(conn,
02337 hostaddr,
02338 &conn->sock[FIRSTSOCKET],
02339 &addr,
02340 connected);
02341 if(CURLE_OK == result) {
02342
02343 conn->dns_entry = hostaddr;
02344 conn->ip_addr = addr;
02345
02346 Curl_store_ip_addr(conn);
02347
02348 switch(data->set.proxytype) {
02349 case CURLPROXY_SOCKS5:
02350 result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, conn->host.name,
02351 conn->remote_port, FIRSTSOCKET, conn);
02352 break;
02353 case CURLPROXY_HTTP:
02354
02355 break;
02356 case CURLPROXY_SOCKS4:
02357 result = Curl_SOCKS4(conn->proxyuser, conn->host.name, conn->remote_port,
02358 FIRSTSOCKET, conn);
02359 break;
02360 default:
02361 failf(data, "unknown proxytype option given");
02362 result = CURLE_COULDNT_CONNECT;
02363 break;
02364 }
02365 }
02366 if(result)
02367 *connected = FALSE;
02368
02369 return result;
02370 }
02371
02372
02373
02374
02375 #ifndef CURL_DISABLE_VERBOSE_STRINGS
02376 static void verboseconnect(struct connectdata *conn)
02377 {
02378 infof(conn->data, "Connected to %s (%s) port %d (#%d)\n",
02379 conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
02380 conn->ip_addr_str, conn->port, conn->connectindex);
02381 }
02382 #endif
02383
02384 int Curl_protocol_getsock(struct connectdata *conn,
02385 curl_socket_t *socks,
02386 int numsocks)
02387 {
02388 if(conn->curl_proto_getsock)
02389 return conn->curl_proto_getsock(conn, socks, numsocks);
02390 return GETSOCK_BLANK;
02391 }
02392
02393 int Curl_doing_getsock(struct connectdata *conn,
02394 curl_socket_t *socks,
02395 int numsocks)
02396 {
02397 if(conn && conn->curl_doing_getsock)
02398 return conn->curl_doing_getsock(conn, socks, numsocks);
02399 return GETSOCK_BLANK;
02400 }
02401
02402
02403
02404
02405
02406
02407
02408 CURLcode Curl_protocol_connecting(struct connectdata *conn,
02409 bool *done)
02410 {
02411 CURLcode result=CURLE_OK;
02412
02413 if(conn && conn->curl_connecting) {
02414 *done = FALSE;
02415 result = conn->curl_connecting(conn, done);
02416 }
02417 else
02418 *done = TRUE;
02419
02420 return result;
02421 }
02422
02423
02424
02425
02426
02427
02428 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
02429 {
02430 CURLcode result=CURLE_OK;
02431
02432 if(conn && conn->curl_doing) {
02433 *done = FALSE;
02434 result = conn->curl_doing(conn, done);
02435 }
02436 else
02437 *done = TRUE;
02438
02439 return result;
02440 }
02441
02442
02443
02444
02445
02446
02447 CURLcode Curl_protocol_connect(struct connectdata *conn,
02448 bool *protocol_done)
02449 {
02450 CURLcode result=CURLE_OK;
02451 struct SessionHandle *data = conn->data;
02452
02453 *protocol_done = FALSE;
02454
02455 if(conn->bits.tcpconnect && conn->bits.protoconnstart) {
02456
02457
02458
02459
02460
02461
02462 if(!conn->curl_connecting)
02463 *protocol_done = TRUE;
02464
02465 return CURLE_OK;
02466 }
02467
02468 if(!conn->bits.tcpconnect) {
02469
02470 Curl_pgrsTime(data, TIMER_CONNECT);
02471
02472 if(data->set.verbose)
02473 verboseconnect(conn);
02474 }
02475
02476 if(!conn->bits.protoconnstart) {
02477 if(conn->curl_connect) {
02478
02479
02480
02481
02482 conn->now = Curl_tvnow();
02483
02484
02485 result = conn->curl_connect(conn, protocol_done);
02486 }
02487 else
02488 *protocol_done = TRUE;
02489
02490
02491
02492 if (!result)
02493 conn->bits.protoconnstart = TRUE;
02494 }
02495
02496 return result;
02497 }
02498
02499
02500
02501
02502 #ifdef USE_LIBIDN
02503 static bool is_ASCII_name(const char *hostname)
02504 {
02505 const unsigned char *ch = (const unsigned char*)hostname;
02506
02507 while (*ch) {
02508 if (*ch++ & 0x80)
02509 return FALSE;
02510 }
02511 return TRUE;
02512 }
02513
02514
02515
02516
02517 static bool tld_check_name(struct SessionHandle *data,
02518 const char *ace_hostname)
02519 {
02520 size_t err_pos;
02521 char *uc_name = NULL;
02522 int rc;
02523 #ifndef CURL_DISABLE_VERBOSE_STRINGS
02524 char *tld_errmsg = (char *)"<no msg>";
02525 #else
02526 (void)data;
02527 #endif
02528
02529
02530 rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
02531 if (rc != IDNA_SUCCESS)
02532 return (FALSE);
02533
02534 rc = tld_check_lz(uc_name, &err_pos, NULL);
02535 #ifndef CURL_DISABLE_VERBOSE_STRINGS
02536 #ifdef HAVE_TLD_STRERROR
02537 if (rc != TLD_SUCCESS)
02538 tld_errmsg = (char *)tld_strerror((Tld_rc)rc);
02539 #endif
02540 if (rc == TLD_INVALID)
02541 infof(data, "WARNING: %s; pos %u = `%c'/0x%02X\n",
02542 tld_errmsg, err_pos, uc_name[err_pos],
02543 uc_name[err_pos] & 255);
02544 else if (rc != TLD_SUCCESS)
02545 infof(data, "WARNING: TLD check for %s failed; %s\n",
02546 uc_name, tld_errmsg);
02547 #endif
02548 if (uc_name)
02549 idn_free(uc_name);
02550 return (bool)(rc == TLD_SUCCESS);
02551 }
02552 #endif
02553
02554 static void fix_hostname(struct SessionHandle *data,
02555 struct connectdata *conn, struct hostname *host)
02556 {
02557 #ifndef USE_LIBIDN
02558 (void)data;
02559 (void)conn;
02560 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
02561 (void)conn;
02562 #endif
02563
02564
02565 host->dispname = host->name;
02566
02567 #ifdef USE_LIBIDN
02568
02569
02570
02571 if (!is_ASCII_name(host->name) &&
02572 stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
02573 char *ace_hostname = NULL;
02574 int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
02575 infof (data, "Input domain encoded as `%s'\n",
02576 stringprep_locale_charset ());
02577 if (rc != IDNA_SUCCESS)
02578 infof(data, "Failed to convert %s to ACE; %s\n",
02579 host->name, Curl_idn_strerror(conn,rc));
02580 else {
02581
02582
02583 (void)tld_check_name(data, ace_hostname);
02584
02585 host->encalloc = ace_hostname;
02586
02587 host->name = host->encalloc;
02588 }
02589 }
02590 #endif
02591 }
02592
02593
02594
02595
02596 static CURLcode ParseURLAndFillConnection(struct SessionHandle *data,
02597 struct connectdata *conn)
02598 {
02599 char *at;
02600 char *tmp;
02601
02602 char *path = data->reqdata.path;
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612 if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
02613 conn->protostr,
02614 path)) && strequal(conn->protostr, "file")) {
02615 if(path[0] == '/' && path[1] == '/') {
02616
02617
02618
02619
02620
02621
02622
02623 memmove(path, path + 2, strlen(path + 2)+1);
02624 }
02625
02626
02627
02628
02629
02630 if(path[0] != '/') {
02631
02632
02633 char *ptr=strchr(path, '/');
02634 if(ptr) {
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650 if(ptr[1] && ('/' == ptr[1]))
02651
02652
02653 ptr++;
02654
02655
02656 memmove(path, ptr, strlen(ptr)+1);
02657 }
02658 }
02659
02660 strcpy(conn->protostr, "file");
02661 }
02662 else {
02663
02664 path[0]=0;
02665
02666 if (2 > sscanf(data->change.url,
02667 "%15[^\n:]://%[^\n/]%[^\n]",
02668 conn->protostr,
02669 conn->host.name, path)) {
02670
02671
02672
02673
02674
02675 if((1 > sscanf(data->change.url, "%[^\n/]%[^\n]",
02676 conn->host.name, path)) ) {
02677
02678
02679
02680 failf(data, "<url> malformed");
02681 return CURLE_URL_MALFORMAT;
02682 }
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692 if(checkprefix("FTP.", conn->host.name))
02693 strcpy(conn->protostr, "ftp");
02694 else if (checkprefix("DICT.", conn->host.name))
02695 strcpy(conn->protostr, "DICT");
02696 else if (checkprefix("LDAP.", conn->host.name))
02697 strcpy(conn->protostr, "LDAP");
02698 else {
02699 strcpy(conn->protostr, "http");
02700 }
02701
02702 conn->protocol |= PROT_MISSING;
02703 }
02704 }
02705
02706
02707
02708
02709
02710 at = strchr(conn->host.name, '@');
02711 if(at)
02712 tmp = strchr(at+1, '?');
02713 else
02714 tmp = strchr(conn->host.name, '?');
02715
02716 if(tmp) {
02717
02718
02719
02720
02721
02722
02723
02724
02725 size_t hostlen = strlen(tmp);
02726 size_t pathlen = strlen(path);
02727
02728
02729
02730 memmove(path+hostlen+1, path, pathlen+1);
02731
02732
02733 memcpy(path+1, tmp, hostlen);
02734
02735 path[0]='/';
02736
02737 *tmp=0;
02738 }
02739 else if(!path[0]) {
02740
02741 strcpy(path, "/");
02742 }
02743
02744
02745
02746
02747
02748 if(path[0] == '?') {
02749
02750
02751
02752 memmove(&path[1], path, strlen(path)+1);
02753 path[0] = '/';
02754 }
02755
02756
02757
02758
02759
02760
02761
02762
02763 return CURLE_OK;
02764 }
02765
02766 static void llist_dtor(void *user, void *element)
02767 {
02768 (void)user;
02769 (void)element;
02770
02771 }
02772
02773 static CURLcode setup_range(struct SessionHandle *data)
02774 {
02775
02776
02777
02778
02779 struct HandleData *req = &data->reqdata;
02780
02781 req->resume_from = data->set.set_resume_from;
02782 if (req->resume_from || data->set.set_range) {
02783 if (req->rangestringalloc == TRUE)
02784 free(req->range);
02785
02786 if(req->resume_from)
02787 req->range = aprintf("%" FORMAT_OFF_T "-", req->resume_from);
02788 else
02789 req->range = strdup(data->set.set_range);
02790
02791 req->rangestringalloc = req->range?TRUE:FALSE;
02792
02793 if(!req->range)
02794 return CURLE_OUT_OF_MEMORY;
02795
02796
02797 req->use_range = TRUE;
02798 }
02799 else
02800 req->use_range = FALSE;
02801
02802 return CURLE_OK;
02803 }
02804
02824 static CURLcode CreateConnection(struct SessionHandle *data,
02825 struct connectdata **in_connect,
02826 struct Curl_dns_entry **addr,
02827 bool *async)
02828 {
02829
02830 char *tmp;
02831 CURLcode result=CURLE_OK;
02832 struct connectdata *conn;
02833 struct connectdata *conn_temp = NULL;
02834 size_t urllen;
02835 struct Curl_dns_entry *hostaddr;
02836 #if defined(HAVE_ALARM) && !defined(USE_ARES)
02837 unsigned int prev_alarm=0;
02838 #endif
02839 char endbracket;
02840 char user[MAX_CURL_USER_LENGTH];
02841 char passwd[MAX_CURL_PASSWORD_LENGTH];
02842 int rc;
02843 bool reuse;
02844 char *proxy = NULL;
02845
02846 #ifndef USE_ARES
02847 #ifdef SIGALRM
02848 #ifdef HAVE_SIGACTION
02849 struct sigaction keep_sigact;
02850 bool keep_copysig=FALSE;
02851 #else
02852 #ifdef HAVE_SIGNAL
02853 void (*keep_sigact)(int);
02854 #endif
02855 #endif
02856 #endif
02857 #endif
02858
02859 *addr = NULL;
02860 *async = FALSE;
02861
02862
02863
02864
02865
02866 if(!data->change.url)
02867 return CURLE_URL_MALFORMAT;
02868
02869
02870
02871
02872
02873
02874 conn = (struct connectdata *)calloc(1, sizeof(struct connectdata));
02875 if(!conn) {
02876 *in_connect = NULL;
02877 return CURLE_OUT_OF_MEMORY;
02878 }
02879
02880
02881
02882 *in_connect = conn;
02883
02884
02885
02886 conn->data = data;
02887
02888
02889 conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
02890 conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
02891 conn->connectindex = -1;
02892
02893 conn->proxytype = data->set.proxytype;
02894 conn->bits.proxy = (bool)(data->set.proxy && *data->set.proxy);
02895 conn->bits.httpproxy = (bool)(conn->bits.proxy
02896 && (conn->proxytype == CURLPROXY_HTTP));
02897
02898
02899
02900
02901
02902 conn->bits.close = TRUE;
02903
02904 conn->readchannel_inuse = FALSE;
02905 conn->writechannel_inuse = FALSE;
02906
02907 conn->read_pos = 0;
02908 conn->buf_len = 0;
02909
02910
02911 conn->created = Curl_tvnow();
02912
02913 conn->bits.user_passwd = (bool)(NULL != data->set.userpwd);
02914 conn->bits.proxy_user_passwd = (bool)(NULL != data->set.proxyuserpwd);
02915 conn->bits.no_body = data->set.opt_no_body;
02916 conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
02917 conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
02918 conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
02919
02920 if (data->multi && Curl_multi_canPipeline(data->multi) &&
02921 !conn->master_buffer) {
02922
02923 conn->master_buffer = calloc(BUFSIZE, sizeof (char));
02924 if (!conn->master_buffer)
02925 return CURLE_OUT_OF_MEMORY;
02926 }
02927
02928
02929 conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
02930 conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
02931 if (!conn->send_pipe || !conn->recv_pipe)
02932 return CURLE_OUT_OF_MEMORY;
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942 #define LEAST_PATH_ALLOC 256
02943 urllen=strlen(data->change.url);
02944 if(urllen < LEAST_PATH_ALLOC)
02945 urllen=LEAST_PATH_ALLOC;
02946
02947 if (!data->set.source_url
02948 && data->reqdata.pathbuffer) {
02949
02950 free(data->reqdata.pathbuffer);
02951 }
02952
02953
02954
02955
02956
02957
02958
02959 data->reqdata.pathbuffer=(char *)malloc(urllen+2);
02960 if(NULL == data->reqdata.pathbuffer)
02961 return CURLE_OUT_OF_MEMORY;
02962 data->reqdata.path = data->reqdata.pathbuffer;
02963
02964 conn->host.rawalloc=(char *)malloc(urllen+2);
02965 if(NULL == conn->host.rawalloc)
02966 return CURLE_OUT_OF_MEMORY;
02967
02968 conn->host.name = conn->host.rawalloc;
02969 conn->host.name[0] = 0;
02970
02971 result = ParseURLAndFillConnection(data, conn);
02972 if (result != CURLE_OK) {
02973 return result;
02974 }
02975
02976
02977
02978
02979 if(conn->bits.proxy_user_passwd) {
02980 char proxyuser[MAX_CURL_USER_LENGTH]="";
02981 char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
02982
02983 sscanf(data->set.proxyuserpwd,
02984 "%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
02985 "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
02986 proxyuser, proxypasswd);
02987
02988 conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
02989 if(!conn->proxyuser)
02990 return CURLE_OUT_OF_MEMORY;
02991
02992 conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
02993 if(!conn->proxypasswd)
02994 return CURLE_OUT_OF_MEMORY;
02995 }
02996
02997 if (data->set.proxy) {
02998 proxy = strdup(data->set.proxy);
02999 if(NULL == proxy) {
03000 failf(data, "memory shortage");
03001 return CURLE_OUT_OF_MEMORY;
03002 }
03003 }
03004
03005
03006 #ifndef CURL_DISABLE_HTTP
03007
03008
03009
03010
03011 if(!proxy) {
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029 char *no_proxy=NULL;
03030 char *no_proxy_tok_buf;
03031 char proxy_env[128];
03032
03033 no_proxy=curl_getenv("no_proxy");
03034 if(!no_proxy)
03035 no_proxy=curl_getenv("NO_PROXY");
03036
03037 if(!no_proxy || !strequal("*", no_proxy)) {
03038
03039 char *nope;
03040
03041 nope=no_proxy?strtok_r(no_proxy, ", ", &no_proxy_tok_buf):NULL;
03042 while(nope) {
03043 size_t namelen;
03044 char *endptr = strchr(conn->host.name, ':');
03045 if(endptr)
03046 namelen=endptr-conn->host.name;
03047 else
03048 namelen=strlen(conn->host.name);
03049
03050 if(strlen(nope) <= namelen) {
03051 char *checkn=
03052 conn->host.name + namelen - strlen(nope);
03053 if(checkprefix(nope, checkn)) {
03054
03055 break;
03056 }
03057 }
03058 nope=strtok_r(NULL, ", ", &no_proxy_tok_buf);
03059 }
03060 if(!nope) {
03061
03062 char *protop = conn->protostr;
03063 char *envp = proxy_env;
03064 char *prox;
03065
03066
03067 while(*protop)
03068 *envp++ = (char)tolower((int)*protop++);
03069
03070
03071 strcpy(envp, "_proxy");
03072
03073
03074 prox=curl_getenv(proxy_env);
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088 if(!prox && !strequal("http_proxy", proxy_env)) {
03089
03090 for(envp = proxy_env; *envp; envp++)
03091 *envp = (char)toupper((int)*envp);
03092 prox=curl_getenv(proxy_env);
03093 }
03094
03095 if(prox && *prox) {
03096 proxy = prox;
03097 }
03098 else {
03099 proxy = curl_getenv("all_proxy");
03100 if(!proxy)
03101 proxy=curl_getenv("ALL_PROXY");
03102 }
03103
03104 if(proxy && *proxy) {
03105 long bits = conn->protocol & (PROT_HTTPS|PROT_SSL|PROT_MISSING);
03106
03107 if(conn->proxytype == CURLPROXY_HTTP) {
03108
03109 conn->protocol = PROT_HTTP | bits;
03110 conn->bits.httpproxy = TRUE;
03111 }
03112 }
03113 }
03114 }
03115 if(no_proxy)
03116 free(no_proxy);
03117 }
03118 #endif
03119
03120
03121
03122
03123 if(conn->protocol&PROT_MISSING) {
03124
03125
03126
03127 char *reurl;
03128
03129 reurl = aprintf("%s://%s", conn->protostr, data->change.url);
03130
03131 if(!reurl) {
03132 Curl_safefree(proxy);
03133 return CURLE_OUT_OF_MEMORY;
03134 }
03135
03136 data->change.url = reurl;
03137 data->change.url_alloc = TRUE;
03138 conn->protocol &= ~PROT_MISSING;
03139 }
03140
03141
03142
03143
03144
03145 conn->socktype = SOCK_STREAM;
03146
03147 if (strequal(conn->protostr, "HTTP")) {
03148 #ifndef CURL_DISABLE_HTTP
03149 conn->port = PORT_HTTP;
03150 conn->remote_port = PORT_HTTP;
03151 conn->protocol |= PROT_HTTP;
03152 conn->curl_do = Curl_http;
03153 conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
03154 conn->curl_done = Curl_http_done;
03155 conn->curl_connect = Curl_http_connect;
03156 #else
03157 failf(data, LIBCURL_NAME
03158 " was built with HTTP disabled, http: not supported!");
03159 return CURLE_UNSUPPORTED_PROTOCOL;
03160 #endif
03161 }
03162 else if (strequal(conn->protostr, "HTTPS")) {
03163 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
03164
03165 conn->port = PORT_HTTPS;
03166 conn->remote_port = PORT_HTTPS;
03167 conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
03168
03169 conn->curl_do = Curl_http;
03170 conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
03171 conn->curl_done = Curl_http_done;
03172 conn->curl_connect = Curl_http_connect;
03173 conn->curl_connecting = Curl_https_connecting;
03174 conn->curl_proto_getsock = Curl_https_getsock;
03175
03176 #else
03177 failf(data, LIBCURL_NAME
03178 " was built with SSL disabled, https: not supported!");
03179 return CURLE_UNSUPPORTED_PROTOCOL;
03180 #endif
03181 }
03182 else if(strequal(conn->protostr, "FTP") ||
03183 strequal(conn->protostr, "FTPS")) {
03184
03185 #ifndef CURL_DISABLE_FTP
03186 char *type;
03187 int port = PORT_FTP;
03188
03189 if(strequal(conn->protostr, "FTPS")) {
03190 #ifdef USE_SSL
03191 conn->protocol |= PROT_FTPS|PROT_SSL;
03192
03193 conn->ssl[SECONDARYSOCKET].use = data->set.ftp_ssl != CURLFTPSSL_CONTROL;
03194 port = PORT_FTPS;
03195 #else
03196 failf(data, LIBCURL_NAME
03197 " was built with SSL disabled, ftps: not supported!");
03198 return CURLE_UNSUPPORTED_PROTOCOL;
03199 #endif
03200 }
03201
03202 conn->port = port;
03203 conn->remote_port = (unsigned short)port;
03204 conn->protocol |= PROT_FTP;
03205
03206 if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
03207
03208
03209 #ifndef CURL_DISABLE_HTTP
03210 conn->curl_do = Curl_http;
03211 conn->curl_done = Curl_http_done;
03212 conn->protocol = PROT_HTTP;
03213 #else
03214 failf(data, "FTP over http proxy requires HTTP support built-in!");
03215 return CURLE_UNSUPPORTED_PROTOCOL;
03216 #endif
03217 }
03218 else {
03219 conn->curl_do = Curl_ftp;
03220 conn->curl_do_more = Curl_ftp_nextconnect;
03221 conn->curl_done = Curl_ftp_done;
03222 conn->curl_connect = Curl_ftp_connect;
03223 conn->curl_connecting = Curl_ftp_multi_statemach;
03224 conn->curl_doing = Curl_ftp_doing;
03225 conn->curl_proto_getsock = Curl_ftp_getsock;
03226 conn->curl_doing_getsock = Curl_ftp_getsock;
03227 conn->curl_disconnect = Curl_ftp_disconnect;
03228 }
03229
03230 data->reqdata.path++;
03231
03232
03233
03234 type=strstr(data->reqdata.path, ";type=");
03235 if(!type) {
03236 type=strstr(conn->host.rawalloc, ";type=");
03237 }
03238 if(type) {
03239 char command;
03240 *type=0;
03241 command = (char)toupper((int)type[6]);
03242 switch(command) {
03243 case 'A':
03244 data->set.prefer_ascii = TRUE;
03245 break;
03246 case 'D':
03247 data->set.ftp_list_only = TRUE;
03248 break;
03249 case 'I':
03250 default:
03251
03252 data->set.prefer_ascii = FALSE;
03253 break;
03254 }
03255 }
03256 #else
03257 failf(data, LIBCURL_NAME
03258 " was built with FTP disabled, ftp/ftps: not supported!");
03259 return CURLE_UNSUPPORTED_PROTOCOL;
03260 #endif
03261 }
03262 else if(strequal(conn->protostr, "TELNET")) {
03263 #ifndef CURL_DISABLE_TELNET
03264
03265 conn->protocol |= PROT_TELNET;
03266
03267 conn->port = PORT_TELNET;
03268 conn->remote_port = PORT_TELNET;
03269 conn->curl_do = Curl_telnet;
03270 conn->curl_done = Curl_telnet_done;
03271 #else
03272 failf(data, LIBCURL_NAME
03273 " was built with TELNET disabled!");
03274 return CURLE_UNSUPPORTED_PROTOCOL;
03275 #endif
03276 }
03277 else if (strequal(conn->protostr, "DICT")) {
03278 #ifndef CURL_DISABLE_DICT
03279 conn->protocol |= PROT_DICT;
03280 conn->port = PORT_DICT;
03281 conn->remote_port = PORT_DICT;
03282 conn->curl_do = Curl_dict;
03283
03284 conn->curl_done = (Curl_done_func)ZERO_NULL;
03285 #else
03286 failf(data, LIBCURL_NAME
03287 " was built with DICT disabled!");
03288 return CURLE_UNSUPPORTED_PROTOCOL;
03289 #endif
03290 }
03291 else if (strequal(conn->protostr, "LDAP")) {
03292 #ifndef CURL_DISABLE_LDAP
03293 conn->protocol |= PROT_LDAP;
03294 conn->port = PORT_LDAP;
03295 conn->remote_port = PORT_LDAP;
03296 conn->curl_do = Curl_ldap;
03297
03298 conn->curl_done = (Curl_done_func)ZERO_NULL;
03299 #else
03300 failf(data, LIBCURL_NAME
03301 " was built with LDAP disabled!");
03302 return CURLE_UNSUPPORTED_PROTOCOL;
03303 #endif
03304 }
03305 else if (strequal(conn->protostr, "FILE")) {
03306 #ifndef CURL_DISABLE_FILE
03307 conn->protocol |= PROT_FILE;
03308
03309 conn->curl_do = Curl_file;
03310 conn->curl_done = Curl_file_done;
03311 #else
03312 failf(data, LIBCURL_NAME
03313 " was built with FILE disabled!");
03314 return CURLE_UNSUPPORTED_PROTOCOL;
03315 #endif
03316 }
03317 else if (strequal(conn->protostr, "TFTP")) {
03318 #ifndef CURL_DISABLE_TFTP
03319 char *type;
03320 conn->socktype = SOCK_DGRAM;
03321 conn->protocol |= PROT_TFTP;
03322 conn->port = PORT_TFTP;
03323 conn->remote_port = PORT_TFTP;
03324 conn->curl_connect = Curl_tftp_connect;
03325 conn->curl_do = Curl_tftp;
03326 conn->curl_done = Curl_tftp_done;
03327
03328
03329 type=strstr(data->reqdata.path, ";mode=");
03330 if(!type) {
03331 type=strstr(conn->host.rawalloc, ";mode=");
03332 }
03333 if(type) {
03334 char command;
03335 *type=0;
03336 command = (char)toupper((int)type[6]);
03337 switch(command) {
03338 case 'A':
03339 case 'N':
03340 data->set.prefer_ascii = TRUE;
03341 break;
03342 case 'O':
03343 case 'I':
03344 default:
03345
03346 data->set.prefer_ascii = FALSE;
03347 break;
03348 }
03349 }
03350 #else
03351 failf(data, LIBCURL_NAME
03352 " was built with TFTP disabled!");
03353 return CURLE_UNSUPPORTED_PROTOCOL;
03354 #endif
03355 }
03356 else if (strequal(conn->protostr, "SCP")) {
03357 #ifdef USE_LIBSSH2
03358 conn->port = PORT_SSH;
03359 conn->remote_port = PORT_SSH;
03360 conn->protocol = PROT_SCP;
03361 conn->curl_connect = Curl_ssh_connect;
03362 conn->curl_do = Curl_scp_do;
03363 conn->curl_done = Curl_scp_done;
03364 conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
03365 #else
03366 failf(data, LIBCURL_NAME
03367 " was built without LIBSSH2, scp: not supported!");
03368 return CURLE_UNSUPPORTED_PROTOCOL;
03369 #endif
03370 }
03371 else if (strequal(conn->protostr, "SFTP")) {
03372 #ifdef USE_LIBSSH2
03373 conn->port = PORT_SSH;
03374 conn->remote_port = PORT_SSH;
03375 conn->protocol = PROT_SFTP;
03376 conn->curl_connect = Curl_ssh_connect;
03377 conn->curl_do = Curl_sftp_do;
03378 conn->curl_done = Curl_sftp_done;
03379 conn->curl_do_more = (Curl_do_more_func)NULL;
03380 #else
03381 failf(data, LIBCURL_NAME
03382 " was built without LIBSSH2, scp: not supported!");
03383 return CURLE_UNSUPPORTED_PROTOCOL;
03384 #endif
03385 }
03386 else {
03387
03388
03389 failf(data, "Unsupported protocol: %s", conn->protostr);
03390 return CURLE_UNSUPPORTED_PROTOCOL;
03391 }
03392
03393 if(proxy && *proxy) {
03394
03395
03396
03397
03398 char *prox_portno;
03399 char *endofprot;
03400
03401
03402 char *proxyptr=proxy;
03403 char *portptr;
03404 char *atsign;
03405
03406
03407
03408
03409
03410
03411
03412 endofprot=strstr(proxyptr, "://");
03413 if(endofprot)
03414 proxyptr = endofprot+3;
03415
03416
03417 atsign = strchr(proxyptr, '@');
03418 if(atsign) {
03419 char proxyuser[MAX_CURL_USER_LENGTH];
03420 char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
03421 proxypasswd[0] = 0;
03422
03423 if(1 <= sscanf(proxyptr,
03424 "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
03425 "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
03426 proxyuser, proxypasswd)) {
03427 CURLcode res = CURLE_OK;
03428
03429
03430
03431
03432
03433 Curl_safefree(conn->proxyuser);
03434 conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
03435
03436 if(!conn->proxyuser)
03437 res = CURLE_OUT_OF_MEMORY;
03438 else {
03439 Curl_safefree(conn->proxypasswd);
03440 conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
03441
03442 if(!conn->proxypasswd)
03443 res = CURLE_OUT_OF_MEMORY;
03444 }
03445
03446 if(CURLE_OK == res) {
03447 conn->bits.proxy_user_passwd = TRUE;
03448 atsign = strdup(atsign+1);
03449
03450 if(atsign) {
03451 free(proxy);
03452 proxy = proxyptr = atsign;
03453 }
03454 else
03455 res = CURLE_OUT_OF_MEMORY;
03456 }
03457
03458 if(res) {
03459 free(proxy);
03460 return res;
03461 }
03462 }
03463 }
03464
03465
03466 portptr = proxyptr;
03467
03468
03469 if(*proxyptr == '[') {
03470 char *ptr = ++proxyptr;
03471 while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':')))
03472 ptr++;
03473 if(*ptr == ']') {
03474
03475 *ptr = 0;
03476 portptr = ptr+1;
03477 }
03478
03479
03480
03481
03482 }
03483
03484
03485 prox_portno = strchr(portptr, ':');
03486 if (prox_portno) {
03487 *prox_portno = 0x0;
03488 prox_portno ++;
03489
03490 conn->port = atoi(prox_portno);
03491 }
03492 else if(data->set.proxyport) {
03493
03494
03495 conn->port = data->set.proxyport;
03496 }
03497
03498
03499 conn->proxy.rawalloc = strdup(proxyptr);
03500 conn->proxy.name = conn->proxy.rawalloc;
03501
03502 free(proxy);
03503 proxy = NULL;
03504 if(!conn->proxy.rawalloc)
03505 return CURLE_OUT_OF_MEMORY;
03506 }
03507
03508
03509
03510
03511 #ifndef CURL_DISABLE_FILE
03512 if (strequal(conn->protostr, "FILE")) {
03513
03514
03515 result = Curl_file_connect(conn);
03516
03517
03518 if(CURLE_OK == result) {
03519 conn->data = data;
03520 conn->bits.tcpconnect = TRUE;
03521 ConnectionStore(data, conn);
03522
03523 result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL,
03524 -1, NULL);
03525 }
03526
03527 return result;
03528 }
03529 #endif
03530
03531
03532
03533
03534
03535 if((conn->protocol&PROT_SSL) && conn->bits.httpproxy)
03536 conn->bits.tunnel_proxy = TRUE;
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564 user[0] =0;
03565 passwd[0]=0;
03566
03567 if (conn->protocol & (PROT_FTP|PROT_HTTP|PROT_SCP|PROT_SFTP)) {
03568
03569
03570
03571 char *ptr=strchr(conn->host.name, '@');
03572 char *userpass = conn->host.name;
03573 if(ptr != NULL) {
03574
03575
03576 conn->host.name = ++ptr;
03577
03578
03579
03580
03581
03582
03583
03584 if (data->set.use_netrc != CURL_NETRC_REQUIRED) {
03585
03586
03587 conn->bits.user_passwd = 1;
03588
03589 if(*userpass != ':') {
03590
03591 sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:@]:"
03592 "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
03593 user, passwd);
03594 }
03595 else
03596
03597 sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", passwd);
03598
03599 if(user[0]) {
03600 char *newname=curl_easy_unescape(data, user, 0, NULL);
03601 if(!newname)
03602 return CURLE_OUT_OF_MEMORY;
03603 if(strlen(newname) < sizeof(user))
03604 strcpy(user, newname);
03605
03606
03607
03608 free(newname);
03609 }
03610 if (passwd[0]) {
03611
03612 char *newpasswd=curl_easy_unescape(data, passwd, 0, NULL);
03613 if(!newpasswd)
03614 return CURLE_OUT_OF_MEMORY;
03615 if(strlen(newpasswd) < sizeof(passwd))
03616 strcpy(passwd, newpasswd);
03617
03618 free(newpasswd);
03619 }
03620 }
03621 }
03622 }
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636 if((1 == sscanf(conn->host.name, "[%*39[0-9a-fA-F:.]%c", &endbracket)) &&
03637 (']' == endbracket)) {
03638
03639 conn->bits.ipv6_ip = TRUE;
03640
03641 conn->host.name++;
03642 tmp = strchr(conn->host.name, ']');
03643 *tmp = 0;
03644 tmp++;
03645 if(':' != *tmp)
03646 tmp = NULL;
03647 }
03648 else
03649 tmp = strrchr(conn->host.name, ':');
03650
03651 if(data->set.use_port && data->state.allow_port) {
03652
03653 conn->remote_port = (unsigned short)data->set.use_port;
03654 if(tmp)
03655 *tmp = '\0';
03656
03657 if(conn->bits.httpproxy) {
03658
03659 char *url;
03660
03661 url = aprintf("%s://%s:%d%s", conn->protostr, conn->host.name,
03662 conn->remote_port, data->reqdata.path);
03663 if(!url)
03664 return CURLE_OUT_OF_MEMORY;
03665
03666 if(data->change.url_alloc)
03667 free(data->change.url);
03668
03669 data->change.url = url;
03670 data->change.url_alloc = TRUE;
03671 }
03672 }
03673 else if (tmp) {
03674
03675
03676 char *rest;
03677 unsigned long port;
03678
03679 port=strtoul(tmp+1, &rest, 10);
03680
03681 if (rest != (tmp+1) && *rest == '\0') {
03682
03683
03684
03685 if (port > 0xffff) {
03686
03687 failf(data, "Port number too large: %lu", port);
03688 return CURLE_URL_MALFORMAT;
03689 }
03690
03691 *tmp = '\0';
03692 conn->remote_port = (unsigned short)port;
03693 }
03694 }
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705 if (data->set.userpwd != NULL) {
03706
03707 sscanf(data->set.userpwd,
03708 "%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
03709 "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
03710 user, passwd);
03711 }
03712
03713 conn->bits.netrc = FALSE;
03714 if (data->set.use_netrc != CURL_NETRC_IGNORED) {
03715 if(Curl_parsenetrc(conn->host.name,
03716 user, passwd,
03717 data->set.netrc_file)) {
03718 infof(data, "Couldn't find host %s in the " DOT_CHAR
03719 "netrc file, using defaults\n",
03720 conn->host.name);
03721 }
03722 else {
03723
03724
03725
03726 conn->bits.netrc = TRUE;
03727
03728 conn->bits.user_passwd = 1;
03729 }
03730 }
03731
03732
03733 if ( (conn->protocol & PROT_FTP) &&
03734 !conn->bits.user_passwd) {
03735
03736 conn->user = strdup(CURL_DEFAULT_USER);
03737 conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
03738
03739 }
03740 else {
03741
03742 conn->user = strdup(user);
03743 conn->passwd = strdup(passwd);
03744 }
03745 if(!conn->user || !conn->passwd)
03746 return CURLE_OUT_OF_MEMORY;
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756 if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
03757 return CURLE_OUT_OF_MEMORY;
03758
03759
03760
03761
03762
03763 if(data->set.reuse_fresh && !data->state.this_is_a_follow)
03764 reuse = FALSE;
03765 else
03766 reuse = ConnectionExists(data, conn, &conn_temp);
03767
03768 if(reuse) {
03769
03770
03771
03772
03773
03774
03775 struct connectdata *old_conn = conn;
03776
03777 if(old_conn->proxy.rawalloc)
03778 free(old_conn->proxy.rawalloc);
03779
03780
03781
03782 Curl_free_ssl_config(&conn->ssl_config);
03783
03784 conn = conn_temp;
03785
03786 conn->data = old_conn->data;
03787
03788
03789
03790 conn->bits.user_passwd = old_conn->bits.user_passwd;
03791 if (conn->bits.user_passwd) {
03792
03793 Curl_safefree(conn->user);
03794 Curl_safefree(conn->passwd);
03795 conn->user = old_conn->user;
03796 conn->passwd = old_conn->passwd;
03797 old_conn->user = NULL;
03798 old_conn->passwd = NULL;
03799 }
03800
03801 conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
03802 if (conn->bits.proxy_user_passwd) {
03803
03804 Curl_safefree(conn->proxyuser);
03805 Curl_safefree(conn->proxypasswd);
03806 conn->proxyuser = old_conn->proxyuser;
03807 conn->proxypasswd = old_conn->proxypasswd;
03808 old_conn->proxyuser = NULL;
03809 old_conn->proxypasswd = NULL;
03810 }
03811
03812
03813 if (conn->bits.proxy) {
03814 free(conn->host.rawalloc);
03815 conn->host=old_conn->host;
03816 }
03817 else
03818 free(old_conn->host.rawalloc);
03819
03820
03821 conn->bits.no_body = old_conn->bits.no_body;
03822
03823
03824 conn->bits.reuse = TRUE;
03825
03826 Curl_safefree(old_conn->user);
03827 Curl_safefree(old_conn->passwd);
03828 Curl_safefree(old_conn->proxyuser);
03829 Curl_safefree(old_conn->proxypasswd);
03830 Curl_llist_destroy(old_conn->send_pipe, NULL);
03831 Curl_llist_destroy(old_conn->recv_pipe, NULL);
03832 Curl_safefree(old_conn->master_buffer);
03833
03834 free(old_conn);
03835
03836 *in_connect = conn;
03837
03838 infof(data, "Re-using existing connection! (#%ld) with host %s\n",
03839 conn->connectindex,
03840 conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
03841 }
03842 else {
03843
03844
03845
03846
03847 ConnectionStore(data, conn);
03848 }
03849
03850 result = setup_range(data);
03851 if(result)
03852 return result;
03853
03854
03855
03856
03857
03858
03859
03860 conn->fread = data->set.fread;
03861 conn->fread_in = data->set.in;
03862
03863 if ((conn->protocol&PROT_HTTP) &&
03864 data->set.upload &&
03865 (data->set.infilesize == -1) &&
03866 (data->set.httpversion != CURL_HTTP_VERSION_1_0)) {
03867
03868 conn->bits.upload_chunky = TRUE;
03869 }
03870 else {
03871
03872 conn->bits.upload_chunky = FALSE;
03873 }
03874
03875 #ifndef USE_ARES
03876
03877
03878
03879
03880 if((data->set.timeout || data->set.connecttimeout) && !data->set.no_signal) {
03881
03882
03883
03884
03885
03886 #ifdef SIGALRM
03887 #ifdef HAVE_ALARM
03888 long shortest;
03889 #endif
03890 #ifdef HAVE_SIGACTION
03891 struct sigaction sigact;
03892 sigaction(SIGALRM, NULL, &sigact);
03893 keep_sigact = sigact;
03894 keep_copysig = TRUE;
03895 sigact.sa_handler = alarmfunc;
03896 #ifdef SA_RESTART
03897
03898 sigact.sa_flags &= ~SA_RESTART;
03899 #endif
03900
03901 sigaction(SIGALRM, &sigact, NULL);
03902 #else
03903
03904 #ifdef HAVE_SIGNAL
03905 keep_sigact = signal(SIGALRM, alarmfunc);
03906 #endif
03907 #endif
03908
03909
03910
03911
03912
03913
03914 #ifdef HAVE_ALARM
03915 shortest = data->set.timeout;
03916 if(shortest && data->set.connecttimeout &&
03917 (data->set.connecttimeout < shortest))
03918
03919 shortest = data->set.connecttimeout;
03920 else if(!shortest)
03921
03922 shortest = data->set.connecttimeout;
03923
03924 if(shortest < 1000)
03925
03926
03927 return CURLE_OPERATION_TIMEDOUT;
03928
03929
03930
03931 prev_alarm = alarm((unsigned int) (shortest ? shortest/1000L : shortest));
03932
03933
03934
03935 #endif
03936 #endif
03937 }
03938 #endif
03939
03940
03941
03942
03943 if(conn->bits.reuse) {
03944
03945 hostaddr = NULL;
03946
03947
03948 if (conn->bits.proxy)
03949 fix_hostname(data, conn, &conn->host);
03950 }
03951 else {
03952
03953
03954
03955 fix_hostname(data, conn, &conn->host);
03956
03957 if(!conn->proxy.name || !*conn->proxy.name) {
03958
03959
03960 conn->port = conn->remote_port;
03961
03962
03963 rc = Curl_resolv(conn, conn->host.name, (int)conn->port, &hostaddr);
03964 if(rc == CURLRESOLV_PENDING)
03965 *async = TRUE;
03966
03967 else if(!hostaddr) {
03968 failf(data, "Couldn't resolve host '%s'", conn->host.dispname);
03969 result = CURLE_COULDNT_RESOLVE_HOST;
03970
03971 }
03972 }
03973 else {
03974
03975
03976
03977 fix_hostname(data, conn, &conn->proxy);
03978
03979
03980 rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &hostaddr);
03981
03982 if(rc == CURLRESOLV_PENDING)
03983 *async = TRUE;
03984
03985 else if(!hostaddr) {
03986 failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
03987 result = CURLE_COULDNT_RESOLVE_PROXY;
03988
03989 }
03990 }
03991 }
03992 *addr = hostaddr;
03993
03994 #if defined(HAVE_ALARM) && defined(SIGALRM) && !defined(USE_ARES)
03995 if((data->set.timeout || data->set.connecttimeout) && !data->set.no_signal) {
03996 #ifdef HAVE_SIGACTION
03997 if(keep_copysig) {
03998
03999
04000 sigaction(SIGALRM, &keep_sigact, NULL);
04001 }
04002 #else
04003 #ifdef HAVE_SIGNAL
04004
04005 signal(SIGALRM, keep_sigact);
04006 #endif
04007 #endif
04008
04009
04010
04011 if(prev_alarm) {
04012
04013 unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
04014 unsigned long alarm_set;
04015
04016
04017 alarm_set = prev_alarm - elapsed_ms/1000;
04018
04019 if(!alarm_set ||
04020 ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
04021
04022
04023
04024
04025 alarm(1);
04026 result = CURLE_OPERATION_TIMEOUTED;
04027 failf(data, "Previous alarm fired off!");
04028 }
04029 else
04030 alarm((unsigned int)alarm_set);
04031 }
04032 else
04033 alarm(0);
04034 }
04035 #endif
04036
04037 return result;
04038 }
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049 static CURLcode SetupConnection(struct connectdata *conn,
04050 struct Curl_dns_entry *hostaddr,
04051 bool *protocol_done)
04052 {
04053 CURLcode result=CURLE_OK;
04054 struct SessionHandle *data = conn->data;
04055
04056 Curl_pgrsTime(data, TIMER_NAMELOOKUP);
04057
04058 if(conn->protocol & PROT_FILE) {
04059
04060
04061 *protocol_done = TRUE;
04062 return result;
04063 }
04064 *protocol_done = FALSE;
04065
04066
04067
04068
04069 if((conn->protocol&PROT_HTTP) && data->set.useragent) {
04070 Curl_safefree(conn->allocptr.uagent);
04071 conn->allocptr.uagent =
04072 aprintf("User-Agent: %s\r\n", data->set.useragent);
04073 if(!conn->allocptr.uagent)
04074 return CURLE_OUT_OF_MEMORY;
04075 }
04076
04077 data->reqdata.keep.headerbytecount = 0;
04078
04079 #ifdef CURL_DO_LINEEND_CONV
04080 data->state.crlf_conversions = 0;
04081 #endif
04082
04083 for(;;) {
04084
04085
04086 if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
04087 bool connected = FALSE;
04088
04089
04090 result = ConnectPlease(data, conn, hostaddr, &connected);
04091
04092 if(connected) {
04093 result = Curl_protocol_connect(conn, protocol_done);
04094 if(CURLE_OK == result)
04095 conn->bits.tcpconnect = TRUE;
04096 }
04097 else
04098 conn->bits.tcpconnect = FALSE;
04099
04100
04101
04102
04103 if(conn->bits.proxy_connect_closed) {
04104
04105 if (data->set.errorbuffer)
04106 data->set.errorbuffer[0] = '\0';
04107 data->state.errorbuf = FALSE;
04108 continue;
04109 }
04110
04111 if(CURLE_OK != result)
04112 return result;
04113 }
04114 else {
04115 Curl_pgrsTime(data, TIMER_CONNECT);
04116 conn->bits.tcpconnect = TRUE;
04117 *protocol_done = TRUE;
04118 if(data->set.verbose)
04119 verboseconnect(conn);
04120 }
04121
04122 break;
04123 }
04124
04125 conn->now = Curl_tvnow();
04126
04127
04128 #ifdef __EMX__
04129
04130
04131
04132
04133
04134
04135 if ((data->set.out)->_handle == NULL) {
04136 _fsetmode(stdout, "b");
04137 }
04138 #endif
04139
04140 return CURLE_OK;
04141 }
04142
04143 CURLcode Curl_connect(struct SessionHandle *data,
04144 struct connectdata **in_connect,
04145 bool *asyncp,
04146 bool *protocol_done)
04147 {
04148 CURLcode code;
04149 struct Curl_dns_entry *dns;
04150
04151 *asyncp = FALSE;
04152
04153
04154 code = CreateConnection(data, in_connect, &dns, asyncp);
04155
04156 if(CURLE_OK == code) {
04157
04158 if(dns || !*asyncp)
04159
04160
04161
04162 code = SetupConnection(*in_connect, dns, protocol_done);
04163
04164
04165 }
04166
04167 if(CURLE_OK != code) {
04168
04169
04170 if(*in_connect) {
04171 Curl_disconnect(*in_connect);
04172 *in_connect = NULL;
04173 }
04174 }
04175 else {
04176 if ((*in_connect)->is_in_pipeline)
04177 data->state.is_in_pipeline = TRUE;
04178 }
04179
04180 return code;
04181 }
04182
04183
04184
04185
04186
04187
04188 CURLcode Curl_async_resolved(struct connectdata *conn,
04189 bool *protocol_done)
04190 {
04191 #if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME) || \
04192 defined(USE_THREADING_GETADDRINFO)
04193 CURLcode code = SetupConnection(conn, conn->async.dns, protocol_done);
04194
04195 if(code)
04196
04197
04198 Curl_disconnect(conn);
04199
04200 return code;
04201 #else
04202 (void)conn;
04203 (void)protocol_done;
04204 return CURLE_OK;
04205 #endif
04206 }
04207
04208
04209 CURLcode Curl_done(struct connectdata **connp,
04210 CURLcode status,
04211
04212 bool premature)
04213 {
04214 CURLcode result;
04215 struct connectdata *conn = *connp;
04216 struct SessionHandle *data = conn->data;
04217
04218 Curl_expire(data, 0);
04219
04220 if(conn->bits.done)
04221 return CURLE_OK;
04222
04223 conn->bits.done = TRUE;
04224
04225 if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) &&
04226 conn->readchannel_inuse)
04227 conn->readchannel_inuse = FALSE;
04228 if(Curl_removeHandleFromPipeline(data, conn->send_pipe) &&
04229 conn->writechannel_inuse)
04230 conn->writechannel_inuse = FALSE;
04231
04232
04233 if(data->reqdata.newurl) {
04234 free(data->reqdata.newurl);
04235 data->reqdata.newurl = NULL;
04236 }
04237
04238 if(conn->dns_entry) {
04239 Curl_resolv_unlock(data, conn->dns_entry);
04240 conn->dns_entry = NULL;
04241 }
04242
04243
04244 if(conn->curl_done)
04245 result = conn->curl_done(conn, status, premature);
04246 else
04247 result = CURLE_OK;
04248
04249 Curl_pgrsDone(conn);
04250
04251
04252
04253 ares_cancel(data->state.areschannel);
04254
04255
04256
04257
04258
04259
04260
04261 if(data->set.reuse_forbid || conn->bits.close) {
04262 CURLcode res2 = Curl_disconnect(conn);
04263
04264
04265
04266 if(!result && res2)
04267 result = res2;
04268 }
04269 else {
04270 ConnectionDone(conn);
04271
04272
04273 data->state.lastconnect = conn->connectindex;
04274
04275 infof(data, "Connection #%ld to host %s left intact\n",
04276 conn->connectindex,
04277 conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
04278 }
04279
04280 *connp = NULL;
04281
04282
04283
04284
04285 return result;
04286 }
04287
04288 CURLcode Curl_do(struct connectdata **connp, bool *done)
04289 {
04290 CURLcode result=CURLE_OK;
04291 struct connectdata *conn = *connp;
04292 struct SessionHandle *data = conn->data;
04293
04294 conn->bits.done = FALSE;
04295 conn->bits.do_more = FALSE;
04296
04297 if(conn->curl_do) {
04298
04299 result = conn->curl_do(conn, done);
04300
04301
04302
04303 if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
04304
04305
04306
04307
04308
04309
04310 infof(data, "Re-used connection seems dead, get a new one\n");
04311
04312 conn->bits.close = TRUE;
04313 result = Curl_done(&conn, result, FALSE);
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324 if((CURLE_OK == result) || (CURLE_SEND_ERROR == result)) {
04325 bool async;
04326 bool protocol_done = TRUE;
04327
04328
04329 result = Curl_connect(data, connp, &async, &protocol_done);
04330 if(CURLE_OK == result) {
04331
04332
04333 conn = *connp;
04334 if(async) {
04335
04336
04337 result = Curl_wait_for_resolv(conn, NULL);
04338 if(result)
04339 return result;
04340
04341
04342 result = Curl_async_resolved(conn, &protocol_done);
04343 if(result)
04344 return result;
04345 }
04346
04347
04348 result = conn->curl_do(conn, done);
04349 }
04350 }
04351 }
04352 }
04353 return result;
04354 }
04355
04356 CURLcode Curl_do_more(struct connectdata *conn)
04357 {
04358 CURLcode result=CURLE_OK;
04359
04360 if(conn->curl_do_more)
04361 result = conn->curl_do_more(conn);
04362
04363 return result;
04364 }