int test(char *URL) { CURL *easy = NULL; CURLM *multi = NULL; int res = 0; int running; int msgs_left; int phase; CURLMsg *msg; start_test_timing(); res_global_init(CURL_GLOBAL_ALL); if(res) { return res; } easy_init(easy); multi_init(multi); for (phase = CONNECT_ONLY_PHASE; phase < LAST_PHASE; ++phase) { /* go verbose */ easy_setopt(easy, CURLOPT_VERBOSE, 1L); /* specify target */ easy_setopt(easy, CURLOPT_URL, URL); /* enable 'CONNECT_ONLY' option when in connect phase */ if (phase == CONNECT_ONLY_PHASE) easy_setopt(easy, CURLOPT_CONNECT_ONLY, 1L); /* enable 'NOBODY' option to send 'QUIT' command in quit phase */ if (phase == QUIT_PHASE) { easy_setopt(easy, CURLOPT_CONNECT_ONLY, 0L); easy_setopt(easy, CURLOPT_NOBODY, 1L); easy_setopt(easy, CURLOPT_FORBID_REUSE, 1L); } multi_add_handle(multi, easy); for(;;) { struct timeval interval; fd_set fdread; fd_set fdwrite; fd_set fdexcep; long timeout = -99; int maxfd = -99; multi_perform(multi, &running); abort_on_test_timeout(); if(!running) break; /* done */ FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); /* At this point, maxfd is guaranteed to be greater or equal than -1. */ multi_timeout(multi, &timeout); /* At this point, timeout is guaranteed to be greater or equal than -1. */ if(timeout != -1L) { int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; interval.tv_sec = itimeout/1000; interval.tv_usec = (itimeout%1000)*1000; } else { interval.tv_sec = TEST_HANG_TIMEOUT/1000+1; interval.tv_usec = 0; } select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval); abort_on_test_timeout(); } msg = curl_multi_info_read(multi, &msgs_left); if(msg) res = msg->data.result; multi_remove_handle(multi, easy); } test_cleanup: /* undocumented cleanup sequence - type UA */ curl_multi_cleanup(multi); curl_easy_cleanup(easy); curl_global_cleanup(); return res; }
int test(char *URL) { CURL *easy = NULL; CURLM *multi = NULL; int res = 0; int running; int msgs_left; CURLMsg *msg; FILE *upload = NULL; int error; start_test_timing(); upload = fopen(libtest_arg3, "rb"); if(!upload) { error = ERRNO; fprintf(stderr, "fopen() failed with error: %d (%s)\n", error, strerror(error)); fprintf(stderr, "Error opening file: (%s)\n", libtest_arg3); return TEST_ERR_FOPEN; } res_global_init(CURL_GLOBAL_ALL); if(res) { fclose(upload); return res; } easy_init(easy); /* go verbose */ easy_setopt(easy, CURLOPT_VERBOSE, 1L); /* specify target */ easy_setopt(easy, CURLOPT_URL, URL); /* enable uploading */ easy_setopt(easy, CURLOPT_UPLOAD, 1L); /* data pointer for the file read function */ easy_setopt(easy, CURLOPT_READDATA, upload); /* use active mode FTP */ easy_setopt(easy, CURLOPT_FTPPORT, "-"); /* server connection timeout */ easy_setopt(easy, CURLOPT_ACCEPTTIMEOUT_MS, strtol(libtest_arg2, NULL, 10)*1000); multi_init(multi); multi_add_handle(multi, easy); for(;;) { struct timeval interval; fd_set fdread; fd_set fdwrite; fd_set fdexcep; long timeout = -99; int maxfd = -99; multi_perform(multi, &running); abort_on_test_timeout(); if(!running) break; /* done */ FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); /* At this point, maxfd is guaranteed to be greater or equal than -1. */ multi_timeout(multi, &timeout); /* At this point, timeout is guaranteed to be greater or equal than -1. */ if(timeout != -1L) { int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; interval.tv_sec = itimeout/1000; interval.tv_usec = (itimeout%1000)*1000; } else { interval.tv_sec = 0; interval.tv_usec = 100000L; /* 100 ms */ } select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval); abort_on_test_timeout(); } msg = curl_multi_info_read(multi, &msgs_left); if(msg) res = msg->data.result; test_cleanup: /* undocumented cleanup sequence - type UA */ curl_multi_cleanup(multi); curl_easy_cleanup(easy); curl_global_cleanup(); /* close the local file */ fclose(upload); return res; }
int test(char *url) { CURLM *multi = NULL; int running; int i, j; int num_handles = 0; enum HandleState state = ReadyForNewHandle; size_t urllen = strlen(url) + 4 + 1; char* full_url = malloc(urllen); start_test_timing(); if(!full_url) { fprintf(stderr, "Not enough memory for full url\n"); return TEST_ERR_MAJOR_BAD; } for(i = 0; i < MAX_EASY_HANDLES; ++i) { easy[i] = NULL; sockets[i] = CURL_SOCKET_BAD; } res_global_init(CURL_GLOBAL_ALL); if(res) { free(full_url); return res; } multi_init(multi); #ifdef USE_PIPELINING multi_setopt(multi, CURLMOPT_PIPELINING, 1L); multi_setopt(multi, CURLMOPT_MAX_HOST_CONNECTIONS, 5L); multi_setopt(multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, 10L); #endif for(;;) { struct timeval interval; fd_set fdread; fd_set fdwrite; fd_set fdexcep; long timeout = -99; int maxfd = -99; bool found_new_socket = FALSE; /* Start a new handle if we aren't at the max */ if(state == ReadyForNewHandle) { easy_init(easy[num_handles]); if(num_handles % 3 == 2) { snprintf(full_url, urllen, "%s0200", url); easy_setopt(easy[num_handles], CURLOPT_HTTPAUTH, CURLAUTH_NTLM); } else { snprintf(full_url, urllen, "%s0100", url); easy_setopt(easy[num_handles], CURLOPT_HTTPAUTH, CURLAUTH_BASIC); } easy_setopt(easy[num_handles], CURLOPT_FRESH_CONNECT, 1L); easy_setopt(easy[num_handles], CURLOPT_URL, full_url); easy_setopt(easy[num_handles], CURLOPT_VERBOSE, 1L); easy_setopt(easy[num_handles], CURLOPT_HTTPGET, 1L); easy_setopt(easy[num_handles], CURLOPT_USERPWD, "testuser:testpass"); easy_setopt(easy[num_handles], CURLOPT_WRITEFUNCTION, callback); easy_setopt(easy[num_handles], CURLOPT_WRITEDATA, easy + num_handles); easy_setopt(easy[num_handles], CURLOPT_HEADER, 1L); multi_add_handle(multi, easy[num_handles]); num_handles += 1; state = NeedSocketForNewHandle; } multi_perform(multi, &running); abort_on_test_timeout(); if(!running && state == NoMoreHandles) break; /* done */ FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); /* At this point, maxfd is guaranteed to be greater or equal than -1. */ /* Any socket which is new in fdread is associated with the new handle */ for(i = 0; i <= maxfd; ++i) { bool socket_exists = FALSE; curl_socket_t curfd = (curl_socket_t)i; if(!FD_ISSET(curfd, &fdread)) { continue; } /* Check if this socket was already detected for an earlier handle (or for this handle, num_handles-1, in the callback */ for(j = 0; j < num_handles; ++j) { if(sockets[j] == curfd) { socket_exists = TRUE; break; } } if(socket_exists) { continue; } if(found_new_socket || state != NeedSocketForNewHandle) { fprintf(stderr, "Unexpected new socket\n"); res = TEST_ERR_MAJOR_BAD; goto test_cleanup; } /* Now we know the socket is for the most recent handle, num_handles-1 */ if(sockets[num_handles-1] != CURL_SOCKET_BAD) { /* A socket for this handle was already detected in the callback; if it matched socket_exists should be true and we would never get here */ assert(curfd != sockets[num_handles-1]); fprintf(stderr, "Handle %d wrote to socket %d then detected on %d\n", num_handles-1, (int)sockets[num_handles-1], (int)curfd); res = TEST_ERR_MAJOR_BAD; goto test_cleanup; } else { sockets[num_handles-1] = curfd; found_new_socket = TRUE; /* continue to make sure there's only one new handle */ } } if(state == NeedSocketForNewHandle) { if(maxfd != -1 && !found_new_socket) { fprintf(stderr, "Warning: socket did not open immediately for new " "handle (trying again)\n"); continue; } state = num_handles < MAX_EASY_HANDLES ? ReadyForNewHandle : NoMoreHandles; } multi_timeout(multi, &timeout); /* At this point, timeout is guaranteed to be greater or equal than -1. */ fprintf(stderr, "%s:%d num_handles %d timeout %ld\n", __FILE__, __LINE__, num_handles, timeout); if(timeout != -1L) { int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; interval.tv_sec = itimeout/1000; interval.tv_usec = (itimeout%1000)*1000; } else { interval.tv_sec = TEST_HANG_TIMEOUT/1000+1; interval.tv_usec = 0; /* if there's no timeout and we get here on the last handle, we may already have read the last part of the stream so waiting makes no sense */ if(!running && num_handles == MAX_EASY_HANDLES) { break; } } select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval); abort_on_test_timeout(); } test_cleanup: /* proper cleanup sequence - type PB */ for(i = 0; i < MAX_EASY_HANDLES; i++) { curl_multi_remove_handle(multi, easy[i]); curl_easy_cleanup(easy[i]); } curl_multi_cleanup(multi); curl_global_cleanup(); free(full_url); return res; }