1e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/***************************************************************************
29bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                                  _   _ ____  _
39bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *  Project                     ___| | | |  _ \| |
49bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                             / __| | | | |_) | |
59bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                            | (__| |_| |  _ <| |___
69bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                             \___|\___/|_| \_\_____|
79bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
88f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
99bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
10e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is licensed as described in the file COPYING, which
11e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * you should have received as part of this distribution. The terms
128f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html.
13e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
14e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * copies of the Software, and permit persons to whom the Software is
16e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * furnished to do so, under the terms of the COPYING file.
17e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
18e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * KIND, either express or implied.
20e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
21e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ***************************************************************************/
228f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo/* <DESC>
238f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * using the multi interface to do a multipart formpost without blocking
248f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * </DESC>
258f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo */
268f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo
279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <stdio.h>
289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <string.h>
299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <sys/time.h>
309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <curl/curl.h>
329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
33e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETint main(void)
349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURL *curl;
369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  CURLM *multi_handle;
389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int still_running;
399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  struct curl_httppost *formpost=NULL;
419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  struct curl_httppost *lastptr=NULL;
429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  struct curl_slist *headerlist=NULL;
439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  static const char buf[] = "Expect:";
449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* Fill in the file upload field. This makes libcurl load data from
469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels     the given file name when curl_easy_perform() is called. */
479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_formadd(&formpost,
489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               &lastptr,
499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_COPYNAME, "sendfile",
509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_FILE, "postit2.c",
519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_END);
529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* Fill in the filename field */
549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_formadd(&formpost,
559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               &lastptr,
569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_COPYNAME, "filename",
579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_COPYCONTENTS, "postit2.c",
589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_END);
599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* Fill in the submit field too, even if this is rarely needed */
619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl_formadd(&formpost,
629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               &lastptr,
639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_COPYNAME, "submit",
649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_COPYCONTENTS, "send",
659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels               CURLFORM_END);
669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  curl = curl_easy_init();
689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  multi_handle = curl_multi_init();
699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
70e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  /* initialize custom header list (stating that Expect: 100-continue is not
719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels     wanted */
729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  headerlist = curl_slist_append(headerlist, buf);
739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if(curl && multi_handle) {
749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    /* what URL that receives this POST */
769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com/upload.cgi");
779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_multi_add_handle(multi_handle, curl);
839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_multi_perform(multi_handle, &still_running);
859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
86e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    do {
879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      struct timeval timeout;
889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      int rc; /* select() return code */
89e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      CURLMcode mc; /* curl_multi_fdset() return code */
909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      fd_set fdread;
929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      fd_set fdwrite;
939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      fd_set fdexcep;
949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      int maxfd = -1;
959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      long curl_timeo = -1;
979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      FD_ZERO(&fdread);
999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      FD_ZERO(&fdwrite);
1009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      FD_ZERO(&fdexcep);
1019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      /* set a suitable timeout to play around with */
1039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      timeout.tv_sec = 1;
1049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      timeout.tv_usec = 0;
1059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      curl_multi_timeout(multi_handle, &curl_timeo);
1079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if(curl_timeo >= 0) {
1089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        timeout.tv_sec = curl_timeo / 1000;
1099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        if(timeout.tv_sec > 1)
1109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          timeout.tv_sec = 1;
1119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        else
1129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          timeout.tv_usec = (curl_timeo % 1000) * 1000;
1139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
1149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      /* get file descriptors from the transfers */
116e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
1179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1188f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo      if(mc != CURLM_OK) {
119e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
120e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        break;
121e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
1229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
123e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      /* On success the value of maxfd is guaranteed to be >= -1. We call
124e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET         select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
125e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET         no fds ready yet so we call select(0, ...) --or Sleep() on Windows--
126e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET         to sleep 100ms, which is the minimum suggested value in the
127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET         curl_multi_fdset() doc. */
128e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
129e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(maxfd == -1) {
130e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef _WIN32
131e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        Sleep(100);
132e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        rc = 0;
133e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#else
134e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        /* Portable sleep for platforms other than Windows. */
135e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        struct timeval wait = { 0, 100 * 1000 }; /* 100ms */
136e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        rc = select(0, NULL, NULL, NULL, &wait);
137e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif
138e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
139e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      else {
140e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        /* Note that on some platforms 'timeout' may be modified by select().
141e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET           If you need access to the original value save a copy beforehand. */
142e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
143e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
1449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      switch(rc) {
1469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      case -1:
1479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        /* select error */
1489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        break;
1499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      case 0:
1509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      default:
1519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        /* timeout or readable/writable sockets */
1529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        printf("perform!\n");
1539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        curl_multi_perform(multi_handle, &still_running);
1549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        printf("running: %d!\n", still_running);
1559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        break;
1569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
157e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    } while(still_running);
1589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_multi_cleanup(multi_handle);
1609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    /* always cleanup */
1629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_easy_cleanup(curl);
1639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    /* then cleanup the formpost chain */
1659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_formfree(formpost);
1669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    /* free slist */
1689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    curl_slist_free_all (headerlist);
1699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
1709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return 0;
1719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
172