aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-03-14 11:05:35 +0100
committertomsmeding <tom.smeding@gmail.com>2017-03-14 11:05:35 +0100
commit54064158d84fc4006e651deb314cde156cc383e8 (patch)
treea534f160fe02b593143e03aaaf52f65513352c90 /main.c
Register working
Diffstat (limited to 'main.c')
-rw-r--r--main.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..1679f4b
--- /dev/null
+++ b/main.c
@@ -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();
+}