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 /command.c |
Register working
Diffstat (limited to 'command.c')
-rw-r--r-- | command.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/command.c b/command.c new file mode 100644 index 0000000..deaeabe --- /dev/null +++ b/command.c @@ -0,0 +1,121 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <sys/socket.h> +#include "command.h" +#include "db.h" + + +static bool send_raw_text(int fd,const char *text,i64 len){ + i64 cursor=0; + while(cursor<len){ + i64 nwr=send(fd,text+cursor,len-cursor,0); + if(nwr<0){ + if(errno==EINTR)continue; + if(errno==ECONNRESET||errno==EPIPE)return true; + die_perror("send"); + } + cursor+=nwr; + } + return false; +} + +static bool send_ok(int fd,const char *tag){ + char *buf=NULL; + i64 len=asprintf(&buf,"%s ok\n",tag); + assert(buf); + bool closed=send_raw_text(fd,buf,len); + free(buf); + return closed; +} + +static bool send_error(int fd,const char *tag,const char *msg){ + char *buf=NULL; + i64 len=asprintf(&buf,"%s error %s\n",tag,msg); + assert(buf); + bool closed=send_raw_text(fd,buf,len); + free(buf); + return closed; +} + + +static bool cmd_register(int fd,const char *tag,const char **args){ + i64 userid=db_find_user(args[0]); + if(userid!=-1){ + send_error(fd,tag,"Username already exists"); + return false; + } + db_create_user(args[0],args[1]); + return send_ok(fd,tag); +} + +static bool cmd_login(int fd,const char *tag,const char **args){ + (void)fd; (void)tag; (void)args; + return true; +} + + +struct cmd_info{ + const char *cmdname; + int nargs; + bool longlast; // whether the last argument should span the rest of the input line + bool (*handler)(int fd,const char *tag,const char **args); +}; + +static const struct cmd_info commands[]={ + {"register",2,false,cmd_register}, + {"login",2,false,cmd_login}, +}; +#define NCOMMANDS (sizeof(commands)/sizeof(commands[0])) + + +bool handle_input_line(int fd,char *line,size_t linelen){ + char *sepp=memchr(line,' ',linelen); + if(sepp==NULL){ + debug("No space in input line from connection %d",fd); + return true; + } + char *tag=line; + size_t taglen=sepp-tag; + *sepp='\0'; + line+=taglen+1; + linelen-=taglen+1; + + sepp=memchr(line,' ',linelen); + if(sepp==NULL)sepp=line+linelen; + size_t cmdlen=sepp-line; + size_t cmdi; + for(cmdi=0;cmdi<NCOMMANDS;cmdi++){ + if(strncmp(line,commands[cmdi].cmdname,cmdlen)==0){ + break; + } + } + + int nargs=commands[cmdi].nargs; + char *args[nargs]; + size_t cursor=cmdlen+1; + + for(int i=0;i<nargs;i++){ + if(cursor>=linelen){ + debug("Connection %d sent too few parameters to command %s",fd,commands[cmdi].cmdname); + return true; + } + if(i==nargs-1&&commands[cmdi].longlast){ + sepp=line+linelen; + } else { + sepp=memchr(line+cursor,' ',linelen-cursor); + if(sepp==NULL)sepp=line+linelen; + } + *sepp='\0'; + args[i]=line+cursor; + cursor=sepp-line+1; + } + if(sepp-line<(i64)linelen){ + debug("Connection %d sent too many parameters to command %s",fd,commands[cmdi].cmdname); + return true; + } + + return commands[cmdi].handler(fd,tag,(const char**)args); +} |