diff options
author | tomsmeding <tom.smeding@gmail.com> | 2017-03-14 11:05:35 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2017-03-14 11:05:35 +0100 |
commit | 54064158d84fc4006e651deb314cde156cc383e8 (patch) | |
tree | a534f160fe02b593143e03aaaf52f65513352c90 /main.c |
Register working
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 123 |
1 files changed, 123 insertions, 0 deletions
@@ -0,0 +1,123 @@ +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <unistd.h> +#include <errno.h> +#include <assert.h> +#include "command.h" +#include "conn_data.h" +#include "db.h" +#include "runloop.h" + +#define PORT (29536) // python: int("msg",36) + + +static int create_server_socket(void){ + int sock=socket(AF_INET,SOCK_STREAM,0); + if(sock<0)die_perror("socket"); + int one=1; + setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&one,sizeof one); + + struct sockaddr_in name; + name.sin_family=AF_INET; + name.sin_addr.s_addr=htonl(INADDR_ANY); + name.sin_port=htons(PORT); + if(bind(sock,(struct sockaddr*)&name,sizeof name)<0)die_perror("bind"); + + if(listen(sock,16)<0)die_perror("listen"); + return sock; +} + +struct hash_item{ + struct conn_data cd; + struct hash_item *next; +}; + +#define CONN_HASH_SIZE (16) +static struct hash_item *conn_hash[CONN_HASH_SIZE]; + +static struct conn_data* find_conn_data(int fd){ + struct hash_item *item=conn_hash[fd%CONN_HASH_SIZE]; + while(item&&item->cd.fd!=fd)item=item->next; + assert(item); + return &item->cd; +} + +static void delete_conn_data(int fd){ + struct hash_item *item=conn_hash[fd%CONN_HASH_SIZE]; + assert(item); + if(item->cd.fd==fd){ + conn_hash[fd%CONN_HASH_SIZE]=item->next; + conn_data_nullify(&item->cd); + free(item); + return; + } + struct hash_item *parent=NULL; + while(item&&item->cd.fd!=fd){ + parent=item; + item=item->next; + } + assert(parent); + assert(item); + conn_data_nullify(&item->cd); + parent->next=item->next; + free(item); +} + +static bool client_socket_callback(int fd){ + struct conn_data *data=find_conn_data(fd); + if(data->bufsz-data->buflen<256){ + data->bufsz*=2; + data->buffer=realloc(data->buffer,data->bufsz,char); + } + + ssize_t ret; + do ret=read(fd,data->buffer+data->buflen,data->bufsz-data->buflen); + while(ret<0&&errno==EINTR); + if(ret<0)die_perror("read"); + if(ret==0){ + delete_conn_data(fd); + close(fd); + return true; + } + data->buflen+=ret; + + char *lfp=memchr(data->buffer,'\n',data->buflen); + if(lfp==NULL)return false; + size_t length=lfp-data->buffer; + bool should_close=handle_input_line(fd,data->buffer,length); + memmove(data->buffer,lfp+1,data->buflen-length-1); + data->buflen-=length+1; + + if(should_close){ + delete_conn_data(fd); + close(fd); + return true; + } + return false; +} + +static bool server_socket_callback(int fd){ + int sock; + do sock=accept(fd,NULL,NULL); + while(sock<0&&errno==EINTR); + if(sock<0)die_perror("accept"); + runloop_add_fd(sock,client_socket_callback); + + struct hash_item *item=malloc(1,struct hash_item); + conn_data_init(&item->cd,sock); + item->next=conn_hash[sock%CONN_HASH_SIZE]; + conn_hash[sock%CONN_HASH_SIZE]=item; + debug("Added conn_data for fd=%d",sock); + return false; +} + +int main(void){ + db_init(); + int sock=create_server_socket(); + printf("Listening on port %d\n",PORT); + runloop_add_fd(sock,server_socket_callback); + runloop_run(); + db_close(); +} |