VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/tmoacc.c@ 55761

最後變更 在這個檔案從55761是 1,由 vboxsync 提交於 55 年 前

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 11.1 KB
 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#include "nspr.h"
39
40#include <stdlib.h>
41#include <string.h>
42
43#include "plerror.h"
44#include "plgetopt.h"
45
46#ifdef XP_MAC
47#include "prlog.h"
48#define printf PR_LogPrint
49#endif
50
51#define BASE_PORT 9867
52#define DEFAULT_THREADS 1
53#define DEFAULT_BACKLOG 10
54#define DEFAULT_TIMEOUT 10
55#define RANDOM_RANGE 100 /* should be significantly smaller than RAND_MAX */
56
57typedef enum {running, stopped} Status;
58
59typedef struct Shared
60{
61 PRLock *ml;
62 PRCondVar *cv;
63 PRBool passed;
64 PRBool random;
65 PRFileDesc *debug;
66 PRIntervalTime timeout;
67 PRFileDesc *listenSock;
68 Status status;
69} Shared;
70
71static PRIntervalTime Timeout(const Shared *shared)
72{
73 PRIntervalTime timeout = shared->timeout;
74 if (shared->random)
75 {
76 PRIntervalTime half = timeout >> 1; /* one half of the interval */
77 PRIntervalTime quarter = half >> 1; /* one quarter of the interval */
78 /* something in [0..timeout / 2) */
79 PRUint32 random = (rand() % RANDOM_RANGE) * half / RANDOM_RANGE;
80 timeout = (3 * quarter) + random; /* [75..125)% */
81 }
82 return timeout;
83} /* Timeout */
84
85static void Accept(void *arg)
86{
87 PRStatus rv;
88 char *buffer = NULL;
89 PRNetAddr clientAddr;
90 Shared *shared = (Shared*)arg;
91 PRInt32 recv_length = 0, flags = 0;
92 PRFileDesc *clientSock;
93 PRIntn toread, byte, bytes, loop = 0;
94 struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor;
95
96 do
97 {
98 PRUint32 checksum = 0;
99 if (NULL != shared->debug)
100 PR_fprintf(shared->debug, "[%d]accepting ... ", loop++);
101 clientSock = PR_Accept(
102 shared->listenSock, &clientAddr, Timeout(shared));
103 if (clientSock != NULL)
104 {
105 if (NULL != shared->debug)
106 PR_fprintf(shared->debug, "reading length ... ");
107 bytes = PR_Recv(
108 clientSock, &descriptor, sizeof(descriptor),
109 flags, Timeout(shared));
110 if (sizeof(descriptor) == bytes)
111 {
112 /* and, before doing something stupid ... */
113 descriptor.length = PR_ntohl(descriptor.length);
114 descriptor.checksum = PR_ntohl(descriptor.checksum);
115 if (NULL != shared->debug)
116 PR_fprintf(shared->debug, "%d bytes ... ", descriptor.length);
117 toread = descriptor.length;
118 if (recv_length < descriptor.length)
119 {
120 if (NULL != buffer) PR_DELETE(buffer);
121 buffer = (char*)PR_MALLOC(descriptor.length);
122 recv_length = descriptor.length;
123 }
124 for (toread = descriptor.length; toread > 0; toread -= bytes)
125 {
126 bytes = PR_Recv(
127 clientSock, &buffer[descriptor.length - toread],
128 toread, flags, Timeout(shared));
129 if (-1 == bytes)
130 {
131 if (NULL != shared->debug)
132 PR_fprintf(shared->debug, "read data failed...");
133 bytes = 0;
134 }
135 }
136 }
137 else if (NULL != shared->debug)
138 {
139 PR_fprintf(shared->debug, "read desciptor failed...");
140 descriptor.length = -1;
141 }
142 if (NULL != shared->debug)
143 PR_fprintf(shared->debug, "closing");
144 rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH);
145 if ((PR_FAILURE == rv) && (NULL != shared->debug))
146 {
147 PR_fprintf(shared->debug, " failed");
148 shared->passed = PR_FALSE;
149 }
150 rv = PR_Close(clientSock);
151 if (PR_FAILURE == rv) if (NULL != shared->debug)
152 {
153 PR_fprintf(shared->debug, " failed");
154 shared->passed = PR_FALSE;
155 }
156 if (descriptor.length > 0)
157 {
158 for (byte = 0; byte < descriptor.length; ++byte)
159 {
160 PRUint32 overflow = checksum & 0x80000000;
161 checksum = (checksum << 1);
162 if (0x00000000 != overflow) checksum += 1;
163 checksum += buffer[byte];
164 }
165 if ((descriptor.checksum != checksum) && (NULL != shared->debug))
166 {
167 PR_fprintf(shared->debug, " ... data mismatch");
168 shared->passed = PR_FALSE;
169 }
170 }
171 else if (0 == descriptor.length)
172 {
173 PR_Lock(shared->ml);
174 shared->status = stopped;
175 PR_NotifyCondVar(shared->cv);
176 PR_Unlock(shared->ml);
177 }
178 if (NULL != shared->debug)
179 PR_fprintf(shared->debug, "\n");
180 }
181 else
182 {
183 if (PR_PENDING_INTERRUPT_ERROR != PR_GetError())
184 {
185 if (NULL != shared->debug) PL_PrintError("Accept");
186 shared->passed = PR_FALSE;
187 }
188 }
189 } while (running == shared->status);
190 if (NULL != buffer) PR_DELETE(buffer);
191} /* Accept */
192
193PRIntn Tmoacc(PRIntn argc, char **argv)
194{
195 PRStatus rv;
196 PRIntn exitStatus;
197 PRIntn index;
198 Shared *shared;
199 PLOptStatus os;
200 PRThread **thread;
201 PRNetAddr listenAddr;
202 PRSocketOptionData sockOpt;
203 PRIntn timeout = DEFAULT_TIMEOUT;
204 PRIntn threads = DEFAULT_THREADS;
205 PRIntn backlog = DEFAULT_BACKLOG;
206 PRThreadScope thread_scope = PR_LOCAL_THREAD;
207
208 PLOptState *opt = PL_CreateOptState(argc, argv, "dGb:t:T:R");
209
210 shared = PR_NEWZAP(Shared);
211
212 shared->debug = NULL;
213 shared->passed = PR_TRUE;
214 shared->random = PR_TRUE;
215 shared->status = running;
216 shared->ml = PR_NewLock();
217 shared->cv = PR_NewCondVar(shared->ml);
218
219 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
220 {
221 if (PL_OPT_BAD == os) continue;
222 switch (opt->option)
223 {
224 case 'd': /* debug mode */
225 shared->debug = PR_GetSpecialFD(PR_StandardError);
226 break;
227 case 'G': /* use global threads */
228 thread_scope = PR_GLOBAL_THREAD;
229 break;
230 case 'b': /* size of listen backlog */
231 backlog = atoi(opt->value);
232 break;
233 case 't': /* number of threads doing accept */
234 threads = atoi(opt->value);
235 break;
236 case 'T': /* timeout used for network operations */
237 timeout = atoi(opt->value);
238 break;
239 case 'R': /* randomize the timeout values */
240 shared->random = PR_TRUE;
241 break;
242 default:
243 break;
244 }
245 }
246 PL_DestroyOptState(opt);
247 if (0 == threads) threads = DEFAULT_THREADS;
248 if (0 == backlog) backlog = DEFAULT_BACKLOG;
249 if (0 == timeout) timeout = DEFAULT_TIMEOUT;
250
251 PR_STDIO_INIT();
252 memset(&listenAddr, 0, sizeof(listenAddr));
253 rv = PR_InitializeNetAddr(PR_IpAddrAny, BASE_PORT, &listenAddr);
254 PR_ASSERT(PR_SUCCESS == rv);
255
256 shared->timeout = PR_SecondsToInterval(timeout);
257
258 /* First bind to the socket */
259 shared->listenSock = PR_NewTCPSocket();
260 if (shared->listenSock)
261 {
262 sockOpt.option = PR_SockOpt_Reuseaddr;
263 sockOpt.value.reuse_addr = PR_TRUE;
264 rv = PR_SetSocketOption(shared->listenSock, &sockOpt);
265 PR_ASSERT(PR_SUCCESS == rv);
266 rv = PR_Bind(shared->listenSock, &listenAddr);
267 if (rv != PR_FAILURE)
268 {
269 rv = PR_Listen(shared->listenSock, threads + backlog);
270 if (PR_SUCCESS == rv)
271 {
272 thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*));
273 for (index = 0; index < threads; ++index)
274 {
275 thread[index] = PR_CreateThread(
276 PR_USER_THREAD, Accept, shared,
277 PR_PRIORITY_NORMAL, thread_scope,
278 PR_JOINABLE_THREAD, 0);
279 PR_ASSERT(NULL != thread[index]);
280 }
281
282 PR_Lock(shared->ml);
283 while (shared->status == running)
284 PR_WaitCondVar(shared->cv, PR_INTERVAL_NO_TIMEOUT);
285 PR_Unlock(shared->ml);
286 for (index = 0; index < threads; ++index)
287 {
288 rv = PR_Interrupt(thread[index]);
289 PR_ASSERT(PR_SUCCESS== rv);
290 rv = PR_JoinThread(thread[index]);
291 PR_ASSERT(PR_SUCCESS== rv);
292 }
293 PR_DELETE(thread);
294 }
295 else
296 {
297 if (shared->debug) PL_PrintError("Listen");
298 shared->passed = PR_FALSE;
299 }
300 }
301 else
302 {
303 if (shared->debug) PL_PrintError("Bind");
304 shared->passed = PR_FALSE;
305 }
306
307 PR_Close(shared->listenSock);
308 }
309 else
310 {
311 if (shared->debug) PL_PrintError("Create");
312 shared->passed = PR_FALSE;
313 }
314
315 PR_DestroyCondVar(shared->cv);
316 PR_DestroyLock(shared->ml);
317
318 PR_fprintf(
319 PR_GetSpecialFD(PR_StandardError), "%s\n",
320 ((shared->passed) ? "PASSED" : "FAILED"));
321
322 exitStatus = (shared->passed) ? 0 : 1;
323 PR_DELETE(shared);
324 return exitStatus;
325}
326
327int main(int argc, char **argv)
328{
329 return (PR_VersionCheck(PR_VERSION)) ?
330 PR_Initialize(Tmoacc, argc, argv, 4) : -1;
331} /* main */
332
333/* tmoacc */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette