python-wsgi binding is working (to some extent)
[ebb.git] / src / ebb.c
bloba64439b60de0008cce59ae58d92c7f00092958e6
1 /* The Ebb Web Server
2 * Copyright (c) 2008 Ry Dahl. This software is released under the MIT
3 * License. See README file for details.
4 */
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/types.h>
8 #include <arpa/inet.h>
9 #include <netinet/tcp.h>
10 #include <sys/un.h>
11 #include <netdb.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include <assert.h>
20 #include <pthread.h>
21 #include <glib.h>
23 #define EV_STANDALONE 1
24 #include <ev.c>
26 #include "parser.h"
27 #include "ebb.h"
29 #define min(a,b) (a < b ? a : b)
30 #define ramp(a) (a > 0 ? a : 0)
32 static int server_socket(const int port);
33 static int server_socket_unix(const char *path, int access_mask);
35 void env_add(ebb_client *client, const char *field, int flen, const char *value, int vlen)
37 if(client->env_size >= EBB_MAX_ENV) {
38 client->parser.overflow_error = TRUE;
39 return;
41 client->env[client->env_size].type = EBB_FIELD_VALUE_PAIR;
42 client->env[client->env_size].field = field;
43 client->env[client->env_size].field_length = flen;
44 client->env[client->env_size].value = value;
45 client->env[client->env_size].value_length = vlen;
46 client->env_size += 1;
50 void env_add_const(ebb_client *client, int type, const char *value, int vlen)
52 if(client->env_size >= EBB_MAX_ENV) {
53 client->parser.overflow_error = TRUE;
54 return;
56 client->env[client->env_size].type = type;
57 client->env[client->env_size].field = NULL;
58 client->env[client->env_size].field_length = -1;
59 client->env[client->env_size].value = value;
60 client->env[client->env_size].value_length = vlen;
61 client->env_size += 1;
65 void http_field_cb(void *data, const char *field, size_t flen, const char *value, size_t vlen)
67 ebb_client *client = (ebb_client*)(data);
68 assert(field != NULL);
69 assert(value != NULL);
70 env_add(client, field, flen, value, vlen);
74 void request_method_cb(void *data, const char *at, size_t length)
76 ebb_client *client = (ebb_client*)(data);
77 env_add_const(client, EBB_REQUEST_METHOD, at, length);
81 void request_uri_cb(void *data, const char *at, size_t length)
83 ebb_client *client = (ebb_client*)(data);
84 env_add_const(client, EBB_REQUEST_URI, at, length);
88 void fragment_cb(void *data, const char *at, size_t length)
90 ebb_client *client = (ebb_client*)(data);
91 env_add_const(client, EBB_FRAGMENT, at, length);
95 void request_path_cb(void *data, const char *at, size_t length)
97 ebb_client *client = (ebb_client*)(data);
98 env_add_const(client, EBB_REQUEST_PATH, at, length);
102 void query_string_cb(void *data, const char *at, size_t length)
104 ebb_client *client = (ebb_client*)(data);
105 env_add_const(client, EBB_QUERY_STRING, at, length);
109 void http_version_cb(void *data, const char *at, size_t length)
111 ebb_client *client = (ebb_client*)(data);
112 env_add_const(client, EBB_HTTP_VERSION, at, length);
116 void content_length_cb(void *data, const char *at, size_t length)
118 ebb_client *client = (ebb_client*)(data);
119 env_add_const(client, EBB_CONTENT_LENGTH, at, length);
120 /* atoi_length - why isn't this in the statndard library? i hate c */
121 int i, mult;
122 for(mult=1, i=length-1; i>=0; i--, mult*=10)
123 client->content_length += (at[i] - '0') * mult;
127 const char* localhost_str = "0.0.0.0";
128 void dispatch(ebb_client *client)
130 ebb_server *server = client->server;
132 if(client->open == FALSE)
133 return;
135 /* Set the env variables */
136 if(server->port) {
137 env_add_const(client, EBB_SERVER_NAME
138 , localhost_str
141 env_add_const(client, EBB_SERVER_PORT
142 , server->port
143 , strlen(server->port)
146 server->request_cb(client, server->request_cb_data);
150 void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
152 ebb_client *client = (ebb_client*)(watcher->data);
154 assert(client->server->loop == loop);
155 assert(&(client->timeout_watcher) == watcher);
157 ebb_client_close(client);
158 #ifdef DEBUG
159 g_message("peer timed out");
160 #endif
163 #define client_finished_parsing http_parser_is_finished(&client->parser)
164 #define total_request_size (client->content_length + client->parser.nread)
166 void* read_body_into_file(void *_client)
168 ebb_client *client = (ebb_client*)_client;
169 static unsigned int id;
170 FILE *tmpfile;
172 assert(client->open);
173 assert(client->server->open);
174 assert(client->content_length > 0);
175 assert(client_finished_parsing);
177 /* set blocking socket */
178 int flags = fcntl(client->fd, F_GETFL, 0);
179 assert(0 <= fcntl(client->fd, F_SETFL, flags & ~O_NONBLOCK));
181 sprintf(client->upload_file_filename, "/tmp/ebb_upload_%010d", id++);
182 tmpfile = fopen(client->upload_file_filename, "w+");
183 if(tmpfile == NULL) g_message("Cannot open tmpfile %s", client->upload_file_filename);
184 client->upload_file = tmpfile;
186 size_t body_head_length = client->read - client->parser.nread;
187 size_t written = 0, r;
188 while(written < body_head_length) {
189 r = fwrite( client->request_buffer + sizeof(char)*(client->parser.nread + written)
190 , sizeof(char)
191 , body_head_length - written
192 , tmpfile
194 if(r <= 0) {
195 ebb_client_close(client);
196 return NULL;
198 written += r;
201 int bufsize = 5*1024;
202 char buffer[bufsize];
203 size_t received;
204 while(written < client->content_length) {
205 received = recv(client->fd
206 , buffer
207 , min(client->content_length - written, bufsize)
210 if(received < 0) goto error;
211 client->read += received;
213 ssize_t w = 0;
214 int rv;
215 while(w < received) {
216 rv = fwrite( buffer + w*sizeof(char)
217 , sizeof(char)
218 , received - w
219 , tmpfile
221 if(rv <= 0) goto error;
222 w += rv;
224 written += received;
226 rewind(tmpfile);
227 // g_debug("%d bytes written to file %s", written, client->upload_file_filename);
228 dispatch(client);
229 return NULL;
230 error:
231 ebb_client_close(client);
232 return NULL;
236 void on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
238 ebb_client *client = (ebb_client*)(watcher->data);
240 assert(client->open);
241 assert(client->server->open);
242 assert(client->server->loop == loop);
243 assert(&client->read_watcher == watcher);
245 ssize_t read = recv( client->fd
246 , client->request_buffer + client->read
247 , EBB_BUFFERSIZE - client->read
250 if(read < 0) goto error; /* XXX is this the right action to take for read==0 ? */
251 if(read == 0) return;
252 client->read += read;
253 ev_timer_again(loop, &client->timeout_watcher);
255 if(client->read == EBB_BUFFERSIZE) goto error;
257 if(FALSE == client_finished_parsing) {
258 http_parser_execute( &client->parser
259 , client->request_buffer
260 , client->read
261 , client->parser.nread
263 if(http_parser_has_error(&client->parser)) goto error;
266 if(client_finished_parsing) {
267 if(total_request_size == client->read) {
268 ev_io_stop(loop, watcher);
269 client->nread_from_body = 0;
270 dispatch(client);
271 return;
273 if(total_request_size > EBB_BUFFERSIZE ) {
274 /* read body into file - in a thread */
275 ev_io_stop(loop, watcher);
276 pthread_t thread;
277 assert(0 <= pthread_create(&thread, NULL, read_body_into_file, client));
278 pthread_detach(thread);
279 return;
282 return;
283 error:
284 if(read < 0) g_message("Error recving data: %s", strerror(errno));
285 ebb_client_close(client);
289 void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
291 ebb_server *server = (ebb_server*)(watcher->data);
292 assert(server->open);
293 assert(server->loop == loop);
294 assert(&server->request_watcher == watcher);
296 if(EV_ERROR & revents) {
297 g_message("on_request() got error event, closing server.");
298 ebb_server_unlisten(server);
299 return;
301 /* Now we're going to initialize the client
302 * and set up her callbacks for read and write
303 * the client won't get passed back to the user, however,
304 * until the request is complete and parsed.
306 int i;
307 ebb_client *client;
308 /* Get next availible peer */
309 for(i=0; i < EBB_MAX_CLIENTS; i++)
310 if(!server->clients[i].open) {
311 client = &(server->clients[i]);
312 break;
314 if(client == NULL) {
315 g_message("Too many peers. Refusing connections.");
316 return;
319 #ifdef DEBUG
320 int count = 0;
321 for(i = 0; i < EBB_MAX_CLIENTS; i++)
322 if(server->clients[i].open) count += 1;
323 g_debug("%d open connections", count);
325 /* does ragel fuck up if request buffer isn't null? */
326 for(i=0; i< EBB_BUFFERSIZE; i++)
327 client->request_buffer[i] = 'A';
328 #endif
330 client->open = TRUE;
331 client->server = server;
333 /* DO SOCKET STUFF */
334 socklen_t len;
335 client->fd = accept(server->fd, (struct sockaddr*)&(server->sockaddr), &len);
336 assert(client->fd >= 0);
337 int flags = fcntl(client->fd, F_GETFL, 0);
338 assert(0 <= fcntl(client->fd, F_SETFL, flags | O_NONBLOCK));
340 /* INITIALIZE http_parser */
341 http_parser_init(&(client->parser));
342 client->parser.data = client;
343 client->parser.http_field = http_field_cb;
344 client->parser.request_method = request_method_cb;
345 client->parser.request_uri = request_uri_cb;
346 client->parser.fragment = fragment_cb;
347 client->parser.request_path = request_path_cb;
348 client->parser.query_string = query_string_cb;
349 client->parser.http_version = http_version_cb;
350 client->parser.content_length = content_length_cb;
352 /* OTHER */
354 client->env_size = 0;
355 client->read = client->nread_from_body = 0;
356 client->response_buffer->len = 0; /* see note in ebb_client_close */
357 client->content_length = 0;
359 client->status_sent = FALSE;
360 client->headers_sent = FALSE;
361 client->body_sent = FALSE;
363 /* SETUP READ AND TIMEOUT WATCHERS */
364 client->read_watcher.data = client;
365 ev_init(&client->read_watcher, on_readable);
366 ev_io_set(&client->read_watcher, client->fd, EV_READ | EV_ERROR);
367 ev_io_start(server->loop, &client->read_watcher);
369 client->timeout_watcher.data = client;
370 ev_timer_init(&client->timeout_watcher, on_timeout, EBB_TIMEOUT, EBB_TIMEOUT);
371 ev_timer_start(server->loop, &client->timeout_watcher);
375 ebb_server* ebb_server_alloc()
377 ebb_server *server = g_new0(ebb_server, 1);
378 return server;
382 void ebb_server_init( ebb_server *server
383 , struct ev_loop *loop
384 , ebb_request_cb request_cb
385 , void *request_cb_data
388 int i;
389 for(i=0; i < EBB_MAX_CLIENTS; i++)
390 server->clients[i].response_buffer = g_string_new("");
392 server->request_cb = request_cb;
393 server->request_cb_data = request_cb_data;
394 server->loop = loop;
395 server->open = FALSE;
396 server->fd = -1;
397 return;
398 error:
399 ebb_server_free(server);
400 return;
404 void ebb_server_free(ebb_server *server)
406 ebb_server_unlisten(server);
408 int i;
409 for(i=0; i < EBB_MAX_CLIENTS; i++)
410 g_string_free(server->clients[i].response_buffer, TRUE);
411 if(server->port)
412 free(server->port);
413 if(server->socketpath)
414 free(server->socketpath);
415 free(server);
419 void ebb_server_unlisten(ebb_server *server)
421 if(server->open) {
422 int i;
423 ebb_client *client;
424 ev_io_stop(server->loop, &server->request_watcher);
425 close(server->fd);
426 if(server->socketpath)
427 unlink(server->socketpath);
428 server->open = FALSE;
433 void ebb_server_listen(ebb_server *server)
435 int r = listen(server->fd, EBB_MAX_CLIENTS);
436 assert(r >= 0);
437 assert(server->open == FALSE);
438 server->open = TRUE;
440 server->request_watcher.data = server;
441 ev_init (&server->request_watcher, on_request);
442 ev_io_set (&server->request_watcher, server->fd, EV_READ | EV_ERROR);
443 ev_io_start (server->loop, &server->request_watcher);
447 int ebb_server_listen_on_port(ebb_server *server, const int port)
449 int fd = server_socket(port);
450 if(fd < 0) return 0;
451 server->port = malloc(sizeof(char)*8); /* for easy access to the port */
452 sprintf(server->port, "%d", port);
453 server->fd = fd;
454 ebb_server_listen(server);
455 return fd;
459 int ebb_server_listen_on_socket(ebb_server *server, const char *socketpath)
461 int fd = server_socket_unix(socketpath, 0755);
462 if(fd < 0) return 0;
463 server->socketpath = strdup(socketpath);
464 server->fd = fd;
465 ebb_server_listen(server);
466 return fd;
470 void ebb_client_close(ebb_client *client)
472 if(client->open) {
473 ev_io_stop(client->server->loop, &client->read_watcher);
474 ev_io_stop(client->server->loop, &client->write_watcher);
475 ev_timer_stop(client->server->loop, &client->timeout_watcher);
477 if(client->upload_file) {
478 fclose(client->upload_file);
479 unlink(client->upload_file_filename);
482 /* here we do not free the already allocated GString client->response_buffer
483 * that we're holding the response in. we reuse it again -
484 * presumably because the backend is going to keep sending such long
485 * requests.
487 client->response_buffer->len = 0;
489 close(client->fd);
490 client->open = FALSE;
495 void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
497 ebb_client *client = (ebb_client*)(watcher->data);
498 ssize_t sent;
500 if(EV_ERROR & revents) {
501 g_message("on_client_writable() got error event, closing peer");
502 return;
505 //if(client->written != 0)
506 // g_debug("total written: %d", (int)(client->written));
508 sent = send( client->fd
509 , client->response_buffer->str + sizeof(gchar)*(client->written)
510 , client->response_buffer->len - client->written
513 if(sent < 0) {
514 #ifdef DEBUG
515 g_message("Error writing: %s", strerror(errno));
516 #endif
517 ebb_client_close(client);
518 return;
520 client->written += sent;
522 assert(client->written <= client->response_buffer->len);
523 //g_message("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
525 ev_timer_again(loop, &(client->timeout_watcher));
527 if(client->written == client->response_buffer->len)
528 ebb_client_close(client);
531 void ebb_client_write_status(ebb_client *client, int status, const char *human_status)
533 assert(client->status_sent == FALSE);
534 g_string_append_printf( client->response_buffer
535 , "HTTP/1.1 %d %s\r\n"
536 , status
537 , human_status
539 client->status_sent = TRUE;
542 void ebb_client_write_header(ebb_client *client, const char *field, const char *value)
544 assert(client->status_sent == TRUE);
545 assert(client->headers_sent == FALSE);
546 g_string_append_printf( client->response_buffer
547 , "%s: %s\r\n"
548 , field
549 , value
553 void ebb_client_write(ebb_client *client, const char *data, int length)
555 g_string_append_len(client->response_buffer, data, length);
559 void ebb_client_finished(ebb_client *client)
561 assert(client->open);
562 assert(FALSE == ev_is_active(&(client->write_watcher)));
564 /* assure the socket is still in non-blocking mode
565 * in the ruby binding, for example, i change this flag
567 int flags = fcntl(client->fd, F_GETFL, 0);
568 if(0 > fcntl(client->fd, F_SETFL, flags | O_NONBLOCK)) {
569 perror("fcntl()");
570 ebb_client_close(client);
571 return;
574 client->written = 0;
575 client->write_watcher.data = client;
576 ev_init (&(client->write_watcher), on_client_writable);
577 ev_io_set (&(client->write_watcher), client->fd, EV_WRITE | EV_ERROR);
578 ev_io_start(client->server->loop, &(client->write_watcher));
582 /* pass an allocated buffer and the length to read. this function will try to
583 * fill the buffer with that length of data read from the body of the request.
584 * the return value says how much was actually written.
586 int ebb_client_read(ebb_client *client, char *buffer, int length)
588 size_t read;
590 assert(client->open);
591 assert(client_finished_parsing);
593 if(client->upload_file) {
594 read = fread(buffer, 1, length, client->upload_file);
595 /* TODO error checking! */
596 return read;
597 } else {
598 char* request_body = client->request_buffer + client->parser.nread;
600 read = ramp(min(length, client->content_length - client->nread_from_body));
601 memcpy( buffer
602 , request_body + client->nread_from_body
603 , read
605 client->nread_from_body += read;
606 return read;
610 /* The following socket creation routines are modified and stolen from memcached */
612 static int server_socket(const int port) {
613 int sfd;
614 struct linger ling = {0, 0};
615 struct sockaddr_in addr;
616 int flags =1;
618 if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
619 perror("socket()");
620 return -1;
623 if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
624 fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
625 perror("setting O_NONBLOCK");
626 close(sfd);
627 return -1;
630 flags = 1;
631 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
632 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
633 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
634 setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
637 * the memset call clears nonstandard fields in some impementations
638 * that otherwise mess things up.
640 memset(&addr, 0, sizeof(addr));
642 addr.sin_family = AF_INET;
643 addr.sin_port = htons(port);
644 addr.sin_addr.s_addr = htonl(INADDR_ANY);
646 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
647 perror("bind()");
648 close(sfd);
649 return -1;
651 if (listen(sfd, EBB_MAX_CLIENTS) == -1) {
652 perror("listen()");
653 close(sfd);
654 return -1;
656 return sfd;
660 static int server_socket_unix(const char *path, int access_mask) {
661 int sfd;
662 struct linger ling = {0, 0};
663 struct sockaddr_un addr;
664 struct stat tstat;
665 int flags =1;
666 int old_umask;
668 if (!path) {
669 return -1;
672 if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
673 perror("socket()");
674 return -1;
677 if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
678 fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
679 perror("setting O_NONBLOCK");
680 close(sfd);
681 return -1;
685 * Clean up a previous socket file if we left it around
687 if (lstat(path, &tstat) == 0) {
688 if (S_ISSOCK(tstat.st_mode))
689 unlink(path);
692 flags = 1;
693 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
694 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
695 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
698 * the memset call clears nonstandard fields in some impementations
699 * that otherwise mess things up.
701 memset(&addr, 0, sizeof(addr));
703 addr.sun_family = AF_UNIX;
704 strcpy(addr.sun_path, path);
705 old_umask=umask( ~(access_mask&0777));
706 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
707 perror("bind()");
708 close(sfd);
709 umask(old_umask);
710 return -1;
712 umask(old_umask);
713 if (listen(sfd, EBB_MAX_CLIENTS) == -1) {
714 perror("listen()");
715 close(sfd);
716 return -1;
718 return sfd;