#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 <crosser@average.org>
COPYRIGHT:
Public domain
*/
#include "config.h"
#include <sys/types.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <netdb.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#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<buf+MAXREQL) && (crcount<2) && (lfcount<2);
p++)
switch (*p) {
case '\r': crcount++;
break;
case '\n': lfcount++;
break;
default: crcount=0; lfcount=0;
break;
}
off+=len;
left-=len;
if ((crcount > 1) || (lfcount > 1)) break;
}
buf[off]='\0';
#ifdef _REENTRANT
close(FD);
FD=-1;
#endif
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1