varnish-cache/bin/varnishtest/vtc_http.c
1
/*-
2
 * Copyright (c) 2008-2019 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include "config.h"
30
31
#include <sys/socket.h>
32
33
#include <math.h>
34
#include <poll.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <unistd.h>
38
#include <string.h>
39
40
#include "vtc.h"
41
#include "vtc_http.h"
42
43
#include "vct.h"
44
#include "vfil.h"
45
#include "vnum.h"
46
#include "vrnd.h"
47
#include "vtcp.h"
48
#include "hpack.h"
49
50
extern const struct cmds http_cmds[];
51
52
/* SECTION: client-server client/server
53
 *
54
 * Client and server threads are fake HTTP entities used to test your Varnish
55
 * and VCL. They take any number of arguments, and the one that are not
56
 * recognized, assuming they don't start with '-', are treated as
57
 * specifications, laying out the actions to undertake::
58
 *
59
 *         client cNAME [...]
60
 *         server sNAME [...]
61
 *
62
 * Clients and server are identified by a string that's the first argument,
63
 * clients' names start with 'c' and servers' names start with 's'.
64
 *
65
 * As the client and server commands share a good deal of arguments and
66
 * specification actions, they are grouped in this single section, specific
67
 * items will be explicitly marked as such.
68
 *
69
 * SECTION: client-server.macros Macros and automatic behaviour
70
 *
71
 * To make things easier in the general case, clients will connect by default
72
 * to a Varnish server called v1. To connect to a different Varnish server, use
73
 * '-connect ${vNAME_sock}'.
74
 *
75
 * The -vcl+backend switch of the ``varnish`` command will add all the declared
76
 * servers as backends. Be careful though, servers will by default listen to
77
 * the 127.0.0.1 IP and will pick a random port, and publish 3 macros:
78
 * sNAME_addr, sNAME_port and sNAME_sock, but only once they are started. For
79
 * 'varnish -vcl+backend' to create the vcl with the correct values, the server
80
 * must be started first.
81
 *
82
 * SECTION: client-server.args Arguments
83
 *
84
 * \-start
85
 *        Start the thread in background, processing the last given
86
 *        specification.
87
 *
88
 * \-wait
89
 *        Block until the thread finishes.
90
 *
91
 * \-run (client only)
92
 *        Equivalent to "-start -wait".
93
 *
94
 * \-repeat NUMBER
95
 *        Instead of processing the specification only once, do it NUMBER times.
96
 *
97
 * \-keepalive
98
 *        For repeat, do not open new connections but rather run all
99
 *        iterations in the same connection
100
 *
101
 * \-break (server only)
102
 *        Stop the server.
103
 *
104
 * \-listen STRING (server only)
105
 *        Dictate the listening socket for the server. STRING is of the form
106
 *        "IP PORT", or "/PATH/TO/SOCKET" for a Unix domain socket. In the
107
 *        latter case, the path must begin with '/', and the server must be
108
 *        able to create it.
109
 *
110
 * \-connect STRING (client only)
111
 *        Indicate the server to connect to. STRING is also of the form
112
 *        "IP PORT", or "/PATH/TO/SOCKET". As with "server -listen", a
113
 *        Unix domain socket is recognized when STRING begins with a '/'.
114
 *
115
 * \-dispatch (server only, s0 only)
116
 *        Normally, to keep things simple, server threads only handle one
117
 *        connection at a time, but the -dispatch switch allows to accept
118
 *        any number of connection and handle them following the given spec.
119
 *
120
 *        However, -dispatch is only allowed for the server name "s0".
121
 *
122
 * \-proxy1 STRING (client only)
123
 *        Use the PROXY protocol version 1 for this connection. STRING
124
 *        is of the form "CLIENTIP:PORT SERVERIP:PORT".
125
 *
126
 * \-proxy2 STRING (client only)
127
 *        Use the PROXY protocol version 2 for this connection. STRING
128
 *        is of the form "CLIENTIP:PORT SERVERIP:PORT".
129
 *
130
 * SECTION: client-server.spec Specification
131
 *
132
 * It's a string, either double-quoted "like this", but most of the time
133
 * enclosed in curly brackets, allowing multilining. Write a command per line in
134
 * it, empty line are ignored, and long line can be wrapped by using a
135
 * backslash. For example::
136
 *
137
 *     client c1 {
138
 *         txreq -url /foo \
139
 *               -hdr "bar: baz"
140
 *
141
 *         rxresp
142
 *     } -run
143
 */
144
145
#define ONLY_CLIENT(hp, av)                                             \
146
        do {                                                            \
147
                if (hp->h2)                                             \
148
                        vtc_fatal(hp->vl,                               \
149
                            "\"%s\" only possible before H/2 upgrade",  \
150
                                        av[0]);                         \
151
                if (hp->sfd != NULL)                                    \
152
                        vtc_fatal(hp->vl,                               \
153
                            "\"%s\" only possible in client", av[0]);   \
154
        } while (0)
155
156
#define ONLY_SERVER(hp, av)                                             \
157
        do {                                                            \
158
                if (hp->h2)                                             \
159
                        vtc_fatal(hp->vl,                               \
160
                            "\"%s\" only possible before H/2 upgrade",  \
161
                                        av[0]);                         \
162
                if (hp->sfd == NULL)                                    \
163
                        vtc_fatal(hp->vl,                               \
164
                            "\"%s\" only possible in server", av[0]);   \
165
        } while (0)
166
167
168
/* XXX: we may want to vary this */
169
static const char * const nl = "\r\n";
170
171
/**********************************************************************
172
 * Generate a synthetic body
173
 */
174
175
char *
176 3200
synth_body(const char *len, int rnd)
177
{
178
        int i, j, k, l;
179
        char *b;
180
181
182 3200
        AN(len);
183 3200
        i = strtoul(len, NULL, 0);
184 3200
        assert(i > 0);
185 3200
        b = malloc(i + 1L);
186 3200
        AN(b);
187 3200
        l = k = '!';
188 332989824
        for (j = 0; j < i; j++) {
189 332986624
                if ((j % 64) == 63) {
190 5202128
                        b[j] = '\n';
191 5202128
                        k++;
192 5202128
                        if (k == '~')
193 55616
                                k = '!';
194 5202128
                        l = k;
195 332986624
                } else if (rnd) {
196 66048
                        b[j] = (VRND_RandomTestable() % 95) + ' ';
197 66048
                } else {
198 327718448
                        b[j] = (char)l;
199 327718448
                        if (++l == '~')
200 3516864
                                l = '!';
201
                }
202 332986624
        }
203 3200
        b[i - 1] = '\n';
204 3200
        b[i] = '\0';
205 3200
        return (b);
206
}
207
208
/**********************************************************************
209
 * Finish and write the vsb to the fd
210
 */
211
212
static void
213 69069
http_write(const struct http *hp, int lvl, const char *pfx)
214
{
215
216 69069
        AZ(VSB_finish(hp->vsb));
217 69070
        vtc_dump(hp->vl, lvl, pfx, VSB_data(hp->vsb), VSB_len(hp->vsb));
218 69070
        if (VSB_tofile(hp->fd, hp->vsb))
219 128
                vtc_log(hp->vl, hp->fatal, "Write failed: %s",
220 64
                    strerror(errno));
221 69070
}
222
223
/**********************************************************************
224
 * find header
225
 */
226
227
static char *
228 181447
http_find_header(char * const *hh, const char *hdr)
229
{
230
        int n, l;
231
        char *r;
232
233 181447
        l = strlen(hdr);
234
235 1129986
        for (n = 3; hh[n] != NULL; n++) {
236 1027682
                if (strncasecmp(hdr, hh[n], l) || hh[n][l] != ':')
237 948548
                        continue;
238 158493
                for (r = hh[n] + l + 1; vct_issp(*r); r++)
239 79342
                        continue;
240 79149
                return (r);
241
        }
242 102299
        return (NULL);
243 181448
}
244
245
/**********************************************************************
246
 * count header
247
 */
248
249
static int
250 69182
http_count_header(char * const *hh, const char *hdr)
251
{
252 69182
        int n, l, r = 0;
253
254 69182
        l = strlen(hdr);
255
256 489538
        for (n = 3; hh[n] != NULL; n++) {
257 420343
                if (strncasecmp(hdr, hh[n], l) || hh[n][l] != ':')
258 386202
                        continue;
259 34159
                r++;
260 34159
        }
261 69181
        return (r);
262
}
263
264
/* SECTION: client-server.spec.expect
265
 *
266
 * expect STRING1 OP STRING2
267
 *         Test if "STRING1 OP STRING2" is true, and if not, fails the test.
268
 *         OP can be ==, <, <=, >, >= when STRING1 and STRING2 represent numbers
269
 *         in which case it's an order operator. If STRING1 and STRING2 are
270
 *         meant as strings OP is a matching operator, either == (exact match)
271
 *         or ~ (regex match).
272
 *
273
 *         varnishtet will first try to resolve STRING1 and STRING2 by looking
274
 *         if they have special meanings, in which case, the resolved value is
275
 *         use for the test. Note that this value can be a string representing a
276
 *         number, allowing for tests such as::
277
 *
278
 *                 expect req.http.x-num > 2
279
 *
280
 *         Here's the list of recognized strings, most should be obvious as they
281
 *         either match VCL logic, or the txreq/txresp options:
282
 *
283
 *         - remote.ip
284
 *         - remote.port
285
 *         - remote.path
286
 *         - req.method
287
 *         - req.url
288
 *         - req.proto
289
 *         - resp.proto
290
 *         - resp.status
291
 *         - resp.reason
292
 *         - resp.chunklen
293
 *         - req.bodylen
294
 *         - req.body
295
 *         - resp.bodylen
296
 *         - resp.body
297
 *         - req.http.NAME
298
 *         - resp.http.NAME
299
 */
