source: bin/varnishd/cache_http.c @ 3b5cb3

Revision 3b5cb3, 18.5 KB checked in by Tollef Fog Heen <tfheen@…>, 5 years ago (diff)

Merge r3530: More asserts

Be much more BOFH about bereq, more asserts, free them where they
obviously should be freed.

This could fix 421 or make it much worse, but give us more info.

git-svn-id:  http://www.varnish-cache.org/svn/branches/2.0@3717 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2008 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 "config.h"
35
36#include <errno.h>
37#include <unistd.h>
38#include <stdarg.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <strings.h>
43
44#include "shmlog.h"
45#include "vct.h"
46#include "cache.h"
47
48#ifndef HAVE_STRLCPY
49#include <compat/strlcpy.h>
50#endif
51
52#define HTTPH(a, b, c, d, e, f, g) char b[] = "*" a ":";
53#include "http_headers.h"
54#undef HTTPH
55
56/*lint -save -e773 not () */
57#define LOGMTX2(ax, bx, cx)     [bx] = SLT_##ax##cx
58
59#define LOGMTX1(ax) {                                   \
60        LOGMTX2(ax, HTTP_HDR_REQ,       Request),       \
61        LOGMTX2(ax, HTTP_HDR_RESPONSE,  Response),      \
62        LOGMTX2(ax, HTTP_HDR_STATUS,    Status),        \
63        LOGMTX2(ax, HTTP_HDR_URL,       URL),           \
64        LOGMTX2(ax, HTTP_HDR_PROTO,     Protocol),      \
65        LOGMTX2(ax, HTTP_HDR_FIRST,     Header),        \
66        }
67
68static const enum shmlogtag logmtx[][HTTP_HDR_FIRST + 1] = {
69        [HTTP_Rx] = LOGMTX1(Rx),
70        [HTTP_Tx] = LOGMTX1(Tx),
71        [HTTP_Obj] = LOGMTX1(Obj)
72};
73/*lint -restore */
74
75static enum shmlogtag
76http2shmlog(const struct http *hp, int t)
77{
78
79        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
80        if (t > HTTP_HDR_FIRST)
81                t = HTTP_HDR_FIRST;
82        assert(hp->logtag >= HTTP_Rx && hp->logtag <= HTTP_Obj); /*lint !e685*/
83        assert(t >= HTTP_HDR_REQ && t <= HTTP_HDR_FIRST);
84        return (logmtx[hp->logtag][t]);
85}
86
87static void
88WSLH(struct worker *w, int fd, const struct http *hp, unsigned hdr)
89{
90
91        WSLR(w, http2shmlog(hp, hdr), fd, hp->hd[hdr]);
92}
93
94/*--------------------------------------------------------------------*/
95/* List of canonical HTTP response code names from RFC2616 */
96
97static struct http_msg {
98        unsigned        nbr;
99        const char      *txt;
100} http_msg[] = {
101#define HTTP_RESP(n, t) { n, t},
102#include "http_response.h"
103        { 0, NULL }
104};
105
106const char *
107http_StatusMessage(unsigned status)
108{
109        struct http_msg *mp;
110
111        assert(status >= 100 && status <= 999);
112        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
113                if (mp->nbr == status)
114                        return (mp->txt);
115        return ("Unknown Error");
116}
117
118/*--------------------------------------------------------------------*/
119
120void
121http_Setup(struct http *hp, struct ws *ws)
122{
123
124        memset(hp, 0, sizeof *hp);
125        hp->magic = HTTP_MAGIC;
126        hp->ws = ws;
127        hp->nhd = HTTP_HDR_FIRST;
128}
129
130/*--------------------------------------------------------------------*/
131
132
133static int
134http_IsHdr(const txt *hh, const char *hdr)
135{
136        unsigned l;
137
138        Tcheck(*hh);
139        AN(hdr);
140        l = hdr[0];
141        assert(l == strlen(hdr + 1));
142        assert(hdr[l] == ':');
143        hdr++;
144        return (!strncasecmp(hdr, hh->b, l));
145}
146
147/*--------------------------------------------------------------------*/
148
149static unsigned
150http_findhdr(const struct http *hp, unsigned l, const char *hdr)
151{
152        unsigned u;
153
154        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
155                Tcheck(hp->hd[u]);
156                if (hp->hd[u].e < hp->hd[u].b + l + 1)
157                        continue;
158                if (hp->hd[u].b[l] != ':')
159                        continue;
160                if (strncasecmp(hdr, hp->hd[u].b, l))
161                        continue;
162                return (u);
163        }
164        return (0);
165}
166
167int
168http_GetHdr(const struct http *hp, const char *hdr, char **ptr)
169{
170        unsigned u, l;
171        char *p;
172
173        l = hdr[0];
174        diagnostic(l == strlen(hdr + 1));
175        assert(hdr[l] == ':');
176        hdr++;
177        u = http_findhdr(hp, l - 1, hdr);
178        if (u == 0) {
179                if (ptr != NULL)
180                        *ptr = NULL;
181                return (0);
182        }
183        if (ptr != NULL) {
184                p = hp->hd[u].b + l;
185                while (vct_issp(*p))
186                        p++;
187                *ptr = p;
188        }
189        return (1);
190}
191
192/*--------------------------------------------------------------------
193 * Find a given headerfield, and if present and wanted, the beginning
194 * of its value.
195 */
196
197int
198http_GetHdrField(const struct http *hp, const char *hdr,
199    const char *field, char **ptr)
200{
201        char *h, *e;
202        unsigned fl;
203
204        if (ptr != NULL)
205                *ptr = NULL;
206        if (!http_GetHdr(hp, hdr, &h))
207                return (0);
208        AN(h);
209        e = strchr(h, '\0');
210        fl = strlen(field);
211        while (h + fl <= e) {
212                /* Skip leading separators */
213                if (vct_issepctl(*h)) {
214                        h++;
215                        continue;
216                }
217                /* Check for substrings before memcmp() */
218                if ((h + fl == e || vct_issepctl(h[fl])) &&
219                    !memcmp(h, field, fl)) {
220                        /* got it */
221                        h += fl;
222                        if (ptr != NULL) {
223                                /* Skip whitespace, looking for '=' */
224                                while (*h && vct_issp(*h))
225                                        h++;
226                                if (*h == '=') {
227                                        h++;
228                                        while (*h && vct_issp(*h))
229                                                h++;
230                                        *ptr = h;
231                                }
232                        }
233                        return (1);
234                }
235                /* Skip token */
236                while (*h && !vct_issepctl(*h))
237                        h++;
238        }
239        return (0);
240}
241
242/*--------------------------------------------------------------------
243 * XXX: redo with http_GetHdrField() ?
244 */
245
246const char *
247http_DoConnection(struct http *hp)
248{
249        char *p, *q;
250        const char *ret;
251        unsigned u;
252
253        if (!http_GetHdr(hp, H_Connection, &p)) {
254                if (hp->protover < 1.1)
255                        return ("not HTTP/1.1");
256                return (NULL);
257        }
258        ret = NULL;
259        for (; *p; p++) {
260                if (vct_issp(*p))
261                        continue;
262                if (*p == ',')
263                        continue;
264                for (q = p + 1; *q; q++)
265                        if (*q == ',' || vct_issp(*q))
266                                break;
267                u = pdiff(p, q);
268                if (u == 5 && !strncasecmp(p, "close", u))
269                        ret = "Connection: close";
270                u = http_findhdr(hp, u, p);
271                if (u != 0)
272                        hp->hdf[u] |= HDF_FILTER;
273                if (!*q)
274                        break;
275                p = q;
276        }
277        return (ret);
278}
279
280/*--------------------------------------------------------------------*/
281
282int
283http_HdrIs(const struct http *hp, const char *hdr, const char *val)
284{
285        char *p;
286
287        if (!http_GetHdr(hp, hdr, &p))
288                return (0);
289        AN(p);
290        if (!strcasecmp(p, val))
291                return (1);
292        return (0);
293}
294
295/*--------------------------------------------------------------------*/
296
297int
298http_GetStatus(const struct http *hp)
299{
300
301        Tcheck(hp->hd[HTTP_HDR_STATUS]);
302        return (hp->status);
303}
304
305const char *
306http_GetReq(const struct http *hp)
307{
308
309        Tcheck(hp->hd[HTTP_HDR_REQ]);
310        return (hp->hd[HTTP_HDR_REQ].b);
311}
312
313/*--------------------------------------------------------------------
314 * Dissect the headers of the HTTP protocol message.
315 * Detect conditionals (headers which start with '^[Ii][Ff]-')
316 */
317
318static int
319http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p, txt t)
320{
321        char *q, *r;
322
323        if (*p == '\r')
324                p++;
325
326        hp->nhd = HTTP_HDR_FIRST;
327        hp->conds = 0;
328        r = NULL;               /* For FlexeLint */
329        for (; p < t.e; p = r) {
330                /* XXX: handle continuation lines */
331                q = strchr(p, '\n');
332                assert(q != NULL);
333                r = q + 1;
334                if (q > p && q[-1] == '\r')
335                        q--;
336                if (p == q)
337                        break;
338
339                if ((p[0] == 'i' || p[0] == 'I') &&
340                    (p[1] == 'f' || p[1] == 'F') &&
341                    p[2] == '-')
342                        hp->conds = 1;
343
344                while (q > p && vct_issp(q[-1]))
345                        q--;
346                *q = '\0';
347
348                if (hp->nhd < HTTP_HDR_MAX) {
349                        hp->hdf[hp->nhd] = 0;
350                        hp->hd[hp->nhd].b = p;
351                        hp->hd[hp->nhd].e = q;
352                        WSLH(w, fd, hp, hp->nhd);
353                        hp->nhd++;
354                } else {
355                        VSL_stats->losthdr++;
356                        WSL(w, SLT_LostHeader, fd, "%.*s", q - p, p);
357                        return (400);
358                }
359        }
360        return (0);
361}
362
363/*--------------------------------------------------------------------
364 * Deal with first line of HTTP protocol message.
365 */
366
367static int
368http_splitline(struct worker *w, int fd, struct http *hp,
369    const struct http_conn *htc, int h1, int h2, int h3)
370{
371        char *p;
372
373        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
374        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
375
376        /* XXX: Assert a NUL at rx.e ? */
377        Tcheck(htc->rxbuf);
378
379        /* Skip leading LWS */
380        for (p = htc->rxbuf.b ; vct_islws(*p); p++)
381                continue;
382
383        /* First field cannot contain SP, CRLF or CTL */
384        hp->hd[h1].b = p;
385        for (; !vct_issp(*p); p++)
386                if (vct_isctl(*p))
387                        return (400);
388        hp->hd[h1].e = p;
389
390        /* Skip SP */
391        for (; vct_issp(*p); p++)
392                ;
393
394        /* Second field cannot contain LWS */
395        hp->hd[h2].b = p;
396        for (; !vct_islws(*p); p++)
397                ;
398        hp->hd[h2].e = p;
399
400        if (!Tlen(hp->hd[h2]))
401                return (400);
402
403        /* Skip SP */
404        for (; vct_issp(*p); p++)
405                ;
406
407        /* Third field is optional and cannot contain CTL */
408        if (!vct_iscrlf(*p)) {
409                hp->hd[h3].b = p;
410                for (; !vct_iscrlf(*p); p++)
411                        if (vct_isctl(*p))
412                                return (400);
413                hp->hd[h3].e = p;
414        } else {
415                hp->hd[h3].b = p;
416                hp->hd[h3].e = p;
417        }
418
419        /* Skip CRLF */
420        p += vct_skipcrlf(p);
421
422        *hp->hd[h1].e = '\0';
423        WSLH(w, fd, hp, h1);
424
425        *hp->hd[h2].e = '\0';
426        WSLH(w, fd, hp, h2);
427
428        if (hp->hd[h3].e != NULL) {
429                *hp->hd[h3].e = '\0';
430                WSLH(w, fd, hp, h3);
431        }
432
433        return (http_dissect_hdrs(w, hp, fd, p, htc->rxbuf));
434}
435
436/*--------------------------------------------------------------------*/
437
438static void
439http_ProtoVer(struct http *hp)
440{
441
442        if (!strcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.0"))
443                hp->protover = 1.0;
444        else if (!strcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
445                hp->protover = 1.1;
446        else
447                hp->protover = 0.9;
448}
449
450
451/*--------------------------------------------------------------------*/
452
453int
454http_DissectRequest(struct sess *sp)
455{
456        struct http_conn *htc;
457        struct http *hp;
458        int i;
459
460        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
461        htc = sp->htc;
462        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
463        hp = sp->http;
464        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
465
466        hp->logtag = HTTP_Rx;
467
468        i = http_splitline(sp->wrk, sp->fd, hp, htc,
469            HTTP_HDR_REQ, HTTP_HDR_URL, HTTP_HDR_PROTO);
470        if (i != 0) {
471                WSPR(sp, SLT_HttpGarbage, htc->rxbuf);
472                return (i);
473        }
474        http_ProtoVer(hp);
475        return (i);
476}
477
478/*--------------------------------------------------------------------*/
479
480int
481http_DissectResponse(struct worker *w, const struct http_conn *htc,
482    struct http *hp)
483{
484        int i;
485
486        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
487        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
488        hp->logtag = HTTP_Rx;
489
490        i = http_splitline(w, htc->fd, hp, htc,
491            HTTP_HDR_PROTO, HTTP_HDR_STATUS, HTTP_HDR_RESPONSE);
492
493        if (i != 0 || memcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.", 7))
494                WSLR(w, SLT_HttpGarbage, htc->fd, htc->rxbuf);
495        if (i != 0) {
496                if (hp->status == 0)
497                        hp->status = i;
498        } else {
499                hp->status =
500                    strtoul(hp->hd[HTTP_HDR_STATUS].b, NULL /* XXX */, 10);
501        }
502        http_ProtoVer(hp);
503        if (hp->hd[HTTP_HDR_RESPONSE].b == NULL ||
504            !Tlen(hp->hd[HTTP_HDR_RESPONSE])) {
505                /* Backend didn't send a response string, use the standard */
506                hp->hd[HTTP_HDR_RESPONSE].b =
507                    TRUST_ME(http_StatusMessage(hp->status));
508                hp->hd[HTTP_HDR_RESPONSE].e =
509                    strchr(hp->hd[HTTP_HDR_RESPONSE].b, '\0');
510        }
511        return (i);
512}
513
514/*--------------------------------------------------------------------*/
515
516void
517http_SetH(struct http *to, unsigned n, const char *fm)
518{
519
520        assert(n < HTTP_HDR_MAX);
521        AN(fm);
522        to->hd[n].b = TRUST_ME(fm);
523        to->hd[n].e = strchr(to->hd[n].b, '\0');
524        to->hdf[n] = 0;
525}
526
527static void
528http_copyh(struct http *to, const struct http *fm, unsigned n)
529{
530
531        assert(n < HTTP_HDR_MAX);
532        Tcheck(fm->hd[n]);
533        to->hd[n] = fm->hd[n];
534        to->hdf[n] = fm->hdf[n];
535}
536
537static void
538http_copyreq(struct http *to, const struct http *fm, int how)
539{
540
541        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
542        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
543
544        if ((how == HTTPH_R_PIPE) || (how == HTTPH_R_PASS)) {
545                http_copyh(to, fm, HTTP_HDR_REQ);
546                http_copyh(to, fm, HTTP_HDR_PROTO);
547        } else {
548                http_SetH(to, HTTP_HDR_REQ, "GET");
549                http_SetH(to, HTTP_HDR_PROTO, "HTTP/1.1");
550        }
551        http_copyh(to, fm, HTTP_HDR_URL);
552}
553
554void
555http_ForceGet(struct http *to)
556{
557        if (strcmp(http_GetReq(to), "GET"))
558                http_SetH(to, HTTP_HDR_REQ, "GET");
559}
560
561void
562http_CopyResp(struct http *to, const struct http *fm)
563{
564
565        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
566        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
567        if (params->client_http11)
568                http_SetH(to, HTTP_HDR_PROTO, "HTTP/1.1");
569        else
570                http_copyh(to, fm, HTTP_HDR_PROTO);
571        http_copyh(to, fm, HTTP_HDR_STATUS);
572        http_copyh(to, fm, HTTP_HDR_RESPONSE);
573}
574
575void
576http_SetResp(struct http *to, const char *proto, const char *status,
577    const char *response)
578{
579
580        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
581        http_SetH(to, HTTP_HDR_PROTO, proto);
582        http_SetH(to, HTTP_HDR_STATUS, status);
583        http_SetH(to, HTTP_HDR_RESPONSE, response);
584}
585
586static void
587http_copyheader(struct worker *w, int fd, struct http *to,
588    const struct http *fm, unsigned n)
589{
590
591        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
592        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
593        assert(n < HTTP_HDR_MAX);
594        Tcheck(fm->hd[n]);
595        if (to->nhd < HTTP_HDR_MAX) {
596                to->hd[to->nhd] = fm->hd[n];
597                to->hdf[to->nhd] = 0;
598                to->nhd++;
599        } else  {
600                VSL_stats->losthdr++;
601                WSLR(w, SLT_LostHeader, fd, fm->hd[n]);
602        }
603}
604
605/*--------------------------------------------------------------------*/
606
607void
608http_FilterFields(struct worker *w, int fd, struct http *to,
609    const struct http *fm, unsigned how)
610{
611        unsigned u;
612
613        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
614        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
615        to->nhd = HTTP_HDR_FIRST;
616        to->status = fm->status;
617        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
618                if (fm->hdf[u] & HDF_FILTER)
619                        continue;
620#define HTTPH(a, b, c, d, e, f, g) \
621                if (((e) & how) && http_IsHdr(&fm->hd[u], (b))) \
622                        continue;
623#include "http_headers.h"
624#undef HTTPH
625                http_copyheader(w, fd, to, fm, u);
626        }
627}
628
629/*--------------------------------------------------------------------*/
630
631void
632http_FilterHeader(struct sess *sp, unsigned how)
633{
634        struct bereq *bereq;
635        struct http *hp;
636
637        AZ(sp->bereq);
638        bereq = VBE_new_bereq();
639        AN(bereq);
640        hp = bereq->http;
641        hp->logtag = HTTP_Tx;
642
643        http_copyreq(hp, sp->http, how);
644        http_FilterFields(sp->wrk, sp->fd, hp, sp->http, how);
645        http_PrintfHeader(sp->wrk, sp->fd, hp, "X-Varnish: %u", sp->xid);
646        http_PrintfHeader(sp->wrk, sp->fd, hp,
647            "X-Forwarded-For: %s", sp->addr);
648
649        sp->bereq = bereq;
650}
651
652/*--------------------------------------------------------------------
653 * This function copies any header fields which reference foreign
654 * storage into our own WS.
655 */
656
657void
658http_CopyHome(struct worker *w, int fd, struct http *hp)
659{
660        unsigned u, l;
661        char *p;
662
663        for (u = 0; u < hp->nhd; u++) {
664                if (hp->hd[u].b == NULL)
665                        continue;
666                if (hp->hd[u].b >= hp->ws->s && hp->hd[u].e <= hp->ws->e) {
667                        WSLH(w, fd, hp, u);
668                        continue;
669                }
670                l = Tlen(hp->hd[u]);
671                p = WS_Alloc(hp->ws, l + 1);
672                if (p != NULL) {
673                        WSLH(w, fd, hp, u);
674                        memcpy(p, hp->hd[u].b, l + 1);
675                        hp->hd[u].b = p;
676                        hp->hd[u].e = p + l;
677                } else {
678                        WSLR(w, SLT_LostHeader, fd, hp->hd[u]);
679                        hp->hd[u].b = NULL;
680                        hp->hd[u].e = NULL;
681                }
682        }
683}
684
685/*--------------------------------------------------------------------*/
686
687void
688http_ClrHeader(struct http *to)
689{
690
691        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
692        /* XXX: don't to->f = to->v;  it would kill pipelining */
693        to->nhd = HTTP_HDR_FIRST;
694        memset(to->hd, 0, sizeof to->hd);
695}
696
697/*--------------------------------------------------------------------*/
698
699void
700http_SetHeader(struct worker *w, int fd, struct http *to, const char *hdr)
701{
702
703        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
704        if (to->nhd >= HTTP_HDR_MAX) {
705                VSL_stats->losthdr++;
706                WSL(w, SLT_LostHeader, fd, "%s", hdr);
707                return;
708        }
709        http_SetH(to, to->nhd++, hdr);
710}
711
712/*--------------------------------------------------------------------*/
713
714static void
715http_PutField(struct worker *w, int fd, struct http *to, int field,
716    const char *string)
717{
718        char *p;
719        unsigned l;
720
721        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
722        l = strlen(string);
723        p = WS_Alloc(to->ws, l + 1);
724        if (p == NULL) {
725                WSL(w, SLT_LostHeader, fd, "%s", string);
726                to->hd[field].b = NULL;
727                to->hd[field].e = NULL;
728                to->hdf[field] = 0;
729        } else {
730                memcpy(p, string, l + 1);
731                to->hd[field].b = p;
732                to->hd[field].e = p + l;
733                to->hdf[field] = 0;
734        }
735}
736
737void
738http_PutProtocol(struct worker *w, int fd, struct http *to,
739    const char *protocol)
740{
741
742        http_PutField(w, fd, to, HTTP_HDR_PROTO, protocol);
743}
744
745void
746http_PutStatus(struct worker *w, int fd, struct http *to, int status)
747{
748        char stat[4];
749
750        assert(status >= 0 && status <= 999);
751        sprintf(stat, "%d", status);
752        http_PutField(w, fd, to, HTTP_HDR_STATUS, stat);
753        to->status = status;
754}
755
756void
757http_PutResponse(struct worker *w, int fd, struct http *to,
758    const char *response)
759{
760
761        http_PutField(w, fd, to, HTTP_HDR_RESPONSE, response);
762}
763
764void
765http_PrintfHeader(struct worker *w, int fd, struct http *to,
766    const char *fmt, ...)
767{
768        va_list ap;
769        unsigned l, n;
770
771        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
772        l = WS_Reserve(to->ws, 0);
773        va_start(ap, fmt);
774        n = vsnprintf(to->ws->f, l, fmt, ap);
775        va_end(ap);
776        if (n + 1 >= l || to->nhd >= HTTP_HDR_MAX) {
777                VSL_stats->losthdr++;
778                WSL(w, SLT_LostHeader, fd, "%s", to->ws->f);
779                WS_Release(to->ws, 0);
780        } else {
781                to->hd[to->nhd].b = to->ws->f;
782                to->hd[to->nhd].e = to->ws->f + n;
783                to->hdf[to->nhd] = 0;
784                WS_Release(to->ws, n + 1);
785                to->nhd++;
786        }
787}
788/*--------------------------------------------------------------------*/
789
790void
791http_Unset(struct http *hp, const char *hdr)
792{
793        unsigned u, v;
794
795        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
796                if (http_IsHdr(&hp->hd[u], hdr))
797                        continue;
798                if (v != u) {
799                        memcpy(&hp->hd[v], &hp->hd[u], sizeof hp->hd[v]);
800                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof hp->hdf[v]);
801                }
802                v++;
803        }
804        hp->nhd = v;
805}
806
807/*--------------------------------------------------------------------*/
808
809unsigned
810http_Write(struct worker *w, const struct http *hp, int resp)
811{
812        unsigned u, l;
813
814        if (resp) {
815                AN(hp->hd[HTTP_HDR_STATUS].b);
816                l = WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], " ");
817                WSLH(w, *w->wfd, hp, HTTP_HDR_PROTO);
818                l += WRW_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " ");
819                WSLH(w, *w->wfd, hp, HTTP_HDR_STATUS);
820                l += WRW_WriteH(w, &hp->hd[HTTP_HDR_RESPONSE], "\r\n");
821                WSLH(w, *w->wfd, hp, HTTP_HDR_RESPONSE);
822        } else {
823                AN(hp->hd[HTTP_HDR_URL].b);
824                l = WRW_WriteH(w, &hp->hd[HTTP_HDR_REQ], " ");
825                WSLH(w, *w->wfd, hp, HTTP_HDR_REQ);
826                l += WRW_WriteH(w, &hp->hd[HTTP_HDR_URL], " ");
827                WSLH(w, *w->wfd, hp, HTTP_HDR_URL);
828                l += WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
829                WSLH(w, *w->wfd, hp, HTTP_HDR_PROTO);
830        }
831        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
832                AN(hp->hd[u].b);
833                AN(hp->hd[u].e);
834                l += WRW_WriteH(w, &hp->hd[u], "\r\n");
835                WSLH(w, *w->wfd, hp, u);
836        }
837        l += WRW_Write(w, "\r\n", -1);
838        return (l);
839}
840
841/*--------------------------------------------------------------------*/
842
843void
844HTTP_Init(void)
845{
846
847#define HTTPH(a, b, c, d, e, f, g) b[0] = (char)strlen(b + 1);
848#include "http_headers.h"
849#undef HTTPH
850}
Note: See TracBrowser for help on using the repository browser.