upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / test / sendfile.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <assert.h>
18 #include <errno.h>
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "apr_network_io.h"
23 #include "apr_errno.h"
24 #include "apr_general.h"
25 #include "apr_poll.h"
26
27 #if !APR_HAS_SENDFILE
28 int main(void)
29 {
30     fprintf(stderr, 
31             "This program won't work on this platform because there is no "
32             "support for sendfile().\n");
33     return 0;
34 }
35 #else /* !APR_HAS_SENDFILE */
36
37 #define FILE_LENGTH    200000
38
39 #define FILE_DATA_CHAR '0'
40
41 #define HDR1           "1234567890ABCD\n"
42 #define HDR2           "EFGH\n"
43 #define HDR3_LEN       80000
44 #define HDR3_CHAR      '^'
45 #define TRL1           "IJKLMNOPQRSTUVWXYZ\n"
46 #define TRL2           "!@#$%&*()\n"
47 #define TRL3_LEN       90000
48 #define TRL3_CHAR      '@'
49
50 #define TESTSF_PORT    8021
51
52 #define TESTFILE       "testsf.dat"
53
54 typedef enum {BLK, NONBLK, TIMEOUT} client_socket_mode_t;
55
56 static void apr_setup(apr_pool_t **p, apr_socket_t **sock, int *family)
57 {
58     char buf[120];
59     apr_status_t rv;
60
61     rv = apr_initialize();
62     if (rv != APR_SUCCESS) {
63         fprintf(stderr, "apr_initialize()->%d/%s\n",
64                 rv,
65                 apr_strerror(rv, buf, sizeof buf));
66         exit(1);
67     }
68
69     atexit(apr_terminate);
70
71     rv = apr_pool_create(p, NULL);
72     if (rv != APR_SUCCESS) {
73         fprintf(stderr, "apr_pool_create()->%d/%s\n",
74                 rv,
75                 apr_strerror(rv, buf, sizeof buf));
76         exit(1);
77     }
78
79     *sock = NULL;
80     rv = apr_socket_create(sock, *family, SOCK_STREAM, *p);
81     if (rv != APR_SUCCESS) {
82         fprintf(stderr, "apr_socket_create()->%d/%s\n",
83                 rv,
84                 apr_strerror(rv, buf, sizeof buf));
85         exit(1);
86     }
87
88     if (*family == APR_UNSPEC) {
89         apr_sockaddr_t *localsa;
90
91         rv = apr_socket_addr_get(&localsa, APR_LOCAL, *sock);
92         if (rv != APR_SUCCESS) {
93             fprintf(stderr, "apr_socket_addr_get()->%d/%s\n",
94                     rv,
95                     apr_strerror(rv, buf, sizeof buf));
96             exit(1);
97         }
98         *family = localsa->family;
99     }
100 }
101
102 static void create_testfile(apr_pool_t *p, const char *fname)
103 {
104     apr_file_t *f = NULL;
105     apr_status_t rv;
106     char buf[120];
107     int i;
108     apr_finfo_t finfo;
109
110     printf("Creating a test file...\n");
111     rv = apr_file_open(&f, fname, 
112                  APR_CREATE | APR_WRITE | APR_TRUNCATE | APR_BUFFERED,
113                  APR_UREAD | APR_UWRITE, p);
114     if (rv) {
115         fprintf(stderr, "apr_file_open()->%d/%s\n",
116                 rv, apr_strerror(rv, buf, sizeof buf));
117         exit(1);
118     }
119     
120     buf[0] = FILE_DATA_CHAR;
121     buf[1] = '\0';
122     for (i = 0; i < FILE_LENGTH; i++) {
123         /* exercise apr_file_putc() and apr_file_puts() on buffered files */
124         if ((i % 2) == 0) {
125             rv = apr_file_putc(buf[0], f);
126             if (rv) {
127                 fprintf(stderr, "apr_file_putc()->%d/%s\n",
128                         rv, apr_strerror(rv, buf, sizeof buf));
129                 exit(1);
130             }
131         }
132         else {
133             rv = apr_file_puts(buf, f);
134             if (rv) {
135                 fprintf(stderr, "apr_file_puts()->%d/%s\n",
136                         rv, apr_strerror(rv, buf, sizeof buf));
137                 exit(1);
138             }
139         }
140     }
141
142     rv = apr_file_close(f);
143     if (rv) {
144         fprintf(stderr, "apr_file_close()->%d/%s\n",
145                 rv, apr_strerror(rv, buf, sizeof buf));
146         exit(1);
147     }
148
149     rv = apr_stat(&finfo, fname, APR_FINFO_NORM, p);
150     if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
151         fprintf(stderr, "apr_stat()->%d/%s\n",
152                 rv, apr_strerror(rv, buf, sizeof buf));
153         exit(1);
154     }
155
156     if (finfo.size != FILE_LENGTH) {
157         fprintf(stderr, 
158                 "test file %s should be %ld-bytes long\n"
159                 "instead it is %ld-bytes long\n",
160                 fname,
161                 (long int)FILE_LENGTH,
162                 (long int)finfo.size);
163         exit(1);
164     }
165 }
166
167 static int client(client_socket_mode_t socket_mode, char *host)
168 {
169     apr_status_t rv, tmprv;
170     apr_socket_t *sock;
171     apr_pool_t *p;
172     char buf[120];
173     apr_file_t *f = NULL;
174     apr_size_t len;
175     apr_size_t expected_len;
176     apr_off_t current_file_offset;
177     apr_hdtr_t hdtr;
178     struct iovec headers[3];
179     struct iovec trailers[3];
180     apr_size_t bytes_read;
181     apr_pollfd_t *pfd;
182     apr_int32_t nsocks;
183     int i;
184     int family;
185     apr_sockaddr_t *destsa;
186
187     family = APR_INET;
188     apr_setup(&p, &sock, &family);
189     create_testfile(p, TESTFILE);
190
191     rv = apr_file_open(&f, TESTFILE, APR_READ, 0, p);
192     if (rv != APR_SUCCESS) {
193         fprintf(stderr, "apr_file_open()->%d/%s\n",
194                 rv,
195                 apr_strerror(rv, buf, sizeof buf));
196         exit(1);
197     }
198
199     if (!host) {
200         host = "127.0.0.1";
201     }
202     rv = apr_sockaddr_info_get(&destsa, host, family, TESTSF_PORT, 0, p);
203     if (rv != APR_SUCCESS) {
204         fprintf(stderr, "apr_sockaddr_info_get()->%d/%s\n",
205                 rv,
206                 apr_strerror(rv, buf, sizeof buf));
207         exit(1);
208     }
209
210     rv = apr_socket_connect(sock, destsa);
211     if (rv != APR_SUCCESS) {
212         fprintf(stderr, "apr_socket_connect()->%d/%s\n", 
213                 rv,
214                 apr_strerror(rv, buf, sizeof buf));
215         exit(1);
216     }
217
218     switch(socket_mode) {
219     case BLK:
220         /* leave it blocking */
221         break;
222     case NONBLK:
223         /* set it non-blocking */
224         rv = apr_socket_opt_set(sock, APR_SO_NONBLOCK, 1);
225         if (rv != APR_SUCCESS) {
226             fprintf(stderr, "apr_socket_opt_set(APR_SO_NONBLOCK)->%d/%s\n", 
227                     rv,
228                     apr_strerror(rv, buf, sizeof buf));
229             exit(1);
230         }
231         break;
232     case TIMEOUT:
233         /* set a timeout */
234         rv = apr_socket_timeout_set(sock, 100 * APR_USEC_PER_SEC);
235         if (rv != APR_SUCCESS) {
236             fprintf(stderr, "apr_socket_opt_set(APR_SO_NONBLOCK)->%d/%s\n", 
237                     rv,
238                     apr_strerror(rv, buf, sizeof buf));
239             exit(1);
240         }
241         break;
242     default:
243         assert(1 != 1);
244     }
245
246     printf("Sending the file...\n");
247
248     hdtr.headers = headers;
249     hdtr.numheaders = 3;
250     hdtr.headers[0].iov_base = HDR1;
251     hdtr.headers[0].iov_len  = strlen(hdtr.headers[0].iov_base);
252     hdtr.headers[1].iov_base = HDR2;
253     hdtr.headers[1].iov_len  = strlen(hdtr.headers[1].iov_base);
254     hdtr.headers[2].iov_base = malloc(HDR3_LEN);
255     assert(hdtr.headers[2].iov_base);
256     memset(hdtr.headers[2].iov_base, HDR3_CHAR, HDR3_LEN);
257     hdtr.headers[2].iov_len  = HDR3_LEN;
258
259     hdtr.trailers = trailers;
260     hdtr.numtrailers = 3;
261     hdtr.trailers[0].iov_base = TRL1;
262     hdtr.trailers[0].iov_len  = strlen(hdtr.trailers[0].iov_base);
263     hdtr.trailers[1].iov_base = TRL2;
264     hdtr.trailers[1].iov_len  = strlen(hdtr.trailers[1].iov_base);
265     hdtr.trailers[2].iov_base = malloc(TRL3_LEN);
266     memset(hdtr.trailers[2].iov_base, TRL3_CHAR, TRL3_LEN);
267     assert(hdtr.trailers[2].iov_base);
268     hdtr.trailers[2].iov_len  = TRL3_LEN;
269
270     expected_len = 
271         strlen(HDR1) + strlen(HDR2) + HDR3_LEN +
272         strlen(TRL1) + strlen(TRL2) + TRL3_LEN +
273         FILE_LENGTH;
274     
275     if (socket_mode == BLK) {
276         current_file_offset = 0;
277         len = FILE_LENGTH;
278         rv = apr_socket_sendfile(sock, f, &hdtr, &current_file_offset, &len, 0);
279         if (rv != APR_SUCCESS) {
280             fprintf(stderr, "apr_socket_sendfile()->%d/%s\n",
281                     rv,
282                     apr_strerror(rv, buf, sizeof buf));
283             exit(1);
284         }
285         
286         printf("apr_socket_sendfile() updated offset with %ld\n",
287                (long int)current_file_offset);
288         
289         printf("apr_socket_sendfile() updated len with %ld\n",
290                (long int)len);
291         
292         printf("bytes really sent: %" APR_SIZE_T_FMT "\n",
293                expected_len);
294
295         if (len != expected_len) {
296             fprintf(stderr, "apr_socket_sendfile() didn't report the correct "
297                     "number of bytes sent!\n");
298             exit(1);
299         }
300     }
301     else {
302         /* non-blocking... wooooooo */
303         apr_size_t total_bytes_sent;
304
305         pfd = NULL;
306         rv = apr_poll_setup(&pfd, 1, p);
307         assert(!rv);
308         rv = apr_poll_socket_add(pfd, sock, APR_POLLOUT);
309         assert(!rv);
310
311         total_bytes_sent = 0;
312         current_file_offset = 0;
313         len = FILE_LENGTH;
314         do {
315             apr_size_t tmplen;
316
317             tmplen = len; /* bytes remaining to send from the file */
318             printf("Calling apr_socket_sendfile()...\n");
319             printf("Headers (%d):\n", hdtr.numheaders);
320             for (i = 0; i < hdtr.numheaders; i++) {
321                 printf("\t%ld bytes (%c)\n",
322                        (long)hdtr.headers[i].iov_len,
323                        *(char *)hdtr.headers[i].iov_base);
324             }
325             printf("File: %ld bytes from offset %ld\n",
326                    (long)tmplen, (long)current_file_offset);
327             printf("Trailers (%d):\n", hdtr.numtrailers);
328             for (i = 0; i < hdtr.numtrailers; i++) {
329                 printf("\t%ld bytes\n",
330                        (long)hdtr.trailers[i].iov_len);
331             }
332
333             rv = apr_socket_sendfile(sock, f, &hdtr, &current_file_offset, &tmplen, 0);
334             printf("apr_socket_sendfile()->%d, sent %ld bytes\n", rv, (long)tmplen);
335             if (rv) {
336                 if (APR_STATUS_IS_EAGAIN(rv)) {
337                     assert(tmplen == 0);
338                     nsocks = 1;
339                     tmprv = apr_poll(pfd, 1, &nsocks, -1);
340                     assert(!tmprv);
341                     assert(nsocks == 1);
342                     /* continue; */
343                 }
344             }
345
346             total_bytes_sent += tmplen;
347
348             /* Adjust hdtr to compensate for partially-written
349              * data.
350              */
351
352             /* First, skip over any header data which might have
353              * been written.
354              */
355             while (tmplen && hdtr.numheaders) {
356                 if (tmplen >= hdtr.headers[0].iov_len) {
357                     tmplen -= hdtr.headers[0].iov_len;
358                     --hdtr.numheaders;
359                     ++hdtr.headers;
360                 }
361                 else {
362                     hdtr.headers[0].iov_len -= tmplen;
363                     hdtr.headers[0].iov_base = 
364                         (char*) hdtr.headers[0].iov_base + tmplen;
365                     tmplen = 0;
366                 }
367             }
368
369             /* Now, skip over any file data which might have been
370              * written.
371              */
372
373             if (tmplen <= len) {
374                 current_file_offset += tmplen;
375                 len -= tmplen;
376                 tmplen = 0;
377             }
378             else {
379                 tmplen -= len;
380                 len = 0;
381                 current_file_offset = 0;
382             }
383
384             /* Last, skip over any trailer data which might have
385              * been written.
386              */
387
388             while (tmplen && hdtr.numtrailers) {
389                 if (tmplen >= hdtr.trailers[0].iov_len) {
390                     tmplen -= hdtr.trailers[0].iov_len;
391                     --hdtr.numtrailers;
392                     ++hdtr.trailers;
393                 }
394                 else {
395                     hdtr.trailers[0].iov_len -= tmplen;
396                     hdtr.trailers[0].iov_base = 
397                         (char *)hdtr.trailers[0].iov_base + tmplen;
398                     tmplen = 0;
399                 }
400             }
401
402         } while (total_bytes_sent < expected_len &&
403                  (rv == APR_SUCCESS || 
404                  (APR_STATUS_IS_EAGAIN(rv) && socket_mode != TIMEOUT)));
405         if (total_bytes_sent != expected_len) {
406             fprintf(stderr,
407                     "client problem: sent %ld of %ld bytes\n",
408                     (long)total_bytes_sent, (long)expected_len);
409             exit(1);
410         }
411
412         if (rv) {
413             fprintf(stderr,
414                     "client problem: rv %d\n",
415                     rv);
416             exit(1);
417         }
418     }
419     
420     current_file_offset = 0;
421     rv = apr_file_seek(f, APR_CUR, &current_file_offset);
422     if (rv != APR_SUCCESS) {
423         fprintf(stderr, "apr_file_seek()->%d/%s\n",
424                 rv,
425                 apr_strerror(rv, buf, sizeof buf));
426         exit(1);
427     }
428
429     printf("After apr_socket_sendfile(), the kernel file pointer is "
430            "at offset %ld.\n",
431            (long int)current_file_offset);
432
433     rv = apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE);
434     if (rv != APR_SUCCESS) {
435         fprintf(stderr, "apr_socket_shutdown()->%d/%s\n",
436                 rv,
437                 apr_strerror(rv, buf, sizeof buf));
438         exit(1);
439     }
440
441     /* in case this is the non-blocking test, set socket timeout;
442      * we're just waiting for EOF */
443
444     rv = apr_socket_timeout_set(sock, apr_time_from_sec(3));
445     if (rv != APR_SUCCESS) {
446         fprintf(stderr, "apr_socket_timeout_set()->%d/%s\n",
447                 rv,
448                 apr_strerror(rv, buf, sizeof buf));
449         exit(1);
450     }
451     
452     bytes_read = 1;
453     rv = apr_socket_recv(sock, buf, &bytes_read);
454     if (rv != APR_EOF) {
455         fprintf(stderr, "apr_socket_recv()->%d/%s (expected APR_EOF)\n",
456                 rv,
457                 apr_strerror(rv, buf, sizeof buf));
458         exit(1);
459     }
460     if (bytes_read != 0) {
461         fprintf(stderr, "We expected to get 0 bytes read with APR_EOF\n"
462                 "but instead we read %ld bytes.\n",
463                 (long int)bytes_read);
464         exit(1);
465     }
466
467     printf("client: apr_socket_sendfile() worked as expected!\n");
468
469     rv = apr_file_remove(TESTFILE, p);
470     if (rv != APR_SUCCESS) {
471         fprintf(stderr, "apr_file_remove()->%d/%s\n",
472                 rv,
473                 apr_strerror(rv, buf, sizeof buf));
474         exit(1);
475     }
476
477     return 0;
478 }
479
480 static int server(void)
481 {
482     apr_status_t rv;
483     apr_socket_t *sock;
484     apr_pool_t *p;
485     char buf[120];
486     int i;
487     apr_socket_t *newsock = NULL;
488     apr_size_t bytes_read;
489     apr_sockaddr_t *localsa;
490     int family;
491
492     family = APR_UNSPEC;
493     apr_setup(&p, &sock, &family);
494
495     rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
496     if (rv != APR_SUCCESS) {
497         fprintf(stderr, "apr_socket_opt_set()->%d/%s\n",
498                 rv,
499                 apr_strerror(rv, buf, sizeof buf));
500         exit(1);
501     }
502
503     rv = apr_sockaddr_info_get(&localsa, NULL, family, TESTSF_PORT, 0, p);
504     if (rv != APR_SUCCESS) {
505         fprintf(stderr, "apr_sockaddr_info_get()->%d/%s\n",
506                 rv,
507                 apr_strerror(rv, buf, sizeof buf));
508         exit(1);
509     }
510
511     rv = apr_socket_bind(sock, localsa);
512     if (rv != APR_SUCCESS) {
513         fprintf(stderr, "apr_socket_bind()->%d/%s\n",
514                 rv,
515                 apr_strerror(rv, buf, sizeof buf));
516         exit(1);
517     }
518
519     rv = apr_socket_listen(sock, 5);
520     if (rv != APR_SUCCESS) {
521         fprintf(stderr, "apr_socket_listen()->%d/%s\n",
522                 rv,
523                 apr_strerror(rv, buf, sizeof buf));
524         exit(1);
525     }
526
527     printf("Waiting for a client to connect...\n");
528
529     rv = apr_socket_accept(&newsock, sock, p);
530     if (rv != APR_SUCCESS) {
531         fprintf(stderr, "apr_socket_accept()->%d/%s\n",
532                 rv,
533                 apr_strerror(rv, buf, sizeof buf));
534         exit(1);
535     }
536
537     printf("Processing a client...\n");
538
539     assert(sizeof buf > strlen(HDR1));
540     bytes_read = strlen(HDR1);
541     rv = apr_socket_recv(newsock, buf, &bytes_read);
542     if (rv != APR_SUCCESS) {
543         fprintf(stderr, "apr_socket_recv()->%d/%s\n",
544                 rv,
545                 apr_strerror(rv, buf, sizeof buf));
546         exit(1);
547     }
548     if (bytes_read != strlen(HDR1)) {
549         fprintf(stderr, "wrong data read (1)\n");
550         exit(1);
551     }
552     if (memcmp(buf, HDR1, strlen(HDR1))) {
553         fprintf(stderr, "wrong data read (2)\n");
554         fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
555                 (int)bytes_read, buf, HDR1);
556         exit(1);
557     }
558         
559     assert(sizeof buf > strlen(HDR2));
560     bytes_read = strlen(HDR2);
561     rv = apr_socket_recv(newsock, buf, &bytes_read);
562     if (rv != APR_SUCCESS) {
563         fprintf(stderr, "apr_socket_recv()->%d/%s\n",
564                 rv,
565                 apr_strerror(rv, buf, sizeof buf));
566         exit(1);
567     }
568     if (bytes_read != strlen(HDR2)) {
569         fprintf(stderr, "wrong data read (3)\n");
570         exit(1);
571     }
572     if (memcmp(buf, HDR2, strlen(HDR2))) {
573         fprintf(stderr, "wrong data read (4)\n");
574         fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
575                 (int)bytes_read, buf, HDR2);
576         exit(1);
577     }
578
579     for (i = 0; i < HDR3_LEN; i++) {
580         bytes_read = 1;
581         rv = apr_socket_recv(newsock, buf, &bytes_read);
582         if (rv != APR_SUCCESS) {
583             fprintf(stderr, "apr_socket_recv()->%d/%s\n",
584                     rv,
585                     apr_strerror(rv, buf, sizeof buf));
586             exit(1);
587         }
588         if (bytes_read != 1) {
589             fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
590                     (long int)bytes_read);
591             exit(1);
592         }
593         if (buf[0] != HDR3_CHAR) {
594             fprintf(stderr,
595                     "problem with data read (byte %d of hdr 3):\n",
596                     i);
597             fprintf(stderr, "read `%c' (0x%x) from client; expected "
598                     "`%c'\n",
599                     buf[0], buf[0], HDR3_CHAR);
600             exit(1);
601         }
602     }
603         
604     for (i = 0; i < FILE_LENGTH; i++) {
605         bytes_read = 1;
606         rv = apr_socket_recv(newsock, buf, &bytes_read);
607         if (rv != APR_SUCCESS) {
608             fprintf(stderr, "apr_socket_recv()->%d/%s\n",
609                     rv,
610                     apr_strerror(rv, buf, sizeof buf));
611             exit(1);
612         }
613         if (bytes_read != 1) {
614             fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
615                     (long int)bytes_read);
616             exit(1);
617         }
618         if (buf[0] != FILE_DATA_CHAR) {
619             fprintf(stderr,
620                     "problem with data read (byte %d of file):\n",
621                     i);
622             fprintf(stderr, "read `%c' (0x%x) from client; expected "
623                     "`%c'\n",
624                     buf[0], buf[0], FILE_DATA_CHAR);
625             exit(1);
626         }
627     }
628         
629     assert(sizeof buf > strlen(TRL1));
630     bytes_read = strlen(TRL1);
631     rv = apr_socket_recv(newsock, buf, &bytes_read);
632     if (rv != APR_SUCCESS) {
633         fprintf(stderr, "apr_socket_recv()->%d/%s\n",
634                 rv,
635                 apr_strerror(rv, buf, sizeof buf));
636         exit(1);
637     }
638     if (bytes_read != strlen(TRL1)) {
639         fprintf(stderr, "wrong data read (5)\n");
640         exit(1);
641     }
642     if (memcmp(buf, TRL1, strlen(TRL1))) {
643         fprintf(stderr, "wrong data read (6)\n");
644         fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
645                 (int)bytes_read, buf, TRL1);
646         exit(1);
647     }
648         
649     assert(sizeof buf > strlen(TRL2));
650     bytes_read = strlen(TRL2);
651     rv = apr_socket_recv(newsock, buf, &bytes_read);
652     if (rv != APR_SUCCESS) {
653         fprintf(stderr, "apr_socket_recv()->%d/%s\n",
654                 rv,
655                 apr_strerror(rv, buf, sizeof buf));
656         exit(1);
657     }
658     if (bytes_read != strlen(TRL2)) {
659         fprintf(stderr, "wrong data read (7)\n");
660         exit(1);
661     }
662     if (memcmp(buf, TRL2, strlen(TRL2))) {
663         fprintf(stderr, "wrong data read (8)\n");
664         fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
665                 (int)bytes_read, buf, TRL2);
666         exit(1);
667     }
668
669     for (i = 0; i < TRL3_LEN; i++) {
670         bytes_read = 1;
671         rv = apr_socket_recv(newsock, buf, &bytes_read);
672         if (rv != APR_SUCCESS) {
673             fprintf(stderr, "apr_socket_recv()->%d/%s\n",
674                     rv,
675                     apr_strerror(rv, buf, sizeof buf));
676             exit(1);
677         }
678         if (bytes_read != 1) {
679             fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
680                     (long int)bytes_read);
681             exit(1);
682         }
683         if (buf[0] != TRL3_CHAR) {
684             fprintf(stderr,
685                     "problem with data read (byte %d of trl 3):\n",
686                     i);
687             fprintf(stderr, "read `%c' (0x%x) from client; expected "
688                     "`%c'\n",
689                     buf[0], buf[0], TRL3_CHAR);
690             exit(1);
691         }
692     }
693         
694     bytes_read = 1;
695     rv = apr_socket_recv(newsock, buf, &bytes_read);
696     if (rv != APR_EOF) {
697         fprintf(stderr, "apr_socket_recv()->%d/%s (expected APR_EOF)\n",
698                 rv,
699                 apr_strerror(rv, buf, sizeof buf));
700         exit(1);
701     }
702     if (bytes_read != 0) {
703         fprintf(stderr, "We expected to get 0 bytes read with APR_EOF\n"
704                 "but instead we read %ld bytes (%c).\n",
705                 (long int)bytes_read, buf[0]);
706         exit(1);
707     }
708
709     printf("server: apr_socket_sendfile() worked as expected!\n");
710
711     return 0;
712 }
713
714 int main(int argc, char *argv[])
715 {
716 #ifdef SIGPIPE
717     signal(SIGPIPE, SIG_IGN);
718 #endif
719
720     /* Gee whiz this is goofy logic but I wanna drive sendfile right now, 
721      * not dork around with the command line!
722      */
723     if (argc >= 3 && !strcmp(argv[1], "client")) {
724         char *host = 0;
725         if (argv[3]) {
726             host = argv[3];
727         }       
728         if (!strcmp(argv[2], "blocking")) {
729             return client(BLK, host);
730         }
731         else if (!strcmp(argv[2], "timeout")) {
732             return client(TIMEOUT, host);
733         }
734         else if (!strcmp(argv[2], "nonblocking")) {
735             return client(NONBLK, host);
736         }
737     }
738     else if (argc == 2 && !strcmp(argv[1], "server")) {
739         return server();
740     }
741
742     fprintf(stderr, 
743             "Usage: %s client {blocking|nonblocking|timeout}\n"
744             "       %s server\n",
745             argv[0], argv[0]);
746     return -1;
747 }
748
749 #endif /* !APR_HAS_SENDFILE */