예제 #1
0
int HTTPConnectionReadBodyLine(HTTPConnectionRef const conn, str_t out[], size_t const max) {
	if(!conn) return UV_EINVAL;
	if(!max) return UV_EINVAL;
	uv_buf_t buf[1];
	int rc;
	size_t i;
	HTTPEvent type;
	out[0] = '\0';
	for(;;) {
		rc = HTTPConnectionPeek(conn, &type, buf);
		if(rc < 0) return rc;
		if(HTTPMessageEnd == type) {
			if(out[0]) return 0;
			HTTPConnectionPop(conn, buf->len);
			return UV_EOF;
		}
		if(HTTPBody != type) {
			assertf(0, "Unexpected HTTP event %d", type);
			return UV_UNKNOWN;
		}
		for(i = 0; i < buf->len; ++i) {
			if('\r' == buf->base[i]) break;
			if('\n' == buf->base[i]) break;
		}
		append_buf_to_string(out, max, buf->base, i);
		HTTPConnectionPop(conn, i);
		if(i < buf->len) break;
	}

	rc = HTTPConnectionPeek(conn, &type, buf);
	if(rc < 0) return rc;
	if(HTTPMessageEnd == type) {
		if(out[0]) return 0;
		HTTPConnectionPop(conn, i);
		return UV_EOF;
	}
	if(HTTPBody != type) return UV_UNKNOWN;
	if('\r' == buf->base[0]) HTTPConnectionPop(conn, 1);

	rc = HTTPConnectionPeek(conn, &type, buf);
	if(rc < 0) return rc;
	if(HTTPMessageEnd == type) {
		if(out[0]) return 0;
		HTTPConnectionPop(conn, i);
		return UV_EOF;
	}
	if(HTTPBody != type) return UV_UNKNOWN;
	if('\n' == buf->base[0]) HTTPConnectionPop(conn, 1);

	return 0;
}
예제 #2
0
int MultipartFormPeek(MultipartFormRef const form, MultipartEvent *const type, uv_buf_t *const buf) {
	if(!form) return UV_EINVAL;
	if(!type) return UV_EINVAL;
	if(!buf) return UV_EINVAL;
	uv_buf_t raw[1];
	HTTPEvent t;
	int rc;
	ssize_t len;
	for(;;) {
		if(MultipartNothing != form->type) break;
		rc = HTTPConnectionPeek(form->conn, &t, raw);
		if(rc < 0) return rc;
		if(HTTPMessageEnd == t) {
			*raw = uv_buf_init(NULL, 0);
			t = HTTPBody;
		}
		if(HTTPBody != t) {
			assertf(0, "Multipart unexpected HTTP event: %d\n", t);
			return UV_UNKNOWN;
		}
		len = multipart_parser_execute(form->parser, raw->base, raw->len);
		if(len < 0) {
			alogf("Multipart parse error\n");
			return -1;
		}
		HTTPConnectionPop(form->conn, len);
	}
	assertf(MultipartNothing != form->type, "MultipartFormPeek must return an event");
	*type = form->type;
	*buf = *form->out;
	return 0;
}
예제 #3
0
ssize_t HTTPConnectionReadRequest(HTTPConnectionRef const conn, HTTPMethod *const method, str_t *const out, size_t const max) {
	if(!conn) return UV_EINVAL;
	if(!max) return UV_EINVAL;
	uv_buf_t buf[1];
	int rc;
	HTTPEvent type;
	size_t len = 0;
	for(;;) {
		// Use unref because we shouldn't block the server
		// on a request that may never arrive.
		uv_unref((uv_handle_t *)conn->stream);
		rc = HTTPConnectionPeek(conn, &type, buf);
		uv_ref((uv_handle_t *)conn->stream);
		if(rc < 0) return rc;
		if(HTTPHeaderField == type || HTTPHeadersComplete == type) break;
		HTTPConnectionPop(conn, buf->len);
		if(HTTPMessageBegin == type) continue;
		if(HTTPURL != type) {
			assertf(0, "Unexpected HTTP event %d", type);
			return UV_UNKNOWN;
		}
		if(len+buf->len+1 > max) return UV_EMSGSIZE;
		memcpy(out+len, buf->base, buf->len);
		len += buf->len;
		out[len] = '\0';
	}
	*method = conn->parser->method;
	return (ssize_t)len;
}
예제 #4
0
int HTTPHeadersLoad(HTTPHeadersRef const h, HTTPConnectionRef const conn) {
	if(!h) return 0;
	if(!conn) return UV_EINVAL;
	uv_buf_t buf[1];
	HTTPEvent type;
	str_t field[FIELD_MAX];
	str_t value[VALUE_MAX];
	int rc;
	for(;;) {
		rc = HTTPConnectionPeek(conn, &type, buf);
		if(rc < 0) return rc;
		if(HTTPHeadersComplete == type) {
			HTTPConnectionPop(conn, buf->len);
			break;
		}
		ssize_t const flen = HTTPConnectionReadHeaderField(conn, field, sizeof(field));
		ssize_t const vlen = HTTPConnectionReadHeaderValue(conn, value, sizeof(value));
		if(UV_EMSGSIZE == flen) continue;
		if(flen < 0) return flen;
		if(vlen < 0) return vlen;

		if(h->count >= HEADERS_MAX) return UV_EMSGSIZE;
		if(h->offset+flen+1 > FIELDS_SIZE) return UV_EMSGSIZE;
		if(h->total+vlen > TOTAL_MAX) return UV_EMSGSIZE;
		if(!flen) continue;

		// We could use strlcpy() here, but it doesn't buy us much...
		memcpy(h->fields + h->offset, field, flen+1);
		h->offset += flen+1;
		h->values[h->count] = strndup(value, vlen);
		h->count++;
		h->total += vlen+1;
	}
	return 0;
}
예제 #5
0
int HTTPConnectionReadBody(HTTPConnectionRef const conn, uv_buf_t *const buf) {
	if(!conn) return UV_EINVAL;
	HTTPEvent type;
	int rc = HTTPConnectionPeek(conn, &type, buf);
	if(rc < 0) return rc;
	if(HTTPBody != type && HTTPMessageEnd != type) {
		assertf(0, "Unexpected HTTP event %d", type);
		return UV_UNKNOWN;
	}
	HTTPConnectionPop(conn, buf->len);
	return 0;
}
예제 #6
0
int HTTPConnectionReadResponseStatus(HTTPConnectionRef const conn) {
	if(!conn) return UV_EINVAL;
	uv_buf_t buf[1];
	int rc;
	HTTPEvent type;
	for(;;) {
		rc = HTTPConnectionPeek(conn, &type, buf);
		if(rc < 0) return rc;
		if(HTTPHeaderField == type || HTTPHeadersComplete == type) break;
		if(HTTPMessageBegin != type) {
			assertf(0, "Unexpected HTTP event %d", type);
			return UV_UNKNOWN;
		}
		HTTPConnectionPop(conn, buf->len);
	}
	return conn->parser->status_code;
}
예제 #7
0
int HTTPConnectionDrainMessage(HTTPConnectionRef const conn) {
	if(!conn) return 0;
	if(HTTPStreamEOF & conn->flags) return UV_EOF;
	if(!(HTTPMessageIncomplete & conn->flags)) return 0;
	uv_buf_t buf[1];
	int rc;
	HTTPEvent type;
	for(;;) {
		rc = HTTPConnectionPeek(conn, &type, buf);
		if(rc < 0) return rc;
		if(HTTPMessageBegin == type) {
			assertf(0, "HTTPConnectionDrainMessage shouldn't start a new message");
			return UV_UNKNOWN;
		}
		HTTPConnectionPop(conn, buf->len);
		if(HTTPMessageEnd == type) break;
	}
	return 0;
}
예제 #8
0
ssize_t HTTPConnectionReadHeaderValue(HTTPConnectionRef const conn, str_t out[], size_t const max) {
	if(!conn) return UV_EINVAL;
	uv_buf_t buf[1];
	int rc;
	HTTPEvent type;
	size_t len = 0;
	if(max > 0) out[0] = '\0';
	for(;;) {
		rc = HTTPConnectionPeek(conn, &type, buf);
		if(rc < 0) return rc;
		if(HTTPHeaderField == type) break;
		if(HTTPHeadersComplete == type) break;
		HTTPConnectionPop(conn, buf->len);
		if(HTTPHeaderValue != type) {
			assertf(0, "Unexpected HTTP event %d", type);
			return UV_UNKNOWN;
		}
		if(len+buf->len+1 > max) return UV_EMSGSIZE;
		memcpy(out+len, buf->base, buf->len);
		len += buf->len;
		out[len] = '\0';
	}
	return (ssize_t)len;
}