Move abort() into opr
[openafs.git] / src / rx / test / testserver.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* Server test program */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14 #include <roken.h>
15
16 #include <sys/types.h>
17 #include <stdio.h>
18 #ifdef AFS_NT40_ENV
19 #include <io.h>
20 #include <winsock2.h>
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #else
24 #include <netinet/in.h>
25 #include <netdb.h>
26 #include <sys/file.h>
27 #include <sys/time.h>
28 #endif
29 #include <signal.h>
30 #include <sys/stat.h>
31
32 #include <afs/opr.h>
33 #include <rx/rx_clock.h>
34 #include <rx/rx.h>
35 #include <rx/rx_globals.h>
36 #include <rx/rx_null.h>
37
38 int error;                      /* Return this error number on a call */
39 int print = 0, eventlog = 0, rxlog = 0;
40 struct clock computeTime, waitTime;
41 FILE *debugFile;
42 char *rcvFile;
43 int logstdout = 0;
44
45 void Abort(char *msg, ...);
46 void Quit(char *msg);
47 void OpenFD(int n);
48 int  FileRequest(struct rx_call *call);
49 int  SimpleRequest(struct rx_call *call);
50
51 void
52 intSignal(int ignore)
53 {
54     Quit("Interrupted");
55 }
56
57 void
58 quitSignal(int ignore)
59 {
60     static int quitCount = 0;
61     if (++quitCount > 1)
62         Quit("rx_ctest: second quit signal, aborting");
63     rx_debugFile = debugFile = fopen("rx_stest.db", "w");
64     if (debugFile)
65         rx_PrintStats(debugFile);
66 }
67
68 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV)
69 int
70 test_syscall(a3, a4, a5)
71      afs_uint32 a3, a4;
72      void *a5;
73 {
74     afs_uint32 rcode;
75     void (*old) (int);
76
77     old = signal(SIGSYS, SIG_IGN);
78     rcode =
79         syscall(31 /* AFS_SYSCALL */ , 28 /* AFSCALL_CALL */ , a3, a4, a5);
80     signal(SIGSYS, old);
81
82     return rcode;
83 }
84 #endif
85
86 main(argc, argv)
87      char **argv;
88 {
89     struct rx_service *service;
90     struct rx_securityClass *(secobjs[1]);
91     int err = 0;
92     int setFD = 0;
93     int jumbo = 0;
94
95 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV)
96     setlinebuf(stdout);
97     rxi_syscallp = test_syscall;
98 #endif
99     argv++;
100     argc--;
101     while (argc && **argv == '-') {
102         if (strcmp(*argv, "-verbose") == 0)
103             print = 1;
104         else if (strcmp(*argv, "-jumbo") == 0)
105             jumbo = 1;
106         else if (strcmp(*argv, "-rxlog") == 0)
107             rxlog = 1;
108 #if defined(RXDEBUG) && !defined(AFS_NT40_ENV)
109         else if (strcmp(*argv, "-trace") == 0)
110             strcpy(rxi_tracename, *(++argv)), argc--;
111 #endif
112         else if (strcmp(*argv, "-logstdout") == 0)
113             logstdout = 1;
114         else if (strcmp(*argv, "-eventlog") == 0)
115             eventlog = 1;
116         else if (strcmp(*argv, "-npb") == 0)
117             rx_nPackets = atoi(*++argv), argc--;
118         else if (!strcmp(*argv, "-nsf"))
119             rxi_nSendFrags = atoi(*++argv), argc--;
120         else if (!strcmp(*argv, "-nrf"))
121             rxi_nRecvFrags = atoi(*++argv), argc--;
122         else if (strcmp(*argv, "-twind") == 0)
123             rx_initSendWindow = atoi(*++argv), argc--;
124         else if (strcmp(*argv, "-rwind") == 0)
125             rx_initReceiveWindow = atoi(*++argv), argc--;
126         else if (strcmp(*argv, "-file") == 0)
127             rcvFile = *++argv, argc--;
128         else if (strcmp(*argv, "-drop") == 0) {
129 #ifdef RXDEBUG
130             rx_intentionallyDroppedPacketsPer100 = atoi(*++argv), argc--;
131 #else
132             fprintf(stderr, "ERROR: Compiled without RXDEBUG\n");
133 #endif
134         }
135         else if (strcmp(*argv, "-err") == 0)
136             error = atoi(*++argv), argc--;
137         else if (strcmp(*argv, "-compute") == 0) {
138             /* Simulated "compute" time for each call--to test acknowledgement protocol.  This is simulated by doing an iomgr_select:  imperfect, admittedly. */
139             computeTime.sec = atoi(*++argv), argc--;
140             computeTime.usec = atoi(*++argv), argc--;
141         } else if (strcmp(*argv, "-wait") == 0) {
142             /* Wait time between calls--to test lastack code */
143             waitTime.sec = atoi(*++argv), argc--;
144             waitTime.usec = atoi(*++argv), argc--;
145         } else if (strcmp(*argv, "-fd") == 0) {
146             /* Open at least this many fd's. */
147             setFD = atoi(*++argv), argc--;
148         } else {
149             err++;
150             break;
151         }
152         argv++, argc--;
153     }
154     if (err || argc != 0)
155         Quit("usage: rx_stest [-silent] [-rxlog] [-eventlog]");
156
157     if (rxlog || eventlog) {
158         if (logstdout)
159             debugFile = stdout;
160         else
161             debugFile = fopen("rx_stest.db", "w");
162         if (debugFile == NULL)
163             Quit("Couldn't open rx_stest.db");
164         if (rxlog)
165             rx_debugFile = debugFile;
166         if (eventlog)
167             rxevent_debugFile = debugFile;
168     }
169
170     signal(SIGINT, intSignal);  /* Changed to SIGQUIT since dbx is broken right now */
171 #ifndef AFS_NT40_ENV
172     signal(SIGQUIT, quitSignal);
173 #endif
174
175     if (setFD > 0)
176         OpenFD(setFD);
177
178 #ifdef AFS_NT40_ENV
179     rx_EnableHotThread();
180 #endif
181
182     if (!jumbo)
183         rx_SetNoJumbo();
184
185     rx_SetUdpBufSize(256 * 1024);
186
187     if (rx_Init(htons(2500)) != 0) {
188         printf("RX initialization failed, exiting.\n");
189         exit(1);
190     }
191     if (setFD > 0) {
192         printf("rx_socket=%d\n", rx_socket);
193     }
194
195     secobjs[0] = rxnull_NewServerSecurityObject();
196     service = rx_NewService( /*port */ 0, /*service */ 3, "test", secobjs,      /*nsec */
197                             1,  /*Execute request */
198                             rcvFile ? FileRequest : SimpleRequest);
199     if (!service)
200         Abort("rx_NewService returned 0!\n");
201
202     rx_SetMinProcs(service, 2);
203     rx_SetMaxProcs(service, 100);
204     rx_SetCheckReach(service, 1);
205
206     printf("Using %d packet buffers\n", rx_nPackets);
207     rx_StartServer(1);
208 }
209
210 static char buf[2000000];
211
212 int SimpleRequest(struct rx_call *call)
213 {
214     int n;
215     int nbytes = sizeof(buf);
216     while ((n = rx_Read(call, buf, nbytes)) > 0)
217         if (print)
218             printf("stest: Received %d bytes\n", n);
219     if (!rx_Error(call)) {
220         /* Fake compute time (use select to lock out everything) */
221 #ifndef AFS_NT40_ENV
222         struct timeval t;
223 #endif
224         if (!clock_IsZero(&computeTime)) {
225 #ifdef AFS_NT40_ENV
226             Sleep(computeTime.sec * 1000 + 100 * computeTime.usec);
227 #else
228             t.tv_sec = computeTime.sec;
229             t.tv_usec = computeTime.usec;
230 #ifdef AFS_PTHREAD_ENV
231             if (select(0, 0, 0, 0, &t) != 0)
232                 Quit("Select didn't return 0");
233 #else
234             IOMGR_Sleep(t.tv_sec);
235 #endif
236 #endif
237         }
238         /* Then wait time (use iomgr_select to allow rx to run) */
239         if (!clock_IsZero(&waitTime)) {
240 #ifdef AFS_NT40_ENV
241             Sleep(waitTime.sec * 1000 + 100 * waitTime.usec);
242 #else
243             t.tv_sec = waitTime.sec;
244             t.tv_usec = waitTime.usec;
245 #ifdef AFS_PTHREAD_ENV
246             select(0, 0, 0, 0, &t);
247 #else
248             IOMGR_Sleep(t.tv_sec);
249 #endif
250 #endif
251         }
252         rx_Write(call, "So long, and thanks for all the fish!\n",
253                  strlen("So long, and thanks for all the fish!\n"));
254     }
255     if (debugFile)
256         rx_PrintPeerStats(debugFile, rx_PeerOf(call->conn));
257     rx_PrintPeerStats(stdout, rx_PeerOf(call->conn));
258     return 0;
259 }
260
261 int
262 FileRequest(struct rx_call *call)
263 {
264     int fd;
265     struct stat status;
266     int nbytes, blockSize;
267     char *buffer;
268 #ifdef  AFS_AIX_ENV
269 #include <sys/statfs.h>
270     struct statfs tstatfs;
271 #endif
272     /* Open the file ahead of time:  the client timing the operation doesn't have to include the open time */
273     fd = open(rcvFile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
274     if (fd < 0) {
275         perror("open");
276         return -1;
277     }
278     fstat(fd, &status);
279 #ifdef AFS_NT40_ENV
280     blockSize = 1024;
281 #else
282 #ifdef  AFS_AIX_ENV
283     fstatfs(fd, &tstatfs);
284     blockSize = tstatfs.f_bsize;
285 #else
286     blockSize = status.st_blksize;
287 #endif
288 #endif /* AFS_NT40_ENV */
289     buffer = (char *)malloc(blockSize);
290
291     rx_SetLocalStatus(call, 79);        /* Emulation of file server's old "RCallBackReceivedStore" */
292
293     while (nbytes = rx_Read(call, buffer, blockSize)) {
294         if (write(fd, buffer, nbytes) != nbytes) {
295             perror("writev");
296             Abort("Write Failed.\n");
297             break;
298         }
299     }
300     rx_Write(call, "So long, and thanks for all the fish!\n",
301              strlen("So long, and thanks for all the fish!\n"));
302     printf("Received file %s\n", rcvFile);
303     close(fd);
304     if (debugFile)
305         rx_PrintPeerStats(debugFile, rx_PeerOf(call->conn));
306     rx_PrintPeerStats(stdout, rx_PeerOf(call->conn));
307     return 0;
308 }
309
310 void
311 Abort(char *msg, ...)
312 {
313     va_list args;
314
315     va_start(args, msg);
316     printf((char *)msg, args);
317     va_end(args);
318
319     printf("\n");
320     if (debugFile) {
321         rx_PrintStats(debugFile);
322         fflush(debugFile);
323     }
324     opr_abort();
325     exit(1);
326 }
327
328 void
329 Quit(char *msg)
330 {
331     printf("%s\n", msg);
332     if (debugFile) {
333         rx_PrintStats(debugFile);
334         fflush(debugFile);
335     }
336     rx_PrintStats(stdout);
337     exit(0);
338 }
339
340
341 /* OpenFD
342  *
343  * Open file descriptors until file descriptor n or higher is returned.
344  */
345 #include <sys/stat.h>
346 void
347 OpenFD(int n)
348 {
349     int i;
350     struct stat sbuf;
351     int fd, lfd;
352
353     lfd = -1;
354     for (i = 0; i < n; i++) {
355         if (fstat(i, &sbuf) == 0)
356             continue;
357         if ((fd = open("/dev/null", 0, 0)) < 0) {
358             if (lfd >= 0) {
359                 close(lfd);
360                 return;
361             }
362         } else {
363             if (fd >= n) {
364                 close(fd);
365                 return;
366             } else {
367                 lfd = fd;
368             }
369         }
370     }
371 }