300
301
static const char *
302 176934
cmd_var_resolve(struct http *hp, char *spec)
303
{
304
        char **hh, *hdr;
305 176934
        if (!strcmp(spec, "remote.ip"))
306 64
                return (hp->rem_ip);
307 176915
        if (!strcmp(spec, "remote.port"))
308 64
                return (hp->rem_port);
309 176845
        if (!strcmp(spec, "remote.path"))
310 64
                return (hp->rem_path);
311 176788
        if (!strcmp(spec, "req.method"))
312 656
                return (hp->req[0]);
313 176135
        if (!strcmp(spec, "req.url"))
314 8912
                return (hp->req[1]);
315 167221
        if (!strcmp(spec, "req.proto"))
316 688
                return (hp->req[2]);
317 166529
        if (!strcmp(spec, "resp.proto"))
318 544
                return (hp->resp[0]);
319 165997
        if (!strcmp(spec, "resp.status"))
320 21040
                return (hp->resp[1]);
321 144950
        if (!strcmp(spec, "resp.reason"))
322 2208
                return (hp->resp[2]);
323 142745
        if (!strcmp(spec, "resp.chunklen"))
324 0
                return (hp->chunklen);
325 142749
        if (!strcmp(spec, "req.bodylen"))
326 256
                return (hp->bodylen);
327 142484
        if (!strcmp(spec, "req.body"))
328 48
                return (hp->body != NULL ? hp->body : spec);
329 142444
        if (!strcmp(spec, "resp.bodylen"))
330 9600
                return (hp->bodylen);
331 132843
        if (!strcmp(spec, "resp.body"))
332 2432
                return (hp->body != NULL ? hp->body : spec);
333 130410
        if (!strncmp(spec, "req.http.", 9)) {
334 3840
                hh = hp->req;
335 3840
                hdr = spec + 9;
336 130413
        } else if (!strncmp(spec, "resp.http.", 10)) {
337 40224
                hh = hp->resp;
338 40224
                hdr = spec + 10;
339 126572
        } else if (!strcmp(spec, "h2.state")) {
340 112
                if (hp->h2)
341 48
                        return ("true");
342
                else
343 64
                        return ("false");
344
        } else
345 86238
                return (spec);
346 44064
        hdr = http_find_header(hh, hdr);
347 44064
        return (hdr);
348 176988
}
349
350
static void
351 88478
cmd_http_expect(CMD_ARGS)
352
{
353
        struct http *hp;
354
        const char *lhs;
355
        char *cmp;
356
        const char *rhs;
357
358 88478
        (void)cmd;
359 88478
        (void)vl;
360 88478
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
361 88492
        AZ(strcmp(av[0], "expect"));
362 88494
        av++;
363
364 88494
        AN(av[0]);
365 88493
        AN(av[1]);
366 88491
        AN(av[2]);
367 88486
        AZ(av[3]);
368 88491
        lhs = cmd_var_resolve(hp, av[0]);
369 88491
        cmp = av[1];
370 88491
        rhs = cmd_var_resolve(hp, av[2]);
371
372 88491
        vtc_expect(vl, av[0], lhs, cmp, av[2], rhs);
373 88491
}
374
375
static void
376 64
cmd_http_expect_pattern(CMD_ARGS)
377
{
378
        char *p;
379
        struct http *hp;
380 64
        char t = '0';
381
382 64
        (void)cmd;
383 64
        (void)vl;
384 64
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
385 64
        AZ(strcmp(av[0], "expect_pattern"));
386 64
        av++;
387 64
        AZ(av[0]);
388 4194368
        for (p = hp->body; *p != '\0'; p++) {
389 4194304
                if (*p != t)
390 0
                        vtc_fatal(hp->vl,
391
                            "EXPECT PATTERN FAIL @%zd should 0x%02x is 0x%02x",
392 0
                            p - hp->body, t, *p);
393 4194304
                t += 1;
394 4194304
                t &= ~0x08;
395 4194304
        }
396 64
        vtc_log(hp->vl, 4, "EXPECT PATTERN SUCCESS");
397 64
}
398
399
/**********************************************************************
400
 * Split a HTTP protocol header
401
 */
402
403
static void
404 69182
http_splitheader(struct http *hp, int req)
405
{
406
        char *p, *q, **hh;
407
        int n;
408
        char buf[20];
409
410 69182
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
411 69182
        if (req) {
412 30398
                memset(hp->req, 0, sizeof hp->req);
413 30398
                hh = hp->req;
414 30398
        } else {
415 38784
                memset(hp->resp, 0, sizeof hp->resp);
416 38784
                hh = hp->resp;
417
        }
418
419 69182
        n = 0;
420 69182
        p = hp->rx_b;
421 69182
        if (*p == '\0') {
422 0
                vtc_log(hp->vl, 4, "No headers");
423 0
                return;
424
        }
425
426
        /* REQ/PROTO */
427 69182
        while (vct_islws(*p))
428 0
                p++;
429 69182
        hh[n++] = p;
430 471397
        while (!vct_islws(*p))
431 402216
                p++;
432 69182
        AZ(vct_iscrlf(p, hp->rx_e));
433 69182
        *p++ = '\0';
434
435
        /* URL/STATUS */
436 69182
        while (vct_issp(*p))            /* XXX: H space only */
437 0
                p++;
438 69182
        AZ(vct_iscrlf(p, hp->rx_e));
439 69182
        hh[n++] = p;
440 362023
        while (!vct_islws(*p))
441 292841
                p++;
442 69181
        if (vct_iscrlf(p, hp->rx_e)) {
443 16
                hh[n++] = NULL;
444 16
                q = p;
445 16
                p = vct_skipcrlf(p, hp->rx_e);
446 16
                *q = '\0';
447 16
        } else {
448 69165
                *p++ = '\0';
449
                /* PROTO/MSG */
450 69165
                while (vct_issp(*p))            /* XXX: H space only */
451 0
                        p++;
452 69165
                hh[n++] = p;
453 485014
                while (!vct_iscrlf(p, hp->rx_e))
454 415849
                        p++;
455 69166
                q = p;
456 69166
                p = vct_skipcrlf(p, hp->rx_e);
457 69166
                *q = '\0';
458
        }
459 69182
        assert(n == 3);
460
461 489539
        while (*p != '\0') {
462 489532
                assert(n < MAX_HDR);
463 489524
                if (vct_iscrlf(p, hp->rx_e))
464 69167
                        break;
465 420352
                hh[n++] = p++;
466 10567069
                while (*p != '\0' && !vct_iscrlf(p, hp->rx_e))
467 10146717
                        p++;
468 420376
                if (*p == '\0') {
469 15
                        break;
470
                }
471 420357
                q = p;
472 420357
                p = vct_skipcrlf(p, hp->rx_e);
473 420357
                *q = '\0';
474
        }
475 69182
        p = vct_skipcrlf(p, hp->rx_e);
476 69182
        assert(*p == '\0');
477
478 697110
        for (n = 0; n < 3 || hh[n] != NULL; n++) {
479 627910
                bprintf(buf, "http[%2d] ", n);
480 627916
                vtc_dump(hp->vl, 4, buf, hh[n], -1);
481 627916
        }
482 69182
}
483
484
485
/**********************************************************************
486
 * Receive another character
487
 */
