~ubuntu-branches/ubuntu/lucid/curl/lucid-201101212007

« back to all changes in this revision

Viewing changes to lib/url.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-05-16 15:16:54 UTC
  • mto: (3.1.1 lenny) (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20070516151654-x9nkigtr2j0i8d0v
Tags: upstream-7.16.2
ImportĀ upstreamĀ versionĀ 7.16.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: url.c,v 1.514 2006-07-31 17:46:28 yangtse Exp $
 
21
 * $Id: url.c,v 1.611 2007-04-10 20:46:40 bagder Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
/* -- WIN32 approved -- */
30
30
#include <stdarg.h>
31
31
#include <stdlib.h>
32
32
#include <ctype.h>
33
 
#ifdef HAVE_SYS_TYPES_H
34
 
#include <sys/types.h>
35
 
#endif
36
 
#ifdef HAVE_SYS_STAT_H
37
 
#include <sys/stat.h>
38
 
#endif
39
33
#include <errno.h>
40
34
 
41
 
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
 
35
#ifdef WIN32
42
36
#include <time.h>
43
37
#include <io.h>
44
38
#else
45
39
#ifdef HAVE_SYS_SOCKET_H
46
40
#include <sys/socket.h>
47
41
#endif
 
42
#ifdef HAVE_NETINET_IN_H
48
43
#include <netinet/in.h>
 
44
#endif
 
45
#ifdef HAVE_SYS_TIME_H
49
46
#include <sys/time.h>
 
47
#endif
50
48
#ifdef HAVE_UNISTD_H
51
49
#include <unistd.h>
52
50
#endif
 
51
#ifdef HAVE_NETDB_H
53
52
#include <netdb.h>
 
53
#endif
54
54
#ifdef HAVE_ARPA_INET_H
55
55
#include <arpa/inet.h>
56
56
#endif
57
57
#ifdef HAVE_NET_IF_H
58
58
#include <net/if.h>
59
59
#endif
 
60
#ifdef HAVE_SYS_IOCTL_H
60
61
#include <sys/ioctl.h>
 
62
#endif
 
63
#if HAVE_SIGNAL_H
61
64
#include <signal.h>
 
65
#endif
62
66
 
63
67
#ifdef HAVE_SYS_PARAM_H
64
68
#include <sys/param.h>
77
81
#error "We can't compile without socket() support!"
78
82
#endif
79
83
 
80
 
#endif
 
84
#endif  /* WIN32 */
 
85
 
81
86
#ifdef USE_LIBIDN
82
87
#include <idna.h>
83
88
#include <tld.h>
93
98
   instead */
94
99
#define idn_free(x) (free)(x)
95
100
#endif
96
 
#endif
 
101
#endif  /* USE_LIBIDN */
97
102
 
98
103
#include "urldata.h"
99
104
#include "netrc.h"
116
121
#include "http_negotiate.h"
117
122
#include "select.h"
118
123
#include "multiif.h"
 
124
#include "easyif.h"
119
125
 
120
126
/* And now for the protocols */
121
127
#include "ftp.h"
125
131
#include "http.h"
126
132
#include "file.h"
127
133
#include "ldap.h"
 
134
#include "ssh.h"
128
135
#include "url.h"
129
136
#include "connect.h"
130
137
#include "inet_ntop.h"
131
138
#include "http_ntlm.h"
 
139
#include "socks.h"
132
140
#include <ca-bundle.h>
133
141
 
134
142
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
153
161
                             struct connectdata **usethis);
154
162
static long ConnectionStore(struct SessionHandle *data,
155
163
                            struct connectdata *conn);
 
164
static bool IsPipeliningPossible(struct SessionHandle *handle);
 
165
static bool IsPipeliningEnabled(struct SessionHandle *handle);
 
166
static void conn_free(struct connectdata *conn);
 
167
 
 
168
static void signalPipeClose(struct curl_llist *pipe);
 
169
 
 
170
static struct SessionHandle* gethandleathead(struct curl_llist *pipe);
 
171
 
 
172
#define MAX_PIPELINE_LENGTH 5
 
173
 
 
174
/*
 
175
 * We use this ZERO_NULL to avoid picky compiler warnings,
 
176
 * when assigning a NULL pointer to a function pointer var.
 
177
 */
 
178
 
 
179
#define ZERO_NULL 0
156
180
 
157
181
#ifndef USE_ARES
158
 
/* not for Win32, unless it is cygwin
159
 
   not for ares builds */
160
 
#if !defined(WIN32) || defined(__CYGWIN__)
161
 
 
162
 
#ifndef RETSIGTYPE
163
 
#define RETSIGTYPE void
164
 
#endif
 
182
/* not for ares builds */
 
183
 
 
184
#ifndef WIN32
 
185
/* not for WIN32 builds */
 
186
 
165
187
#ifdef HAVE_SIGSETJMP
166
188
extern sigjmp_buf curl_jmpenv;
167
189
#endif
 
190
 
 
191
#ifdef SIGALRM
168
192
static
169
193
RETSIGTYPE alarmfunc(int sig)
170
194
{
175
199
#endif
176
200
  return;
177
201
}
 
202
#endif /* SIGALRM */
 
203
#endif /* WIN32 */
 
204
#endif /* USE_ARES */
 
205
 
 
206
#ifdef CURL_DISABLE_VERBOSE_STRINGS
 
207
#define verboseconnect(x)  do { } while (0)
178
208
#endif
179
 
#endif /* USE_ARES */
180
209
 
181
210
void Curl_safefree(void *ptr)
182
211
{
184
213
    free(ptr);
185
214
}
186
215
 
 
216
static void close_connections(struct SessionHandle *data)
 
217
{
 
218
  /* Loop through all open connections and kill them one by one */
 
219
  while(-1 != ConnectionKillOne(data))
 
220
    ; /* empty loop */
 
221
}
 
222
 
187
223
/*
188
224
 * This is the internal function curl_easy_cleanup() calls. This should
189
225
 * cleanup and free all resources associated with this sessionhandle.
195
231
 
196
232
CURLcode Curl_close(struct SessionHandle *data)
197
233
{
198
 
  if(data->multi) {
199
 
    /* this handle is still part of a multi handle, take care of this first */
 
234
  struct Curl_multi *m = data->multi;
 
235
 
 
236
#ifdef CURLDEBUG
 
237
  /* only for debugging, scan through all connections and see if there's a
 
238
     pipe reference still identifying this handle */
 
239
 
 
240
  if(data->state.is_in_pipeline)
 
241
    fprintf(stderr, "CLOSED when in pipeline!\n");
 
242
 
 
243
  if(data->state.connc && data->state.connc->type == CONNCACHE_MULTI) {
 
244
    struct conncache *c = data->state.connc;
 
245
    int i;
 
246
    struct curl_llist *pipe;
 
247
    struct curl_llist_element *curr;
 
248
    struct connectdata *connptr;
 
249
 
 
250
    for(i=0; i< c->num; i++) {
 
251
      connptr = c->connects[i];
 
252
      if(!connptr)
 
253
        continue;
 
254
 
 
255
      pipe = connptr->send_pipe;
 
256
      if(pipe) {
 
257
        for (curr = pipe->head; curr; curr=curr->next) {
 
258
          if(data == (struct SessionHandle *) curr->ptr) {
 
259
            fprintf(stderr,
 
260
                    "MAJOR problem we %p are still in send pipe for %p done %d\n",
 
261
                    data, connptr, connptr->bits.done);
 
262
          }
 
263
        }
 
264
      }
 
265
      pipe = connptr->recv_pipe;
 
266
      if(pipe) {
 
267
        for (curr = pipe->head; curr; curr=curr->next) {
 
268
          if(data == (struct SessionHandle *) curr->ptr) {
 
269
            fprintf(stderr,
 
270
                    "MAJOR problem we %p are still in recv pipe for %p done %d\n",
 
271
                    data, connptr, connptr->bits.done);
 
272
          }
 
273
        }
 
274
      }
 
275
    }
 
276
  }
 
277
#endif
 
278
 
 
279
  if(m)
 
280
    /* This handle is still part of a multi handle, take care of this first
 
281
       and detach this handle from there. */
200
282
    Curl_multi_rmeasy(data->multi, data);
201
 
  }
202
 
  /* Loop through all open connections and kill them one by one */
203
 
  while(-1 != ConnectionKillOne(data))
204
 
    ; /* empty loop */
 
283
 
 
284
  data->magic = 0; /* force a clear AFTER the possibly enforced removal from
 
285
                      the multi handle, since that function uses the magic
 
286
                      field! */
 
287
 
 
288
  if(data->state.connc) {
 
289
 
 
290
    if(data->state.connc->type == CONNCACHE_PRIVATE) {
 
291
      /* close all connections still alive that are in the private connection
 
292
         cache, as we no longer have the pointer left to the shared one. */
 
293
      close_connections(data);
 
294
 
 
295
      /* free the connection cache if allocated privately */
 
296
      Curl_rm_connc(data->state.connc);
 
297
    }
 
298
  }
 
299
 
 
300
  if(data->state.shared_conn) {
 
301
    /* marked to be used by a pending connection so we can't kill this handle
 
302
       just yet */
 
303
    data->state.closed = TRUE;
 
304
    return CURLE_OK;
 
305
  }
205
306
 
206
307
  if ( ! (data->share && data->share->hostcache) ) {
207
308
    if ( !Curl_global_host_cache_use(data)) {
209
310
    }
210
311
  }
211
312
 
 
313
  /* Free the pathbuffer */
 
314
  Curl_safefree(data->reqdata.pathbuffer);
 
315
  Curl_safefree(data->reqdata.proto.generic);
 
316
 
212
317
  /* Close down all open SSL info and sessions */
213
318
  Curl_ssl_close_all(data);
214
319
  Curl_safefree(data->state.first_host);
215
320
  Curl_safefree(data->state.scratch);
216
321
 
217
 
  if(data->change.proxy_alloc)
218
 
    free(data->change.proxy);
219
 
 
220
322
  if(data->change.referer_alloc)
221
323
    free(data->change.referer);
222
324
 
252
354
  Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
253
355
#endif
254
356
 
255
 
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
256
357
  Curl_digest_cleanup(data);
257
 
#endif
258
 
 
259
 
  /* free the connection cache */
260
 
  free(data->state.connects);
261
358
 
262
359
  Curl_safefree(data->info.contenttype);
263
360
 
264
 
#ifdef USE_ARES
265
361
  /* this destroys the channel and we cannot use it anymore after this */
266
362
  ares_destroy(data->state.areschannel);
267
 
#endif
268
363
 
269
364
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
270
365
  /* close iconv conversion descriptors */
287
382
  return CURLE_OK;
288
383
}
289
384
 
 
385
/* create a connection cache of a private or multi type */
 
386
struct conncache *Curl_mk_connc(int type,
 
387
                                long amount) /* set -1 to use default */
 
388
{
 
389
  /* It is subject for debate how many default connections to have for a multi
 
390
     connection cache... */
 
391
 
 
392
  struct conncache *c;
 
393
  long default_amount;
 
394
 
 
395
  if (type == CONNCACHE_PRIVATE) {
 
396
    default_amount = (amount < 0) ? 5 : amount;
 
397
  }
 
398
  else {
 
399
    default_amount = (amount < 0) ? 10 : amount;
 
400
  }
 
401
 
 
402
  c= calloc(sizeof(struct conncache), 1);
 
403
  if(!c)
 
404
    return NULL;
 
405
 
 
406
  if ((size_t)(default_amount) > ((size_t)-1) / sizeof(struct connectdata *))
 
407
    default_amount = ((size_t)-1) / sizeof(struct connectdata *);
 
408
 
 
409
  c->connects = calloc(sizeof(struct connectdata *), (size_t)default_amount);
 
410
  if(!c->connects) {
 
411
    free(c);
 
412
    return NULL;
 
413
  }
 
414
 
 
415
  c->num = default_amount;
 
416
 
 
417
  return c;
 
418
}
 
419
 
 
420
/* Change number of entries of a connection cache */
 
421
CURLcode Curl_ch_connc(struct SessionHandle *data,
 
422
                       struct conncache *c,
 
423
                       long newamount)
 
424
{
 
425
  long i;
 
426
  struct connectdata **newptr;
 
427
 
 
428
  if(newamount < 1)
 
429
    newamount = 1; /* we better have at least one entry */
 
430
 
 
431
  if(!c) {
 
432
    /* we get a NULL pointer passed in as connection cache, which means that
 
433
       there is no cache created for this SessionHandle just yet, we create a
 
434
       brand new with the requested size.
 
435
    */
 
436
    data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, newamount);
 
437
    if(!data->state.connc)
 
438
      return CURLE_OUT_OF_MEMORY;
 
439
    return CURLE_OK;
 
440
  }
 
441
 
 
442
  if(newamount < c->num) {
 
443
    /* Since this number is *decreased* from the existing number, we must
 
444
       close the possibly open connections that live on the indexes that
 
445
       are being removed!
 
446
 
 
447
       NOTE: for conncache_multi cases we must make sure that we only
 
448
       close handles not in use.
 
449
    */
 
450
    for(i=newamount; i< c->num; i++)
 
451
      Curl_disconnect(c->connects[i]);
 
452
 
 
453
    /* If the most recent connection is no longer valid, mark it
 
454
       invalid. */
 
455
    if(data->state.lastconnect <= newamount)
 
456
      data->state.lastconnect = -1;
 
457
  }
 
458
  if(newamount > 0) {
 
459
    newptr= (struct connectdata **)
 
460
      realloc(c->connects, sizeof(struct connectdata *) * newamount);
 
461
    if(!newptr)
 
462
      /* we closed a few connections in vain, but so what? */
 
463
      return CURLE_OUT_OF_MEMORY;
 
464
 
 
465
    /* nullify the newly added pointers */
 
466
    for(i=c->num; i<newamount; i++)
 
467
      newptr[i] = NULL;
 
468
 
 
469
    c->connects = newptr;
 
470
    c->num = newamount;
 
471
  }
 
472
  /* we no longer support less than 1 as size for the connection cache, and
 
473
     I'm not sure it ever worked to set it to zero */
 
474
  return CURLE_OK;
 
475
}
 
476
 
 
477
/* Free a connection cache. This is called from Curl_close() and
 
478
   curl_multi_cleanup(). */
 
479
void Curl_rm_connc(struct conncache *c)
 
480
{
 
481
  if(c->connects) {
 
482
    int i;
 
483
    for(i = 0; i < c->num; ++i)
 
484
      conn_free(c->connects[i]);
 
485
 
 
486
    free(c->connects);
 
487
  }
 
488
 
 
489
  free(c);
 
490
}
 
491
 
290
492
/**
291
493
 * Curl_open()
292
494
 *
299
501
{
300
502
  CURLcode res = CURLE_OK;
301
503
  struct SessionHandle *data;
 
504
#ifdef USE_ARES
 
505
  int status;
 
506
#endif
 
507
 
302
508
  /* Very simple start-up: alloc the struct, init it with zeroes and return */
303
509
  data = (struct SessionHandle *)calloc(1, sizeof(struct SessionHandle));
304
 
  if(!data)
 
510
  if(!data) {
305
511
    /* this is a very serious error */
 
512
    DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n"));
306
513
    return CURLE_OUT_OF_MEMORY;
 
514
  }
 
515
 
 
516
  data->magic = CURLEASY_MAGIC_NUMBER;
307
517
 
308
518
#ifdef USE_ARES
309
 
  if(ARES_SUCCESS != ares_init(&data->state.areschannel)) {
 
519
  if ((status = ares_init(&data->state.areschannel)) != ARES_SUCCESS) {
 
520
    DEBUGF(fprintf(stderr, "Error: ares_init failed\n"));
310
521
    free(data);
311
 
    return CURLE_FAILED_INIT;
 
522
    if (status == ARES_ENOMEM)
 
523
      return CURLE_OUT_OF_MEMORY;
 
524
    else
 
525
      return CURLE_FAILED_INIT;
312
526
  }
313
527
  /* make sure that all other returns from this function should destroy the
314
528
     ares channel before returning error! */
317
531
  /* We do some initial setup here, all those fields that can't be just 0 */
318
532
 
319
533
  data->state.headerbuff=(char*)malloc(HEADERSIZE);
320
 
  if(!data->state.headerbuff)
 
534
  if(!data->state.headerbuff) {
 
535
    DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
321
536
    res = CURLE_OUT_OF_MEMORY;
 
537
  }
322
538
  else {
323
539
    data->state.headersize=HEADERSIZE;
324
540
 
333
549
    data->set.fread = (curl_read_callback)fread;
334
550
 
335
551
    /* conversion callbacks for non-ASCII hosts */
336
 
    data->set.convfromnetwork = (curl_conv_callback)NULL;
337
 
    data->set.convtonetwork   = (curl_conv_callback)NULL;
338
 
    data->set.convfromutf8    = (curl_conv_callback)NULL;
 
552
    data->set.convfromnetwork = (curl_conv_callback)ZERO_NULL;
 
553
    data->set.convtonetwork   = (curl_conv_callback)ZERO_NULL;
 
554
    data->set.convfromutf8    = (curl_conv_callback)ZERO_NULL;
339
555
 
340
556
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
341
557
    /* conversion descriptors for iconv calls */
367
583
    data->set.httpauth = CURLAUTH_BASIC;  /* defaults to basic */
368
584
    data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic */
369
585
 
370
 
    /* create an array with connection data struct pointers */
371
 
    data->state.numconnects = 5; /* hard-coded right now */
372
 
    data->state.connects = (struct connectdata **)
373
 
      calloc(sizeof(struct connectdata *) * data->state.numconnects, 1);
 
586
    /* This no longer creates a connection cache here. It is instead made on
 
587
       the first call to curl_easy_perform() or when the handle is added to a
 
588
       multi stack. */
374
589
 
375
 
    if(!data->state.connects)
376
 
      res = CURLE_OUT_OF_MEMORY;
 
590
    data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
 
591
                                                        type */
377
592
 
378
593
    /* most recent connection is not yet defined */
379
594
    data->state.lastconnect = -1;
380
595
 
 
596
    Curl_easy_initHandleData(data);
 
597
 
381
598
    /*
382
599
     * libcurl 7.10 introduced SSL verification *by default*! This needs to be
383
600
     * switched off unless wanted.
384
601
     */
385
602
    data->set.ssl.verifypeer = TRUE;
386
603
    data->set.ssl.verifyhost = 2;
 
604
    data->set.ssl.sessionid = TRUE; /* session ID caching enabled by default */
387
605
#ifdef CURL_CA_BUNDLE
388
606
    /* This is our preferred CA cert bundle since install time */
389
607
    data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
391
609
  }
392
610
 
393
611
  if(res) {
394
 
#ifdef USE_ARES
395
612
    ares_destroy(data->state.areschannel);
396
 
#endif
397
613
    if(data->state.headerbuff)
398
614
      free(data->state.headerbuff);
399
615
    free(data);
400
616
    data = NULL;
401
617
  }
 
618
  else
 
619
    *curl = data;
402
620
 
403
 
  *curl = data;
404
 
  return CURLE_OK;
 
621
  return res;
405
622
}
406
623
 
