Annotation of embedaddon/curl/tests/libtest/libntlmconnect.c, revision 1.1.1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>