488
489
static int
490 16214353
http_rxchar(struct http *hp, int n, int eof)
491
{
492
        int i;
493
        struct pollfd pfd[1];
494
495 32423301
        while (n > 0) {
496 16212376
                pfd[0].fd = hp->fd;
497 16212376
                pfd[0].events = POLLIN;
498 16212376
                pfd[0].revents = 0;
499 16212376
                i = poll(pfd, 1, hp->timeout);
500 16212376
                if (i < 0 && errno == EINTR)
501 0
                        continue;
502 16208477
                if (i == 0) {
503 0
                        vtc_log(hp->vl, hp->fatal,
504
                            "HTTP rx timeout (fd:%d %u ms)",
505 0
                            hp->fd, hp->timeout);
506 0
                        continue;
507
                }
508 16209443
                if (i < 0) {
509 0
                        vtc_log(hp->vl, hp->fatal,
510
                            "HTTP rx failed (fd:%d poll: %s)",
511 0
                            hp->fd, strerror(errno));
512 0
                        continue;
513
                }
514 16210479
                assert(i > 0);
515 16209263
                assert(hp->rx_p + n < hp->rx_e);
516 16211025
                i = read(hp->fd, hp->rx_p, n);
517 16211025
                if (!(pfd[0].revents & POLLIN))
518 0
                        vtc_log(hp->vl, 4,
519
                            "HTTP rx poll (fd:%d revents: %x n=%d, i=%d)",
520 0
                            hp->fd, pfd[0].revents, n, i);
521 16207608
                if (i == 0 && eof)
522 95
                        return (i);
523 16209292
                if (i == 0) {
524 96
                        vtc_log(hp->vl, hp->fatal,
525
                            "HTTP rx EOF (fd:%d read: %s) %d",
526 48
                            hp->fd, strerror(errno), n);
527 48
                        return (-1);
528
                }
529 16208559
                if (i < 0) {
530 0
                        vtc_log(hp->vl, hp->fatal,
531
                            "HTTP rx failed (fd:%d read: %s)",
532 0
                            hp->fd, strerror(errno));
533 0
                        return (-1);
534
                }
535 16208948
                hp->rx_p += i;
536 16208948
                *hp->rx_p = '\0';
537 16208948
                n -= i;
538
        }
539 16216432
        return (1);
540 16216923
}
541
542
static int
543 15551
http_rxchunk(struct http *hp)
544
{
545
        char *q, *old;
546
        int i;
547
548 15551
        old = hp->rx_p;
549 15551
        do {
550 75916
                if (http_rxchar(hp, 1, 0) < 0)
551 16
                        return (-1);
552 75896
        } while (hp->rx_p[-1] != '\n');
553 15535
        vtc_dump(hp->vl, 4, "len", old, -1);
554 15535
        i = strtoul(old, &q, 16);
555 15535
        bprintf(hp->chunklen, "%d", i);
556 15535
        if ((q == old) || (q == hp->rx_p) || (*q != '\0' && !vct_islws(*q))) {
557 0
                vtc_log(hp->vl, hp->fatal, "Chunklen fail (%02x @ %td)",
558 0
                    (*q & 0xff), q - old);
559 0
                return (-1);
560
        }
561 15533
        assert(*q == '\0' || vct_islws(*q));
562 15534
        hp->rx_p = old;
563 15534
        if (i > 0) {
564 12029
                if (http_rxchar(hp, i, 0) < 0)
565 0
                        return (-1);
566 12029
                vtc_dump(hp->vl, 4, "chunk", old, i);
567 12029
        }
568 15535
        old = hp->rx_p;
569 15535
        if (http_rxchar(hp, 2, 0) < 0)
570 0
                return (-1);
571 15535
        if (!vct_iscrlf(old, hp->rx_e)) {
572 0
                vtc_log(hp->vl, hp->fatal, "Chunklen without CRLF");
573 0
                return (-1);
574
        }
575 15535
        hp->rx_p = old;
576 15535
        *hp->rx_p = '\0';
577 15535
        return (i);
578 15551
}
579
580
/**********************************************************************
581
 * Swallow a HTTP message body
582
 *
583
 * max: 0 is all
584
 */
585
586
static void
587 68670
http_swallow_body(struct http *hp, char * const *hh, int body, int max)
588
{
589
        const char *p, *q;
590
        int i, l, ll;
591
592 68670
        l = hp->rx_p - hp->body;
593
594 68670
        p = http_find_header(hh, "transfer-encoding");
595 68670
        q = http_find_header(hh, "content-length");
596 68670
        if (p != NULL && !strcasecmp(p, "chunked")) {
597 3617
                if (q != NULL) {
598 0
                        vtc_log(hp->vl, hp->fatal, "Both C-E: Chunked and C-L");
599 0
                        return;
600
                }
601 3617
                ll = 0;
602 15439
                while (http_rxchunk(hp) > 0) {
603 11918
                        ll = (hp->rx_p - hp->body) - l;
604 11918
                        if (max && ll >= max)
605 96
                                break;
606
                }
607 3617
                p = "chunked";
608 68669
        } else if (q != NULL) {
609 33966
                ll = strtoul(q, NULL, 10);
610 33966
                if (max && ll > l + max)
611 32
                        ll = max;
612
                else
613 33935
                        ll -= l;
614 33967
                i = http_rxchar(hp, ll, 0);
615 33967
                if (i < 0)
616 32
                        return;
617 33934
                p = "c-l";
618 65020
        } else if (body) {
619 112
                ll = 0;
620 112
                do  {
621 3147600
                        i = http_rxchar(hp, 1, 1);
622 3147600
                        if (i < 0)
623 0
                                return;
624 3147600
                        ll += i;
625 3147600
                        if (max && ll >= max)
626 32
                                break;
627 3147568
                } while (i > 0);
628 112
                p = "eof";
629 112
        } else {
630 30974
                p = "none";
631 30974
                ll = l = 0;
632
        }
633 68638
        vtc_dump(hp->vl, 4, p, hp->body + l, ll);
634 68638
        l += ll;
635 68638
        hp->bodyl = l;
636 68638
        bprintf(hp->bodylen, "%d", l);
637 68669
}
638
639
/**********************************************************************
640
 * Receive a HTTP protocol header
641
 */
642
643
static void
644 69416
http_rxhdr(struct http *hp)
645
{
646 69416
        int i, s = 0;
647
        char *p;
648
        ssize_t l;
649
650 69416
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
651 69416
        hp->rx_p = hp->rx_b;
652 69416
        *hp->rx_p = '\0';
653 69416
        hp->body = NULL;
654 69416
        bprintf(hp->bodylen, "%s", "<undef>");
655 12934077
        while (1) {
656 12933520
                p = hp->rx_p;
657 12933520
                i = http_rxchar(hp, 1, 1);
658 12933520
                if (i < 1)
659 15
                        break;
660 12931396
                if (s == 0 && *p == '\r')
661 489529
                        s = 1;
662 12443653
                else if ((s == 0 || s == 1) && *p == '\n')
663 489529
                        s = 2;
664 11954794
                else if (s == 2 && *p == '\r')
665 69166
                        s = 3;
666 11885894
                else if ((s == 2 || s == 3) && *p == '\n')
667 69166
                        break;
668
                else
669 11817920
                        s = 0;
670
        }
671 69181
        l = hp->rx_p - hp->rx_b;
672 69181
        vtc_dump(hp->vl, 4, "rxhdr", hp->rx_b, l);
673 69181
        vtc_log(hp->vl, 4, "rxhdrlen = %zd", l);
674 69181
        if (i < 1)
675 15
                vtc_log(hp->vl, hp->fatal, "HTTP header is incomplete");
676 69182
        *hp->rx_p = '\0';
677 69182
        hp->body = hp->rx_p;
678 69182
}
679
680
/* SECTION: client-server.spec.rxresp
681
 *
682
 * rxresp [-no_obj] (client only)
683
 *         Receive and parse a response's headers and body. If -no_obj is
684
 *         present, only get the headers.
685
 */
686
687
static void
688 38384
cmd_http_rxresp(CMD_ARGS)
689
{
690
        struct http *hp;
691 38384
        int has_obj = 1;
692
693 38384
        (void)cmd;
694 38384
        (void)vl;
695 38384
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
696 38416
        ONLY_CLIENT(hp, av);
697 38416
        AZ(strcmp(av[0], "rxresp"));
698 38416
        av++;
699
700 38848
        for (; *av != NULL; av++)
701 864
                if (!strcmp(*av, "-no_obj"))
702 432
                        has_obj = 0;
703
                else
704 0
                        vtc_fatal(hp->vl,
705 0
                            "Unknown http rxresp spec: %s\n", *av);
706 38416
        http_rxhdr(hp);
707 38416
        http_splitheader(hp, 0);
708 38416
        if (http_count_header(hp->resp, "Content-Length") > 1)
709 0
                vtc_fatal(hp->vl,
710
                    "Multiple Content-Length headers.\n");
711 38415
        if (!has_obj)
712 432
                return;
713 37983
        if (!hp->resp[0] || !hp->resp[1])
714 0
                return;
715 37983
        if (hp->head_method)
716 16
                return;
717 37967
        if (!strcmp(hp->resp[1], "200"))
718 30176
                http_swallow_body(hp, hp->resp, 1, 0);
719
        else
720 7792
                http_swallow_body(hp, hp->resp, 0, 0);
721 37968
        vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
722 38416
}
723
724
/* SECTION: client-server.spec.rxresphdrs
725
 *
726
 * rxresphdrs (client only)
727
 *         Receive and parse a response's headers.
728
 */
729
730
static void
731 368
cmd_http_rxresphdrs(CMD_ARGS)
732
{
733
        struct http *hp;
734
735 368
        (void)cmd;
736 368
        (void)vl;
737 368
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
738 368
        ONLY_CLIENT(hp, av);
739 368
        AZ(strcmp(av[0], "rxresphdrs"));
740 368
        av++;
741
742 368
        for (; *av != NULL; av++)
743 0
                vtc_fatal(hp->vl, "Unknown http rxresp spec: %s\n", *av);
744 368
        http_rxhdr(hp);
745 368
        http_splitheader(hp, 0);
746 368
        if (http_count_header(hp->resp, "Content-Length") > 1)
747 0
                vtc_fatal(hp->vl,
748
                    "Multiple Content-Length headers.\n");
749 368
}
750
751
/* SECTION: client-server.spec.gunzip
752
 *
753
 * gunzip
754
 *         Gunzip the body in place.
755
 */
756
static void
757 592
cmd_http_gunzip(CMD_ARGS)
758
{
759
        struct http *hp;
760
761 592
        (void)av;
762 592
        (void)cmd;
763 592
        (void)vl;
764
765 592
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
766 592
        vtc_gunzip(hp, hp->body, &hp->bodyl);
767 592
}
768
769
/**********************************************************************
770
 * Handle common arguments of a transmited request or response
771
 */
