649 lines
16 KiB
C
649 lines
16 KiB
C
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
#include <sys/timeb.h>
|
|
#include <strings.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include "myc_mem.h"
|
|
#include "sys_util.h"
|
|
#include "myc_err.h"
|
|
#include "coc_logfile.h"
|
|
#include "coc_util.h"
|
|
#include "coc_server.h"
|
|
#include "myc_str.h"
|
|
#include "myc_time.h"
|
|
|
|
#define COC_NUL COC_SEP
|
|
|
|
typedef struct _CocVar {
|
|
struct _CocVar *next;
|
|
char name[32];
|
|
void *var;
|
|
int access;
|
|
int type;
|
|
int size;
|
|
void *strucType;
|
|
int (*hdl)(int, void *, int);
|
|
int pending;
|
|
} CocVar;
|
|
|
|
CocVar *serverVarList=NULL;
|
|
static CocVar **varListHandle=&serverVarList;
|
|
static CocVar *lastDef=NULL;
|
|
|
|
typedef struct {
|
|
CocVar *var;
|
|
void *base;
|
|
int mode;
|
|
} Pend;
|
|
|
|
typedef struct _CocClient {
|
|
struct _CocClient *next;
|
|
int fd;
|
|
int mode;
|
|
Pend pend[16];
|
|
int npend;
|
|
int logmask;
|
|
char synch;
|
|
void *data;
|
|
} CocClient;
|
|
|
|
void *(*setData)(void *);
|
|
|
|
/*
|
|
static CocClientData **clData;
|
|
static int clDataSize;
|
|
*/
|
|
|
|
DeclStrBuf(buf, COC_CMD_LEN);
|
|
DeclStrBuf(bufo, COC_RES_LEN);
|
|
|
|
static fd_set mask, rmask;
|
|
static int maxfd;
|
|
CocClient *cList;
|
|
static int mainFd;
|
|
static int modified;
|
|
static char loglist[16];
|
|
|
|
void CocVarList(void **varList) {
|
|
if (varList==NULL) {
|
|
varListHandle=(CocVar **)varList;
|
|
} else {
|
|
varListHandle=&serverVarList;
|
|
}
|
|
}
|
|
|
|
void CocList() { CocVar *p;
|
|
|
|
p=*varListHandle;
|
|
while (p!=NULL) {
|
|
printf("%s %d ", p->name, p->type);
|
|
p=p->next;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
CocVar *CocFindVar1(const char *name) {
|
|
CocVar *p;
|
|
|
|
p=*varListHandle;
|
|
while (p!=NULL && 0!=strcasecmp(p->name,name)) p=p->next;
|
|
return(p);
|
|
}
|
|
|
|
void *CocFindVar(const char *name, void **adr) {
|
|
CocVar *p, *t;
|
|
const char *f;
|
|
void *base;
|
|
char nam[32];
|
|
|
|
f=str_split(nam, name, '.');
|
|
if (f==NULL) {
|
|
f=str_split(nam, name, '-');
|
|
if (f!=NULL) {
|
|
if (f[0]!='>') {
|
|
f=NULL;
|
|
} else {
|
|
f++;
|
|
}
|
|
}
|
|
}
|
|
if (f!=NULL) {
|
|
if (adr!=NULL) *adr=NULL;
|
|
p=CocFindVar1(nam);
|
|
if (p==NULL) { return(NULL); }
|
|
t=p->strucType;
|
|
if (t==NULL) { return(NULL); }
|
|
str_copy(nam, t->name);
|
|
str_append(nam, ":");
|
|
str_append(nam, f);
|
|
if (adr!=NULL) {
|
|
base=p->var;
|
|
if (p->type==COC_PTR) base=*(void **)base;
|
|
*adr=base;
|
|
}
|
|
} else if (adr!=NULL) {
|
|
*adr=NULL;
|
|
}
|
|
p=CocFindVar1(nam);
|
|
if (p!=NULL && p->type==COC_ALIAS) { /* recursive call for alias */
|
|
p=CocFindVar(p->var, adr);
|
|
}
|
|
return(p);
|
|
}
|
|
|
|
void *CocIntPtr(int *ptr) { return(ptr); }
|
|
void *CocFltPtr(float *ptr) { return(ptr); }
|
|
void *CocChrPtr(char *ptr) { return(ptr); }
|
|
|
|
void *CocDefVar(const char *name, void *var, int type, int size, int access) {
|
|
CocVar *p;
|
|
const char *f;
|
|
void *adr;
|
|
|
|
assert(varListHandle!=NULL);
|
|
p=CocFindVar1(name);
|
|
if (p==NULL) {
|
|
NEW(p,CocVar);
|
|
p->next=*varListHandle;
|
|
*varListHandle=p;
|
|
str_copy(p->name, name);
|
|
p->type=type;
|
|
p->size=size;
|
|
} else {
|
|
assert(p->type==type);
|
|
}
|
|
p->var=var;
|
|
p->access=access;
|
|
/* printf("define %s %d\n", name, (int)var); */
|
|
lastDef=p;
|
|
return(p);
|
|
OnError:
|
|
assert(0);
|
|
}
|
|
|
|
void CocHdl(int (*handler)(int, void *, int)) {
|
|
assert(lastDef!=NULL);
|
|
lastDef->hdl=handler;
|
|
}
|
|
|
|
int *CocSizePtr(void) {
|
|
assert(lastDef!=NULL && lastDef->type==COC_ARRAY);
|
|
return &lastDef->size;
|
|
}
|
|
|
|
void CocDefVarS(const char *name, const char *tname, void *var, int type) {
|
|
CocVar *p, *t;
|
|
|
|
assert(type==COC_PTR || type==COC_STRUCT);
|
|
p=CocDefVar(name, var, type, 0, COC_RDONLY);
|
|
p->strucType=CocDefVar(tname, NULL, COC_TYPE, 0, COC_RDONLY);
|
|
}
|
|
|
|
char err_name[64];
|
|
|
|
int CocGetThisVar(CocVar *var, void *base, StrBuf *buf, int separator) {
|
|
void *adr;
|
|
int iret;
|
|
|
|
if (base==NULL) {
|
|
adr=var->var;
|
|
if (adr==NULL)
|
|
ERR_MSG("NULL pointer accessed");
|
|
} else { /* dereference */
|
|
adr=(char *)base + (int)var->var;
|
|
}
|
|
/* printf("get %s %d\n", name, (int)adr); */
|
|
if (var->type==COC_CHAR) {
|
|
ERR_P(StrNGet(buf, (char *)adr, var->size, separator));
|
|
} else if (var->type==COC_INT) {
|
|
ERR_I(StrGetInt(buf, (int *)adr, separator));
|
|
} else if (var->type==COC_FLT) {
|
|
ERR_I(StrGetFloat(buf, (float *)adr, separator));
|
|
} else if (var->type==COC_ARRAY) {
|
|
ERR_I(StrGetArray(buf, (float *)adr, var->size));
|
|
} else {
|
|
ERR_MSG("unknown type");
|
|
}
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int CocPutThisVar(CocVar *var, void *base, StrBuf *buf, int separator) {
|
|
void *adr;
|
|
int iret;
|
|
|
|
if (base==NULL) {
|
|
adr=var->var;
|
|
if (adr==NULL)
|
|
ERR_MSG("NULL pointer accessed");
|
|
} else { /* dereference */
|
|
adr=(char *)base + (int)var->var;
|
|
}
|
|
/* printf("put %s %d\n", name, (int)adr); */
|
|
if (var->type==COC_CHAR) {
|
|
ERR_I(StrPut(buf, adr, separator));
|
|
} else if (var->type==COC_INT) {
|
|
ERR_I(StrPutInt(buf, *(int *)adr, separator));
|
|
} else if (var->type==COC_FLT) {
|
|
ERR_I(StrPutFloat(buf, *(float *)adr, separator));
|
|
} else if (var->type==COC_ARRAY) {
|
|
ERR_I(StrPutArray(buf, (float *)adr, var->size));
|
|
} else {
|
|
ERR_MSG("unknown type");
|
|
}
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int CocGetVar(const char *name, StrBuf *buf, int separator) {
|
|
CocVar *var;
|
|
void *base;
|
|
|
|
var=CocFindVar(name, &base);
|
|
if (var==NULL) ERR_MSG("undefined variable");
|
|
ERR_I(CocGetThisVar(var, base, buf, separator));
|
|
return(0);
|
|
OnError: str_copy(err_name, name); ErrTxt(err_name,0); return(-1);
|
|
}
|
|
|
|
int CocPutVar(const char *name, StrBuf *buf, int separator) {
|
|
CocVar *var;
|
|
void *base;
|
|
|
|
var=CocFindVar(name, &base);
|
|
if (var==NULL) ERR_MSG("undefined variable");
|
|
ERR_I(CocPutThisVar(var, base, buf, separator));
|
|
return(0);
|
|
OnError: str_copy(err_name, name); ErrTxt(err_name,0); return(-1);
|
|
}
|
|
|
|
void CocFreeVarList(void) {
|
|
CocVar *p, *v;
|
|
|
|
v=*varListHandle;
|
|
while (v!=NULL) {
|
|
p=v;
|
|
v=p->next;
|
|
p->next=NULL;
|
|
FREE(p);
|
|
}
|
|
*varListHandle=NULL;
|
|
}
|
|
|
|
char *CocReadVars(char *str, char stop){
|
|
int i, l;
|
|
char *eql, *cr, buf[80];
|
|
StrBuf sbuf;
|
|
|
|
/* interprete variables until stop character appeares */
|
|
i=sscanf(str, "%79s%n", buf, &l);
|
|
while (i>0 && buf[0]!=stop) {
|
|
if (buf[0]=='!') {
|
|
cr=strchr(str, '\n');
|
|
if (cr==NULL) return strchr(str, '\0');
|
|
str=cr+1;
|
|
} else {
|
|
str+=l;
|
|
eql=strchr(buf,'=');
|
|
if (eql==NULL) ERR_MSG("syntax error");
|
|
*eql='\0';
|
|
StrLink(&sbuf, eql+1);
|
|
ERR_I(CocGetVar(buf, &sbuf, ' '));
|
|
}
|
|
i=sscanf(str, "%79s%n", buf, &l);
|
|
}
|
|
return str;
|
|
OnError: return NULL;
|
|
}
|
|
|
|
void CocToClients(int mask, char *str) {
|
|
int iret;
|
|
CocClient *cl;
|
|
|
|
cl=cList->next;
|
|
while (cl!=NULL) {
|
|
if (cl->logmask & mask) {
|
|
iret=CocSend(cl->fd, str, strlen(str)+1);
|
|
if (iret<0) {
|
|
cl->logmask=0; /* disable logging for dead clients */
|
|
logfileOut(LOG_MAIN, "(%d) disconnected while logging\n", cl->fd);
|
|
}
|
|
}
|
|
cl=cl->next;
|
|
}
|
|
}
|
|
|
|
int CocInitServer(void *(*setDataRtn)(void *), int port) {
|
|
int i;
|
|
struct sockaddr_in sadr;
|
|
char *err;
|
|
|
|
setData=setDataRtn;
|
|
/*
|
|
clDataSize=clientDataSize;
|
|
clData=clientData;
|
|
*/
|
|
NEW(cList,CocClient); /* empty header */
|
|
|
|
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)));
|
|
logfileOutRtn=CocToClients;
|
|
logfileOut(LOG_INFO, "created server on port %d\n", port);
|
|
ERR_SI(listen(mainFd, 8));
|
|
FD_ZERO(&mask);
|
|
FD_SET(mainFd, &mask);
|
|
maxfd=mainFd+1;
|
|
CocDefStr(loglist, COC_RDWR);
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int CocHandleThis(CocVar *var, void *base, StrBuf *outBuf, int mode, int fd) {
|
|
int iret;
|
|
|
|
if (var->hdl!=NULL) {
|
|
iret=var->hdl(mode, base, fd);
|
|
if (iret<0) { /* error */
|
|
ErrShow(var->name);
|
|
ERR_I(StrPut(outBuf, "", COC_ERR)); /* signal error message */
|
|
ERR_I(StrPut(outBuf, ErrMessage, COC_SEP));
|
|
return(0);
|
|
}
|
|
if (iret==COC_DRD) {
|
|
ERR_I(StrPut(outBuf, "", COC_DELAYED)); /* delayed response message */
|
|
ERR_I(StrPut(outBuf, "", COC_SEP)); /* empty message */
|
|
return(COC_DRD);
|
|
}
|
|
if (iret!=0 && iret!=COC_DWR)
|
|
ERR_MSG("illegal return value from handler");
|
|
} else {
|
|
iret=0;
|
|
}
|
|
ERR_I(CocPutThisVar(var, base, outBuf, COC_NUL));
|
|
return(iret);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int CocPushThisHandler(CocVar *var, CocClient *cl, void *base, int mode) {
|
|
int n;
|
|
|
|
if (mode==COC_DWR) {
|
|
if (var->pending) return(0);
|
|
var->pending=1;
|
|
}
|
|
n=cl->npend;
|
|
if (n>=sizeof(cl->pend)) {
|
|
ERR_MSG("too many commands")
|
|
}
|
|
cl->pend[n].var=var;
|
|
cl->pend[n].base=base;
|
|
cl->pend[n].mode=mode;
|
|
cl->npend=n+1;
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int CocCallHandlers(void) {
|
|
CocClient *cl;
|
|
CocVar *var;
|
|
Pend *p;
|
|
int i, iret, mode, delayedRead;
|
|
char synch;
|
|
DeclStrBuf(bufr, COC_RES_LEN);
|
|
|
|
cl=cList->next;
|
|
while (cl!=NULL) {
|
|
|
|
delayedRead=0;
|
|
/* treat delayed write handlers first */
|
|
for (i=0; i<cl->npend; i++) {
|
|
p=&cl->pend[i];
|
|
mode=p->mode;
|
|
var=p->var;
|
|
assert(var!=NULL && var->hdl!=NULL);
|
|
if (mode==COC_DWR) {
|
|
var->pending=0;
|
|
ERR_I(var->hdl(mode, p->base, cl->fd));
|
|
p->mode=0;
|
|
} else {
|
|
delayedRead=1;
|
|
}
|
|
}
|
|
if (delayedRead) {
|
|
StrClear(&bufr);
|
|
synch=cl->synch;
|
|
ERR_I(StrPut(&bufr, "", cl->synch));
|
|
for (i=0; i<cl->npend; i++) {
|
|
p=&cl->pend[i];
|
|
mode=p->mode;
|
|
var=p->var;
|
|
assert(var!=NULL && var->hdl!=NULL);
|
|
if (mode==COC_DRD) {
|
|
iret=var->hdl(mode, p->base, cl->fd);
|
|
if (iret<0) { /* error */
|
|
ERR_I(StrPut(&bufr, "", COC_ERR)); /* signal error message */
|
|
ERR_I(StrPut(&bufr, ErrMessage, COC_SEP));
|
|
}
|
|
ERR_I(CocPutThisVar(var, p->base, &bufr, COC_NUL));
|
|
}
|
|
}
|
|
if (cl->synch==synch) { /* send only if no new request from client received */
|
|
assert(cl->fd!=0);
|
|
ERR_I(CocSend(cl->fd, bufr.buf, bufr.wrpos));
|
|
}
|
|
}
|
|
cl->npend=0;
|
|
cl=cl->next;
|
|
}
|
|
return(0);
|
|
OnError:
|
|
cl->npend=0;
|
|
return(-1);
|
|
}
|
|
|
|
void CocShowHandlers(char *buf, int buf_len) {
|
|
CocClient *cl;
|
|
Pend *p;
|
|
int i;
|
|
|
|
buf[0]='\0';
|
|
cl=cList->next;
|
|
while (cl!=NULL) {
|
|
for (i=0; i<cl->npend; i++) {
|
|
p=&cl->pend[i];
|
|
if (p->mode==COC_DWR) {
|
|
assert(p->var!=NULL);
|
|
if (buf[0]!='\0') str_ncat(buf, ", ", buf_len);
|
|
str_ncat(buf, p->var->name, buf_len);
|
|
}
|
|
}
|
|
cl=cl->next;
|
|
}
|
|
return;
|
|
}
|
|
|
|
int CocHandle1Request(int tmo_msec, int fd) {
|
|
struct sockaddr_in cadr;
|
|
struct hostent *h;
|
|
struct timeval tmo={0,1};
|
|
CocClient *cl, *cl0;
|
|
CocVar *var;
|
|
int i, lmask, newfd, n, iret;
|
|
sys_adr_len cadrlen; /* see sys_util.h */
|
|
char *err, *cmd, *arg, *varname;
|
|
void *base;
|
|
|
|
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); /* event on fd */
|
|
if (i==0) return(0); /* timeout */
|
|
|
|
if (FD_ISSET(mainFd, &rmask)) {
|
|
cadrlen=sizeof(cadr);
|
|
ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen));
|
|
FD_SET(newfd, &mask);
|
|
if (newfd>=maxfd) maxfd=newfd+1;
|
|
NEW(cl, CocClient);
|
|
cl->fd=newfd;
|
|
cl->mode=0;
|
|
if (setData!=NULL) {
|
|
ERR_P(cl->data = setData(NULL)); /* create new client data object */
|
|
}
|
|
/*
|
|
ERR_SP(cList=calloc(1,sizeof(CocClient)+clDataSize));
|
|
*/
|
|
cl->next=cList->next;
|
|
cList->next=cl;
|
|
h=gethostbyaddr((void *)&cadr.sin_addr, 4, AF_INET);
|
|
if (h==NULL) {
|
|
logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, "local");
|
|
} else {
|
|
logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, h->h_name);
|
|
}
|
|
} else {
|
|
cl0=cList; cl=cl0->next;
|
|
while (cl!=NULL) {
|
|
if (FD_ISSET(cl->fd, &rmask)) {
|
|
iret=CocRecv(cl->fd, &buf, -1, NULL);
|
|
if (iret<=0) {
|
|
logfileOut(LOG_INFO, "(%d) disconnected\n",cl->fd);
|
|
close(cl->fd);
|
|
FD_CLR(cl->fd, &mask);
|
|
cl0->next=cl->next;
|
|
FREE(cl);
|
|
cl=cl0;
|
|
} else {
|
|
cl->logmask=0; /* stop output to log client */
|
|
lmask=0;
|
|
StrReset(&buf);
|
|
StrClear(&bufo);
|
|
err=NULL;
|
|
logfileOut(LOG_NET, "(%d) ", cl->fd);
|
|
logfileOutBuf(LOG_NET, &buf);
|
|
/* cl->npend=0; why that ? */
|
|
logfileOut(LOG_NET, "\n");
|
|
cl->synch=buf.buf[0];
|
|
ERR_P(StrGet(&buf, NULL, cl->synch));
|
|
ERR_I(StrPut(&bufo, "", cl->synch));
|
|
while (!StrEnd(&buf)) {
|
|
ERR_P(varname=StrGet(&buf, NULL, ' '));
|
|
if (cl->synch==COC_MAGIC) { /* access code */
|
|
if (0==strcmp(varname,"rdacs")) {
|
|
logfileOut(LOG_INFO, "set read mode\n");
|
|
cl->mode=1;
|
|
ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
|
|
} else if (0==strcmp(varname,"rwacs")) {
|
|
logfileOut(LOG_INFO, "set write mode\n");
|
|
cl->mode=2;
|
|
ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
|
|
} else {
|
|
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
|
ERR_I(StrPut(&bufo, "bad access code", COC_SEP));
|
|
}
|
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
|
} else if (cl->mode==0) {
|
|
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal terminal error message */
|
|
ERR_I(StrPut(&bufo, "no access", COC_SEP));
|
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
|
} else {
|
|
if (cl->data!=NULL) {
|
|
setData(cl->data);
|
|
}
|
|
var=CocFindVar(varname, &base);
|
|
if (var==NULL) {
|
|
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
|
ERR_I(StrPut(&bufo, "undefined variable", COC_SEP));
|
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
|
} else if (buf.seen) { /* separator was there: set mode */
|
|
if (var->access > cl->mode) {
|
|
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
|
ERR_I(StrPut(&bufo, "no access", COC_SEP));
|
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
|
} else {
|
|
ERR_I(CocGetThisVar(var, base, &buf, COC_SEP));
|
|
if (0==strcmp(var->name,"loglist")) {
|
|
str_upcase(loglist, loglist);
|
|
if (NULL!=strchr(loglist,'A')) lmask = lmask | LOG_ALL;
|
|
if (NULL!=strchr(loglist,'S')) lmask = lmask | LOG_SER;
|
|
if (NULL!=strchr(loglist,'N')) lmask = lmask | LOG_NET;
|
|
if (NULL!=strchr(loglist,'I')) lmask = lmask | LOG_INFO;
|
|
if (NULL!=strchr(loglist,'M')) lmask = lmask | LOG_MAIN;
|
|
ERR_I(StrPut(&bufo, "", COC_NUL)); /* o.k. */
|
|
} else {
|
|
ERR_I(iret=CocHandleThis(var, base, &bufo, COC_WR, cl->fd));
|
|
if (iret) ERR_I(CocPushThisHandler(var, cl, base, iret));
|
|
}
|
|
modified=1;
|
|
}
|
|
} else {
|
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
|
ERR_I(iret=CocHandleThis(var, base, &bufo, COC_RD, cl->fd));
|
|
if (iret) ERR_I(CocPushThisHandler(var, cl, base, iret));
|
|
}
|
|
}
|
|
}
|
|
ERR_I(StrGetEnd(&buf));
|
|
logfileOut(LOG_NET, " ");
|
|
logfileOutBuf(LOG_NET, &bufo);
|
|
logfileOut(LOG_NET, "\n");
|
|
ERR_I(CocSend(cl->fd, bufo.buf, bufo.wrpos));
|
|
cl->logmask=lmask;
|
|
}
|
|
}
|
|
cl0=cl; cl=cl->next;
|
|
}
|
|
}
|
|
if (modified) return(2);
|
|
return(3);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int CocHandleRequests(int tmo_msec, int fd) {
|
|
int tdif, iret, tim0;
|
|
|
|
if (modified && fd==0) { /* earlier modification */
|
|
modified=0;
|
|
return(2);
|
|
}
|
|
tim0=mycMsecSince(0);
|
|
tdif=tmo_msec;
|
|
while (tdif>=0) {
|
|
ERR_I(iret=CocHandle1Request(tdif, fd));
|
|
if (fd==0) {
|
|
if (iret==2) return(2); /* modification of a variable */
|
|
} else {
|
|
if (iret==1) return(1); /* event on fd */
|
|
}
|
|
if (iret==0) return(0); /* timeout */
|
|
tdif = tmo_msec - mycMsecSince(tim0);
|
|
}
|
|
return(0); /* timeout */
|
|
OnError: return(-1);
|
|
}
|
|
|
|
void CocCloseServer() {
|
|
CocClient *cl, *cl0;
|
|
|
|
cl=cList->next;
|
|
while (cl!=NULL) {
|
|
close(cl->fd);
|
|
cl0=cl;
|
|
cl=cl->next;
|
|
FREE(cl0);
|
|
}
|
|
FREE(cList);
|
|
close(mainFd);
|
|
}
|