- 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 <arpa/inet.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#define PORT 1
|
#define PORT 1
|
||||||
#define SOCKET 2
|
#define SOCKET 2
|
||||||
@ -206,19 +207,21 @@ CreateSocketAdress(
|
|||||||
free(pRes);
|
free(pRes);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
i = sizeof(struct linger);
|
i = sizeof(struct linger);
|
||||||
lili.l_onoff = 1;
|
lili.l_onoff = 1;
|
||||||
lili.l_linger = 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;
|
i = 1;
|
||||||
setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int));
|
setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int));
|
||||||
*/ pRes->iType = SOCKET;
|
*/
|
||||||
|
pRes->iType = SOCKET;
|
||||||
pRes->lMagic = NETMAGIC;
|
pRes->lMagic = NETMAGIC;
|
||||||
return pRes;
|
return pRes;
|
||||||
|
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
mkChannel *NETConnect(char *name, int port)
|
mkChannel *NETConnectWithFlags(char *name, int port, int flags)
|
||||||
{
|
{
|
||||||
mkChannel *pRes = NULL;
|
mkChannel *pRes = NULL;
|
||||||
int iRet, i, cnt;
|
int iRet, i, cnt;
|
||||||
@ -227,6 +230,7 @@ CreateSocketAdress(
|
|||||||
struct linger lili;
|
struct linger lili;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
long dif;
|
long dif;
|
||||||
|
int oldopts;
|
||||||
|
|
||||||
assert(port > 0);
|
assert(port > 0);
|
||||||
|
|
||||||
@ -255,22 +259,38 @@ CreateSocketAdress(
|
|||||||
free(pRes);
|
free(pRes);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (lastclose.tv_sec >= 0) {
|
|
||||||
gettimeofday(&now, NULL);
|
if (flags & 2) { /* wait if closed recently */
|
||||||
dif = (now.tv_sec-lastclose.tv_sec)*1000+(now.tv_usec-lastclose.tv_usec)/1000;
|
/* workaround for a bug in Lantronix terminal server:
|
||||||
if (dif < 0) dif += 24*3600*1000;
|
if a channel is closed and reopened within short time
|
||||||
} else {
|
the connect will be succesful, but a message will be
|
||||||
dif = 0;
|
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),
|
iRet = connect(pRes->sockid,(struct sockaddr *)&(pRes->adresse),
|
||||||
sizeof(struct sockaddr_in));
|
sizeof(struct sockaddr_in));
|
||||||
if(iRet < 0)
|
if(iRet < 0)
|
||||||
{
|
{
|
||||||
|
if (errno != EINPROGRESS) {
|
||||||
free(pRes);
|
free(pRes);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
i = sizeof(struct linger);
|
i = sizeof(struct linger);
|
||||||
@ -284,6 +304,51 @@ CreateSocketAdress(
|
|||||||
pRes->lMagic = NETMAGIC;
|
pRes->lMagic = NETMAGIC;
|
||||||
return pRes;
|
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)
|
int VerifyChannel(mkChannel *self)
|
||||||
{
|
{
|
||||||
@ -379,10 +444,13 @@ CreateSocketAdress(
|
|||||||
iRet = send(self->sockid,buffer,lLen,0);
|
iRet = send(self->sockid,buffer,lLen,0);
|
||||||
if(iRet != lLen)
|
if(iRet != lLen)
|
||||||
{
|
{
|
||||||
printf("Incomplete send: %d to %ld\n",iRet,lLen);
|
|
||||||
if(iRet < 0)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -493,6 +561,8 @@ int NETReadTillTermNew(mkChannel *self, long timeout,
|
|||||||
|
|
||||||
gettimeofday(&start, NULL);
|
gettimeofday(&start, NULL);
|
||||||
|
|
||||||
|
if (pTerm == NULL) pTerm="";
|
||||||
|
|
||||||
length = strlen(pTerm);
|
length = strlen(pTerm);
|
||||||
memset(pBuffer,0,iBufLen);
|
memset(pBuffer,0,iBufLen);
|
||||||
|
|
||||||
@ -512,20 +582,24 @@ int NETReadTillTermNew(mkChannel *self, long timeout,
|
|||||||
{
|
{
|
||||||
if(c == pTerm[i])
|
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 */
|
return -1; /* overflow */
|
||||||
}
|
}
|
||||||
pBuffer[bufPtr] = c;
|
pBuffer[bufPtr] = c;
|
||||||
bufPtr++;
|
return bufPtr+1;
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
pBuffer[bufPtr] = c;
|
||||||
|
bufPtr++;
|
||||||
/*
|
/*
|
||||||
wait for more data
|
wait for more data
|
||||||
*/
|
*/
|
||||||
@ -542,7 +616,8 @@ int NETReadTillTermNew(mkChannel *self, long timeout,
|
|||||||
status = NETAvailable(self,timeout-dif);
|
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:
|
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
|
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);
|
int NETInfo(mkChannel *self, char *pComposter, int iBufLen);
|
||||||
/* Once a socket is connected it is possible to figure out
|
/* Once a socket is connected it is possible to figure out
|
||||||
which host the connection came from. Maximum iBufLen characters
|
which host the connection came from. Maximum iBufLen characters
|
||||||
@ -90,12 +102,15 @@
|
|||||||
been found. The data is copied into the buffer pBuffer. A
|
been found. The data is copied into the buffer pBuffer. A
|
||||||
maximum length of iBufLen characters is observed. The timeout
|
maximum length of iBufLen characters is observed. The timeout
|
||||||
parameter defines a maximum time to wait for a terminator to
|
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
|
and a negative value if a network error occurred. Beware that
|
||||||
this may not work correctly if the wrong terminator is given.
|
this may not work correctly if the wrong terminator is given.
|
||||||
The last one is really needed.
|
The last one is really needed.
|
||||||
In the new version, timeout is in MILLIseconds (10 -3 sec).
|
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 ******************************** */
|
/* ********************* KILLING FIELD ******************************** */
|
||||||
int NETClosePort(mkChannel *self);
|
int NETClosePort(mkChannel *self);
|
||||||
|
Reference in New Issue
Block a user