Ignore SIGPIPE. (Wow that suddenly makes things usable!)
[ebb.git] / ebb.c
blob50c97c941069b8316b9f5bffccea447304399f86
1 /* Ebb Web Server
2 * Copyright (c) 2007 Ry Dahl
3 * This software is released under the "MIT License". See README file for details.
4 */
6 #include <glib.h>
7 #include <ev.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <assert.h>
13 #include <errno.h>
15 #include "mongrel/parser.h"
16 #include "tcp.h"
18 #include "ebb.h"
19 #include "parser_callbacks.h"
21 void* ebb_handle_request(void *_client);
23 ebb_server* ebb_server_new(struct ev_loop *loop)
25 ebb_server *server = g_new0(ebb_server, 1);
26 server->socket = tcp_listener_new(loop);
27 return server;
30 void ebb_server_free(ebb_server *server)
32 tcp_listener_free(server->socket);
35 void ebb_server_stop(ebb_server *server)
37 tcp_listener_close(server->socket);
40 void ebb_on_read(char *buffer, int length, void *_client)
42 ebb_client *client = (ebb_client*)(_client);
43 assert(client);
44 assert(client->socket);
45 assert(client->socket->open);
46 //assert(client->socket->open);
47 assert(!http_parser_is_finished(&(client->parser)));
49 g_string_append_len(client->buffer, buffer, length);
51 http_parser_execute( &(client->parser)
52 , client->buffer->str
53 , client->buffer->len
54 , client->parser.nread
57 if(http_parser_is_finished(&(client->parser))) {
58 ebb_handle_request(client);
63 /* User is responsible for freeing the client */
64 void* ebb_handle_request(void *_client)
66 const char *ebb_input = "ebb.input";
67 const char *server_name = "SERVER_NAME";
68 const char *server_port = "SERVER_PORT";
69 ebb_client *client = (ebb_client*)(_client);
71 assert(client);
72 assert(client->socket);
73 assert(client->socket->open);
75 g_queue_push_head(client->env,
76 ebb_env_pair_new(ebb_input, strlen(ebb_input), client->buffer->str, client->buffer->len));
78 g_queue_push_head(client->env, ebb_env_pair_new2(server_name,
79 tcp_listener_address(client->server->socket)));
81 g_queue_push_head(client->env, ebb_env_pair_new2(server_port,
82 client->server->socket->port_s));
84 client->server->request_cb(client, client->server->request_cb_data);
85 /* Cannot access client beyond this point because it's possible that the
86 * user has freed it.
89 return NULL;
93 void ebb_on_request(tcp_peer *socket, void *data)
95 ebb_server *server = (ebb_server*)(data);
96 ebb_client *client = ebb_client_new(server, socket);
98 assert(client->socket->open);
99 assert(server->socket->open);
101 socket->read_cb = ebb_on_read;
102 socket->read_cb_data = client;
105 void ebb_server_start( ebb_server *server
106 , char *host
107 , int port
108 , ebb_request_cb_t request_cb
109 , void *request_cb_data
112 server->request_cb = request_cb;
113 server->request_cb_data = request_cb_data;
114 tcp_listener_listen(server->socket, host, port, ebb_on_request, server);
117 ebb_client* ebb_client_new(ebb_server *server, tcp_peer *socket)
119 ebb_client *client = g_new0(ebb_client, 1);
121 client->server = server;
122 client->socket = socket;
124 /* http_parser */
125 http_parser_init(&(client->parser));
126 client->parser.data = client;
127 client->parser.http_field = ebb_http_field_cb;
128 client->parser.request_method = ebb_request_method_cb;
129 client->parser.request_uri = ebb_request_uri_cb;
130 client->parser.fragment = ebb_fragment_cb;
131 client->parser.request_path = ebb_request_path_cb;
132 client->parser.query_string = ebb_query_string_cb;
133 client->parser.http_version = ebb_http_version_cb;
134 client->parser.header_done = ebb_header_done_cb;
136 /* buffer */
137 client->buffer = g_string_new("");
139 /* env */
140 client->env = g_queue_new();
142 return client;
145 void ebb_client_close(ebb_client *client)
147 assert(client->socket->open);
148 tcp_peer_close(client->socket);
151 void ebb_client_free(ebb_client *client)
153 tcp_peer_close(client->socket);
155 /* http_parser */
156 http_parser_finish(&(client->parser));
158 /* buffer */
159 g_string_free(client->buffer, TRUE);
161 /* env */
162 ebb_env_pair *pair;
163 while((pair = g_queue_pop_head(client->env)))
164 ebb_env_pair_free(pair);
165 g_queue_free(client->env);
167 free(client);
170 // writes to the client
171 int ebb_client_write(ebb_client *this, const char *data, int length)
173 return tcp_peer_write(this->socket, data, length);
177 ebb_env_pair* ebb_env_pair_new(const char *field, size_t flen, const char *value, size_t vlen)
179 ebb_env_pair *pair = g_new(ebb_env_pair, 1);
180 pair->field = field;
181 pair->flen = flen;
182 pair->value = value;
183 pair->vlen = vlen;
184 return pair;