*** empty log message ***
This commit is contained in:
226
tecs/server.c
Normal file
226
tecs/server.c
Normal file
@@ -0,0 +1,226 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <assert.h>
|
||||
#include "logfile.h"
|
||||
#include "server.h"
|
||||
#include "util.h"
|
||||
|
||||
static buf_type *buf, *bufo;
|
||||
|
||||
static fd_set mask, rmask;
|
||||
static int maxfd;
|
||||
struct CocClient *cList, *cLastCmd=NULL;
|
||||
static int mainFd;
|
||||
|
||||
int CocInitServer(int bufsize, int port) {
|
||||
int i;
|
||||
struct sockaddr_in sadr;
|
||||
char *err;
|
||||
|
||||
if (bufsize==0) bufsize=1024;
|
||||
buf=buf_create(bufsize);
|
||||
bufo=buf_create(bufsize);
|
||||
cList=malloc(sizeof(*cList)); /* empty header */
|
||||
|
||||
/* first try to connect to an existing server */
|
||||
|
||||
logfileStamp("start server");
|
||||
|
||||
ERR_SI(mainFd=socket(AF_INET, SOCK_STREAM, 0));
|
||||
i = 1;
|
||||
ERR_SI(setsockopt(mainFd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */
|
||||
ERR_I(CocCreateSockAdr(&sadr, NULL, port));
|
||||
ERR_SI(bind(mainFd, (struct sockaddr *)&sadr, sizeof(sadr)));
|
||||
logfileOut("created server on port %d\n", port);
|
||||
ERR_SI(listen(mainFd, SOMAXCONN));
|
||||
FD_ZERO(&mask);
|
||||
FD_SET(mainFd, &mask);
|
||||
maxfd=mainFd+1;
|
||||
logfileUpd();
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int CocHandle1Request(int tmo_msec, int fd) {
|
||||
struct sockaddr_in cadr;
|
||||
struct hostent *h;
|
||||
struct timeval tmo={0,1};
|
||||
struct CocClient *cl, *cl0;
|
||||
int i, newfd, setmode, status;
|
||||
size_t cadrlen;
|
||||
char *err, *varname;
|
||||
|
||||
status=3;
|
||||
rmask=mask;
|
||||
if (fd>0) FD_SET(fd, &rmask);
|
||||
tmo.tv_sec=tmo_msec / 1000;
|
||||
tmo.tv_usec=(tmo_msec % 1000)*1000+1;
|
||||
if (fd>=maxfd) maxfd=fd+1;
|
||||
ERR_SI(i=select(maxfd,&rmask,NULL,NULL,&tmo));
|
||||
if (fd>0 && FD_ISSET(fd, &rmask)) return(1);
|
||||
|
||||
logfileStamp("");
|
||||
if (FD_ISSET(mainFd, &rmask)) {
|
||||
ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen));
|
||||
FD_SET(newfd, &mask);
|
||||
if (newfd>=maxfd) maxfd=newfd+1;
|
||||
cl=cList;
|
||||
cl->fd=newfd;
|
||||
cl->mode=0;
|
||||
cl->cmd[0]='\0';
|
||||
cl->res[0]='\0';
|
||||
cList=malloc(sizeof(*cList));
|
||||
cList->next=cl;
|
||||
h=gethostbyaddr(&cadr.sin_addr, 4, AF_INET);
|
||||
if (h==NULL) {
|
||||
logfileOut("(%d) open from %s\n", newfd, "local");
|
||||
} else {
|
||||
logfileOut("(%d) open from %s\n", newfd, h->h_name);
|
||||
}
|
||||
logfileUpd();
|
||||
} else {
|
||||
cl0=cList; cl=cl0->next;
|
||||
while (cl!=NULL) {
|
||||
if (FD_ISSET(cl->fd, &rmask)) {
|
||||
buf->usize=recv(cl->fd, buf->start, buf->isize, 0);
|
||||
if (buf->usize<=0) {
|
||||
logfileOut("(%d) disconnected\n",cl->fd);
|
||||
close(cl->fd);
|
||||
FD_CLR(cl->fd, &mask);
|
||||
cl0->next=cl->next;
|
||||
free(cl);
|
||||
cl=cl0;
|
||||
} else {
|
||||
if (buf->usize<0) ERR_MSG("usize negative");
|
||||
|
||||
buf_put_start(bufo);
|
||||
buf_put_str(bufo, ""); /* empty error message */
|
||||
setmode=0;
|
||||
buf_reset(buf);
|
||||
err=NULL;
|
||||
varname=buf_get_str(buf);
|
||||
logfileOutTmp("(%d) ", cl->fd);
|
||||
if (varname[0]=='#') { /* access code */
|
||||
if (0==strcmp(varname,"#rdacc")) {
|
||||
logfileOutTmp(" set read mode");
|
||||
cl->mode=1;
|
||||
} else if (0==strcmp(varname,"#rwacs")) {
|
||||
logfileOutTmp(" set write mode");
|
||||
cl->mode=2;
|
||||
} else {
|
||||
err="bad access code";
|
||||
}
|
||||
} else if (cl->mode==0) {
|
||||
err="no access";
|
||||
} else {
|
||||
while (1) {
|
||||
if (varname[0]=='[') {
|
||||
if (cl->mode<2) { err="no write access"; break; }
|
||||
setmode=1; /* switch to set mode */
|
||||
} else if (varname[0]==']') { /* switch to read mode */
|
||||
setmode=0;
|
||||
} else if (setmode) {
|
||||
if (0==strcmp("$", varname)) { /* special case: command */
|
||||
str_copy(cl->cmd, buf_get_str(buf));
|
||||
cl->res[0]='\0';
|
||||
} else {
|
||||
i=CocGetVar(serverVarList, buf, varname);
|
||||
if (i<0) { err=ErrMessage; break; }
|
||||
}
|
||||
status=2;
|
||||
} else {
|
||||
if (0==strcmp("$", varname)) { /* special case: response */
|
||||
buf_put_str(bufo, cl->res);
|
||||
cl->res[0]='\0';
|
||||
} else {
|
||||
i=CocPutVar(serverVarList, bufo, varname);
|
||||
if (i<0) { err=ErrMessage; break; }
|
||||
}
|
||||
}
|
||||
i=buf_size(buf);
|
||||
if (i<=0) {
|
||||
if (i<0) err="type mismatch";
|
||||
break;
|
||||
}
|
||||
varname=buf_get_str(buf);
|
||||
if (buf_size(buf)<0) { err="syntax error"; break; }
|
||||
}
|
||||
buf_reset(buf);
|
||||
logfileOutBuf(buf);
|
||||
}
|
||||
buf_put_end(bufo);
|
||||
logfileOutTmp(" |");
|
||||
logfileOutBuf(bufo);
|
||||
if (err==NULL) {
|
||||
logfileOutTmp("\n");
|
||||
} else {
|
||||
buf_put_start(bufo); /* reset output */
|
||||
buf_put_str(bufo, err); /* put error message */
|
||||
buf_put_end(bufo);
|
||||
logfileOutTmp(" (%s)\n", err);
|
||||
}
|
||||
ERR_SI(send(cl->fd, bufo->buf, bufo->size, 0));
|
||||
}
|
||||
}
|
||||
cl0=cl; cl=cl->next;
|
||||
}
|
||||
logfileUpd();
|
||||
}
|
||||
return(status);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int CocHandleRequests(int tmo_msec, int fd) {
|
||||
struct timeb tim1, tim0;
|
||||
int tdif, iret;
|
||||
|
||||
ftime(&tim0);
|
||||
tdif=tmo_msec;
|
||||
while (tdif>=0) {
|
||||
ERR_I(iret=CocHandle1Request(tdif, fd));
|
||||
if (iret==2 && fd==0) return(iret); /* a variable was changed */
|
||||
if (iret!=3) return(iret); /* event on fd or timeout */
|
||||
ftime(&tim1);
|
||||
tdif=tmo_msec-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm);
|
||||
}
|
||||
return(0); /* timeout */
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
struct CocClient *CocGetNextCmd() {
|
||||
struct CocClient *cl;
|
||||
|
||||
cl=cLastCmd;
|
||||
while (cl!=NULL) {
|
||||
if (cl->cmd[0]!='\0') {
|
||||
cLastCmd=cl->next;
|
||||
return(cl);
|
||||
}
|
||||
cl=cl->next;
|
||||
}
|
||||
cl=cList->next;
|
||||
while (cl!=NULL && cl!=cLastCmd) {
|
||||
if (cl->cmd[0]!='\0') {
|
||||
cLastCmd=cl->next;
|
||||
return(cl);
|
||||
}
|
||||
cl=cl->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void CocCloseServer() {
|
||||
struct CocClient *cl, *cl0;
|
||||
|
||||
cl=cList->next;
|
||||
while (cl!=NULL) {
|
||||
close(cl->fd);
|
||||
cl0=cl;
|
||||
cl=cl->next;
|
||||
free(cl0);
|
||||
}
|
||||
free(cList);
|
||||
close(mainFd);
|
||||
buf_free(buf); buf_free(bufo);
|
||||
logfileClose();
|
||||
}
|
||||
Reference in New Issue
Block a user