Added a timeout watcher to TCP class - probably isn't working properly yet.
[ebb.git] / ebb.c
blob85f986011ae800bd859de9c8269021211c644536
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 <pthread.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"
17 #include "ebb.h"
19 void* ebb_handle_request(void *_client);
21 ebb_server* ebb_server_new()
23 ebb_server *server = g_new0(ebb_server, 1);
24 server->socket = tcp_server_new();
25 return server;
28 void ebb_server_free(ebb_server *server)
30 tcp_server_free(server->socket);
33 void ebb_server_stop(ebb_server *server)
35 tcp_server_close(server->socket);
38 void ebb_on_read(char *buffer, int length, void *_client)
40 ebb_client *client = (ebb_client*)(_client);
42 assert(client->socket->open);
43 assert(!http_parser_is_finished(client->parser));
45 g_string_append_len(client->buffer, buffer, length);
47 http_parser_execute( client->parser
48 , client->buffer->str
49 , client->buffer->len
50 , client->parser->nread
53 if(http_parser_is_finished(client->parser)) {
54 pthread_t thread; // = g_new(pthread_t, 1);
55 pthread_attr_t attr;
56 pthread_attr_init(&attr);
57 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
58 int rc = pthread_create(&thread, &attr, ebb_handle_request, client);
59 if(rc < 0)
60 ebb_error("Could not create thread.");
64 const char *ebb_input = "ebb.input";
65 const char *server_name = "SERVER_NAME";
66 const char *server_port = "SERVER_PORT";
67 /* User is responsible for freeing the client */
68 void* ebb_handle_request(void *_client)
70 ebb_client *client = (ebb_client*)(_client);
72 g_queue_push_head(client->env,
73 ebb_env_pair_new(ebb_input, strlen(ebb_input), client->buffer->str, client->buffer->len));
75 g_queue_push_head(client->env, ebb_env_pair_new2(server_name,
76 tcp_server_address(client->server->socket)));
78 g_queue_push_head(client->env, ebb_env_pair_new2(server_port,
79 client->server->socket->port_s));
81 client->server->request_cb(client, client->server->request_cb_data);
82 /* Cannot access client beyond this point because it's possible that the
83 * user has freed it.
86 pthread_exit(NULL);
87 return NULL;
91 void ebb_on_request(tcp_client *socket, void *data)
93 ebb_server *server = (ebb_server*)(data);
94 ebb_client *client = ebb_client_new(server, socket);
96 assert(client->socket->open);
97 assert(server->socket->open);
99 socket->read_cb = ebb_on_read;
100 socket->read_cb_data = client;
103 void ebb_server_start( ebb_server *server
104 , char *host
105 , int port
106 , ebb_request_cb_t request_cb
107 , void *request_cb_data
110 server->request_cb = request_cb;
111 server->request_cb_data = request_cb_data;
112 tcp_server_listen(server->socket, host, port, 950, ebb_on_request, server);
115 #include "parser_callbacks.h"
117 ebb_client* ebb_client_new(ebb_server *server, tcp_client *socket)
119 ebb_client *client = g_new0(ebb_client, 1);
121 client->server = server;
122 client->socket = socket;
124 /* http_parser */
125 client->parser = g_new0(http_parser, 1);
126 http_parser_init(client->parser);
127 client->parser->data = client;
128 client->parser->http_field = ebb_http_field_cb;
129 client->parser->request_method = ebb_request_method_cb;
130 client->parser->request_uri = ebb_request_uri_cb;
131 client->parser->fragment = ebb_fragment_cb;
132 client->parser->request_path = ebb_request_path_cb;
133 client->parser->query_string = ebb_query_string_cb;
134 client->parser->http_version = ebb_http_version_cb;
135 client->parser->header_done = ebb_header_done_cb;
137 /* buffer */
138 client->buffer = g_string_new("");
140 /* env */
141 client->env = g_queue_new();
143 return client;
146 void ebb_client_close(ebb_client *client)
148 assert(client->socket->open);
149 tcp_client_close(client->socket);
152 void ebb_client_free(ebb_client *client)
154 tcp_client_free(client->socket);
156 /* http_parser */
157 http_parser_finish(client->parser);
158 free(client->parser);
160 /* buffer */
161 g_string_free(client->buffer, TRUE);
163 /* env */
164 ebb_env_pair *pair;
165 while((pair = g_queue_pop_head(client->env)))
166 ebb_env_pair_free(pair);
167 g_queue_free(client->env);
169 free(client);
171 //g_debug("ebb client freed");
174 // writes to the client
175 int ebb_client_write(ebb_client *this, const char *data, int length)
177 return tcp_client_write(this->socket, data, length);
181 ebb_env_pair* ebb_env_pair_new(const char *field, size_t flen, const char *value, size_t vlen)
183 ebb_env_pair *pair = g_new(ebb_env_pair, 1);
184 pair->field = field;
185 pair->flen = flen;
186 pair->value = value;
187 pair->vlen = vlen;
188 return pair;