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 21280
synth_body(const char *len, int rnd)
178
{
179
        int i, j, k, l;
180
        char *b;
181
182
183 21280
        AN(len);
184 21280
        i = strtoul(len, NULL, 0);
185 21280
        assert(i > 0);
186 21280
        b = malloc(i + 1L);
187 21280
        AN(b);
188 21280
        l = k = '!';
189 1442810520
        for (j = 0; j < i; j++) {
190 1442789240
                if ((j % 64) == 63) {
191 22530600
                        b[j] = '\n';
192 22530600
                        k++;
193 22530600
                        if (k == '~')
194 240200
                                k = '!';
195 22530600
                        l = k;
196 1442789240
                } else if (rnd) {
197 165120
                        b[j] = (VRND_RandomTestable() % 95) + ' ';
198 165120
                } else {
199 1420093520
                        b[j] = (char)l;
200 1420093520
                        if (++l == '~')
201 15210520
                                l = '!';
202
                }
203 1442789240
        }
204 21280
        b[i - 1] = '\n';
205 21280
        b[i] = '\0';
206 21280
        return (b);
207
}
208
209
/**********************************************************************
210
 * Finish and write the vsb to the fd
211
 */
212
213
static void
214 222003
http_write(const struct http *hp, int lvl, const char *pfx)
215
{
216
217 222003
        AZ(VSB_finish(hp->vsb));
218 222003
        vtc_dump(hp->vl, lvl, pfx, VSB_data(hp->vsb), VSB_len(hp->vsb));
219 222003
        if (VSB_tofile(hp->vsb, hp->sess->fd))
220 538
                vtc_log(hp->vl, hp->fatal, "Write failed: %s",
221 269
                    strerror(errno));
222 222003
}
223
224
/**********************************************************************
225
 * find header
226
 */
227
228
static char *
229 560520
http_find_header(char * const *hh, const char *hdr)
230
{
231
        int n, l;
232
        char *r;
233
234 560520
        l = strlen(hdr);
235
236 4092115
        for (n = 3; hh[n] != NULL; n++) {
237 3775831
                if (strncasecmp(hdr, hh[n], l) || hh[n][l] != ':')
238 3531595
                        continue;
239 488869
                for (r = hh[n] + l + 1; vct_issp(*r); r++)
240 244633
                        continue;
241 244236
                return (r);
242
        }
243 316284
        return (NULL);
244 560520
}
245
246
/**********************************************************************
247
 * count header
248
 */
