- allow empty terminator in NETReadTillTermNew

- introduced NETReadFinished and NETConnectWithFlags
This commit is contained in:
zolliker
2005-09-05 08:18:22 +00:00
parent 476ad8d672
commit 15a307eef8
2 changed files with 113 additions and 23 deletions

117
network.c
View File

@ -49,6 +49,7 @@
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#define PORT 1
#define SOCKET 2
@ -206,19 +207,21 @@ 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, cnt;
@ -227,6 +230,7 @@ CreateSocketAdress(
struct linger lili;
struct timeval now;
long dif;
int oldopts;
assert(port > 0);
@ -255,22 +259,38 @@ CreateSocketAdress(
free(pRes);
return NULL;
}
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 (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 (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);
@ -284,6 +304,51 @@ CreateSocketAdress(
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 bmode */
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) {
if (FD_ISSET(self->sockid, &wmask)) {
if (FD_ISSET(self->sockid, &rmask)) {
iret = recv(self->sockid, NULL, 0, 0);
if (iret >= 0) {
iret = 1;
}
} else {
iret = send(self->sockid, NULL, 0, 0);
if (iret >= 0) {
iret = 1;
}
}
}
}
/* reset to blocking mode */
fcntl(self->sockid, F_SETFL, oldopts | ~ O_NONBLOCK);
return iret;
}
/*------------------------------------------------------------------------*/
int VerifyChannel(mkChannel *self)
{
@ -379,10 +444,13 @@ CreateSocketAdress(
iRet = send(self->sockid,buffer,lLen,0);
if(iRet != lLen)
{
printf("Incomplete send: %d to %ld\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;
}
@ -493,6 +561,8 @@ int NETReadTillTermNew(mkChannel *self, long timeout,
gettimeofday(&start, NULL);
if (pTerm == NULL) pTerm="";
length = strlen(pTerm);
memset(pBuffer,0,iBufLen);
@ -512,20 +582,24 @@ int NETReadTillTermNew(mkChannel *self, long timeout,
{
if(c == pTerm[i])
{
return 1;
return bufPtr+1;
}
}
if(c != 0) /* skip null characters */
if (c == 0 && *pTerm != 0)
{
if(bufPtr >= iBufLen-1)
{
/* 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;
bufPtr++;
} else {
return -1;
return bufPtr+1;
}
pBuffer[bufPtr] = c;
bufPtr++;
/*
wait for more data
*/
@ -542,7 +616,8 @@ int NETReadTillTermNew(mkChannel *self, long timeout,
status = NETAvailable(self,timeout-dif);
};
};
return status;
assert(bufPtr > 0);
return bufPtr;
}
/*--------------------------------------------------------------------------
This old version may be removed in some stage. It has two problems: