~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/test/sendfile.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20061209210545-l2c6ssmet17xa2o3
ImportĀ upstreamĀ versionĀ 2.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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, 0, *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_pollset_t *pset;
 
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
        apr_pollfd_t pfd;
 
305
 
 
306
        pset = NULL;
 
307
        rv = apr_pollset_create(&pset, 1, p, 0);
 
308
        assert(!rv);
 
309
        pfd.p = p;
 
310
        pfd.desc_type = APR_POLL_SOCKET;
 
311
        pfd.reqevents = APR_POLLOUT;
 
312
        pfd.rtnevents = 0;
 
313
        pfd.desc.s = sock;
 
314
        pfd.client_data = NULL;
 
315
 
 
316
        rv = apr_pollset_add(pset, &pfd);        
 
317
        assert(!rv);
 
318
 
 
319
        total_bytes_sent = 0;
 
320
        current_file_offset = 0;
 
321
        len = FILE_LENGTH;
 
322
        do {
 
323
            apr_size_t tmplen;
 
324
 
 
325
            tmplen = len; /* bytes remaining to send from the file */
 
326
            printf("Calling apr_socket_sendfile()...\n");
 
327
            printf("Headers (%d):\n", hdtr.numheaders);
 
328
            for (i = 0; i < hdtr.numheaders; i++) {
 
329
                printf("\t%ld bytes (%c)\n",
 
330
                       (long)hdtr.headers[i].iov_len,
 
331
                       *(char *)hdtr.headers[i].iov_base);
 
332
            }
 
333
            printf("File: %ld bytes from offset %ld\n",
 
334
                   (long)tmplen, (long)current_file_offset);
 
335
            printf("Trailers (%d):\n", hdtr.numtrailers);
 
336
            for (i = 0; i < hdtr.numtrailers; i++) {
 
337
                printf("\t%ld bytes\n",
 
338
                       (long)hdtr.trailers[i].iov_len);
 
339
            }
 
340
 
 
341
            rv = apr_socket_sendfile(sock, f, &hdtr, &current_file_offset, &tmplen, 0);
 
342
            printf("apr_socket_sendfile()->%d, sent %ld bytes\n", rv, (long)tmplen);
 
343
            if (rv) {
 
344
                if (APR_STATUS_IS_EAGAIN(rv)) {
 
345
                    assert(tmplen == 0);
 
346
                    nsocks = 1;
 
347
                    tmprv = apr_pollset_poll(pset, -1, &nsocks, NULL);
 
348
                    assert(!tmprv);
 
349
                    assert(nsocks == 1);
 
350
                    /* continue; */
 
351
                }
 
352
            }
 
353
 
 
354
            total_bytes_sent += tmplen;
 
355
 
 
356
            /* Adjust hdtr to compensate for partially-written
 
357
             * data.
 
358
             */
 
359
 
 
360
            /* First, skip over any header data which might have
 
361
             * been written.
 
362
             */
 
363
            while (tmplen && hdtr.numheaders) {
 
364
                if (tmplen >= hdtr.headers[0].iov_len) {
 
365
                    tmplen -= hdtr.headers[0].iov_len;
 
366
                    --hdtr.numheaders;
 
367
                    ++hdtr.headers;
 
368
                }
 
369
                else {
 
370
                    hdtr.headers[0].iov_len -= tmplen;
 
371
                    hdtr.headers[0].iov_base = 
 
372
                        (char*) hdtr.headers[0].iov_base + tmplen;
 
373
                    tmplen = 0;
 
374
                }
 
375
            }
 
376
 
 
377
            /* Now, skip over any file data which might have been
 
378
             * written.
 
379
             */
 
380
 
 
381
            if (tmplen <= len) {
 
382
                current_file_offset += tmplen;
 
383
                len -= tmplen;
 
384
                tmplen = 0;
 
385
            }
 
386
            else {
 
387
                tmplen -= len;
 
388
                len = 0;
 
389
                current_file_offset = 0;
 
390
            }
 
391
 
 
392
            /* Last, skip over any trailer data which might have
 
393
             * been written.
 
394
             */
 
395
 
 
396
            while (tmplen && hdtr.numtrailers) {
 
397
                if (tmplen >= hdtr.trailers[0].iov_len) {
 
398
                    tmplen -= hdtr.trailers[0].iov_len;
 
399
                    --hdtr.numtrailers;
 
400
                    ++hdtr.trailers;
 
401
                }
 
402
                else {
 
403
                    hdtr.trailers[0].iov_len -= tmplen;
 
404
                    hdtr.trailers[0].iov_base = 
 
405
                        (char *)hdtr.trailers[0].iov_base + tmplen;
 
406
                    tmplen = 0;
 
407
                }
 
408
            }
 
409
 
 
410
        } while (total_bytes_sent < expected_len &&
 
411
                 (rv == APR_SUCCESS || 
 
412
                 (APR_STATUS_IS_EAGAIN(rv) && socket_mode != TIMEOUT)));
 