772
773
static char* const *
774 66254
http_tx_parse_args(char * const *av, struct vtclog *vl, struct http *hp,
775
    char *body, unsigned nohost)
776
{
777 66254
        long bodylen = 0;
778
        char *b, *c;
779
        char *nullbody;
780
        char *m;
781
        ssize_t len;
782 66254
        int nolen = 0;
783
        int l;
784
785 66254
        (void)vl;
786 66254
        nullbody = body;
787
788 94361
        for (; *av != NULL; av++) {
789 42955
                if (!strcmp(*av, "-nolen")) {
790 1616
                        nolen = 1;
791 42955
                } else if (!strcmp(*av, "-nohost")) {
792 32
                        nohost = 1;
793 41339
                } else if (!strcmp(*av, "-hdr")) {
794 26395
                        if (!strncasecmp(av[1], "Host:", 5))
795 208
                                nohost = 1;
796 26395
                        VSB_printf(hp->vsb, "%s%s", av[1], nl);
797 26395
                        av++;
798 41307
                } else if (!strcmp(*av, "-hdrlen")) {
799 64
                        VSB_printf(hp->vsb, "%s: ", av[1]);
800 64
                        l = atoi(av[2]);
801 12064
                        while (l-- > 0)
802 12000
                                VSB_putc(hp->vsb, '0' + (l % 10));
803 64
                        VSB_printf(hp->vsb, "%s", nl);
804 64
                        av+=2;
805 64
                } else
806 14848
                        break;
807 28107
        }
808 81351
        for (; *av != NULL; av++) {
809 15104
                if (!strcmp(*av, "-body")) {
810 10880
                        assert(body == nullbody);
811 10880
                        REPLACE(body, av[1]);
812
813 10880
                        AN(body);
814 10880
                        av++;
815 10880
                        bodylen = strlen(body);
816 343696
                        for (b = body; *b != '\0'; b++) {
817 332816
                                if (*b == '\\' && b[1] == '0') {
818 64
                                        *b = '\0';
819 656
                                        for (c = b+1; *c != '\0'; c++) {
820 592
                                                *c = c[1];
821 592
                                        }
822 64
                                        b++;
823 64
                                        bodylen--;
824 64
                                }
825 332816
                        }
826 15104
                } else if (!strcmp(*av, "-bodyfrom")) {
827 32
                        assert(body == nullbody);
828 32
                        free(body);
829 32
                        body = VFIL_readfile(NULL, av[1], &len);
830 32
                        AN(body);
831 32
                        assert(len < INT_MAX);
832 32
                        bodylen = len;
833 32
                        av++;
834 4224
                } else if (!strcmp(*av, "-bodylen")) {
835 2976
                        assert(body == nullbody);
836 2976
                        free(body);
837 2976
                        body = synth_body(av[1], 0);
838 2976
                        bodylen = strlen(body);
839 2976
                        av++;
840 4192
                } else if (!strcmp(*av, "-gzipresidual")) {
841 128
                        hp->gzipresidual = strtoul(av[1], NULL, 0);
842 128
                        av++;
843 1216
                } else if (!strcmp(*av, "-gziplevel")) {
844 128
                        hp->gziplevel = strtoul(av[1], NULL, 0);
845 128
                        av++;
846 1088
                } else if (!strcmp(*av, "-gziplen")) {
847 48
                        assert(body == nullbody);
848 48
                        free(body);
849 48
                        b = synth_body(av[1], 1);
850 48
                        vtc_gzip(hp, b, &body, &bodylen);
851 48
                        free(b);
852 48
                        VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl);
853
                        // vtc_hexdump(hp->vl, 4, "gzip", (void*)body, bodylen);
854 48
                        av++;
855 960
                } else if (!strcmp(*av, "-gzipbody")) {
856 912
                        assert(body == nullbody);
857 912
                        free(body);
858 912
                        vtc_gzip(hp, av[1], &body, &bodylen);
859 912
                        VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl);
860
                        // vtc_hexdump(hp->vl, 4, "gzip", (void*)body, bodylen);
861 912
                        av++;
862 912
                } else
863 0
                        break;
864 15104
        }
865 66254
        if (!nohost) {
866 37281
                m = macro_get("localhost", NULL);
867 37281
                AN(m);
868 37296
                VSB_printf(hp->vsb, "Host: %s%s", m, nl);
869 37296
                free(m);
870 37296
        }
871 66230
        if (body != NULL && !nolen)
872 27230
                VSB_printf(hp->vsb, "Content-Length: %ld%s", bodylen, nl);
873 66253
        VSB_cat(hp->vsb, nl);
874 66253
        if (body != NULL) {
875 28654
                VSB_bcat(hp->vsb, body, bodylen);
876 28654
                free(body);
877 28654
        }
878 66253
        return (av);
879
}
880
881
/* SECTION: client-server.spec.txreq
882
 *
883
 * txreq|txresp [...]
884
 *         Send a minimal request or response, but overload it if necessary.
885
 *
886
 *         txreq is client-specific and txresp is server-specific.
887
 *
888
 *         The only thing different between a request and a response, apart
889
 *         from who can send them is that the first line (request line vs
890
 *         status line), so all the options are prety much the same.
891
 *
892
 *         \-method STRING (txreq only)
893
 *                 What method to use (default: "GET").
894
 *
895
 *         \-req STRING (txreq only)
896
 *                 Alias for -method.
897
 *
898
 *         \-url STRING (txreq only)
899
 *                 What location to use (default "/").
900
 *
901
 *         \-proto STRING
902
 *                 What protocol use in the status line.
903
 *                 (default: "HTTP/1.1").
904
 *
905
 *         \-status NUMBER (txresp only)
906
 *                 What status code to return (default 200).
907
 *
908
 *         \-reason STRING (txresp only)
909
 *                 What message to put in the status line (default: "OK").
910
 *
911
 *         These three switches can appear in any order but must come before the
912
 *         following ones.
913
 *
914
 *         \-nohost
915
 *                 Don't include a Host header in the request.
916
 *
917
 *         \-nolen
918
 *                 Don't include a Content-Length header.
919
 *
920
 *         \-hdr STRING
921
 *                 Add STRING as a header, it must follow this format:
922
 *                 "name: value". It can be called multiple times.
923
 *
924
 *         \-hdrlen STRING NUMBER
925
 *                 Add STRING as a header with NUMBER bytes of content.
926
 *
927
 *         You can then use the arguments related to the body:
928
 *
929
 *         \-body STRING
930
 *                 Input STRING as body.
931
 *
932
 *         \-bodyfrom FILE
933
 *                 Same as -body but content is read from FILE.
934
 *
935
 *         \-bodylen NUMBER
936
 *                 Generate and input a body that is NUMBER bytes-long.
937
 *
938
 *         \-gziplevel NUMBER
939
 *                 Set the gzip level (call it before any of the other gzip
940
 *                 switches).
941
 *
942
 *         \-gzipresidual NUMBER
943
 *                 Add extra gzip bits. You should never need it.
944
 *
945
 *         \-gzipbody STRING
946
 *                 Zip STRING and send it as body.
947
 *
948
 *         \-gziplen NUMBER
949
 *                 Combine -body and -gzipbody: create a body of length NUMBER,
950
 *                 zip it and send as body.
951
 */
952
953
/**********************************************************************
954
 * Transmit a response
955
 */
956
957
static void
958 28046
cmd_http_txresp(CMD_ARGS)
959
{
960
        struct http *hp;
961 28046
        const char *proto = "HTTP/1.1";
962 28046
        const char *status = "200";
963 28046
        const char *reason = "OK";
964 28046
        char* body = NULL;
965
966 28046
        (void)cmd;
967 28046
        (void)vl;
968 28046
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
969 28046
        ONLY_SERVER(hp, av);
970 28046
        AZ(strcmp(av[0], "txresp"));
971 28046
        av++;
972
973 28046
        VSB_clear(hp->vsb);
974
975 31262
        for (; *av != NULL; av++) {
976 21696
                if (!strcmp(*av, "-proto")) {
977 656
                        proto = av[1];
978 656
                        av++;
979 21696
                } else if (!strcmp(*av, "-status")) {
980 2144
                        status = av[1];
981 2144
                        av++;
982 21040
                } else if (!strcmp(*av, "-reason")) {
983 416
                        reason = av[1];
984 416
                        av++;
985 416
                        continue;
986
                } else
987 18480
                        break;
988 2800
        }
989
990 28046
        VSB_printf(hp->vsb, "%s %s %s%s", proto, status, reason, nl);
991
992
        /* send a "Content-Length: 0" header unless something else happens */
993 28046
        REPLACE(body, "");
994
995 28046
        av = http_tx_parse_args(av, vl, hp, body, 1);
996 28046
        if (*av != NULL)
997 0
                vtc_fatal(hp->vl, "Unknown http txresp spec: %s\n", *av);
998
999 28046
        http_write(hp, 4, "txresp");
1000 28046
}
1001
1002
static void
1003 16
cmd_http_upgrade(CMD_ARGS)
1004
{
1005
        char *h;
1006
        struct http *hp;
1007
1008 16
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1009 16
        ONLY_SERVER(hp, av);
1010 16
        AN(hp->sfd);
1011
1012 16
        h = http_find_header(hp->req, "Upgrade");
1013 16
        if (!h || strcmp(h, "h2c"))
1014 0
                vtc_fatal(vl, "Req misses \"Upgrade: h2c\" header");
1015
1016 16
        h = http_find_header(hp->req, "Connection");
1017 16
        if (!h || strcmp(h, "Upgrade, HTTP2-Settings"))
1018 0
                vtc_fatal(vl, "Req misses \"Connection: "
1019
                        "Upgrade, HTTP2-Settings\" header");
1020
1021 16
        h = http_find_header(hp->req, "HTTP2-Settings");
1022 16
        if (!h)
1023 0
                vtc_fatal(vl, "Req misses \"HTTP2-Settings\" header");
1024
1025
1026 16
        parse_string("txresp -status 101 "
1027
                                "-hdr \"Connection: Upgrade\" "
1028 16
                                "-hdr \"Upgrade: h2c\"\n", cmd, hp, vl);
1029
1030 16
        b64_settings(hp, h);
1031
1032 16
        parse_string("rxpri\n"
1033
                        "stream 0 {\n"
1034
                        "txsettings\n"
1035
                        "rxsettings\n"
1036
                        "txsettings -ack\n"
1037
                        "rxsettings\n"
1038
                        "expect settings.ack == true\n"
1039 16
                        "} -start\n", cmd, hp, vl);
1040 16
}
1041
1042
/**********************************************************************
1043
 * Receive a request
1044
 */