249
250
static int
251 220027
http_count_header(char * const *hh, const char *hdr)
252
{
253 220027
        int n, l, r = 0;
254
255 220027
        l = strlen(hdr);
256
257 1757125
        for (n = 3; hh[n] != NULL; n++) {
258 1537098
                if (strncasecmp(hdr, hh[n], l) || hh[n][l] != ':')
259 1427942
                        continue;
260 109156
                r++;
261 109156
        }
262 220027
        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 533118
cmd_var_resolve(struct http *hp, char *spec)
304
{
305
        char **hh, *hdr;
306 533118
        if (!strcmp(spec, "remote.ip"))
307 160
                return (hp->rem_ip);
308 532958
        if (!strcmp(spec, "remote.port"))
309 160
                return (hp->rem_port);
310 532798
        if (!strcmp(spec, "remote.path"))
311 160
                return (hp->rem_path);
312 532638
        if (!strcmp(spec, "req.method"))
313 1960
                return (hp->req[0]);
314 530678
        if (!strcmp(spec, "req.url"))
315 24760
                return (hp->req[1]);
316 505918
        if (!strcmp(spec, "req.proto"))
317 1800
                return (hp->req[2]);
318 504118
        if (!strcmp(spec, "resp.proto"))
319 1360
                return (hp->resp[0]);
320 502758
        if (!strcmp(spec, "resp.status"))
321 64238
                return (hp->resp[1]);
322 438520
        if (!strcmp(spec, "resp.reason"))
323 9080
                return (hp->resp[2]);
324 429440
        if (!strcmp(spec, "resp.chunklen"))
325 0
                return (hp->chunklen);
326 429440
        if (!strcmp(spec, "req.bodylen"))
327 1160
                return (hp->bodylen);
328 428280
        if (!strcmp(spec, "req.body"))
329 800
                return (hp->body != NULL ? hp->body : spec);
330 427480
        if (!strcmp(spec, "resp.bodylen"))
331 25997
                return (hp->bodylen);
332 401483
        if (!strcmp(spec, "resp.body"))
333 8120
                return (hp->body != NULL ? hp->body : spec);
334 393363
        if (!strncmp(spec, "req.http.", 9)) {
335 14240
                hh = hp->req;
336 14240
                hdr = spec + 9;
337 393363
        } else if (!strncmp(spec, "resp.http.", 10)) {
338 119957
                hh = hp->resp;
339 119957
                hdr = spec + 10;
340 379123
        } else if (!strcmp(spec, "h2.state")) {
341 294
                if (hp->h2)
342 134
                        return ("true");
343
                else
344 160
                        return ("false");
345
        } else
346 258872
                return (spec);
347 134197
        hdr = http_find_header(hh, hdr);
348 134197
        return (hdr);
349 533118
}
350
351
static void
352 266563
cmd_http_expect(CMD_ARGS)
353
{
354
        struct http *hp;
355
        const char *lhs;
356
        char *cmp;
357
        const char *rhs;
358
359 266563
        (void)vl;
360 266563
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
361 266563
        AZ(strcmp(av[0], "expect"));
362 266563
        av++;
363
364 266563
        AN(av[0]);
365 266563
        AN(av[1]);
366 266563
        AN(av[2]);
367 266563
        AZ(av[3]);
368 266563
        lhs = cmd_var_resolve(hp, av[0]);
369 266563
        cmp = av[1];
370 266563
        rhs = cmd_var_resolve(hp, av[2]);
371
372 266563
        vtc_expect(vl, av[0], lhs, cmp, av[2], rhs);
373 266563
}
374
375
/* SECTION: client-server.spec.expect_pattern
376
 *
377
 * expect_pattern
378
 *
379
 * Expect as the http body the test pattern generated by chunkedlen ('0'..'7'
380
 * repeating).
381
 */
382
static void
383 160
cmd_http_expect_pattern(CMD_ARGS)
384
{
385
        char *p;
386
        struct http *hp;
387 160
        char t = '0';
388
389 160
        (void)vl;
390 160
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
391 160
        AZ(strcmp(av[0], "expect_pattern"));
392 160
        av++;
393 160
        AZ(av[0]);
394 10485920
        for (p = hp->body; *p != '\0'; p++) {
395 10485760
                if (*p != t)
396 0
                        vtc_fatal(hp->vl,
397
                            "EXPECT PATTERN FAIL @%zd should 0x%02x is 0x%02x",
398 0
                            (ssize_t) (p - hp->body), t, *p);
399 10485760
                t += 1;
400 10485760
                t &= ~0x08;
401 10485760
        }
402 160
        vtc_log(hp->vl, 4, "EXPECT PATTERN SUCCESS");
403 160
}
404
405
/**********************************************************************
406
 * Split a HTTP protocol header
407
 */
408
409
static void
410 220025
http_splitheader(struct http *hp, int req)
411
{
412
        char *p, *q, **hh;
413
        int n;
414
        char buf[20];
415
416 220025
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
417 220025
        if (req) {
418 92105
                memset(hp->req, 0, sizeof hp->req);
419 92105
                hh = hp->req;
420 92105
        } else {
421 127920
                memset(hp->resp, 0, sizeof hp->resp);
422 127920
                hh = hp->resp;
423
        }
424
425 220025
        n = 0;
426 220025
        p = hp->rx_b;
427 220025
        if (*p == '\0') {
428 3200
                vtc_log(hp->vl, 4, "No headers");
429 3200
                return;
430
        }
431
432
        /* REQ/PROTO */
433 216865
        while (vct_islws(*p))
434 40
                p++;
435 216825
        hh[n++] = p;
436 1498329
        while (!vct_islws(*p))
437 1281504
                p++;
438 216825
        AZ(vct_iscrlf(p, hp->rx_e));
439 216825
        *p++ = '\0';
440
441
        /* URL/STATUS */
442 216825
        while (vct_issp(*p))            /* XXX: H space only */
443 0
                p++;
444 216825
        AZ(vct_iscrlf(p, hp->rx_e));
445 216825
        hh[n++] = p;
446 1063760
        while (!vct_islws(*p))
447 846935
                p++;
448 216825
        if (vct_iscrlf(p, hp->rx_e)) {
449 40
                hh[n++] = NULL;
450 40
                q = p;
451 40
                p = vct_skipcrlf(p, hp->rx_e);
452 40
                *q = '\0';
453 40
        } else {
454 216785
                *p++ = '\0';
455
                /* PROTO/MSG */
456 216785
                while (vct_issp(*p))            /* XXX: H space only */
457 0
                        p++;
458 216785
                hh[n++] = p;
459 1691384
                while (!vct_iscrlf(p, hp->rx_e))
460 1474599
                        p++;
461 216785
                q = p;
462 216785
                p = vct_skipcrlf(p, hp->rx_e);
463 216785
                *q = '\0';
464
        }
465 216825
        assert(n == 3);
466
467 1753793
        while (*p != '\0') {
468 1753932
                assert(n < MAX_HDR);
469 1753932
                if (vct_iscrlf(p, hp->rx_e))
470 216818
                        break;
471 1537114
                hh[n++] = p++;
472 33678892
                while (*p != '\0' && !vct_iscrlf(p, hp->rx_e))
473 32141778
                        p++;
474 1536968
                if (*p == '\0') {
475 0
                        break;
476
                }
477 1536968
                q = p;
478 1536968
                p = vct_skipcrlf(p, hp->rx_e);
479 1536968
                *q = '\0';
480
        }
481 216973
        p = vct_skipcrlf(p, hp->rx_e);
482 216973
        assert(*p == '\0');
483
484 2404580
        for (n = 0; n < 3 || hh[n] != NULL; n++) {
485 2187607
                bprintf(buf, "http[%2d] ", n);
486 2187607
                vtc_dump(hp->vl, 4, buf, hh[n], -1);
487 2187607
        }
488 220173
}
489
490
491
/**********************************************************************
492
 * Receive another character
493
 */
494
495
static int
496 50010575
http_rxchar(struct http *hp, int n, int eof)
497
{
498
        int i;
499
        struct pollfd pfd[1];
500
501 100070584
        while (n > 0) {
502 50064169
                pfd[0].fd = hp->sess->fd;
503 50064169
                pfd[0].events = POLLIN;
504 50064169
                pfd[0].revents = 0;
505 50064169
                i = poll(pfd, 1, (int)(hp->timeout * 1000));
506 50064169
                if (i < 0 && errno == EINTR)
507 0
                        continue;
508 50064169
                if (i == 0) {
509 0
                        vtc_log(hp->vl, hp->fatal,
510
                            "HTTP rx timeout (fd:%d %.3fs)",
511 0
                            hp->sess->fd, hp->timeout);
512 0
                        continue;
513
                }
514 50064169
                if (i < 0) {
515 0
                        vtc_log(hp->vl, hp->fatal,
516
                            "HTTP rx failed (fd:%d poll: %s)",
517 0
                            hp->sess->fd, strerror(errno));
518 0
                        continue;
519
                }
520 50064169
                assert(i > 0);
521 50064169
                assert(hp->rx_p + n < hp->rx_e);
522 50064169
                i = read(hp->sess->fd, hp->rx_p, n);
523 50064169
                if (!(pfd[0].revents & POLLIN))
524 0
                        vtc_log(hp->vl, 4,
525
                            "HTTP rx poll (fd:%d revents: %x n=%d, i=%d)",
526 0
                            hp->sess->fd, pfd[0].revents, n, i);
527 50064169
                if (i == 0 && eof)
528 3400
                        return (i);
529 50060769
                if (i == 0) {
530 1520
                        vtc_log(hp->vl, hp->fatal,
531
                            "HTTP rx EOF (fd:%d read: %s) %d",
532 760
                            hp->sess->fd, strerror(errno), n);
533 760
                        return (-1);
534
                }
535 50060009
                if (i < 0) {
536 0
                        vtc_log(hp->vl, hp->fatal,
537
                            "HTTP rx failed (fd:%d read: %s)",
538 0
                            hp->sess->fd, strerror(errno));
539 0
                        return (-1);
540
                }
541 50060009
                hp->rx_p += i;
542 50060009
                *hp->rx_p = '\0';
543 50060009
                n -= i;
544
        }
545 50006415
        return (1);
546 50010575
}
547
548
static int
549 53802
http_rxchunk(struct http *hp)
550
{
551
        char *q, *old;
552
        int i;
553
554 53802
        old = hp->rx_p;
555 53802
        do {
556 271488
                if (http_rxchar(hp, 1, 0) < 0)
557 406
                        return (-1);
558 271082
        } while (hp->rx_p[-1] != '\n');
559 53396
        vtc_dump(hp->vl, 4, "len", old, -1);
560 53396
        i = strtoul(old, &q, 16);
561 53396
        bprintf(hp->chunklen, "%d", i);
562 53396
        if ((q == old) || (q == hp->rx_p) || (*q != '\0' && !vct_islws(*q))) {
563 8
                vtc_log(hp->vl, hp->fatal, "Chunklen fail (%02x @ %td)",
564 4
                    (*q & 0xff), q - old);
565 4
                return (-1);
566
        }
567 53396
        assert(*q == '\0' || vct_islws(*q));
568 53392
        hp->rx_p = old;
569 53392
        if (i > 0) {
570 42991
                if (http_rxchar(hp, i, 0) < 0)
571 74
                        return (-1);
572 42917
                vtc_dump(hp->vl, 4, "chunk", old, i);
573 42917
        }
574 53318
        old = hp->rx_p;
575 53318
        if (http_rxchar(hp, 2, 0) < 0)
576 0
                return (-1);
577 53318
        if (!vct_iscrlf(old, hp->rx_e)) {
578 0
                vtc_log(hp->vl, hp->fatal, "Chunklen without CRLF");
579 0
                return (-1);
580
        }
581 53318
        hp->rx_p = old;
582 53318
        *hp->rx_p = '\0';
583 53318
        return (i);
584 53798
}
585
586
/**********************************************************************
587
 * Swallow a HTTP message body
588
 *
589
 * max: 0 is all
590
 */
591
592
static void
593 213103
http_swallow_body(struct http *hp, char * const *hh, int body, int max)
594
{
595
        const char *p, *q;
596
        int i, l, ll;
597
598 213103
        l = hp->rx_p - hp->body;
599
600 213103
        p = http_find_header(hh, "transfer-encoding");
601 213103
        q = http_find_header(hh, "content-length");
602 213103
        if (p != NULL && !strcasecmp(p, "chunked")) {
603 11002
                if (q != NULL) {
604 0
                        vtc_log(hp->vl, hp->fatal, "Both C-E: Chunked and C-L");
605 0
                        return;
606
                }
607 11002
                ll = 0;
608 53277
                while (http_rxchunk(hp) > 0) {
609 42515
                        ll = (hp->rx_p - hp->body) - l;
610 42515
                        if (max && ll >= max)
611 240
                                break;
612
                }
613 11002
                p = "chunked";
614 213103
        } else if (q != NULL) {
615 107115
                ll = strtoul(q, NULL, 10);
616 107115
                if (max && ll > l + max)
617 80
                        ll = max;
618
                else
619 107035
                        ll -= l;
620 107115
                i = http_rxchar(hp, ll, 0);
621 107115
                if (i < 0)
622 280
                        return;
623 106835
                p = "c-l";
624 201821
        } else if (body) {
625 280
                ll = 0;
626 280
                do  {
627 7869000
                        i = http_rxchar(hp, 1, 1);
628 7869000
                        if (i < 0)
629 0
                                return;
630 7869000
                        ll += i;
631 7869000
                        if (max && ll >= max)
632 80
                                break;
633 7868920
                } while (i > 0);
634 280
                p = "eof";
635 280
        } else {
636 94706
                p = "none";
637 94706
                ll = l = 0;
638
        }
639 212823
        vtc_dump(hp->vl, 4, p, hp->body + l, ll);
640 212823
        l += ll;
641 212823
        hp->bodyl = l;
642 212823
        bprintf(hp->bodylen, "%d", l);
643 213103
}
644
645
/**********************************************************************
646
 * Receive a HTTP protocol header
647
 */
648
649
static void
650 220025
http_rxhdr(struct http *hp)
651
{
652 220025
        int i, s = 0;
653
        char *p;
654
        ssize_t l;
655
656 220025
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
657 220025
        hp->rx_p = hp->rx_b;
658 220025
        *hp->rx_p = '\0';
659 220025
        hp->body = NULL;
660 220025
        bprintf(hp->bodylen, "%s", "<undef>");
661 41659953
        while (1) {
662 41659953
                p = hp->rx_p;
663 41659953
                i = http_rxchar(hp, 1, 1);
664 41659953
                if (i < 1)
665 3200
                        break;
666 41656753
                if (s == 0 && *p == '\r')
667 1753814
                        s = 1;
668 39902939
                else if ((s == 0 || s == 1) && *p == '\n')
669 1753967
                        s = 2;
670 38148972
                else if (s == 2 && *p == '\r')
671 216785
                        s = 3;
672 37932187
                else if ((s == 2 || s == 3) && *p == '\n')
673 216825
                        break;
674
                else
675 37715362
                        s = 0;
676
        }
677 220025
        l = hp->rx_p - hp->rx_b;
678 220025
        vtc_dump(hp->vl, 4, "rxhdr", hp->rx_b, l);
679 220025
        vtc_log(hp->vl, 4, "rxhdrlen = %zd", l);
680 220025
        if (i < 1)
681 3200
                vtc_log(hp->vl, hp->fatal, "HTTP header is incomplete");
682 220025
        *hp->rx_p = '\0';
683 220025
        hp->body = hp->rx_p;
684 220025
}
685
686
/* SECTION: client-server.spec.rxresp
687
 *
688
 * rxresp [-no_obj] (client only)
689
 *         Receive and parse a response's headers and body. If -no_obj is
690
 *         present, only get the headers.
691
 */
692
693
static void
694 126074
cmd_http_rxresp(CMD_ARGS)
695
{
696
        struct http *hp;
697 126074
        int has_obj = 1;
698
699 126074
        (void)vl;
700 126074
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
701 126074
        ONLY_CLIENT(hp, av);
702 126074
        AZ(strcmp(av[0], "rxresp"));
703 126074
        av++;
704
705 127114
        for (; *av != NULL; av++)
706 2080
                if (!strcmp(*av, "-no_obj"))
707 1040
                        has_obj = 0;
708
                else
709 0
                        vtc_fatal(hp->vl,
710 0
                            "Unknown http rxresp spec: %s\n", *av);
711 126074
        http_rxhdr(hp);
712 126074
        http_splitheader(hp, 0);
713 126074
        if (http_count_header(hp->resp, "Content-Length") > 1)
714 0
                vtc_fatal(hp->vl,
715
                    "Multiple Content-Length headers.\n");
716 126074
        if (!has_obj)
717 1040
                return;
718 125034
        if (!hp->resp[0] || !hp->resp[1])
719 2520
                return;
720 122516
        if (hp->head_method)
721 2800
                return;
722 119716
        if (!strcmp(hp->resp[1], "200"))
723 89916
                http_swallow_body(hp, hp->resp, 1, 0);
724
        else
725 29800
                http_swallow_body(hp, hp->resp, 0, 0);
726 119716
        vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
727 126076
}
728
729
/* SECTION: client-server.spec.rxresphdrs
730
 *
731
 * rxresphdrs (client only)
732
 *         Receive and parse a response's headers.
733
 */
734
735
static void
736 1840
cmd_http_rxresphdrs(CMD_ARGS)
737
{
738
        struct http *hp;
739
740 1840
        (void)vl;
741 1840
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
742 1840
        ONLY_CLIENT(hp, av);
743 1840
        AZ(strcmp(av[0], "rxresphdrs"));
744 1840
        av++;
745
746 1840
        for (; *av != NULL; av++)
747 0
                vtc_fatal(hp->vl, "Unknown http rxresp spec: %s\n", *av);
748 1840
        http_rxhdr(hp);
749 1840
        http_splitheader(hp, 0);
750 1840
        if (http_count_header(hp->resp, "Content-Length") > 1)
751 0
                vtc_fatal(hp->vl,
752
                    "Multiple Content-Length headers.\n");
753 1840
}
754
755
/* SECTION: client-server.spec.gunzip
756
 *
757
 * gunzip
758
 *         Gunzip the body in place.
759
 */
760
static void
761 1480
cmd_http_gunzip(CMD_ARGS)
762
{
763
        struct http *hp;
764
765 1480
        (void)av;
766 1480
        (void)vl;
767
768 1480
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
769 1480
        vtc_gunzip(hp, hp->body, &hp->bodyl);
770 1480
}
771
772
/**********************************************************************
773
 * Handle common arguments of a transmitted request or response
774
 */
775
776
static char* const *
777 212283
http_tx_parse_args(char * const *av, struct vtclog *vl, struct http *hp,
778
    char *body, unsigned nohost, unsigned nodate, unsigned noserver, unsigned nouseragent)
779
{
780 212283
        long bodylen = 0;
781
        char *b, *c;
782
        char *nullbody;
783
        ssize_t len;
784 212283
        int nolen = 0;
785
        int l;
786
787 212283
        nullbody = body;
788
789 300404
        for (; *av != NULL; av++) {
790 133441
                if (!strcmp(*av, "-nolen")) {
791 5319
                        nolen = 1;
792 133441
                } else if (!strcmp(*av, "-nohost")) {
793 80
                        nohost = 1;
794 128122
                } else if (!strcmp(*av, "-nodate")) {
795 320
                        nodate = 1;
796 128042
                } else if (!strcmp(*av, "-hdr")) {
797 82242
                        if (!strncasecmp(av[1], "Content-Length:", 15) ||
798 79680
                            !strncasecmp(av[1], "Transfer-Encoding:", 18))
799 5919
                                nolen = 1;
800 82242
                        if (!strncasecmp(av[1], "Host:", 5))
801 1440
                                nohost = 1;
802 82242
                        if (!strncasecmp(av[1], "Date:", 5))
803 320
                                nodate = 1;
804 82242
                        if (!strncasecmp(av[1], "Server:", 7))
805 600
                                noserver = 1;
806 82242
                        if (!strncasecmp(av[1], "User-Agent:", 11))
807 80
                                nouseragent = 1;
808 82242
                        VSB_printf(hp->vsb, "%s%s", av[1], nl);
809 82242
                        av++;
810 127722
                } else if (!strcmp(*av, "-hdrlen")) {
811 160
                        VSB_printf(hp->vsb, "%s: ", av[1]);
812 160
                        l = atoi(av[2]);
813 30160
                        while (l-- > 0)
814 30000
                                VSB_putc(hp->vsb, '0' + (l % 10));
815 160
                        VSB_printf(hp->vsb, "%s", nl);
816 160
                        av+=2;
817 160
                } else
818 45320
                        break;
819 88121
        }
820 258242
        for (; *av != NULL; av++) {
821 45959
                if (!strcmp(*av, "-body")) {
822 29879
                        assert(body == nullbody);
823 29879
                        REPLACE(body, av[1]);
824
825 29879
                        AN(body);
826 29879
                        av++;
827 29879
                        bodylen = strlen(body);
828 926467
                        for (b = body; *b != '\0'; b++) {
829 896588
                                if (*b == '\\' && b[1] == '0') {
830 160
                                        *b = '\0';
831 1640
                                        for (c = b+1; *c != '\0'; c++) {
832 1480
                                                *c = c[1];
833 1480
                                        }
834 160
                                        b++;
835 160
                                        bodylen--;
836 160
                                }
837 896588
                        }
838 45959
                } else if (!strcmp(*av, "-bodyfrom")) {
839 80
                        assert(body == nullbody);
840 80
                        free(body);
841 80
                        body = VFIL_readfile(NULL, av[1], &len);
842 80
                        AN(body);
843 80
                        assert(len < INT_MAX);
844 80
                        bodylen = len;
845 80
                        av++;
846 16080
                } else if (!strcmp(*av, "-bodylen")) {
847 8840
                        assert(body == nullbody);
848 8840
                        free(body);
849 8840
                        body = synth_body(av[1], 0);
850 8840
                        bodylen = strlen(body);
851 8840
                        av++;
852 16000
                } else if (!strncmp(*av, "-gzip", 5)) {
853 7160
                        l = vtc_gzip_cmd(hp, av, &body, &bodylen);
854 7160
                        if (l == 0)
855 0
                                break;
856 7160
                        av += l;
857 7160
                        if (l > 1)
858 6520
                                VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl);
859 7160
                } else
860 0
                        break;
861 45959
        }
862 212283
        if (!nohost) {
863 123193
                VSB_cat(hp->vsb, "Host: ");
864 123193
                macro_cat(vl, hp->vsb, "localhost", NULL);
865 123193
                VSB_cat(hp->vsb, nl);
866 123193
        }
867 212283
        if (!nodate) {
868 85251
                VSB_cat(hp->vsb, "Date: ");
869 85251
                macro_cat(vl, hp->vsb, "date", NULL);
870 85251
                VSB_cat(hp->vsb, nl);
871 85251
        }
872 212283
        if (!noserver)
873 84734
                VSB_printf(hp->vsb, "Server: %s%s", hp->sess->name, nl);
874 212283
        if (!nouseragent)
875 126157
                VSB_printf(hp->vsb, "User-Agent: %s%s", hp->sess->name, nl);
876 212283
        if (body != NULL && !nolen)
877 83254
                VSB_printf(hp->vsb, "Content-Length: %ld%s", bodylen, nl);
878 212283
        VSB_cat(hp->vsb, nl);
879 212283
        if (body != NULL) {
880 88454
                VSB_bcat(hp->vsb, body, bodylen);
881 88454
                free(body);
882 88454
        }
883 212283
        return (av);
884
}
885
886
/* SECTION: client-server.spec.txreq
887
 *
888
 * txreq|txresp [...]
889
 *         Send a minimal request or response, but overload it if necessary.
890
 *
891
 *         txreq is client-specific and txresp is server-specific.
892
 *
893
 *         The only thing different between a request and a response, apart
894
 *         from who can send them is that the first line (request line vs
895
 *         status line), so all the options are pretty much the same.
896
 *
897
 *         \-method STRING (txreq only)
898
 *                 What method to use (default: "GET").
899
 *
900
 *         \-req STRING (txreq only)
901
 *                 Alias for -method.
902
 *
903
 *         \-url STRING (txreq only)
904
 *                 What location to use (default "/").
905
 *
906
 *         \-proto STRING
907
 *                 What protocol use in the status line.
908
 *                 (default: "HTTP/1.1").
909
 *
910
 *         \-status NUMBER (txresp only)
911
 *                 What status code to return (default 200).
912
 *
913
 *         \-reason STRING (txresp only)
914
 *                 What message to put in the status line (default: "OK").
915
 *
916
 *         \-noserver (txresp only)
917
 *                 Don't include a Server header with the id of the server.
918
 *
919
 *         \-nouseragent (txreq only)
920
 *                 Don't include a User-Agent header with the id of the client.
921
 *
922
 *         These three switches can appear in any order but must come before the
923
 *         following ones.
924
 *
925
 *         \-nohost
926
 *                 Don't include a Host header in the request. Also Implied
927
 *                 by the addition of a Host header with ``-hdr``.
928
 *
929
 *         \-nolen
930
 *                 Don't include a Content-Length header. Also implied by the
931
 *                 addition of a Content-Length or Transfer-Encoding header
932
 *                 with ``-hdr``.
933
 *
934
 *         \-nodate
935
 *                 Don't include a Date header in the response. Also implied
936
 *                 by the addition of a Date header with ``-hdr``.
937
 *
938
 *         \-hdr STRING
939
 *                 Add STRING as a header, it must follow this format:
940
 *                 "name: value". It can be called multiple times.
941
 *
942
 *         \-hdrlen STRING NUMBER
943
 *                 Add STRING as a header with NUMBER bytes of content.
944
 *
945
 *         You can then use the arguments related to the body:
946
 *
947
 *         \-body STRING
948
 *                 Input STRING as body.
949
 *
950
 *         \-bodyfrom FILE
951
 *                 Same as -body but content is read from FILE.
952
 *
953
 *         \-bodylen NUMBER
954
 *                 Generate and input a body that is NUMBER bytes-long.
955
 *
956
 *         \-gziplevel NUMBER
957
 *                 Set the gzip level (call it before any of the other gzip
958
 *                 switches).
959
 *
960
 *         \-gzipresidual NUMBER
961
 *                 Add extra gzip bits. You should never need it.
962
 *
963
 *         \-gzipbody STRING
964
 *                 Gzip STRING and send it as body.
965
 *
966
 *         \-gziplen NUMBER
967
 *                 Combine -bodylen and -gzipbody: generate a string of length
968
 *                 NUMBER, gzip it and send as body.
969
 */
