~ubuntu-branches/ubuntu/jaunty/curl/jaunty-security

« back to all changes in this revision

Viewing changes to lib/multi.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-08-01 12:22:30 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070801122230-uaarmp6lo65py9t6
Tags: 7.16.4-1ubuntu1
* Merge with Debian.
  - Drop debian/patches/gnutls-verifications, applied upstream.
  - Remove all stuff which should be reverted according to 7.16.2-6ubuntu4.
  - Remaining change: drop stunnel build dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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: multi.c,v 1.138 2007-04-10 20:46:40 bagder Exp $
 
21
 * $Id: multi.c,v 1.148 2007-06-26 21:09:28 bagder Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
#include "setup.h"
50
50
/* The last #include file should be: */
51
51
#include "memdebug.h"
52
52
 
 
53
/*
 
54
  CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
 
55
  to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes.  Still, every
 
56
  CURL handle takes 45-50 K memory, therefore this 3K are not significant.
 
57
*/
 
58
#ifndef CURL_SOCKET_HASH_TABLE_SIZE
 
59
#define CURL_SOCKET_HASH_TABLE_SIZE 911
 
60
#endif
 
61
 
53
62
struct Curl_message {
54
63
  /* the 'CURLMsg' is the part that is visible to the external user */
55
64
  struct CURLMsg extmsg;
121
130
#define CURL_MULTI_HANDLE 0x000bab1e
122
131
 
123
132
#define GOOD_MULTI_HANDLE(x) \
124
 
