source: bin/varnishd/cache_http.c @ 897a6f

Revision 897a6f, 22.6 KB checked in by Poul-Henning Kamp <phk@…>, 7 years ago (diff)

Use pdiff() to guard against negative point differences

git-svn-id:  http://www.varnish-cache.org/svn/trunk@2022 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2007 Linpro AS
4 * All rights reserved.
5 *
6 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id$
30 *
31 * HTTP request storage and manipulation
32 */
33
34#include <stdio.h>
35#include <errno.h>
36#include <unistd.h>
37#include <stdarg.h>
38#include <stdlib.h>
39#include <string.h>
40#include <ctype.h>
41
42#include "heritage.h"
43#include "shmlog.h"
44#include "cache.h"
45
46#ifndef HAVE_STRLCPY
47#include <compat/strlcpy.h>
48#endif
49
50#define HTTPH(a, b, c, d, e, f, g) char b[] = "*" a ":";
51#include "http_headers.h"
52#undef HTTPH
53
54enum httptag {
55        HTTP_T_Request,
56        HTTP_T_Response,
57        HTTP_T_Status,
58        HTTP_T_URL,
59        HTTP_T_Protocol,
60        HTTP_T_Header,
61};
62
63#define LOGMTX2(ax, bx)         \
64        [HTTP_T_##bx] = SLT_##ax##bx
65
66#define LOGMTX1(ax) {           \
67        LOGMTX2(ax, Request),   \
68        LOGMTX2(ax, Response),  \
69        LOGMTX2(ax, Status),    \
70        LOGMTX2(ax, URL),       \
71        LOGMTX2(ax, Protocol),  \
72        LOGMTX2(ax, Header),    \
73        }
74
75static enum shmlogtag logmtx[3][7] = {
76        [HTTP_Rx] = LOGMTX1(Rx),
77        [HTTP_Tx] = LOGMTX1(Tx),
78        [HTTP_Obj] = LOGMTX1(Obj)
79};
80
81static enum shmlogtag
82http2shmlog(const struct http *hp, enum httptag t)
83{
84
85        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
86        assert(/* hp->logtag >= HTTP_Rx && */hp->logtag <= HTTP_Obj);
87        assert(/* t >= HTTP_T_Request && */t <= HTTP_T_Header);
88        return (logmtx[hp->logtag][t]);
89}
90
91static void
92WSLH(struct worker *w, enum httptag t, int fd, const struct http *hp, int hdr)
93{
94
95        WSLR(w, http2shmlog(hp, t), fd, hp->hd[hdr].b, hp->hd[hdr].e);
96}
97
98/*--------------------------------------------------------------------*/
99/* List of canonical HTTP response code names from RFC2616 */
100
101static struct http_msg {
102        unsigned        nbr;
103        const char      *txt;
104} http_msg[] = {
105        { 101, "Switching Protocols" },
106        { 200, "OK" },
107        { 201, "Created" },
108        { 202, "Accepted" },
109        { 203, "Non-Authoritative Information" },
110        { 204, "No Content" },
111        { 205, "Reset Content" },
112        { 206, "Partial Content" },
113        { 300, "Multiple Choices" },
114        { 301, "Moved Permanently" },
115        { 302, "Found" },
116        { 303, "See Other" },
117        { 304, "Not Modified" },
118        { 305, "Use Proxy" },
119        { 306, "(Unused)" },
120        { 307, "Temporary Redirect" },
121        { 400, "Bad Request" },
122        { 401, "Unauthorized" },
123        { 402, "Payment Required" },
124        { 403, "Forbidden" },
125        { 404, "Not Found" },
126        { 405, "Method Not Allowed" },
127        { 406, "Not Acceptable" },
128        { 407, "Proxy Authentication Required" },
129        { 408, "Request Timeout" },
130        { 409, "Conflict" },
131        { 410, "Gone" },
132        { 411, "Length Required" },
133        { 412, "Precondition Failed" },
134        { 413, "Request Entity Too Large" },
135        { 414, "Request-URI Too Long" },
136        { 415, "Unsupported Media Type" },
137        { 416, "Requested Range Not Satisfiable" },
138        { 417, "Expectation Failed" },
139        { 500, "Internal Server Error" },
140        { 501, "Not Implemented" },
141        { 502, "Bad Gateway" },
142        { 503, "Service Unavailable" },
143        { 504, "Gateway Timeout" },
144        { 505, "HTTP Version Not Supported" },
145        { 0, NULL }
146};
147
148const char *
149http_StatusMessage(int status)
150{
151        struct http_msg *mp;
152
153        assert(status >= 100 && status <= 999);
154        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
155                if (mp->nbr == status)
156                        return (mp->txt);
157        return ("Unknown Error");
158}
159
160/*--------------------------------------------------------------------*/
161
162void
163http_Setup(struct http *hp, void *space, unsigned len)
164{
165
166        assert(len > 0);
167        memset(hp, 0, sizeof *hp);
168        hp->magic = HTTP_MAGIC;
169        WS_Init(hp->ws, space, len);
170        hp->nhd = HTTP_HDR_FIRST;
171}
172
173/*--------------------------------------------------------------------*/
174
175
176static int
177http_IsHdr(const struct http_hdr *hh, const char *hdr)
178{
179        unsigned l;
180
181        AN(hh->b);
182        AN(hh->e);
183        AN(hdr);
184        l = hdr[0];
185        assert(l == strlen(hdr + 1));
186        assert(hdr[l] == ':');
187        hdr++;
188        return (!strncasecmp(hdr, hh->b, l));
189}
190
191/*--------------------------------------------------------------------*/
192
193static unsigned
194http_findhdr(const struct http *hp, unsigned l, const char *hdr)
195{
196        unsigned u;
197
198        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
199                AN(hp->hd[u].b);
200                AN(hp->hd[u].e);
201                if (hp->hd[u].e < hp->hd[u].b + l + 1)
202                        continue;
203                if (hp->hd[u].b[l] != ':')
204                        continue;
205                if (strncasecmp(hdr, hp->hd[u].b, l))
206                        continue;
207                return (u);
208        }
209        return (0);
210}
211
212int
213http_GetHdr(const struct http *hp, const char *hdr, char **ptr)
214{
215        unsigned u, l;
216        char *p;
217
218        l = hdr[0];
219        assert(l == strlen(hdr + 1));
220        assert(hdr[l] == ':');
221        hdr++;
222        u = http_findhdr(hp, l - 1, hdr);
223        if (u == 0) {
224                *ptr = NULL;
225                return (0);
226        }
227        p = hp->hd[u].b + l;
228        while (isspace(*p))
229                p++;
230        *ptr = p;
231        return (1);
232}
233
234/*--------------------------------------------------------------------*/
235
236int
237http_GetHdrField(const struct http *hp, const char *hdr, const char *field, char **ptr)
238{
239        char *h;
240        int fl;
241
242        if (!http_GetHdr(hp, hdr, &h))
243                return (0);
244        fl = strlen(field);
245        while (*h) {
246                if (isspace(*h)) {
247                        h++;
248                        continue;
249                }
250                if (*h == ',') {
251                        h++;
252                        continue;
253                }
254                if (memcmp(h, field, fl) ||
255                    isalpha(h[fl]) || h[fl] == '-') {
256                        while (*h && !(isspace(*h) || *h == ','))
257                                h++;
258                        continue;
259                }
260                if (h[fl] == '=')
261                        *ptr = &h[fl + 1];
262                else
263                        *ptr = NULL;
264                return (1);
265        }
266        return (0);
267}
268
269/*--------------------------------------------------------------------*/
270
271void
272http_DoConnection(struct sess *sp)
273{
274        struct http *hp = sp->http;
275        char *p, *q;
276        int i;
277        unsigned u;
278
279        if (!http_GetHdr(hp, H_Connection, &p)) {
280                if (strcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
281                        sp->doclose = "not HTTP/1.1";
282                return;
283        }
284        for (; *p; p++) {
285                if (isspace(*p))
286                        continue;
287                if (*p == ',')
288                        continue;
289                for (q = p + 1; *q; q++)
290                        if (*q == ',' || isspace(*q))
291                                break;
292                i = pdiff(p, q);
293                if (i == 5 && !strncasecmp(p, "close", i))
294                        sp->doclose = "Connection: close";
295                u = http_findhdr(hp, i, p);
296                if (u != 0)
297                        hp->hdf[u] |= HDF_FILTER;
298                if (!*q)
299                        break;
300                p = q;
301        }
302}
303
304/*--------------------------------------------------------------------*/
305
306int
307http_HdrIs(const struct http *hp, const char *hdr, const char *val)
308{
309        char *p;
310
311        if (!http_GetHdr(hp, hdr, &p))
312                return (0);
313        AN(p);
314        if (!strcasecmp(p, val))
315                return (1);
316        return (0);
317}
318
319/*--------------------------------------------------------------------*/
320
321int
322http_GetTail(struct http *hp, unsigned len, char **b, char **e)
323{
324
325        if (hp->pl_s >= hp->pl_e)
326                return (0);
327
328        if (len == 0)
329                len = pdiff(hp->pl_s, hp->pl_e);
330
331        if (hp->pl_s + len > hp->pl_e)
332                len = pdiff(hp->pl_s, hp->pl_e);
333        if (len == 0)
334                return (0);
335        *b = hp->pl_s;
336        *e = hp->pl_s + len;
337        hp->pl_s += len;
338        assert(hp->pl_s <= hp->pl_e);
339        return (1);
340}
341
342/*--------------------------------------------------------------------*/
343/* Read from fd, but soak up any tail first */
344
345int
346http_Read(struct http *hp, int fd, void *p, unsigned len)
347{
348        int i;
349        int u;
350        char *b = p;
351
352        u = 0;
353        if (hp->pl_s < hp->pl_e) {
354                u = pdiff(hp->pl_s, hp->pl_e);
355                if (u > len)
356                        u = len;
357                memcpy(b, hp->pl_s, u);
358                hp->pl_s += u;
359                b += u;
360                len -= u;
361        }
362        if (hp->pl_e == hp->pl_s)
363                hp->pl_s = hp->pl_e = NULL;
364        if (len > 0) {
365                i = read(fd, b, len);
366                if (i < 0)
367                        return (i);
368                u += i;
369        }
370        return (u);
371}
372
373/*--------------------------------------------------------------------*/
374
375int
376http_GetStatus(const struct http *hp)
377{
378
379        AN(hp->hd[HTTP_HDR_STATUS].b);
380        return (strtoul(hp->hd[HTTP_HDR_STATUS].b,
381            NULL /* XXX */, 10));
382}
383
384const char *
385http_GetProto(const struct http *hp)
386{
387        AN(hp->hd[HTTP_HDR_PROTO].b);
388        return (hp->hd[HTTP_HDR_PROTO].b);
389}
390
391const char *
392http_GetReq(const struct http *hp)
393{
394        AN(hp->hd[HTTP_HDR_REQ].b);
395        return (hp->hd[HTTP_HDR_REQ].b);
396}
397
398/*--------------------------------------------------------------------
399 * Dissect the headers of the HTTP protocol message.
400 * Detect conditionals (headers which start with '^[Ii][Ff]-')
401 */
402
403static int
404http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
405{
406        char *q, *r;
407
408        if (*p == '\r')
409                p++;
410
411        hp->nhd = HTTP_HDR_FIRST;
412        hp->conds = 0;
413        r = NULL;               /* For FlexeLint */
414        assert(p < hp->rx_e);   /* http_header_complete() guarantees this */
415        for (; p < hp->rx_e; p = r) {
416                /* XXX: handle continuation lines */
417                q = strchr(p, '\n');
418                assert(q != NULL);
419                r = q + 1;
420                if (q > p && q[-1] == '\r')
421                        q--;
422                *q = '\0';
423                if (p == q)
424                        break;
425
426                if ((p[0] == 'i' || p[0] == 'I') &&
427                    (p[1] == 'f' || p[1] == 'F') &&
428                    p[2] == '-')
429                        hp->conds = 1;
430
431                if (hp->nhd < HTTP_HDR_MAX) {
432                        hp->hdf[hp->nhd] = 0;
433                        hp->hd[hp->nhd].b = p;
434                        hp->hd[hp->nhd].e = q;
435                        WSLH(w, HTTP_T_Header, fd, hp, hp->nhd);
436                        hp->nhd++;
437                } else {
438                        VSL_stats->losthdr++;
439                        WSLR(w, SLT_LostHeader, fd, p, q);
440                }
441        }
442        return (0);
443}
444
445/*--------------------------------------------------------------------*/
446
447int
448http_DissectRequest(struct worker *w, struct http *hp, int fd)
449{
450        char *p;
451
452        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
453        /* Assert a NUL at rx_e */
454        assert(hp->rx_s < hp->rx_e);
455        hp->logtag = HTTP_Rx;
456
457        for (p = hp->rx_s ; isspace(*p); p++)
458                continue;
459
460        /* First, the request type (GET/HEAD etc) */
461        hp->hd[HTTP_HDR_REQ].b = p;
462        for (; isalpha(*p); p++)
463                ;
464        hp->hd[HTTP_HDR_REQ].e = p;
465        WSLH(w, HTTP_T_Request, fd, hp, HTTP_HDR_REQ);
466        *p++ = '\0';
467
468        /* Next find the URI */
469        while (isspace(*p) && *p != '\n')
470                p++;
471        if (*p == '\n') {
472                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
473                return (400);
474        }
475        hp->hd[HTTP_HDR_URL].b = p;
476        while (!isspace(*p))
477                p++;
478        hp->hd[HTTP_HDR_URL].e = p;
479        WSLH(w, HTTP_T_URL, fd, hp, HTTP_HDR_URL);
480        if (*p == '\n') {
481                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
482                return (400);
483        }
484        *p++ = '\0';
485
486        /* Finally, look for protocol */
487        while (isspace(*p) && *p != '\n')
488                p++;
489        if (*p == '\n') {
490                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
491                return (400);
492        }
493        hp->hd[HTTP_HDR_PROTO].b = p;
494        while (!isspace(*p))
495                p++;
496        hp->hd[HTTP_HDR_PROTO].e = p;
497        WSLH(w, HTTP_T_Protocol, fd, hp, HTTP_HDR_PROTO);
498        if (*p != '\n')
499                *p++ = '\0';
500        while (isspace(*p) && *p != '\n')
501                p++;
502        if (*p != '\n') {
503                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
504                return (400);
505        }
506        *p++ = '\0';
507
508        return (http_dissect_hdrs(w, hp, fd, p));
509}
510
511/*--------------------------------------------------------------------*/
512
513int
514http_DissectResponse(struct worker *w, struct http *hp, int fd)
515{
516        char *p, *q;
517
518        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
519        /* Assert a NUL at rx_e */
520        assert(hp->rx_s < hp->rx_e);
521        hp->logtag = HTTP_Rx;
522
523        for (p = hp->rx_s ; isspace(*p); p++)
524                continue;
525
526        if (memcmp(p, "HTTP/1.", 7)) {
527                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
528                return (400);
529        }
530        /* First, protocol */
531        hp->hd[HTTP_HDR_PROTO].b = p;
532        while (!isspace(*p))
533                p++;
534        hp->hd[HTTP_HDR_PROTO].e = p;
535        WSLH(w, HTTP_T_Protocol, fd, hp, HTTP_HDR_PROTO);
536        *p++ = '\0';
537
538        /* Next find the status */
539        while (isspace(*p))
540                p++;
541        hp->hd[HTTP_HDR_STATUS].b = p;
542        while (!isspace(*p))
543                p++;
544        hp->hd[HTTP_HDR_STATUS].e = p;
545        WSLH(w, HTTP_T_Status, fd, hp, HTTP_HDR_STATUS);
546        *p++ = '\0';
547
548        /* Next find the response */
549        while (isspace(*p))
550                p++;
551        hp->hd[HTTP_HDR_RESPONSE].b = p;
552        while (*p != '\n')
553                p++;
554        for (q = p; q > hp->hd[HTTP_HDR_RESPONSE].b &&
555            isspace(q[-1]); q--)
556                continue;
557        *q = '\0';
558        hp->hd[HTTP_HDR_RESPONSE].e = q;
559        WSLH(w, HTTP_T_Response, fd, hp, HTTP_HDR_RESPONSE);
560        p++;
561
562        return (http_dissect_hdrs(w, hp, fd, p));
563}
564
565/*--------------------------------------------------------------------
566 * Return nonzero if we have a complete HTTP request.
567 */
568
569static int
570http_header_complete(struct http *hp)
571{
572        char *p;
573
574        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
575        assert(*hp->rx_e == '\0');
576        /* Skip any leading white space */
577        for (p = hp->rx_s ; p < hp->rx_e && isspace(*p); p++)
578                continue;
579        if (p >= hp->rx_e) {
580                hp->rx_e = hp->rx_s;
581                return (0);
582        }
583        while (1) {
584                /* XXX: we could save location of all linebreaks for later */
585                p = strchr(p, '\n');
586                if (p == NULL)
587                        return (0);     /* XXX: Could cache p */
588                p++;
589                if (*p == '\r')
590                        p++;
591                if (*p == '\n')
592                        break;
593        }
594        p++;
595        WS_ReleaseP(hp->ws, hp->rx_e);
596        if (p != hp->rx_e) {
597                hp->pl_s = p;
598                hp->pl_e = hp->rx_e;
599                hp->rx_e = p;
600        }
601        /* XXX: Check this stuff... */
602        return (1);
603}
604
605/*--------------------------------------------------------------------*/
606
607void
608http_RecvPrep(struct http *hp)
609{
610        unsigned l;
611
612        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
613        WS_Assert(hp->ws);
614        WS_Reset(hp->ws);
615        WS_Reserve(hp->ws, 0);
616        hp->rx_s = hp->ws->f;
617        hp->rx_e = hp->rx_s;
618        if (hp->pl_s != NULL) {
619                assert(hp->pl_s < hp->pl_e);
620                l = pdiff(hp->pl_s, hp->pl_s);
621                memmove(hp->rx_s, hp->pl_s, l);
622                hp->rx_e = hp->rx_s + l;
623                hp->pl_s = hp->pl_e = NULL;
624        }
625        *hp->rx_e = '\0';
626}
627
628int
629http_RecvPrepAgain(struct http *hp)
630{
631        http_RecvPrep(hp);
632        if (hp->rx_s == hp->rx_e)
633                return (0);
634        return (http_header_complete(hp));
635}
636
637/*--------------------------------------------------------------------*/
638
639int
640http_RecvSome(int fd, struct http *hp)
641{
642        unsigned l;
643        int i;
644
645        l = pdiff(hp->rx_e, hp->ws->e) - 1;
646        l /= 2;         /* Don't fill all of workspace with read-ahead */
647        if (l <= 1) {
648                VSL(SLT_HttpError, fd, "Received too much");
649                VSLR(SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
650                hp->rx_s = hp->rx_e = NULL;
651                WS_Release(hp->ws, 0);
652                return (1);
653        }
654        errno = 0;
655        i = read(fd, hp->rx_e, l - 1);
656        if (i > 0) {
657                hp->rx_e += i;
658                *hp->rx_e = '\0';
659                if (http_header_complete(hp))
660                        return(0);
661                return (-1);
662        }
663
664        if (hp->rx_e != hp->rx_s) {
665                VSL(SLT_HttpError, fd,
666                    "Received (only) %d bytes, errno %d",
667                    hp->rx_e - hp->rx_s, errno);
668                VSLR(SLT_Debug, fd, hp->rx_s, hp->rx_e);
669        } else if (errno == 0)
670                VSL(SLT_HttpError, fd, "Received nothing");
671        else
672                VSL(SLT_HttpError, fd, "Received errno %d", errno);
673        hp->rx_s = hp->rx_e = NULL;
674        WS_Release(hp->ws, 0);
675        return(2);
676}
677
678/*--------------------------------------------------------------------*/
679
680int
681http_RecvHead(struct http *hp, int fd)
682{
683        int i;
684
685        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
686        http_RecvPrep(hp);
687        do
688                i = http_RecvSome(fd, hp);
689        while (i == -1);
690        return (i);
691}
692
693/*--------------------------------------------------------------------*/
694
695void
696http_SetH(struct http *to, unsigned n, const char *fm)
697{
698
699        assert(n < HTTP_HDR_MAX);
700        AN(fm);
701        to->hd[n].b = (void*)(uintptr_t)fm;
702        to->hd[n].e = (void*)(uintptr_t)strchr(fm, '\0');
703        to->hdf[n] = 0;
704}
705
706static void
707http_copyh(struct http *to, const struct http *fm, unsigned n)
708{
709
710        assert(n < HTTP_HDR_MAX);
711        AN(fm->hd[n].b);
712        to->hd[n].b = fm->hd[n].b;
713        to->hd[n].e = fm->hd[n].e;
714        to->hdf[n] = fm->hdf[n];
715}
716
717static void
718http_copyreq(struct http *to, const struct http *fm, int transparent)
719{
720
721        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
722        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
723        if (transparent)
724                http_copyh(to, fm, HTTP_HDR_REQ);
725        else
726                http_SetH(to, HTTP_HDR_REQ, "GET");
727        http_copyh(to, fm, HTTP_HDR_URL);
728        if (transparent)
729                http_copyh(to, fm, HTTP_HDR_PROTO);
730        else
731                http_SetH(to, HTTP_HDR_PROTO, "HTTP/1.1");
732}
733
734void
735http_CopyResp(struct http *to, const struct http *fm)
736{
737
738        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
739        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
740        if (params->client_http11)
741                http_SetH(to, HTTP_HDR_PROTO, "HTTP/1.1");
742        else
743                http_copyh(to, fm, HTTP_HDR_PROTO);
744        http_copyh(to, fm, HTTP_HDR_STATUS);
745        http_copyh(to, fm, HTTP_HDR_RESPONSE);
746}
747
748void
749http_SetResp(struct http *to, const char *proto, const char *status, const char *response)
750{
751
752        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
753        http_SetH(to, HTTP_HDR_PROTO, proto);
754        http_SetH(to, HTTP_HDR_STATUS, status);
755        http_SetH(to, HTTP_HDR_RESPONSE, response);
756}
757
758static void
759http_copyheader(struct worker *w, int fd, struct http *to, const struct http *fm, unsigned n)
760{
761
762        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
763        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
764        assert(n < HTTP_HDR_MAX);
765        AN(fm->hd[n].b);
766        if (to->nhd < HTTP_HDR_MAX) {
767                to->hd[to->nhd].b = fm->hd[n].b;
768                to->hd[to->nhd].e = fm->hd[n].e;
769                to->nhd++;
770        } else  {
771                VSL_stats->losthdr++;
772                WSLR(w, SLT_LostHeader, fd, fm->hd[n].b, fm->hd[n].e);
773        }
774}
775
776/*--------------------------------------------------------------------*/
777
778void
779http_FilterFields(struct worker *w, int fd, struct http *to, const struct http *fm, unsigned how)
780{
781        unsigned u;
782
783        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
784        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
785        to->nhd = HTTP_HDR_FIRST;
786        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
787                if (fm->hdf[u] & HDF_FILTER)
788                        continue;
789#define HTTPH(a, b, c, d, e, f, g) \
790                if (((e) & how) && http_IsHdr(&fm->hd[u], (b))) \
791                        continue;
792#include "http_headers.h"
793#undef HTTPH
794                http_copyheader(w, fd, to, fm, u);
795        }
796}
797
798/*--------------------------------------------------------------------*/
799
800void
801http_FilterHeader(struct sess *sp, unsigned how)
802{
803        struct bereq *bereq;
804        struct http *hp;
805        char *b;
806
807        bereq = VBE_new_bereq();
808        AN(bereq);
809        hp = bereq->http;
810        hp->logtag = HTTP_Tx;
811
812        http_copyreq(hp, sp->http,
813            (how == HTTPH_R_PIPE) || (how == HTTPH_R_PASS));
814        http_FilterFields(sp->wrk, sp->fd, hp, sp->http, how);
815        http_PrintfHeader(sp->wrk, sp->fd, hp, "X-Varnish: %u", sp->xid);
816        http_PrintfHeader(sp->wrk, sp->fd, hp,
817            "X-Forwarded-for: %s", sp->addr);
818
819        /* XXX: This really ought to go into the default VCL */
820        if (!http_GetHdr(hp, H_Host, &b)) {
821                http_PrintfHeader(sp->wrk, sp->fd, hp, "Host: %s",
822                    sp->backend->method->gethostname(sp->backend));
823        }
824        sp->bereq = bereq;
825}
826
827/*--------------------------------------------------------------------
828 * This function copies any header fields which reference foreign
829 * storage into our own WS.
830 */
831
832void
833http_CopyHome(struct worker *w, int fd, struct http *hp)
834{
835        unsigned u, l;
836        enum httptag htt;
837        char *p;
838
839        for (u = 0; u < hp->nhd; u++) {
840                if (hp->hd[u].b == NULL)
841                        continue;
842                switch (u) {
843                case HTTP_HDR_PROTO:
844                        htt = HTTP_T_Protocol;
845                        break;
846                case HTTP_HDR_STATUS:
847                        htt = HTTP_T_Status;
848                        break;
849                case HTTP_HDR_RESPONSE:
850                        htt = HTTP_T_Response;
851                        break;
852                default:
853                        htt = HTTP_T_Header;
854                        break;
855                }
856                if (hp->hd[u].b >= hp->ws->s && hp->hd[u].e <= hp->ws->e) {
857                        WSLH(w, htt, fd, hp, u);
858                        continue;
859                }
860                l = pdiff(hp->hd[u].b,  hp->hd[u].e);
861                p = WS_Alloc(hp->ws, l + 1);
862                if (p != NULL) {
863                        WSLH(w, htt, fd, hp, u);
864                        memcpy(p, hp->hd[u].b, l + 1);
865                        hp->hd[u].b = p;
866                        hp->hd[u].e = p + l;
867                } else {
868                        WSLR(w, SLT_LostHeader, fd, hp->hd[u].b, hp->hd[u].e);
869                        hp->hd[u].b = NULL;
870                        hp->hd[u].e = NULL;
871                }
872        }
873}
874
875/*--------------------------------------------------------------------*/
876
877void
878http_ClrHeader(struct http *to)
879{
880
881        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
882        /* XXX: don't to->f = to->v;  it would kill pipelining */
883        to->nhd = HTTP_HDR_FIRST;
884        memset(to->hd, 0, sizeof to->hd);
885}
886
887/*--------------------------------------------------------------------*/
888
889void
890http_SetHeader(struct worker *w, int fd, struct http *to, const char *hdr)
891{
892
893        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
894        if (to->nhd >= HTTP_HDR_MAX) {
895                VSL_stats->losthdr++;
896                WSL(w, SLT_LostHeader, fd, "%s", hdr);
897                return;
898        }
899        http_SetH(to, to->nhd++, hdr);
900}
901
902/*--------------------------------------------------------------------*/
903
904static void
905http_PutField(struct worker *w, int fd, struct http *to, int field, const char *string)
906{
907        char *p;
908        int l;
909
910        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
911        l = strlen(string);
912        p = WS_Alloc(to->ws, l + 1);
913        if (p == NULL) {
914                WSL(w, SLT_LostHeader, fd, "%s", string);
915                to->hd[field].b = NULL;
916                to->hd[field].e = NULL;
917        } else {
918                memcpy(p, string, l + 1);
919                to->hd[field].b = p;
920                to->hd[field].e = p + l;
921        }
922}
923
924void
925http_PutProtocol(struct worker *w, int fd, struct http *to, const char *protocol)
926{
927
928        http_PutField(w, fd, to, HTTP_HDR_PROTO, protocol);
929}
930
931void
932http_PutStatus(struct worker *w, int fd, struct http *to, int status)
933{
934        char stat[4];
935
936        assert(status >= 0 && status <= 999);
937        sprintf(stat, "%d", status);
938        http_PutField(w, fd, to, HTTP_HDR_STATUS, stat);
939}
940
941void
942http_PutResponse(struct worker *w, int fd, struct http *to, const char *response)
943{
944
945        http_PutField(w, fd, to, HTTP_HDR_RESPONSE, response);
946}
947
948void
949http_PrintfHeader(struct worker *w, int fd, struct http *to, const char *fmt, ...)
950{
951        va_list ap;
952        unsigned l, n;
953
954        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
955        l = WS_Reserve(to->ws, 0);
956        va_start(ap, fmt);
957        n = vsnprintf(to->ws->f, l, fmt, ap);
958        va_end(ap);
959        if (n + 1 >= l || to->nhd >= HTTP_HDR_MAX) {
960                VSL_stats->losthdr++;
961                WSL(w, SLT_LostHeader, fd, "%s", to->ws->f);
962                WS_Release(to->ws, 0);
963        } else {
964                to->hd[to->nhd].b = to->ws->f;
965                to->hd[to->nhd].e = to->ws->f + n;
966                WS_Release(to->ws, n + 1);
967                to->nhd++;
968        }
969}
970/*--------------------------------------------------------------------*/
971
972void
973http_Unset(struct http *hp, const char *hdr)
974{
975        unsigned u, v;
976
977        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
978                if (http_IsHdr(&hp->hd[u], hdr)) 
979                        continue;
980                if (v != u)
981                        memcpy(&hp->hd[v], &hp->hd[u], sizeof hp->hd[v]);
982                v++;
983        }
984        hp->nhd = v;
985}
986
987/*--------------------------------------------------------------------*/
988
989unsigned
990http_Write(struct worker *w, struct http *hp, int resp)
991{
992        unsigned u, l;
993
994        if (resp) {
995                AN(hp->hd[HTTP_HDR_STATUS].b);
996                l = WRK_WriteH(w, &hp->hd[HTTP_HDR_PROTO], " ");
997                WSLH(w, HTTP_T_Protocol, *w->wfd, hp, HTTP_HDR_PROTO);
998                l += WRK_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " ");
999                WSLH(w, HTTP_T_Status, *w->wfd, hp, HTTP_HDR_STATUS);
1000                l += WRK_WriteH(w, &hp->hd[HTTP_HDR_RESPONSE], "\r\n");
1001                WSLH(w, HTTP_T_Response, *w->wfd, hp, HTTP_HDR_RESPONSE);
1002        } else {
1003                AN(hp->hd[HTTP_HDR_URL].b);
1004                l = WRK_WriteH(w, &hp->hd[HTTP_HDR_REQ], " ");
1005                WSLH(w, HTTP_T_Request, *w->wfd, hp, HTTP_HDR_REQ);
1006                l += WRK_WriteH(w, &hp->hd[HTTP_HDR_URL], " ");
1007                WSLH(w, HTTP_T_URL, *w->wfd, hp, HTTP_HDR_URL);
1008                l += WRK_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
1009                WSLH(w, HTTP_T_Protocol, *w->wfd, hp, HTTP_HDR_PROTO);
1010        }
1011        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1012                AN(hp->hd[u].b);
1013                AN(hp->hd[u].e);
1014                l += WRK_WriteH(w, &hp->hd[u], "\r\n");
1015                WSLH(w, HTTP_T_Header, *w->wfd, hp, u);
1016        }
1017        l += WRK_Write(w, "\r\n", -1);
1018        return (l);
1019}
1020
1021/*--------------------------------------------------------------------*/
1022
1023void
1024HTTP_Init(void)
1025{
1026#define HTTPH(a, b, c, d, e, f, g) b[0] = (char)strlen(b + 1);
1027#include "http_headers.h"
1028#undef HTTPH
1029}
Note: See TracBrowser for help on using the repository browser.