1045
1046
/* SECTION: client-server.spec.rxreq
1047
 *
1048
 * rxreq (server only)
1049
 *         Receive and parse a request's headers and body.
1050
 */
1051
static void
1052 30605
cmd_http_rxreq(CMD_ARGS)
1053
{
1054
        struct http *hp;
1055
1056 30605
        (void)cmd;
1057 30605
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1058 30616
        ONLY_SERVER(hp, av);
1059 30616
        AZ(strcmp(av[0], "rxreq"));
1060 30616
        av++;
1061
1062 30616
        for (; *av != NULL; av++)
1063 0
                vtc_fatal(vl, "Unknown http rxreq spec: %s\n", *av);
1064 30616
        http_rxhdr(hp);
1065 30616
        http_splitheader(hp, 1);
1066 30616
        if (http_count_header(hp->req, "Content-Length") > 1)
1067 0
                vtc_fatal(vl, "Multiple Content-Length headers.\n");
1068 30382
        http_swallow_body(hp, hp->req, 0, 0);
1069 30382
        vtc_log(vl, 4, "bodylen = %s", hp->bodylen);
1070 30382
}
1071
1072
/* SECTION: client-server.spec.rxreqhdrs
1073
 *
1074
 * rxreqhdrs (server only)
1075
 *         Receive and parse a request's headers (but not the body).
1076
 */
1077
1078
static void
1079 16
cmd_http_rxreqhdrs(CMD_ARGS)
1080
{
1081
        struct http *hp;
1082
1083 16
        (void)cmd;
1084 16
        (void)vl;
1085 16
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1086 16
        AZ(strcmp(av[0], "rxreqhdrs"));
1087 16
        av++;
1088
1089 16
        for (; *av != NULL; av++)
1090 0
                vtc_fatal(hp->vl, "Unknown http rxreq spec: %s\n", *av);
1091 16
        http_rxhdr(hp);
1092 16
        http_splitheader(hp, 1);
1093 16
        if (http_count_header(hp->req, "Content-Length") > 1)
1094 0
                vtc_fatal(hp->vl, "Multiple Content-Length headers.\n");
1095 16
}
1096
1097
/* SECTION: client-server.spec.rxreqbody
1098
 *
1099
 * rxreqbody (server only)
1100
 *         Receive a request's body.
1101
 */
1102
1103
static void
1104 0
cmd_http_rxreqbody(CMD_ARGS)
1105
{
1106
        struct http *hp;
1107
1108 0
        (void)cmd;
1109 0
        (void)vl;
1110 0
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1111 0
        ONLY_SERVER(hp, av);
1112 0
        AZ(strcmp(av[0], "rxreqbody"));
1113 0
        av++;
1114
1115 0
        for (; *av != NULL; av++)
1116 0
                vtc_fatal(hp->vl, "Unknown http rxreq spec: %s\n", *av);
1117 0
        http_swallow_body(hp, hp->req, 0, 0);
1118 0
        vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
1119 0
}
1120
1121
/* SECTION: client-server.spec.rxrespbody
1122
 *
1123
 * rxrespbody (client only)
1124
 *         Receive (part of) a response's body.
1125
 *
1126
 * -max : max length of this receive, 0 for all
1127
 */
1128
1129
static void
1130 320
cmd_http_rxrespbody(CMD_ARGS)
1131
{
1132
        struct http *hp;
1133 320
        int max = 0;
1134
1135 320
        (void)cmd;
1136 320
        (void)vl;
1137 320
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1138 320
        ONLY_CLIENT(hp, av);
1139 320
        AZ(strcmp(av[0], "rxrespbody"));
1140 320
        av++;
1141
1142 480
        for (; *av != NULL; av++)
1143 320
                if (!strcmp(*av, "-max")) {
1144 160
                        max = atoi(av[1]);
1145 160
                        av++;
1146 160
                } else
1147 0
                        vtc_fatal(hp->vl,
1148 0
                            "Unknown http rxrespbody spec: %s\n", *av);
1149
1150 320
        http_swallow_body(hp, hp->resp, 1, max);
1151 320
        vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
1152 320
}
1153
1154
/* SECTION: client-server.spec.rxchunk
1155
 *
1156
 * rxchunk
1157
 *         Receive an HTTP chunk.
1158
 */
1159
1160
static void
1161 112
cmd_http_rxchunk(CMD_ARGS)
1162
{
1163
        struct http *hp;
1164
        int ll, i;
1165
1166 112
        (void)cmd;
1167 112
        (void)vl;
1168 112
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1169 112
        ONLY_CLIENT(hp, av);
1170
1171 112
        i = http_rxchunk(hp);
1172 112
        if (i == 0) {
1173 0
                ll = hp->rx_p - hp->body;
1174 0
                hp->bodyl = ll;
1175 0
                bprintf(hp->bodylen, "%d", ll);
1176 0
                vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
1177 0
        }
1178 112
}
1179
1180
/**********************************************************************
1181
 * Transmit a request
1182
 */
1183
1184
static void
1185 38171
cmd_http_txreq(CMD_ARGS)
1186
{
1187
        struct http *hp;
1188 38171
        const char *req = "GET";
1189 38171
        const char *url = "/";
1190 38171
        const char *proto = "HTTP/1.1";
1191 38171
        const char *up = NULL;
1192
        unsigned nohost;
1193
1194 38171
        (void)cmd;
1195 38171
        (void)vl;
1196 38171
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1197 38208
        ONLY_CLIENT(hp, av);
1198 38208
        AZ(strcmp(av[0], "txreq"));
1199 38207
        av++;
1200
1201 38207
        VSB_clear(hp->vsb);
1202
1203 38207
        hp->head_method = 0;
1204 61368
        for (; *av != NULL; av++) {
1205 33229
                if (!strcmp(*av, "-url")) {
1206 20624
                        url = av[1];
1207 20624
                        av++;
1208 33232
                } else if (!strcmp(*av, "-proto")) {
1209 768
                        proto = av[1];
1210 768
                        av++;
1211 12608
                } else if (!strcmp(*av, "-method") ||
1212 11792
                    !strcmp(*av, "-req")) {
1213 1776
                        req = av[1];
1214 1776
                        hp->head_method = !strcasecmp(av[1], "HEAD") ;
1215 1776
                        av++;
1216 11840
                } else if (!hp->sfd && !strcmp(*av, "-up")) {
1217 0
                        up = av[1];
1218 0
                        av++;
1219 0
                } else
1220 10064
                        break;
1221 23165
        }
1222 38206
        VSB_printf(hp->vsb, "%s %s %s%s", req, url, proto, nl);
1223
1224 38206
        if (up)
1225 0
                VSB_printf(hp->vsb, "Connection: Upgrade, HTTP2-Settings%s"
1226
                                "Upgrade: h2c%s"
1227 0
                                "HTTP2-Settings: %s%s", nl, nl, up, nl);
1228
1229 38207
        nohost = strcasecmp(proto, "HTTP/1.1") != 0;
1230 38207
        av = http_tx_parse_args(av, vl, hp, NULL, nohost);
1231 38207
        if (*av != NULL)
1232 0
                vtc_fatal(hp->vl, "Unknown http txreq spec: %s\n", *av);
1233 38208
        http_write(hp, 4, "txreq");
1234
1235 38208
        if (up) {
1236 0
                parse_string("rxresp\n"
1237
                                "expect resp.status == 101\n"
1238
                                "expect resp.http.connection == Upgrade\n"
1239
                                "expect resp.http.upgrade == h2c\n"
1240 0
                                "txpri\n", http_cmds, hp, vl);
1241 0
                b64_settings(hp, up);
1242 0
                parse_string("stream 0 {\n"
1243
                                "txsettings\n"
1244
                                "rxsettings\n"
1245
                                "txsettings -ack\n"
1246
                                "rxsettings\n"
1247
                                "expect settings.ack == true"
1248 0
                             "} -start\n", http_cmds, hp, vl);
1249 0
        }
1250 38208
}
1251
1252
/* SECTION: client-server.spec.recv
1253
 *
1254
 * recv NUMBER
1255
 *         Read NUMBER bytes from the connection.
1256
 */