970
971
/**********************************************************************
972
 * Transmit a response
973
 */
974
975
static void
976 85892
cmd_http_txresp(CMD_ARGS)
977
{
978
        struct http *hp;
979 85892
        const char *proto = "HTTP/1.1";
980 85892
        const char *status = "200";
981 85892
        const char *reason = "OK";
982 85892
        char* body = NULL;
983 85892
        unsigned noserver = 0;
984
985 85892
        (void)vl;
986 85892
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
987 85892
        ONLY_SERVER(hp, av);
988 85892
        AZ(strcmp(av[0], "txresp"));
989 85892
        av++;
990
991 85892
        VSB_clear(hp->vsb);
992
993 95412
        for (; *av != NULL; av++) {
994 66039
                if (!strcmp(*av, "-proto")) {
995 1640
                        proto = av[1];
996 1640
                        av++;
997 66039
                } else if (!strcmp(*av, "-status")) {
998 6200
                        status = av[1];
999 6200
                        av++;
1000 64399
                } else if (!strcmp(*av, "-reason")) {
1001 1120
                        reason = av[1];
1002 1120
                        av++;
1003 1120
                        continue;
1004 57079
                } else if (!strcmp(*av, "-noserver")) {
1005 560
                        noserver = 1;
1006 560
                        continue;
1007
                } else
1008 56519
                        break;
1009 7840
        }
1010
1011 85892
        VSB_printf(hp->vsb, "%s %s %s%s", proto, status, reason, nl);
1012
1013
        /* send a "Content-Length: 0" header unless something else happens */
1014 85892
        REPLACE(body, "");
1015
1016 85892
        av = http_tx_parse_args(av, vl, hp, body, 1, 0, noserver, 1);
1017 85892
        if (*av != NULL)
1018 0
                vtc_fatal(hp->vl, "Unknown http txresp spec: %s\n", *av);
1019
1020 85892
        http_write(hp, 4, "txresp");
1021 85892
}
1022
1023
static void
1024 40
cmd_http_upgrade(CMD_ARGS)
1025
{
1026
        char *h;
1027
        struct http *hp;
1028
1029 40
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1030 40
        ONLY_SERVER(hp, av);
1031 40
        AN(hp->sfd);
1032
1033 40
        h = http_find_header(hp->req, "Upgrade");
1034 40
        if (!h || strcmp(h, "h2c"))
1035 0
                vtc_fatal(vl, "Req misses \"Upgrade: h2c\" header");
1036
1037 40
        h = http_find_header(hp->req, "Connection");
1038 40
        if (!h || strcmp(h, "Upgrade, HTTP2-Settings"))
1039 0
                vtc_fatal(vl, "Req misses \"Connection: "
1040
                        "Upgrade, HTTP2-Settings\" header");
1041
1042 40
        h = http_find_header(hp->req, "HTTP2-Settings");
1043 40
        if (!h)
1044 0
                vtc_fatal(vl, "Req misses \"HTTP2-Settings\" header");
1045
1046 40
        parse_string(vl, hp,
1047
            "txresp -status 101"
1048
            " -hdr \"Connection: Upgrade\""
1049
            " -hdr \"Upgrade: h2c\"\n"
1050
        );
1051
1052 40
        b64_settings(hp, h);
1053
1054 40
        parse_string(vl, hp,
1055
            "rxpri\n"
1056
            "stream 0 {\n"
1057
            "    txsettings\n"
1058
            "    rxsettings\n"
1059
            "    txsettings -ack\n"
1060
            "    rxsettings\n"
1061
            "    expect settings.ack == true\n"
1062
            "} -start\n"
1063
        );
1064 40
}
1065
1066
/**********************************************************************
1067
 * Receive a request
1068
 */