407
624
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
421
638
        Curl_global_host_cache_init();
422
639
      }
423
640
 
424
 
      data->set.global_dns_cache = use_cache;
 
641
      data->set.global_dns_cache = (bool)(0 != use_cache);
425
642
    }
426
643
    break;
427
644
  case CURLOPT_SSL_CIPHER_LIST:
447
664
     * Set the absolute number of maximum simultaneous alive connection that
448
665
     * libcurl is allowed to have.
449
666
     */
450
 
    {
451
 
      long newconnects= va_arg(param, long);
452
 
      struct connectdata **newptr;
453
 
      long i;
454
 
 
455
 
      if(newconnects < data->state.numconnects) {
456
 
        /* Since this number is *decreased* from the existing number, we must
457
 
           close the possibly open connections that live on the indexes that
458
 
           are being removed! */
459
 
        for(i=newconnects; i< data->state.numconnects; i++)
460
 
          Curl_disconnect(data->state.connects[i]);
461
 
 
462
 
        /* If the most recent connection is no longer valid, mark it invalid. */
463
 
        if(data->state.lastconnect <= newconnects)
464
 
          data->state.lastconnect = -1;
465
 
      }
466
 
      if(newconnects) {
467
 
        newptr= (struct connectdata **)
468
 
          realloc(data->state.connects,
469
 
                  sizeof(struct connectdata *) * newconnects);
470
 
        if(!newptr)
471
 
          /* we closed a few connections in vain, but so what? */
472
 
          return CURLE_OUT_OF_MEMORY;
473
 
 
474
 
        /* nullify the newly added pointers */
475
 
        for(i=data->state.numconnects; i<newconnects; i++) {
476
 
          newptr[i] = NULL;
477
 
        }
478
 
 
479
 
        data->state.connects = newptr;
480
 
        data->state.numconnects = newconnects;
481
 
      }
482
 
      else {
483
 
        /* zero makes NO cache at all */
484
 
        if(data->state.connects)
485
 
          free(data->state.connects);
486
 
        data->state.connects = NULL;
487
 
        data->state.numconnects = 0;
488
 
        data->state.lastconnect = -1;
489
 
      }
490
 
    }
 
667
    result = Curl_ch_connc(data, data->state.connc, va_arg(param, long));
491
668
    break;
492
669
  case CURLOPT_FORBID_REUSE:
493
670
    /*
494
671
     * When this transfer is done, it must not be left to be reused by a
495
672
     * subsequent transfer but shall be closed immediately.
496
673
     */
497
 
    data->set.reuse_forbid = va_arg(param, long)?TRUE:FALSE;
 
674
    data->set.reuse_forbid = (bool)(0 != va_arg(param, long));
498
675
    break;
499
676
  case CURLOPT_FRESH_CONNECT:
500
677
    /*
501
678
     * This transfer shall not use a previously cached connection but
502
679
     * should be made with a fresh new connect!
503
680
     */
504
 
    data->set.reuse_fresh = va_arg(param, long)?TRUE:FALSE;
 
681
    data->set.reuse_fresh = (bool)(0 != va_arg(param, long));
505
682
    break;
506
683
  case CURLOPT_VERBOSE:
507
684
    /*
508
685
     * Verbose means infof() calls that give a lot of information about
509
686
     * the connection and transfer procedures as well as internal choices.
510
687
     */
511
 
    data->set.verbose = va_arg(param, long)?TRUE:FALSE;
 
688
    data->set.verbose = (bool)(0 != va_arg(param, long));
512
689
    break;
513
690
  case CURLOPT_HEADER:
514
691
    /*
515
692
     * Set to include the header in the general data output stream.
516
693
     */
517
 
    data->set.include_header = va_arg(param, long)?TRUE:FALSE;
 
694
    data->set.include_header = (bool)(0 != va_arg(param, long));
518
695
    break;
519
696
  case CURLOPT_NOPROGRESS:
520
697
    /*
521
698
     * Shut off the internal supported progress meter
522
699
     */
523
 
    data->set.hide_progress = va_arg(param, long)?TRUE:FALSE;
 
700
    data->set.hide_progress = (bool)(0 != va_arg(param, long));
524
701
    if(data->set.hide_progress)
525
702
      data->progress.flags |= PGRS_HIDE;
526
703
    else
530
707
    /*
531
708
     * Do not include the body part in the output data stream.
532
709
     */
533
 
    data->set.opt_no_body = va_arg(param, long)?TRUE:FALSE;
 
710
    data->set.opt_no_body = (bool)(0 != va_arg(param, long));
534
711
    if(data->set.opt_no_body)
535
712
      /* in HTTP lingo, this means using the HEAD request */
536
713
      data->set.httpreq = HTTPREQ_HEAD;
540
717
     * Don't output the >=300 error code HTML-page, but instead only
541
718
     * return error.
542
719
     */
543
 
    data->set.http_fail_on_error = va_arg(param, long)?TRUE:FALSE;
 
720
    data->set.http_fail_on_error = (bool)(0 != va_arg(param, long));
544
721
    break;
545
722
  case CURLOPT_UPLOAD:
546
723
  case CURLOPT_PUT:
548
725
     * We want to sent data to the remote host. If this is HTTP, that equals
549
726
     * using the PUT request.
550
727
     */
551
 
    data->set.upload = va_arg(param, long)?TRUE:FALSE;
 
728
    data->set.upload = (bool)(0 != va_arg(param, long));
552
729
    if(data->set.upload)
553
730
      /* If this is HTTP, PUT is what's needed to "upload" */
554
731
      data->set.httpreq = HTTPREQ_PUT;
558
735
     * Try to get the file time of the remote document. The time will
559
736
     * later (possibly) become available using curl_easy_getinfo().
560
737
     */
561
 
    data->set.get_filetime = va_arg(param, long)?TRUE:FALSE;
 
738
    data->set.get_filetime = (bool)(0 != va_arg(param, long));
562
739
    break;
563
740
  case CURLOPT_FTP_CREATE_MISSING_DIRS:
564
741
    /*
565
742
     * An FTP option that modifies an upload to create missing directories on
566
743
     * the server.
567
744
     */
568
 
    data->set.ftp_create_missing_dirs = va_arg( param , long )?TRUE:FALSE;
 
745
    data->set.ftp_create_missing_dirs = (bool)(0 != va_arg(param, long));
569
746
    break;
570
747
  case CURLOPT_FTP_RESPONSE_TIMEOUT:
571
748
    /*
572
749
     * An FTP option that specifies how quickly an FTP response must be
573
750
     * obtained before it is considered failure.
574
751
     */
575
 
    data->set.ftp_response_timeout = va_arg( param , long );
 
752
    data->set.ftp_response_timeout = va_arg( param , long ) * 1000;
576
753
    break;
577
754
  case CURLOPT_FTPLISTONLY:
578
755
    /*
579
756
     * An FTP option that changes the command to one that asks for a list
580
757
     * only, no file info details.
581
758
     */
582
 
    data->set.ftp_list_only = va_arg(param, long)?TRUE:FALSE;
 
759
    data->set.ftp_list_only = (bool)(0 != va_arg(param, long));
583
760
    break;
584
761
  case CURLOPT_FTPAPPEND:
585
762
    /*
586
763
     * We want to upload and append to an existing (FTP) file.
587
764
     */
588
 
    data->set.ftp_append = va_arg(param, long)?TRUE:FALSE;
 
765
    data->set.ftp_append = (bool)(0 != va_arg(param, long));
589
766
    break;
590
767
  case CURLOPT_FTP_FILEMETHOD:
591
768
    /*
612
789
     *
613
790
     * Transfer using ASCII (instead of BINARY).
614
791
     */
615
 
    data->set.ftp_ascii = va_arg(param, long)?TRUE:FALSE;
 
792
    data->set.prefer_ascii = (bool)(0 != va_arg(param, long));
616
793
    break;
617
794
  case CURLOPT_TIMECONDITION:
618
795
    /*
641
818
    /*
642
819
     * Switch on automatic referer that gets set if curl follows locations.
643
820
     */
644
 
    data->set.http_auto_referer = va_arg(param, long)?1:0;
 
821
    data->set.http_auto_referer = (bool)(0 != va_arg(param, long));
645
822
    break;
646
823
 
647
824
  case CURLOPT_ENCODING:
663
840
    /*
664
841
     * Follow Location: header hints on a HTTP-server.
665
842
     */
666
 
    data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
 
843
    data->set.http_follow_location = (bool)(0 != va_arg(param, long));
667
844
    break;
668
845
 
669
846
  case CURLOPT_UNRESTRICTED_AUTH:
672
849
     * hostname changed.
673
850
     */
674
851
    data->set.http_disable_hostname_check_before_authentication =
675
 
      va_arg(param, long)?TRUE:FALSE;
 
852
      (bool)(0 != va_arg(param, long));
676
853
    break;
677
854
 
678
855
  case CURLOPT_MAXREDIRS:
817
994
     * We run mostly with the original cookie spec, as hardly anyone implements
818
995
     * anything else.
819
996
     */
820
 
    data->set.cookiesession = (bool)va_arg(param, long);
 
997
    data->set.cookiesession = (bool)(0 != va_arg(param, long));
821
998
    break;
822
999
 
823
1000
  case CURLOPT_COOKIELIST:
882
1059
    /*
883
1060
     * Tunnel operations through the proxy instead of normal proxy use
884
1061
     */
885
 
    data->set.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
 
1062
    data->set.tunnel_thru_httpproxy = (bool)(0 != va_arg(param, long));
886
1063
    break;
887
1064
 
888
1065
  case CURLOPT_CUSTOMREQUEST:
955
1132
     * Setting it to NULL, means no proxy but allows the environment variables
956
1133
     * to decide for us.
957
1134
     */
958
 
    if(data->change.proxy_alloc) {
959
 
      /*
960
 
       * The already set string is allocated, free that first
961
 
       */
962
 
      data->change.proxy_alloc=FALSE;;
963
 
      free(data->change.proxy);
964
 
    }
965
 
    data->set.set_proxy = va_arg(param, char *);
966
 
    data->change.proxy = data->set.set_proxy;
 
1135
    data->set.proxy = va_arg(param, char *);
967
1136
    break;
968
1137
 
969
1138
  case CURLOPT_WRITEHEADER:
990
1159
     * Use FTP PORT, this also specifies which IP address to use
991
1160
     */
992
1161
    data->set.ftpport = va_arg(param, char *);
993
 
    data->set.ftp_use_port = data->set.ftpport?1:0;
 
1162
    data->set.ftp_use_port = (bool)(NULL != data->set.ftpport);
994
1163
    break;
995
1164
 
996
1165
  case CURLOPT_FTP_USE_EPRT:
997
 
    data->set.ftp_use_eprt = va_arg(param, long)?TRUE:FALSE;
 
1166
    data->set.ftp_use_eprt = (bool)(0 != va_arg(param, long));
998
1167
    break;
999
1168
 
1000
1169
  case CURLOPT_FTP_USE_EPSV:
1001
 
    data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
 
1170
    data->set.ftp_use_epsv = (bool)(0 != va_arg(param, long));
 
1171
    break;
 
1172
 
 
1173
  case CURLOPT_FTP_SSL_CCC:
 
1174
    data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
1002
1175
    break;
1003
1176
 
1004
1177
  case CURLOPT_FTP_SKIP_PASV_IP:
1006
1179
     * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
1007
1180
     * bypass of the IP address in PASV responses.
1008
1181
     */
1009
 
    data->set.ftp_skip_ip = (bool)va_arg(param, long);
 
1182
    data->set.ftp_skip_ip = (bool)(0 != va_arg(param, long));
1010
1183
    break;
1011
1184
 
1012
1185
  case CURLOPT_INFILE:
1084
1257
     * The maximum time you allow curl to use for a single transfer
1085
1258
     * operation.
1086
1259
     */
 
1260
    data->set.timeout = va_arg(param, long) * 1000L;
 
1261
    break;
 
1262
 
 
1263
  case CURLOPT_TIMEOUT_MS:
1087
1264
    data->set.timeout = va_arg(param, long);
1088
1265
    break;
 
1266
 
1089
1267
  case CURLOPT_CONNECTTIMEOUT:
1090
1268
    /*
1091
1269
     * The maximum time you allow curl to use to connect.
1092
1270
     */
 
1271
    data->set.connecttimeout = va_arg(param, long) * 1000L;
 
1272
    break;
 
1273
 
 
1274
  case CURLOPT_CONNECTTIMEOUT_MS:
1093
1275
    data->set.connecttimeout = va_arg(param, long);
1094
1276
    break;
1095
1277
 
1286
1468
    /*
1287
1469
     * Kludgy option to enable CRLF conversions. Subject for removal.
1288
1470
     */
1289
 
    data->set.crlf = va_arg(param, long)?TRUE:FALSE;
 
1471
    data->set.crlf = (bool)(0 != va_arg(param, long));
1290
1472
    break;
1291
1473
 
1292
1474
  case CURLOPT_INTERFACE:
1313
1495
     * A string that defines the krb4 security level.
1314
1496
     */
1315
1497
    data->set.krb4_level = va_arg(param, char *);
1316
 
    data->set.krb4=data->set.krb4_level?TRUE:FALSE;
 
1498
    data->set.krb4 = (bool)(NULL != data->set.krb4_level);
1317
1499
    break;
1318
1500
  case CURLOPT_SSL_VERIFYPEER:
1319
1501
    /*
1378
1560
     * The application asks not to set any signal() or alarm() handlers,
1379
1561
     * even when using a timeout.
1380
1562
     */
1381
 
    data->set.no_signal = va_arg(param, long) ? TRUE : FALSE;
 
1563
    data->set.no_signal = (bool)(0 != va_arg(param, long));
1382
1564
    break;
1383
1565
 
1384
1566
  case CURLOPT_SHARE:
1492
1674
     * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
1493
1675
     * algorithm
1494
1676
     */
1495
 
    data->set.tcp_nodelay = (bool)va_arg(param, long);
1496
 
    break;
1497
 
 
1498
 
  /*********** 3rd party transfer options ***********/
1499
 
  case CURLOPT_SOURCE_URL:
1500
 
    /*
1501
 
     * SOURCE URL
1502
 
     */
1503
 
    data->set.source_url = va_arg(param, char *);
1504
 
    data->set.printhost = (data->set.source_url != NULL);
1505
 
    break;
1506
 
 
1507
 
  case CURLOPT_SOURCE_USERPWD:
1508
 
    /*
1509
 
     * Use SOURCE USER[:PASSWORD]
1510
 
     */
1511
 
    data->set.source_userpwd = va_arg(param, char *);
1512
 
    break;
1513
 
 
1514
 
  case CURLOPT_SOURCE_QUOTE:
1515
 
    /*
1516
 
     * List of RAW FTP commands to use after a connect
1517
 
     */
1518
 
    data->set.source_quote = va_arg(param, struct curl_slist *);
1519
 
    break;
1520
 
 
1521
 
  case CURLOPT_SOURCE_PREQUOTE:
1522
 
    /*
1523
 
     * List of RAW FTP commands to use before a transfer on the source host
1524
 
     */
1525
 
    data->set.source_prequote = va_arg(param, struct curl_slist *);
1526
 
    break;
1527
 
 
1528
 
  case CURLOPT_SOURCE_POSTQUOTE:
1529
 
    /*
1530
 
     * List of RAW FTP commands to use after a transfer on the source host
1531
 
     */
1532
 
    data->set.source_postquote = va_arg(param, struct curl_slist *);
1533
 
    break;
 
1677
    data->set.tcp_nodelay = (bool)(0 != va_arg(param, long));
 
1678
    break;
 
1679
 
 
1680
    /*
 
1681
      case CURLOPT_SOURCE_URL:
 
1682
      case CURLOPT_SOURCE_USERPWD:
 
1683
      case CURLOPT_SOURCE_QUOTE:
 
1684
      case CURLOPT_SOURCE_PREQUOTE:
 
1685
      case CURLOPT_SOURCE_POSTQUOTE:
 
1686
      These former 3rd party transfer options are deprecated */
1534
1687
 
1535
1688
  case CURLOPT_FTP_ACCOUNT:
1536
1689
    data->set.ftp_account = va_arg(param, char *);
1537
1690
    break;
1538
1691
 
1539
1692
  case CURLOPT_IGNORE_CONTENT_LENGTH:
1540
 
    data->set.ignorecl = va_arg(param, long)?TRUE:FALSE;
 
1693
    data->set.ignorecl = (bool)(0 != va_arg(param, long));
1541
1694
    break;
1542
1695
 
1543
1696
  case CURLOPT_CONNECT_ONLY:
1544
1697
    /*
1545
1698
     * No data transfer, set up connection and let application use the socket
1546
1699
     */
1547
 
    data->set.connect_only = va_arg(param, long)?TRUE:FALSE;
 
1700
    data->set.connect_only = (bool)(0 != va_arg(param, long));
1548
1701
    break;
1549
1702
 
1550
1703
  case CURLOPT_FTP_ALTERNATIVE_TO_USER:
1551
1704
    data->set.ftp_alternative_to_user = va_arg(param, char *);
1552
1705
    break;
1553
1706
 
 
1707
  case CURLOPT_SOCKOPTFUNCTION:
 
1708
    /*
 
1709
     * socket callback function: called after socket() but before connect()
 
1710
     */
 
1711
    data->set.fsockopt = va_arg(param, curl_sockopt_callback);
 
1712
    break;
 
1713
 
 
1714
  case CURLOPT_SOCKOPTDATA:
 
1715
    /*
 
1716
     * socket callback data pointer. Might be NULL.
 
1717
     */
 
1718
    data->set.sockopt_client = va_arg(param, void *);
 
1719
    break;
 
1720
 
 
1721
  case CURLOPT_SSL_SESSIONID_CACHE:
 
1722
    data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
 
1723
    break;
 
1724
 
 
1725
  case CURLOPT_SSH_AUTH_TYPES:
 
1726
    data->set.ssh_auth_types = va_arg(param, long);
 
1727
    break;
 
1728
 
 
1729
  case CURLOPT_SSH_PUBLIC_KEYFILE:
 
1730
    /*
 
1731
     * Use this file instead of the $HOME/.ssh/id_dsa.pub file
 
1732
     */
 
1733
    data->set.ssh_public_key = va_arg(param, char *);
 
1734
    break;
 
1735
 
 
1736
  case CURLOPT_SSH_PRIVATE_KEYFILE:
 
1737
    /*
 
1738
     * Use this file instead of the $HOME/.ssh/id_dsa file
 
1739
     */
 
1740
    data->set.ssh_private_key = va_arg(param, char *);
 
1741
    break;
 