1257
1258
static void
1259 128
cmd_http_recv(CMD_ARGS)
1260
{
1261
        struct http *hp;
1262
        int i, n;
1263
        char u[32];
1264
1265 128
        (void)cmd;
1266 128
        (void)vl;
1267 128
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1268 128
        AN(av[1]);
1269 128
        AZ(av[2]);
1270 128
        n = strtoul(av[1], NULL, 0);
1271 435
        while (n > 0) {
1272 307
                i = read(hp->fd, u, n > 32 ? 32 : n);
1273 307
                if (i > 0)
1274 307
                        vtc_dump(hp->vl, 4, "recv", u, i);
1275
                else
1276 0
                        vtc_log(hp->vl, hp->fatal, "recv() got %d (%s)", i,
1277 0
                            strerror(errno));
1278 307
                n -= i;
1279
        }
1280 128
}
1281
1282
/* SECTION: client-server.spec.send
1283
 *
1284
 * send STRING
1285
 *         Push STRING on the connection.
1286
 */
1287
1288
static void
1289 12336
cmd_http_send(CMD_ARGS)
1290
{
1291
        struct http *hp;
1292
        int i;
1293
1294 12336
        (void)cmd;
1295 12336
        (void)vl;
1296 12336
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1297 12336
        AN(av[1]);
1298 12336
        AZ(av[2]);
1299 12336
        vtc_dump(hp->vl, 4, "send", av[1], -1);
1300 12336
        i = write(hp->fd, av[1], strlen(av[1]));
1301 12336
        if (i != strlen(av[1]))
1302 0
                vtc_log(hp->vl, hp->fatal, "Write error in http_send(): %s",
1303 0
                    strerror(errno));
1304 12336
}
1305
1306
/* SECTION: client-server.spec.send_n
1307
 *
1308
 * send_n NUMBER STRING
1309
 *         Write STRING on the socket NUMBER times.
1310
 */
1311
1312
static void
1313 32
cmd_http_send_n(CMD_ARGS)
1314
{
1315
        struct http *hp;
1316
        int i, n, l;
1317
1318 32
        (void)cmd;
1319 32
        (void)vl;
1320 32
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1321 32
        AN(av[1]);
1322 32
        AN(av[2]);
1323 32
        AZ(av[3]);
1324 32
        n = strtoul(av[1], NULL, 0);
1325 32
                vtc_dump(hp->vl, 4, "send_n", av[2], -1);
1326 32
        l = strlen(av[2]);
1327 32960
        while (n--) {
1328 32928
                i = write(hp->fd, av[2], l);
1329 32928
                if (i != l)
1330 0
                        vtc_log(hp->vl, hp->fatal,
1331
                            "Write error in http_send(): %s",
1332 0
                            strerror(errno));
1333
        }
1334 32
}
1335
1336
/* SECTION: client-server.spec.send_urgent
1337
 *
1338
 * send_urgent STRING
1339
 *         Send string as TCP OOB urgent data. You will never need this.
1340
 */
1341
1342
static void
1343 160
cmd_http_send_urgent(CMD_ARGS)
1344
{
1345
        struct http *hp;
1346
        int i;
1347
1348 160
        (void)cmd;
1349 160
        (void)vl;
1350 160
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1351 160
        AN(av[1]);
1352 160
        AZ(av[2]);
1353 160
        vtc_dump(hp->vl, 4, "send_urgent", av[1], -1);
1354 160
        i = send(hp->fd, av[1], strlen(av[1]), MSG_OOB);
1355 160
        if (i != strlen(av[1]))
1356 0
                vtc_log(hp->vl, hp->fatal,
1357 0
                    "Write error in http_send_urgent(): %s", strerror(errno));
1358 160
}
1359
1360
/* SECTION: client-server.spec.sendhex
1361
 *
1362
 * sendhex STRING
1363
 *         Send bytes as described by STRING. STRING should consist of hex pairs
1364
 *         possibly separated by whitespace or newlines. For example:
1365
 *         "0F EE a5    3df2".
1366
 */
1367
1368
static void
1369 2144
cmd_http_sendhex(CMD_ARGS)
1370
{
1371
        struct vsb *vsb;
1372
        struct http *hp;
1373
1374 2144
        (void)cmd;
1375 2144
        (void)vl;
1376 2144
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1377 2144
        AN(av[1]);
1378 2144
        AZ(av[2]);
1379 2144
        vsb = vtc_hex_to_bin(hp->vl, av[1]);
1380 2144
        assert(VSB_len(vsb) >= 0);
1381 2144
        vtc_hexdump(hp->vl, 4, "sendhex", VSB_data(vsb), VSB_len(vsb));
1382 2144
        if (VSB_tofile(hp->fd, vsb))
1383 0
                vtc_log(hp->vl, hp->fatal, "Write failed: %s",
1384 0
                    strerror(errno));
1385 2144
        VSB_destroy(&vsb);
1386 2144
}
1387
1388
/* SECTION: client-server.spec.chunked
1389
 *
1390
 * chunked STRING
1391
 *         Send STRING as chunked encoding.
1392
 */
1393
1394
static void
1395 800
cmd_http_chunked(CMD_ARGS)
1396
{
1397
        struct http *hp;
1398
1399 800
        (void)cmd;
1400 800
        (void)vl;
1401 800
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1402 800
        AN(av[1]);
1403 800
        AZ(av[2]);
1404 800
        VSB_clear(hp->vsb);
1405 1600
        VSB_printf(hp->vsb, "%jx%s%s%s",
1406 800
            (uintmax_t)strlen(av[1]), nl, av[1], nl);
1407 800
        http_write(hp, 4, "chunked");
1408 800
}
1409
1410
/* SECTION: client-server.spec.chunkedlen
1411
 *
1412
 * chunkedlen NUMBER
1413
 *         Do as ``chunked`` except that the string will be generated
1414
 *         for you, with a length of NUMBER characters.
1415
 */
1416
1417
static void
1418 2016
cmd_http_chunkedlen(CMD_ARGS)
1419
{
1420
        unsigned len;
1421
        unsigned u, v;
1422
        char buf[16384];
1423
        struct http *hp;
1424
1425 2016
        (void)cmd;
1426 2016
        (void)vl;
1427 2016
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1428 2016
        AN(av[1]);
1429 2016
        AZ(av[2]);
1430 2016
        VSB_clear(hp->vsb);
1431
1432 2016
        len = atoi(av[1]);
1433
1434 2016
        if (len == 0) {
1435 768
                VSB_printf(hp->vsb, "0%s%s", nl, nl);
1436 768
        } else {
1437 19343057
                for (u = 0; u < sizeof buf; u++)
1438 19202817
                        buf[u] = (u & 7) + '0';
1439
1440 1248
                VSB_printf(hp->vsb, "%x%s", len, nl);
1441 4704
                for (u = 0; u < len; u += v) {
1442 3456
                        v = len - u;
1443 3456
                        if (v > sizeof buf)
1444 2208
                                v = sizeof buf;
1445 3456
                        VSB_bcat(hp->vsb, buf, v);
1446 3456
                }
1447 1248
                VSB_printf(hp->vsb, "%s", nl);
1448
        }
1449 2016
        http_write(hp, 4, "chunked");
1450 2016
}
1451
1452
1453
/* SECTION: client-server.spec.timeout
1454
 *
1455
 * timeout NUMBER
1456
 *         Set the TCP timeout for this entity.
1457
 */
1458
1459
static void
1460 480
cmd_http_timeout(CMD_ARGS)
1461
{
1462
        struct http *hp;
1463
        double d;
1464
1465 480
        (void)cmd;
1466 480
        (void)vl;
1467 480
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1468 480
        AN(av[1]);
1469 480
        AZ(av[2]);
1470 480
        d = VNUM(av[1]);
1471 480
        if (isnan(d))
1472 0
                vtc_fatal(vl, "timeout is not a number (%s)", av[1]);
1473 480
        hp->timeout = (int)(d * 1000.0);
1474 480
}
1475
1476
/* SECTION: client-server.spec.expect_close
1477
 *
1478
 * expect_close
1479
 *      Reads from the connection, expecting nothing to read but an EOF.
1480
 */
