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