413
        if (total_bytes_sent != expected_len) {
 
414
            fprintf(stderr,
 
415
                    "client problem: sent %ld of %ld bytes\n",
 
416
                    (long)total_bytes_sent, (long)expected_len);
 
417
            exit(1);
 
418
        }
 
419
 
 
420
        if (rv) {
 
421
            fprintf(stderr,
 
422
                    "client problem: rv %d\n",
 
423
                    rv);
 
424
            exit(1);
 
425
        }
 
426
    }
 
427
    
 
428
    current_file_offset = 0;
 
429
    rv = apr_file_seek(f, APR_CUR, &current_file_offset);
 
430
    if (rv != APR_SUCCESS) {
 
431
        fprintf(stderr, "apr_file_seek()->%d/%s\n",
 
432
                rv,
 
433
                apr_strerror(rv, buf, sizeof buf));
 
434
        exit(1);
 
435
    }
 
436
 
 
437
    printf("After apr_socket_sendfile(), the kernel file pointer is "
 
438
           "at offset %ld.\n",
 
439
           (long int)current_file_offset);
 
440
 
 
441
    rv = apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE);
 
442
    if (rv != APR_SUCCESS) {
 
443
        fprintf(stderr, "apr_socket_shutdown()->%d/%s\n",
 
444
                rv,
 
445
                apr_strerror(rv, buf, sizeof buf));
 
446
        exit(1);
 
447
    }
 
448
 
 
449
    /* in case this is the non-blocking test, set socket timeout;
 
450
     * we're just waiting for EOF */
 
451
 
 
452
    rv = apr_socket_timeout_set(sock, apr_time_from_sec(3));
 
453
    if (rv != APR_SUCCESS) {
 
454
        fprintf(stderr, "apr_socket_timeout_set()->%d/%s\n",
 
455
                rv,
 
456
                apr_strerror(rv, buf, sizeof buf));
 
457
        exit(1);
 
458
    }
 
459
    
 
460
    bytes_read = 1;
 
461
    rv = apr_socket_recv(sock, buf, &bytes_read);
 
462
    if (rv != APR_EOF) {
 
463
        fprintf(stderr, "apr_socket_recv()->%d/%s (expected APR_EOF)\n",
 
464
                rv,
 
465
                apr_strerror(rv, buf, sizeof buf));
 
466
        exit(1);
 
467
    }
 
468
    if (bytes_read != 0) {
 
469
        fprintf(stderr, "We expected to get 0 bytes read with APR_EOF\n"
 
470
                "but instead we read %ld bytes.\n",
 
471
                (long int)bytes_read);
 
472
        exit(1);
 
473
    }
 
474
 
 
475
    printf("client: apr_socket_sendfile() worked as expected!\n");
 
476
 
 
477
    rv = apr_file_remove(TESTFILE, p);
 
478
    if (rv != APR_SUCCESS) {
 
479
        fprintf(stderr, "apr_file_remove()->%d/%s\n",
 
480
                rv,
 
481
                apr_strerror(rv, buf, sizeof buf));
 
482
        exit(1);
 
483
    }
 
