PSI sics-cvs-psi-2006

This commit is contained in:
2006-05-08 02:00:00 +00:00
committed by Douglas Clowes
parent ae77364de2
commit 6e926b813f
388 changed files with 445529 additions and 14109 deletions

289
network.c
View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
Some metworking functions. This version for TCP/IP.
Some networking functions. This version for TCP/IP.
@@ -42,17 +42,23 @@
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#define PORT 1
#define SOCKET 2
#define UDP 3
/* wait time [ms] between a close and the next open */
#define WAIT_CLOSE_OPEN 500
struct timeval lastclose={-1,0};
/*-----------------------------------------------------------------------
Redefine this function if another means of error reporting is necessary.
*/
@@ -102,7 +108,6 @@ CreateSocketAdress(
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
return 1;
}
/*-------------------------------------------------------------------------*/
mkChannel *NETOpenPort(int iPort)
@@ -150,15 +155,16 @@ CreateSocketAdress(
i = sizeof(struct linger);
lili.l_onoff = 1;
lili.l_linger = 1;
/* setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
*/
/*
setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
*/
pRes->iType = PORT;
pRes->lMagic = NETMAGIC;
return pRes;
}
/*---------------------------------------------------------------------------*/
mkChannel *NETAccept(mkChannel *self, int timeout)
mkChannel *NETAccept(mkChannel *self, long timeout)
{
mkChannel *pRes = NULL;
int iRet;
@@ -169,10 +175,11 @@ CreateSocketAdress(
assert(self != NULL);
if(timeout > 0)
if(timeout >= 0)
{
/* select first */
tmo.tv_usec = timeout;
tmo.tv_usec = (timeout % 1000) * 1000;
tmo.tv_sec = timeout / 1000;
FD_ZERO(&lMask);
FD_SET(self->sockid,&lMask);
if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) ) /* invalid descriptor */
@@ -200,25 +207,30 @@ CreateSocketAdress(
free(pRes);
return NULL;
}
/*
i = sizeof(struct linger);
lili.l_onoff = 1;
lili.l_linger = 1;
/* setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
i = 1;
setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int));
*/ pRes->iType = SOCKET;
*/
pRes->iType = SOCKET;
pRes->lMagic = NETMAGIC;
return pRes;
}
/*--------------------------------------------------------------------------*/
mkChannel *NETConnect(char *name, int port)
mkChannel *NETConnectWithFlags(char *name, int port, int flags)
{
mkChannel *pRes = NULL;
int iRet, i;
int iRet, i, cnt;
char pBueffel[80];
struct hostent *pServer = NULL;
struct linger lili;
struct timeval now;
long dif;
int oldopts;
assert(port > 0);
@@ -247,24 +259,101 @@ CreateSocketAdress(
free(pRes);
return NULL;
}
if (flags & 2) { /* wait if closed recently */
/* workaround for a bug in Lantronix terminal server:
if a channel is closed and reopened within short time
the connect will be succesful, but a message will be
sent on the channel! */
if (lastclose.tv_sec >= 0) {
gettimeofday(&now, NULL);
dif = (now.tv_sec-lastclose.tv_sec)*1000+(now.tv_usec-lastclose.tv_usec)/1000;
if (dif < 0) dif += 24*3600*1000;
} else {
dif = 0;
}
if (dif < WAIT_CLOSE_OPEN) {
usleep((WAIT_CLOSE_OPEN-dif)*1000);
}
}
if (flags & 1) { /* open in non blocking mode */
oldopts = fcntl(pRes->sockid, F_GETFL, 0);
fcntl(pRes->sockid, F_SETFL, oldopts | O_NONBLOCK);
}
iRet = connect(pRes->sockid,(struct sockaddr *)&(pRes->adresse),
sizeof(struct sockaddr_in));
if(iRet < 0)
{
if (errno != EINPROGRESS) {
free(pRes);
return NULL;
}
}
/*
i = sizeof(struct linger);
lili.l_onoff = 1;
lili.l_linger = 1;
/* setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
i = 1;
setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int));
*/ pRes->iType = SOCKET;
*/
pRes->iType = SOCKET;
pRes->lMagic = NETMAGIC;
return pRes;
}
/*--------------------------------------------------------------------------*/
mkChannel *NETConnect(char *name, int port) {
return NETConnectWithFlags(name, port, 0);
}
/*--------------------------------------------------------------------------*/
int NETConnectFinished(mkChannel *self) {
fd_set wmask, rmask;
struct timeval tmo = {0,0};
int iret;
int oldopts;
if (self->sockid == 0) {
errno = ENOTCONN;
return -1;
}
oldopts = fcntl(self->sockid, F_GETFL, 0);
if (! (oldopts | O_NONBLOCK)) {
/* assume success when in blocking mode */
return 1;
}
FD_ZERO(&wmask);
FD_ZERO(&rmask);
FD_SET(self->sockid, &wmask);
FD_SET(self->sockid, &rmask);
iret = select(self->sockid+1, &rmask, &wmask, NULL, &tmo);
if (iret == 0) return 0; /* in progress */
if (iret > 0) {
/* the connection has either succeded or failed
- the write flag indicates success
- the read flag indicates, if there is already data pending
the read flag should not appear without the write flag
*/
if (FD_ISSET(self->sockid, &wmask)) { /* should always be true */
if (FD_ISSET(self->sockid, &rmask)) { /* there may already be data for read */
iret = recv(self->sockid, NULL, 0, 0); /* zero length, check only return value */
if (iret >= 0) {
iret = 1; /* success */
} /* else failure */
} else {
iret = send(self->sockid, NULL, 0, 0); /* zero length, check only return value */
if (iret >= 0) {
iret = 1; /* success */
} /* else failure */
}
}
}
/* reset to blocking mode */
fcntl(self->sockid, F_SETFL, oldopts | ~ O_NONBLOCK);
return iret;
}
/*------------------------------------------------------------------------*/
int VerifyChannel(mkChannel *self)
{
@@ -335,7 +424,8 @@ CreateSocketAdress(
return 0;
}
/* setup for select first */
#ifndef CYGNUS
/* setup for select first */
tmo.tv_usec = 100;
FD_ZERO(&lMask);
FD_SET(self->sockid,&lMask);
@@ -344,7 +434,6 @@ CreateSocketAdress(
{
return -1; /* eof */
}
#ifndef CYGNUS
iRet = select( (self->sockid + 1),NULL, &lMask, NULL,&tmo);
if( iRet <= 0)
{
@@ -360,10 +449,13 @@ CreateSocketAdress(
iRet = send(self->sockid,buffer,lLen,0);
if(iRet != lLen)
{
printf("Incomplete send: %d to %d\n ",iRet,lLen);
if(iRet < 0)
{
printf("System error: %s\n",strerror(errno));
if (errno != EPIPE) { /* do not write "broken pipe" error */
printf("System error: %s\n",strerror(errno));
}
} else {
printf("Incomplete send: %d to %ld\n",iRet,lLen);
}
return 0;
}
@@ -374,7 +466,7 @@ CreateSocketAdress(
}
/* -------------------------------------------------------------------------*/
long NETRead(mkChannel *self, char *buffer, long lLen, int timeout)
long NETRead(mkChannel *self, char *buffer, long lLen, long timeout)
{
fd_set lMask;
struct timeval tmo ={0,1};
@@ -385,10 +477,11 @@ CreateSocketAdress(
return 0;
}
if(timeout > 0)
if(timeout >= 0)
{
/* setup for select first */
tmo.tv_usec = timeout;
tmo.tv_usec = (timeout % 1000) *1000;
tmo.tv_sec = timeout / 1000;
FD_ZERO(&lMask);
FD_SET(self->sockid,&lMask);
if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) ) /* invalid descriptor */
@@ -422,8 +515,8 @@ CreateSocketAdress(
}
}
/*---------------------------------------------------------------------*/
int NETAvailable(mkChannel *self, int timeout)
{
int NETAvailable(mkChannel *self, long timeout)
{
fd_set lMask;
struct timeval tmo ={0,1};
int iRet;
@@ -434,7 +527,8 @@ CreateSocketAdress(
}
/* setup for select */
tmo.tv_usec = timeout;
tmo.tv_usec = (timeout % 1000) * 1000;
tmo.tv_sec = timeout / 1000;
FD_ZERO(&lMask);
FD_SET(self->sockid,&lMask);
if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) )
@@ -456,83 +550,80 @@ CreateSocketAdress(
return 0;
}
}
/*--------------------------------------------------------------------------*/
int NETReadTillTerm(mkChannel *self, int timeout,
/*-------------------------------------------------------------------------*/
int NETReadTillTerm(mkChannel *self, long timeout,
char *pTerm, char *pBuffer, int iBufLen)
{
int iRet, termLen, i, j, nLoop;
int read = 0;
{
struct timeval start, now;
int bufPtr = 0, status, i, length;
char c;
long dif;
if(!VerifyChannel(self))
{
return -1;
}
gettimeofday(&start, NULL);
if(!VerifyChannel(self))
if (pTerm == NULL) pTerm="";
length = strlen(pTerm);
memset(pBuffer,0,iBufLen);
status = NETAvailable(self,timeout); /* first time: full timeout */
if(status <= 0) /* return on error or on timeout */
{
return status;
}
while (status > 0)
{
status = recv(self->sockid,&c,1,0);
if(status <= 0)
{
return status;
}
for(i = 0; i < length; i++)
{
if(c == pTerm[i])
{
return -1;
return bufPtr+1;
}
/*
how may cycles to read in order to have a timeout
*/
nLoop = timeout/5;
if(nLoop <= 0)
{
nLoop = 1;
}
for(i = 0; i < nLoop; i++)
{
iRet = NETAvailable(self,5);
if(iRet < 0)
{
return iRet;
}
else if(iRet == 0)
{
continue;
}
else
{
/*
data is pending, read it
*/
iRet = recv(self->sockid,pBuffer+read,iBufLen - read,0);
if(iRet < 0)
{
return iRet;
}
else
{
read += iRet;
}
if(read >= iBufLen)
{
pBuffer[iBufLen-1] = '\0';
}
else
{
pBuffer[read+1] = '\0';
}
/*
have we found a terminator ?
*/
for(j = 0; j < strlen(pTerm); j++)
{
if(strrchr(pBuffer,pTerm[j]) != NULL)
{
return 1;
}
}
if(read >= iBufLen)
{
/*
we have filled the buffer but not found a terminator
*/
return -1;
}
}
}
return 0; /* timeout! */
}
}
if (c == 0 && *pTerm != 0)
{
/* a null character is an error, except when no terminator is defined (binary data) */
return -1;
}
if(bufPtr >= iBufLen-1)
{
if (*pTerm != 0) { /* terminator expected */
return -1; /* overflow */
}
pBuffer[bufPtr] = c;
return bufPtr+1;
}
pBuffer[bufPtr] = c;
bufPtr++;
/*
wait for more data
*/
status = NETAvailable(self,0); /* timeout 0 (just poll) */
if (status == 0 && timeout > 0)
{
gettimeofday(&now, NULL);
dif = (now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
if (dif < 0) dif += 24*3600*1000; /* treat midnight correctly */
if(dif > timeout)
{
return 0; /* timeout */
}
status = NETAvailable(self,timeout-dif);
};
};
assert(bufPtr > 0);
return bufPtr;
}
/*---------------------------------------------------------------------------*/
int NETClosePort(mkChannel *self)
{
@@ -544,6 +635,7 @@ CreateSocketAdress(
}
iRet = close(self->sockid);
gettimeofday(&lastclose, NULL);
self->iType = 0;
self->sockid = 0;
if(iRet < 0)
@@ -664,10 +756,11 @@ CreateSocketAdress(
}
assert(self->iType == UDP);
if(timeout > 0)
if(timeout >= 0)
{
/* setup for select first */
tmo.tv_usec = timeout;
tmo.tv_usec = (timeout % 1000) *1000;
tmo.tv_sec = timeout / 1000;
lMask = (1 << self->sockid);
iRet = select( (self->sockid + 1),(fd_set *)&lMask, NULL, NULL,&tmo);
if( iRet <= 0)