#include #include #include #include #include #include #include "err_handling.h" #include "coc_client.h" #include "str_util.h" /*-------------------------------------------------------------------------*/ int CocConnect(CocConn *conn, int allowConnRefused) { int i; struct sockaddr_in sadr; ERR_I(CocCreateSockAdr(&sadr, conn->host, conn->port)); ERR_SI(conn->fd=socket(AF_INET, SOCK_STREAM, 0)); i = 1; ERR_SI(setsockopt(conn->fd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */ i=connect(conn->fd, (struct sockaddr *)&sadr, sizeof(sadr)); if (i<0) { if (allowConnRefused && errno==ECONNREFUSED) return(1); ERR_COD(errno); } return(0); OnError: return(-1); } int CocOpen(CocConn *conn) { int i, try, tmo; ERR_I(i=CocConnect(conn, conn->startcmd[0]!='\0')); if (i==0) return(0); printf("%s\n", conn->startcmd); ERR_I(system(conn->startcmd)); try=15; tmo=100; /* wait total ca. 10 sec. for 15 tries */ while (try>0) { try--; CocDelay(tmo); tmo=tmo*5/4; ERR_I(i=CocConnect(conn, try>0)); if (i==0) return(0); } ERR_MSG("error in CocConnect"); OnError: return(-1); } /*-------------------------------------------------------------------------*/ int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd) { assert(conn!=NULL); if (bufsize==0) bufsize=1024; ERR_P(conn->cmdbuf=str_create_buf(bufsize, '\0')); ERR_P(conn->resbuf=str_create_buf(bufsize, '\0')); conn->port=port; ERR_I(str_copy(conn->host, host)); ERR_I(str_copy(conn->magic, magic)); ERR_I(str_copy(conn->startcmd, startcmd)); conn->fd=-1; conn->varList=NULL; CocVarList(&conn->varList); ERR_I(CocOpen(conn)); ERR_I(CocSendMagic(conn, conn->magic)); return(0); OnError: return(-1); } /*-------------------------------------------------------------------------*/ int CocSendMagic(CocConn *conn, char *magic) { char *err; if (magic[0]!='#') ERR_MSG("magic must start with '#'"); str_put_start(conn->resbuf); /* use return buffer for command in order to preserve command buffer */ ERR_I(str_put_str(conn->resbuf, magic)); ERR_SI(send(conn->fd, conn->resbuf->buf, conn->resbuf->wrpos, 0)); ERR_I(CocRecv(conn->fd, conn->resbuf)); ERR_P(err=str_get_str(conn->resbuf, NULL)); if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0); goto OnError; } ERR_I(str_get_end(conn->resbuf)); return(0); OnError: return(-1); } /*-------------------------------------------------------------------------*/ int CocTryCmd(CocConn *conn) { if (conn->fd<0) { ERR_I(CocOpen(conn)); ERR_I(CocSendMagic(conn, conn->magic)); } ERR_SI(send(conn->fd, conn->cmdbuf->buf, conn->cmdbuf->wrpos, 0)); ERR_I(CocRecv(conn->fd, conn->resbuf)); return(0); OnError: return(-1); } /*-------------------------------------------------------------------------*/ int CocCmdWithRetry(CocConn *conn) { int cnt, iret; char *err; cnt=3; while (1) { cnt--; if (cnt<=0) { ERR_I(CocTryCmd(conn)); break; } iret=CocTryCmd(conn); if (iret>=0) break; close(conn->fd); conn->fd=-1; if (ErrCode!=ECONNRESET && ErrCode!=EPIPE) goto OnError; ErrWrite("try again, error was"); } ERR_P(err=str_get_str(conn->resbuf, NULL)); if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0 ); goto OnError; } return(0); OnError: return(-1); } /*-------------------------------------------------------------------------*/ int CocSet(CocConn *conn, const char *name, const char *value) { assert(conn!=NULL); str_put_start(conn->cmdbuf); ERR_I(str_put_str(conn->cmdbuf, "[")); ERR_I(str_put_str(conn->cmdbuf, name)); ERR_I(str_put_str(conn->cmdbuf, value)); ERR_I(str_put_str(conn->cmdbuf, "]")); ERR_I(CocCmdWithRetry(conn)); ERR_I(str_get_end(conn->resbuf)); return(0); OnError: return(-1); } /*-------------------------------------------------------------------------*/ int CocGetN(CocConn *conn, const char *name, char *value, int reslen) { assert(conn!=NULL); str_put_start(conn->cmdbuf); ERR_I(str_put_str(conn->cmdbuf, name)); ERR_I(CocCmdWithRetry(conn)); ERR_P(str_nget_str(conn->resbuf, value, reslen)); ERR_I(str_get_end(conn->resbuf)); return(0); OnError: return(-1); } /*-------------------------------------------------------------------------*/ int CocCmd(CocConn *conn, const char *rwList) { int setmode, i; const char *t, *s; char nam[32]; CocVar *var; void *adr; assert(conn!=NULL); str_put_start(conn->cmdbuf); s=rwList; setmode=0; do { t=strchr(s, ','); if (t==NULL) t=s+strlen(s); if (*s=='[') { if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "[")); s++; setmode=1; } i=t-s; assert(i<32); str_ncpy(nam, s, i+1); if (setmode) { if (nam[i-1]==']') { i--; nam[i]='\0'; setmode=0; } ERR_I(str_put_str(conn->cmdbuf, nam)); ERR_I(CocPutVar(conn->varList, conn->cmdbuf, nam, 0)); if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "]")); } else { var=CocFindVar(conn->varList, nam, NULL); if (var==NULL) ERR_MSG("variable not found"); ERR_I(str_put_str(conn->cmdbuf, nam)); } s=t+1; } while (*t!='\0'); ERR_I(CocCmdWithRetry(conn)); /* read values */ s=rwList; setmode=0; do { t=strchr(s, ','); if (t==NULL) t=s+strlen(s); if (*s=='[') { s++; setmode=1; } i=t-s; if (setmode) { if (*(t-1)==']') setmode=0; } else { str_ncpy(nam, s, i+1); ERR_I(CocGetVar(conn->varList, conn->resbuf, nam, 0)); } s=t+1; } while (*t!='\0'); ERR_I(str_get_end(conn->resbuf)); return(0); OnError: return(-1); } void CocCloseClient(CocConn *conn) { assert(conn!=NULL); close(conn->fd); str_free_buf(conn->cmdbuf); str_free_buf(conn->resbuf); CocFreeVarList(&conn->varList); }