Return to libntlmconnect.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / tests / libtest |
1.1 ! misho 1: /*************************************************************************** ! 2: * _ _ ____ _ ! 3: * Project ___| | | | _ \| | ! 4: * / __| | | | |_) | | ! 5: * | (__| |_| | _ <| |___ ! 6: * \___|\___/|_| \_\_____| ! 7: * ! 8: * Copyright (C) 2012 - 2018, 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: #include "test.h" ! 23: ! 24: #include <limits.h> ! 25: #include <assert.h> ! 26: ! 27: #include "testutil.h" ! 28: #include "warnless.h" ! 29: #include "memdebug.h" ! 30: ! 31: #define TEST_HANG_TIMEOUT 5 * 1000 ! 32: #define MAX_EASY_HANDLES 3 ! 33: ! 34: static int counter[MAX_EASY_HANDLES]; ! 35: static CURL *easy[MAX_EASY_HANDLES]; ! 36: static curl_socket_t sockets[MAX_EASY_HANDLES]; ! 37: static int res = 0; ! 38: ! 39: static size_t callback(char *ptr, size_t size, size_t nmemb, void *data) ! 40: { ! 41: ssize_t idx = ((CURL **) data) - easy; ! 42: curl_socket_t sock; ! 43: long longdata; ! 44: CURLcode code; ! 45: const size_t failure = (size && nmemb) ? 0 : 1; ! 46: (void)ptr; ! 47: ! 48: counter[idx] += (int)(size * nmemb); ! 49: ! 50: /* Get socket being used for this easy handle, otherwise CURL_SOCKET_BAD */ ! 51: code = curl_easy_getinfo(easy[idx], CURLINFO_LASTSOCKET, &longdata); ! 52: if(CURLE_OK != code) { ! 53: fprintf(stderr, "%s:%d curl_easy_getinfo() failed, " ! 54: "with code %d (%s)\n", ! 55: __FILE__, __LINE__, (int)code, curl_easy_strerror(code)); ! 56: res = TEST_ERR_MAJOR_BAD; ! 57: return failure; ! 58: } ! 59: if(longdata == -1L) ! 60: sock = CURL_SOCKET_BAD; ! 61: else ! 62: sock = (curl_socket_t)longdata; ! 63: ! 64: if(sock != CURL_SOCKET_BAD) { ! 65: /* Track relationship between this easy handle and the socket. */ ! 66: if(sockets[idx] == CURL_SOCKET_BAD) { ! 67: /* An easy handle without previous socket, record the socket. */ ! 68: sockets[idx] = sock; ! 69: } ! 70: else if(sock != sockets[idx]) { ! 71: /* An easy handle with a socket different to previously ! 72: tracked one, log and fail right away. Known bug #37. */ ! 73: fprintf(stderr, "Handle %d started on socket %d and moved to %d\n", ! 74: curlx_sztosi(idx), (int)sockets[idx], (int)sock); ! 75: res = TEST_ERR_MAJOR_BAD; ! 76: return failure; ! 77: } ! 78: } ! 79: return size * nmemb; ! 80: } ! 81: ! 82: enum HandleState { ! 83: ReadyForNewHandle, ! 84: NeedSocketForNewHandle, ! 85: NoMoreHandles ! 86: }; ! 87: ! 88: int test(char *url) ! 89: { ! 90: CURLM *multi = NULL; ! 91: int running; ! 92: int i; ! 93: int num_handles = 0; ! 94: enum HandleState state = ReadyForNewHandle; ! 95: size_t urllen = strlen(url) + 4 + 1; ! 96: char *full_url = malloc(urllen); ! 97: ! 98: start_test_timing(); ! 99: ! 100: if(!full_url) { ! 101: fprintf(stderr, "Not enough memory for full url\n"); ! 102: return TEST_ERR_MAJOR_BAD; ! 103: } ! 104: ! 105: for(i = 0; i < MAX_EASY_HANDLES; ++i) { ! 106: easy[i] = NULL; ! 107: sockets[i] = CURL_SOCKET_BAD; ! 108: } ! 109: ! 110: res_global_init(CURL_GLOBAL_ALL); ! 111: if(res) { ! 112: free(full_url); ! 113: return res; ! 114: } ! 115: ! 116: multi_init(multi); ! 117: ! 118: #ifdef USE_PIPELINING ! 119: multi_setopt(multi, CURLMOPT_PIPELINING, 1L); ! 120: multi_setopt(multi, CURLMOPT_MAX_HOST_CONNECTIONS, 5L); ! 121: multi_setopt(multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, 10L); ! 122: #endif ! 123: ! 124: for(;;) { ! 125: struct timeval interval; ! 126: fd_set fdread; ! 127: fd_set fdwrite; ! 128: fd_set fdexcep; ! 129: long timeout = -99; ! 130: int maxfd = -99; ! 131: bool found_new_socket = FALSE; ! 132: ! 133: /* Start a new handle if we aren't at the max */ ! 134: if(state == ReadyForNewHandle) { ! 135: easy_init(easy[num_handles]); ! 136: ! 137: if(num_handles % 3 == 2) { ! 138: msnprintf(full_url, urllen, "%s0200", url); ! 139: easy_setopt(easy[num_handles], CURLOPT_HTTPAUTH, CURLAUTH_NTLM); ! 140: } ! 141: else { ! 142: msnprintf(full_url, urllen, "%s0100", url); ! 143: easy_setopt(easy[num_handles], CURLOPT_HTTPAUTH, CURLAUTH_BASIC); ! 144: } ! 145: easy_setopt(easy[num_handles], CURLOPT_FRESH_CONNECT, 1L); ! 146: easy_setopt(easy[num_handles], CURLOPT_URL, full_url); ! 147: easy_setopt(easy[num_handles], CURLOPT_VERBOSE, 1L); ! 148: easy_setopt(easy[num_handles], CURLOPT_HTTPGET, 1L); ! 149: easy_setopt(easy[num_handles], CURLOPT_USERPWD, "testuser:testpass"); ! 150: easy_setopt(easy[num_handles], CURLOPT_WRITEFUNCTION, callback); ! 151: easy_setopt(easy[num_handles], CURLOPT_WRITEDATA, easy + num_handles); ! 152: easy_setopt(easy[num_handles], CURLOPT_HEADER, 1L); ! 153: ! 154: multi_add_handle(multi, easy[num_handles]); ! 155: num_handles += 1; ! 156: state = NeedSocketForNewHandle; ! 157: } ! 158: ! 159: multi_perform(multi, &running); ! 160: ! 161: fprintf(stderr, "%s:%d running %d state %d\n", ! 162: __FILE__, __LINE__, running, state); ! 163: ! 164: abort_on_test_timeout(); ! 165: ! 166: if(!running && state == NoMoreHandles) ! 167: break; /* done */ ! 168: ! 169: FD_ZERO(&fdread); ! 170: FD_ZERO(&fdwrite); ! 171: FD_ZERO(&fdexcep); ! 172: ! 173: multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); ! 174: ! 175: /* At this point, maxfd is guaranteed to be greater or equal than -1. */ ! 176: ! 177: if(state == NeedSocketForNewHandle) { ! 178: if(maxfd != -1 && !found_new_socket) { ! 179: fprintf(stderr, "Warning: socket did not open immediately for new " ! 180: "handle (trying again)\n"); ! 181: continue; ! 182: } ! 183: state = num_handles < MAX_EASY_HANDLES ? ReadyForNewHandle ! 184: : NoMoreHandles; ! 185: fprintf(stderr, "%s:%d new state %d\n", ! 186: __FILE__, __LINE__, state); ! 187: } ! 188: ! 189: multi_timeout(multi, &timeout); ! 190: ! 191: /* At this point, timeout is guaranteed to be greater or equal than -1. */ ! 192: ! 193: fprintf(stderr, "%s:%d num_handles %d timeout %ld running %d\n", ! 194: __FILE__, __LINE__, num_handles, timeout, running); ! 195: ! 196: if(timeout != -1L) { ! 197: int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; ! 198: interval.tv_sec = itimeout/1000; ! 199: interval.tv_usec = (itimeout%1000)*1000; ! 200: } ! 201: else { ! 202: interval.tv_sec = 0; ! 203: interval.tv_usec = 5000; ! 204: ! 205: /* if there's no timeout and we get here on the last handle, we may ! 206: already have read the last part of the stream so waiting makes no ! 207: sense */ ! 208: if(!running && num_handles == MAX_EASY_HANDLES) { ! 209: break; ! 210: } ! 211: } ! 212: ! 213: select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval); ! 214: ! 215: abort_on_test_timeout(); ! 216: } ! 217: ! 218: test_cleanup: ! 219: ! 220: /* proper cleanup sequence - type PB */ ! 221: ! 222: for(i = 0; i < MAX_EASY_HANDLES; i++) { ! 223: printf("Data connection %d: %d\n", i, counter[i]); ! 224: curl_multi_remove_handle(multi, easy[i]); ! 225: curl_easy_cleanup(easy[i]); ! 226: } ! 227: ! 228: curl_multi_cleanup(multi); ! 229: curl_global_cleanup(); ! 230: ! 231: free(full_url); ! 232: ! 233: return res; ! 234: }