0
#define ramp(a) (a > 0 ? a : 0)
0
static int server_socket_unix(const char *path, int access_mask);
0
+static void client_init(ebb_client *client);
0
+static void set_nonblock(int fd)
0
+ int flags = fcntl(fd, F_GETFL, 0);
0
+ assert(0 <= fcntl(fd, F_SETFL, flags | O_NONBLOCK) && "Setting socket non-block failed!");
0
void env_add(ebb_client *client, const char *field, int flen, const char *value, int vlen)
0
@@ -73,6 +81,16 @@ void http_field_cb(void *data, const char *field, size_t flen, const char *value
0
void on_element(void *data, int type, const char *at, size_t length)
0
ebb_client *client = (ebb_client*)(data);
0
+ case MONGREL_HTTP_VERSION:
0
+ /* "HTTP/1.1" by default is keep-alive true, otherwise not*/
0
+ /* note that the version will always come first */
0
+ client->keep_alive = (strncmp(at+5, "1.1", 3) == 0);
0
+ case MONGREL_CONNECTION:
0
+ client->keep_alive = (strncmp(at, "close", 5) != 0);
0
env_add_const(client, type, at, length);
0
@@ -83,6 +101,12 @@ static void dispatch(ebb_client *client)
0
if(client->open == FALSE)
0
+ /* decide if to use keep-alive or not */
0
server->request_cb(client, server->request_cb_data);
0
@@ -118,9 +142,9 @@ static void* read_body_into_file(void *_client)
0
int flags = fcntl(client->fd, F_GETFL, 0);
0
assert(0 <= fcntl(client->fd, F_SETFL, flags & ~O_NONBLOCK));
0
- sprintf(client->upload_file_filename, "/tmp/ebb_upload_%010d", id++);
0
- tmpfile = fopen(client->upload_file_filename, "w+");
0
- if(tmpfile == NULL) g_message("Cannot open tmpfile %s", client->upload_file_filename);
0
+ sprintf(client->upload_filename, "/tmp/ebb_upload_%010d", id++);
0
+ tmpfile = fopen(client->upload_filename, "w+");
0
+ if(tmpfile == NULL) g_message("Cannot open tmpfile %s", client->upload_filename);
0
client->upload_file = tmpfile;
0
size_t body_head_length = client->read - client->parser.nread;
0
@@ -164,7 +188,7 @@ static void* read_body_into_file(void *_client)
0
- // g_debug("%d bytes written to file %s", written, client->upload_file_filename);
0
+ // g_debug("%d bytes written to file %s", written, client->upload_filename);
0
@@ -188,7 +212,7 @@ static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents
0
, EBB_BUFFERSIZE - client->read
0
- if(read < 0) goto error;
0
+ if(read < 0) goto error;
0
if(read == 0) goto error; /* XXX is this the right action to take for read==0 ? */
0
ev_timer_again(loop, &client->timeout_watcher);
0
@@ -222,7 +246,9 @@ static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents
0
if(read < 0) g_message("Error recving data: %s", strerror(errno));
0
ebb_client_close(client);
0
@@ -265,12 +291,17 @@ static void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents
0
assert(client->written <= client->response_buffer->len);
0
//g_message("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
0
- ev_timer_again(loop, &(client->timeout_watcher));
0
+ ev_timer_again(loop, &client->timeout_watcher);
0
if(client->written == client->response_buffer->len) {
0
+ /* stop the write watcher. to be restarted by the next call to ebb_client_write_body
0
+ * or if client->body_written is set (by using ebb_client_release) then
0
+ * we close the connection
0
ev_io_stop(loop, watcher);
0
- if(client->body_written)
0
- ebb_client_close(client);
0
+ if(client->body_written) {
0
+ client->keep_alive ? client_init(client) : ebb_client_close(client);
0
@@ -278,15 +309,26 @@ error:
0
-static client_init(ebb_client *client, int fd)
0
+static void client_init(ebb_client *client)
0
assert(client->in_use == FALSE);
0
+ /* If the client is already open, reuse the fd, just reset all the parameters
0
+ * this would happen in the case of a keep_alive request
0
+ int fd = accept(client->server->fd, (struct sockaddr*)&(client->server->sockaddr), &len);
0
- int flags = fcntl(client->fd, F_GETFL, 0);
0
- assert(0 <= fcntl(client->fd, F_SETFL, flags | O_NONBLOCK));
0
+ set_nonblock(client->fd);
0
/* INITIALIZE http_parser */
0
http_parser_init(&client->parser);
0
@@ -297,15 +339,18 @@ static client_init(ebb_client *client, int fd)
0
client->read = client->nread_from_body = 0;
0
- client->response_buffer->len = 0; /* see note in ebb_client_close */
0
if(client->request_buffer == NULL) {
0
+ /* Only allocate the request_buffer once */
0
client->request_buffer = (char*)malloc(EBB_BUFFERSIZE);
0
- client->status_written = FALSE;
0
- client->headers_written = FALSE;
0
- client->body_written = FALSE;
0
+ client->keep_alive = TRUE;
0
+ client->status_written = client->headers_written = client->body_written = FALSE;
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 - presumably
0
+ * because the backend is going to keep sending such long requests.
0
+ client->response_buffer->len = 0;
0
/* SETUP READ AND TIMEOUT WATCHERS */
0
client->write_watcher.data = client;
0
@@ -325,12 +370,6 @@ static client_init(ebb_client *client, int fd)
0
-static client_reinit(ebb_client *client)
0
- client_init(client, client->fd);
0
static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
0
ebb_server *server = (ebb_server*)(watcher->data);
0
@@ -368,15 +407,7 @@ static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
0
g_debug("%d open connections", count);
0
- int client_fd = accept(server->fd, (struct sockaddr*)&(server->sockaddr), &len);
0
- client_init(client, client_fd);
0
@@ -454,11 +485,7 @@ int ebb_server_listen_on_port(ebb_server *server, const int port)
0
- flags = fcntl(sfd, F_GETFL, 0);
0
- if(fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
0
- perror("setting O_NONBLOCK");
0
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
0
@@ -532,16 +559,9 @@ void ebb_client_close(ebb_client *client)
0
if(client->upload_file) {
0
fclose(client->upload_file);
0
- unlink(client->upload_file_filename);
0
+ unlink(client->upload_filename);
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->response_buffer->len = 0;
0
@@ -582,6 +602,7 @@ void ebb_client_write_body(ebb_client *client, const char *data, int length)
0
if(client->headers_written == FALSE) {
0
g_string_append(client->response_buffer, "\r\n");
0
+ client->headers_written = TRUE;
0
g_string_append_len(client->response_buffer, data, length);
0
@@ -590,11 +611,7 @@ void ebb_client_write_body(ebb_client *client, const char *data, int length)
0
* we're streaming and the watcher has been stopped. In that case we
0
* start it again since we have more to write. */
0
if(ev_is_active(&client->write_watcher) == FALSE) {
0
- /* assure the socket is still in non-blocking mode */
0
- int flags = fcntl(client->fd, F_GETFL, 0);
0
- if(0 > fcntl(client->fd, F_SETFL, flags | O_NONBLOCK))
0
- perror("fcntl() setting non-block");
0
- client->headers_written = TRUE;
0
+ set_nonblock(client->fd);
0
ev_io_start(client->server->loop, &client->write_watcher);
Comments
No one has commented yet.