1742
 
 
1743
  case CURLOPT_HTTP_TRANSFER_DECODING:
 
1744
    /*
 
1745
     * disable libcurl transfer encoding is used
 
1746
     */
 
1747
    data->set.http_te_skip = (bool)(0 == va_arg(param, long));
 
1748
    break;
 
1749
 
 
1750
  case CURLOPT_HTTP_CONTENT_DECODING:
 
1751
    /*
 
1752
     * raw data passed to the application when content encoding is used
 
1753
     */
 
1754
    data->set.http_ce_skip = (bool)(0 == va_arg(param, long));
 
1755
    break;
1554
1756
  default:
1555
1757
    /* unknown tag and its companion, just ignore: */
1556
1758
    result = CURLE_FAILED_INIT; /* correct this */
1560
1762
  return result;
1561
1763
}
1562
1764
 
 
1765
static void conn_free(struct connectdata *conn)
 
1766
{
 
1767
  if (!conn)
 
1768
    return;
 
1769
 
 
1770
  /* close possibly still open sockets */
 
1771
  if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
 
1772
    sclose(conn->sock[SECONDARYSOCKET]);
 
1773
  if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
 
1774
    sclose(conn->sock[FIRSTSOCKET]);
 
1775
 
 
1776
  Curl_safefree(conn->user);
 
1777
  Curl_safefree(conn->passwd);
 
1778
  Curl_safefree(conn->proxyuser);
 
1779
  Curl_safefree(conn->proxypasswd);
 
1780
  Curl_safefree(conn->allocptr.proxyuserpwd);
 
1781
  Curl_safefree(conn->allocptr.uagent);
 
1782
  Curl_safefree(conn->allocptr.userpwd);
 
1783
  Curl_safefree(conn->allocptr.accept_encoding);
 
1784
  Curl_safefree(conn->allocptr.rangeline);
 
1785
  Curl_safefree(conn->allocptr.ref);
 
1786
  Curl_safefree(conn->allocptr.host);
 
1787
  Curl_safefree(conn->allocptr.cookiehost);
 
1788
  Curl_safefree(conn->ip_addr_str);
 
1789
  Curl_safefree(conn->trailer);
 
1790
  Curl_safefree(conn->host.rawalloc); /* host name buffer */
 
1791
  Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
 
1792
 
 
1793
  Curl_llist_destroy(conn->send_pipe, NULL);
 
1794
  Curl_llist_destroy(conn->recv_pipe, NULL);
 
1795
 
 
1796
  /* possible left-overs from the async name resolvers */
 
1797
#if defined(USE_ARES)
 
1798
  Curl_safefree(conn->async.hostname);
 
1799
  Curl_safefree(conn->async.os_specific);
 
1800
#elif defined(CURLRES_THREADED)
 
1801
  Curl_destroy_thread_data(&conn->async);
 
1802
#endif
 
1803
 
 
1804
  Curl_ssl_close(conn);
 
1805
 
 
1806
  Curl_free_ssl_config(&conn->ssl_config);
 
1807
 
 
1808
  free(conn); /* free all the connection oriented data */
 
1809
}
 
1810
 
1563
1811
CURLcode Curl_disconnect(struct connectdata *conn)
1564
1812
{
1565
1813
  struct SessionHandle *data;
1566
1814
  if(!conn)
1567
1815
    return CURLE_OK; /* this is closed and fine already */
1568
 
 
1569
1816
  data = conn->data;
1570
1817
 
 
1818
  if(!data) {
 
1819
    DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
 
1820
    return CURLE_OK;
 
1821
  }
 
1822
 
1571
1823
#if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
1572
1824
  /* scan for DNS cache entries still marked as in use */
1573
1825
  Curl_hash_apply(data->hostcache,
1582
1834
   * get here *instead* if we fail prematurely. Thus we need to be able
1583
1835
   * to free this resource here as well.
1584
1836
   */
1585
 
  if(conn->bits.rangestringalloc) {
1586
 
    free(conn->range);
1587
 
    conn->bits.rangestringalloc = FALSE;
 
1837
  if(data->reqdata.rangestringalloc) {
 
1838
    free(data->reqdata.range);
 
1839
    data->reqdata.rangestringalloc = FALSE;
1588
1840
  }
1589
1841
 
1590
1842
  if((conn->ntlm.state != NTLMSTATE_NONE) ||
1612
1864
  if(-1 != conn->connectindex) {
1613
1865
    /* unlink ourselves! */
1614
1866
    infof(data, "Closing connection #%ld\n", conn->connectindex);
1615
 
    data->state.connects[conn->connectindex] = NULL;
 
1867
    if(data->state.connc)
 
1868
      /* only clear the table entry if we still know in which cache we
 
1869
         used to be in */
 
1870
      data->state.connc->connects[conn->connectindex] = NULL;
1616
1871
  }
1617
1872
 
1618
 
  Curl_safefree(conn->proto.generic);
1619
 
  Curl_safefree(conn->newurl);
1620
 
  Curl_safefree(conn->pathbuffer); /* the URL path buffer */
1621
 
 
1622
 
  Curl_safefree(conn->host.rawalloc); /* host name buffer */
1623
 
  Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
1624
1873
#ifdef USE_LIBIDN
1625
1874
  if(conn->host.encalloc)
1626
1875
    idn_free(conn->host.encalloc); /* encoded host name buffer, must be freed
1631
1880
                                       freed with idn_free() since this was
1632
1881
                                       allocated by libidn */
1633
1882
#endif
 
1883
 
1634
1884
  Curl_ssl_close(conn);
1635
1885
 
1636
 
  /* close possibly still open sockets */
1637
 
  if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
1638
 
    sclose(conn->sock[SECONDARYSOCKET]);
1639
 
  if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
1640
 
    sclose(conn->sock[FIRSTSOCKET]);
1641
 
 
1642
 
  Curl_safefree(conn->user);
1643
 
  Curl_safefree(conn->passwd);
1644
 
  Curl_safefree(conn->proxyuser);
1645
 
  Curl_safefree(conn->proxypasswd);
1646
 
  Curl_safefree(conn->allocptr.proxyuserpwd);
1647
 
  Curl_safefree(conn->allocptr.uagent);
1648
 
  Curl_safefree(conn->allocptr.userpwd);
1649
 
  Curl_safefree(conn->allocptr.accept_encoding);
1650
 
  Curl_safefree(conn->allocptr.rangeline);
1651
 
  Curl_safefree(conn->allocptr.ref);
1652
 
  Curl_safefree(conn->allocptr.host);
1653
 
  Curl_safefree(conn->allocptr.cookiehost);
1654
 
  Curl_safefree(conn->ip_addr_str);
1655
 
  Curl_safefree(conn->trailer);
1656
 
 
1657
 
  /* possible left-overs from the async name resolvers */
1658
 
#if defined(USE_ARES)
1659
 
  Curl_safefree(conn->async.hostname);
1660
 
  Curl_safefree(conn->async.os_specific);
1661
 
#elif defined(CURLRES_THREADED)
1662
 
  Curl_destroy_thread_data(&conn->async);
1663
 
#endif
1664
 
 
1665
 
  Curl_free_ssl_config(&conn->ssl_config);
1666
 
 
1667
 
  free(conn); /* free all the connection oriented data */
 
1886
  /* Indicate to all handles on the pipe that we're dead */
 
1887
  if (IsPipeliningEnabled(data)) {
 
1888
    signalPipeClose(conn->send_pipe);
 
1889
    signalPipeClose(conn->recv_pipe);
 
1890
  }
 
1891
 
 
1892
  conn_free(conn);
1668
1893
 
1669
1894
  return CURLE_OK;
1670
1895
}
1679
1904
  int sval;
1680
1905
  bool ret_val = TRUE;
1681
1906
 
1682
 
  sval = Curl_select(sock, CURL_SOCKET_BAD, 0);
 
1907
  sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
1683
1908
  if(sval == 0)
1684
1909
    /* timeout */
1685
1910
    ret_val = FALSE;
1687
1912
  return ret_val;
1688
1913
}
1689
1914
 
 
1915
static bool IsPipeliningPossible(struct SessionHandle *handle)
 
1916
{
 
1917
  if (handle->multi && Curl_multi_canPipeline(handle->multi) &&
 
1918
      (handle->set.httpreq == HTTPREQ_GET ||
 
1919
       handle->set.httpreq == HTTPREQ_HEAD) &&
 
1920
      handle->set.httpversion != CURL_HTTP_VERSION_1_0)
 
1921
    return TRUE;
 
1922
 
 
1923
  return FALSE;
 
1924
}
 
1925
 
 
1926
static bool IsPipeliningEnabled(struct SessionHandle *handle)
 
1927
{
 
1928
  if (handle->multi && Curl_multi_canPipeline(handle->multi))
 
1929
    return TRUE;
 
1930
 
 
1931
  return FALSE;
 
1932
}
 
1933
 
 
1934
void Curl_addHandleToPipeline(struct SessionHandle *data,
 
1935
                              struct curl_llist *pipe)
 
1936
{
 
1937
#ifdef CURLDEBUG
 
1938
  if(!IsPipeliningPossible(data)) {
 
1939
    /* when not pipelined, there MUST be no handle in the list already */
 
1940
    if(pipe->head)
 
1941
      infof(data, "PIPE when no PIPE supposed!\n");
 
1942
  }
 
1943
#endif
 
1944
  Curl_llist_insert_next(pipe, pipe->tail, data);
 
1945
}
 
1946
 
 
1947
 
 
1948
int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
 
1949
                                   struct curl_llist *pipe)
 
1950
{
 
1951
  struct curl_llist_element *curr;
 
1952
 
 
1953
  curr = pipe->head;
 
1954
  while (curr) {
 
1955
    if (curr->ptr == handle) {
 
1956
      Curl_llist_remove(pipe, curr, NULL);
 
1957
      return 1; /* we removed a handle */
 
1958
    }
 
1959
    curr = curr->next;
 
1960
  }
 
1961
 
 
1962
  return 0;
 
1963
}
 
1964
 
 
1965
#if 0 /* this code is saved here as it is useful for debugging purposes */
 
1966
static void Curl_printPipeline(struct curl_llist *pipe)
 
1967
{
 
1968
  struct curl_llist_element *curr;
 
1969
 
 
1970
  curr = pipe->head;
 
1971
  while (curr) {
 
1972
    struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
 
1973
    infof(data, "Handle in pipeline: %s\n", data->reqdata.path);
 
1974
    curr = curr->next;
 
1975
  }
 
1976
}
 
1977
#endif
 
1978
 
 
1979
bool Curl_isHandleAtHead(struct SessionHandle *handle,
 
1980
                         struct curl_llist *pipe)
 
1981
{
 
1982
  struct curl_llist_element *curr = pipe->head;
 
1983
  if (curr) {
 
1984
    return (bool)(curr->ptr == handle);
 
1985
  }
 
1986
 
 
1987
  return FALSE;
 
1988
}
 
1989
 
 
1990
static struct SessionHandle* gethandleathead(struct curl_llist *pipe)
 
1991
{
 
1992
  struct curl_llist_element *curr = pipe->head;
 
1993
  if (curr) {
 
1994
    return (struct SessionHandle *) curr->ptr;
 
1995
  }
 
1996
 
 
1997
  return NULL;
 
1998
}
 
1999
 
 
2000
static void signalPipeClose(struct curl_llist *pipe)
 
2001
{
 
2002
  struct curl_llist_element *curr;
 
2003
 
 
2004
  curr = pipe->head;
 
2005
  while (curr) {
 
2006
    struct curl_llist_element *next = curr->next;
 
2007
    struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
 
2008
 
 
2009
#ifdef CURLDEBUG /* debug-only code */
 
2010
    if(data->magic != CURLEASY_MAGIC_NUMBER) {
 
2011
      /* MAJOR BADNESS */
 
2012
      infof(data, "signalPipeClose() found BAAD easy handle\n");
 
2013
    }
 
2014
#endif
 
2015
 
 
2016
    data->state.pipe_broke = TRUE;
 
2017
    Curl_multi_handlePipeBreak(data);
 
2018
    Curl_llist_remove(pipe, curr, NULL);
 
2019
    curr = next;
 
2020
  }
 
2021
}
 
2022
 
 
2023
 
1690
2024
/*
1691
2025
 * Given one filled in connection struct (named needle), this function should
1692
 
 * detect if there already is one that have all the significant details
 
2026
 * detect if there already is one that has all the significant details
1693
2027
 * exactly the same and thus should be used instead.
 
2028
 *
 
2029
 * If there is a match, this function returns TRUE - and has marked the
 
2030
 * connection as 'in-use'. It must later be called with ConnectionDone() to
 
2031
 * return back to 'idle' (unused) state.
1694
2032
 */
1695
2033
static bool
1696
2034
ConnectionExists(struct SessionHandle *data,
1699
2037
{
1700
2038
  long i;
1701
2039
  struct connectdata *check;
 
2040
  bool canPipeline = IsPipeliningPossible(data);
1702
2041
 
1703
 
  for(i=0; i< data->state.numconnects; i++) {
 
2042
  for(i=0; i< data->state.connc->num; i++) {
1704
2043
    bool match = FALSE;
 
2044
    size_t pipeLen = 0;
1705
2045
    /*
1706
2046
     * Note that if we use a HTTP proxy, we check connections to that
1707
2047
     * proxy and not to the actual remote server.
1708
2048
     */
1709
 
    check = data->state.connects[i];
 
2049
    check = data->state.connc->connects[i];
1710
2050
    if(!check)
1711
2051
      /* NULL pointer means not filled-in entry */
1712
2052
      continue;
1713
2053
 
 
2054
    pipeLen = check->send_pipe->size + check->recv_pipe->size;
 
2055
 
 
2056
    if (check->connectindex == -1) {
 
2057
      check->connectindex = i; /* Set this appropriately since it might have
 
2058
                                  been set to -1 when the easy was removed
 
2059
                                  from the multi */
 
2060
    }
 
2061
 
 
2062
    DEBUGF(infof(data, "Examining connection #%ld for reuse"
 
2063
                 " (pipeLen = %ld)\n", check->connectindex, pipeLen));
 
2064
 
 
2065
    if(pipeLen > 0 && !canPipeline) {
 
2066
      /* can only happen within multi handles, and means that another easy
 
2067
         handle is using this connection */
 
2068
      continue;
 
2069
    }
 
2070
 
 
2071
#ifdef CURLRES_ASYNCH
 
2072
    /* ip_addr_str is NULL only if the resolving of the name hasn't completed
 
2073
       yet and until then we don't re-use this connection */
 
2074
    if (!check->ip_addr_str) {
 
2075
      infof(data,
 
2076
            "Connection #%ld hasn't finished name resolve, can't reuse\n",
 
2077
            check->connectindex);
 
2078
      continue;
 
2079
    }
 
2080
#endif
 
2081
 
 
2082
    if ((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) || check->bits.close) {
 
2083
      /* Don't pick a connection that hasn't connected yet or that is going to
 
2084
         get closed. */
 
2085
      infof(data, "Connection #%ld isn't open enough, can't reuse\n",
 
2086
            check->connectindex);
 
2087
#ifdef CURLDEBUG
 
2088
      if (check->recv_pipe->size > 0) {
 
2089
        infof(data, "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
 
2090
              check->connectindex);
 
2091
      }
 
2092
#endif
 
2093
      continue;
 
2094
    }
 
2095
 
 
2096
    if (pipeLen >= MAX_PIPELINE_LENGTH) {
 
2097
      infof(data, "Connection #%ld has its pipeline full, can't reuse\n",
 
2098
            check->connectindex);
 
2099
      continue;
 
2100
    }
 
2101
 
 
2102
    if (canPipeline) {
 
2103
      /* Make sure the pipe has only GET requests */
 
2104
      struct SessionHandle* sh = gethandleathead(check->send_pipe);
 
2105
      struct SessionHandle* rh = gethandleathead(check->recv_pipe);
 
2106
      if (sh) {
 
2107
        if(!IsPipeliningPossible(sh))
 
2108
          continue;
 
2109
      }
 
2110
      else if (rh) {
 
2111
        if(!IsPipeliningPossible(rh))
 
2112
          continue;
 
2113
      }
 
2114
    }
 
2115
 
1714
2116
    if((needle->protocol&PROT_SSL) != (check->protocol&PROT_SSL))
1715
2117
      /* don't do mixed SSL and non-SSL connections */
1716
2118
      continue;
1732
2134
             ssl options as well */
1733
2135
          if(!Curl_ssl_config_matches(&needle->ssl_config,
1734
2136
                                      &check->ssl_config)) {
 
2137
            infof(data,
 
2138
                  "Connection #%ld has different SSL parameters, "
 
2139
                  "can't reuse\n",
 
2140
                  check->connectindex );
1735
2141
            continue;
1736
2142
          }
1737
2143
        }
1738
2144
        if((needle->protocol & PROT_FTP) ||
1739
2145
           ((needle->protocol & PROT_HTTP) &&
1740
 
            (needle->data->state.authhost.want==CURLAUTH_NTLM))) {
 
2146
            (data->state.authhost.want==CURLAUTH_NTLM))) {
1741
2147
          /* This is FTP or HTTP+NTLM, verify that we're using the same name
1742
2148
             and password as well */
1743
2149
          if(!strequal(needle->user, check->user) ||
1750
2156
      }
1751
2157
    }
1752
2158
    else { /* The requested needle connection is using a proxy,
1753
 
              is the checked one using the same? */
1754
 
      if(check->bits.httpproxy &&
 
2159
              is the checked one using the same host, port and type? */
 
2160
      if(check->bits.proxy &&
 
2161
         (needle->proxytype == check->proxytype) &&
1755
2162
         strequal(needle->proxy.name, check->proxy.name) &&
1756
2163
         needle->port == check->port) {
1757
2164
        /* This is the same proxy connection, use it! */
1760
2167
    }
1761
2168
 
1762
2169
    if(match) {
1763
 
      bool dead = SocketIsDead(check->sock[FIRSTSOCKET]);
1764
 
      if(dead) {
1765
 
        /*
1766
 
         */
1767
 
        infof(data, "Connection %d seems to be dead!\n", i);
1768
 
        Curl_disconnect(check); /* disconnect resources */
1769
 
        data->state.connects[i]=NULL; /* nothing here */
1770
 
 
1771
 
        /* There's no need to continue searching, because we only store
1772
 
           one connection for each unique set of identifiers */
1773
 
        return FALSE;
 
2170
      if (!IsPipeliningEnabled(data)) {
 
2171
        /* The check for a dead socket makes sense only in the
 
2172
           non-pipelining case */
 
2173
        bool dead = SocketIsDead(check->sock[FIRSTSOCKET]);
 
2174
        if(dead) {
 
2175
          check->data = data;
 
2176
          infof(data, "Connection #%d seems to be dead!\n", i);
 
2177
 
 
2178
          Curl_disconnect(check); /* disconnect resources */
 
2179
          data->state.connc->connects[i]=NULL; /* nothing here */
 
2180
 
 
2181
          return FALSE;
 
2182
        }
 
2183
      }
 
2184
 
 
2185
      check->inuse = TRUE; /* mark this as being in use so that no other
 
2186
                              handle in a multi stack may nick it */
 
2187
      if (canPipeline) {
 
2188
        /* Mark the connection as being in a pipeline */
 
2189
        check->is_in_pipeline = TRUE;
1774
2190
      }
1775
2191
 
1776
2192
      *usethis = check;
1777
2193
      return TRUE; /* yes, we found one to use! */
1778
2194
    }
1779
2195
  }
 
2196
 
1780
2197
  return FALSE; /* no matching connecting exists */
1781
2198
}
1782
2199
 
 
2200
 
 
2201
 
1783
2202
/*
1784
2203
 * This function frees/closes a connection in the connection cache. This
1785
2204
 * should take the previously set policy into account when deciding which
1797
2216
 
1798
2217
  now = Curl_tvnow();
1799
2218
 
1800
 
  for(i=0; i< data->state.numconnects; i++) {
1801
 
    conn = data->state.connects[i];
 
2219
  for(i=0; data->state.connc && (i< data->state.connc->num); i++) {
 
2220
    conn = data->state.connc->connects[i];
1802
2221
 
1803
 
    if(!conn)
 
2222
    if(!conn || conn->inuse)
1804
2223
      continue;
1805
2224
 
1806
 
    /*
1807
 
     * By using the set policy, we score each connection.
1808
 
     */
1809
 
    switch(data->set.closepolicy) {
1810
 
    case CURLCLOSEPOLICY_LEAST_RECENTLY_USED:
1811
 
    default:
1812
 
      /*
1813
 
       * Set higher score for the age passed since the connection
1814
 
       * was used.
1815
 
       */
1816
 
      score = Curl_tvdiff(now, conn->now);
1817
 
      break;
1818
 
    case CURLCLOSEPOLICY_OLDEST:
1819
 
      /*
1820
 
       * Set higher score for the age passed since the connection
1821
 
       * was created.
1822
 
       */
1823
 
      score = Curl_tvdiff(now, conn->created);
1824
 
      break;
1825
 
    }
 
2225
    /* Set higher score for the age passed since the connection was used */
 
2226
    score = Curl_tvdiff(now, conn->now);
1826
2227
 
1827
2228
    if(score > highscore) {
1828
2229
      highscore = score;
1830
2231
    }
1831
2232
  }
1832
2233
  if(connindex >= 0) {
 
2234
    /* Set the connection's owner correctly */
 
2235
    conn = data->state.connc->connects[connindex];
 
2236
    conn->data = data;
1833
2237
 
1834
2238
    /* the winner gets the honour of being disconnected */
1835
 
    (void) Curl_disconnect(data->state.connects[connindex]);
 
2239
    (void)Curl_disconnect(conn);
1836
2240
 
1837
2241
    /* clean the array entry */
1838
 
    data->state.connects[connindex] = NULL;
 
2242
    data->state.connc->connects[connindex] = NULL;
1839
2243
  }
1840
2244
 
1841
2245
  return connindex; /* return the available index or -1 */
1842
2246
}
1843
2247
 
 
2248
/* this connection can now be marked 'idle' */
 
2249
static void
 
2250
ConnectionDone(struct connectdata *conn)
 
2251
{
 
2252
  conn->inuse = FALSE;
 
2253
  if (!conn->send_pipe && !conn->recv_pipe)
 
2254
    conn->is_in_pipeline = FALSE;
 
2255
}
 
2256
 
1844
2257
/*
1845
2258
 * The given input connection struct pointer is to be stored. If the "cache"
1846
2259
 * is already full, we must clean out the most suitable using the previously
1854
2267
                struct connectdata *conn)
1855
2268
{
1856
2269
  long i;
1857
 
  for(i=0; i< data->state.numconnects; i++) {
1858
 
    if(!data->state.connects[i])
 
2270
  for(i=0; i< data->state.connc->num; i++) {
 
2271
    if(!data->state.connc->connects[i])
1859
2272
      break;
1860
2273
  }
1861
 
  if(i == data->state.numconnects) {
 
2274
  if(i == data->state.connc->num) {
1862
2275
    /* there was no room available, kill one */
1863
2276
    i = ConnectionKillOne(data);
1864
 
    infof(data, "Connection (#%d) was killed to make room\n", i);
 
2277
    if(-1 != i)
 
2278
      infof(data, "Connection (#%d) was killed to make room (holds %d)\n",
 
2279
            i, data->state.connc->num);
 
2280
    else
 
2281
      infof(data, "This connection did not fit in the connection cache\n");
1865
2282
  }
1866
2283
 
 
2284
  conn->connectindex = i; /* Make the child know where the pointer to this
 
2285
                             particular data is stored. But note that this -1
 
2286
                             if this is not within the cache and this is
 
2287
                             probably not checked for everywhere (yet). */
 
2288
  conn->inuse = TRUE;
1867
2289
  if(-1 != i) {
1868
 
    /* only do this if a true index was returned, if -1 was returned there
 
2290
    /* Only do this if a true index was returned, if -1 was returned there
1869
2291
       is no room in the cache for an unknown reason and we cannot store
1870
 
       this there. */
1871
 
    data->state.connects[i] = conn; /* fill in this */
1872
 
    conn->connectindex = i; /* make the child know where the pointer to this
1873
 
                               particular data is stored */
 
2292
       this there.
 
2293
 
 
2294
       TODO: make sure we really can work with more handles than positions in
 
2295
       the cache, or possibly we should (allow to automatically) resize the
 
2296
       connection cache when we add more easy handles to a multi handle!
 
2297
    */
 
2298
    data->state.connc->connects[i] = conn; /* fill in this */
 
2299
    conn->data = data;
1874
2300
  }
 
2301
 
1875
2302
  return i;
1876
2303
}
1877
2304
 
