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