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