1878
 
/*
1879
 
* This function logs in to a SOCKS4 proxy and sends the specifics to the final
1880
 
* destination server.
1881
 
*
1882
 
* Reference :
1883
 
*   http://socks.permeo.com/protocol/socks4.protocol
1884
 
*
1885
 
* Note :
1886
 
*   Nonsupport "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
1887
 
*   Nonsupport "Identification Protocol (RFC1413)"
1888
 
*/
1889
 
static int handleSock4Proxy(const char *proxy_name, struct connectdata *conn)
1890
 
{
1891
 
  unsigned char socksreq[262]; /* room for SOCKS4 request incl. user id */
1892
 
  int result;
1893
 
  CURLcode code;
1894
 
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
1895
 
  struct SessionHandle *data = conn->data;
1896
 
 
1897
 
  Curl_nonblock(sock, FALSE);
1898
 
 
1899
 
  /*
1900
 
  * Compose socks4 request
1901
 
  *
1902
 
  * Request format
1903
 
  *
1904
 
  *     +----+----+----+----+----+----+----+----+----+----+....+----+
1905
 
  *     | VN | CD | DSTPORT |      DSTIP        | USERID       |NULL|
1906
 
  *     +----+----+----+----+----+----+----+----+----+----+....+----+
1907
 
  * # of bytes:  1    1      2              4           variable       1
1908
 
  */
1909
 
 
1910
 
  socksreq[0] = 4; /* version (SOCKS4) */
1911
 
  socksreq[1] = 1; /* connect */
1912
 
  *((unsigned short*)&socksreq[2]) = htons(conn->remote_port);
1913
 
 
1914
 
  /* DNS resolve */
1915
 
  {
1916
 
    struct Curl_dns_entry *dns;
1917
 
    Curl_addrinfo *hp=NULL;
1918
 
    int rc;
1919
 
 
1920
 
    rc = Curl_resolv(conn, conn->host.name, (int)conn->remote_port, &dns);
1921
 
 
1922
 
    if(rc == CURLRESOLV_ERROR)
1923
 
      return 1;
1924
 
 
1925
 
    if(rc == CURLRESOLV_PENDING)
1926
 
      /* this requires that we're in "wait for resolve" state */
1927
 
      rc = Curl_wait_for_resolv(conn, &dns);
1928
 
 
1929
 
    /*
1930
 
    * We cannot use 'hostent' as a struct that Curl_resolv() returns.  It
1931
 
    * returns a Curl_addrinfo pointer that may not always look the same.
1932
 
    */
1933
 
    if(dns)
1934
 
      hp=dns->addr;
1935
 
    if (hp) {
1936
 
      char buf[64];
1937
 
      unsigned short ip[4];
1938
 
      Curl_printable_address(hp, buf, sizeof(buf));
1939
 
 
1940
 
      if(4 == sscanf( buf, "%hu.%hu.%hu.%hu",
1941
 
        &ip[0], &ip[1], &ip[2], &ip[3])) {
1942
 
          /* Set DSTIP */
1943
 
          socksreq[4] = (unsigned char)ip[0];
1944
 
          socksreq[5] = (unsigned char)ip[1];
1945
 
          socksreq[6] = (unsigned char)ip[2];
1946
 
          socksreq[7] = (unsigned char)ip[3];
1947
 
        }
1948
 
      else
1949
 
        hp = NULL; /* fail! */
1950
 
 
1951
 
      Curl_resolv_unlock(conn->data, dns); /* not used anymore from now on */
1952
 
 
1953
 
    }
1954
 
    if(!hp) {
1955
 
      failf(conn->data, "Failed to resolve \"%s\" for SOCKS4 connect.",
1956
 
        conn->host.name);
1957
 
      return 1;
1958
 
    }
1959
 
  }
1960
 
 
1961
 
  /*
1962
 
   * This is currently not supporting "Identification Protocol (RFC1413)".
1963
 
   */
1964
 
  socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
1965
 
  if (proxy_name)
1966
 
    strlcat((char*)socksreq + 8, proxy_name, sizeof(socksreq) - 8);
1967
 
 
1968
 
  /*
1969
 
   * Make connection
1970
 
   */
1971
 
  {
1972
 
    ssize_t actualread;
1973
 
    ssize_t written;
1974
 
    int packetsize = 9 +
1975
 
      (int)strlen((char*)socksreq + 8); /* size including NUL */
1976
 
 
1977
 
    /* Send request */
1978
 
    code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
1979
 
    if ((code != CURLE_OK) || (written != packetsize)) {
1980
 
      failf(conn->data, "Failed to send SOCKS4 connect request.");
1981
 
      return 1;
1982
 
    }
1983
 
 
1984
 
    packetsize = 8; /* receive data size */
1985
 
 
1986
 
    /* Receive response */
1987
 
    result = Curl_read(conn, sock, (char *)socksreq, packetsize, &actualread);
1988
 
    if ((result != CURLE_OK) || (actualread != packetsize)) {
1989
 
      failf(conn->data, "Failed to receive SOCKS4 connect request ack.");
1990
 
      return 1;
1991
 
    }
1992
 
 
1993
 
    /*
1994
 
    * Response format
1995
 
    *
1996
 
    *     +----+----+----+----+----+----+----+----+
1997
 
    *     | VN | CD | DSTPORT |      DSTIP        |
1998
 
    *     +----+----+----+----+----+----+----+----+
1999
 
    * # of bytes:  1    1      2              4
2000
 
    *
2001
 
    * VN is the version of the reply code and should be 0. CD is the result
2002
 
    * code with one of the following values:
2003
 
    *
2004
 
    * 90: request granted
2005
 
    * 91: request rejected or failed
2006
 
    * 92: request rejected because SOCKS server cannot connect to
2007
 
    *     identd on the client
2008
 
    * 93: request rejected because the client program and identd
2009
 
    *     report different user-ids
2010
 
    */
2011
 
 
2012
 
    /* wrong version ? */
2013
 
    if (socksreq[0] != 0) {
2014
 
      failf(conn->data,
2015
 
        "SOCKS4 reply has wrong version, version should be 4.");
2016
 
      return 1;
2017
 
    }
2018
 
 
2019
 
    /* Result */
2020
 
    switch(socksreq[1])
2021
 
    {
2022
 
      case 90:
2023
 
        infof(data, "SOCKS4 request granted.\n");
2024
 
        break;
2025
 
      case 91:
2026
 
        failf(conn->data,
2027
 
          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
2028
 
          ", request rejected or failed.",
2029
 
          (unsigned char)socksreq[4], (unsigned char)socksreq[5],
2030
 
          (unsigned char)socksreq[6], (unsigned char)socksreq[7],
2031
 
          (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
2032
 
          socksreq[1]);
2033
 
        return 1;
2034
 
      case 92:
2035
 
        failf(conn->data,
2036
 
          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
2037
 
          ", request rejected because SOCKS server cannot connect to "
2038
 
          "identd on the client.",
2039
 
          (unsigned char)socksreq[4], (unsigned char)socksreq[5],
2040
 
          (unsigned char)socksreq[6], (unsigned char)socksreq[7],
2041
 
          (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
2042
 
          socksreq[1]);
2043
 
        return 1;
2044
 
      case 93:
2045
 
        failf(conn->data,
2046
 
          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
2047
 
          ", request rejected because the client program and identd "
2048
 
          "report different user-ids.",
2049
 
          (unsigned char)socksreq[4], (unsigned char)socksreq[5],
2050
 
          (unsigned char)socksreq[6], (unsigned char)socksreq[7],
2051
 
          (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
2052
 
          socksreq[1]);
2053
 
        return 1;
2054
 
      default :
2055
 
        failf(conn->data,
2056
 
          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
2057
 
          ", Unknown.",
2058
 
          (unsigned char)socksreq[4], (unsigned char)socksreq[5],
2059
 
          (unsigned char)socksreq[6], (unsigned char)socksreq[7],
2060
 
          (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
2061
 
          socksreq[1]);
2062
 
        return 1;
2063
 
    }
2064
 
  }
2065
 
 
2066
 
  Curl_nonblock(sock, TRUE);
2067
 
 
2068
 
  return 0; /* Proxy was successful! */
2069
 
}
2070
 
 
2071
 
/*
2072
 
 * This function logs in to a SOCKS5 proxy and sends the specifics to the final
2073
 
 * destination server.
2074
 
 */
2075
 
static int handleSock5Proxy(const char *proxy_name,
2076
 
                            const char *proxy_password,
2077
 
                            struct connectdata *conn)
2078
 
{
2079
 
  /*
2080
 
    According to the RFC1928, section "6.  Replies". This is what a SOCK5
2081
 
    replies:
2082
 
 
2083
 
        +----+-----+-------+------+----------+----------+
2084
 
        |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
2085
 
        +----+-----+-------+------+----------+----------+
2086
 
        | 1  |  1  | X'00' |  1   | Variable |    2     |
2087
 
        +----+-----+-------+------+----------+----------+
2088
 
 
2089
 
    Where:
2090
 
 
2091
 
    o  VER    protocol version: X'05'
2092
 
    o  REP    Reply field:
2093
 
    o  X'00' succeeded
2094
 
  */
2095
 
 
2096
 
  unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
2097
 
  ssize_t actualread;
2098
 
  ssize_t written;
2099
 
  int result;
2100
 
  CURLcode code;
2101
 
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
2102
 
 
2103
 
  Curl_nonblock(sock, FALSE);
2104
 
 
2105
 
  socksreq[0] = 5; /* version */
2106
 
  socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
2107
 
  socksreq[2] = 0; /* no authentication */
2108
 
  socksreq[3] = 2; /* username/password */
2109
 
 
2110
 
  code = Curl_write(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
2111
 
                      &written);
2112
 
  if ((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) {
2113
 
    failf(conn->data, "Unable to send initial SOCKS5 request.");
2114
 
    return 1;
2115
 
  }
2116
 
 
2117
 
  result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread);
2118
 
  if ((result != CURLE_OK) || (actualread != 2)) {
2119
 
    failf(conn->data, "Unable to receive initial SOCKS5 response.");
2120
 
    return 1;
2121
 
  }
2122
 
 
2123
 
  if (socksreq[0] != 5) {
2124
 
    failf(conn->data, "Received invalid version in initial SOCKS5 response.");
2125
 
    return 1;
2126
 
  }
2127
 
  if (socksreq[1] == 0) {
2128
 
    /* Nothing to do, no authentication needed */
2129
 
    ;
2130
 
  }
2131
 
  else if (socksreq[1] == 2) {
2132
 
    /* Needs user name and password */
2133
 
    int userlen, pwlen, len;
2134
 
 
2135
 
    userlen = (int)strlen(proxy_name);
2136
 
    pwlen = proxy_password?(int)strlen(proxy_password):0;
2137
 
 
2138
 
    /*   username/password request looks like
2139
 
     * +----+------+----------+------+----------+
2140
 
     * |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
2141
 
     * +----+------+----------+------+----------+
2142
 
     * | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
2143
 
     * +----+------+----------+------+----------+
2144
 
     */
2145
 
    len = 0;
2146
 
    socksreq[len++] = 1;    /* username/pw subnegotiation version */
2147
 
    socksreq[len++] = (char) userlen;
2148
 
    memcpy(socksreq + len, proxy_name, (int) userlen);
2149
 
    len += userlen;
2150
 
    socksreq[len++] = (char) pwlen;
2151
 
    memcpy(socksreq + len, proxy_password, (int) pwlen);
2152
 
    len += pwlen;
2153
 
 
2154
 
    code = Curl_write(conn, sock, (char *)socksreq, len, &written);
2155
 
    if ((code != CURLE_OK) || (len != written)) {
2156
 
      failf(conn->data, "Failed to send SOCKS5 sub-negotiation request.");
2157
 
      return 1;
2158
 
    }
2159
 
 
2160
 
    result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread);
2161
 
    if ((result != CURLE_OK) || (actualread != 2)) {
2162
 
      failf(conn->data, "Unable to receive SOCKS5 sub-negotiation response.");
2163
 
      return 1;
2164
 
    }
2165
 
 
2166
 
    /* ignore the first (VER) byte */
2167
 
    if (socksreq[1] != 0) { /* status */
2168
 
      failf(conn->data, "User was rejected by the SOCKS5 server (%d %d).",
2169
 
            socksreq[0], socksreq[1]);
2170
 
      return 1;
2171
 
    }
2172
 
 
2173
 
    /* Everything is good so far, user was authenticated! */
2174
 
  }
2175
 
  else {
2176
 
    /* error */
2177
 
    if (socksreq[1] == 1) {
2178
 
      failf(conn->data,
2179
 
            "SOCKS5 GSSAPI per-message authentication is not supported.");
2180
 
      return 1;
2181
 
    }
2182
 
    else if (socksreq[1] == 255) {
2183
 
      if (!proxy_name || !*proxy_name) {
2184
 
        failf(conn->data,
2185
 
              "No authentication method was acceptable. (It is quite likely"
2186
 
              " that the SOCKS5 server wanted a username/password, since none"
2187
 
              " was supplied to the server on this connection.)");
2188
 
      }
2189
 
      else {
2190
 
        failf(conn->data, "No authentication method was acceptable.");
2191
 
      }
2192
 
      return 1;
2193
 
    }
2194
 
    else {
2195
 
      failf(conn->data,
2196
 
            "Undocumented SOCKS5 mode attempted to be used by server.");
2197
 
      return 1;
2198
 
    }
2199
 
  }
2200
 
 
2201
 
  /* Authentication is complete, now specify destination to the proxy */
2202
 
  socksreq[0] = 5; /* version (SOCKS5) */
2203
 
  socksreq[1] = 1; /* connect */
2204
 
  socksreq[2] = 0; /* must be zero */
2205
 
  socksreq[3] = 1; /* IPv4 = 1 */
2206
 
 
2207
 
  {
2208
 
    struct Curl_dns_entry *dns;
2209
 
    Curl_addrinfo *hp=NULL;
2210
 
    int rc = Curl_resolv(conn, conn->host.name, (int)conn->remote_port, &dns);
2211
 
 
2212
 
    if(rc == CURLRESOLV_ERROR)
2213
 
      return 1;
2214
 
 
2215
 
    if(rc == CURLRESOLV_PENDING)
2216
 
      /* this requires that we're in "wait for resolve" state */
2217
 
      rc = Curl_wait_for_resolv(conn, &dns);
2218
 
 
2219
 
    /*
2220
 
     * We cannot use 'hostent' as a struct that Curl_resolv() returns.  It
2221
 
     * returns a Curl_addrinfo pointer that may not always look the same.
2222
 
     */
2223
 
    if(dns)
2224
 
      hp=dns->addr;
2225
 
    if (hp) {
2226
 
      char buf[64];
2227
 
      unsigned short ip[4];
2228
 
      Curl_printable_address(hp, buf, sizeof(buf));
2229
 
 
2230
 
      if(4 == sscanf( buf, "%hu.%hu.%hu.%hu",
2231
 
                      &ip[0], &ip[1], &ip[2], &ip[3])) {
2232
 
        socksreq[4] = (unsigned char)ip[0];
2233
 
        socksreq[5] = (unsigned char)ip[1];
2234
 
        socksreq[6] = (unsigned char)ip[2];
2235
 
        socksreq[7] = (unsigned char)ip[3];
2236
 
      }
2237
 
      else
2238
 
        hp = NULL; /* fail! */
2239
 
 
2240
 
      Curl_resolv_unlock(conn->data, dns); /* not used anymore from now on */
2241
 
    }
2242
 
    if(!hp) {
2243
 
      failf(conn->data, "Failed to resolve \"%s\" for SOCKS5 connect.",
2244
 
            conn->host.name);
2245
 
      return 1;
2246
 
    }
2247
 
  }
2248
 
 
2249
 
  *((unsigned short*)&socksreq[8]) = htons(conn->remote_port);
2250
 
 
2251
 
  {
2252
 
    const int packetsize = 10;
2253
 
 
2254
 
    code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
2255
 
    if ((code != CURLE_OK) || (written != packetsize)) {
2256
 
      failf(conn->data, "Failed to send SOCKS5 connect request.");
2257
 
      return 1;
2258
 
    }
2259
 
 
2260
 
    result = Curl_read(conn, sock, (char *)socksreq, packetsize, &actualread);
2261
 
    if ((result != CURLE_OK) || (actualread != packetsize)) {
2262
 
      failf(conn->data, "Failed to receive SOCKS5 connect request ack.");
2263
 
      return 1;
2264
 
    }
2265
 
 
2266
 
    if (socksreq[0] != 5) { /* version */
2267
 
      failf(conn->data,
2268
 
            "SOCKS5 reply has wrong version, version should be 5.");
2269
 
      return 1;
2270
 
    }
2271
 
    if (socksreq[1] != 0) { /* Anything besides 0 is an error */
2272
 
        failf(conn->data,
2273
 
              "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
2274
 
              (unsigned char)socksreq[4], (unsigned char)socksreq[5],
2275
 
              (unsigned char)socksreq[6], (unsigned char)socksreq[7],
2276
 
              (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
2277
 
              socksreq[1]);
2278
 
        return 1;
2279
 
    }
2280
 
  }
2281
 
 
2282
 
  Curl_nonblock(sock, TRUE);
2283
 
  return 0; /* Proxy was successful! */
2284
 
}
2285
 
 
2286
 
static CURLcode ConnectPlease(struct connectdata *conn,
 
2305
static CURLcode ConnectPlease(struct SessionHandle *data,
 
2306
                              struct connectdata *conn,
2287
2307
                              struct Curl_dns_entry *hostaddr,
2288
2308
                              bool *connected)
2289
2309
{
2290
2310
  CURLcode result;
2291
2311
  Curl_addrinfo *addr;
2292
 
  struct SessionHandle *data = conn->data;
2293
 
  char *hostname = data->change.proxy?conn->proxy.name:conn->host.name;
 
2312
#ifndef CURL_DISABLE_VERBOSE_STRINGS
 
2313
  char *hostname = conn->bits.proxy?conn->proxy.name:conn->host.name;
2294
2314
 
2295
 
  infof(data, "About to connect() to %s%s port %d\n",
2296
 
        data->change.proxy?"proxy ":"",
2297
 
        hostname, conn->port);
 
2315
  infof(data, "About to connect() to %s%s port %d (#%d)\n",
 
2316
        conn->bits.proxy?"proxy ":"",
 
2317
        hostname, conn->port, conn->connectindex);
 
2318
#endif
2298
2319
 
2299
2320
  /*************************************************************
2300
2321
   * Connect to server/proxy
2311
2332
 
2312
2333
    Curl_store_ip_addr(conn);
2313
2334
 
2314
 
    switch(conn->data->set.proxytype) {
 
2335
    switch(data->set.proxytype) {
2315
2336
    case CURLPROXY_SOCKS5:
2316
 
      return handleSock5Proxy(conn->proxyuser,
2317
 
                              conn->proxypasswd,
2318
 
                              conn) ?
2319
 
        CURLE_COULDNT_CONNECT : CURLE_OK;
 
2337
      result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, conn->host.name,
 
2338
                           conn->remote_port, FIRSTSOCKET, conn);
 
2339
      break;
2320
2340
    case CURLPROXY_HTTP:
2321
2341
      /* do nothing here. handled later. */
2322
2342
      break;
2323
2343
    case CURLPROXY_SOCKS4:
2324
 
      return handleSock4Proxy(conn->proxyuser, conn) ?
2325
 
        CURLE_COULDNT_CONNECT : CURLE_OK;
 
2344
      result = Curl_SOCKS4(conn->proxyuser, conn->host.name, conn->remote_port,
 
2345
                           FIRSTSOCKET, conn);
 
2346
      break;
2326
2347
    default:
2327
 
      failf(conn->data, "unknown proxytype option given");
2328
 
      return CURLE_COULDNT_CONNECT;
 
2348
      failf(data, "unknown proxytype option given");
 
2349
      result = CURLE_COULDNT_CONNECT;
 
2350
      break;
2329
2351
    }
2330
2352
  }
2331
2353
 
2335
2357
/*
2336
2358
 * verboseconnect() displays verbose information after a connect
2337
2359
 */
 
2360
#ifndef CURL_DISABLE_VERBOSE_STRINGS
2338
2361
static void verboseconnect(struct connectdata *conn)
2339
2362
{
2340
 
  infof(conn->data, "Connected to %s (%s) port %d\n",
2341
 
        conn->bits.httpproxy ? conn->proxy.dispname : conn->host.dispname,
2342
 
        conn->ip_addr_str, conn->port);
 
2363
  infof(conn->data, "Connected to %s (%s) port %d (#%d)\n",
 
2364
        conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
 
2365
        conn->ip_addr_str, conn->port, conn->connectindex);
2343
2366
}
 
2367
#endif
2344
2368
 
2345
2369
int Curl_protocol_getsock(struct connectdata *conn,
2346
2370
                          curl_socket_t *socks,
2366
2390
 * protocol layer.
2367
2391
 */
2368
2392
 
2369
 
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done)
 
2393
CURLcode Curl_protocol_connecting(struct connectdata *conn,
 
2394
                                  bool *done)
2370
2395
{
2371
2396
  CURLcode result=CURLE_OK;
2372
2397
 
2404
2429
 * proceed with some action.
2405
2430
 *
2406
2431
 */
2407
 
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *protocol_done)
 
2432
CURLcode Curl_protocol_connect(struct connectdata *conn,
 
2433
                               bool *protocol_done)
2408
2434
{
 
2435
  CURLcode result=CURLE_OK;
2409
2436
  struct SessionHandle *data = conn->data;
2410
 
  CURLcode result=CURLE_OK;
2411
2437
 
2412
2438
  *protocol_done = FALSE;
2413
2439
 
2448
2474
 
2449
2475
    /* it has started, possibly even completed but that knowledge isn't stored
2450
2476
       in this bit! */
2451
 
    conn->bits.protoconnstart = TRUE;
 
2477
    if (!result)
 
2478
      conn->bits.protoconnstart = TRUE;
2452
2479
  }
2453
2480
 
2454
2481
  return result; /* pass back status */
2478
2505
  size_t err_pos;
2479
2506
  char *uc_name = NULL;
2480
2507
  int rc;
 
2508
#ifndef CURL_DISABLE_VERBOSE_STRINGS
 
2509
  char *tld_errmsg = (char *)"<no msg>";
 
2510
#else
 
2511
  (void)data;
 
2512
#endif
2481
2513
 
2482
2514
  /* Convert (and downcase) ACE-name back into locale's character set */
2483
2515
  rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
2485
2517
    return (FALSE);
2486
2518
 
2487
2519
  rc = tld_check_lz(uc_name, &err_pos, NULL);
 
2520
#ifndef CURL_DISABLE_VERBOSE_STRINGS
 
2521
#ifdef HAVE_TLD_STRERROR
 
2522
  if (rc != TLD_SUCCESS)
 
2523
    tld_errmsg = (char *)tld_strerror((Tld_rc)rc);
 
2524
#endif
2488
2525
  if (rc == TLD_INVALID)
2489
 
     infof(data, "WARNING: %s; pos %u = `%c'/0x%02X\n",
2490
 
#ifdef HAVE_TLD_STRERROR
2491
 
           tld_strerror((Tld_rc)rc),
2492
 
#else
2493
 
           "<no msg>",
2494
 
#endif
2495
 
           err_pos, uc_name[err_pos],
2496
 
           uc_name[err_pos] & 255);
 
2526
    infof(data, "WARNING: %s; pos %u = `%c'/0x%02X\n",
 
2527
          tld_errmsg, err_pos, uc_name[err_pos],
 
2528
          uc_name[err_pos] & 255);
2497
2529
  else if (rc != TLD_SUCCESS)
2498
 
       infof(data, "WARNING: TLD check for %s failed; %s\n",
2499
 
             uc_name,
2500
 
#ifdef HAVE_TLD_STRERROR
2501
 
             tld_strerror((Tld_rc)rc)
2502
 
#else
2503
 
             "<no msg>"
2504
 
#endif
2505
 
         );
 
2530
    infof(data, "WARNING: TLD check for %s failed; %s\n",
 
2531
          uc_name, tld_errmsg);
 
2532
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
2506
2533
  if (uc_name)
2507
2534
     idn_free(uc_name);
2508
 
  return (rc == TLD_SUCCESS);
 
2535
  return (bool)(rc == TLD_SUCCESS);
2509
2536
}
2510
2537
#endif
2511
2538
 
2512
 
static void fix_hostname(struct connectdata *conn, struct hostname *host)
 
2539
static void fix_hostname(struct SessionHandle *data,
 
2540
                         struct connectdata *conn, struct hostname *host)
2513
2541
{
 
2542
#ifndef USE_LIBIDN
 
2543
  (void)data;
 
2544
  (void)conn;
 
2545
#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
 
2546
  (void)conn;
 
2547
#endif
 
2548
 
2514
2549
  /* set the name we use to display the host name */
2515
2550
  host->dispname = host->name;
2516
2551
 
2521
2556
  if (!is_ASCII_name(host->name) &&
2522
2557
      stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
2523
2558
    char *ace_hostname = NULL;
2524
 
    struct SessionHandle *data = conn->data;
2525
2559
    int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
2526
2560
    infof (data, "Input domain encoded as `%s'\n",
2527
2561
           stringprep_locale_charset ());
2538
2572
      host->name = host->encalloc;
2539
2573
    }
2540
2574
  }
2541
 
#else
2542
 
  (void)conn; /* never used */
2543
2575
#endif
2544
2576
}
2545
2577
 
2546
 
 
2547
 
/**
2548
 
 * CreateConnection() sets up a new connectdata struct, or re-uses an already
2549
 
 * existing one, and resolves host name.
2550
 
 *
2551
 
 * if this function returns CURLE_OK and *async is set to TRUE, the resolve
2552
 
 * response will be coming asynchronously. If *async is FALSE, the name is
2553
 
 * already resolved.
2554
 
 *
2555
 
 * @param data The sessionhandle pointer
2556
 
 * @param in_connect is set to the next connection data pointer
2557
 
 * @param addr is set to the new dns entry for this connection. If this
2558
 
 *        connection is re-used it will be NULL.
2559
 
 * @param async is set TRUE/FALSE depending on the nature of this lookup
2560
 
 * @return CURLcode
2561
 
 * @see SetupConnection()
 
2578
/*
 
2579
 * Parse URL and fill in the relevant members of the connection struct.
2562
2580
 */
2563
 
 
2564
 
static CURLcode CreateConnection(struct SessionHandle *data,
2565
 
                                 struct connectdata **in_connect,
2566
 
                                 struct Curl_dns_entry **addr,
2567
 
                                 bool *async)
 
2581
static CURLcode ParseURLAndFillConnection(struct SessionHandle *data,
 
2582
                                          struct connectdata *conn)
2568
2583
{
2569
 
  char *tmp;
2570
2584
  char *at;
2571
 
  CURLcode result=CURLE_OK;
2572
 
  struct connectdata *conn;
2573
 
  struct connectdata *conn_temp = NULL;
2574
 
  size_t urllen;
2575
 
  struct Curl_dns_entry *hostaddr;
2576
 
#if defined(HAVE_ALARM) && !defined(USE_ARES)
2577
 
  unsigned int prev_alarm=0;
2578
 
#endif
2579
 
  char endbracket;
2580
 
  char user[MAX_CURL_USER_LENGTH];
2581
 
  char passwd[MAX_CURL_PASSWORD_LENGTH];
2582
 
  int rc;
2583
 
  bool reuse;
2584
 
 
2585
 
#ifndef USE_ARES
2586
 
#ifdef SIGALRM
2587
 
#ifdef HAVE_SIGACTION
2588
 
  struct sigaction keep_sigact;   /* store the old struct here */
2589
 
  bool keep_copysig=FALSE;        /* did copy it? */
2590
 
#else
2591
 
#ifdef HAVE_SIGNAL
2592
 
  void *keep_sigact;              /* store the old handler here */
2593
 
#endif /* HAVE_SIGNAL */
2594
 
#endif /* HAVE_SIGACTION */
2595
 
#endif /* SIGALRM */
2596
 
#endif /* USE_ARES */
2597
 
 
2598
 
  *addr = NULL; /* nothing yet */
2599
 
  *async = FALSE;
2600
 
 
2601
 
  /*************************************************************
2602
 
   * Check input data
2603
 
   *************************************************************/
2604
 
 
2605
 
  if(!data->change.url)
2606
 
    return CURLE_URL_MALFORMAT;
2607
 
 
2608
 
  /* First, split up the current URL in parts so that we can use the
2609
 
     parts for checking against the already present connections. In order
2610
 
     to not have to modify everything at once, we allocate a temporary
2611
 
     connection data struct and fill in for comparison purposes. */
2612
 
 
2613
 
  conn = (struct connectdata *)calloc(sizeof(struct connectdata), 1);
2614
 
  if(!conn) {
2615
 
    *in_connect = NULL; /* clear the pointer */
2616
 
    return CURLE_OUT_OF_MEMORY;
2617
 
  }
2618
 
  /* We must set the return variable as soon as possible, so that our
2619
 
     parent can cleanup any possible allocs we may have done before
2620
 
     any failure */
2621
 
  *in_connect = conn;
2622
 
 
2623
 
  /* and we setup a few fields in case we end up actually using this struct */
2624
 
  conn->data = data;           /* remember our daddy */
2625
 
  conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
2626
 
  conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
2627
 
  conn->connectindex = -1;    /* no index */
2628
 
  conn->bits.httpproxy = (data->change.proxy && *data->change.proxy &&
2629
 
                          (data->set.proxytype == CURLPROXY_HTTP))?
2630
 
    TRUE:FALSE; /* http proxy or not */
2631
 
 
2632
 
  /* Default protocol-independent behavior doesn't support persistent
2633
 
     connections, so we set this to force-close. Protocols that support
2634
 
     this need to set this to FALSE in their "curl_do" functions. */
2635
 
  conn->bits.close = TRUE;
2636
 
 
2637
 
  /* maxdownload must be -1 on init, as 0 is a valid value! */
2638
 
  conn->maxdownload = -1;  /* might have been used previously! */
2639
 
 
2640
 
  /* Store creation time to help future close decision making */
2641
 
  conn->created = Curl_tvnow();
2642
 
 
2643
 
  conn->bits.use_range = data->set.set_range?TRUE:FALSE; /* range status */
2644
 
  conn->range = data->set.set_range;              /* clone the range setting */
2645
 
  conn->resume_from = data->set.set_resume_from;   /* inherit resume_from */
2646
 
 
2647
 
  conn->bits.user_passwd = data->set.userpwd?1:0;
2648
 
  conn->bits.proxy_user_passwd = data->set.proxyuserpwd?1:0;
2649
 
  conn->bits.no_body = data->set.opt_no_body;
2650
 
  conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
2651
 
  conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
2652
 
  conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
2653
 
 
2654
 
  /* This initing continues below, see the comment "Continue connectdata
2655
 
   * initialization here" */
2656
 
 
2657
 
  /***********************************************************
2658
 
   * We need to allocate memory to store the path in. We get the size of the
2659
 
   * full URL to be sure, and we need to make it at least 256 bytes since
2660
 
   * other parts of the code will rely on this fact
2661
 
   ***********************************************************/
2662
 
#define LEAST_PATH_ALLOC 256
2663
 
  urllen=strlen(data->change.url);
2664
 
  if(urllen < LEAST_PATH_ALLOC)
2665
 
    urllen=LEAST_PATH_ALLOC;
2666
 
 
2667
 
  /*
2668
 
   * We malloc() the buffers below urllen+2 to make room for to possibilities:
2669
 
   * 1 - an extra terminating zero
2670
 
   * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
2671
 
   */
2672
 
 
2673
 
  conn->pathbuffer=(char *)malloc(urllen+2);
2674
 
  if(NULL == conn->pathbuffer)
2675
 
    return CURLE_OUT_OF_MEMORY; /* really bad error */
2676
 
  conn->path = conn->pathbuffer;
2677
 
 
2678
 
  conn->host.rawalloc=(char *)malloc(urllen+2);
2679
 
  if(NULL == conn->host.rawalloc)
2680
 
    return CURLE_OUT_OF_MEMORY;
2681
 
  conn->host.name = conn->host.rawalloc;
2682
 
  conn->host.name[0] = 0;
 
2585
  char *tmp;
 
2586
 
 
2587
  char *path = data->reqdata.path;
2683
2588
 
2684
2589
  /*************************************************************
2685
2590
   * Parse the URL.
2691
2596
   ************************************************************/
2692
2597
  if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
2693
2598
                  conn->protostr,
2694
 
                  conn->path)) && strequal(conn->protostr, "file")) {
2695
 
    if(conn->path[0] == '/' && conn->path[1] == '/') {
 
2599
                  path)) && strequal(conn->protostr, "file")) {
 
2600
    if(path[0] == '/' && path[1] == '/') {
2696
2601
      /* Allow omitted hostname (e.g. file:/<path>).  This is not strictly
2697
2602
       * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
2698
2603
       * file://localhost/<path> is similar to how other schemes treat missing
2700
2605
 
2701
2606
      /* This cannot be done with strcpy() in a portable manner, since the
2702
2607
         memory areas overlap! */
2703
 
      memmove(conn->path, conn->path + 2, strlen(conn->path + 2)+1);
 
2608
      memmove(path, path + 2, strlen(path + 2)+1);
2704
2609
    }
2705
2610
    /*
2706
2611
     * we deal with file://<host>/<path> differently since it supports no
2707
2612
     * hostname other than "localhost" and "127.0.0.1", which is unique among
2708
2613
     * the URL protocols specified in RFC 1738
2709
2614
     */
2710
 
    if(conn->path[0] != '/') {
 
2615
    if(path[0] != '/') {
2711
2616
      /* the URL included a host name, we ignore host names in file:// URLs
2712
2617
         as the standards don't define what to do with them */
2713
 
      char *ptr=strchr(conn->path, '/');
 
2618
      char *ptr=strchr(path, '/');
2714
2619
      if(ptr) {
2715
2620
        /* there was a slash present
2716
2621
 
2733
2638
          ptr++;
2734
2639
 
2735
2640
        /* This cannot be made with strcpy, as the memory chunks overlap! */
2736
 
        memmove(conn->path, ptr, strlen(ptr)+1);
 
2641
        memmove(path, ptr, strlen(ptr)+1);
2737
2642
      }
2738
2643
    }
2739
2644
 
2741
2646
  }
2742
2647
  else {
2743
2648
    /* clear path */
2744
 
    conn->path[0]=0;
 
2649
    path[0]=0;
2745
2650
 
2746
2651
    if (2 > sscanf(data->change.url,
2747
2652
                   "%15[^\n:]://%[^\n/]%[^\n]",
2748
2653
                   conn->protostr,
2749
 
                   conn->host.name, conn->path)) {
 
2654
                   conn->host.name, path)) {
2750
2655
 
2751
2656
      /*
2752
2657
       * The URL was badly formatted, let's try the browser-style _without_
2753
2658
       * protocol specified like 'http://'.
2754
2659
       */
2755
2660
      if((1 > sscanf(data->change.url, "%[^\n/]%[^\n]",
2756
 
                     conn->host.name, conn->path)) ) {
 
2661
                     conn->host.name, path)) ) {
2757
2662
        /*
2758
2663
         * We couldn't even get this format.
2759
2664
         */
2771
2676
 
2772
2677
      if(checkprefix("FTP.", conn->host.name))
2773
2678
        strcpy(conn->protostr, "ftp");
2774
 
#ifdef USE_SSL
2775
 
      else if(checkprefix("FTPS", conn->host.name))
2776
 
        strcpy(conn->protostr, "ftps");
2777
 
#endif /* USE_SSL */
2778
 
      else if(checkprefix("TELNET.", conn->host.name))
2779
 
        strcpy(conn->protostr, "telnet");
2780
2679
      else if (checkprefix("DICT.", conn->host.name))
2781
2680
        strcpy(conn->protostr, "DICT");
2782
2681
      else if (checkprefix("LDAP.", conn->host.name))
2809
2708
    */
2810
2709
 
2811
2710
    size_t hostlen = strlen(tmp);
2812
 
    size_t pathlen = strlen(conn->path);
 
2711
    size_t pathlen = strlen(path);
2813
2712
 
2814
2713
    /* move the existing path plus the zero byte forward, to make room for
2815
2714
       the host-name part */
2816
 
    memmove(conn->path+hostlen+1, conn->path, pathlen+1);
 
2715
    memmove(path+hostlen+1, path, pathlen+1);
2817
2716
 
2818
2717
     /* now copy the trailing host part in front of the existing path */
2819
 
    memcpy(conn->path+1, tmp, hostlen);
 
2718
    memcpy(path+1, tmp, hostlen);
2820
2719
 
2821
 
    conn->path[0]='/'; /* prepend the missing slash */
 
2720
    path[0]='/'; /* prepend the missing slash */
2822
2721
 
2823
2722
    *tmp=0; /* now cut off the hostname at the ? */
2824
2723
  }
2825
 
  else if(!conn->path[0]) {
 
2724
  else if(!path[0]) {
2826
2725
    /* if there's no path set, use a single slash */
2827
 
    strcpy(conn->path, "/");
 
2726
    strcpy(path, "/");
2828
2727
  }
2829
2728
 
2830
2729
  /* If the URL is malformatted (missing a '/' after hostname before path) we
2831
2730
   * insert a slash here. The only letter except '/' we accept to start a path
2832
2731
   * is '?'.
2833
2732
   */
2834
 
  if(conn->path[0] == '?') {
 
2733
  if(path[0] == '?') {
2835
2734
    /* We need this function to deal with overlapping memory areas. We know
2836
2735
       that the memory area 'path' points to is 'urllen' bytes big and that
2837
2736
       is bigger than the path. Use +1 to move the zero byte too. */
2838
 
    memmove(&conn->path[1], conn->path, strlen(conn->path)+1);
2839
 
    conn->path[0] = '/';
 
2737
    memmove(&path[1], path, strlen(path)+1);
 
2738
    path[0] = '/';
2840
2739
  }
2841
2740
 
2842
2741
  /*
2843
2742
   * So if the URL was A://B/C,
2844
2743
   *   conn->protostr is A
2845
2744
   *   conn->host.name is B
2846
 
   *   conn->path is /C
2847
 
   */
 
2745
   *   data->reqdata.path is /C
 
2746
   */
 
2747
 
 
2748
  return CURLE_OK;
 
2749
}
 
2750
 
 
2751
static void llist_dtor(void *user, void *element)
 
2752
{
 
2753
  (void)user;
 
2754
  (void)element;
 
2755
  /* Do nothing */
 
2756
}
 
2757
 
 
2758
 
 
2759
/**
 
2760
 * CreateConnection() sets up a new connectdata struct, or re-uses an already
 
2761
 * existing one, and resolves host name.
 
2762
 *
 
2763
 * if this function returns CURLE_OK and *async is set to TRUE, the resolve
 
2764
 * response will be coming asynchronously. If *async is FALSE, the name is
 
2765
 * already resolved.
 
2766
 *
 
2767
 * @param data The sessionhandle pointer
 
2768
 * @param in_connect is set to the next connection data pointer
 
2769
 * @param addr is set to the new dns entry for this connection. If this
 
2770
 *        connection is re-used it will be NULL.
 
2771
 * @param async is set TRUE/FALSE depending on the nature of this lookup
 
2772
 * @return CURLcode
 
2773
 * @see SetupConnection()
 
2774
 *
 
2775
 * *NOTE* this function assigns the conn->data pointer!
 
2776
 */
 
2777
 
 
2778
static CURLcode CreateConnection(struct SessionHandle *data,
 
2779
                                 struct connectdata **in_connect,
 
2780
                                 struct Curl_dns_entry **addr,
 
2781
                                 bool *async)
 
2782
{
 
2783
 
 
2784
  char *tmp;
 
2785
  CURLcode result=CURLE_OK;
 
2786
  struct connectdata *conn;
 
2787
  struct connectdata *conn_temp = NULL;
 
2788
  size_t urllen;
 
2789
  struct Curl_dns_entry *hostaddr;
 
2790
#if defined(HAVE_ALARM) && !defined(USE_ARES)
 
2791
  unsigned int prev_alarm=0;
 
2792
#endif
 
2793
  char endbracket;
 
2794
  char user[MAX_CURL_USER_LENGTH];
 
2795
  char passwd[MAX_CURL_PASSWORD_LENGTH];
 
2796
  int rc;
 
2797
  bool reuse;
 
2798
  char *proxy = NULL;
 
2799
 
 
2800
#ifndef USE_ARES
 
2801
#ifdef SIGALRM
 
2802
#ifdef HAVE_SIGACTION
 
2803
  struct sigaction keep_sigact;   /* store the old struct here */
 
2804
  bool keep_copysig=FALSE;        /* did copy it? */
 
2805
#else
 
2806
#ifdef HAVE_SIGNAL
 
2807
  void (*keep_sigact)(int);       /* store the old handler here */
 
2808
#endif /* HAVE_SIGNAL */
 
2809
#endif /* HAVE_SIGACTION */
 
2810
#endif /* SIGALRM */
 
2811
#endif /* USE_ARES */
 
2812
 
 
2813
  *addr = NULL; /* nothing yet */
 
2814
  *async = FALSE;
 
2815
 
 
2816
  /*************************************************************
 
2817
   * Check input data
 
2818
   *************************************************************/
 
2819
 
 
2820
  if(!data->change.url)
 
2821
    return CURLE_URL_MALFORMAT;
 
2822
 
 
2823
  /* First, split up the current URL in parts so that we can use the
 
2824
     parts for checking against the already present connections. In order
 
2825
     to not have to modify everything at once, we allocate a temporary
 
2826
     connection data struct and fill in for comparison purposes. */
 
2827
 
 
2828
  conn = (struct connectdata *)calloc(sizeof(struct connectdata), 1);
 
2829
  if(!conn) {
 
2830
    *in_connect = NULL; /* clear the pointer */
 
2831
    return CURLE_OUT_OF_MEMORY;
 
2832
  }
 
2833
  /* We must set the return variable as soon as possible, so that our
 
2834
     parent can cleanup any possible allocs we may have done before
 
2835
     any failure */
 
2836
  *in_connect = conn;
 
2837
 
 
2838
  /* and we setup a few fields in case we end up actually using this struct */
 
2839
 
 
2840
  conn->data = data; /* Setup the association between this connection
 
2841
                        and the SessionHandle */
 
2842
 
 
2843
  conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
 
2844
  conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
 
2845
  conn->connectindex = -1;    /* no index */
 
2846
 
 
2847
  conn->proxytype = data->set.proxytype; /* type */
 
2848
  conn->bits.proxy = (bool)(data->set.proxy && *data->set.proxy);
 
2849
  conn->bits.httpproxy = (bool)(conn->bits.proxy
 
2850
                                && (conn->proxytype == CURLPROXY_HTTP));
 
2851
 
 
2852
 
 
2853
  /* Default protocol-independent behavior doesn't support persistent
 
2854
     connections, so we set this to force-close. Protocols that support
 
2855
     this need to set this to FALSE in their "curl_do" functions. */
 
2856
  conn->bits.close = TRUE;
 
2857
 
 
2858
  conn->readchannel_inuse = FALSE;
 
2859
  conn->writechannel_inuse = FALSE;
 
2860
 
 
2861
  conn->read_pos = 0;
 
2862
  conn->buf_len = 0;
 
2863
 
 
2864
  /* Initialize the pipeline lists */
 
2865
  conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
 
2866
  conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
 
2867
  if (!conn->send_pipe || !conn->recv_pipe)
 
2868
    return CURLE_OUT_OF_MEMORY;
 
2869
 
 
2870
  /* Store creation time to help future close decision making */
 
2871
  conn->created = Curl_tvnow();
 
2872
 
 
2873
  /* range status */
 
2874
  data->reqdata.use_range = (bool)(NULL != data->set.set_range);
 
2875
 
 
2876
  data->reqdata.range = data->set.set_range; /* clone the range setting */
 
2877
  data->reqdata.resume_from = data->set.set_resume_from;
 
2878
 
 
2879
  conn->bits.user_passwd = (bool)(NULL != data->set.userpwd);
 
2880
  conn->bits.proxy_user_passwd = (bool)(NULL != data->set.proxyuserpwd);
 
2881
  conn->bits.no_body = data->set.opt_no_body;
 
2882
  conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
 
2883
  conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
 
2884
  conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
 
2885
 
 
2886
  /* This initing continues below, see the comment "Continue connectdata
 
2887
   * initialization here" */
 
2888
 
 
2889
  /***********************************************************
 
2890
   * We need to allocate memory to store the path in. We get the size of the
 
2891
   * full URL to be sure, and we need to make it at least 256 bytes since
 
2892
   * other parts of the code will rely on this fact
 
2893
   ***********************************************************/
 
2894
#define LEAST_PATH_ALLOC 256
 
2895
  urllen=strlen(data->change.url);
 
2896
  if(urllen < LEAST_PATH_ALLOC)
 
2897
    urllen=LEAST_PATH_ALLOC;
 
2898
 
 
2899
  if (!data->set.source_url /* 3rd party FTP */
 
2900
      && data->reqdata.pathbuffer) {
 
2901
      /* Free the old buffer */
 
2902
      free(data->reqdata.pathbuffer);
 
2903
  }
 
2904
 
 
2905
  /*
 
2906
   * We malloc() the buffers below urllen+2 to make room for to possibilities:
 
2907
   * 1 - an extra terminating zero
 
2908
   * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
 
2909
   */
 
2910
 
 
2911
  data->reqdata.pathbuffer=(char *)malloc(urllen+2);
 
2912
  if(NULL == data->reqdata.pathbuffer)
 
2913
    return CURLE_OUT_OF_MEMORY; /* really bad error */
 
2914
  data->reqdata.path = data->reqdata.pathbuffer;
 
2915
 
 
2916
  conn->host.rawalloc=(char *)malloc(urllen+2);
 
2917
  if(NULL == conn->host.rawalloc)
 
2918
    return CURLE_OUT_OF_MEMORY;
 
2919
 
 
2920
  conn->host.name = conn->host.rawalloc;
 
2921
  conn->host.name[0] = 0;
 
2922
 
 
2923
  result = ParseURLAndFillConnection(data, conn);
 
2924
  if (result != CURLE_OK) {
 
2925
      return result;
 
2926
  }
2848
2927
 
2849
2928
  /*************************************************************
2850
2929
   * Take care of proxy authentication stuff
2867
2946
      return CURLE_OUT_OF_MEMORY;
2868
2947
  }
2869
2948
 
 
2949
  if (data->set.proxy) {
 
2950
    proxy = strdup(data->set.proxy); /* if global proxy is set, this is it */
 
2951
    if(NULL == proxy) {
 
2952
      failf(data, "memory shortage");
 
2953
      return CURLE_OUT_OF_MEMORY;
 
2954
    }
 
2955
  }
 
2956
  /* proxy must be freed later unless NULL */
 
2957
 
2870
2958
#ifndef CURL_DISABLE_HTTP
2871
2959
  /*************************************************************
2872
 
   * Detect what (if any) proxy to use
 
2960
   * Detect what (if any) proxy to use. Remember that this selects a host
 
2961
   * name and is not limited to HTTP proxies only.
2873
2962
   *************************************************************/
2874
 
  if(!data->change.proxy) {
 
2963
  if(!proxy) {
2875
2964
    /* If proxy was not specified, we check for default proxy environment
2876
2965
     * variables, to enable i.e Lynx compliance:
2877
2966
     *
2891
2980
     */
2892
2981
    char *no_proxy=NULL;
2893
2982
    char *no_proxy_tok_buf;
2894
 
    char *proxy=NULL;
2895
2983
    char proxy_env[128];
2896
2984
 
2897
2985
    no_proxy=curl_getenv("no_proxy");
2966
3054
        }
2967
3055
 
2968
3056
        if(proxy && *proxy) {
2969
 
          long bits = conn->protocol & (PROT_HTTPS|PROT_SSL);
2970
 
          data->change.proxy = proxy;
2971
 
          data->change.proxy_alloc=TRUE; /* this needs to be freed later */
2972
 
          conn->bits.httpproxy = TRUE;
 
3057
          long bits = conn->protocol & (PROT_HTTPS|PROT_SSL|PROT_MISSING);
2973
3058
 
2974
 
          /* force this to become HTTP */
2975
 
          conn->protocol = PROT_HTTP | bits;
 
3059
          if(conn->proxytype == CURLPROXY_HTTP) {
 
3060
            /* force this connection's protocol to become HTTP */
 
3061
            conn->protocol = PROT_HTTP | bits;
 
3062
            conn->bits.httpproxy = TRUE;
 
3063
          }
2976
3064
        }
2977
3065
      } /* if (!nope) - it wasn't specified non-proxy */
2978
3066
    } /* NO_PROXY wasn't specified or '*' */