1481
static void
1482 1611
cmd_http_expect_close(CMD_ARGS)
1483
{
1484
        struct http *hp;
1485
        struct pollfd fds[1];
1486
        char c;
1487
        int i;
1488
1489 1611
        (void)cmd;
1490 1611
        (void)vl;
1491 1611
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1492 1611
        AZ(av[1]);
1493
1494 1611
        vtc_log(vl, 4, "Expecting close (fd = %d)", hp->fd);
1495 1611
        if (hp->h2)
1496 224
                stop_h2(hp);
1497 1611
        while (1) {
1498 1611
                fds[0].fd = hp->fd;
1499 1611
                fds[0].events = POLLIN;
1500 1611
                fds[0].revents = 0;
1501 1611
                i = poll(fds, 1, hp->timeout);
1502 1611
                if (i < 0 && errno == EINTR)
1503 0
                        continue;
1504 1595
                if (i == 0)
1505 0
                        vtc_log(vl, hp->fatal, "Expected close: timeout");
1506 1595
                if (i != 1 || !(fds[0].revents & (POLLIN|POLLERR|POLLHUP)))
1507 0
                        vtc_log(vl, hp->fatal,
1508
                            "Expected close: poll = %d, revents = 0x%x",
1509 0
                            i, fds[0].revents);
1510 1595
                i = read(hp->fd, &c, 1);
1511 1595
                if (VTCP_Check(i))
1512 1595
                        break;
1513 0
                if (i == 1 && vct_islws(c))
1514 0
                        continue;
1515 0
                vtc_log(vl, hp->fatal,
1516 0
                    "Expecting close: read = %d, c = 0x%02x", i, c);
1517
        }
1518 1595
        vtc_log(vl, 4, "fd=%d EOF, as expected", hp->fd);
1519 1595
}
1520
1521
/* SECTION: client-server.spec.close
1522
 *
1523
 * close (server only)
1524
 *      Close the connection. Note that if operating in HTTP/2 mode no
1525
 *      extra (GOAWAY) frame is sent, it's simply a TCP close.
1526
 */
1527
static void
1528 256
cmd_http_close(CMD_ARGS)
1529
{
1530
        struct http *hp;
1531
1532 256
        (void)cmd;
1533 256
        (void)vl;
1534 256
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1535 256
        ONLY_SERVER(hp, av);
1536 256
        AZ(av[1]);
1537 256
        assert(hp->sfd != NULL);
1538 256
        assert(*hp->sfd >= 0);
1539 256
        if (hp->h2)
1540 0
                stop_h2(hp);
1541 256
        VTCP_close(&hp->fd);
1542 256
        vtc_log(vl, 4, "Closed");
1543 256
}
1544
1545
/* SECTION: client-server.spec.accept
1546
 *
1547
 * accept (server only)
1548
 *      Close the current connection, if any, and accept a new one. Note
1549
 *      that this new connection is HTTP/1.x.
1550
 */
1551
static void
1552 2191
cmd_http_accept(CMD_ARGS)
1553
{
1554
        struct http *hp;
1555
1556 2191
        (void)cmd;
1557 2191
        (void)vl;
1558 2191
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1559 2191
        ONLY_SERVER(hp, av);
1560 2191
        AZ(av[1]);
1561 2191
        assert(hp->sfd != NULL);
1562 2191
        assert(*hp->sfd >= 0);
1563 2191
        if (hp->h2)
1564 0
                stop_h2(hp);
1565 2191
        if (hp->fd >= 0)
1566 1951
                VTCP_close(&hp->fd);
1567 2191
        vtc_log(vl, 4, "Accepting");
1568 2191
        hp->fd = accept(*hp->sfd, NULL, NULL);
1569 2191
        if (hp->fd < 0)
1570 0
                vtc_log(vl, hp->fatal, "Accepted failed: %s", strerror(errno));
1571 2047
        vtc_log(vl, 3, "Accepted socket fd is %d", hp->fd);
1572 2047
}
1573
1574
/* SECTION: client-server.spec.loop
1575
 *
1576
 * loop NUMBER STRING
1577
 *         Process STRING as a specification, NUMBER times.
1578
 */
1579
1580
static void
1581 516
cmd_http_loop(CMD_ARGS)
1582
{
1583
        struct http *hp;
1584
        unsigned n, m;
1585
1586 516
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1587 517
        AN(av[1]);
1588 517
        AN(av[2]);
1589 517
        AZ(av[3]);
1590 517
        n = strtoul(av[1], NULL, 0);
1591 7305
        for (m = 1 ; m <= n; m++) {
1592 6877
                vtc_log(vl, 4, "Loop #%u", m);
1593 6877
                parse_string(av[2], cmd, hp, vl);
1594 6877
        }
1595 428
}
1596
1597
/* SECTION: client-server.spec.fatal
1598
 *
1599
 * fatal|non_fatal
1600
 *         Control whether a failure of this entity should stop the test.
1601
 */
1602
1603
static void
1604 500
cmd_http_fatal(CMD_ARGS)
1605
{
1606
        struct http *hp;
1607 500
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1608
1609 512
        AZ(av[1]);
1610 512
        if (!strcmp(av[0], "fatal"))
1611 108
                hp->fatal = 0;
1612 400
        else if (!strcmp(av[0], "non_fatal"))
1613 400
                hp->fatal = -1;
1614
        else
1615 0
                vtc_fatal(vl, "XXX: fatal %s", cmd->name);
1616 511
}
1617
1618
#define cmd_http_non_fatal cmd_http_fatal
1619
1620
static const char PREFACE[24] = {
1621
        0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54,
1622
        0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a,
1623
        0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a
1624
};
1625
1626
/* SECTION: client-server.spec.txpri
1627
 *
1628
 * txpri (client only)
1629
 *      Send an HTTP/2 preface ("PRI * HTTP/2.0\\r\\n\\r\\nSM\\r\\n\\r\\n")
1630
 *      and set client to HTTP/2.
1631
 */
1632
static void
1633 1712
cmd_http_txpri(CMD_ARGS)
1634
{
1635
        size_t l;
1636
        struct http *hp;
1637 1712
        (void)cmd;
1638 1712
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1639 1712
        ONLY_CLIENT(hp, av);
1640
1641 1712
        vtc_dump(hp->vl, 4, "txpri", PREFACE, sizeof(PREFACE));
1642
        /* Dribble out the preface */
1643 1712
        l = write(hp->fd, PREFACE, 18);
1644 1712
        if (l != 18)
1645 0
                vtc_log(vl, hp->fatal, "Write failed: (%zd vs %zd) %s",
1646 0
                    l, sizeof(PREFACE), strerror(errno));
1647 1712
        usleep(10000);
1648 1712
        l = write(hp->fd, PREFACE + 18, sizeof(PREFACE) - 18);
1649 1712
        if (l != sizeof(PREFACE) - 18)
1650 0
                vtc_log(vl, hp->fatal, "Write failed: (%zd vs %zd) %s",
1651 0
                    l, sizeof(PREFACE), strerror(errno));
1652
1653 1712
        start_h2(hp);
1654 1712
        AN(hp->h2);
1655 1712
}
1656
1657
/* SECTION: client-server.spec.rxpri
1658
 *
1659
 * rxpri (server only)
1660
 *      Receive a preface. If valid set the server to HTTP/2, abort
1661
 *      otherwise.
1662
 */
1663
static void
1664 448
cmd_http_rxpri(CMD_ARGS)
1665
{
1666
        struct http *hp;
1667 448
        (void)cmd;
1668 448
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1669 448
        ONLY_SERVER(hp, av);
1670
1671 448
        hp->rx_p = hp->rx_b;
1672 448
        if (!http_rxchar(hp, sizeof(PREFACE), 0))
1673 0
                vtc_fatal(vl, "Couldn't retrieve connection preface");
1674 448
        if (memcmp(hp->rx_b, PREFACE, sizeof(PREFACE)))
1675 0
                vtc_fatal(vl, "Received invalid preface\n");
1676 448
        start_h2(hp);
1677 448
        AN(hp->h2);
1678 448
}
1679
1680
/* SECTION: client-server.spec.settings
1681
 *
1682
 * settings -dectbl INT
1683
 *      Force internal HTTP/2 settings to certain values. Currently only
1684
 *      support setting the decoding table size.
1685
 */
1686
static void
1687 0
cmd_http_settings(CMD_ARGS)
1688
{
1689
        uint32_t n;
1690
        char *p;
1691
        struct http *hp;
1692 0
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1693 0
        (void)cmd;
1694
1695 0
        if (!hp->h2)
1696 0
                vtc_fatal(hp->vl, "Only possible in H/2 mode");
1697
1698 0
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1699
1700 0
        for (; *av != NULL; av++) {
1701 0
                if (!strcmp(*av, "-dectbl")) {
1702 0
                        n = strtoul(av[1], &p, 0);
1703 0
                        if (*p != '\0')
1704 0
                                vtc_fatal(hp->vl, "-dectbl takes an integer as "
1705 0
                                    "argument (found %s)", av[1]);
1706 0
                        assert(HPK_ResizeTbl(hp->decctx, n) != hpk_err);
1707 0
                        av++;
1708 0
                } else
1709 0
                        vtc_fatal(vl, "Unknown settings spec: %s\n", *av);
1710 0
        }
1711 0
}
1712
1713
static void
1714 6290
cmd_http_stream(CMD_ARGS)
1715
{
1716
        struct http *hp;
1717 6290
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1718 6476
        if (!hp->h2) {
1719 1868
                vtc_log(hp->vl, 4, "Not in H/2 mode, do what's needed");
1720 1868
                if (hp->sfd)
1721 400
                        parse_string("rxpri", http_cmds, hp, vl);
1722
                else
1723 1472
                        parse_string("txpri", http_cmds, hp, vl);
1724 1872
                parse_string("stream 0 {\n"
1725
                                "txsettings\n"
1726
                                "rxsettings\n"
1727
                                "txsettings -ack\n"
1728
                                "rxsettings\n"
1729
                                "expect settings.ack == true"
1730 1872
                             "} -run\n", http_cmds, hp, vl);
1731 1872
        }
1732 6480
        cmd_stream(av, hp, cmd, vl);
1733 6480
}
1734
1735
/* SECTION: client-server.spec.write_body
1736
 *
1737
 * write_body STRING
1738
 *      Write the body of a request or a response to a file. By using the
1739
 *      shell command, higher-level checks on the body can be performed
1740
 *      (eg. XML, JSON, ...) provided that such checks can be delegated
1741
 *      to an external program.
1742
 */
1743
static void
1744 32
cmd_http_write_body(CMD_ARGS)
1745
{
1746
        struct http *hp;
1747
1748 32
        (void)cmd;
1749 32
        (void)vl;
1750 32
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1751 32
        AN(av[0]);
1752 32
        AN(av[1]);
1753 32
        AZ(av[2]);
1754 32
        AZ(strcmp(av[0], "write_body"));
1755 32
        if (VFIL_writefile(NULL, av[1], hp->body, hp->bodyl) != 0)
1756 0
                vtc_fatal(hp->vl, "failed to write body: %s (%d)",
1757 0
                    strerror(errno), errno);
1758 32
}
1759
1760
/**********************************************************************
1761
 * Execute HTTP specifications
1762
 */
1763
1764
const struct cmds http_cmds[] = {
1765
#define CMD_HTTP(n) { #n, cmd_http_##n },
1766
        /* session */
1767
        CMD_HTTP(accept)
1768
        CMD_HTTP(close)
1769
        CMD_HTTP(recv)
1770
        CMD_HTTP(send)
1771
        CMD_HTTP(send_n)
1772
        CMD_HTTP(send_urgent)
1773
        CMD_HTTP(sendhex)
1774
        CMD_HTTP(timeout)
1775
1776
        /* spec */
1777
        CMD_HTTP(fatal)
1778
        CMD_HTTP(loop)
1779
        CMD_HTTP(non_fatal)
1780
1781
        /* body */
1782
        CMD_HTTP(gunzip)
1783
        CMD_HTTP(write_body)
1784
1785
        /* HTTP/1.x */
1786
        CMD_HTTP(chunked)
1787
        CMD_HTTP(chunkedlen)
1788
        CMD_HTTP(rxchunk)
1789
1790
        /* HTTP/2 */
1791
        CMD_HTTP(stream)
1792
        CMD_HTTP(settings)
1793
1794
        /* client */
1795
        CMD_HTTP(rxresp)
1796
        CMD_HTTP(rxrespbody)
1797
        CMD_HTTP(rxresphdrs)
1798
        CMD_HTTP(txpri)
1799
        CMD_HTTP(txreq)
1800
1801
        /* server */
1802
        CMD_HTTP(rxpri)
1803
        CMD_HTTP(rxreq)
1804
        CMD_HTTP(rxreqbody)
1805
        CMD_HTTP(rxreqhdrs)
1806
        CMD_HTTP(txresp)
1807
        CMD_HTTP(upgrade)
1808
1809
        /* expect */
1810
        CMD_HTTP(expect)
1811
        CMD_HTTP(expect_close)
1812
        CMD_HTTP(expect_pattern)
1813
#undef CMD_HTTP
1814
        { NULL, NULL }
1815
};
1816
1817
static void
1818 46916
http_process_cleanup(void *arg)
1819
{
1820 46916
        struct http *hp = arg;
1821
1822 46916
        if (hp->h2)
1823 1936
                stop_h2(hp);
1824 46916
        VSB_destroy(&hp->vsb);
1825 46916
        free(hp->rx_b);
1826 46916
        free(hp->rem_ip);
1827 46916
        free(hp->rem_port);
1828 46916
        free(hp->rem_path);
1829 46916
        FREE_OBJ(hp);
1830 46916
}
1831
1832
int
1833 46788
http_process(struct vtclog *vl, const char *spec, int sock, int *sfd,
1834
    const char *addr, int rcvbuf)
1835
{
1836
        struct http *hp;
1837
        int retval, oldbuf;
1838 46788
        socklen_t intlen = sizeof(int);
1839
1840 46788
        (void)sfd;
1841 46788
        ALLOC_OBJ(hp, HTTP_MAGIC);
1842 46916
        AN(hp);
1843 46916
        hp->fd = sock;
1844 46916
        hp->timeout = vtc_maxdur * 1000 / 2;
1845
1846 46916
        if (rcvbuf) {
1847
                // XXX setsockopt() too late on SunOS
1848
                // https://github.com/varnishcache/varnish-cache/pull/2980#issuecomment-486214661
1849 64
                hp->rcvbuf = rcvbuf;
1850
1851 64
                oldbuf = 0;
1852 64
                AZ(getsockopt(hp->fd, SOL_SOCKET, SO_RCVBUF, &oldbuf, &intlen));
1853 64
                AZ(setsockopt(hp->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, intlen));
1854 64
                AZ(getsockopt(hp->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &intlen));
1855
1856 128
                vtc_log(vl, 3, "-rcvbuf fd=%d old=%d new=%d actual=%d",
1857 64
                    hp->fd, oldbuf, hp->rcvbuf, rcvbuf);
1858 64
        }
1859
1860 46915
        hp->nrxbuf = 2048*1024;
1861 46915
        hp->rx_b = malloc(hp->nrxbuf);
1862 46915
        AN(hp->rx_b);
1863 46916
        hp->rx_e = hp->rx_b + hp->nrxbuf;
1864 46916
        hp->rx_p = hp->rx_b;
1865 46916
        *hp->rx_p = '\0';
1866
1867 46916
        hp->vsb = VSB_new_auto();
1868 46916
        AN(hp->vsb);
1869
1870 46915
        hp->sfd = sfd;
1871
1872 46915
        hp->rem_ip = malloc(VTCP_ADDRBUFSIZE);
1873 46915
        AN(hp->rem_ip);
1874
1875 46916
        hp->rem_port = malloc(VTCP_PORTBUFSIZE);
1876 46916
        AN(hp->rem_port);
1877
1878 46916
        hp->vl = vl;
1879 46916
        hp->gziplevel = 0;
1880 46916
        hp->gzipresidual = -1;
1881
1882 46916
        if (*addr != '/') {
1883 45137
                VTCP_hisname(sock, hp->rem_ip, VTCP_ADDRBUFSIZE, hp->rem_port,
1884
                             VTCP_PORTBUFSIZE);
1885 45137
                hp->rem_path = NULL;
1886 45137
        } else {
1887 1779
                strcpy(hp->rem_ip, "0.0.0.0");
1888 1779
                strcpy(hp->rem_port, "0");
1889 1779
                hp->rem_path = strdup(addr);
1890
        }
1891 46912
        pthread_cleanup_push(http_process_cleanup, hp);
1892 46912
        parse_string(spec, http_cmds, hp, vl);
1893 46912
        retval = hp->fd;
1894 46912
        pthread_cleanup_pop(0);
1895 46912
        http_process_cleanup(hp);
1896 46912
        return (retval);
1897
}
1898
1899
/**********************************************************************
1900
 * Magic test routine
1901
 *
1902
 * This function brute-forces some short strings through gzip(9) to
1903
 * find candidates for all possible 8 bit positions of the stopbit.
1904
 *
1905
 * Here is some good short output strings:
1906
 *
1907
 *      0 184 <e04c8d0fd604c>
1908
 *      1 257 <1ea86e6cf31bf4ec3d7a86>
1909
 *      2 106 <10>
1910
 *      3 163 <a5e2e2e1c2e2>
1911
 *      4 180 <71c5d18ec5d5d1>
1912
 *      5 189 <39886d28a6d2988>
1913
 *      6 118 <80000>
1914
 *      7 151 <386811868>
1915
 *
1916
 */
1917
1918
#if 0
1919
void xxx(void);
1920
1921
void
1922
xxx(void)
1923
{
1924
        z_stream vz;
1925
        int n;
1926
        char ibuf[200];
1927
        char obuf[200];
1928
        int fl[8];
1929
        int i, j;
1930
1931
        for (n = 0; n < 8; n++)
1932
                fl[n] = 9999;
1933
1934
        memset(&vz, 0, sizeof vz);
1935
1936
        for (n = 0;  n < 999999999; n++) {
1937
                *ibuf = 0;
1938
                for (j = 0; j < 7; j++) {
1939
                        snprintf(strchr(ibuf, 0), 5, "%x",
1940
                            (unsigned)VRND_RandomTestable() & 0xffff);
1941
                        vz.next_in = TRUST_ME(ibuf);
1942
                        vz.avail_in = strlen(ibuf);
1943
                        vz.next_out = TRUST_ME(obuf);
1944
                        vz.avail_out = sizeof obuf;
1945
                        assert(Z_OK == deflateInit2(&vz,
1946
                            9, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY));
1947
                        assert(Z_STREAM_END == deflate(&vz, Z_FINISH));
1948
                        i = vz.stop_bit & 7;
1949
                        if (fl[i] > strlen(ibuf)) {
1950
                                printf("%d %jd <%s>\n", i, vz.stop_bit, ibuf);
1951
                                fl[i] = strlen(ibuf);
1952
                        }
1953
                        assert(Z_OK == deflateEnd(&vz));
1954
                }
1955
        }
1956
1957
        printf("FOO\n");
1958
}
1959
#endif