0
+#include <netinet/tcp.h>
0
#define min(a,b) (a < b ? a : b)
0
#define ramp(a) (a > 0 ? a : 0)
0
+static int server_socket(const int port);
0
+static int server_socket_unix(const char *path, int access_mask);
0
#define env_add(client, field,flen,value,vlen) \
0
client->env_fields[client->env_size] = field; \
0
client->env_field_lengths[client->env_size] = flen; \
0
/* Set the env variables */
0
- env_add_const(client, EBB_SERVER_NAME
0
- , strlen(server->address)
0
- env_add_const(client, EBB_SERVER_PORT
0
- , strlen(server->port)
0
+ // env_add_const(client, EBB_SERVER_NAME
0
+ // , strlen(server->address)
0
+ // env_add_const(client, EBB_SERVER_PORT
0
+ // , strlen(server->port)
0
server->request_cb(client, server->request_cb_data);
0
ebb_server *server = (ebb_server*)(watcher->data);
0
assert(server->loop == loop);
0
- assert(
server->request_watcher == watcher);
0
+ assert(
&server->request_watcher == watcher);
0
if(EV_ERROR & revents) {
0
ebb_info("on_request() got error event, closing server.");
0
ebb_server_unlisten(server);
0
/* Now we're going to initialize the client
0
* and set up her callbacks for read and write
0
* the client won't get passed back to the user, however,
0
* until the request is complete and parsed.
0
/* Get next availible peer */
0
int flags = fcntl(client->fd, F_GETFL, 0);
0
assert(0 <= fcntl(client->fd, F_SETFL, flags | O_NONBLOCK));
0
- /* INITIALIZE
inline http_parser */
0
+ /* INITIALIZE
http_parser */
0
http_parser_init(&(client->parser));
0
client->parser.data = client;
0
client->parser.http_field = http_field_cb;
0
void ebb_server_init( ebb_server *server
0
, ebb_request_cb request_cb
0
, void *request_cb_data
0
- /* SETUP SOCKET STUFF */
0
- server->fd = socket(PF_INET, SOCK_STREAM, 0);
0
- int r = fcntl(server->fd, F_SETFL, O_NONBLOCK);
0
for(i=0; i < EBB_MAX_CLIENTS; i++)
0
server->clients[i].write_buffer = g_string_new("");
0
- r = setsockopt(server->fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
0
- server->sockaddr.sin_family = AF_INET;
0
- server->sockaddr.sin_port = htons(port);
0
- server->address = strdup(address); /* TODO: use looked up address? */
0
- server->port = malloc(sizeof(char)*8); /* for easy access to the port */
0
- sprintf(server->port, "%d", port);
0
- server->dns_info = gethostbyname(address);
0
- if (!(server->dns_info && server->dns_info->h_addr)) {
0
- ebb_error("Could not look up hostname %s", address);
0
- memmove( &(server->sockaddr.sin_addr)
0
- , server->dns_info->h_addr
0
- , sizeof(struct in_addr)
0
server->request_cb = request_cb;
0
server->request_cb_data = request_cb_data;
0
ebb_server_free(server);
0
g_string_free(server->clients[i].write_buffer, TRUE);
0
- free(server->address);
0
- free(server->dns_info);
0
+ if(server->socketpath)
0
+ free(server->socketpath);
0
for(i=0; i < EBB_MAX_CLIENTS; i++)
0
ebb_client_close(client);
0
- if(server->request_watcher) {
0
- ev_io_stop(server->loop, server->request_watcher);
0
- free(server->request_watcher);
0
- server->request_watcher = NULL;
0
+ ev_io_stop(server->loop, &server->request_watcher);
0
void ebb_server_listen(ebb_server *server)
0
- int r = bind( server->fd
0
- , (struct sockaddr*)&(server->sockaddr)
0
- , sizeof(server->sockaddr)
0
- ebb_error("Failed to bind to %s %s", server->address, server->port);
0
- ebb_server_unlisten(server);
0
- r = listen(server->fd, EBB_MAX_CLIENTS);
0
+ int r = listen(server->fd, EBB_MAX_CLIENTS);
0
assert(server->open == FALSE);
0
- server->request_watcher = g_new0(ev_io, 1);
0
- server->request_watcher->data = server;
0
- ev_init (server->request_watcher, on_request);
0
- ev_io_set (server->request_watcher, server->fd, EV_READ | EV_ERROR);
0
- ev_io_start (server->loop, server->request_watcher);
0
+ server->request_watcher.data = server;
0
+ ev_init (&server->request_watcher, on_request);
0
+ ev_io_set (&server->request_watcher, server->fd, EV_READ | EV_ERROR);
0
+ ev_io_start (server->loop, &server->request_watcher);
0
+int ebb_server_listen_on_port(ebb_server *server, const int port)
0
+ int fd = server_socket(port);
0
+ server->port = malloc(sizeof(char)*8); /* for easy access to the port */
0
+ sprintf(server->port, "%d", port);
0
+ ebb_server_listen(server);
0
+int ebb_server_listen_on_socket(ebb_server *server, const char *socketpath)
0
+ int fd = server_socket_unix(socketpath, 0x700);
0
+ server->socketpath = strdup(socketpath);
0
+ ebb_server_listen(server);
0
void ebb_client_close(ebb_client *client)
0
void ebb_on_writable( struct ev_loop *loop
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
ev_io_start(client->server->loop, &(client->write_watcher));
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
client->nread_from_body += read;
0
+/* The following socket creation routines are modified and stolen from memcached */
0
+static int server_socket(const int port) {
0
+ struct linger ling = {0, 0};
0
+ struct sockaddr_in addr;
0
+ if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
0
+ if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
0
+ 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
+ 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
0
+ * that otherwise mess things up.
0
+ memset(&addr, 0, sizeof(addr));
0
+ addr.sin_family = AF_INET;
0
+ addr.sin_port = htons(port);
0
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
0
+ if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
0
+ if (listen(sfd, EBB_MAX_CLIENTS) == -1) {
0
+static int server_socket_unix(const char *path, int access_mask) {
0
+ struct linger ling = {0, 0};
0
+ struct sockaddr_un addr;
0
+ if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
0
+ if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
0
+ fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
0
+ perror("setting O_NONBLOCK");
0
+ * Clean up a previous socket file if we left it around
0
+ if (lstat(path, &tstat) == 0) {
0
+ if (S_ISSOCK(tstat.st_mode))
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
+ * the memset call clears nonstandard fields in some impementations
0
+ * that otherwise mess things up.
0
+ memset(&addr, 0, sizeof(addr));
0
+ addr.sun_family = AF_UNIX;
0
+ strcpy(addr.sun_path, path);
0
+ old_umask=umask( ~(access_mask&0777));
0
+ if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
0
+ if (listen(sfd, 1024) == -1) {
Comments
No one has commented yet.