2992
3080
 
2993
3081
    reurl = aprintf("%s://%s", conn->protostr, data->change.url);
2994
3082
 
2995
 
    if(!reurl)
 
3083
    if(!reurl) {
 
3084
      Curl_safefree(proxy);
2996
3085
      return CURLE_OUT_OF_MEMORY;
 
3086
    }
2997
3087
 
2998
3088
    data->change.url = reurl;
2999
3089
    data->change.url_alloc = TRUE; /* free this later */
3000
3090
    conn->protocol &= ~PROT_MISSING; /* switch that one off again */
3001
3091
  }
3002
3092
 
3003
 
#ifndef CURL_DISABLE_HTTP
3004
 
  /************************************************************
3005
 
   * RESUME on a HTTP page is a tricky business. First, let's just check that
3006
 
   * 'range' isn't used, then set the range parameter and leave the resume as
3007
 
   * it is to inform about this situation for later use. We will then
3008
 
   * "attempt" to resume, and if we're talking to a HTTP/1.1 (or later)
3009
 
   * server, we will get the document resumed. If we talk to a HTTP/1.0
3010
 
   * server, we just fail since we can't rewind the file writing from within
3011
 
   * this function.
3012
 
   ***********************************************************/
3013
 
  if(conn->resume_from) {
3014
 
    if(!conn->bits.use_range) {
3015
 
      /* if it already was in use, we just skip this */
3016
 
      conn->range = aprintf("%" FORMAT_OFF_T "-", conn->resume_from);
3017
 
      if(!conn->range)
3018
 
        return CURLE_OUT_OF_MEMORY;
3019
 
      conn->bits.rangestringalloc = TRUE; /* mark as allocated */
3020
 
      conn->bits.use_range = 1; /* switch on range usage */
3021
 
    }
3022
 
  }
