/* cache_hash.c */
struct object *HSH_Lookup(struct sess *sp);
void HSH_Unbusy(struct object *o);
+void HSH_Ref(struct object *o);
void HSH_Deref(struct object *o);
void HSH_Init(void);
int http_GetStatus(struct http *hp);
int http_HdrIs(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, char *b, unsigned len);
void http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg);
int http_DissectRequest(struct http *sp, int fd);
int http_DissectResponse(struct http *sp, int fd);
{
vca_write_obj(sp->wrk, sp);
+ HSH_Deref(sp->obj);
+ sp->obj = NULL;
sp->step = STP_DONE;
return (0);
}
{
char *b;
+ assert(sp->obj == NULL);
if (http_GetHdr(sp->http, "Connection", &b) &&
!strcmp(b, "close")) {
vca_close_session(sp, "Connection header");
sp->obj->pass = 1;
sp->obj->cacheable = 1;
HSH_Unbusy(sp->obj);
+ /* Don't HSH_Deref(sp->obj); we need the ref for storage */
sp->obj = NULL;
sp->step = STP_PASSBODY;
return (0);
if (sp->handling == VCL_RET_INSERT) {
sp->obj->cacheable = 1;
FetchBody(sp->wrk, sp);
+ HSH_Ref(sp->obj); /* get another, STP_DELIVER will deref */
+ HSH_Unbusy(sp->obj);
sp->step = STP_DELIVER;
return (0);
}
sp->vcl = VCL_Get();
SES_RefSrcAddr(sp);
+ assert(sp->obj == NULL);
+
done = http_DissectRequest(sp->http, sp->fd);
if (done != 0) {
RES_Error(sp->wrk, sp, done, NULL);
fetch_straight(const struct sess *sp, int fd, struct http *hp, char *b)
{
int i;
- char *e;
unsigned char *p;
off_t cl;
struct storage *st;
i &= ~O_NONBLOCK;
i = fcntl(fd, F_SETFL, i);
- if (http_GetTail(hp, cl, &b, &e)) {
- i = e - b;
- memcpy(p, b, i);
- p += i;
- cl -= i;
- }
-
while (cl != 0) {
- i = read(fd, p, cl);
+ i = http_Read(hp, fd, p, cl);
assert(i > 0); /* XXX seen */
p += i;
cl -= i;
fetch_chunked(const struct sess *sp, int fd, struct http *hp)
{
int i;
- char *b, *q, *e;
+ char *q;
unsigned char *p;
struct storage *st;
unsigned u, v;
bp = buf;
st = NULL;
while (1) {
- if (http_GetTail(hp, be - bp, &b, &e)) {
- memcpy(bp, b, e - b);
- bp += e - b;
- *bp = '\0';
- } else {
- i = read(fd, bp, be - bp);
- assert(i >= 0);
- bp += i;
- *bp = '\0';
- }
+ i = http_Read(hp, fd, bp, be - bp);
+ assert(i >= 0);
+ bp += i;
+ *bp = '\0';
u = strtoul(buf, &q, 16);
if (q == NULL || q == buf)
continue;
break;
if (v == 0)
continue;
- if (http_GetTail(hp, v, &b, &e)) {
- memcpy(p, b, e - b);
- p += e - b;
- st->len += e - b;
- v -= e - b;
- u -= e - b;
- }
while (v > 0) {
- i = read(fd, p, v);
+ i = http_Read(hp, fd, p, v);
assert(i > 0);
st->len += i;
v -= i;
fetch_eof(const struct sess *sp, int fd, struct http *hp)
{
int i;
- char *b, *e;
unsigned char *p;
struct storage *st;
unsigned v;
}
assert(p != NULL);
assert(st != NULL);
- if (http_GetTail(hp, v, &b, &e)) {
- memcpy(p, b, e - b);
- p += e - b;
- v -= e - b;
- st->len += e - b;
- sp->obj->len += e - b;
- *p = '\0';
- }
- i = read(fd, p, v);
+ i = http_Read(hp, fd, p, v);
assert(i >= 0);
if (i == 0)
break;
}
}
+void
+HSH_Ref(struct object *o)
+{
+ struct objhead *oh;
+
+ oh = o->objhead;
+ AZ(pthread_mutex_lock(&oh->mtx));
+ o->refcnt++;
+ AZ(pthread_mutex_unlock(&oh->mtx));
+}
+
void
HSH_Deref(struct object *o)
{
return (1);
}
+/* Read from fd, but soak up any tail first */
+
+int
+http_Read(struct http *hp, int fd, char *b, unsigned len)
+{
+ int i;
+ unsigned u;
+
+ u = 0;
+ if (hp->t < hp->v) {
+ u = hp->v - hp->t;
+ if (u > len)
+ u = len;
+ memcpy(b, hp->t, u);
+ hp->t += u;
+ b += u;
+ len -= u;
+ }
+ if (len > 0) {
+ i = read(fd, b, len);
+ if (i < 0)
+ return (i);
+ u += i;
+ }
+ return (u);
+}
+
int
http_GetStatus(struct http *hp)
{
pass_straight(struct sess *sp, int fd, struct http *hp, char *bi)
{
int i;
- char *b, *e;
off_t cl;
unsigned c;
char buf[PASS_BUFSIZ];
c = cl;
if (c > sizeof buf)
c = sizeof buf;
- if (http_GetTail(hp, c, &b, &e)) {
- i = e - b;
- vca_write(sp, b, i);
- cl -= i;
- continue;
- }
- i = read(fd, buf, c);
+ i = http_Read(hp, fd, buf, c);
if (i == 0 && bi == NULL)
return (1);
assert(i > 0);
be = buf + sizeof buf;
p = buf;
while (1) {
- if (http_GetTail(hp, be - bp, &b, &e)) {
- memcpy(bp, b, e - b);
- bp += e - b;
- } else {
- /* XXX: must be safe from backend */
- i = read(fd, bp, be - bp);
- assert(i > 0);
- bp += i;
- }
+ i = http_Read(hp, fd, bp, be - bp);
+ i = read(fd, bp, be - bp);
+ assert(i > 0);
+ bp += i;
/* buffer valid from p to bp */
u = strtoul(p, &q, 16);
vc = sp->vbc;
assert(vc != NULL);
- http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp);
+ http_BuildSbuf(sp->fd, Build_Passreply, w->sb, hp);
sbuf_cat(w->sb, "\r\n");
sbuf_finish(w->sb);
vca_write(sp, sbuf_data(w->sb), sbuf_len(w->sb));
http_BuildSbuf(vc->fd, Build_Pipe, w->sb, sp->http);
i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
assert(i == sbuf_len(w->sb));
- if (http_GetTail(sp->http, 0, &b, &e) && b != e) { /* XXX */
+ if (http_GetTail(sp->http, 0, &b, &e) && b != e) {
i = write(vc->fd, b, e - b);
if (i != e - b) {
close (vc->fd);