#ifndef LINT static char *rcsid="$Id: clnt_tcp.c,v 1.14 1999/10/03 21:18:03 crosser Exp $"; #endif /* $Log: clnt_tcp.c,v $ Revision 1.14 1999/10/03 21:18:03 crosser First (probably) working version with new run time config parser. Also added listenq parameter (backlog size for listen()) and renamed wtest to whoson (and with man page). Release 2.00beta1. Revision 1.13 1999/08/19 17:22:14 crosser Move to new config scheme (does not work yet) Revision 1.12 1999/07/27 17:30:05 crosser fix names Revision 1.11 1999/01/30 14:41:05 crosser fix use of saved errno Revision 1.10 1998/07/26 14:06:40 crosser fix for multiline responces Revision 1.9 1998/07/12 16:43:57 crosser Change protocol: responce now is terminated with empty line Revision 1.8 1998/07/05 00:26:18 crosser Change copyright Revision 1.7 1998/07/03 11:10:39 crosser setup for _REENTRANT mode Revision 1.6 1998/07/03 09:32:48 crosser make persistant connections work Revision 1.5 1998/07/02 18:01:15 crosser change error reporting to syslog Revision 1.4 1998/07/02 15:37:07 crosser make right return if req invalid or disallowed Revision 1.3 1998/07/01 21:55:16 crosser forgot to close fd in normal case Revision 1.2 1998/07/01 05:18:09 crosser minor warnings fix Revision 1.1 1998/07/01 05:01:22 crosser Initial revision Revision 1.1 1998/05/05 19:08:16 crosser Initial revision */ /* WHAT IS IT: Implementation of experimental "whoson" protocol AUTHOR: Eugene G. Crosser COPYRIGHT: Public domain */ #include "config.h" #include #include #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H #include #endif #include #include #include #include #include #include #include #include #include "whoson.h" #include "rtconfig.h" #include "clnt_common.h" #include "report.h" #include "rtc_begin.h" #include "clnt_tcp_cfg.h" #include "rtc_middle.h" #include "clnt_tcp_cfg.h" #include "rtc_end.h" #define MAXTRIES 3 #define MAXREQL 1024 int wso_tcp_clnt_connect(void *priv,char *buf) { wso_clnt_tcp_cfg *rec=(wso_clnt_tcp_cfg *)(priv); struct sockaddr_in server; struct protoent *pe; int protonum; int len,off,left,crcount,lfcount,saveerr; char *p; int tries=0; RETSIGTYPE (*savepipe)(int); #ifdef _REENTRANT int fd=-1; #define FD fd #else #define FD rec->fd #endif if (FD >= 0) goto session; reconnect: memset((char *)&server,0,sizeof(server)); server.sin_family = AF_INET; if ((pe=getprotobyname("tcp"))) protonum=pe->p_proto; else protonum=6; server.sin_port=htons(rec->port); server.sin_addr=rec->address; if ((FD=socket(AF_INET,SOCK_STREAM,protonum)) < 0) { ERRLOG((LOG_ERR,"[WHOSON] server socket: %m")) return -1; } if (connect(FD,(struct sockaddr *)&server,sizeof(server)) < 0) { ERRLOG((LOG_ERR,"[WHOSON] connect server: %m")) close(FD); FD=-1; return -1; } session: savepipe=signal(SIGPIPE,SIG_IGN); len=write(FD,buf,strlen(buf)); saveerr=errno; (void)signal(SIGPIPE,savepipe); errno=saveerr; if (len != strlen(buf)) { if ((errno == EPIPE) && (++tries < MAXTRIES)) { DPRINT(("server gone (write), reconnecting %d\n",tries)) close(FD); goto reconnect; } ERRLOG((LOG_ERR,"[WHOSON] write to server: %m")) close(FD); FD=-1; return -1; } off=0; left=MAXREQL-1; crcount=0; lfcount=0; while (left) { if ((len=read(FD,buf+off,left)) < 0) { if ((errno == EPIPE) && (++tries < MAXTRIES)) { DPRINT(("server gone (read), reconnect %d\n", tries)) close(FD); goto reconnect; } ERRLOG((LOG_ERR,"[WHOSON] read from server: %m")) close(FD); FD=-1; return -1; } if (len == 0) break; for (p=buf+off; (p 1) || (lfcount > 1)) break; } buf[off]='\0'; #ifdef _REENTRANT close(FD); FD=-1; #endif return 0; }