1069
1070
/* SECTION: client-server.spec.rxreq
1071
 *
1072
 * rxreq (server only)
1073
 *         Receive and parse a request's headers and body.
1074
 */
1075
static void
1076 92543
cmd_http_rxreq(CMD_ARGS)
1077
{
1078
        struct http *hp;
1079
1080 92543
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1081 92543
        ONLY_SERVER(hp, av);
1082 92543
        AZ(strcmp(av[0], "rxreq"));
1083 92543
        av++;
1084
1085 92543
        for (; *av != NULL; av++)
1086 0
                vtc_fatal(vl, "Unknown http rxreq spec: %s\n", *av);
1087 92543
        http_rxhdr(hp);
1088 92543
        http_splitheader(hp, 1);
1089 92543
        if (http_count_header(hp->req, "Content-Length") > 1)
1090 0
                vtc_fatal(vl, "Multiple Content-Length headers.\n");
1091 92543
        http_swallow_body(hp, hp->req, 0, 0);
1092 92543
        vtc_log(vl, 4, "bodylen = %s", hp->bodylen);
1093 92543
}
1094
1095
/* SECTION: client-server.spec.rxreqhdrs
1096
 *
1097
 * rxreqhdrs (server only)
1098
 *         Receive and parse a request's headers (but not the body).
1099
 */
1100
1101
static void
1102 200
cmd_http_rxreqhdrs(CMD_ARGS)
1103
{
1104
        struct http *hp;
1105
1106 200
        (void)vl;
1107 200
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1108 200
        AZ(strcmp(av[0], "rxreqhdrs"));
1109 200
        av++;
1110
1111 200
        for (; *av != NULL; av++)
1112 0
                vtc_fatal(hp->vl, "Unknown http rxreq spec: %s\n", *av);
1113 200
        http_rxhdr(hp);
1114 200
        http_splitheader(hp, 1);
1115 200
        if (http_count_header(hp->req, "Content-Length") > 1)
1116 0
                vtc_fatal(hp->vl, "Multiple Content-Length headers.\n");
1117 200
}
1118
1119
/* SECTION: client-server.spec.rxreqbody
1120
 *
1121
 * rxreqbody (server only)
1122
 *         Receive a request's body.
1123
 */
