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