#include #include #include #include #include #include #include "rs232c_def.h" #include "asynsrv_def.h" #include "sinq_prototypes.h" #include "sys_util.h" #include "myc_err.h" #include "tecs_serial.h" #include "coc_logfile.h" #include "coc_util.h" #include "myc_str.h" #include "myc_mem.h" #define ASYNSRV_TYPE 1 #define TERMSRV_TYPE 2 #define EOT '\r' typedef struct { int type; /* = ASYNSRV_TYPE */ struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */ struct RS__MsgStruct to_host; struct RS__RespStruct from_host; } AsynSrvChan; typedef struct { int type; /* = TERMSRV_TYPE */ char res[SER_BUF_LEN]; int fd, tmo; int (*idleHdl)(int,int); } TermSrvChan; void SerA_error(void) { char *a_txt; int a_cod, a_my, a_vms; AsynSrv_ErrInfo(&a_txt, &a_cod, &a_my, &a_vms); ErrMsg("asynsrv error"); ErrTxt(a_txt,0); } int SerWait(int tmo_msec, int fd) { struct timeval tmo; fd_set mask; int i; FD_ZERO(&mask); FD_SET(fd, &mask); tmo.tv_sec=tmo_msec / 1000; tmo.tv_usec=(tmo_msec % 1000) % 1000 +1; ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo)); if (i==0) return(0); /* timeout */ return(1); OnError: return(-1); } SerChannel *SerOpen(const char *hostPort, int msecTmo, int (*idleHdl)(int,int)) { AsynSrvChan *aser; TermSrvChan *tser; char hbuf[64], cport[16], host[32]; char *p, *c; struct sockaddr_in sadr; int iret; time_t t1, t2; static int ecnt; time(&t1); str_copy(hbuf, hostPort); p=str_split(host, hbuf, ':'); assert(p!=NULL); c=str_split(cport, p, '/'); if (msecTmo==0) msecTmo=5000; if (c!=NULL) { NEW(aser, AsynSrvChan); aser->type=ASYNSRV_TYPE; str_copy(aser->asyn_info.host, host); aser->asyn_info.port=atoi(cport); aser->asyn_info.chan=atoi(c); iret=AsynSrv_Open(&aser->asyn_info); if (iret==1) { iret=AsynSrv_Config(&aser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL); } if (iret!=1) { SerA_error(); goto OnError; } time(&t2); ecnt=0; logfileOut(LOG_MAIN, "connection to %s:%d/%d opened (%d sec)\n", aser->asyn_info.host, aser->asyn_info.port, aser->asyn_info.chan, t2-t1); return((SerChannel *)aser); } else { NEW(tser, TermSrvChan); tser->type=TERMSRV_TYPE; tser->tmo=msecTmo; if (idleHdl==NULL) { tser->idleHdl=SerWait; } else { tser->idleHdl=idleHdl; } ERR_I(CocCreateSockAdr(&sadr, host, atoi(p))); ERR_SI(tser->fd=socket(AF_INET, SOCK_STREAM, 0)); ERR_SI(connect(tser->fd, (struct sockaddr *)&sadr, sizeof(sadr))); time(&t2); ecnt=0; logfileOut(LOG_MAIN, "connected to %s (%d sec)\n", hostPort, t2-t1); return ((SerChannel *)tser); } OnError: time(&t2); if (ecnt<4) { logfileOut(LOG_MAIN, "failed after %d sec\n", t2-t1); ecnt++; } return(NULL); } int SerSetTmo(SerChannel *serch, int msecTmo) { AsynSrvChan *aser; TermSrvChan *tser; int iret; if (serch->type==ASYNSRV_TYPE) { aser=(AsynSrvChan *)serch; iret=AsynSrv_Config(&aser->asyn_info, "msecTmo", msecTmo, NULL); if (iret!=1) { SerA_error(); goto OnError; } } else if (serch->type==TERMSRV_TYPE) { tser=(TermSrvChan *)serch; tser->tmo=msecTmo; } return 0; OnError: return -1; } void SerClose(SerChannel *serch) { AsynSrvChan *aser; TermSrvChan *tser; if (serch->type==ASYNSRV_TYPE) { aser=(AsynSrvChan *)serch; AsynSrv_Close(&aser->asyn_info, 0); } else if (serch->type==TERMSRV_TYPE) { tser=(TermSrvChan *)serch; close(tser->fd); } serch->type=0; } SerChannel *SerCheck(SerChannel *serch) { if (serch==NULL || serch->type==0) { return(NULL); } else { return(serch); } } char *SerCmd(SerChannel *serch, char *cmnd) { int l, n; AsynSrvChan *aser; TermSrvChan *tser; char *result, *pos, *trm; int iret, incomplete; l=strlen(cmnd); if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS); cmnd[l]=EOT; l++; cmnd[l]='\0'; logfileOut(LOG_SER, ">%s\n", cmnd); if (serch->type==ASYNSRV_TYPE) { aser=(AsynSrvChan *)serch; iret=AsynSrv_SendCmnds(&aser->asyn_info, &aser->to_host, &aser->from_host, cmnd, NULL); if (iret!=1) { SerA_error(); SerClose(serch); return(NULL); } result=AsynSrv_GetReply(&aser->asyn_info, &aser->from_host, NULL); if (result==NULL) ERR_MSG("empty result"); } else if (serch->type==TERMSRV_TYPE) { tser=(TermSrvChan *)serch; iret=send(tser->fd, cmnd, l, 0); if (iret<0) { ErrMsg("disconnected"); SerClose(serch); goto OnError; } n=sizeof(tser->res); pos=tser->res; result=NULL; incomplete=1; while (incomplete) { /* Wait for an event on tser->fd or a timeout tmo */ iret=tser->idleHdl(tser->tmo, tser->fd); if (iret==0) { if (result==NULL) ERR_MSG("timeout"); ERR_MSG("missing terminator"); } ERR_SI(l=recv(tser->fd, pos, n, 0)); if (l==0) { ErrMsg("disconnected"); SerClose(serch); goto OnError; } n -= l; if (n==0) ERR_MSG("answer too long"); while (l>0) { if (*pos>' ') { if (result==NULL) result=pos; /* skip trailing white space */ } else if (*pos<' ') { /* all control characters are treated as terminators */ if (result!=NULL) { *pos='\0'; incomplete=0; } } pos++; l--; } } } else { serch->type=0; ERR_MSG("invalid channel"); } logfileOut(LOG_SER, "<%s\n", result); return(result); OnError: return(NULL); } /* obsolete ? char *SerCmdC(SerChannel *serch, const char *cmnd) { char cmd[SER_BUF_LEN]; int l; l=strlen(cmnd); if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS); strcpy(cmd, cmnd); return(SerCmd(serch, cmd)); OnError: return(NULL); } */