Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /***********************************************************************
7 **
8 ** Name: tmocon.c
9 **
10 ** Description: test client socket connection.
11 **
12 ** Modification History:
13 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
14 ** The debug mode will print all of the printfs associated with this test.
15 ** The regress mode will be the default mode. Since the regress tool limits
16 ** the output to a one line status:PASS or FAIL,all of the printf statements
17 ** have been handled with an if (debug_mode) statement.
18 ***********************************************************************/
20 /***********************************************************************
21 ** Includes
22 ***********************************************************************/
23 /* Used to get the command line option */
24 #include "plgetopt.h"
26 #include "nspr.h"
27 #include "pprio.h"
29 #include "plerror.h"
30 #include "plgetopt.h"
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
36 /* for getcwd */
37 #if defined(XP_UNIX) || defined (XP_OS2) || defined(XP_BEOS)
38 #include <unistd.h>
39 #elif defined(XP_PC)
40 #include <direct.h>
41 #endif
43 #ifdef WINCE
44 #include <windows.h>
45 char *getcwd(char *buf, size_t size)
46 {
47 wchar_t wpath[MAX_PATH];
48 _wgetcwd(wpath, MAX_PATH);
49 WideCharToMultiByte(CP_ACP, 0, wpath, -1, buf, size, 0, 0);
50 }
51 #endif
53 #define BASE_PORT 9867
55 #define DEFAULT_DALLY 1
56 #define DEFAULT_THREADS 1
57 #define DEFAULT_TIMEOUT 10
58 #define DEFAULT_MESSAGES 100
59 #define DEFAULT_MESSAGESIZE 100
61 static PRFileDesc *debug_out = NULL;
63 typedef struct Shared
64 {
65 PRBool random;
66 PRBool failed;
67 PRBool intermittant;
68 PRIntn debug;
69 PRInt32 messages;
70 PRIntervalTime dally;
71 PRIntervalTime timeout;
72 PRInt32 message_length;
73 PRNetAddr serverAddress;
74 } Shared;
76 static PRIntervalTime Timeout(const Shared *shared)
77 {
78 PRIntervalTime timeout = shared->timeout;
79 if (shared->random)
80 {
81 PRIntervalTime quarter = timeout >> 2; /* one quarter of the interval */
82 PRUint32 random = rand() % quarter; /* something in[0..timeout / 4) */
83 timeout = (((3 * quarter) + random) >> 2) + quarter; /* [75..125)% */
84 }
85 return timeout;
86 } /* Timeout */
88 static void CauseTimeout(const Shared *shared)
89 {
90 if (shared->intermittant) PR_Sleep(Timeout(shared));
91 } /* CauseTimeout */
93 static PRStatus MakeReceiver(Shared *shared)
94 {
95 PRStatus rv = PR_FAILURE;
96 if (PR_IsNetAddrType(&shared->serverAddress, PR_IpAddrLoopback))
97 {
98 char *argv[3];
99 char path[1024 + sizeof("/tmoacc")];
101 getcwd(path, sizeof(path));
103 (void)strcat(path, "/tmoacc");
104 #ifdef XP_PC
105 (void)strcat(path, ".exe");
106 #endif
107 argv[0] = path;
108 if (shared->debug > 0)
109 {
110 argv[1] = "-d";
111 argv[2] = NULL;
112 }
113 else argv[1] = NULL;
114 if (shared->debug > 1)
115 PR_fprintf(debug_out, " creating accept process %s ...", path);
116 fflush(stdout);
117 rv = PR_CreateProcessDetached(path, argv, NULL, NULL);
118 if (PR_SUCCESS == rv)
119 {
120 if (shared->debug > 1)
121 PR_fprintf(debug_out, " wait 5 seconds");
122 if (shared->debug > 1)
123 PR_fprintf(debug_out, " before connecting to accept process ...");
124 fflush(stdout);
125 PR_Sleep(PR_SecondsToInterval(5));
126 return rv;
127 }
128 shared->failed = PR_TRUE;
129 if (shared->debug > 0)
130 PL_FPrintError(debug_out, "PR_CreateProcessDetached failed");
131 }
132 return rv;
133 } /* MakeReceiver */
135 static void Connect(void *arg)
136 {
137 PRStatus rv;
138 char *buffer = NULL;
139 PRFileDesc *clientSock;
140 Shared *shared = (Shared*)arg;
141 PRInt32 loop, bytes, flags = 0;
142 struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor;
143 debug_out = (0 == shared->debug) ? NULL : PR_GetSpecialFD(PR_StandardError);
145 buffer = (char*)PR_MALLOC(shared->message_length);
147 for (bytes = 0; bytes < shared->message_length; ++bytes)
148 buffer[bytes] = (char)bytes;
150 descriptor.checksum = 0;
151 for (bytes = 0; bytes < shared->message_length; ++bytes)
152 {
153 PRUint32 overflow = descriptor.checksum & 0x80000000;
154 descriptor.checksum = (descriptor.checksum << 1);
155 if (0x00000000 != overflow) descriptor.checksum += 1;
156 descriptor.checksum += buffer[bytes];
157 }
158 descriptor.checksum = PR_htonl(descriptor.checksum);
160 for (loop = 0; loop < shared->messages; ++loop)
161 {
162 if (shared->debug > 1)
163 PR_fprintf(debug_out, "[%d]socket ... ", loop);
164 clientSock = PR_NewTCPSocket();
165 if (clientSock)
166 {
167 /*
168 * We need to slow down the rate of generating connect requests,
169 * otherwise the listen backlog queue on the accept side may
170 * become full and we will get connection refused or timeout
171 * error.
172 */
174 PR_Sleep(shared->dally);
175 if (shared->debug > 1)
176 {
177 char buf[128];
178 PR_NetAddrToString(&shared->serverAddress, buf, sizeof(buf));
179 PR_fprintf(debug_out, "connecting to %s ... ", buf);
180 }
181 rv = PR_Connect(
182 clientSock, &shared->serverAddress, Timeout(shared));
183 if (PR_SUCCESS == rv)
184 {
185 PRInt32 descriptor_length = (loop < (shared->messages - 1)) ?
186 shared->message_length : 0;
187 descriptor.length = PR_htonl(descriptor_length);
188 if (shared->debug > 1)
189 PR_fprintf(
190 debug_out, "sending %d bytes ... ", descriptor_length);
191 CauseTimeout(shared); /* might cause server to timeout */
192 bytes = PR_Send(
193 clientSock, &descriptor, sizeof(descriptor),
194 flags, Timeout(shared));
195 if (bytes != sizeof(descriptor))
196 {
197 shared->failed = PR_TRUE;
198 if (shared->debug > 0)
199 PL_FPrintError(debug_out, "PR_Send failed");
200 }
201 if (0 != descriptor_length)
202 {
203 CauseTimeout(shared);
204 bytes = PR_Send(
205 clientSock, buffer, descriptor_length,
206 flags, Timeout(shared));
207 if (bytes != descriptor_length)
208 {
209 shared->failed = PR_TRUE;
210 if (shared->debug > 0)
211 PL_FPrintError(debug_out, "PR_Send failed");
212 }
213 }
214 if (shared->debug > 1) PR_fprintf(debug_out, "closing ... ");
215 rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH);
216 rv = PR_Close(clientSock);
217 if (shared->debug > 1)
218 {
219 if (PR_SUCCESS == rv) PR_fprintf(debug_out, "\n");
220 else PL_FPrintError(debug_out, "shutdown failed");
221 }
222 }
223 else
224 {
225 if (shared->debug > 1) PL_FPrintError(debug_out, "connect failed");
226 PR_Close(clientSock);
227 if ((loop == 0) && (PR_GetError() == PR_CONNECT_REFUSED_ERROR))
228 {
229 if (MakeReceiver(shared) == PR_FAILURE) break;
230 }
231 else
232 {
233 if (shared->debug > 1) PR_fprintf(debug_out, " exiting\n");
234 break;
235 }
236 }
237 }
238 else
239 {
240 shared->failed = PR_TRUE;
241 if (shared->debug > 0) PL_FPrintError(debug_out, "create socket");
242 break;
243 }
244 }
246 PR_DELETE(buffer);
247 } /* Connect */
249 int Tmocon(int argc, char **argv)
250 {
251 /*
252 * USAGE
253 * -d turn on debugging output (default = off)
254 * -v turn on verbose output (default = off)
255 * -h <n> dns name of host serving the connection (default = self)
256 * -i dally intermittantly to cause timeouts (default = off)
257 * -m <n> number of messages to send (default = 100)
258 * -s <n> size of each message (default = 100)
259 * -t <n> number of threads sending (default = 1)
260 * -G use global threads (default = local)
261 * -T <n> timeout on I/O operations (seconds) (default = 10)
262 * -D <n> dally between connect requests (seconds)(default = 0)
263 * -R randomize the dally types around 'T' (default = no)
264 */
266 PRStatus rv;
267 int exitStatus;
268 PLOptStatus os;
269 Shared *shared = NULL;
270 PRThread **thread = NULL;
271 PRIntn index, threads = DEFAULT_THREADS;
272 PRThreadScope thread_scope = PR_LOCAL_THREAD;
273 PRInt32 dally = DEFAULT_DALLY, timeout = DEFAULT_TIMEOUT;
274 PLOptState *opt = PL_CreateOptState(argc, argv, "divGRh:m:s:t:T:D:");
276 shared = PR_NEWZAP(Shared);
278 shared->debug = 0;
279 shared->failed = PR_FALSE;
280 shared->random = PR_FALSE;
281 shared->messages = DEFAULT_MESSAGES;
282 shared->message_length = DEFAULT_MESSAGESIZE;
284 PR_STDIO_INIT();
285 memset(&shared->serverAddress, 0, sizeof(shared->serverAddress));
286 rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &shared->serverAddress);
287 PR_ASSERT(PR_SUCCESS == rv);
289 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
290 {
291 if (PL_OPT_BAD == os) continue;
292 switch (opt->option)
293 {
294 case 'd':
295 if (0 == shared->debug) shared->debug = 1;
296 break;
297 case 'v':
298 if (0 == shared->debug) shared->debug = 2;
299 break;
300 case 'i':
301 shared->intermittant = PR_TRUE;
302 break;
303 case 'R':
304 shared->random = PR_TRUE;
305 break;
306 case 'G':
307 thread_scope = PR_GLOBAL_THREAD;
308 break;
309 case 'h': /* the value for backlock */
310 {
311 PRIntn es = 0;
312 PRHostEnt host;
313 char buffer[1024];
314 (void)PR_GetHostByName(
315 opt->value, buffer, sizeof(buffer), &host);
316 es = PR_EnumerateHostEnt(
317 es, &host, BASE_PORT, &shared->serverAddress);
318 PR_ASSERT(es > 0);
319 }
320 break;
321 case 'm': /* number of messages to send */
322 shared->messages = atoi(opt->value);
323 break;
324 case 't': /* number of threads sending */
325 threads = atoi(opt->value);
326 break;
327 case 'D': /* dally time between transmissions */
328 dally = atoi(opt->value);
329 break;
330 case 'T': /* timeout on I/O operations */
331 timeout = atoi(opt->value);
332 break;
333 case 's': /* total size of each message */
334 shared->message_length = atoi(opt->value);
335 break;
336 default:
337 break;
338 }
339 }
340 PL_DestroyOptState(opt);
342 if (0 == timeout) timeout = DEFAULT_TIMEOUT;
343 if (0 == threads) threads = DEFAULT_THREADS;
344 if (0 == shared->messages) shared->messages = DEFAULT_MESSAGES;
345 if (0 == shared->message_length) shared->message_length = DEFAULT_MESSAGESIZE;
347 shared->dally = PR_SecondsToInterval(dally);
348 shared->timeout = PR_SecondsToInterval(timeout);
350 thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*));
352 for (index = 0; index < threads; ++index)
353 thread[index] = PR_CreateThread(
354 PR_USER_THREAD, Connect, shared,
355 PR_PRIORITY_NORMAL, thread_scope,
356 PR_JOINABLE_THREAD, 0);
357 for (index = 0; index < threads; ++index)
358 rv = PR_JoinThread(thread[index]);
360 PR_DELETE(thread);
362 PR_fprintf(
363 PR_GetSpecialFD(PR_StandardError), "%s\n",
364 ((shared->failed) ? "FAILED" : "PASSED"));
365 exitStatus = (shared->failed) ? 1 : 0;
366 PR_DELETE(shared);
367 return exitStatus;
368 }
370 int main(int argc, char **argv)
371 {
372 return (PR_VersionCheck(PR_VERSION)) ?
373 PR_Initialize(Tmocon, argc, argv, 4) : -1;
374 } /* main */
376 /* tmocon.c */