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