multi-legacy.c (5600B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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.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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 /* <DESC> 25 * A basic application source code using the multi interface doing two 26 * transfers in parallel without curl_multi_wait/poll. 27 * </DESC> 28 */ 29 30 #include <stdio.h> 31 #include <string.h> 32 33 /* somewhat Unix-specific */ 34 #ifndef _WIN32 35 #include <sys/time.h> 36 #include <unistd.h> 37 #endif 38 39 /* curl stuff */ 40 #include <curl/curl.h> 41 42 /* 43 * Download an HTTP file and upload an FTP file simultaneously. 44 */ 45 46 #define HANDLECOUNT 2 /* Number of simultaneous transfers */ 47 #define HTTP_HANDLE 0 /* Index for the HTTP transfer */ 48 #define FTP_HANDLE 1 /* Index for the FTP transfer */ 49 50 int main(void) 51 { 52 CURL *handles[HANDLECOUNT]; 53 CURLM *multi_handle; 54 55 int still_running = 0; /* keep number of running handles */ 56 int i; 57 58 CURLMsg *msg; /* for picking up messages with the transfer status */ 59 int msgs_left; /* how many messages are left */ 60 61 /* Allocate one curl handle per transfer */ 62 for(i = 0; i < HANDLECOUNT; i++) 63 handles[i] = curl_easy_init(); 64 65 /* set the options (I left out a few, you get the point anyway) */ 66 curl_easy_setopt(handles[HTTP_HANDLE], CURLOPT_URL, "https://example.com"); 67 68 curl_easy_setopt(handles[FTP_HANDLE], CURLOPT_URL, "ftp://example.com"); 69 curl_easy_setopt(handles[FTP_HANDLE], CURLOPT_UPLOAD, 1L); 70 71 /* init a multi stack */ 72 multi_handle = curl_multi_init(); 73 74 /* add the individual transfers */ 75 for(i = 0; i < HANDLECOUNT; i++) 76 curl_multi_add_handle(multi_handle, handles[i]); 77 78 /* we start some action by calling perform right away */ 79 curl_multi_perform(multi_handle, &still_running); 80 81 while(still_running) { 82 struct timeval timeout; 83 int rc; /* select() return code */ 84 CURLMcode mc; /* curl_multi_fdset() return code */ 85 86 fd_set fdread; 87 fd_set fdwrite; 88 fd_set fdexcep; 89 int maxfd = -1; 90 91 long curl_timeo = -1; 92 93 FD_ZERO(&fdread); 94 FD_ZERO(&fdwrite); 95 FD_ZERO(&fdexcep); 96 97 /* set a suitable timeout to play around with */ 98 timeout.tv_sec = 1; 99 timeout.tv_usec = 0; 100 101 curl_multi_timeout(multi_handle, &curl_timeo); 102 if(curl_timeo >= 0) { 103 #if defined(MSDOS) || defined(__AMIGA__) 104 timeout.tv_sec = (time_t)(curl_timeo / 1000); 105 #else 106 timeout.tv_sec = curl_timeo / 1000; 107 #endif 108 if(timeout.tv_sec > 1) 109 timeout.tv_sec = 1; 110 else 111 #if defined(MSDOS) || defined(__AMIGA__) 112 timeout.tv_usec = (time_t)(curl_timeo % 1000) * 1000; 113 #else 114 timeout.tv_usec = (int)(curl_timeo % 1000) * 1000; 115 #endif 116 } 117 118 /* get file descriptors from the transfers */ 119 mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); 120 121 if(mc != CURLM_OK) { 122 fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc); 123 break; 124 } 125 126 /* On success the value of maxfd is guaranteed to be >= -1. We call 127 select(maxfd + 1, ...); specially in case of (maxfd == -1) there are 128 no fds ready yet so we call select(0, ...) --or Sleep() on Windows-- 129 to sleep 100ms, which is the minimum suggested value in the 130 curl_multi_fdset() doc. */ 131 132 if(maxfd == -1) { 133 #ifdef _WIN32 134 Sleep(100); 135 rc = 0; 136 #else 137 /* Portable sleep for platforms other than Windows. */ 138 struct timeval wait = {0}; 139 wait.tv_usec = 100 * 1000; /* 100ms */ 140 rc = select(0, NULL, NULL, NULL, &wait); 141 #endif 142 } 143 else { 144 /* Note that on some platforms 'timeout' may be modified by select(). 145 If you need access to the original value save a copy beforehand. */ 146 rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); 147 } 148 149 switch(rc) { 150 case -1: 151 /* select error */ 152 break; 153 case 0: /* timeout */ 154 default: /* action */ 155 curl_multi_perform(multi_handle, &still_running); 156 break; 157 } 158 } 159 160 /* See how the transfers went */ 161 /* !checksrc! disable EQUALSNULL 1 */ 162 while((msg = curl_multi_info_read(multi_handle, &msgs_left)) != NULL) { 163 if(msg->msg == CURLMSG_DONE) { 164 int idx; 165 166 /* Find out which handle this message is about */ 167 for(idx = 0; idx < HANDLECOUNT; idx++) { 168 int found = (msg->easy_handle == handles[idx]); 169 if(found) 170 break; 171 } 172 173 switch(idx) { 174 case HTTP_HANDLE: 175 printf("HTTP transfer completed with status %d\n", msg->data.result); 176 break; 177 case FTP_HANDLE: 178 printf("FTP transfer completed with status %d\n", msg->data.result); 179 break; 180 } 181 } 182 } 183 184 curl_multi_cleanup(multi_handle); 185 186 /* Free the curl handles */ 187 for(i = 0; i < HANDLECOUNT; i++) 188 curl_easy_cleanup(handles[i]); 189 190 return 0; 191 }