0
@@ -135,13 +135,11 @@ void content_length_cb(void *data, const char *at, size_t length)
0
ebb_client *client = (ebb_client*)(data);
0
env_add_const(client, EBB_CONTENT_LENGTH, at, length);
0
- client->content_length = 0;
0
- for(i = length-1; 0 <= i; i--) { /* i hate c. */
0
- client->content_length *= 10;
0
- client->content_length += at[i] - '0';
0
- // ebb_debug("content length read: %d", client->content_length);
0
+ strncpy(buf, at, length);
0
+ client->content_length = atoi(buf);
0
@@ -181,11 +179,9 @@ void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
0
+#define client_finished_parsing http_parser_is_finished(&client->parser)
0
-void on_readable( struct ev_loop *loop
0
+void on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
0
ebb_client *client = (ebb_client*)(watcher->data);
0
@@ -193,29 +189,26 @@ void on_readable( struct ev_loop *loop
0
assert(client->server->open);
0
assert(client->server->loop == loop);
0
assert(&client->read_watcher == watcher);
0
- assert(FALSE == http_parser_is_finished(&client->parser));
0
+ assert(FALSE == client_finished_parsing);
0
ssize_t read = recv( client->fd
0
- , client->request_buffer + client->read
0
- , EBB_BUFFERSIZE - client->read - 1
0
+ , client->request_buffer + client->nread_head
0
+ , EBB_BUFFERSIZE - client->nread_head - 1
0
if(read <= 0) goto error; /* XXX is this the right action to take for read==0 ? */
0
+ client->nread_head += read;
0
ev_timer_again(loop, &client->timeout_watcher);
0
- client->request_buffer[client->read] = '\0'; /* make ragel happy */
0
+ client->request_buffer[client->nread_head] = '\0'; /* make ragel happy */
0
http_parser_execute( &client->parser
0
, client->request_buffer
0
if(http_parser_has_error(&client->parser)) goto error;
0
- if(http_parser_is_finished(&client->parser)) {
0
+ if(client_finished_parsing) {
0
ev_io_stop(loop, watcher);
0
- client->read_from_body = 0;
0
- client->request_body_head = client->request_buffer + client->parser.nread;
0
- client->request_body_head_size = client->read - client->parser.nread;
0
@@ -288,11 +281,9 @@ void on_request( struct ev_loop *loop
0
- client->write_buffer->len = 0; // see note in ebb_client_close
0
- client->content_length = 0;
0
- client->request_body_head = NULL;
0
- client->request_body_head_size = 0;
0
+ client->nread_head = client->nread_body = 0;
0
+ client->response_buffer->len = 0; /* see note in ebb_client_close */
0
+ client->content_length = -1;
0
/* SETUP READ AND TIMEOUT WATCHERS */
0
client->read_watcher.data = client;
0
@@ -321,7 +312,7 @@ void ebb_server_init( ebb_server *server
0
for(i=0; i < EBB_MAX_CLIENTS; i++)
0
- server->clients[i].write_buffer = g_string_new("");
0
+ server->clients[i].response_buffer = g_string_new("");
0
server->request_cb = request_cb;
0
server->request_cb_data = request_cb_data;
0
@@ -341,7 +332,7 @@ void ebb_server_free(ebb_server *server)
0
for(i=0; i < EBB_MAX_CLIENTS; i++)
0
- g_string_free(server->clients[i].write_buffer, TRUE);
0
+ g_string_free(server->clients[i].response_buffer, TRUE);
0
@@ -409,20 +400,18 @@ int ebb_server_listen_on_socket(ebb_server *server, const char *socketpath)
0
void ebb_client_close(ebb_client *client)
0
- ev_io_stop(client->server->loop, &(client->read_watcher));
0
- ev_io_stop(client->server->loop, &(client->write_watcher));
0
- ev_timer_stop(client->server->loop, &(client->timeout_watcher));
0
+ ev_io_stop(client->server->loop, &client->read_watcher);
0
+ ev_io_stop(client->server->loop, &client->write_watcher);
0
+ ev_timer_stop(client->server->loop, &client->timeout_watcher);
0
- http_parser_finish(&(client->parser));
0
+ http_parser_finish(&client->parser);
0
- /* the theory here is that we do not free the already allocated
0
- * strings that we're holding the response in. we reuse it again -
0
+ /* here we do not free the already allocated GString client->response_buffer
0
+ * that we're holding the response in. we reuse it again -
0
* presumably because the backend is going to keep sending such long
0
- client->write_buffer->len = 0;
0
+ client->response_buffer->len = 0;
0
@@ -444,8 +433,8 @@ void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
0
// ebb_debug("total written: %d", (int)(client->written));
0
sent = send( client->fd
0
- , client->write_buffer->str + sizeof(gchar)*(client->written)
0
- , client->write_buffer->len - client->written
0
+ , client->response_buffer->str + sizeof(gchar)*(client->written)
0
+ , client->response_buffer->len - client->written
0
@@ -457,54 +446,76 @@ void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
0
client->written += sent;
0
- assert(client->written <= client->write_buffer->len);
0
+ assert(client->written <= client->response_buffer->len);
0
//ebb_info("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
0
ev_timer_again(loop, &(client->timeout_watcher));
0
- if(client->written == client->write_buffer->len)
0
+ if(client->written == client->response_buffer->len)
0
ebb_client_close(client);
0
void ebb_client_write(ebb_client *client, const char *data, int length)
0
- g_string_append_len(client->write_buffer, data, length);
0
+ g_string_append_len(client->response_buffer, data, length);
0
/* pass an allocated buffer and the length to read. this function will try to
0
* fill the buffer with that length of data read from the body of the request.
0
* the return value says how much was actually written.
0
+ * return length read on successful read
0
+ * returns -2 if the nonblocking socket is not yet availible for reading
0
+ * returns -3 if content_length is present and the request is finished.
0
-size_t ebb_client_read(ebb_client *client, char *buffer, int length)
0
+int ebb_client_read(ebb_client *client, char *buffer, int length)
0
- assert(TRUE == http_parser_is_finished(&client->parser));
0
- assert(client->read_from_body <= client->content_length);
0
+ char* body_beginning = client->request_buffer + client->parser.nread;
0
+ int body_beginning_size = client->nread_head - client->parser.nread;
0
+ if(!client->open) return -1;
0
- size_t to_read = ramp(min(length, client->content_length - client->read_from_body));
0
+ assert(client->nread_body >= 0);
0
- if(client->read_from_body < client->request_body_head_size) {
0
+ assert(client_finished_parsing);
0
+ assert(client->parser.nread + body_beginning_size < EBB_BUFFERSIZE);
0
+ assert(client->parser.nread + body_beginning_size == client->nread_head);
0
+ if(client->nread_body == client->content_length) return(-3);
0
+ if(client->nread_body < body_beginning_size) {
0
+ to_read = min(length, body_beginning_size - client->nread_body);
0
+ assert(0 <= to_read && to_read <= length);
0
- , client->request_body_head + client->read_from_body
0
+ , body_beginning + client->nread_body
0
- client->read_from_body += to_read;
0
+ client->nread_body += to_read;
0
+ /* allow for requests where the content length is not mentioned. e.g.
0
+ read = recv(client->fd, buffer, length, 0);
0
+ //ebb_info("recv(%d, buffer, %d, 0) -> %d (%s)", client->fd, length, read, strerror(errno));
0
+ if(errno == EAGAIN) return -2;
0
+ ebb_warning("closing client. ebb_client_read: %s", strerror(errno));
0
+ ebb_client_close(client);
0
+ client->nread_body += read;
0
- ssize_t read = recv(client->fd, buffer, to_read, 0);
0
- ebb_warning("closing client. ebb_client_read: %s", strerror(errno));
0
- ebb_client_close(client);
0
- client->read_from_body += read;
0
-void ebb_client_finished( ebb_client *client)
0
+void ebb_client_finished(ebb_client *client)
0
assert(FALSE == ev_is_active(&(client->write_watcher)));
0
@@ -549,9 +560,9 @@ static int server_socket(const int port) {
0
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
0
- setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
0
- setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
0
- setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
0
+ // setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
0
+ // setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
0
+ // setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
0
* the memset call clears nonstandard fields in some impementations
Comments
No one has commented yet.