File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / easy.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years, 1 month ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: /***************************************************************************
    2:  *                                  _   _ ____  _
    3:  *  Project                     ___| | | |  _ \| |
    4:  *                             / __| | | | |_) | |
    5:  *                            | (__| |_| |  _ <| |___
    6:  *                             \___|\___/|_| \_\_____|
    7:  *
    8:  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
    9:  *
   10:  * This software is licensed as described in the file COPYING, which
   11:  * you should have received as part of this distribution. The terms
   12:  * are also available at https://curl.haxx.se/docs/copyright.html.
   13:  *
   14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
   15:  * copies of the Software, and permit persons to whom the Software is
   16:  * furnished to do so, under the terms of the COPYING file.
   17:  *
   18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
   19:  * KIND, either express or implied.
   20:  *
   21:  ***************************************************************************/
   22: 
   23: #include "curl_setup.h"
   24: 
   25: /*
   26:  * See comment in curl_memory.h for the explanation of this sanity check.
   27:  */
   28: 
   29: #ifdef CURLX_NO_MEMORY_CALLBACKS
   30: #error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined"
   31: #endif
   32: 
   33: #ifdef HAVE_NETINET_IN_H
   34: #include <netinet/in.h>
   35: #endif
   36: #ifdef HAVE_NETDB_H
   37: #include <netdb.h>
   38: #endif
   39: #ifdef HAVE_ARPA_INET_H
   40: #include <arpa/inet.h>
   41: #endif
   42: #ifdef HAVE_NET_IF_H
   43: #include <net/if.h>
   44: #endif
   45: #ifdef HAVE_SYS_IOCTL_H
   46: #include <sys/ioctl.h>
   47: #endif
   48: 
   49: #ifdef HAVE_SYS_PARAM_H
   50: #include <sys/param.h>
   51: #endif
   52: 
   53: #include "urldata.h"
   54: #include <curl/curl.h>
   55: #include "transfer.h"
   56: #include "vtls/vtls.h"
   57: #include "url.h"
   58: #include "getinfo.h"
   59: #include "hostip.h"
   60: #include "share.h"
   61: #include "strdup.h"
   62: #include "progress.h"
   63: #include "easyif.h"
   64: #include "multiif.h"
   65: #include "select.h"
   66: #include "sendf.h" /* for failf function prototype */
   67: #include "connect.h" /* for Curl_getconnectinfo */
   68: #include "slist.h"
   69: #include "mime.h"
   70: #include "amigaos.h"
   71: #include "non-ascii.h"
   72: #include "warnless.h"
   73: #include "multiif.h"
   74: #include "sigpipe.h"
   75: #include "vssh/ssh.h"
   76: #include "setopt.h"
   77: #include "http_digest.h"
   78: #include "system_win32.h"
   79: #include "http2.h"
   80: 
   81: /* The last 3 #include files should be in this order */
   82: #include "curl_printf.h"
   83: #include "curl_memory.h"
   84: #include "memdebug.h"
   85: 
   86: /* true globals -- for curl_global_init() and curl_global_cleanup() */
   87: static unsigned int  initialized;
   88: static long          init_flags;
   89: 
   90: /*
   91:  * strdup (and other memory functions) is redefined in complicated
   92:  * ways, but at this point it must be defined as the system-supplied strdup
   93:  * so the callback pointer is initialized correctly.
   94:  */
   95: #if defined(_WIN32_WCE)
   96: #define system_strdup _strdup
   97: #elif !defined(HAVE_STRDUP)
   98: #define system_strdup curlx_strdup
   99: #else
  100: #define system_strdup strdup
  101: #endif
  102: 
  103: #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
  104: #  pragma warning(disable:4232) /* MSVC extension, dllimport identity */
  105: #endif
  106: 
  107: #ifndef __SYMBIAN32__
  108: /*
  109:  * If a memory-using function (like curl_getenv) is used before
  110:  * curl_global_init() is called, we need to have these pointers set already.
  111:  */
  112: curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
  113: curl_free_callback Curl_cfree = (curl_free_callback)free;
  114: curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
  115: curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
  116: curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
  117: #if defined(WIN32) && defined(UNICODE)
  118: curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
  119: #endif
  120: #else
  121: /*
  122:  * Symbian OS doesn't support initialization to code in writable static data.
  123:  * Initialization will occur in the curl_global_init() call.
  124:  */
  125: curl_malloc_callback Curl_cmalloc;
  126: curl_free_callback Curl_cfree;
  127: curl_realloc_callback Curl_crealloc;
  128: curl_strdup_callback Curl_cstrdup;
  129: curl_calloc_callback Curl_ccalloc;
  130: #endif
  131: 
  132: #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
  133: #  pragma warning(default:4232) /* MSVC extension, dllimport identity */
  134: #endif
  135: 
  136: /**
  137:  * curl_global_init() globally initializes curl given a bitwise set of the
  138:  * different features of what to initialize.
  139:  */
  140: static CURLcode global_init(long flags, bool memoryfuncs)
  141: {
  142:   if(initialized++)
  143:     return CURLE_OK;
  144: 
  145:   if(memoryfuncs) {
  146:     /* Setup the default memory functions here (again) */
  147:     Curl_cmalloc = (curl_malloc_callback)malloc;
  148:     Curl_cfree = (curl_free_callback)free;
  149:     Curl_crealloc = (curl_realloc_callback)realloc;
  150:     Curl_cstrdup = (curl_strdup_callback)system_strdup;
  151:     Curl_ccalloc = (curl_calloc_callback)calloc;
  152: #if defined(WIN32) && defined(UNICODE)
  153:     Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
  154: #endif
  155:   }
  156: 
  157:   if(!Curl_ssl_init()) {
  158:     DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
  159:     goto fail;
  160:   }
  161: 
  162: #ifdef WIN32
  163:   if(Curl_win32_init(flags)) {
  164:     DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
  165:     goto fail;
  166:   }
  167: #endif
  168: 
  169: #ifdef __AMIGA__
  170:   if(!Curl_amiga_init()) {
  171:     DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
  172:     goto fail;
  173:   }
  174: #endif
  175: 
  176: #ifdef NETWARE
  177:   if(netware_init()) {
  178:     DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
  179:   }
  180: #endif
  181: 
  182:   if(Curl_resolver_global_init()) {
  183:     DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
  184:     goto fail;
  185:   }
  186: 
  187: #if defined(USE_SSH)
  188:   if(Curl_ssh_init()) {
  189:     goto fail;
  190:   }
  191: #endif
  192: 
  193: #ifdef USE_WOLFSSH
  194:   if(WS_SUCCESS != wolfSSH_Init()) {
  195:     DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
  196:     return CURLE_FAILED_INIT;
  197:   }
  198: #endif
  199: 
  200:   init_flags = flags;
  201: 
  202:   return CURLE_OK;
  203: 
  204:   fail:
  205:   initialized--; /* undo the increase */
  206:   return CURLE_FAILED_INIT;
  207: }
  208: 
  209: 
  210: /**
  211:  * curl_global_init() globally initializes curl given a bitwise set of the
  212:  * different features of what to initialize.
  213:  */
  214: CURLcode curl_global_init(long flags)
  215: {
  216:   return global_init(flags, TRUE);
  217: }
  218: 
  219: /*
  220:  * curl_global_init_mem() globally initializes curl and also registers the
  221:  * user provided callback routines.
  222:  */
  223: CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
  224:                               curl_free_callback f, curl_realloc_callback r,
  225:                               curl_strdup_callback s, curl_calloc_callback c)
  226: {
  227:   /* Invalid input, return immediately */
  228:   if(!m || !f || !r || !s || !c)
  229:     return CURLE_FAILED_INIT;
  230: 
  231:   if(initialized) {
  232:     /* Already initialized, don't do it again, but bump the variable anyway to
  233:        work like curl_global_init() and require the same amount of cleanup
  234:        calls. */
  235:     initialized++;
  236:     return CURLE_OK;
  237:   }
  238: 
  239:   /* set memory functions before global_init() in case it wants memory
  240:      functions */
  241:   Curl_cmalloc = m;
  242:   Curl_cfree = f;
  243:   Curl_cstrdup = s;
  244:   Curl_crealloc = r;
  245:   Curl_ccalloc = c;
  246: 
  247:   /* Call the actual init function, but without setting */
  248:   return global_init(flags, FALSE);
  249: }
  250: 
  251: /**
  252:  * curl_global_cleanup() globally cleanups curl, uses the value of
  253:  * "init_flags" to determine what needs to be cleaned up and what doesn't.
  254:  */
  255: void curl_global_cleanup(void)
  256: {
  257:   if(!initialized)
  258:     return;
  259: 
  260:   if(--initialized)
  261:     return;
  262: 
  263:   Curl_ssl_cleanup();
  264:   Curl_resolver_global_cleanup();
  265: 
  266: #ifdef WIN32
  267:   Curl_win32_cleanup(init_flags);
  268: #endif
  269: 
  270:   Curl_amiga_cleanup();
  271: 
  272:   Curl_ssh_cleanup();
  273: 
  274: #ifdef USE_WOLFSSH
  275:   (void)wolfSSH_Cleanup();
  276: #endif
  277: 
  278:   init_flags  = 0;
  279: }
  280: 
  281: /*
  282:  * curl_easy_init() is the external interface to alloc, setup and init an
  283:  * easy handle that is returned. If anything goes wrong, NULL is returned.
  284:  */
  285: struct Curl_easy *curl_easy_init(void)
  286: {
  287:   CURLcode result;
  288:   struct Curl_easy *data;
  289: 
  290:   /* Make sure we inited the global SSL stuff */
  291:   if(!initialized) {
  292:     result = curl_global_init(CURL_GLOBAL_DEFAULT);
  293:     if(result) {
  294:       /* something in the global init failed, return nothing */
  295:       DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
  296:       return NULL;
  297:     }
  298:   }
  299: 
  300:   /* We use curl_open() with undefined URL so far */
  301:   result = Curl_open(&data);
  302:   if(result) {
  303:     DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
  304:     return NULL;
  305:   }
  306: 
  307:   return data;
  308: }
  309: 
  310: #ifdef CURLDEBUG
  311: 
  312: struct socketmonitor {
  313:   struct socketmonitor *next; /* the next node in the list or NULL */
  314:   struct pollfd socket; /* socket info of what to monitor */
  315: };
  316: 
  317: struct events {
  318:   long ms;              /* timeout, run the timeout function when reached */
  319:   bool msbump;          /* set TRUE when timeout is set by callback */
  320:   int num_sockets;      /* number of nodes in the monitor list */
  321:   struct socketmonitor *list; /* list of sockets to monitor */
  322:   int running_handles;  /* store the returned number */
  323: };
  324: 
  325: /* events_timer
  326:  *
  327:  * Callback that gets called with a new value when the timeout should be
  328:  * updated.
  329:  */
  330: 
  331: static int events_timer(struct Curl_multi *multi,    /* multi handle */
  332:                         long timeout_ms, /* see above */
  333:                         void *userp)    /* private callback pointer */
  334: {
  335:   struct events *ev = userp;
  336:   (void)multi;
  337:   if(timeout_ms == -1)
  338:     /* timeout removed */
  339:     timeout_ms = 0;
  340:   else if(timeout_ms == 0)
  341:     /* timeout is already reached! */
  342:     timeout_ms = 1; /* trigger asap */
  343: 
  344:   ev->ms = timeout_ms;
  345:   ev->msbump = TRUE;
  346:   return 0;
  347: }
  348: 
  349: 
  350: /* poll2cselect
  351:  *
  352:  * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones
  353:  */
  354: static int poll2cselect(int pollmask)
  355: {
  356:   int omask = 0;
  357:   if(pollmask & POLLIN)
  358:     omask |= CURL_CSELECT_IN;
  359:   if(pollmask & POLLOUT)
  360:     omask |= CURL_CSELECT_OUT;
  361:   if(pollmask & POLLERR)
  362:     omask |= CURL_CSELECT_ERR;
  363:   return omask;
  364: }
  365: 
  366: 
  367: /* socketcb2poll
  368:  *
  369:  * convert from libcurl' CURL_POLL_* bit definitions to poll()'s
  370:  */
  371: static short socketcb2poll(int pollmask)
  372: {
  373:   short omask = 0;
  374:   if(pollmask & CURL_POLL_IN)
  375:     omask |= POLLIN;
  376:   if(pollmask & CURL_POLL_OUT)
  377:     omask |= POLLOUT;
  378:   return omask;
  379: }
  380: 
  381: /* events_socket
  382:  *
  383:  * Callback that gets called with information about socket activity to
  384:  * monitor.
  385:  */
  386: static int events_socket(struct Curl_easy *easy,      /* easy handle */
  387:                          curl_socket_t s, /* socket */
  388:                          int what,        /* see above */
  389:                          void *userp,     /* private callback
  390:                                              pointer */
  391:                          void *socketp)   /* private socket
  392:                                              pointer */
  393: {
  394:   struct events *ev = userp;
  395:   struct socketmonitor *m;
  396:   struct socketmonitor *prev = NULL;
  397: 
  398: #if defined(CURL_DISABLE_VERBOSE_STRINGS)
  399:   (void) easy;
  400: #endif
  401:   (void)socketp;
  402: 
  403:   m = ev->list;
  404:   while(m) {
  405:     if(m->socket.fd == s) {
  406: 
  407:       if(what == CURL_POLL_REMOVE) {
  408:         struct socketmonitor *nxt = m->next;
  409:         /* remove this node from the list of monitored sockets */
  410:         if(prev)
  411:           prev->next = nxt;
  412:         else
  413:           ev->list = nxt;
  414:         free(m);
  415:         m = nxt;
  416:         infof(easy, "socket cb: socket %d REMOVED\n", s);
  417:       }
  418:       else {
  419:         /* The socket 's' is already being monitored, update the activity
  420:            mask. Convert from libcurl bitmask to the poll one. */
  421:         m->socket.events = socketcb2poll(what);
  422:         infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
  423:               (what&CURL_POLL_IN)?"IN":"",
  424:               (what&CURL_POLL_OUT)?"OUT":"");
  425:       }
  426:       break;
  427:     }
  428:     prev = m;
  429:     m = m->next; /* move to next node */
  430:   }
  431:   if(!m) {
  432:     if(what == CURL_POLL_REMOVE) {
  433:       /* this happens a bit too often, libcurl fix perhaps? */
  434:       /* fprintf(stderr,
  435:          "%s: socket %d asked to be REMOVED but not present!\n",
  436:                  __func__, s); */
  437:     }
  438:     else {
  439:       m = malloc(sizeof(struct socketmonitor));
  440:       if(m) {
  441:         m->next = ev->list;
  442:         m->socket.fd = s;
  443:         m->socket.events = socketcb2poll(what);
  444:         m->socket.revents = 0;
  445:         ev->list = m;
  446:         infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
  447:               (what&CURL_POLL_IN)?"IN":"",
  448:               (what&CURL_POLL_OUT)?"OUT":"");
  449:       }
  450:       else
  451:         return CURLE_OUT_OF_MEMORY;
  452:     }
  453:   }
  454: 
  455:   return 0;
  456: }
  457: 
  458: 
  459: /*
  460:  * events_setup()
  461:  *
  462:  * Do the multi handle setups that only event-based transfers need.
  463:  */
  464: static void events_setup(struct Curl_multi *multi, struct events *ev)
  465: {
  466:   /* timer callback */
  467:   curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
  468:   curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
  469: 
  470:   /* socket callback */
  471:   curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
  472:   curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
  473: }
  474: 
  475: 
  476: /* wait_or_timeout()
  477:  *
  478:  * waits for activity on any of the given sockets, or the timeout to trigger.
  479:  */
  480: 
  481: static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
  482: {
  483:   bool done = FALSE;
  484:   CURLMcode mcode = CURLM_OK;
  485:   CURLcode result = CURLE_OK;
  486: 
  487:   while(!done) {
  488:     CURLMsg *msg;
  489:     struct socketmonitor *m;
  490:     struct pollfd *f;
  491:     struct pollfd fds[4];
  492:     int numfds = 0;
  493:     int pollrc;
  494:     int i;
  495:     struct curltime before;
  496:     struct curltime after;
  497: 
  498:     /* populate the fds[] array */
  499:     for(m = ev->list, f = &fds[0]; m; m = m->next) {
  500:       f->fd = m->socket.fd;
  501:       f->events = m->socket.events;
  502:       f->revents = 0;
  503:       /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
  504:       f++;
  505:       numfds++;
  506:     }
  507: 
  508:     /* get the time stamp to use to figure out how long poll takes */
  509:     before = Curl_now();
  510: 
  511:     /* wait for activity or timeout */
  512:     pollrc = Curl_poll(fds, numfds, (int)ev->ms);
  513: 
  514:     after = Curl_now();
  515: 
  516:     ev->msbump = FALSE; /* reset here */
  517: 
  518:     if(0 == pollrc) {
  519:       /* timeout! */
  520:       ev->ms = 0;
  521:       /* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */
  522:       mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
  523:                                        &ev->running_handles);
  524:     }
  525:     else if(pollrc > 0) {
  526:       /* loop over the monitored sockets to see which ones had activity */
  527:       for(i = 0; i< numfds; i++) {
  528:         if(fds[i].revents) {
  529:           /* socket activity, tell libcurl */
  530:           int act = poll2cselect(fds[i].revents); /* convert */
  531:           infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n",
  532:                 fds[i].fd);
  533:           mcode = curl_multi_socket_action(multi, fds[i].fd, act,
  534:                                            &ev->running_handles);
  535:         }
  536:       }
  537: 
  538:       if(!ev->msbump) {
  539:         /* If nothing updated the timeout, we decrease it by the spent time.
  540:          * If it was updated, it has the new timeout time stored already.
  541:          */
  542:         timediff_t timediff = Curl_timediff(after, before);
  543:         if(timediff > 0) {
  544:           if(timediff > ev->ms)
  545:             ev->ms = 0;
  546:           else
  547:             ev->ms -= (long)timediff;
  548:         }
  549:       }
  550:     }
  551:     else
  552:       return CURLE_RECV_ERROR;
  553: 
  554:     if(mcode)
  555:       return CURLE_URL_MALFORMAT;
  556: 
  557:     /* we don't really care about the "msgs_in_queue" value returned in the
  558:        second argument */
  559:     msg = curl_multi_info_read(multi, &pollrc);
  560:     if(msg) {
  561:       result = msg->data.result;
  562:       done = TRUE;
  563:     }
  564:   }
  565: 
  566:   return result;
  567: }
  568: 
  569: 
  570: /* easy_events()
  571:  *
  572:  * Runs a transfer in a blocking manner using the events-based API
  573:  */
  574: static CURLcode easy_events(struct Curl_multi *multi)
  575: {
  576:   /* this struct is made static to allow it to be used after this function
  577:      returns and curl_multi_remove_handle() is called */
  578:   static struct events evs = {2, FALSE, 0, NULL, 0};
  579: 
  580:   /* if running event-based, do some further multi inits */
  581:   events_setup(multi, &evs);
  582: 
  583:   return wait_or_timeout(multi, &evs);
  584: }
  585: #else /* CURLDEBUG */
  586: /* when not built with debug, this function doesn't exist */
  587: #define easy_events(x) CURLE_NOT_BUILT_IN
  588: #endif
  589: 
  590: static CURLcode easy_transfer(struct Curl_multi *multi)
  591: {
  592:   bool done = FALSE;
  593:   CURLMcode mcode = CURLM_OK;
  594:   CURLcode result = CURLE_OK;
  595: 
  596:   while(!done && !mcode) {
  597:     int still_running = 0;
  598: 
  599:     mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL);
  600: 
  601:     if(!mcode)
  602:       mcode = curl_multi_perform(multi, &still_running);
  603: 
  604:     /* only read 'still_running' if curl_multi_perform() return OK */
  605:     if(!mcode && !still_running) {
  606:       int rc;
  607:       CURLMsg *msg = curl_multi_info_read(multi, &rc);
  608:       if(msg) {
  609:         result = msg->data.result;
  610:         done = TRUE;
  611:       }
  612:     }
  613:   }
  614: 
  615:   /* Make sure to return some kind of error if there was a multi problem */
  616:   if(mcode) {
  617:     result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
  618:               /* The other multi errors should never happen, so return
  619:                  something suitably generic */
  620:               CURLE_BAD_FUNCTION_ARGUMENT;
  621:   }
  622: 
  623:   return result;
  624: }
  625: 
  626: 
  627: /*
  628:  * easy_perform() is the external interface that performs a blocking
  629:  * transfer as previously setup.
  630:  *
  631:  * CONCEPT: This function creates a multi handle, adds the easy handle to it,
  632:  * runs curl_multi_perform() until the transfer is done, then detaches the
  633:  * easy handle, destroys the multi handle and returns the easy handle's return
  634:  * code.
  635:  *
  636:  * REALITY: it can't just create and destroy the multi handle that easily. It
  637:  * needs to keep it around since if this easy handle is used again by this
  638:  * function, the same multi handle must be re-used so that the same pools and
  639:  * caches can be used.
  640:  *
  641:  * DEBUG: if 'events' is set TRUE, this function will use a replacement engine
  642:  * instead of curl_multi_perform() and use curl_multi_socket_action().
  643:  */
  644: static CURLcode easy_perform(struct Curl_easy *data, bool events)
  645: {
  646:   struct Curl_multi *multi;
  647:   CURLMcode mcode;
  648:   CURLcode result = CURLE_OK;
  649:   SIGPIPE_VARIABLE(pipe_st);
  650: 
  651:   if(!data)
  652:     return CURLE_BAD_FUNCTION_ARGUMENT;
  653: 
  654:   if(data->set.errorbuffer)
  655:     /* clear this as early as possible */
  656:     data->set.errorbuffer[0] = 0;
  657: 
  658:   if(data->multi) {
  659:     failf(data, "easy handle already used in multi handle");
  660:     return CURLE_FAILED_INIT;
  661:   }
  662: 
  663:   if(data->multi_easy)
  664:     multi = data->multi_easy;
  665:   else {
  666:     /* this multi handle will only ever have a single easy handled attached
  667:        to it, so make it use minimal hashes */
  668:     multi = Curl_multi_handle(1, 3);
  669:     if(!multi)
  670:       return CURLE_OUT_OF_MEMORY;
  671:     data->multi_easy = multi;
  672:   }
  673: 
  674:   if(multi->in_callback)
  675:     return CURLE_RECURSIVE_API_CALL;
  676: 
  677:   /* Copy the MAXCONNECTS option to the multi handle */
  678:   curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
  679: 
  680:   mcode = curl_multi_add_handle(multi, data);
  681:   if(mcode) {
  682:     curl_multi_cleanup(multi);
  683:     if(mcode == CURLM_OUT_OF_MEMORY)
  684:       return CURLE_OUT_OF_MEMORY;
  685:     return CURLE_FAILED_INIT;
  686:   }
  687: 
  688:   sigpipe_ignore(data, &pipe_st);
  689: 
  690:   /* run the transfer */
  691:   result = events ? easy_events(multi) : easy_transfer(multi);
  692: 
  693:   /* ignoring the return code isn't nice, but atm we can't really handle
  694:      a failure here, room for future improvement! */
  695:   (void)curl_multi_remove_handle(multi, data);
  696: 
  697:   sigpipe_restore(&pipe_st);
  698: 
  699:   /* The multi handle is kept alive, owned by the easy handle */
  700:   return result;
  701: }
  702: 
  703: 
  704: /*
  705:  * curl_easy_perform() is the external interface that performs a blocking
  706:  * transfer as previously setup.
  707:  */
  708: CURLcode curl_easy_perform(struct Curl_easy *data)
  709: {
  710:   return easy_perform(data, FALSE);
  711: }
  712: 
  713: #ifdef CURLDEBUG
  714: /*
  715:  * curl_easy_perform_ev() is the external interface that performs a blocking
  716:  * transfer using the event-based API internally.
  717:  */
  718: CURLcode curl_easy_perform_ev(struct Curl_easy *data)
  719: {
  720:   return easy_perform(data, TRUE);
  721: }
  722: 
  723: #endif
  724: 
  725: /*
  726:  * curl_easy_cleanup() is the external interface to cleaning/freeing the given
  727:  * easy handle.
  728:  */
  729: void curl_easy_cleanup(struct Curl_easy *data)
  730: {
  731:   SIGPIPE_VARIABLE(pipe_st);
  732: 
  733:   if(!data)
  734:     return;
  735: 
  736:   sigpipe_ignore(data, &pipe_st);
  737:   Curl_close(&data);
  738:   sigpipe_restore(&pipe_st);
  739: }
  740: 
  741: /*
  742:  * curl_easy_getinfo() is an external interface that allows an app to retrieve
  743:  * information from a performed transfer and similar.
  744:  */
  745: #undef curl_easy_getinfo
  746: CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...)
  747: {
  748:   va_list arg;
  749:   void *paramp;
  750:   CURLcode result;
  751: 
  752:   va_start(arg, info);
  753:   paramp = va_arg(arg, void *);
  754: 
  755:   result = Curl_getinfo(data, info, paramp);
  756: 
  757:   va_end(arg);
  758:   return result;
  759: }
  760: 
  761: static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
  762: {
  763:   CURLcode result = CURLE_OK;
  764:   enum dupstring i;
  765: 
  766:   /* Copy src->set into dst->set first, then deal with the strings
  767:      afterwards */
  768:   dst->set = src->set;
  769:   Curl_mime_initpart(&dst->set.mimepost, dst);
  770: 
  771:   /* clear all string pointers first */
  772:   memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
  773: 
  774:   /* duplicate all strings */
  775:   for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
  776:     result = Curl_setstropt(&dst->set.str[i], src->set.str[i]);
  777:     if(result)
  778:       return result;
  779:   }
  780: 
  781:   /* duplicate memory areas pointed to */
  782:   i = STRING_COPYPOSTFIELDS;
  783:   if(src->set.postfieldsize && src->set.str[i]) {
  784:     /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
  785:     dst->set.str[i] = Curl_memdup(src->set.str[i],
  786:                                   curlx_sotouz(src->set.postfieldsize));
  787:     if(!dst->set.str[i])
  788:       return CURLE_OUT_OF_MEMORY;
  789:     /* point to the new copy */
  790:     dst->set.postfields = dst->set.str[i];
  791:   }
  792: 
  793:   /* Duplicate mime data. */
  794:   result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
  795: 
  796:   if(src->set.resolve)
  797:     dst->change.resolve = dst->set.resolve;
  798: 
  799:   return result;
  800: }
  801: 
  802: /*
  803:  * curl_easy_duphandle() is an external interface to allow duplication of a
  804:  * given input easy handle. The returned handle will be a new working handle
  805:  * with all options set exactly as the input source handle.
  806:  */
  807: struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
  808: {
  809:   struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy));
  810:   if(NULL == outcurl)
  811:     goto fail;
  812: 
  813:   /*
  814:    * We setup a few buffers we need. We should probably make them
  815:    * get setup on-demand in the code, as that would probably decrease
  816:    * the likeliness of us forgetting to init a buffer here in the future.
  817:    */
  818:   outcurl->set.buffer_size = data->set.buffer_size;
  819:   outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1);
  820:   if(!outcurl->state.buffer)
  821:     goto fail;
  822: 
  823:   outcurl->state.headerbuff = malloc(HEADERSIZE);
  824:   if(!outcurl->state.headerbuff)
  825:     goto fail;
  826:   outcurl->state.headersize = HEADERSIZE;
  827: 
  828:   /* copy all userdefined values */
  829:   if(dupset(outcurl, data))
  830:     goto fail;
  831: 
  832:   /* the connection cache is setup on demand */
  833:   outcurl->state.conn_cache = NULL;
  834: 
  835:   outcurl->state.lastconnect = NULL;
  836: 
  837:   outcurl->progress.flags    = data->progress.flags;
  838:   outcurl->progress.callback = data->progress.callback;
  839: 
  840:   if(data->cookies) {
  841:     /* If cookies are enabled in the parent handle, we enable them
  842:        in the clone as well! */
  843:     outcurl->cookies = Curl_cookie_init(data,
  844:                                         data->cookies->filename,
  845:                                         outcurl->cookies,
  846:                                         data->set.cookiesession);
  847:     if(!outcurl->cookies)
  848:       goto fail;
  849:   }
  850: 
  851:   /* duplicate all values in 'change' */
  852:   if(data->change.cookielist) {
  853:     outcurl->change.cookielist =
  854:       Curl_slist_duplicate(data->change.cookielist);
  855:     if(!outcurl->change.cookielist)
  856:       goto fail;
  857:   }
  858: 
  859:   if(data->change.url) {
  860:     outcurl->change.url = strdup(data->change.url);
  861:     if(!outcurl->change.url)
  862:       goto fail;
  863:     outcurl->change.url_alloc = TRUE;
  864:   }
  865: 
  866:   if(data->change.referer) {
  867:     outcurl->change.referer = strdup(data->change.referer);
  868:     if(!outcurl->change.referer)
  869:       goto fail;
  870:     outcurl->change.referer_alloc = TRUE;
  871:   }
  872: 
  873:   /* Reinitialize an SSL engine for the new handle
  874:    * note: the engine name has already been copied by dupset */
  875:   if(outcurl->set.str[STRING_SSL_ENGINE]) {
  876:     if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE]))
  877:       goto fail;
  878:   }
  879: 
  880:   /* Clone the resolver handle, if present, for the new handle */
  881:   if(Curl_resolver_duphandle(outcurl,
  882:                              &outcurl->state.resolver,
  883:                              data->state.resolver))
  884:     goto fail;
  885: 
  886: #ifdef USE_ARES
  887:   {
  888:     CURLcode rc;
  889: 
  890:     rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]);
  891:     if(rc && rc != CURLE_NOT_BUILT_IN)
  892:       goto fail;
  893: 
  894:     rc = Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]);
  895:     if(rc && rc != CURLE_NOT_BUILT_IN)
  896:       goto fail;
  897: 
  898:     rc = Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]);
  899:     if(rc && rc != CURLE_NOT_BUILT_IN)
  900:       goto fail;
  901: 
  902:     rc = Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]);
  903:     if(rc && rc != CURLE_NOT_BUILT_IN)
  904:       goto fail;
  905:   }
  906: #endif /* USE_ARES */
  907: 
  908:   Curl_convert_setup(outcurl);
  909: 
  910:   Curl_initinfo(outcurl);
  911: 
  912:   outcurl->magic = CURLEASY_MAGIC_NUMBER;
  913: 
  914:   /* we reach this point and thus we are OK */
  915: 
  916:   return outcurl;
  917: 
  918:   fail:
  919: 
  920:   if(outcurl) {
  921:     curl_slist_free_all(outcurl->change.cookielist);
  922:     outcurl->change.cookielist = NULL;
  923:     Curl_safefree(outcurl->state.buffer);
  924:     Curl_safefree(outcurl->state.headerbuff);
  925:     Curl_safefree(outcurl->change.url);
  926:     Curl_safefree(outcurl->change.referer);
  927:     Curl_freeset(outcurl);
  928:     free(outcurl);
  929:   }
  930: 
  931:   return NULL;
  932: }
  933: 
  934: /*
  935:  * curl_easy_reset() is an external interface that allows an app to re-
  936:  * initialize a session handle to the default values.
  937:  */
  938: void curl_easy_reset(struct Curl_easy *data)
  939: {
  940:   long old_buffer_size = data->set.buffer_size;
  941: 
  942:   Curl_free_request_state(data);
  943: 
  944:   /* zero out UserDefined data: */
  945:   Curl_freeset(data);
  946:   memset(&data->set, 0, sizeof(struct UserDefined));
  947:   (void)Curl_init_userdefined(data);
  948: 
  949:   /* zero out Progress data: */
  950:   memset(&data->progress, 0, sizeof(struct Progress));
  951: 
  952:   /* zero out PureInfo data: */
  953:   Curl_initinfo(data);
  954: 
  955:   data->progress.flags |= PGRS_HIDE;
  956:   data->state.current_speed = -1; /* init to negative == impossible */
  957: 
  958:   /* zero out authentication data: */
  959:   memset(&data->state.authhost, 0, sizeof(struct auth));
  960:   memset(&data->state.authproxy, 0, sizeof(struct auth));
  961: 
  962: #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
  963:   Curl_http_auth_cleanup_digest(data);
  964: #endif
  965: 
  966:   /* resize receive buffer */
  967:   if(old_buffer_size != data->set.buffer_size) {
  968:     char *newbuff = realloc(data->state.buffer, data->set.buffer_size + 1);
  969:     if(!newbuff) {
  970:       DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
  971:       /* nothing we can do here except use the old size */
  972:       data->set.buffer_size = old_buffer_size;
  973:     }
  974:     else
  975:       data->state.buffer = newbuff;
  976:   }
  977: }
  978: 
  979: /*
  980:  * curl_easy_pause() allows an application to pause or unpause a specific
  981:  * transfer and direction. This function sets the full new state for the
  982:  * current connection this easy handle operates on.
  983:  *
  984:  * NOTE: if you have the receiving paused and you call this function to remove
  985:  * the pausing, you may get your write callback called at this point.
  986:  *
  987:  * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
  988:  *
  989:  * NOTE: This is one of few API functions that are allowed to be called from
  990:  * within a callback.
  991:  */
  992: CURLcode curl_easy_pause(struct Curl_easy *data, int action)
  993: {
  994:   struct SingleRequest *k;
  995:   CURLcode result = CURLE_OK;
  996:   int oldstate;
  997:   int newstate;
  998: 
  999:   if(!GOOD_EASY_HANDLE(data) || !data->conn)
 1000:     /* crazy input, don't continue */
 1001:     return CURLE_BAD_FUNCTION_ARGUMENT;
 1002: 
 1003:   k = &data->req;
 1004:   oldstate = k->keepon & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
 1005: 
 1006:   /* first switch off both pause bits then set the new pause bits */
 1007:   newstate = (k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) |
 1008:     ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
 1009:     ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
 1010: 
 1011:   if((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) == oldstate) {
 1012:     /* Not changing any pause state, return */
 1013:     DEBUGF(infof(data, "pause: no change, early return\n"));
 1014:     return CURLE_OK;
 1015:   }
 1016: 
 1017:   /* Unpause parts in active mime tree. */
 1018:   if((k->keepon & ~newstate & KEEP_SEND_PAUSE) &&
 1019:      (data->mstate == CURLM_STATE_PERFORM ||
 1020:       data->mstate == CURLM_STATE_TOOFAST) &&
 1021:      data->state.fread_func == (curl_read_callback) Curl_mime_read) {
 1022:     Curl_mime_unpause(data->state.in);
 1023:   }
 1024: 
 1025:   /* put it back in the keepon */
 1026:   k->keepon = newstate;
 1027: 
 1028:   if(!(newstate & KEEP_RECV_PAUSE)) {
 1029:     Curl_http2_stream_pause(data, FALSE);
 1030: 
 1031:     if(data->state.tempcount) {
 1032:       /* there are buffers for sending that can be delivered as the receive
 1033:          pausing is lifted! */
 1034:       unsigned int i;
 1035:       unsigned int count = data->state.tempcount;
 1036:       struct tempbuf writebuf[3]; /* there can only be three */
 1037:       struct connectdata *conn = data->conn;
 1038:       struct Curl_easy *saved_data = NULL;
 1039: 
 1040:       /* copy the structs to allow for immediate re-pausing */
 1041:       for(i = 0; i < data->state.tempcount; i++) {
 1042:         writebuf[i] = data->state.tempwrite[i];
 1043:         data->state.tempwrite[i].buf = NULL;
 1044:       }
 1045:       data->state.tempcount = 0;
 1046: 
 1047:       /* set the connection's current owner */
 1048:       if(conn->data != data) {
 1049:         saved_data = conn->data;
 1050:         conn->data = data;
 1051:       }
 1052: 
 1053:       for(i = 0; i < count; i++) {
 1054:         /* even if one function returns error, this loops through and frees
 1055:            all buffers */
 1056:         if(!result)
 1057:           result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
 1058:                                      writebuf[i].len);
 1059:         free(writebuf[i].buf);
 1060:       }
 1061: 
 1062:       /* recover previous owner of the connection */
 1063:       if(saved_data)
 1064:         conn->data = saved_data;
 1065: 
 1066:       if(result)
 1067:         return result;
 1068:     }
 1069:   }
 1070: 
 1071:   /* if there's no error and we're not pausing both directions, we want
 1072:      to have this handle checked soon */
 1073:   if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
 1074:      (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
 1075:     Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
 1076: 
 1077:     /* force a recv/send check of this connection, as the data might've been
 1078:        read off the socket already */
 1079:     data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
 1080:     if(data->multi)
 1081:       Curl_update_timer(data->multi);
 1082:   }
 1083: 
 1084:   if(!data->state.done)
 1085:     /* This transfer may have been moved in or out of the bundle, update the
 1086:        corresponding socket callback, if used */
 1087:     Curl_updatesocket(data);
 1088: 
 1089:   return result;
 1090: }
 1091: 
 1092: 
 1093: static CURLcode easy_connection(struct Curl_easy *data,
 1094:                                 curl_socket_t *sfd,
 1095:                                 struct connectdata **connp)
 1096: {
 1097:   if(data == NULL)
 1098:     return CURLE_BAD_FUNCTION_ARGUMENT;
 1099: 
 1100:   /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
 1101:   if(!data->set.connect_only) {
 1102:     failf(data, "CONNECT_ONLY is required!");
 1103:     return CURLE_UNSUPPORTED_PROTOCOL;
 1104:   }
 1105: 
 1106:   *sfd = Curl_getconnectinfo(data, connp);
 1107: 
 1108:   if(*sfd == CURL_SOCKET_BAD) {
 1109:     failf(data, "Failed to get recent socket");
 1110:     return CURLE_UNSUPPORTED_PROTOCOL;
 1111:   }
 1112: 
 1113:   return CURLE_OK;
 1114: }
 1115: 
 1116: /*
 1117:  * Receives data from the connected socket. Use after successful
 1118:  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
 1119:  * Returns CURLE_OK on success, error code on error.
 1120:  */
 1121: CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
 1122:                         size_t *n)
 1123: {
 1124:   curl_socket_t sfd;
 1125:   CURLcode result;
 1126:   ssize_t n1;
 1127:   struct connectdata *c;
 1128: 
 1129:   if(Curl_is_in_callback(data))
 1130:     return CURLE_RECURSIVE_API_CALL;
 1131: 
 1132:   result = easy_connection(data, &sfd, &c);
 1133:   if(result)
 1134:     return result;
 1135: 
 1136:   *n = 0;
 1137:   result = Curl_read(c, sfd, buffer, buflen, &n1);
 1138: 
 1139:   if(result)
 1140:     return result;
 1141: 
 1142:   *n = (size_t)n1;
 1143: 
 1144:   return CURLE_OK;
 1145: }
 1146: 
 1147: /*
 1148:  * Sends data over the connected socket. Use after successful
 1149:  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
 1150:  */
 1151: CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
 1152:                         size_t buflen, size_t *n)
 1153: {
 1154:   curl_socket_t sfd;
 1155:   CURLcode result;
 1156:   ssize_t n1;
 1157:   struct connectdata *c = NULL;
 1158: 
 1159:   if(Curl_is_in_callback(data))
 1160:     return CURLE_RECURSIVE_API_CALL;
 1161: 
 1162:   result = easy_connection(data, &sfd, &c);
 1163:   if(result)
 1164:     return result;
 1165: 
 1166:   *n = 0;
 1167:   result = Curl_write(c, sfd, buffer, buflen, &n1);
 1168: 
 1169:   if(n1 == -1)
 1170:     return CURLE_SEND_ERROR;
 1171: 
 1172:   /* detect EAGAIN */
 1173:   if(!result && !n1)
 1174:     return CURLE_AGAIN;
 1175: 
 1176:   *n = (size_t)n1;
 1177: 
 1178:   return result;
 1179: }
 1180: 
 1181: /*
 1182:  * Wrapper to call functions in Curl_conncache_foreach()
 1183:  *
 1184:  * Returns always 0.
 1185:  */
 1186: static int conn_upkeep(struct connectdata *conn,
 1187:                        void *param)
 1188: {
 1189:   /* Param is unused. */
 1190:   (void)param;
 1191: 
 1192:   if(conn->handler->connection_check) {
 1193:     /* Do a protocol-specific keepalive check on the connection. */
 1194:     conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
 1195:   }
 1196: 
 1197:   return 0; /* continue iteration */
 1198: }
 1199: 
 1200: static CURLcode upkeep(struct conncache *conn_cache, void *data)
 1201: {
 1202:   /* Loop over every connection and make connection alive. */
 1203:   Curl_conncache_foreach(data,
 1204:                          conn_cache,
 1205:                          data,
 1206:                          conn_upkeep);
 1207:   return CURLE_OK;
 1208: }
 1209: 
 1210: /*
 1211:  * Performs connection upkeep for the given session handle.
 1212:  */
 1213: CURLcode curl_easy_upkeep(struct Curl_easy *data)
 1214: {
 1215:   /* Verify that we got an easy handle we can work with. */
 1216:   if(!GOOD_EASY_HANDLE(data))
 1217:     return CURLE_BAD_FUNCTION_ARGUMENT;
 1218: 
 1219:   if(data->multi_easy) {
 1220:     /* Use the common function to keep connections alive. */
 1221:     return upkeep(&data->multi_easy->conn_cache, data);
 1222:   }
 1223:   else {
 1224:     /* No connections, so just return success */
 1225:     return CURLE_OK;
 1226:   }
 1227: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>