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