Commit fb973a67 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Get a fair bit further in parsing HTTP stuff.



git-svn-id: http://www.varnish-cache.org/svn/trunk@2686 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 418b637a
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
server s1 -listen :9080 -repeat 2 { server s1 -listen :9080 -repeat 2 {
rxreq rxreq
expect req.url == "/" expect req.url == "/"
txresp -body "0123456789" txresp -hdr "Foobar: barf" -body "0123456789"
} }
server s1 -start server s1 -start
......
...@@ -35,12 +35,53 @@ ...@@ -35,12 +35,53 @@
#include <err.h> #include <err.h>
#include "libvarnish.h" #include "libvarnish.h"
#include "vsb.h"
#include "vtc.h" #include "vtc.h"
#define MAX_FILESIZE (1024 * 1024) #define MAX_FILESIZE (1024 * 1024)
#define MAX_TOKENS 20 #define MAX_TOKENS 20
/**********************************************************************
* Dump a string
*/
void
vct_dump(const char *ident, const char *pfx, const char *str)
{
int nl = 1;
struct vsb *vsb;
if (pfx == NULL)
pfx = "";
vsb = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND);
if (str == NULL)
vsb_printf(vsb, "#### %-4s %s(null)\n", ident, pfx);
for(; *str; str++) {
if (nl) {
vsb_printf(vsb, "#### %-4s %s| ", ident, pfx);
nl = 0;
}
if (*str == '\r')
vsb_printf(vsb, "\\r");
else if (*str == '\t')
vsb_printf(vsb, "\\t");
else if (*str == '\n') {
vsb_printf(vsb, "\\n\n");
nl = 1;
} else if (*str < 0x20 || *str > 0x7e)
vsb_printf(vsb, "\\x%02x", *str);
else
vsb_printf(vsb, "%c", *str);
}
if (!nl)
vsb_printf(vsb, "\n");
vsb_finish(vsb);
AZ(vsb_overflowed(vsb));
fputs(vsb_data(vsb), stdout);
vsb_delete(vsb);
}
/********************************************************************** /**********************************************************************
* Read a file into memory * Read a file into memory
*/ */
......
...@@ -42,4 +42,6 @@ void cmd_vcl(char **av, void *priv); ...@@ -42,4 +42,6 @@ void cmd_vcl(char **av, void *priv);
void cmd_stats(char **av, void *priv); void cmd_stats(char **av, void *priv);
void cmd_varnish(char **av, void *priv); void cmd_varnish(char **av, void *priv);
void http_process(const char *spec, int sock, int client); void http_process(const char *ident, const char *spec, int sock, int client);
void vct_dump(const char *ident, const char *pfx, const char *str);
...@@ -76,19 +76,19 @@ client_thread(void *priv) ...@@ -76,19 +76,19 @@ client_thread(void *priv)
CAST_OBJ_NOTNULL(c, priv, CLIENT_MAGIC); CAST_OBJ_NOTNULL(c, priv, CLIENT_MAGIC);
assert(c->naddr > 0); assert(c->naddr > 0);
printf("### Client %s started\n", c->name); printf("## %-4s started\n", c->name);
printf("#### Client %s connect to %s\n", c->name, c->connect); printf("### %-4s connect to %s\n", c->name, c->connect);
for (i = 0; i < c->naddr; i++) { for (i = 0; i < c->naddr; i++) {
fd = VSS_connect(c->vss_addr[i]); fd = VSS_connect(c->vss_addr[i]);
if (fd >= 0) if (fd >= 0)
break; break;
} }
assert(fd >= 0); assert(fd >= 0);
printf("#### Client %s connected to %s fd is %d\n", printf("### %-4s connected to %s fd is %d\n",
c->name, c->connect, fd); c->name, c->connect, fd);
http_process(c->spec, fd, 1); http_process(c->name, c->spec, fd, 1);
AZ(close(fd)); AZ(close(fd));
printf("### Client %s ending\n", c->name); printf("## %-4s ending\n", c->name);
return (NULL); return (NULL);
} }
...@@ -133,7 +133,7 @@ client_wait(struct client *c) ...@@ -133,7 +133,7 @@ client_wait(struct client *c)
void *res; void *res;
CHECK_OBJ_NOTNULL(c, CLIENT_MAGIC); CHECK_OBJ_NOTNULL(c, CLIENT_MAGIC);
printf("Waiting for client %s\n", c->name); printf("## %-4s Waiting for client\n", c->name);
AZ(pthread_join(c->tp, &res)); AZ(pthread_join(c->tp, &res));
if (res != NULL) { if (res != NULL) {
fprintf(stderr, "Server %s returned \"%s\"\n", fprintf(stderr, "Server %s returned \"%s\"\n",
......
...@@ -32,13 +32,16 @@ ...@@ -32,13 +32,16 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <ctype.h>
#include "libvarnish.h" #include "libvarnish.h"
#include "vct.h"
#include "miniobj.h" #include "miniobj.h"
#include "vsb.h" #include "vsb.h"
#include "vtc.h" #include "vtc.h"
#define MAX_HDR 50
struct http { struct http {
unsigned magic; unsigned magic;
...@@ -46,14 +49,113 @@ struct http { ...@@ -46,14 +49,113 @@ struct http {
int fd; int fd;
int client; int client;
int timeout; int timeout;
const char *ident;
int nrxbuf; int nrxbuf;
char *rxbuf; char *rxbuf;
char *req; char *req[MAX_HDR];
char *resp; char *resp[MAX_HDR];
}; };
/**********************************************************************
* Expect
*/
static void
cmd_http_expect(char **av, void *priv)
{
struct http *hp;
CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
assert(!strcmp(av[0], "expect"));
av++;
for(; *av != NULL; av++) {
fprintf(stderr, "Unknown http expect spec: %s\n", *av);
// exit (1);
}
}
/**********************************************************************
* Split a HTTP protocol header
*/
static void
http_splitheader(struct http *hp, int req)
{
char *p, *q, **hh;
int n;
char buf[20];
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
if (req) {
memset(hp->req, 0, sizeof hp->req);
hh = hp->req;
} else {
memset(hp->resp, 0, sizeof hp->resp);
hh = hp->resp;
}
n = 0;
p = hp->rxbuf;
/* REQ/PROTO */
while (vct_islws(*p))
p++;
hh[n++] = p;
while (!vct_islws(*p))
p++;
assert(!vct_iscrlf(*p));
*p++ = '\0';
/* URL/STATUS */
while (vct_issp(*p)) /* XXX: H space only */
p++;
assert(!vct_iscrlf(*p));
hh[n++] = p;
while (!vct_islws(*p))
p++;
if (vct_iscrlf(*p)) {
hh[n++] = NULL;
q = p;
p += vct_skipcrlf(p);
*q = '\0';
} else {
*p++ = '\0';
/* PROTO/MSG */
while (vct_issp(*p)) /* XXX: H space only */
p++;
hh[n++] = p;
while (!vct_iscrlf(*p))
p++;
q = p;
p += vct_skipcrlf(p);
*q = '\0';
}
assert(n == 3);
while (*p != '\0') {
assert(n < MAX_HDR);
if (vct_iscrlf(*p))
break;
hh[n++] = p++;
while (*p != '\0' && !vct_iscrlf(*p))
p++;
q = p;
p += vct_skipcrlf(p);
*q = '\0';
}
p += vct_skipcrlf(p);
assert(*p == '\0');
for (n = 0; n < 3 || hh[n] != NULL; n++) {
sprintf(buf, "http[%2d] ", n);
vct_dump(hp->ident, buf, hh[n]);
}
}
/********************************************************************** /**********************************************************************
* Receive a HTTP protocol header * Receive a HTTP protocol header
*/ */
...@@ -94,7 +196,7 @@ http_rxhdr(struct http *hp) ...@@ -94,7 +196,7 @@ http_rxhdr(struct http *hp)
if (i == 2) if (i == 2)
break; break;
} }
printf("<<<%s>>>\n", hp->rxbuf); vct_dump(hp->ident, NULL, hp->rxbuf);
} }
...@@ -116,8 +218,9 @@ cmd_http_rxresp(char **av, void *priv) ...@@ -116,8 +218,9 @@ cmd_http_rxresp(char **av, void *priv)
fprintf(stderr, "Unknown http rxresp spec: %s\n", *av); fprintf(stderr, "Unknown http rxresp spec: %s\n", *av);
exit (1); exit (1);
} }
printf("### %-4s rxresp\n", hp->ident);
http_rxhdr(hp); http_rxhdr(hp);
hp->resp = hp->rxbuf; http_splitheader(hp, 0);
} }
/********************************************************************** /**********************************************************************
...@@ -193,6 +296,7 @@ cmd_http_txresp(char **av, void *priv) ...@@ -193,6 +296,7 @@ cmd_http_txresp(char **av, void *priv)
} }
vsb_finish(vsb); vsb_finish(vsb);
AZ(vsb_overflowed(vsb)); AZ(vsb_overflowed(vsb));
vct_dump(hp->ident, NULL, vsb_data(vsb));
l = write(hp->fd, vsb_data(vsb), vsb_len(vsb)); l = write(hp->fd, vsb_data(vsb), vsb_len(vsb));
assert(l == vsb_len(vsb)); assert(l == vsb_len(vsb));
vsb_delete(vsb); vsb_delete(vsb);
...@@ -216,8 +320,9 @@ cmd_http_rxreq(char **av, void *priv) ...@@ -216,8 +320,9 @@ cmd_http_rxreq(char **av, void *priv)
fprintf(stderr, "Unknown http rxreq spec: %s\n", *av); fprintf(stderr, "Unknown http rxreq spec: %s\n", *av);
exit (1); exit (1);
} }
printf("### %-4s rxreq\n", hp->ident);
http_rxhdr(hp); http_rxhdr(hp);
hp->req = hp->rxbuf; http_splitheader(hp, 1);
} }
/********************************************************************** /**********************************************************************
...@@ -283,6 +388,7 @@ cmd_http_txreq(char **av, void *priv) ...@@ -283,6 +388,7 @@ cmd_http_txreq(char **av, void *priv)
vsb_cat(vsb, nl); vsb_cat(vsb, nl);
vsb_finish(vsb); vsb_finish(vsb);
AZ(vsb_overflowed(vsb)); AZ(vsb_overflowed(vsb));
vct_dump(hp->ident, NULL, vsb_data(vsb));
l = write(hp->fd, vsb_data(vsb), vsb_len(vsb)); l = write(hp->fd, vsb_data(vsb), vsb_len(vsb));
assert(l == vsb_len(vsb)); assert(l == vsb_len(vsb));
vsb_delete(vsb); vsb_delete(vsb);
...@@ -297,12 +403,12 @@ static struct cmds http_cmds[] = { ...@@ -297,12 +403,12 @@ static struct cmds http_cmds[] = {
{ "rxreq", cmd_http_rxreq }, { "rxreq", cmd_http_rxreq },
{ "txresp", cmd_http_txresp }, { "txresp", cmd_http_txresp },
{ "rxresp", cmd_http_rxresp }, { "rxresp", cmd_http_rxresp },
{ "expect", cmd_dump }, { "expect", cmd_http_expect },
{ NULL, NULL } { NULL, NULL }
}; };
void void
http_process(const char *spec, int sock, int client) http_process(const char *ident, const char *spec, int sock, int client)
{ {
struct http *hp; struct http *hp;
char *s, *q; char *s, *q;
...@@ -310,6 +416,7 @@ http_process(const char *spec, int sock, int client) ...@@ -310,6 +416,7 @@ http_process(const char *spec, int sock, int client)
ALLOC_OBJ(hp, HTTP_MAGIC); ALLOC_OBJ(hp, HTTP_MAGIC);
AN(hp); AN(hp);
hp->fd = sock; hp->fd = sock;
hp->ident = ident;
hp->client = client; hp->client = client;
hp->timeout = 1000; hp->timeout = 1000;
hp->nrxbuf = 8192; hp->nrxbuf = 8192;
......
...@@ -82,18 +82,18 @@ server_thread(void *priv) ...@@ -82,18 +82,18 @@ server_thread(void *priv)
CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC); CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
assert(s->sock >= 0); assert(s->sock >= 0);
printf("### Server %s started\n", s->name); printf("## %-4s started\n", s->name);
for (i = 0; i < s->repeat; i++) { for (i = 0; i < s->repeat; i++) {
if (s->repeat > 1) if (s->repeat > 1)
printf("#### Server %s iteration %d\n", s->name, i); printf("### %-4s iteration %d\n", s->name, i);
addr = (void*)&addr_s; addr = (void*)&addr_s;
l = sizeof addr_s; l = sizeof addr_s;
fd = accept(s->sock, addr, &l); fd = accept(s->sock, addr, &l);
printf("#### Accepted socket %d\n", fd); printf("#### %-4s Accepted socket %d\n", s->name, fd);
http_process(s->spec, fd, 0); http_process(s->name, s->spec, fd, 0);
AZ(close(fd)); AZ(close(fd));
} }
printf("### Server %s ending\n", s->name); printf("## %-4s ending\n", s->name);
return (NULL); return (NULL);
} }
...@@ -157,7 +157,7 @@ server_wait(struct server *s) ...@@ -157,7 +157,7 @@ server_wait(struct server *s)
void *res; void *res;
CHECK_OBJ_NOTNULL(s, SERVER_MAGIC); CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
printf("Waiting for server %s\n", s->name); printf("## %-4s Waiting for server\n", s->name);
AZ(pthread_join(s->tp, &res)); AZ(pthread_join(s->tp, &res));
if (res != NULL) { if (res != NULL) {
fprintf(stderr, "Server %s returned \"%s\"\n", fprintf(stderr, "Server %s returned \"%s\"\n",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment