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