1124
1125
static void
1126 160
cmd_http_rxreqbody(CMD_ARGS)
1127
{
1128
        struct http *hp;
1129
1130 160
        (void)vl;
1131 160
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1132 160
        ONLY_SERVER(hp, av);
1133 160
        AZ(strcmp(av[0], "rxreqbody"));
1134 160
        av++;
1135
1136 160
        for (; *av != NULL; av++)
1137 0
                vtc_fatal(hp->vl, "Unknown http rxreq spec: %s\n", *av);
1138 160
        http_swallow_body(hp, hp->req, 0, 0);
1139 160
        vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
1140 160
}
1141
1142
/* SECTION: client-server.spec.rxrespbody
1143
 *
1144
 * rxrespbody (client only)
1145
 *         Receive (part of) a response's body.
1146
 *
1147
 * -max : max length of this receive, 0 for all
1148
 */
1149
1150
static void
1151 1320
cmd_http_rxrespbody(CMD_ARGS)
1152
{
1153
        struct http *hp;
1154 1320
        int max = 0;
1155
1156 1320
        (void)vl;
1157 1320
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1158 1320
        ONLY_CLIENT(hp, av);
1159 1320
        AZ(strcmp(av[0], "rxrespbody"));
1160 1320
        av++;
1161
1162 1720
        for (; *av != NULL; av++)
1163 800
                if (!strcmp(*av, "-max")) {
1164 400
                        max = atoi(av[1]);
1165 400
                        av++;
1166 400
                } else
1167 0
                        vtc_fatal(hp->vl,
1168 0
                            "Unknown http rxrespbody spec: %s\n", *av);
1169
1170 1320
        http_swallow_body(hp, hp->resp, 1, max);
1171 1320
        vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
1172 1320
}
1173
1174
/* SECTION: client-server.spec.rxchunk
1175
 *
1176
 * rxchunk
1177
 *         Receive an HTTP chunk.
1178
 */
1179
1180
static void
1181 520
cmd_http_rxchunk(CMD_ARGS)
1182
{
1183
        struct http *hp;
1184
        int ll, i;
1185
1186 520
        (void)vl;
1187 520
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1188 520
        ONLY_CLIENT(hp, av);
1189
1190 520
        i = http_rxchunk(hp);
1191 520
        if (i == 0) {
1192 0
                ll = hp->rx_p - hp->body;
1193 0
                hp->bodyl = ll;
1194 0
                bprintf(hp->bodylen, "%d", ll);
1195 0
                vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
1196 0
        }
1197 520
}
1198
1199
/**********************************************************************
1200
 * Transmit a request
1201
 */
1202
1203
static void
1204 126387
cmd_http_txreq(CMD_ARGS)
1205
{
1206
        struct http *hp;
1207 126387
        const char *req = "GET";
1208 126387
        const char *url = "/";
1209 126387
        const char *proto = "HTTP/1.1";
1210 126387
        const char *up = NULL;
1211
        unsigned nohost;
1212 126387
        unsigned nouseragent = 0;
1213
1214 126387
        (void)vl;
1215 126387
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1216 126387
        ONLY_CLIENT(hp, av);
1217 126387
        AZ(strcmp(av[0], "txreq"));
1218 126387
        av++;
1219
1220 126387
        VSB_clear(hp->vsb);
1221
1222 126387
        hp->head_method = 0;
1223 205505
        for (; *av != NULL; av++) {
1224 115038
                if (!strcmp(*av, "-url")) {
1225 66318
                        url = av[1];
1226 66318
                        av++;
1227 115038
                } else if (!strcmp(*av, "-proto")) {
1228 2000
                        proto = av[1];
1229 2000
                        av++;
1230 48720
                } else if (!strcmp(*av, "-method") ||
1231 41880
                    !strcmp(*av, "-req")) {
1232 10640
                        req = av[1];
1233 10640
                        hp->head_method = !strcmp(av[1], "HEAD") ;
1234 10640
                        av++;
1235 46720
                } else if (!hp->sfd && !strcmp(*av, "-up")) {
1236 0
                        up = av[1];
1237 0
                        av++;
1238 36080
                } else if (!strcmp(*av, "-nouseragent")) {
1239 160
                        nouseragent = 1;
1240 160
                } else
1241 35920
                        break;
1242 79118
        }
1243 126387
        VSB_printf(hp->vsb, "%s %s %s%s", req, url, proto, nl);
1244
1245 126387
        if (up)
1246 0
                VSB_printf(hp->vsb, "Connection: Upgrade, HTTP2-Settings%s"
1247
                                "Upgrade: h2c%s"
1248 0
                                "HTTP2-Settings: %s%s", nl, nl, up, nl);
1249
1250 126387
        nohost = strcmp(proto, "HTTP/1.1") != 0;
1251 126387
        av = http_tx_parse_args(av, vl, hp, NULL, nohost, 1, 1, nouseragent);
1252 126387
        if (*av != NULL)
1253 0
                vtc_fatal(hp->vl, "Unknown http txreq spec: %s\n", *av);
1254 126387
        http_write(hp, 4, "txreq");
1255
1256 126387
        if (up) {
1257 0
                parse_string(vl, hp,
1258
                    "rxresp\n"
1259
                    "expect resp.status == 101\n"
1260
                    "expect resp.http.connection == Upgrade\n"
1261
                    "expect resp.http.upgrade == h2c\n"
1262
                    "txpri\n"
1263
                );
1264 0
                b64_settings(hp, up);
1265 0
                parse_string(vl, hp,
1266
                    "stream 0 {\n"
1267
                    "    txsettings\n"
1268
                    "    rxsettings\n"
1269
                    "    txsettings -ack\n"
1270
                    "    rxsettings\n"
1271
                    "    expect settings.ack == true"
1272
                    "} -start\n"
1273
                );
1274 0
        }
1275 126387
}
1276
1277
/* SECTION: client-server.spec.recv
1278
 *
1279
 * recv NUMBER
1280
 *         Read NUMBER bytes from the connection.
1281
 */
1282
1283
static void
1284 360
cmd_http_recv(CMD_ARGS)
1285
{
1286
        struct http *hp;
1287
        int i, n;
1288
        char u[32];
1289
1290 360
        (void)vl;
1291 360
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1292 360
        AN(av[1]);
1293 360
        AZ(av[2]);
1294 360
        n = strtoul(av[1], NULL, 0);
1295 1160
        while (n > 0) {
1296 800
                i = read(hp->sess->fd, u, n > 32 ? 32 : n);
1297 800
                if (i > 0)
1298 800
                        vtc_dump(hp->vl, 4, "recv", u, i);
1299
                else
1300 0
                        vtc_log(hp->vl, hp->fatal, "recv() got %d (%s)", i,
1301 0
                            strerror(errno));
1302 800
                n -= i;
1303
        }
1304 360
}
1305
1306
/* SECTION: client-server.spec.send
1307
 *
1308
 * send STRING
1309
 *         Push STRING on the connection.
1310
 */
1311
1312
static void
1313 34967
cmd_http_send(CMD_ARGS)
1314
{
1315
        struct http *hp;
1316
        int i;
1317
1318 34967
        (void)vl;
1319 34967
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1320 34967
        AN(av[1]);
1321 34967
        AZ(av[2]);
1322 34967
        vtc_dump(hp->vl, 4, "send", av[1], -1);
1323 34967
        i = write(hp->sess->fd, av[1], strlen(av[1]));
1324 34967
        if (i != strlen(av[1]))
1325 8
                vtc_log(hp->vl, hp->fatal, "Write error in http_send(): %s",
1326 4
                    strerror(errno));
1327 34967
}
1328
1329
/* SECTION: client-server.spec.send_n
1330
 *
1331
 * send_n NUMBER STRING
1332
 *         Write STRING on the socket NUMBER times.
1333
 */
1334
1335
static void
1336 80
cmd_http_send_n(CMD_ARGS)
1337
{
1338
        struct http *hp;
1339
        int i, n, l;
1340
1341 80
        (void)vl;
1342 80
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1343 80
        AN(av[1]);
1344 80
        AN(av[2]);
1345 80
        AZ(av[3]);
1346 80
        n = strtoul(av[1], NULL, 0);
1347 80
                vtc_dump(hp->vl, 4, "send_n", av[2], -1);
1348 80
        l = strlen(av[2]);
1349 82400
        while (n--) {
1350 82320
                i = write(hp->sess->fd, av[2], l);
1351 82320
                if (i != l)
1352 7766
                        vtc_log(hp->vl, hp->fatal,
1353
                            "Write error in http_send(): %s",
1354 3883
                            strerror(errno));
1355
        }
1356 80
}
1357
1358
/* SECTION: client-server.spec.send_urgent
1359
 *
1360
 * send_urgent STRING
1361
 *         Send string as TCP OOB urgent data. You will never need this.
1362
 */
