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

Complete the split of HTTP-editing and HTTP-transmission functions.


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@2055 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent f6b82905
......@@ -110,8 +110,6 @@ struct http {
#define HTTP_MAGIC 0x6428b5c9
struct ws *ws;
txt rx; /* Received Request */
txt pl; /* Pipelined bytes */
unsigned char conds; /* If-* headers present */
enum httpwhence logtag;
......@@ -126,7 +124,7 @@ struct http_conn {
unsigned magic;
#define HTTP_CONN_MAGIC 0x3e19edd1
struct http *http;
int fd;
struct ws *ws;
txt rxbuf;
txt pipeline;
......@@ -289,6 +287,8 @@ struct sess {
struct http *http;
struct ws ws[1];
struct http_conn htc[1];
/* Timestamps, all on TIM_real() timescale */
double t_open;
double t_req;
......@@ -470,18 +470,17 @@ int http_GetStatus(const struct http *hp);
const char *http_GetReq(const struct http *hp);
const char *http_GetProto(const struct http *hp);
int http_HdrIs(const struct http *hp, const char *hdr, const char *val);
int http_GetTail(struct http *hp, unsigned len, char **b, char **e);
int http_Read(struct http *hp, int fd, void *b, unsigned len);
void http_RecvPrep(struct http *hp);
int http_RecvPrepAgain(struct http *hp);
int http_RecvSome(int fd, struct http *hp);
int http_RecvHead(struct http *hp, int fd);
int http_DissectRequest(struct worker *w, struct http *sp, int fd);
int http_DissectResponse(struct worker *w, struct http *sp, int fd);
int http_DissectRequest(struct sess *sp);
int http_DissectResponse(struct worker *w, struct http_conn *htc, struct http *sp);
const char *http_DoConnection(struct http *hp);
void http_CopyHome(struct worker *w, int fd, struct http *hp);
void http_Unset(struct http *hp, const char *hdr);
/* cache_httpconn.c */
void HTC_Init(struct http_conn *htc, struct ws *ws, int fd);
int HTC_Reinit(struct http_conn *htc);
int HTC_Rx(struct http_conn *htc);
int HTC_Read(struct http_conn *htc, void *d, unsigned len);
#define HTTPH(a, b, c, d, e, f, g) extern char b[];
#include "http_headers.h"
......
......@@ -194,7 +194,7 @@ vca_acct(void *arg)
sp->id = i;
sp->t_open = TIM_real();
http_RecvPrep(sp->http);
HTC_Init(sp->htc, sp->ws, sp->fd);
sp->step = STP_FIRST;
WRK_QueueSession(sp);
}
......@@ -224,13 +224,13 @@ vca_pollsession(struct sess *sp)
{
int i;
i = http_RecvSome(sp->fd, sp->http);
if (i < 1)
return (i);
i = HTC_Rx(sp->htc);
/* XXX: fix retval */
if (i == 0)
return (-1);
if (i == 1)
vca_close_session(sp, "overflow");
else if (i == 2)
vca_close_session(sp, "no request");
return (0);
vca_close_session(sp, "err/poll");
return (1);
}
......
......@@ -88,20 +88,15 @@ cnt_again(struct sess *sp)
assert(sp->xid == 0);
do
i = http_RecvSome(sp->fd, sp->http);
while (i == -1);
if (i == 0) {
do
i = HTC_Rx(sp->htc);
while (i == 0);
if (i == 1) {
sp->step = STP_RECV;
return (0);
}
if (i == 1)
} else {
vca_close_session(sp, "overflow");
else if (i == 2)
vca_close_session(sp, "no request");
else
INCOMPL();
sp->step = STP_DONE;
sp->step = STP_DONE;
}
return (0);
}
......@@ -185,6 +180,7 @@ static int
cnt_done(struct sess *sp)
{
double dh, dp, da;
int i;
AZ(sp->obj);
AZ(sp->bereq);
......@@ -224,12 +220,13 @@ cnt_done(struct sess *sp)
return (1);
}
if (http_RecvPrepAgain(sp->http)) {
i = HTC_Reinit(sp->htc);
if (i == 1) {
VSL_stats->sess_pipeline++;
sp->step = STP_RECV;
return (0);
}
if (sp->http->pl.b < sp->http->pl.e) {
if (Tlen(sp->htc->rxbuf)) {
VSL_stats->sess_readahead++;
sp->step = STP_AGAIN;
return (0);
......@@ -388,13 +385,13 @@ cnt_first(struct sess *sp)
sp->wrk->acct.sess++;
SES_RefSrcAddr(sp);
do
i = http_RecvSome(sp->fd, sp->http);
while (i == -1);
if (i == 0) {
i = HTC_Rx(sp->htc);
while (i == 0);
if (i == 1) {
sp->step = STP_RECV;
return (0);
}
if (i == 1)
if (i == -1)
vca_close_session(sp, "blast");
else if (i == 2)
vca_close_session(sp, "silent");
......@@ -756,7 +753,7 @@ cnt_recv(struct sess *sp)
sp->vcl = sp->wrk->vcl;
sp->wrk->vcl = NULL;
done = http_DissectRequest(sp->wrk, sp->http, sp->fd);
done = http_DissectRequest(sp);
if (done != 0) {
RES_Error(sp, done, NULL); /* XXX: STP_ERROR ? */
sp->step = STP_DONE;
......
......@@ -49,7 +49,7 @@
/*--------------------------------------------------------------------*/
static int
fetch_straight(struct sess *sp, int fd, struct http *hp, const char *b)
fetch_straight(struct sess *sp, struct http_conn *htc, const char *b)
{
int i;
unsigned char *p;
......@@ -70,12 +70,12 @@ fetch_straight(struct sess *sp, int fd, struct http *hp, const char *b)
sp->obj->len = cl;
p = st->ptr;
i = fcntl(fd, F_GETFL); /* XXX ? */
i = fcntl(htc->fd, F_GETFL); /* XXX ? */
i &= ~O_NONBLOCK;
i = fcntl(fd, F_SETFL, i);
i = fcntl(htc->fd, F_SETFL, i);
while (cl > 0) {
i = http_Read(hp, fd, p, cl);
i = HTC_Read(htc, p, cl);
if (i <= 0)
return (-1);
p += i;
......@@ -88,7 +88,7 @@ fetch_straight(struct sess *sp, int fd, struct http *hp, const char *b)
/* XXX: Cleanup. It must be possible somehow :-( */
static int
fetch_chunked(struct sess *sp, int fd, struct http *hp)
fetch_chunked(struct sess *sp, struct http_conn *htc)
{
int i;
char *q;
......@@ -132,7 +132,7 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp)
* deal more complex than reading a single character
* at a time.
*/
i = http_Read(hp, fd, bp, 1);
i = HTC_Read(htc, bp, 1);
if (i <= 0)
return (-1);
bp += i;
......@@ -179,7 +179,7 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp)
/* Pick up the rest of this chunk */
while (v > 0) {
i = http_Read(hp, fd, st->ptr + st->len, v);
i = HTC_Read(htc, st->ptr + st->len, v);
if (i <= 0)
return (-1);
st->len += i;
......@@ -211,16 +211,16 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp)
#include <errno.h>
static int
fetch_eof(struct sess *sp, int fd, struct http *hp)
fetch_eof(struct sess *sp, struct http_conn *htc)
{
int i;
unsigned char *p;
struct storage *st;
unsigned v;
i = fcntl(fd, F_GETFL); /* XXX ? */
i = fcntl(htc->fd, F_GETFL); /* XXX ? */
i &= ~O_NONBLOCK;
i = fcntl(fd, F_SETFL, i);
i = fcntl(htc->fd, F_SETFL, i);
p = NULL;
v = 0;
......@@ -234,7 +234,7 @@ fetch_eof(struct sess *sp, int fd, struct http *hp)
}
AN(p);
AN(st);
i = http_Read(hp, fd, p, v);
i = HTC_Read(htc, p, v);
if (i < 0)
return (-1);
if (i == 0)
......@@ -268,6 +268,8 @@ Fetch(struct sess *sp)
struct bereq *bereq;
int mklen, is_head;
unsigned len;
struct http_conn htc[1];
int i;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
......@@ -300,12 +302,12 @@ Fetch(struct sess *sp)
CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
if (http_RecvHead(hp, vc->fd)) {
/* XXX: cleanup */
return (1);
}
if (http_DissectResponse(sp->wrk, hp, vc->fd)) {
HTC_Init(htc, bereq->ws, vc->fd);
do
i = HTC_Rx(htc);
while (i == 0);
if (http_DissectResponse(sp->wrk, htc, hp)) {
/* XXX: cleanup */
return (1);
}
......@@ -326,8 +328,8 @@ Fetch(struct sess *sp)
CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
/* Filter into object */
hp2 = &sp->obj->http;
len = Tlen(hp->rx);
len += 256; /* margin for content-length etc */
len = Tlen(htc->rxbuf);
len += 256; /* XXX: margin for content-length etc */
CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
b = malloc(len);
......@@ -349,10 +351,10 @@ Fetch(struct sess *sp)
if (is_head) {
/* nothing */
} else if (http_GetHdr(hp, H_Content_Length, &b)) {
cls = fetch_straight(sp, vc->fd, hp, b);
cls = fetch_straight(sp, htc, b);
mklen = 1;
} else if (http_HdrIs(hp, H_Transfer_Encoding, "chunked")) {
cls = fetch_chunked(sp, vc->fd, hp);
cls = fetch_chunked(sp, htc);
mklen = 1;
} else if (http_GetHdr(hp, H_Transfer_Encoding, &b)) {
/* XXX: AUGH! */
......@@ -362,7 +364,7 @@ Fetch(struct sess *sp)
} else if (strcmp(http_GetProto(hp), "HTTP/1.1")) {
switch (http_GetStatus(hp)) {
case 200:
cls = fetch_eof(sp, vc->fd, hp);
cls = fetch_eof(sp, htc);
mklen = 1;
break;
default:
......
......@@ -347,7 +347,7 @@ http_GetReq(const struct http *hp)
*/
static int
http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p, txt t)
{
char *q, *r;
......@@ -357,8 +357,8 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
hp->nhd = HTTP_HDR_FIRST;
hp->conds = 0;
r = NULL; /* For FlexeLint */
assert(p < hp->rx.e); /* http_header_complete() guarantees this */
for (; p < hp->rx.e; p = r) {
assert(p < t.e); /* http_header_complete() guarantees this */
for (; p < t.e; p = r) {
/* XXX: handle continuation lines */
q = strchr(p, '\n');
assert(q != NULL);
......@@ -391,16 +391,23 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
/*--------------------------------------------------------------------*/
int
http_DissectRequest(struct worker *w, struct http *hp, int fd)
http_DissectRequest(struct sess *sp)
{
char *p;
struct http_conn *htc;
struct http *hp;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
htc = sp->htc;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
hp = sp->http;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
/* Assert a NUL at rx.e */
Tcheck(hp->rx);
Tcheck(htc->rxbuf);
hp->logtag = HTTP_Rx;
for (p = hp->rx.b ; isspace(*p); p++)
for (p = htc->rxbuf.b ; isspace(*p); p++)
continue;
/* First, the request type (GET/HEAD etc) */
......@@ -408,23 +415,23 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
for (; isalpha(*p); p++)
;
hp->hd[HTTP_HDR_REQ].e = p;
WSLH(w, HTTP_T_Request, fd, hp, HTTP_HDR_REQ);
WSLH(sp->wrk, HTTP_T_Request, sp->fd, hp, HTTP_HDR_REQ);
*p++ = '\0';
/* Next find the URI */
while (isspace(*p) && *p != '\n')
p++;
if (*p == '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->rx);
WSLR(sp->wrk, SLT_HttpGarbage, sp->fd, htc->rxbuf);
return (400);
}
hp->hd[HTTP_HDR_URL].b = p;
while (!isspace(*p))
p++;
hp->hd[HTTP_HDR_URL].e = p;
WSLH(w, HTTP_T_URL, fd, hp, HTTP_HDR_URL);
WSLH(sp->wrk, HTTP_T_URL, sp->fd, hp, HTTP_HDR_URL);
if (*p == '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->rx);
WSLR(sp->wrk, SLT_HttpGarbage, sp->fd, htc->rxbuf);
return (400);
}
*p++ = '\0';
......@@ -433,44 +440,45 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
while (isspace(*p) && *p != '\n')
p++;
if (*p == '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->rx);
WSLR(sp->wrk, SLT_HttpGarbage, sp->fd, htc->rxbuf);
return (400);
}
hp->hd[HTTP_HDR_PROTO].b = p;
while (!isspace(*p))
p++;
hp->hd[HTTP_HDR_PROTO].e = p;
WSLH(w, HTTP_T_Protocol, fd, hp, HTTP_HDR_PROTO);
WSLH(sp->wrk, HTTP_T_Protocol, sp->fd, hp, HTTP_HDR_PROTO);
if (*p != '\n')
*p++ = '\0';
while (isspace(*p) && *p != '\n')
p++;
if (*p != '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->rx);
WSLR(sp->wrk, SLT_HttpGarbage, sp->fd, htc->rxbuf);
return (400);
}
*p++ = '\0';
return (http_dissect_hdrs(w, hp, fd, p));
return (http_dissect_hdrs(sp->wrk, hp, sp->fd, p, htc->rxbuf));
}
/*--------------------------------------------------------------------*/
int
http_DissectResponse(struct worker *w, struct http *hp, int fd)
http_DissectResponse(struct worker *w, struct http_conn *htc, struct http *hp)
{
char *p, *q;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
/* Assert a NUL at rx.e */
Tcheck(hp->rx);
/* Assert a NUL at rx.e (?) */
Tcheck(htc->rxbuf);
hp->logtag = HTTP_Rx;
for (p = hp->rx.b ; isspace(*p); p++)
for (p = htc->rxbuf.b ; isspace(*p); p++)
continue;
if (memcmp(p, "HTTP/1.", 7)) {
WSLR(w, SLT_HttpGarbage, fd, hp->rx);
WSLR(w, SLT_HttpGarbage, htc->fd, htc->rxbuf);
return (400);
}
/* First, protocol */
......@@ -478,7 +486,7 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
while (!isspace(*p))
p++;
hp->hd[HTTP_HDR_PROTO].e = p;
WSLH(w, HTTP_T_Protocol, fd, hp, HTTP_HDR_PROTO);
WSLH(w, HTTP_T_Protocol, htc->fd, hp, HTTP_HDR_PROTO);
*p++ = '\0';
/* Next find the status */
......@@ -488,7 +496,7 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
while (!isspace(*p))
p++;
hp->hd[HTTP_HDR_STATUS].e = p;
WSLH(w, HTTP_T_Status, fd, hp, HTTP_HDR_STATUS);
WSLH(w, HTTP_T_Status, htc->fd, hp, HTTP_HDR_STATUS);
*p++ = '\0';
/* Next find the response */
......@@ -502,11 +510,12 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
continue;
*q = '\0';
hp->hd[HTTP_HDR_RESPONSE].e = q;
WSLH(w, HTTP_T_Response, fd, hp, HTTP_HDR_RESPONSE);
WSLH(w, HTTP_T_Response, htc->fd, hp, HTTP_HDR_RESPONSE);
p++;
return (http_dissect_hdrs(w, hp, fd, p));
return (http_dissect_hdrs(w, hp, htc->fd, p, htc->rxbuf));
}
/*--------------------------------------------------------------------*/
void
......
......@@ -31,6 +31,8 @@
* HTTP protocol requests
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
......@@ -39,8 +41,7 @@
#include "cache.h"
/*--------------------------------------------------------------------
* Check if we have a complete HTTP request or response yet between the
* two pointers given.
* Check if we have a complete HTTP request or response yet
*
* Return values:
* -1 No, and you can nuke the (white-space) content.
......@@ -49,19 +50,19 @@
*/
static int
http_header_complete(const char *b, const char *e)
htc_header_complete(txt *t)
{
const char *p;
AN(b);
AN(e);
assert(b <= e);
assert(*e == '\0');
Tcheck(*t);
assert(*t->e == '\0');
/* Skip any leading white space */
for (p = b ; isspace(*p); p++)
for (p = t->b ; isspace(*p); p++)
continue;
if (*p == '\0')
return (-1);
if (*p == '\0') {
t->e = t->b;
return (0);
}
while (1) {
p = strchr(p, '\n');
if (p == NULL)
......@@ -73,169 +74,109 @@ http_header_complete(const char *b, const char *e)
break;
}
p++;
return (p - b);
return (p - t->b);
}
/*--------------------------------------------------------------------*/
void
http_RecvPrep(struct http *hp)
HTC_Init(struct http_conn *htc, struct ws *ws, int fd)
{
unsigned l;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
WS_Assert(hp->ws);
WS_Reset(hp->ws);
WS_Reserve(hp->ws, 0);
hp->rx.b = hp->ws->f;
hp->rx.e = hp->rx.b;
if (hp->pl.b != NULL) {
l = Tlen(hp->pl);
memmove(hp->rx.b, hp->pl.b, l);
hp->rx.e = hp->rx.b + l;
hp->pl.b = hp->pl.e = NULL;
}
*hp->rx.e = '\0';
htc->magic = HTTP_CONN_MAGIC;
htc->ws = ws;
htc->fd = fd;
WS_Reset(htc->ws);
WS_Reserve(htc->ws, (htc->ws->e - htc->ws->s) / 2);
htc->rxbuf.b = ws->f;
htc->rxbuf.e = ws->f;
htc->pipeline.b = NULL;
htc->pipeline.e = NULL;
}
/*--------------------------------------------------------------------
* Start over, and recycle any pipelined input.
* The WS_Reset is safe, even though the pipelined input is stored in
* the ws somewhere, because WS_Reset only fiddles pointers.
*/
int
http_RecvPrepAgain(struct http *hp)
HTC_Reinit(struct http_conn *htc)
{
unsigned l;
int i;
http_RecvPrep(hp);
if (hp->rx.b == hp->rx.e)
return (0);
i = http_header_complete(hp->rx.b, hp->rx.e);
if (i == -1)
hp->rx.e = hp->rx.b;
if (i <= 0)
return (0);
WS_ReleaseP(hp->ws, hp->rx.e);
if (hp->rx.e != hp->rx.b + i) {
hp->pl.b = hp->rx.b + i;
hp->pl.e = hp->rx.e;
hp->rx.e = hp->pl.b;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
WS_Reset(htc->ws);
WS_Reserve(htc->ws, (htc->ws->e - htc->ws->s) / 2);
htc->rxbuf.b = htc->ws->f;
htc->rxbuf.e = htc->ws->f;
if (htc->pipeline.b != NULL) {
l = Tlen(htc->pipeline);
memmove(htc->rxbuf.b, htc->pipeline.b, l);
htc->rxbuf.e += l;
htc->pipeline.b = NULL;
htc->pipeline.e = NULL;
}
*htc->rxbuf.e = '\0';
i = htc_header_complete(&htc->rxbuf);
return (i);
}
/*--------------------------------------------------------------------*/
int
http_RecvSome(int fd, struct http *hp)
HTC_Rx(struct http_conn *htc)
{
unsigned l;
int i;
l = pdiff(hp->rx.e, hp->ws->e) - 1;
l /= 2; /* Don't fill all of workspace with read-ahead */
if (l <= 1) {
VSL(SLT_HttpError, fd, "Received too much");
VSLR(SLT_HttpGarbage, fd, hp->rx);
hp->rx.b = hp->rx.e = NULL;
WS_Release(hp->ws, 0);
return (1);
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
i = (htc->ws->r - htc->rxbuf.e) - 1; /* space for NUL */
assert(i > 0);
i = read(htc->fd, htc->rxbuf.e, i);
if (i < 0) {
WS_ReleaseP(htc->ws, htc->rxbuf.b);
return (-1);
}
errno = 0;
i = read(fd, hp->rx.e, l - 1);
if (i > 0) {
hp->rx.e += i;
*hp->rx.e = '\0';
i = http_header_complete(hp->rx.b, hp->rx.e);
if (i == -1)
hp->rx.e = hp->rx.b;
if (i == 0)
return (-1);
WS_ReleaseP(hp->ws, hp->rx.e);
if (hp->rx.e != hp->rx.b + i) {
hp->pl.b = hp->rx.b + i;
hp->pl.e = hp->rx.e;
hp->rx.e = hp->pl.b;
}
htc->rxbuf.e += i;
*htc->rxbuf.e = '\0';
i = htc_header_complete(&htc->rxbuf);
if (i == 0)
return (0);
WS_ReleaseP(htc->ws, htc->rxbuf.e);
if (htc->rxbuf.b + i < htc->rxbuf.e) {
htc->pipeline.b = htc->rxbuf.b + i;
htc->pipeline.e = htc->rxbuf.e;
htc->rxbuf.e = htc->pipeline.b;
}
if (hp->rx.e != hp->rx.b) {
VSL(SLT_HttpError, fd,
"Received (only) %d bytes, errno %d",
hp->rx.e - hp->rx.b, errno);
VSLR(SLT_Debug, fd, hp->rx);
} else if (errno == 0)
VSL(SLT_HttpError, fd, "Received nothing");
else
VSL(SLT_HttpError, fd, "Received errno %d", errno);
hp->rx.b = hp->rx.e = NULL;
WS_Release(hp->ws, 0);
return(2);
}
/*--------------------------------------------------------------------*/
int
http_RecvHead(struct http *hp, int fd)
{
int i;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
http_RecvPrep(hp);
do
i = http_RecvSome(fd, hp);
while (i == -1);
return (i);
}
/*--------------------------------------------------------------------*/
int
http_GetTail(struct http *hp, unsigned len, char **b, char **e)
{
if (hp->pl.b >= hp->pl.e)
return (0);
if (len == 0)
len = Tlen(hp->pl);
if (hp->pl.b + len > hp->pl.e)
len = Tlen(hp->pl);
if (len == 0)
return (0);
*b = hp->pl.b;
*e = hp->pl.b + len;
hp->pl.b += len;
Tcheck(hp->pl);
return (1);
}
/*--------------------------------------------------------------------*/
/* Read from fd, but soak up any tail first */
int
http_Read(struct http *hp, int fd, void *p, unsigned len)
HTC_Read(struct http_conn *htc, void *d, unsigned len)
{
unsigned l;
unsigned char *p;
int i;
unsigned u;
char *b = p;
u = 0;
if (hp->pl.b < hp->pl.e) {
u = Tlen(hp->pl);
if (u > len)
u = len;
memcpy(b, hp->pl.b, u);
hp->pl.b += u;
b += u;
len -= u;
}
if (hp->pl.e == hp->pl.b)
hp->pl.b = hp->pl.e = NULL;
if (len > 0) {
i = read(fd, b, len);
if (i < 0) /* XXX i == 0 ?? */
return (i);
u += i;
l = 0;
p = d;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
if (htc->pipeline.b) {
l = Tlen(htc->pipeline);
if (l > len)
l = len;
memcpy(p, htc->pipeline.b, l);
p += l;
len -= l;
htc->pipeline.b += l;
if (htc->pipeline.b == htc->pipeline.e)
htc->pipeline.b = htc->pipeline.e = NULL;
}
return (u);
if (len == 0)
return (l);
i = read(htc->fd, p, len);
if (i < 0)
return (i);
return (i + l);
}
......@@ -70,7 +70,6 @@ void
PipeSession(struct sess *sp)
{
struct vbe_conn *vc;
char *b, *e;
struct worker *w;
struct bereq *bereq;
struct pollfd fds[2];
......@@ -89,8 +88,8 @@ PipeSession(struct sess *sp)
WRK_Reset(w, &vc->fd);
http_Write(w, bereq->http, 0);
if (http_GetTail(sp->http, 0, &b, &e) && b != e)
WRK_Write(w, b, e - b);
if (sp->htc->pipeline.b != NULL)
WRK_Write(w, sp->htc->pipeline.b, Tlen(sp->htc->pipeline));
if (WRK_Flush(w)) {
vca_close_session(sp, "pipe");
......
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