484
 
 
485
    return 0;
 
486
}
 
487
 
 
488
static int server(void)
 
489
{
 
490
    apr_status_t rv;
 
491
    apr_socket_t *sock;
 
492
    apr_pool_t *p;
 
493
    char buf[120];
 
494
    int i;
 
495
    apr_socket_t *newsock = NULL;
 
496
    apr_size_t bytes_read;
 
497
    apr_sockaddr_t *localsa;
 
498
    int family;
 
499
 
 
500
    family = APR_UNSPEC;
 
501
    apr_setup(&p, &sock, &family);
 
502
 
 
503
    rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
 
504
    if (rv != APR_SUCCESS) {
 
505
        fprintf(stderr, "apr_socket_opt_set()->%d/%s\n",
 
506
                rv,
 
507
                apr_strerror(rv, buf, sizeof buf));
 
508
        exit(1);
 
509
    }
 
510
 
 
511
    rv = apr_sockaddr_info_get(&localsa, NULL, family, TESTSF_PORT, 0, p);
 
512
    if (rv != APR_SUCCESS) {
 
513
        fprintf(stderr, "apr_sockaddr_info_get()->%d/%s\n",
 
514
                rv,
 
515
                apr_strerror(rv, buf, sizeof buf));
 
516
        exit(1);
 
517
    }
 
518
 
 
519
    rv = apr_socket_bind(sock, localsa);
 
520
    if (rv != APR_SUCCESS) {
 
521
        fprintf(stderr, "apr_socket_bind()->%d/%s\n",
 
522
                rv,
 
523
                apr_strerror(rv, buf, sizeof buf));
 
524
        exit(1);
 
525
    }
 
526
 
 
527
    rv = apr_socket_listen(sock, 5);
 
528
    if (rv != APR_SUCCESS) {
 
529
        fprintf(stderr, "apr_socket_listen()->%d/%s\n",
 
530
                rv,
 
531
                apr_strerror(rv, buf, sizeof buf));
 
532
        exit(1);
 
533
    }
 
534
 
 
535
    printf("Waiting for a client to connect...\n");
 
536
 
 
537
    rv = apr_socket_accept(&newsock, sock, p);
 
538
    if (rv != APR_SUCCESS) {
 
539
        fprintf(stderr, "apr_socket_accept()->%d/%s\n",
 
540
                rv,
 
541
                apr_strerror(rv, buf, sizeof buf));
 
542
        exit(1);
 
543
    }
 
544
 
 
545
    printf("Processing a client...\n");
 
546
 
 
547
    assert(sizeof buf > strlen(HDR1));
 
548
    bytes_read = strlen(HDR1);
 
549
    rv = apr_socket_recv(newsock, buf, &bytes_read);
 
550
    if (rv != APR_SUCCESS) {
 
551
        fprintf(stderr, "apr_socket_recv()->%d/%s\n",
 
552
                rv,
 
553
                apr_strerror(rv, buf, sizeof buf));
 
554
        exit(1);
 
555
    }
 
556
    if (bytes_read != strlen(HDR1)) {
 
557
        fprintf(stderr, "wrong data read (1)\n");
 
558
        exit(1);
 
559
    }
 
560
    if (memcmp(buf, HDR1, strlen(HDR1))) {
 
561
        fprintf(stderr, "wrong data read (2)\n");
 
562
        fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
 
563
                (int)bytes_read, buf, HDR1);
 
564
        exit(1);
 
565
    }
 
566
        
 
567
    assert(sizeof buf > strlen(HDR2));
 
568
    bytes_read = strlen(HDR2);
 
569
    rv = apr_socket_recv(newsock, buf, &bytes_read);
 
570
    if (rv != APR_SUCCESS) {
 
571
        fprintf(stderr, "apr_socket_recv()->%d/%s\n",
 
572
                rv,
 
573
                apr_strerror(rv, buf, sizeof buf));
 
574
        exit(1);
 
575
    }
 
576
    if (bytes_read != strlen(HDR2)) {
 
577
        fprintf(stderr, "wrong data read (3)\n");
 
578
        exit(1);
 
579
    }
 
580
    if (memcmp(buf, HDR2, strlen(HDR2))) {
 
581
        fprintf(stderr, "wrong data read (4)\n");
 
582
        fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
 
583
                (int)bytes_read, buf, HDR2);
 
584
        exit(1);
 
585
    }
 
586
 
 
587
    for (i = 0; i < HDR3_LEN; i++) {
 
588
        bytes_read = 1;
 
589
        rv = apr_socket_recv(newsock, buf, &bytes_read);
 
590
        if (rv != APR_SUCCESS) {
 
591
            fprintf(stderr, "apr_socket_recv()->%d/%s\n",
 
592
                    rv,
 
593
                    apr_strerror(rv, buf, sizeof buf));
 
594
            exit(1);
 
595
        }
 
596
        if (bytes_read != 1) {
 
597
            fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
 
598
                    (long int)bytes_read);
 
599
            exit(1);
 
600
        }
 
601
        if (buf[0] != HDR3_CHAR) {
 
602
            fprintf(stderr,
 
603
                    "problem with data read (byte %d of hdr 3):\n",
 
604
                    i);
 
605
            fprintf(stderr, "read `%c' (0x%x) from client; expected "
 
606
                    "`%c'\n",
 
607
                    buf[0], buf[0], HDR3_CHAR);
 
608
            exit(1);
 
609
        }
 
610
    }
 
611
        
 
612
    for (i = 0; i < FILE_LENGTH; i++) {
 
613
        bytes_read = 1;
 
614
        rv = apr_socket_recv(newsock, buf, &bytes_read);
 
615
        if (rv != APR_SUCCESS) {
 
616
            fprintf(stderr, "apr_socket_recv()->%d/%s\n",
 
617
                    rv,
 
618
                    apr_strerror(rv, buf, sizeof buf));
 
619
            exit(1);
 
620
        }
 
621
        if (bytes_read != 1) {
 
622
            fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
 
623
                    (long int)bytes_read);
 
624
            exit(1);
 
625
        }
 
626
        if (buf[0] != FILE_DATA_CHAR) {
 
627
            fprintf(stderr,
 
628
                    "problem with data read (byte %d of file):\n",
 
629
                    i);
 
630
            fprintf(stderr, "read `%c' (0x%x) from client; expected "
 
631
                    "`%c'\n",
 
632
                    buf[0], buf[0], FILE_DATA_CHAR);
 
633
            exit(1);
 
634
        }
 
635
    }
 
636
        
 
637
    assert(sizeof buf > strlen(TRL1));
 
638
    bytes_read = strlen(TRL1);
 
639
    rv = apr_socket_recv(newsock, buf, &bytes_read);
 
640
    if (rv != APR_SUCCESS) {
 
641
        fprintf(stderr, "apr_socket_recv()->%d/%s\n",
 
642
                rv,
 
643
                apr_strerror(rv, buf, sizeof buf));
 
644
        exit(1);
 
645
    }
 
646
    if (bytes_read != strlen(TRL1)) {
 
647
        fprintf(stderr, "wrong data read (5)\n");
 
648
        exit(1);
 
649
    }
 
650
    if (memcmp(buf, TRL1, strlen(TRL1))) {
 
651
        fprintf(stderr, "wrong data read (6)\n");
 
652
        fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
 
653
                (int)bytes_read, buf, TRL1);
 
654
        exit(1);
 
655
    }
 
656
        
 
657
    assert(sizeof buf > strlen(TRL2));
 
658
    bytes_read = strlen(TRL2);
 
659
    rv = apr_socket_recv(newsock, buf, &bytes_read);
 
660
    if (rv != APR_SUCCESS) {
 
661
        fprintf(stderr, "apr_socket_recv()->%d/%s\n",
 
662
                rv,
 
663
                apr_strerror(rv, buf, sizeof buf));
 
664
        exit(1);
 
665
    }
 
666
    if (bytes_read != strlen(TRL2)) {
 
667
        fprintf(stderr, "wrong data read (7)\n");
 
668
        exit(1);
 
669
    }
 
670
    if (memcmp(buf, TRL2, strlen(TRL2))) {
 
671
        fprintf(stderr, "wrong data read (8)\n");
 
672
        fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n",
 
673
                (int)bytes_read, buf, TRL2);
 
674
        exit(1);
 
675
    }
 
676
 
 
677
    for (i = 0; i < TRL3_LEN; i++) {
 
678
        bytes_read = 1;
 
679
        rv = apr_socket_recv(newsock, buf, &bytes_read);
 
680
        if (rv != APR_SUCCESS) {
 
681
            fprintf(stderr, "apr_socket_recv()->%d/%s\n",
 
682
                    rv,
 
683
                    apr_strerror(rv, buf, sizeof buf));
 
684
            exit(1);
 
685
        }
 
686
        if (bytes_read != 1) {
 
687
            fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n",
 
688
                    (long int)bytes_read);
 
689
            exit(1);
 
690
        }
 
691
        if (buf[0] != TRL3_CHAR) {
 
692
            fprintf(stderr,
 
693
                    "problem with data read (byte %d of trl 3):\n",
 
694
                    i);
 
695
            fprintf(stderr, "read `%c' (0x%x) from client; expected "
 
696
                    "`%c'\n",
 
697
                    buf[0], buf[0], TRL3_CHAR);
 
698
            exit(1);
 
699
        }
 
700
    }
 
701
        
 
702
    bytes_read = 1;
 
703
    rv = apr_socket_recv(newsock, buf, &bytes_read);
 
704
    if (rv != APR_EOF) {
 
705
        fprintf(stderr, "apr_socket_recv()->%d/%s (expected APR_EOF)\n",
 
706
                rv,
 
707
                apr_strerror(rv, buf, sizeof buf));
 
708
        exit(1);
 
709
    }
 
710
    if (bytes_read != 0) {
 
711
        fprintf(stderr, "We expected to get 0 bytes read with APR_EOF\n"
 
712
                "but instead we read %ld bytes (%c).\n",
 
713
                (long int)bytes_read, buf[0]);
 
714
        exit(1);
 
715
    }
 
716
 
 
717
    printf("server: apr_socket_sendfile() worked as expected!\n");
 
718
 
 
719
    return 0;
 
720
}
 
721
 
 
722
int main(int argc, char *argv[])
 
723
{
 
724
#ifdef SIGPIPE
 
725
    signal(SIGPIPE, SIG_IGN);
 
726
#endif
 
727
 
 
728
    /* Gee whiz this is goofy logic but I wanna drive sendfile right now, 
 
729
     * not dork around with the command line!
 
730
     */
 
731
    if (argc >= 3 && !strcmp(argv[1], "client")) {
 
732
        char *host = 0;
 
733
        if (argv[3]) {
 
734
            host = argv[3];
 
735
        }       
 
736
        if (!strcmp(argv[2], "blocking")) {
 
737
            return client(BLK, host);
 
738
        }
 
739
        else if (!strcmp(argv[2], "timeout")) {
 
740
            return client(TIMEOUT, host);
 
741
        }
 
742
        else if (!strcmp(argv[2], "nonblocking")) {
 
743
            return client(NONBLK, host);
 
744
        }
 
745
    }
 
746
    else if (argc == 2 && !strcmp(argv[1], "server")) {
 
747
        return server();
 
748
    }
 
749
 
 
750
    fprintf(stderr, 
 
751
            "Usage: %s client {blocking|nonblocking|timeout}\n"
 
752
            "       %s server\n",
 
753
            argv[0], argv[0]);
 
754
    return -1;
 
755
}
 
756
 
 
757
#endif /* !APR_HAS_SENDFILE */