1363
1364
static void
1365 400
cmd_http_send_urgent(CMD_ARGS)
1366
{
1367
        struct http *hp;
1368
        int i;
1369
1370 400
        (void)vl;
1371 400
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1372 400
        AN(av[1]);
1373 400
        AZ(av[2]);
1374 400
        vtc_dump(hp->vl, 4, "send_urgent", av[1], -1);
1375 400
        i = send(hp->sess->fd, av[1], strlen(av[1]), MSG_OOB);
1376 400
        if (i != strlen(av[1]))
1377 0
                vtc_log(hp->vl, hp->fatal,
1378 0
                    "Write error in http_send_urgent(): %s", strerror(errno));
1379 400
}
1380
1381
/* SECTION: client-server.spec.sendhex
1382
 *
1383
 * sendhex STRING
1384
 *         Send bytes as described by STRING. STRING should consist of hex pairs
1385
 *         possibly separated by whitespace or newlines. For example:
1386
 *         "0F EE a5    3df2".
1387
 */
1388
1389
static void
1390 6440
cmd_http_sendhex(CMD_ARGS)
1391
{
1392
        struct vsb *vsb;
1393
        struct http *hp;
1394
1395 6440
        (void)vl;
1396 6440
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1397 6440
        AN(av[1]);
1398 6440
        AZ(av[2]);
1399 6440
        vsb = vtc_hex_to_bin(hp->vl, av[1]);
1400 6440
        assert(VSB_len(vsb) >= 0);
1401 6440
        vtc_hexdump(hp->vl, 4, "sendhex", VSB_data(vsb), VSB_len(vsb));
1402 6440
        if (VSB_tofile(vsb, hp->sess->fd))
1403 0
                vtc_log(hp->vl, hp->fatal, "Write failed: %s",
1404 0
                    strerror(errno));
1405 6440
        VSB_destroy(&vsb);
1406 6440
}
1407
1408
/* SECTION: client-server.spec.chunked
1409
 *
1410
 * chunked STRING
1411
 *         Send STRING as chunked encoding.
1412
 */
1413
1414
static void
1415 2400
cmd_http_chunked(CMD_ARGS)
1416
{
1417
        struct http *hp;
1418
1419 2400
        (void)vl;
1420 2400
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1421 2400
        AN(av[1]);
1422 2400
        AZ(av[2]);
1423 2400
        VSB_clear(hp->vsb);
1424 4800
        VSB_printf(hp->vsb, "%jx%s%s%s",
1425 2400
            (uintmax_t)strlen(av[1]), nl, av[1], nl);
1426 2400
        http_write(hp, 4, "chunked");
1427 2400
}
1428
1429
/* SECTION: client-server.spec.chunkedlen
1430
 *
1431
 * chunkedlen NUMBER
1432
 *         Do as ``chunked`` except that the string will be generated
1433
 *         for you, with a length of NUMBER characters.
1434
 */
1435
1436
static void
1437 7314
cmd_http_chunkedlen(CMD_ARGS)
1438
{
1439
        unsigned len;
1440
        unsigned u, v;
1441
        char buf[16384];
1442
        struct http *hp;
1443
1444 7314
        (void)vl;
1445 7314
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1446 7314
        AN(av[1]);
1447 7314
        AZ(av[2]);
1448 7314
        VSB_clear(hp->vsb);
1449
1450 7314
        len = atoi(av[1]);
1451
1452 7314
        if (len == 0) {
1453 2719
                VSB_printf(hp->vsb, "0%s%s", nl, nl);
1454 2719
        } else {
1455 67622891
                for (u = 0; u < sizeof buf; u++)
1456 67618296
                        buf[u] = (u & 7) + '0';
1457
1458 4595
                VSB_printf(hp->vsb, "%x%s", len, nl);
1459 16155
                for (u = 0; u < len; u += v) {
1460 11560
                        v = vmin_t(unsigned, len - u, sizeof buf);
1461 11560
                        VSB_bcat(hp->vsb, buf, v);
1462 11560
                }
1463 4595
                VSB_printf(hp->vsb, "%s", nl);
1464
        }
1465 7314
        http_write(hp, 4, "chunked");
1466 7314
}
1467
1468
1469
/* SECTION: client-server.spec.timeout
1470
 *
1471
 * timeout NUMBER
1472
 *         Set the TCP timeout for this entity.
1473
 */
1474
1475
static void
1476 1320
cmd_http_timeout(CMD_ARGS)
1477
{
1478
        struct http *hp;
1479
        double d;
1480
1481 1320
        (void)vl;
1482 1320
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1483 1320
        AN(av[1]);
1484 1320
        AZ(av[2]);
1485 1320
        d = VNUM(av[1]);
1486 1320
        if (isnan(d))
1487 0
                vtc_fatal(vl, "timeout is not a number (%s)", av[1]);
1488 1320
        hp->timeout = d;
1489 1320
}
1490
1491
/* SECTION: client-server.spec.expect_close
1492
 *
1493
 * expect_close
1494
 *      Reads from the connection, expecting nothing to read but an EOF.
1495
 */
1496
static void
1497 6573
cmd_http_expect_close(CMD_ARGS)
1498
{
1499
        struct http *hp;
1500
        struct pollfd fds[1];
1501
        char c;
1502
        int i;
1503
1504 6573
        (void)vl;
1505 6573
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1506 6573
        AZ(av[1]);
1507
1508 6573
        vtc_log(vl, 4, "Expecting close (fd = %d)", hp->sess->fd);
1509 6573
        if (hp->h2)
1510 560
                stop_h2(hp);
1511 6573
        while (1) {
1512 6573
                fds[0].fd = hp->sess->fd;
1513 6573
                fds[0].events = POLLIN;
1514 6573
                fds[0].revents = 0;
1515 6573
                i = poll(fds, 1, (int)(hp->timeout * 1000));
1516 6573
                if (i < 0 && errno == EINTR)
1517 0
                        continue;
1518 6573
                if (i == 0)
1519 0
                        vtc_log(vl, hp->fatal, "Expected close: timeout");
1520 6573
                if (i != 1 || !(fds[0].revents & (POLLIN|POLLERR|POLLHUP)))
1521 416
                        vtc_log(vl, hp->fatal,
1522
                            "Expected close: poll = %d, revents = 0x%x",
1523 208
                            i, fds[0].revents);
1524 6365
                i = read(hp->sess->fd, &c, 1);
1525 6365
                if (i <= 0 && VTCP_Check(i))
1526 6365
                        break;
1527 210
                if (i == 1 && vct_islws(c))
1528 0
                        continue;
1529 0
                vtc_log(vl, hp->fatal,
1530 0
                    "Expecting close: read = %d, c = 0x%02x", i, c);
1531
        }
1532 6365
        vtc_log(vl, 4, "fd=%d EOF, as expected", hp->sess->fd);
1533 6365
}
1534
1535
/* SECTION: client-server.spec.close
1536
 *
1537
 * close (server only)
1538
 *      Close the connection. Note that if operating in HTTP/2 mode no
1539
 *      extra (GOAWAY) frame is sent, it's simply a TCP close.
1540
 */
1541
static void
1542 760
cmd_http_close(CMD_ARGS)
1543
{
1544
        struct http *hp;
1545
1546 760
        (void)vl;
1547 760
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1548 760
        ONLY_SERVER(hp, av);
1549 760
        AZ(av[1]);
1550 760
        assert(hp->sfd != NULL);
1551 760
        assert(*hp->sfd >= 0);
1552 760
        if (hp->h2)
1553 0
                stop_h2(hp);
1554 760
        VTCP_close(&hp->sess->fd);
1555 760
        vtc_log(vl, 4, "Closed");
1556 760
}
1557
1558
/* SECTION: client-server.spec.accept
1559
 *
1560
 * accept (server only)
1561
 *      Close the current connection, if any, and accept a new one. Note
1562
 *      that this new connection is HTTP/1.x.
1563
 */
1564
static void
1565 6518
cmd_http_accept(CMD_ARGS)
1566
{
1567
        struct http *hp;
1568
1569 6518
        (void)vl;
1570 6518
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1571 6518
        ONLY_SERVER(hp, av);
1572 6518
        AZ(av[1]);
1573 6518
        assert(hp->sfd != NULL);
1574 6518
        assert(*hp->sfd >= 0);
1575 6518
        if (hp->h2)
1576 0
                stop_h2(hp);
1577 6518
        if (hp->sess->fd >= 0)
1578 5798
                VTCP_close(&hp->sess->fd);
1579 6518
        vtc_log(vl, 4, "Accepting");
1580 6518
        hp->sess->fd = accept(*hp->sfd, NULL, NULL);
1581 6518
        if (hp->sess->fd < 0)
1582 0
                vtc_log(vl, hp->fatal, "Accepted failed: %s", strerror(errno));
1583 6518
        vtc_log(vl, 3, "Accepted socket fd is %d", hp->sess->fd);
1584 6518
}
1585
1586
/* SECTION: client-server.spec.shutdown
1587
 *
1588
 * shutdown
1589
 *      Initiate shutdown.
1590
 *
1591
 *      \-read
1592
 *              Shutdown the read direction.
1593
 *      \-write
1594
 *              Shutdown the write direction.
1595
 *
1596
 *      The default is both direction.
1597
 */
1598
static void
1599 240
cmd_http_shutdown(CMD_ARGS)
1600
{
1601
        struct http *hp;
1602 240
        int how = SHUT_RDWR;
1603 240
        const char *str[] = {
1604
                [SHUT_RD]       = "RD",
1605
                [SHUT_WR]       = "WR",
1606
                [SHUT_RDWR]     = "RDWR",
1607
        };
1608
1609 240
        (void)vl;
1610 240
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1611 240
        AZ(strcmp(av[0], "shutdown"));
1612 240
        av++;
1613
1614 240
        if (*av != NULL) {
1615 160
                if (!strcmp(*av, "-read")) {
1616 80
                        how = SHUT_RD;
1617 80
                        av++;
1618 160
                } else if (!strcmp(*av, "-write")) {
1619 80
                        how = SHUT_WR;
1620 80
                        av++;
1621 80
                }
1622 160
        }
1623
1624 240
        if (*av != NULL)
1625 0
                vtc_fatal(hp->vl, "Unknown http shutdown spec: %s\n", *av);
1626
1627 240
        vtc_log(vl, 4, "Shutting down fd (%s): %d", str[how], hp->sess->fd);
1628 240
        if (shutdown(hp->sess->fd, how) < 0)
1629 0
                vtc_log(vl, hp->fatal, "Shutdown failed: %s", strerror(errno));
1630 240
        vtc_log(vl, 3, "Shutdown socket fd (%d): %d", how, hp->sess->fd);
1631 240
}
1632
1633
/* SECTION: client-server.spec.fatal
1634
 *
1635
 * fatal|non_fatal
1636
 *         Control whether a failure of this entity should stop the test.
1637
 */
1638
1639
static void
1640 16207
cmd_http_fatal(CMD_ARGS)
1641
{
1642
        struct http *hp;
1643 16207
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1644
1645 16207
        (void)vl;
1646 16207
        AZ(av[1]);
1647 16207
        if (!strcmp(av[0], "fatal")) {
1648 640
                hp->fatal = 0;
1649 640
        } else {
1650 15567
                assert(!strcmp(av[0], "non_fatal"));
1651 15567
                hp->fatal = -1;
1652
        }
1653 16207
}
1654
1655
#define cmd_http_non_fatal cmd_http_fatal
1656
1657
static const char PREFACE[24] = {
1658
        0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54,
1659
        0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a,
1660
        0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a
1661
};
1662
1663
/* SECTION: client-server.spec.txpri
1664
 *
1665
 * txpri (client only)
1666
 *      Send an HTTP/2 preface ("PRI * HTTP/2.0\\r\\n\\r\\nSM\\r\\n\\r\\n")
1667
 *      and set client to HTTP/2.
1668
 */
1669
static void
1670 6760
cmd_http_txpri(CMD_ARGS)
1671
{
1672
        size_t l;
1673
        struct http *hp;
1674
1675 6760
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1676 6760
        ONLY_CLIENT(hp, av);
1677
1678 6760
        vtc_dump(hp->vl, 4, "txpri", PREFACE, sizeof(PREFACE));
1679
        /* Dribble out the preface */
1680 6760
        l = write(hp->sess->fd, PREFACE, 18);
1681 6760
        if (l != 18)
1682 0
                vtc_log(vl, hp->fatal, "Write failed: (%zd vs %zd) %s",
1683 0
                    l, sizeof(PREFACE), strerror(errno));
1684 6760
        usleep(10000);
1685 6760
        l = write(hp->sess->fd, PREFACE + 18, sizeof(PREFACE) - 18);
1686 6760
        if (l != sizeof(PREFACE) - 18)
1687 0
                vtc_log(vl, hp->fatal, "Write failed: (%zd vs %zd) %s",
1688 0
                    l, sizeof(PREFACE), strerror(errno));
1689
1690 6760
        start_h2(hp);
1691 6760
        AN(hp->h2);
1692 6760
}
1693
1694
/* SECTION: client-server.spec.rxpri
1695
 *
1696
 * rxpri (server only)
1697
 *      Receive a preface. If valid set the server to HTTP/2, abort
1698
 *      otherwise.
1699
 */
1700
static void
1701 1160
cmd_http_rxpri(CMD_ARGS)
1702
{
1703
        struct http *hp;
1704
1705 1160
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1706 1160
        ONLY_SERVER(hp, av);
1707
1708 1160
        hp->rx_p = hp->rx_b;
1709 1160
        if (!http_rxchar(hp, sizeof(PREFACE), 0))
1710 0
                vtc_fatal(vl, "Couldn't retrieve connection preface");
1711 1160
        if (memcmp(hp->rx_b, PREFACE, sizeof(PREFACE)))
1712 0
                vtc_fatal(vl, "Received invalid preface\n");
1713 1160
        start_h2(hp);
1714 1160
        AN(hp->h2);
1715 1160
}
1716
1717
/* SECTION: client-server.spec.settings
1718
 *
1719
 * settings -dectbl INT
1720
 *      Force internal HTTP/2 settings to certain values. Currently only
1721
 *      support setting the decoding table size.
1722
 */
1723
static void
1724 0
cmd_http_settings(CMD_ARGS)
1725
{
1726
        uint32_t n;
1727
        char *p;
1728
        struct http *hp;
1729 0
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1730
1731 0
        if (!hp->h2)
1732 0
                vtc_fatal(hp->vl, "Only possible in H/2 mode");
1733
1734 0
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1735
1736 0
        for (; *av != NULL; av++) {
1737 0
                if (!strcmp(*av, "-dectbl")) {
1738 0
                        n = strtoul(av[1], &p, 0);
1739 0
                        if (*p != '\0')
1740 0
                                vtc_fatal(hp->vl, "-dectbl takes an integer as "
1741 0
                                    "argument (found %s)", av[1]);
1742 0
                        assert(HPK_ResizeTbl(hp->decctx, n) != hpk_err);
1743 0
                        av++;
1744 0
                } else
1745 0
                        vtc_fatal(vl, "Unknown settings spec: %s\n", *av);
1746 0
        }
1747 0
}
1748
1749
static void
1750 22360
cmd_http_stream(CMD_ARGS)
1751
{
1752
        struct http *hp;
1753 22360
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1754 22360
        if (!hp->h2) {
1755 7080
                vtc_log(hp->vl, 4, "Not in H/2 mode, do what's needed");
1756 7080
                if (hp->sfd)
1757 1040
                        parse_string(vl, hp, "rxpri");
1758
                else
1759 6040
                        parse_string(vl, hp, "txpri");
1760 7080
                parse_string(vl, hp,
1761
                    "stream 0 {\n"
1762
                    "    txsettings\n"
1763
                    "    rxsettings\n"
1764
                    "    txsettings -ack\n"
1765
                    "    rxsettings\n"
1766
                    "    expect settings.ack == true"
1767
                    "} -run\n"
1768
                );
1769 7080
        }
1770 22360
        cmd_stream(av, hp, vl);
1771 22360
}
1772
1773
/* SECTION: client-server.spec.write_body
1774
 *
1775
 * write_body STRING
1776
 *      Write the body of a request or a response to a file. By using the
1777
 *      shell command, higher-level checks on the body can be performed
1778
 *      (eg. XML, JSON, ...) provided that such checks can be delegated
1779
 *      to an external program.
1780
 */
1781
static void
1782 80
cmd_http_write_body(CMD_ARGS)
1783
{
1784
        struct http *hp;
1785
1786 80
        (void)vl;
1787 80
        CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
1788 80
        AN(av[0]);
1789 80
        AN(av[1]);
1790 80
        AZ(av[2]);
1791 80
        AZ(strcmp(av[0], "write_body"));
1792 80
        if (VFIL_writefile(NULL, av[1], hp->body, hp->bodyl) != 0)
1793 0
                vtc_fatal(hp->vl, "failed to write body: %s (%d)",
1794 0
                    strerror(errno), errno);
1795 80
}
1796
1797
/**********************************************************************
1798
 * Execute HTTP specifications
1799
 */
