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