  ((x)&&(((struct Curl_multi *)x)->type == CURL_MULTI_HANDLE))
 
133
  ((x)&&(((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
125
134
#define GOOD_EASY_HANDLE(x) \
126
 
 (((struct SessionHandle *)x)->magic == CURLEASY_MAGIC_NUMBER)
 
135
 (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER)
127
136
 
128
137
/* This is the struct known as CURLM on the outside */
129
138
struct Curl_multi {
160
169
 
161
170
  /* shared connection cache */
162
171
  struct conncache *connc;
 
172
  long maxconnects; /* if >0, a fixed limit of the maximum number of entries
 
173
                       we're allowed to grow the connection cache to */
163
174
 
164
175
  /* list of easy handles kept around for doing nice connection closures */
165
176
  struct closure *closure;
180
191
static int update_timer(struct Curl_multi *multi);
181
192
 
182
193
#ifdef CURLDEBUG
183
 
static const char *statename[]={
 
194
static const char * const statename[]={
184
195
  "INIT",
185
196
  "CONNECT",
186
197
  "WAITRESOLVE",
303
314
  free(p);
304
315
}
305
316
 
 
317
static size_t fd_key_compare(void*k1, size_t k1_len, void*k2, size_t k2_len)
 
318
{
 
319
  (void) k1_len; (void) k2_len;
 
320
 
 
321
  return ((*((int* ) k1)) == (*((int* ) k2))) ? 1 : 0;
 
322
}
 
323
 
 
324
static size_t hash_fd(void* key, size_t key_length, size_t slots_num)
 
325
{
 
326
  int fd = * ((int* ) key);
 
327
  (void) key_length;
 
328
 
 
329
  return (fd % (int)slots_num);
 
330
}
 
331
 
306
332
/*
307
333
 * sh_init() creates a new socket hash and returns the handle for it.
308
334
 *
323
349
 */
324
350
static struct curl_hash *sh_init(void)
325
351
{
326
 
  return Curl_hash_alloc(97, sh_freeentry);
 
352
  return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
 
353
                         sh_freeentry);
327
354
}
328
355
 
329
356
CURLM *curl_multi_init(void)
469
496
  /* make the SessionHandle struct refer back to this struct */
470
497
  easy->easy_handle->set.one_easy = easy;
471
498
 
 
499
  /* Set the timeout for this handle to expire really soon so that it will
 
500
     be taken care of even when this handle is added in the midst of operation
 
501
     when only the curl_multi_socket() API is used. During that flow, only
 
502
     sockets that time-out or have actions will be dealt with. Since this
 
503
     handle has no action yet, we make sure it times out to get things to
 
504
     happen. */
 
505
  Curl_expire(easy->easy_handle, 10);
 
506
 
472
507
  /* increase the node-counter */
473
508
  multi->num_easy++;
474
509
 
476
511
    /* We want the connection cache to have plenty room. Before we supported
477
512
       the shared cache every single easy handle had 5 entries in their cache
478
513
       by default. */
479
 
    CURLcode res = Curl_ch_connc(easy_handle, multi->connc,
480
 
                                 multi->connc->num*4);
481
 
    if(res != CURLE_OK)
482
 
      /* TODO: we need to do some cleaning up here! */
483
 
      return CURLM_OUT_OF_MEMORY;
 
514
    int newmax = multi->num_easy * 4;
 
515
 
 
516
    if(multi->maxconnects && (multi->maxconnects < newmax))
 
517
      /* don't grow beyond the allowed size */
 
518
      newmax = multi->maxconnects;
 
519
 
 
520
    if(newmax > multi->connc->num) {
 
521
      /* we only do this is we can in fact grow the cache */
 
522
      CURLcode res = Curl_ch_connc(easy_handle, multi->connc, newmax);
 
523
      if(res != CURLE_OK)
 
524
        /* TODO: we need to do some cleaning up here! */
 
525
        return CURLM_OUT_OF_MEMORY;
 
526
    }
484
527
  }
485
528
 
486
529
  /* increase the alive-counter */
796
839
  struct Curl_message *msg = NULL;
797
840
  bool connected;
798
841
  bool async;
799
 
  bool protocol_connect;
 
842
  bool protocol_connect = FALSE;
800
843
  bool dophase_done;
801
844
  bool done;
802
845
  CURLMcode result = CURLM_OK;
888
931
 
889
932
      if(CURLE_OK == easy->result) {
890
933
        /* Add this handle to the send pipeline */
891
 
        Curl_addHandleToPipeline(easy->easy_handle,
892
 
                                 easy->easy_conn->send_pipe);
893
 
 
894
 
        if(async)
895
 
          /* We're now waiting for an asynchronous name lookup */
896
 
          multistate(easy, CURLM_STATE_WAITRESOLVE);
897
 
        else {
898
 
          /* after the connect has been sent off, go WAITCONNECT unless the
899
 
             protocol connect is already done and we can go directly to
900
 
             WAITDO! */
901
 
          result = CURLM_CALL_MULTI_PERFORM;
902
 
 
903
 
          if(protocol_connect)
904
 
            multistate(easy, CURLM_STATE_WAITDO);
905
 
          else {
 
934
        easy->result = Curl_addHandleToPipeline(easy->easy_handle,
 
935
                                                easy->easy_conn->send_pipe);
 
936
        if(CURLE_OK == easy->result) {
 
937
          if(async)
 
938
            /* We're now waiting for an asynchronous name lookup */
 
939
            multistate(easy, CURLM_STATE_WAITRESOLVE);
 
940
          else {
 
941
            /* after the connect has been sent off, go WAITCONNECT unless the
 
942
               protocol connect is already done and we can go directly to
 
943
               WAITDO! */
 
944
            result = CURLM_CALL_MULTI_PERFORM;
 
945
 
 
946
            if(protocol_connect)
 
947
              multistate(easy, CURLM_STATE_WAITDO);
 
948
            else {
906
949
#ifndef CURL_DISABLE_HTTP
907
 
            if (easy->easy_conn->bits.tunnel_connecting)
908
 
              multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
909
 
            else
 
950
              if (easy->easy_conn->bits.tunnel_connecting)
 
951
                multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
 
952
              else
910
953
#endif
911
 
              multistate(easy, CURLM_STATE_WAITCONNECT);
912
 
          }
913
 
        }
 
954
                multistate(easy, CURLM_STATE_WAITCONNECT);
 
955
            }
 
956
          }
 
957
        }
914
958
      }
915
959
      break;
916
960
 
988
1032
        if(!protocol_connect) {
989
1033
          /* We have a TCP connection, but 'protocol_connect' may be false
990
1034
             and then we continue to 'STATE_PROTOCONNECT'. If protocol
991
 
             connect is TRUE, we move on to STATE_DO. */
992
 
          multistate(easy, CURLM_STATE_PROTOCONNECT);
 
1035
             connect is TRUE, we move on to STATE_DO.
 
1036
             BUT if we are using a proxy we must change to WAITPROXYCONNECT
 
1037
             */
 
1038
#ifndef CURL_DISABLE_HTTP
 
1039
          if (easy->easy_conn->bits.tunnel_connecting)
 
1040
            multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
 
1041
          else
 
1042
#endif
 
1043
            multistate(easy, CURLM_STATE_PROTOCONNECT);
993
1044
        }
994
1045
        else {
995
1046
          /* after the connect has completed, go WAITDO */
1145
1196
      Curl_removeHandleFromPipeline(easy->easy_handle,
1146
1197
                                    easy->easy_conn->send_pipe);
1147
1198
      /* Add ourselves to the recv pipeline */
1148
 
      Curl_addHandleToPipeline(easy->easy_handle,
1149
 
                               easy->easy_conn->recv_pipe);
 
1199
      easy->result = Curl_addHandleToPipeline(easy->easy_handle,
 
1200
                                              easy->easy_conn->recv_pipe);
1150
1201
      multistate(easy, CURLM_STATE_WAITPERFORM);
1151
1202
      result = CURLM_CALL_MULTI_PERFORM;
1152
1203
 
1385
1436
    multi->num_msgs++; /* increase message counter */
1386
1437
  }
1387
1438
 
 
1439
  if(CURLM_CALL_MULTI_PERFORM == result)
 
1440
    /* Set the timeout for this handle to expire really soon so that it will
 
1441
       be taken care of even when this handle is added in the midst of
 
1442
       operation when only the curl_multi_socket() API is used. During that
 
1443
       flow, only sockets that time-out or have actions will be dealt
 
1444
       with. Since this handle has no action yet, we make sure it times out to
 
1445
       get things to happen. Also, this makes it less important for callers of
 
1446
       the curl_multi_* functions to bother about the CURLM_CALL_MULTI_PERFORM
 
1447
       return code, as long as they deal with the timeouts properly. */
 
1448
    Curl_expire(easy->easy_handle, 10);
 
1449
 
1388
1450
  return result;
1389
1451
}
1390
1452
 
1443
1505
 
1444
1506
  *running_handles = multi->num_alive;
1445
1507
 
1446
 
  if ( CURLM_OK == returncode )
 
1508
  if ( CURLM_OK >= returncode )
1447
1509
    update_timer(multi);
1448
1510
  return returncode;
1449
1511
}
1661
1723
static CURLMcode multi_socket(struct Curl_multi *multi,
1662
1724
                              bool checkall,
1663
1725
                              curl_socket_t s,
 
1726
                              int ev_bitmask,
1664
1727
                              int *running_handles)
1665
1728
{
1666
1729
  CURLMcode result = CURLM_OK;
1698
1761
      /* bad bad bad bad bad bad bad */
1699
1762
      return CURLM_INTERNAL_ERROR;
1700
1763
 
 
1764
    if (data->set.one_easy->easy_conn)  /* set socket event bitmask */
 
1765
      data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
 
1766
 
1701
1767
    result = multi_runsingle(multi, data->set.one_easy);
1702
1768
 
1703
 
    if(result == CURLM_OK)
 
1769
    if (data->set.one_easy->easy_conn)
 
1770
      data->set.one_easy->easy_conn->cselect_bits = 0;
 
1771
 
 
1772
    if(CURLM_OK >= result)
1704
1773
      /* get the socket(s) and check if the state has been changed since
1705
1774
         last */
1706
1775
      singlesocket(multi, data->set.one_easy);
1726
1795
    if(data) {
1727
1796
      result = multi_runsingle(multi, data->set.one_easy);
1728
1797
 
1729
 
      if(result == CURLM_OK)
 
1798
      if(CURLM_OK >= result)
1730
1799
        /* get the socket(s) and check if the state has been changed since
1731
1800
           last */
1732
1801
        singlesocket(multi, data->set.one_easy);
1783
1852
  case CURLMOPT_TIMERDATA:
1784
1853
    multi->timer_userp = va_arg(param, void *);
1785
1854
    break;
 
1855
  case CURLMOPT_MAXCONNECTS:
 
1856
    multi->maxconnects = va_arg(param, long);
 
1857
    break;
1786
1858
  default:
1787
1859
    res = CURLM_UNKNOWN_OPTION;
1788
1860
    break;
1791
1863
  return res;
1792
1864
}
1793
1865
 
 
1866
/* we define curl_multi_socket() in the public multi.h header */
 
1867
#undef curl_multi_socket
1794
1868
 
1795
1869
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
1796
1870
                            int *running_handles)
1797
1871
{
1798
1872
  CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
1799
 
                                  running_handles);
1800
 
  if (CURLM_OK == result)
 
1873
                                  0, running_handles);
 
1874
  if (CURLM_OK >= result)
 
1875
    update_timer((struct Curl_multi *)multi_handle);
 
1876
  return result;
 
1877
}
 
1878
 
 
1879
CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
 
1880
                                     int ev_bitmask, int *running_handles)
 
1881
{
 
1882
  CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
 
1883
                                  ev_bitmask, running_handles);
 
1884
  if (CURLM_OK >= result)
1801
1885
    update_timer((struct Curl_multi *)multi_handle);
1802
1886
  return result;
1803
1887
}
1806
1890
 
1807
1891
{
1808
1892
  CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
1809
 
                                  TRUE, CURL_SOCKET_BAD, running_handles);
1810
 
  if (CURLM_OK == result)
 
1893
                                  TRUE, CURL_SOCKET_BAD, 0, running_handles);
 
1894
  if (CURLM_OK >= result)
1811
1895
    update_timer((struct Curl_multi *)multi_handle);
1812
1896
  return result;
1813
1897
}