- allow empty terminator in NETReadTillTermNew
- introduced NETReadFinished and NETConnectWithFlags
This commit is contained in:
117
network.c
117
network.c
@ -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:
|
||||
|
19
network.h
19
network.h
@ -58,6 +58,18 @@
|
||||
and port. Returns NULL on failure, a struct else
|
||||
*/
|
||||
|
||||
mkChannel *NETConnectWithFlags(char *name, int port, int flags);
|
||||
/* the same as NETConnect, but with flags:
|
||||
if (flags & 1): do not block on connect (use NETConnectFinished
|
||||
to check success)
|
||||
if (flags & 2): wait 1000 ms after last close (workaround for
|
||||
a bug in Lantronix terminal server
|
||||
*/
|
||||
|
||||
int NETConnectFinished(mkChannel *self);
|
||||
/* returns 0 if in progress, 1 on success, a negative value on error
|
||||
*/
|
||||
|
||||
int NETInfo(mkChannel *self, char *pComposter, int iBufLen);
|
||||
/* Once a socket is connected it is possible to figure out
|
||||
which host the connection came from. Maximum iBufLen characters
|
||||
@ -90,12 +102,15 @@
|
||||
been found. The data is copied into the buffer pBuffer. A
|
||||
maximum length of iBufLen characters is observed. The timeout
|
||||
parameter defines a maximum time to wait for a terminator to
|
||||
appear. NETReadTillTerm returns 1 on success, 0 on a timeout,
|
||||
appear. NETReadTillTerm returns the number of characters read
|
||||
(including terminator) on success, 0 on a timeout,
|
||||
and a negative value if a network error occurred. Beware that
|
||||
this may not work correctly if the wrong terminator is given.
|
||||
The last one is really needed.
|
||||
In the new version, timeout is in MILLIseconds (10 -3 sec).
|
||||
However, the accuracy is machine dependent (for Linux 10 ms, for Tru64 1 ms)
|
||||
However, the accuracy is machine dependent (for Linux 10 ms, for Tru64 1 ms)
|
||||
If no terminator is given, the routine waits for iBufLen characters
|
||||
or timeout.
|
||||
*/
|
||||
/* ********************* KILLING FIELD ******************************** */
|
||||
int NETClosePort(mkChannel *self);
|
||||
|
Reference in New Issue
Block a user