1800
1801
const struct cmds http_cmds[] = {
1802
#define CMD_HTTP(n) { #n, cmd_http_##n },
1803
        /* session */
1804
        CMD_HTTP(accept)
1805
        CMD_HTTP(close)
1806
        CMD_HTTP(recv)
1807
        CMD_HTTP(send)
1808
        CMD_HTTP(send_n)
1809
        CMD_HTTP(send_urgent)
1810
        CMD_HTTP(sendhex)
1811
        CMD_HTTP(shutdown)
1812
        CMD_HTTP(timeout)
1813
1814
        /* spec */
1815
        CMD_HTTP(fatal)
1816
        CMD_HTTP(non_fatal)
1817
1818
        /* body */
1819
        CMD_HTTP(gunzip)
1820
        CMD_HTTP(write_body)
1821
1822
        /* HTTP/1.x */
1823
        CMD_HTTP(chunked)
1824
        CMD_HTTP(chunkedlen)
1825
        CMD_HTTP(rxchunk)
1826
1827
        /* HTTP/2 */
1828
        CMD_HTTP(stream)
1829
        CMD_HTTP(settings)
1830
1831
        /* client */
1832
        CMD_HTTP(rxresp)
1833
        CMD_HTTP(rxrespbody)
1834
        CMD_HTTP(rxresphdrs)
1835
        CMD_HTTP(txpri)
1836
        CMD_HTTP(txreq)
1837
1838
        /* server */
1839
        CMD_HTTP(rxpri)
1840
        CMD_HTTP(rxreq)
1841
        CMD_HTTP(rxreqbody)
1842
        CMD_HTTP(rxreqhdrs)
1843
        CMD_HTTP(txresp)
1844
        CMD_HTTP(upgrade)
1845
1846
        /* expect */
1847
        CMD_HTTP(expect)
1848
        CMD_HTTP(expect_close)
1849
        CMD_HTTP(expect_pattern)
1850
#undef CMD_HTTP
1851
        { NULL, NULL }
1852
};
1853
1854
static void
1855 154570
http_process_cleanup(void *arg)
1856
{
1857
        struct http *hp;
1858
1859 154570
        CAST_OBJ_NOTNULL(hp, arg, HTTP_MAGIC);
1860
1861 154570
        if (hp->h2)
1862 7360
                stop_h2(hp);
1863 154570
        VSB_destroy(&hp->vsb);
1864 154570
        free(hp->rx_b);
1865 154570
        free(hp->rem_ip);
1866 154570
        free(hp->rem_port);
1867 154570
        free(hp->rem_path);
1868 154570
        FREE_OBJ(hp);
1869 154570
}
1870
1871
int
1872 154587
http_process(struct vtclog *vl, struct vtc_sess *vsp, const char *spec,
1873
    int sock, int *sfd, const char *addr, int rcvbuf)
1874
{
1875
        struct http *hp;
1876
        int retval, oldbuf;
1877 154587
        socklen_t intlen = sizeof(int);
1878
1879 154587
        (void)sfd;
1880 154587
        ALLOC_OBJ(hp, HTTP_MAGIC);
1881 154587
        AN(hp);
1882 154587
        hp->sess = vsp;
1883 154587
        hp->sess->fd = sock;
1884 154587
        hp->timeout = vtc_maxdur * .5;
1885
1886 154587
        if (rcvbuf) {
1887
                // XXX setsockopt() too late on SunOS
1888
                // https://github.com/varnishcache/varnish-cache/pull/2980#issuecomment-486214661
1889 360
                hp->rcvbuf = rcvbuf;
1890
1891 360
                oldbuf = 0;
1892 360
                AZ(getsockopt(hp->sess->fd, SOL_SOCKET, SO_RCVBUF, &oldbuf, &intlen));
1893 360
                AZ(setsockopt(hp->sess->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, intlen));
1894 360
                AZ(getsockopt(hp->sess->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &intlen));
1895
1896 720
                vtc_log(vl, 3, "-rcvbuf fd=%d old=%d new=%d actual=%d",
1897 360
                    hp->sess->fd, oldbuf, hp->rcvbuf, rcvbuf);
1898 360
        }
1899
1900 154587
        hp->nrxbuf = 2048*1024;
1901 154587
        hp->rx_b = malloc(hp->nrxbuf);
1902 154587
        AN(hp->rx_b);
1903 154587
        hp->rx_e = hp->rx_b + hp->nrxbuf;
1904 154587
        hp->rx_p = hp->rx_b;
1905 154587
        *hp->rx_p = '\0';
1906
1907 154587
        hp->vsb = VSB_new_auto();
1908 154587
        AN(hp->vsb);
1909
1910 154587
        hp->sfd = sfd;
1911
1912 154587
        hp->rem_ip = malloc(VTCP_ADDRBUFSIZE);
1913 154587
        AN(hp->rem_ip);
1914
1915 154587
        hp->rem_port = malloc(VTCP_PORTBUFSIZE);
1916 154587
        AN(hp->rem_port);
1917
1918 154587
        hp->vl = vl;
1919 154587
        vtc_log_set_cmd(hp->vl, http_cmds);
1920 154587
        hp->gziplevel = 0;
1921 154587
        hp->gzipresidual = -1;
1922
1923 154587
        if (*addr != '/') {
1924 141548
                VTCP_hisname(sock, hp->rem_ip, VTCP_ADDRBUFSIZE, hp->rem_port,
1925
                             VTCP_PORTBUFSIZE);
1926 141548
                hp->rem_path = NULL;
1927 141548
        } else {
1928 13039
                strcpy(hp->rem_ip, "0.0.0.0");
1929 13039
                strcpy(hp->rem_port, "0");
1930 13039
                hp->rem_path = strdup(addr);
1931
        }
1932
        /* XXX: After an upgrade to HTTP/2 the cleanup of a server that is
1933
         * not -wait'ed before the test resets is subject to a race where the
1934
         * cleanup does not happen, so ASAN reports leaks despite the push
1935
         * of a cleanup handler. To easily reproduce, remove the server wait
1936
         * from a02022.vtc and run with ASAN enabled.
1937
         */
1938 154587
        pthread_cleanup_push(http_process_cleanup, hp);
1939 154587
        parse_string(vl, hp, spec);
1940 154587
        retval = hp->sess->fd;
1941 154587
        pthread_cleanup_pop(0);
1942 154587
        http_process_cleanup(hp);
1943 154587
        return (retval);
1944
}
1945
1946
/**********************************************************************
1947
 * Magic test routine
1948
 *
1949
 * This function brute-forces some short strings through gzip(9) to
1950
 * find candidates for all possible 8 bit positions of the stopbit.
1951
 *
1952
 * Here is some good short output strings:
1953
 *
1954
 *      0 184 <e04c8d0fd604c>
1955
 *      1 257 <1ea86e6cf31bf4ec3d7a86>
1956
 *      2 106 <10>
1957
 *      3 163 <a5e2e2e1c2e2>
1958
 *      4 180 <71c5d18ec5d5d1>
1959
 *      5 189 <39886d28a6d2988>
1960
 *      6 118 <80000>
1961
 *      7 151 <386811868>
1962
 *
1963
 */
1964
1965
#if 0
1966
void xxx(void);
1967
1968
void
1969
xxx(void)
1970
{
1971
        z_stream vz;
1972
        int n;
1973
        char ibuf[200];
1974
        char obuf[200];
1975
        int fl[8];
1976
        int i, j;
1977
1978
        for (n = 0; n < 8; n++)
1979
                fl[n] = 9999;
1980
1981
        memset(&vz, 0, sizeof vz);
1982
1983
        for (n = 0;  n < 999999999; n++) {
1984
                *ibuf = 0;
1985
                for (j = 0; j < 7; j++) {
1986
                        snprintf(strchr(ibuf, 0), 5, "%x",
1987
                            (unsigned)VRND_RandomTestable() & 0xffff);
1988
                        vz.next_in = TRUST_ME(ibuf);
1989
                        vz.avail_in = strlen(ibuf);
1990
                        vz.next_out = TRUST_ME(obuf);
1991
                        vz.avail_out = sizeof obuf;
1992
                        assert(Z_OK == deflateInit2(&vz,
1993
                            9, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY));
1994
                        assert(Z_STREAM_END == deflate(&vz, Z_FINISH));
1995
                        i = vz.stop_bit & 7;
1996
                        if (fl[i] > strlen(ibuf)) {
1997
                                printf("%d %jd <%s>\n", i, vz.stop_bit, ibuf);
1998
                                fl[i] = strlen(ibuf);
1999
                        }
2000
                        assert(Z_OK == deflateEnd(&vz));
2001
                }
2002
        }
2003
2004
        printf("FOO\n");
2005
}
2006
#endif