diff --git a/network.c b/network.c index acdddfd5..c75e34f4 100644 --- a/network.c +++ b/network.c @@ -39,6 +39,7 @@ ----------------------------------------------------------------------------*/ #include "fortify.h" #include "network.h" +#include #include #include #include @@ -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 ------------------------------------ @@ -404,6 +410,7 @@ CreateSocketAdress( else { strncpy(pCompost,host->h_name,iBufLen); + pCompost[iBufLen-1]='\0'; } } return 1; @@ -411,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; @@ -429,48 +440,83 @@ CreateSocketAdress( * 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. + * this is active. */ -#ifndef CYGNUS - tmo.tv_usec = 10; - FD_ZERO(&lMask); - FD_SET(self->sockid,&lMask); 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)", + lLen - l, lLen, self->sockid); + NetError(buf); + } + return 0; + } + return 1; } /* -------------------------------------------------------------------------*/ long NETRead(mkChannel *self, char *buffer, long lLen, long timeout)