PSI sics-cvs-psi-2008-10-02
This commit is contained in:
246
network.c
246
network.c
@@ -39,6 +39,7 @@
|
||||
----------------------------------------------------------------------------*/
|
||||
#include "fortify.h"
|
||||
#include "network.h"
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -64,10 +65,15 @@ struct timeval lastclose={-1,0};
|
||||
*/
|
||||
#include "Scommon.h"
|
||||
extern void SICSLogWrite(char *pText, OutCode eCode); /* servlog.c */
|
||||
|
||||
void WriteToCommandLog(char *p, char *t);
|
||||
|
||||
static void NetError(char *pText)
|
||||
{
|
||||
/*
|
||||
SICSLogWrite(pText,eError);
|
||||
*/
|
||||
WriteToCommandLog("NET>", pText);
|
||||
}
|
||||
|
||||
/* ---------------------------- Local ------------------------------------
|
||||
@@ -170,7 +176,8 @@ CreateSocketAdress(
|
||||
int iRet;
|
||||
fd_set lMask;
|
||||
struct timeval tmo = {1,0};
|
||||
int iLen, i;
|
||||
int i;
|
||||
socklen_t iLen;
|
||||
struct linger lili;
|
||||
|
||||
assert(self != NULL);
|
||||
@@ -378,7 +385,7 @@ CreateSocketAdress(
|
||||
{
|
||||
|
||||
int t;
|
||||
int len;
|
||||
socklen_t len;
|
||||
struct sockaddr_in sin;
|
||||
struct hostent *host;
|
||||
|
||||
@@ -403,6 +410,7 @@ CreateSocketAdress(
|
||||
else
|
||||
{
|
||||
strncpy(pCompost,host->h_name,iBufLen);
|
||||
pCompost[iBufLen-1]='\0';
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@@ -410,11 +418,15 @@ CreateSocketAdress(
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int NETWrite(mkChannel *self, char *buffer, long lLen)
|
||||
{
|
||||
int iRet;
|
||||
long iRet;
|
||||
fd_set lMask;
|
||||
struct timeval tmo ={0,1};
|
||||
|
||||
|
||||
struct timeval tmo;
|
||||
char buf[256];
|
||||
time_t expire, delta;
|
||||
char *pos;
|
||||
long l;
|
||||
int disconnected;
|
||||
|
||||
if(!VerifyChannel(self))
|
||||
{
|
||||
return 0;
|
||||
@@ -424,46 +436,87 @@ CreateSocketAdress(
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CYGNUS
|
||||
/* setup for select first */
|
||||
tmo.tv_usec = 100;
|
||||
FD_ZERO(&lMask);
|
||||
FD_SET(self->sockid,&lMask);
|
||||
/*
|
||||
* Check if the we can write to the socket first....
|
||||
* Well, this how it should be. However, on linux I observe that
|
||||
* there is a problem with Java clients not reliably receiving data when
|
||||
* this is active.
|
||||
*/
|
||||
if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) )
|
||||
/* invalid descriptor */
|
||||
{
|
||||
return -1; /* eof */
|
||||
/* invalid descriptor */
|
||||
return 0;
|
||||
}
|
||||
iRet = select( (self->sockid + 1),NULL, &lMask, NULL,&tmo);
|
||||
if( iRet <= 0)
|
||||
{
|
||||
/* failure, or no data */
|
||||
return -1;
|
||||
}
|
||||
/* blocking on write */
|
||||
if(!FD_ISSET(self->sockid,&lMask))
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
#ifdef DO_NOT_SELECT_BEFORE_SEND
|
||||
iRet = send(self->sockid,buffer,lLen,0);
|
||||
if(iRet != lLen)
|
||||
{
|
||||
if(iRet < 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (iRet != lLen) {
|
||||
self->iType = 0;
|
||||
if (iRet < 0) {
|
||||
if (errno == EPIPE) { /* do not write "broken pipe" error */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
snprintf(buf, sizeof buf, "NETWrite: send system error: %s (socket %d)",
|
||||
strerror(errno), self->sockid);
|
||||
} else {
|
||||
snprintf(buf, sizeof buf, "NETWrite: only %ld of %ld bytes sent (socket %d)",
|
||||
iRet, lLen, self->sockid);
|
||||
}
|
||||
NetError(buf);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
pos = buffer;
|
||||
l = lLen;
|
||||
FD_ZERO(&lMask);
|
||||
disconnected = 0;
|
||||
|
||||
#define TIMEOUT 10
|
||||
expire = time(NULL) + TIMEOUT;
|
||||
while (l > 0) {
|
||||
delta = expire - time(NULL);
|
||||
if (delta <= 0) break;
|
||||
FD_SET(self->sockid,&lMask);
|
||||
tmo.tv_usec = 0;
|
||||
tmo.tv_sec = delta;
|
||||
iRet = select( (self->sockid + 1),NULL, &lMask, NULL,&tmo);
|
||||
if (iRet < 0) {
|
||||
/* failure, or no data */
|
||||
self->iType = 0;
|
||||
snprintf(buf, sizeof buf,
|
||||
"NETWrite: failure on select before send: %s (socket %d)",
|
||||
strerror(errno), self->sockid);
|
||||
NetError(buf);
|
||||
return 0;
|
||||
}
|
||||
if (!FD_ISSET(self->sockid,&lMask)) break;
|
||||
|
||||
iRet = send(self->sockid,pos,l,0);
|
||||
disconnected = (iRet == 0);
|
||||
if (iRet < 0) {
|
||||
self->iType = 0;
|
||||
if (errno == EPIPE || errno == ECONNRESET) { /* do not write these errors */
|
||||
return 0;
|
||||
}
|
||||
snprintf(buf, sizeof buf, "NETWrite: send system error: %s (socket %d)",
|
||||
strerror(errno), self->sockid);
|
||||
NetError(buf);
|
||||
return 0;
|
||||
}
|
||||
l -= iRet;
|
||||
pos += iRet;
|
||||
}
|
||||
if (l > 0) {
|
||||
self->iType = 0;
|
||||
if (!disconnected) { /* do not write an error message on disconnect */
|
||||
snprintf(buf, sizeof buf, "NETWrite: timeout, only %ld of %ld bytes sent (socket %d) %ld.%6.6ld",
|
||||
lLen - l, lLen, self->sockid, (long)tmo.tv_sec, (long)tmo.tv_usec);
|
||||
NetError(buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* -------------------------------------------------------------------------*/
|
||||
long NETRead(mkChannel *self, char *buffer, long lLen, long timeout)
|
||||
@@ -555,7 +608,7 @@ int NETReadTillTerm(mkChannel *self, long timeout,
|
||||
char *pTerm, char *pBuffer, int iBufLen)
|
||||
{
|
||||
struct timeval start, now;
|
||||
int bufPtr = 0, status, i, length;
|
||||
int bufPtr = 0, status, i, length, matchIndex=1;
|
||||
char c;
|
||||
long dif;
|
||||
|
||||
@@ -583,11 +636,29 @@ int NETReadTillTerm(mkChannel *self, long timeout,
|
||||
{
|
||||
return status;
|
||||
}
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
if(c == pTerm[i])
|
||||
if ('&' != pTerm[0]) {
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
return bufPtr+1;
|
||||
if(c == pTerm[i])
|
||||
{
|
||||
return bufPtr+1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (matchIndex == 1 && c == pTerm[1]) {
|
||||
matchIndex++;
|
||||
} else {
|
||||
if (c== pTerm[matchIndex] && matchIndex < length -1) {
|
||||
matchIndex++;
|
||||
} else {
|
||||
if (c == pTerm[matchIndex] && matchIndex == length - 1) {
|
||||
bufPtr = bufPtr - matchIndex + 1;
|
||||
pBuffer[bufPtr] = '\0';
|
||||
return bufPtr;
|
||||
} else {
|
||||
matchIndex = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c == 0 && *pTerm != 0)
|
||||
@@ -644,6 +715,89 @@ int NETReadTillTerm(mkChannel *self, long timeout,
|
||||
return 1;
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int NETReconnectWithFlags(mkChannel* self, int flags)
|
||||
{
|
||||
int iRet;
|
||||
int sock;
|
||||
int oldopts;
|
||||
|
||||
/*
|
||||
* Get the flags and close the old socket
|
||||
*/
|
||||
oldopts = fcntl(self->sockid, F_GETFL, 0);
|
||||
close(self->sockid);
|
||||
/* Reopen and try to get it on the olf fd */
|
||||
sock = socket(AF_INET,SOCK_STREAM,0);
|
||||
if (self->sockid != sock) {
|
||||
iRet = fcntl(sock, F_DUPFD, self->sockid);
|
||||
if (iRet != sock)
|
||||
self->sockid = sock;
|
||||
else
|
||||
close(sock);
|
||||
sock = self->sockid;
|
||||
}
|
||||
/* restore the old flags */
|
||||
fcntl(self->sockid, F_SETFL, oldopts);
|
||||
/* set socket non-blocking */
|
||||
oldopts = fcntl(self->sockid, F_GETFL, 0);
|
||||
if (/*(flags & 1) &&*/ !(oldopts & O_NONBLOCK))
|
||||
fcntl(self->sockid, F_SETFL, oldopts | O_NONBLOCK);
|
||||
/* try to reconnect */
|
||||
iRet = connect(self->sockid,
|
||||
(struct sockaddr *)&(self->adresse),
|
||||
sizeof(struct sockaddr_in));
|
||||
if (iRet < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
if ((flags & 1)) {
|
||||
iRet = 0; /* in progress */
|
||||
} else {
|
||||
fd_set rmask;
|
||||
fd_set wmask;
|
||||
struct timeval tmo = {1,0};
|
||||
|
||||
FD_ZERO(&rmask);
|
||||
FD_ZERO(&wmask);
|
||||
FD_SET(self->sockid, &rmask);
|
||||
FD_SET(self->sockid, &wmask);
|
||||
iRet = select(self->sockid+1, &rmask, &wmask, NULL, &tmo);
|
||||
if (iRet < 0) /* error */
|
||||
iRet = -1;
|
||||
else if (iRet == 0) /* timeout */
|
||||
iRet = 0; /* in progress */
|
||||
else {
|
||||
char reply[1];
|
||||
if (FD_ISSET(self->sockid, &rmask)) {
|
||||
iRet = recv(self->sockid, reply, 1, MSG_PEEK);
|
||||
if (iRet <= 0)
|
||||
iRet = -1; /* failure */
|
||||
}
|
||||
if (FD_ISSET(self->sockid, &wmask)) {
|
||||
iRet = send(self->sockid, NULL, 0, 0);
|
||||
if (iRet < 0)
|
||||
iRet = -1; /* failure */
|
||||
else
|
||||
iRet = 1; /* success */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* other error */
|
||||
iRet = -1; /* error */
|
||||
}
|
||||
else
|
||||
iRet = 1; /* success */
|
||||
|
||||
if (iRet != 0 && !(oldopts & O_NONBLOCK))
|
||||
fcntl(self->sockid, F_SETFL, oldopts);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
int NETReconnect(mkChannel* self)
|
||||
{
|
||||
return NETReconnectWithFlags(self, 0);
|
||||
}
|
||||
|
||||
/* ################### UDP -functions ######################################*/
|
||||
mkChannel *UDPOpen(int iPort)
|
||||
{
|
||||
@@ -748,7 +902,7 @@ int NETReadTillTerm(mkChannel *self, long timeout,
|
||||
long lMask = 0L;
|
||||
struct timeval tmo ={0,1};
|
||||
long iRet;
|
||||
int iLang;
|
||||
socklen_t iLang;
|
||||
|
||||
if(!VerifyChannel(self))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user