3023
 
#endif
3024
3093
  /*************************************************************
3025
3094
   * Setup internals depending on protocol
3026
3095
   *************************************************************/
3033
3102
    conn->remote_port = PORT_HTTP;
3034
3103
    conn->protocol |= PROT_HTTP;
3035
3104
    conn->curl_do = Curl_http;
3036
 
    conn->curl_do_more = (Curl_do_more_func)NULL;
 
3105
    conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
3037
3106
    conn->curl_done = Curl_http_done;
3038
3107
    conn->curl_connect = Curl_http_connect;
3039
3108
#else
3050
3119
    conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
3051
3120
 
3052
3121
    conn->curl_do = Curl_http;
3053
 
    conn->curl_do_more = (Curl_do_more_func)NULL;
 
3122
    conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
3054
3123
    conn->curl_done = Curl_http_done;
3055
3124
    conn->curl_connect = Curl_http_connect;
3056
3125
    conn->curl_connecting = Curl_https_connecting;
3057
3126
    conn->curl_proto_getsock = Curl_https_getsock;
3058
3127
 
3059
 
#else /* USE_SS */
 
3128
#else /* USE_SSL */
3060
3129
    failf(data, LIBCURL_NAME
3061
3130
          " was built with SSL disabled, https: not supported!");
3062
3131
    return CURLE_UNSUPPORTED_PROTOCOL;
3072
3141
    if(strequal(conn->protostr, "FTPS")) {
3073
3142
#ifdef USE_SSL
3074
3143
      conn->protocol |= PROT_FTPS|PROT_SSL;
3075
 
      conn->ssl[SECONDARYSOCKET].use = TRUE; /* send data securely */
 
3144
      /* send data securely unless specifically requested otherwise */
 
3145
      conn->ssl[SECONDARYSOCKET].use = data->set.ftp_ssl != CURLFTPSSL_CONTROL;
3076
3146
      port = PORT_FTPS;
3077
3147
#else
3078
3148
      failf(data, LIBCURL_NAME
3085
3155
    conn->remote_port = (unsigned short)port;
3086
3156
    conn->protocol |= PROT_FTP;
3087
3157
 
3088
 
    if(data->change.proxy &&
3089
 
       *data->change.proxy &&
3090
 
       !data->set.tunnel_thru_httpproxy) {
 
3158
    if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
3091
3159
      /* Unless we have asked to tunnel ftp operations through the proxy, we
3092
3160
         switch and use HTTP operations only */
3093
3161
#ifndef CURL_DISABLE_HTTP
3111
3179
      conn->curl_disconnect = Curl_ftp_disconnect;
3112
3180
    }
3113
3181
 
3114
 
    conn->path++; /* don't include the initial slash */
 
3182
    data->reqdata.path++; /* don't include the initial slash */
3115
3183
 
3116
3184
    /* FTP URLs support an extension like ";type=<typecode>" that
3117
3185
     * we'll try to get now! */
3118
 
    type=strstr(conn->path, ";type=");
 
3186
    type=strstr(data->reqdata.path, ";type=");
3119
3187
    if(!type) {
3120
3188
      type=strstr(conn->host.rawalloc, ";type=");
3121
3189
    }
3125
3193
      command = (char)toupper((int)type[6]);
3126
3194
      switch(command) {
3127
3195
      case 'A': /* ASCII mode */
3128
 
        data->set.ftp_ascii = 1;
 
3196
        data->set.prefer_ascii = TRUE;
3129
3197
        break;
3130
3198
      case 'D': /* directory mode */
3131
 
        data->set.ftp_list_only = 1;
 
3199
        data->set.ftp_list_only = TRUE;
3132
3200
        break;
3133
3201
      case 'I': /* binary mode */
3134
3202
      default:
3135
3203
        /* switch off ASCII */
3136
 
        data->set.ftp_ascii = 0;
 
3204
        data->set.prefer_ascii = FALSE;
3137
3205
        break;
3138
3206
      }
3139
3207
    }
3155
3223
#else
3156
3224
    failf(data, LIBCURL_NAME
3157
3225
          " was built with TELNET disabled!");
 
3226
    return CURLE_UNSUPPORTED_PROTOCOL;
3158
3227
#endif
3159
3228
  }
3160
3229
  else if (strequal(conn->protostr, "DICT")) {
3163
3232
    conn->port = PORT_DICT;
3164
3233
    conn->remote_port = PORT_DICT;
3165
3234
    conn->curl_do = Curl_dict;
3166
 
    conn->curl_done = (Curl_done_func)NULL; /* no DICT-specific done */
 
3235
    /* no DICT-specific done */
 
3236
    conn->curl_done = (Curl_done_func)ZERO_NULL;
3167
3237
#else
3168
3238
    failf(data, LIBCURL_NAME
3169
3239
          " was built with DICT disabled!");
 
3240
    return CURLE_UNSUPPORTED_PROTOCOL;
3170
3241
#endif
3171
3242
  }
3172
3243
  else if (strequal(conn->protostr, "LDAP")) {
3175
3246
    conn->port = PORT_LDAP;
3176
3247
    conn->remote_port = PORT_LDAP;
3177
3248
    conn->curl_do = Curl_ldap;
3178
 
    conn->curl_done = (Curl_done_func)NULL; /* no LDAP-specific done */
 
3249
    /* no LDAP-specific done */
 
3250
    conn->curl_done = (Curl_done_func)ZERO_NULL;
3179
3251
#else
3180
3252
    failf(data, LIBCURL_NAME
3181
3253
          " was built with LDAP disabled!");
 
3254
    return CURLE_UNSUPPORTED_PROTOCOL;
3182
3255
#endif
3183
3256
  }
3184
3257
  else if (strequal(conn->protostr, "FILE")) {
3187
3260
 
3188
3261
    conn->curl_do = Curl_file;
3189
3262
    conn->curl_done = Curl_file_done;
3190
 
 
3191
 
    /* anyway, this is supposed to be the connect function so we better
3192
 
       at least check that the file is present here! */
3193
 
    result = Curl_file_connect(conn);
3194
 
 
3195
 
    /* Setup a "faked" transfer that'll do nothing */
3196
 
    if(CURLE_OK == result) {
3197
 
      conn->bits.tcpconnect = TRUE; /* we are "connected */
3198
 
      result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
3199
 
                             -1, NULL); /* no upload */
3200
 
    }
3201
 
 
3202
 
    return result;
3203
3263
#else
3204
3264
    failf(data, LIBCURL_NAME
3205
3265
          " was built with FILE disabled!");
 
3266
    return CURLE_UNSUPPORTED_PROTOCOL;
3206
3267
#endif
3207
3268
  }
3208
3269
  else if (strequal(conn->protostr, "TFTP")) {
3217
3278
    conn->curl_done = Curl_tftp_done;
3218
3279
    /* TFTP URLs support an extension like ";mode=<typecode>" that
3219
3280
     * we'll try to get now! */
3220
 
    type=strstr(conn->path, ";mode=");
 
3281
    type=strstr(data->reqdata.path, ";mode=");
3221
3282
    if(!type) {
3222
3283
      type=strstr(conn->host.rawalloc, ";mode=");
3223
3284
    }
3228
3289
      switch(command) {
3229
3290
      case 'A': /* ASCII mode */
3230
3291
      case 'N': /* NETASCII mode */
3231
 
        data->set.ftp_ascii = 1;
 
3292
        data->set.prefer_ascii = TRUE;
3232
3293
        break;
3233
3294
      case 'O': /* octet mode */
3234
3295
      case 'I': /* binary mode */
3235
3296
      default:
3236
3297
        /* switch off ASCII */
3237
 
        data->set.ftp_ascii = 0;
 
3298
        data->set.prefer_ascii = FALSE;
3238
3299
        break;
3239
3300
      }
3240
3301
    }
3241
3302
#else
3242
3303
    failf(data, LIBCURL_NAME
3243
3304
          " was built with TFTP disabled!");
3244
 
#endif
3245
 
  }
3246
 
  else {
 
3305
    return CURLE_UNSUPPORTED_PROTOCOL;
 
3306
#endif
 
3307
  }
 
3308
  else if (strequal(conn->protostr, "SCP")) {
 
3309
#ifdef USE_LIBSSH2
 
3310
    conn->port = PORT_SSH;
 
3311
    conn->remote_port = PORT_SSH;
 
3312
    conn->protocol = PROT_SCP;
 
3313
    conn->curl_connect = Curl_ssh_connect; /* ssh_connect? */
 
3314
    conn->curl_do = Curl_scp_do;
 
3315
    conn->curl_done = Curl_scp_done;
 
3316
    conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
 
3317
#else
 
3318
    failf(data, LIBCURL_NAME
 
3319
          " was built without LIBSSH2, scp: not supported!");
 
3320
    return CURLE_UNSUPPORTED_PROTOCOL;
 
3321
#endif
 
3322
  }
 
3323
  else if (strequal(conn->protostr, "SFTP")) {
 
3324
#ifdef USE_LIBSSH2
 
3325
    conn->port = PORT_SSH;
 
3326
    conn->remote_port = PORT_SSH;
 
3327
    conn->protocol = PROT_SFTP;
 
3328
    conn->curl_connect = Curl_ssh_connect; /* ssh_connect? */
 
3329
    conn->curl_do = Curl_sftp_do;
 
3330
    conn->curl_done = Curl_sftp_done;
 
3331
    conn->curl_do_more = (Curl_do_more_func)NULL;
 
3332
#else
 
3333
    failf(data, LIBCURL_NAME
 
3334
          " was built without LIBSSH2, scp: not supported!");
 
3335
    return CURLE_UNSUPPORTED_PROTOCOL;
 
3336
#endif
 
3337
}
 
3338
else {
3247
3339
    /* We fell through all checks and thus we don't support the specified
3248
3340
       protocol */
3249
3341
    failf(data, "Unsupported protocol: %s", conn->protostr);
3250
3342
    return CURLE_UNSUPPORTED_PROTOCOL;
3251
3343
  }
3252
3344
 
3253
 
  if(data->change.proxy && *data->change.proxy) {
 
3345
  if(proxy && *proxy) {
3254
3346
    /* If this is supposed to use a proxy, we need to figure out the proxy
3255
3347
       host name name, so that we can re-use an existing connection
3256
3348
       that may exist registered to the same proxy host. */
3258
3350
    char *prox_portno;
3259
3351
    char *endofprot;
3260
3352
 
3261
 
    /* We need to make a duplicate of the proxy so that we can modify the
3262
 
       string safely. */
3263
 
    char *proxydup=strdup(data->change.proxy);
3264
 
 
3265
3353
    /* We use 'proxyptr' to point to the proxy name from now on... */
3266
 
    char *proxyptr=proxydup;
 
3354
    char *proxyptr=proxy;
3267
3355
    char *portptr;
3268
3356
    char *atsign;
3269
3357
 
3270
 
    if(NULL == proxydup) {
3271
 
      failf(data, "memory shortage");
3272
 
      return CURLE_OUT_OF_MEMORY;
3273
 
    }
3274
 
 
3275
3358
    /* We do the proxy host string parsing here. We want the host name and the
3276
3359
     * port name. Accept a protocol:// prefix, even though it should just be
3277
3360
     * ignored.
3287
3370
    if(atsign) {
3288
3371
      char proxyuser[MAX_CURL_USER_LENGTH];
3289
3372
      char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
 
3373
      proxypasswd[0] = 0;
3290
3374
 
3291
 
      if(2 == sscanf(proxyptr,
 
3375
      if(1 <= sscanf(proxyptr,
3292
3376
                     "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
3293
3377
                     "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
3294
3378
                     proxyuser, proxypasswd)) {
3316
3400
          atsign = strdup(atsign+1); /* the right side of the @-letter */
3317
3401
 
3318
3402
          if(atsign) {
3319
 
            free(proxydup); /* free the former proxy string */
3320
 
            proxydup = proxyptr = atsign; /* now use this instead */
 
3403
            free(proxy); /* free the former proxy string */
 
3404
            proxy = proxyptr = atsign; /* now use this instead */
3321
3405
          }
3322
3406
          else
3323
3407
            res = CURLE_OUT_OF_MEMORY;
3324
3408
        }
3325
3409
 
3326
3410
        if(res) {
3327
 
          free(proxydup); /* free the allocated proxy string */
 
3411
          free(proxy); /* free the allocated proxy string */
3328
3412
          return res;
3329
3413
        }
3330
3414
      }
3336
3420
    /* detect and extract RFC2732-style IPv6-addresses */
3337
3421
    if(*proxyptr == '[') {
3338
3422
      char *ptr = ++proxyptr; /* advance beyond the initial bracket */
3339
 
      while(*ptr && (isxdigit((int)*ptr) || (*ptr == ':')))
 
3423
      while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':')))
3340
3424
        ptr++;
3341
3425
      if(*ptr == ']') {
3342
3426
        /* yeps, it ended nicely with a bracket as well */
3367
3451
    conn->proxy.rawalloc = strdup(proxyptr);
3368
3452
    conn->proxy.name = conn->proxy.rawalloc;
3369
3453
 
3370
 
    free(proxydup); /* free the duplicate pointer and not the modified */
 
3454
    free(proxy);
 
3455
    proxy = NULL;
3371
3456
    if(!conn->proxy.rawalloc)
3372
3457
      return CURLE_OUT_OF_MEMORY;
3373
3458
  }
3374
3459
 
 
3460
  /***********************************************************************
 
3461
   * file: is a special case in that it doesn't need a network connection
 
3462
   ***********************************************************************/
 
3463
#ifndef CURL_DISABLE_FILE
 
3464
  if (strequal(conn->protostr, "FILE")) {
 
3465
      /* anyway, this is supposed to be the connect function so we better
 
3466
         at least check that the file is present here! */
 
3467
     result = Curl_file_connect(conn);
 
3468
 
 
3469
      /* Setup a "faked" transfer that'll do nothing */
 
3470
     if(CURLE_OK == result) {
 
3471
        conn->data = data;
 
3472
        conn->bits.tcpconnect = TRUE; /* we are "connected */
 
3473
        ConnectionStore(data, conn);
 
3474
 
 
3475
      result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
 
3476
                                     -1, NULL); /* no upload */
 
3477
    }
 
3478
 
 
3479
    return result;
 
3480
  }
 
3481
#endif
 
3482
 
3375
3483
  /*************************************************************
3376
 
   * If the protcol is using SSL and HTTP proxy is used, we set
 
3484
   * If the protocol is using SSL and HTTP proxy is used, we set
3377
3485
   * the tunnel_proxy bit.
3378
3486
   *************************************************************/
3379
3487
  if((conn->protocol&PROT_SSL) && conn->bits.httpproxy)
3408
3516
  user[0] =0;   /* to make everything well-defined */
3409
3517
  passwd[0]=0;
3410
3518
 
3411
 
  if (conn->protocol & (PROT_FTP|PROT_HTTP)) {
3412
 
    /* This is a FTP or HTTP URL, we will now try to extract the possible
3413
 
     * user+password pair in a string like:
 
3519
  if (conn->protocol & (PROT_FTP|PROT_HTTP|PROT_SCP|PROT_SFTP)) {
 
3520
    /* This is a FTP, HTTP, SCP or SFTP URL, we will now try to extract the
 
3521
     * possible user+password pair in a string like:
3414
3522
     * ftp://user:password@ftp.my.site:8021/README */
3415
3523
    char *ptr=strchr(conn->host.name, '@');
3416
3524
    char *userpass = conn->host.name;
3502
3610
      /* we need to create new URL with the new port number */
3503
3611
      char *url;
3504
3612
 
3505
 
      url = aprintf("http://%s:%d%s", conn->host.name, conn->remote_port,
3506
 
                    conn->path);
 
3613
      url = aprintf("%s://%s:%d%s", conn->protostr, conn->host.name,
 
3614
                    conn->remote_port, data->reqdata.path);
3507
3615
      if(!url)
3508
3616
        return CURLE_OUT_OF_MEMORY;
3509
3617
 
3589
3697
  if(!conn->user || !conn->passwd)
3590
3698
    return CURLE_OUT_OF_MEMORY;
3591
3699
 
 
3700
#ifndef CURL_DISABLE_HTTP
 
3701
  /************************************************************
 
3702
   * RESUME on a HTTP page is a tricky business. First, let's just check that
 
3703
   * 'range' isn't used, then set the range parameter and leave the resume as
 
3704
   * it is to inform about this situation for later use. We will then
 
3705
   * "attempt" to resume, and if we're talking to a HTTP/1.1 (or later)
 
3706
   * server, we will get the document resumed. If we talk to a HTTP/1.0
 
3707
   * server, we just fail since we can't rewind the file writing from within
 
3708
   * this function.
 
3709
   ***********************************************************/
 
3710
  if(data->reqdata.resume_from) {
 
3711
    if(!data->reqdata.use_range) {
 
3712
      /* if it already was in use, we just skip this */
 
3713
      data->reqdata.range = aprintf("%" FORMAT_OFF_T "-", data->reqdata.resume_from);
 
3714
      if(!data->reqdata.range)
 
3715
        return CURLE_OUT_OF_MEMORY;
 
3716
      data->reqdata.rangestringalloc = TRUE; /* mark as allocated */
 
3717
      data->reqdata.use_range = 1; /* switch on range usage */
 
3718
    }
 
3719
  }
 
3720
#endif
 
3721
 
3592
3722
  /*************************************************************
3593
3723
   * Check the current list of connections to see if we can
3594
3724
   * re-use an already existing one or if we have to create a
3627
3757
 
3628
3758
    conn = conn_temp;        /* use this connection from now on */
3629
3759
 
 
3760
    conn->data = old_conn->data;
 
3761
 
3630
3762
    /* get the user+password information from the old_conn struct since it may
3631
3763
     * be new for this request even when we re-use an existing connection */
3632
3764
    conn->bits.user_passwd = old_conn->bits.user_passwd;
3652
3784
    }
3653
3785
 
3654
3786
    /* host can change, when doing keepalive with a proxy ! */
3655
 
    if (conn->bits.httpproxy) {
 
3787
    if (conn->bits.proxy) {
3656
3788
      free(conn->host.rawalloc);
3657
3789
      conn->host=old_conn->host;
3658
3790
    }
 
3791
    else
 
3792
      free(old_conn->host.rawalloc); /* free the newly allocated name buffer */
3659
3793
 
3660
3794
    /* get the newly set value, not the old one */
3661
3795
    conn->bits.no_body = old_conn->bits.no_body;
3662
3796
 
3663
 
    if (!conn->bits.httpproxy)
3664
 
      free(old_conn->host.rawalloc); /* free the newly allocated name buffer */
3665
 
 
3666
 
    free(conn->pathbuffer); /* free the newly allocated path pointer */
3667
 
    conn->pathbuffer = old_conn->pathbuffer; /* use the old one */
3668
 
    conn->path = old_conn->path;
3669
 
 
3670
3797
    /* re-use init */
3671
3798
    conn->bits.reuse = TRUE; /* yes, we're re-using here */
3672
 
    conn->bits.chunk = FALSE; /* always assume not chunked unless told
3673
 
                                 otherwise */
3674
 
    conn->maxdownload = -1;  /* might have been used previously! */
3675
3799
 
3676
3800
    Curl_safefree(old_conn->user);
3677
3801
    Curl_safefree(old_conn->passwd);
3678
3802
    Curl_safefree(old_conn->proxyuser);
3679
3803
    Curl_safefree(old_conn->proxypasswd);
3680
 
 
3681
 
    if(old_conn->bits.rangestringalloc)
3682
 
      free(old_conn->range);
 
3804
    Curl_llist_destroy(old_conn->send_pipe, NULL);
 
3805
    Curl_llist_destroy(old_conn->recv_pipe, NULL);
3683
3806
 
3684
3807
    free(old_conn);          /* we don't need this anymore */
3685
3808
 
3687
3810
     * If we're doing a resumed transfer, we need to setup our stuff
3688
3811
     * properly.
3689
3812
     */
3690
 
    conn->resume_from = data->set.set_resume_from;
3691
 
    if (conn->resume_from) {
3692
 
      if (conn->bits.rangestringalloc == TRUE)
3693
 
        free(conn->range);
3694
 
      conn->range = aprintf("%" FORMAT_OFF_T "-", conn->resume_from);
3695
 
      if(!conn->range)
 
3813
    data->reqdata.resume_from = data->set.set_resume_from;
 
3814
    if (data->reqdata.resume_from) {
 
3815
      if (data->reqdata.rangestringalloc == TRUE)
 
3816
        free(data->reqdata.range);
 
3817
      data->reqdata.range = aprintf("%" FORMAT_OFF_T "-",
 
3818
                                    data->reqdata.resume_from);
 
3819
      if(!data->reqdata.range)
3696
3820
        return CURLE_OUT_OF_MEMORY;
3697
3821
 
3698
3822
      /* tell ourselves to fetch this range */
3699
 
      conn->bits.use_range = TRUE;        /* enable range download */
3700
 
      conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
 
3823
      data->reqdata.use_range = TRUE;        /* enable range download */
 
3824
      data->reqdata.rangestringalloc = TRUE; /* mark range string allocated */
3701
3825
    }
3702
3826
    else if (data->set.set_range) {
3703
3827
      /* There is a range, but is not a resume, useful for random ftp access */
3704
 
      conn->range = strdup(data->set.set_range);
3705
 
      if(!conn->range)
 
3828
      data->reqdata.range = strdup(data->set.set_range);
 
3829
      if(!data->reqdata.range)
3706
3830
        return CURLE_OUT_OF_MEMORY;
3707
 
      conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
3708
 
      conn->bits.use_range = TRUE;        /* enable range download */
 
3831
      data->reqdata.rangestringalloc = TRUE; /* mark range string allocated */
 
3832
      data->reqdata.use_range = TRUE;        /* enable range download */
3709
3833
    }
3710
3834
    else
3711
 
      conn->bits.use_range = FALSE; /* disable range download */
 
3835
      data->reqdata.use_range = FALSE; /* disable range download */
3712
3836
 
3713
3837
    *in_connect = conn;      /* return this instead! */
3714
3838
 
3715
3839
    infof(data, "Re-using existing connection! (#%ld) with host %s\n",
3716
3840
          conn->connectindex,
3717
 
          conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
 
3841
          conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
3718
3842
  }
3719
3843
  else {
3720
3844
    /*
3724
3848
    ConnectionStore(data, conn);
3725
3849
  }
3726
3850
 
3727
 
  /* Continue connectdata initialization here.
 
3851
  /* Continue connectdata initialization here. */
 
3852
 
 
3853
  /*
3728
3854
   *
3729
3855
   * Inherit the proper values from the urldata struct AFTER we have arranged
3730
3856
   * the persistent connection stuff */
3731
3857
  conn->fread = data->set.fread;
3732
3858
  conn->fread_in = data->set.in;
3733
3859
 
3734
 
  conn->bits.upload_chunky =
3735
 
    ((conn->protocol&PROT_HTTP) &&
3736
 
     data->set.upload &&
3737
 
     (data->set.infilesize == -1) &&
3738
 
     (data->set.httpversion != CURL_HTTP_VERSION_1_0))?
 
3860
  if ((conn->protocol&PROT_HTTP) &&
 
3861
      data->set.upload &&
 
3862
      (data->set.infilesize == -1) &&
 
3863
      (data->set.httpversion != CURL_HTTP_VERSION_1_0)) {
3739
3864
    /* HTTP, upload, unknown file size and not HTTP 1.0 */
3740
 
    TRUE:
3741
 
  /* else, no chunky upload */
3742
 
  FALSE;
 
3865
    conn->bits.upload_chunky = TRUE;
 
3866
  }
 
3867
  else {
 
3868
    /* else, no chunky upload */
 
3869
    conn->bits.upload_chunky = FALSE;
 
3870
  }
3743
3871
 
3744
3872
#ifndef USE_ARES
3745
3873
  /*************************************************************
3753
3881
     *************************************************************/
3754
3882
 
3755
3883
#ifdef SIGALRM
 
3884
#ifdef HAVE_ALARM
 
3885
    long shortest;
 
3886
#endif
3756
3887
#ifdef HAVE_SIGACTION
3757
3888
    struct sigaction sigact;
3758
3889
    sigaction(SIGALRM, NULL, &sigact);
3778
3909
     * multi-threaded environments. */
3779
3910
 
3780
3911
#ifdef HAVE_ALARM
 
3912
    shortest = data->set.timeout; /* default to this timeout value */
 
3913
    if(shortest && data->set.connecttimeout &&
 
3914
       (data->set.connecttimeout < shortest))
 
3915
      /* if both are set, pick the shortest */
 
3916
      shortest = data->set.connecttimeout;
 
3917
    else if(!shortest)
 
3918
      /* if timeout is not set, use the connect timeout */
 
3919
      shortest = data->set.connecttimeout;
 
3920
 
 
3921
    if(shortest < 1000)
 
3922
      /* the alarm() function only provide integer second resolution, so if
 
3923
         we want to wait less than one second we must bail out already now. */
 
3924
      return CURLE_OPERATION_TIMEDOUT;
 
3925
 
3781
3926
    /* alarm() makes a signal get sent when the timeout fires off, and that
3782
3927
       will abort system calls */
3783
 
    prev_alarm = alarm((unsigned int) (data->set.connecttimeout?
3784
 
                                       data->set.connecttimeout:
3785
 
                                       data->set.timeout));
 
3928
    prev_alarm = alarm((unsigned int) (shortest ? shortest/1000L : shortest));
3786
3929
    /* We can expect the conn->created time to be "now", as that was just
3787
3930
       recently set in the beginning of this function and nothing slow
3788
3931
       has been done since then until now. */
3799
3942
    hostaddr = NULL;
3800
3943
    /* we'll need to clear conn->dns_entry later in Curl_disconnect() */
3801
3944
 
3802
 
    if (conn->bits.httpproxy)
3803
 
      fix_hostname(conn, &conn->host);
 
3945
    if (conn->bits.proxy)
 
3946
      fix_hostname(data, conn, &conn->host);
3804
3947
  }
3805
3948
  else {
3806
3949
    /* this is a fresh connect */
3807
3950
 
3808
3951
    /* set a pointer to the hostname we display */
3809
 
    fix_hostname(conn, &conn->host);
 
3952
    fix_hostname(data, conn, &conn->host);
3810
3953
 
3811
 
    if(!data->change.proxy || !*data->change.proxy) {
 
3954
    if(!conn->proxy.name || !*conn->proxy.name) {
3812
3955
      /* If not connecting via a proxy, extract the port from the URL, if it is
3813
3956
       * there, thus overriding any defaults that might have been set above. */
3814
3957
      conn->port =  conn->remote_port; /* it is the same port */
3815
3958
 
3816
 
      /* Resolve target host right now */
 
3959
      /* Resolve target host right on */
3817
3960
      rc = Curl_resolv(conn, conn->host.name, (int)conn->port, &hostaddr);
3818
3961
      if(rc == CURLRESOLV_PENDING)
3819
3962
        *async = TRUE;
3828
3971
      /* This is a proxy that hasn't been resolved yet. */
3829
3972
 
3830
3973
      /* IDN-fix the proxy name */
3831
 
      fix_hostname(conn, &conn->proxy);
 
3974
      fix_hostname(data, conn, &conn->proxy);
3832
3975
 
3833
3976
      /* resolve proxy */
3834
3977
      rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &hostaddr);
3896
4039
 *
3897
4040
 * NOTE: the argument 'hostaddr' is NULL when this function is called for a
3898
4041
 * re-used connection.
 
4042
 *
 
4043
 * conn->data MUST already have been setup fine (in CreateConnection)
3899
4044
 */
3900
4045
 
3901
4046
static CURLcode SetupConnection(struct connectdata *conn,
3902
4047
                                struct Curl_dns_entry *hostaddr,
3903
4048
                                bool *protocol_done)
3904
4049
{
 
4050
  CURLcode result=CURLE_OK;
3905
4051
  struct SessionHandle *data = conn->data;
3906
 
  CURLcode result=CURLE_OK;
3907
4052
 
3908
4053
  Curl_pgrsTime(data, TIMER_NAMELOOKUP);
3909
4054
 
3916
4061
  *protocol_done = FALSE; /* default to not done */
3917
4062
 
3918
4063
  /*************************************************************
3919
 
   * Send user-agent to HTTP proxies even if the target protocol
3920
 
   * isn't HTTP.
 
4064
   * Set user-agent for HTTP
3921
4065
   *************************************************************/
3922
 
  if((conn->protocol&PROT_HTTP) ||
3923
 
     (data->change.proxy && *data->change.proxy)) {
3924
 
    if(data->set.useragent) {
3925
 
      Curl_safefree(conn->allocptr.uagent);
3926
 
      conn->allocptr.uagent =
3927
 
        aprintf("User-Agent: %s\015\012", data->set.useragent);
3928
 
      if(!conn->allocptr.uagent)
3929
 
        return CURLE_OUT_OF_MEMORY;
3930
 
    }
 
4066
  if((conn->protocol&PROT_HTTP) && data->set.useragent) {
 
4067
    Curl_safefree(conn->allocptr.uagent);
 
4068
    conn->allocptr.uagent =
 
4069
      aprintf("User-Agent: %s\r\n", data->set.useragent);
 
4070
    if(!conn->allocptr.uagent)
 
4071
      return CURLE_OUT_OF_MEMORY;
3931
4072
  }
3932
4073
 
3933
 
  conn->bytecount = 0;
3934
 
  conn->headerbytecount = 0;
 
4074
  data->reqdata.keep.headerbytecount = 0;
 
4075
 
3935
4076
#ifdef CURL_DO_LINEEND_CONV
3936
4077
  data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
3937
4078
#endif /* CURL_DO_LINEEND_CONV */
3938
4079
 
3939
 
  if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
3940
 
    bool connected = FALSE;
3941
 
 
3942
 
    /* Connect only if not already connected! */
3943
 
    result = ConnectPlease(conn, hostaddr, &connected);
3944
 
 
3945
 
    if(connected) {
3946
 
      result = Curl_protocol_connect(conn, protocol_done);
3947
 
      if(CURLE_OK == result)
3948
 
        conn->bits.tcpconnect = TRUE;
3949
 
    }
3950
 
    else
3951
 
      conn->bits.tcpconnect = FALSE;
3952
 
 
3953
 
 
3954
 
    if(CURLE_OK != result)
3955
 
      return result;
3956
 
  }
3957
 
  else {
3958
 
    Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
3959
 
    conn->bits.tcpconnect = TRUE;
3960
 
    *protocol_done = TRUE;
3961
 
    if(data->set.verbose)
3962
 
      verboseconnect(conn);
 
4080
  for(;;) {
 
4081
    /* loop for CURL_SERVER_CLOSED_CONNECTION */
 
4082
 
 
4083
    if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
 
4084
      bool connected = FALSE;
 
4085
 
 
4086
      /* Connect only if not already connected! */
 
4087
      result = ConnectPlease(data, conn, hostaddr, &connected);
 
4088
 
 
4089
      if(connected) {
 
4090
        result = Curl_protocol_connect(conn, protocol_done);
 
4091
        if(CURLE_OK == result)
 
4092
          conn->bits.tcpconnect = TRUE;
 
4093
      }
 
4094
      else
 
4095
        conn->bits.tcpconnect = FALSE;
 
4096
 
 
4097
      /* if the connection was closed by the server while exchanging
 
4098
         authentication informations, retry with the new set
 
4099
         authentication information */
 
4100
      if(conn->bits.proxy_connect_closed) {
 
4101
        /* reset the error buffer */
 
4102
        if (data->set.errorbuffer)
 
4103
          data->set.errorbuffer[0] = '\0';
 
4104
        data->state.errorbuf = FALSE;
 
4105
        continue;
 
4106
      }
 
4107
 
 
4108
      if(CURLE_OK != result)
 
4109
        return result;
 
4110
    }
 
4111
    else {
 
4112
      Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
 
4113
      conn->bits.tcpconnect = TRUE;
 
4114
      *protocol_done = TRUE;
 
4115
      if(data->set.verbose)
 
4116
        verboseconnect(conn);
 
4117
    }
 
4118
    /* Stop the loop now */
 
4119
    break;
3963
4120
  }
3964
4121
 
3965
4122
  conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
4001
4158
         will be NULL here. Continue connecting from here */
4002
4159
      code = SetupConnection(*in_connect, dns, protocol_done);
4003
4160
    /* else
4004
 
         response will be received and treated async wise */
 
4161
       response will be received and treated async wise */
4005
4162
  }
4006
4163
 
4007
4164
  if(CURLE_OK != code) {
4012
4169
      *in_connect = NULL;           /* return a NULL */
4013
4170
    }
4014
4171
  }
 
4172
  else {
 
4173
    if ((*in_connect)->is_in_pipeline)
 
4174
      data->state.is_in_pipeline = TRUE;
 
4175
  }
4015
4176
 
4016
4177
  return code;
4017
4178
}
4043
4204
 
4044
4205
 
4045
4206
CURLcode Curl_done(struct connectdata **connp,
4046
 
                   CURLcode status) /* an error if this is called after an
4047
 
                                       error was detected */
 
4207
                   CURLcode status,  /* an error if this is called after an
 
4208
                                        error was detected */
 
4209
                   bool premature)
4048
4210
{
4049
4211
  CURLcode result;
4050
4212
  struct connectdata *conn = *connp;
4051
 
  struct SessionHandle *data=conn->data;
 
4213
  struct SessionHandle *data = conn->data;
4052
4214
 
4053
4215
  Curl_expire(data, 0); /* stop timer */
4054
4216
 
4057
4219
 
4058
4220
  conn->bits.done = TRUE; /* called just now! */
4059
4221
 
 
4222
  if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) &&
 
4223
     conn->readchannel_inuse)
 
4224
    conn->readchannel_inuse = FALSE;
 
4225
  if(Curl_removeHandleFromPipeline(data, conn->send_pipe) &&
 
4226
     conn->writechannel_inuse)
 
4227
    conn->writechannel_inuse = FALSE;
 
4228
 
4060
4229
  /* cleanups done even if the connection is re-used */
4061
 
  if(conn->bits.rangestringalloc) {
4062
 
    free(conn->range);
4063
 
    conn->bits.rangestringalloc = FALSE;
 
4230
  if(data->reqdata.rangestringalloc) {
 
4231
    free(data->reqdata.range);
 
4232
    data->reqdata.rangestringalloc = FALSE;
 
4233
  }
 
4234
 
 
4235
  /* Cleanup possible redirect junk */
 
4236
  if(data->reqdata.newurl) {
 
4237
    free(data->reqdata.newurl);
 
4238
    data->reqdata.newurl = NULL;
4064
4239
  }
4065
4240
 
4066
4241
  if(conn->dns_entry) {
4068
4243
    conn->dns_entry = NULL;
4069
4244
  }
4070
4245
 
4071
 
  /* Cleanup possible redirect junk */
4072
 
  if(conn->newurl) {
4073
 
    free(conn->newurl);
4074
 
    conn->newurl = NULL;
4075
 
  }
4076
 
 
4077
4246
  /* this calls the protocol-specific function pointer previously set */
4078
4247
  if(conn->curl_done)
4079
 
    result = conn->curl_done(conn, status);
 
4248
    result = conn->curl_done(conn, status, premature);
4080
4249
  else
4081
4250
    result = CURLE_OK;
4082
4251
 
4093
4262
     closed in spite of all our efforts to be nice, due to protocol
4094
4263
     restrictions in our or the server's end */
4095
4264
  if(data->set.reuse_forbid || conn->bits.close) {
4096
 
    CURLcode res2;
4097
 
    res2 = Curl_disconnect(conn); /* close the connection */
4098
 
 
4099
 
    *connp = NULL; /* to make the caller of this function better detect that
4100
 
                      this was actually killed here */
 
4265
    CURLcode res2 = Curl_disconnect(conn); /* close the connection */
4101
4266
 
4102
4267
    /* If we had an error already, make sure we return that one. But
4103
4268
       if we got a new error, return that. */
4105
4270
      result = res2;
4106
4271
  }
4107
4272
  else {
 
4273
    ConnectionDone(conn); /* the connection is no longer in use */
 
4274
 
4108
4275
    /* remember the most recently used connection */
4109
4276
    data->state.lastconnect = conn->connectindex;
4110
4277
 
4113
4280
          conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
4114
4281
  }
4115
4282
 
 
4283
  *connp = NULL; /* to make the caller of this function better detect that
 
4284
                    this was either closed or handed over to the connection
 
4285
                    cache here, and therefore cannot be used from this point on
 
4286
                 */
 
4287
 
4116
4288
  return result;
4117
4289
}
4118
4290
 
4120
4292
{
4121
4293
  CURLcode result=CURLE_OK;
4122
4294
  struct connectdata *conn = *connp;
4123
 
  struct SessionHandle *data=conn->data;
 
4295
  struct SessionHandle *data = conn->data;
4124
4296
 
4125
4297
  conn->bits.done = FALSE; /* Curl_done() is not called yet */
4126
4298
  conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
4141
4313
      infof(data, "Re-used connection seems dead, get a new one\n");
4142
4314
 
4143
4315
      conn->bits.close = TRUE; /* enforce close of this connection */
4144
 
      result = Curl_done(&conn, result); /* we are so done with this */
 
4316
      result = Curl_done(&conn, result, FALSE); /* we are so done with this */
4145
4317
 
4146
4318
      /* conn may no longer be a good pointer */
4147
4319
 
4193
4365
 
4194
4366
  return result;
4195
4367
}
4196