From f4c20290509d7ed3a8fd5304577e7a4cc0b9d974 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 3 Apr 2007 03:49:53 +0000 Subject: Ok, no code is left in src, it's all in src/old. We'll gradually move code back into src as it's fixed and re-org'd. This includes tests, which, I may write a unit test system into libbu++ just to make my life easier. --- src/old/connection.cpp | 564 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 564 insertions(+) create mode 100644 src/old/connection.cpp (limited to 'src/old/connection.cpp') diff --git a/src/old/connection.cpp b/src/old/connection.cpp new file mode 100644 index 0000000..efef144 --- /dev/null +++ b/src/old/connection.cpp @@ -0,0 +1,564 @@ +#include "connection.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "exceptions.h" + +// Read buffer size...maybe fix wierd issues... +#define RBS (1024*10) + +Connection::Connection() +{ + nSocket = -1; + bActive = false; + bDisconnectMe = false; + pProtocol = NULL; +} + +Connection::~Connection() +{ + if( pProtocol != NULL ) delete pProtocol; +} + +void Connection::ensureCapacity( int nSize ) +{ + xOutputBuf.ensureCapacity( nSize ); +} + +bool Connection::appendOutput( const char *lpOutput, int nSize ) +{ + return xOutputBuf.appendData( lpOutput, nSize ); +} + +bool Connection::appendOutput( const char lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const short lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const int lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const long lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const float lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const double lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const unsigned char lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const unsigned short lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const unsigned long lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const unsigned int lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendInput( const char *lpInput, int nSize ) +{ + return xInputBuf.appendData( lpInput, nSize ); +} + +int Connection::scanInputFor( char cTarget ) +{ + const char *lpTmp = xInputBuf.getData(); + int jMax = xInputBuf.getLength(); + + for( int j = 0; j < jMax; j++ ) + { + if( lpTmp[j] == cTarget ) + { + return j; + } + } + + return -1; +} + +const char *Connection::getOutput() +{ + return xOutputBuf.getData(); +} + +const char *Connection::getInput() +{ + return xInputBuf.getData(); +} + +void Connection::setSocket( int nNewSocket ) +{ + nSocket = nNewSocket; +} + +int Connection::getSocket() +{ + return nSocket; +} + +bool Connection::isActive() +{ + return bActive; +} + +void Connection::close() +{ + //printf("Close called, socket is: %s\n", bActive?"Active":"Inactive" ); + if( bActive ) + { + fsync( nSocket ); + ::close( nSocket ); + //printf("Socket closed.\n"); + } + bActive = false; + //nSocket = -1; + xInputBuf.clearData(); + xOutputBuf.clearData(); + if( pProtocol != NULL ) + { + delete pProtocol; + pProtocol = NULL; + } +} + +bool Connection::open( int nNewSocket ) +{ + bActive = true; + setSocket( nNewSocket ); + bDisconnectMe = false; + + return true; +} + +bool Connection::open( const char *sAddr, int nPort, int nSec ) +{ + struct sockaddr_in xServerName; + bActive = false; + + /* Create the socket. */ + nSocket = socket( PF_INET, SOCK_STREAM, 0 ); + + if( nSocket < 0 ) + { + bActive = false; + return false; + } + + // These lines set the socket to non-blocking, a good thing? + int flags; + flags = fcntl(nSocket, F_GETFL, 0); + flags |= O_NONBLOCK; + if (fcntl(nSocket, F_SETFL, flags) < 0) + { + return false; + } + + /* Connect to the server. */ + //printf("Resolving hostname (%s)...\n", sAddr ); + { + struct hostent *hostinfo; + + xServerName.sin_family = AF_INET; + xServerName.sin_port = htons( nPort ); + hostinfo = gethostbyname( sAddr ); + if (hostinfo == NULL) + { + return false; + } + xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr; + } + + //printf("Making actual connection..."); + //fflush( stdout ); + connect( + nSocket, + (struct sockaddr *)&xServerName, + sizeof(xServerName) + ); + //printf("Connected.\n"); + + bActive = true; + bDisconnectMe = false; + + if( nSec > 0 ) + { + fd_set rfds, wfds, efds; + int retval; + + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + FD_ZERO(&wfds); + FD_SET(nSocket, &wfds); + FD_ZERO(&efds); + FD_SET(nSocket, &efds); + + struct timeval tv; + tv.tv_sec = nSec; + tv.tv_usec = 0; + + retval = select( nSocket+1, &rfds, &wfds, &efds, &tv ); + + if( retval == 0 ) + { + close(); + throw ExceptionBase("Connection timeout.\n"); + } + + } + + /* + if( ret < 0 ) + { + return false; + }*/ + + return true; +} + +int Connection::readInput() +{ + char buffer[RBS]; + int nbytes; + int nTotalRead=0; + + for(;;) + { + //memset( buffer, 0, RBS ); + + nbytes = read( nSocket, buffer, RBS ); + if( nbytes < 0 && errno != 0 && errno != EAGAIN ) + { + //printf("errno: %d, %s\n", errno, strerror( errno ) ); + /* Read error. */ + //perror("readInput"); + throw ConnectionException( excodeReadError, "Read error: %s", strerror( errno ) ); + } + else + { + if( nbytes <= 0 ) + break; + nTotalRead += nbytes; + appendInput( buffer, nbytes ); + /* Data read. */ + if( nbytes < RBS ) + { + break; + } + + /* New test, if data is divisible by RBS bytes on some libs the + * read could block, this keeps it from happening. + */ + { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + struct timeval tv = { 0, 0 }; + int retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); + if( retval == -1 ) + throw ConnectionException( + excodeBadReadError, + "Bad Read error" + ); + if( !FD_ISSET( nSocket, &rfds ) ) + break; + } + + } + } + + if( pProtocol != NULL && nTotalRead > 0 ) + { + pProtocol->onNewData(); + } + + return nTotalRead; +} + +bool Connection::readInput( int nSec, int nUSec, int *pnSecBack, int *pnUSecBack ) +{ + fd_set rfds, efds; + struct timeval tv, start, end; + struct timezone tz; + int retval; + + gettimeofday( &start, &tz ); + + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + FD_ZERO(&efds); + FD_SET(nSocket, &efds); + + tv.tv_sec = nSec; + tv.tv_usec = nUSec; + + //printf("Starting at %d %d\n", nSec, nUSec ); + retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); + + if( retval == -1 ) + { + // Oh my god!!! some kind of horrible problem!!!! + throw ConnectionException( excodeBadReadError, "Bad Read error"); + return false; + } + else if( retval ) + { + //printf("retval=%d, nSocket=%d,%d, sec=%d, usec=%d\n", retval, nSocket, FD_ISSET( nSocket, &rfds ), tv.tv_sec, tv.tv_usec ); + // None of them have data, but the connection is still active. + if( FD_ISSET( nSocket, &rfds ) ) + { + if( readInput() == 0 ) + { + throw ConnectionException( excodeConnectionClosed, "Connection closed"); } + } + } + + gettimeofday( &end, &tz ); + + int st, ust; + st = nSec - ( end.tv_sec - start.tv_sec ); + if( ( end.tv_usec - start.tv_usec ) > nUSec ) + { + (st)--; + ust = 1000000 - (end.tv_usec - start.tv_usec); + } + else + { + ust = nUSec - (end.tv_usec - start.tv_usec); + } + + if( st < 0 ) + { + st = ust = 0; + } + + if( pnSecBack ) + { + *pnSecBack = st; + *pnUSecBack = ust; + } + + //printf("New time: %d %d\n", *pnSecBack, *pnUSecBack ); + + return true; +} + +void Connection::waitForInput( int nBytesIn, int nSec, int nUSec ) +{ + int rlen = getInputAmnt(); + + if( rlen >= nBytesIn ) + return; + + while( rlen < nBytesIn ) + { + if( nSec == 0 && nUSec == 0 ) + { + throw ConnectionException( excodeSocketTimeout, "Timed out while waiting for %d bytes.", nBytesIn ); + } + readInput( nSec, nUSec, &nSec, &nUSec ); + rlen = getInputAmnt(); + } +} + +bool Connection::clearOutput() +{ + return xOutputBuf.clearData(); +} + +bool Connection::clearInput() +{ + return xInputBuf.clearData(); +} + +#define min( a, b ) ((asetConnection( this ); +} + +int Connection::getInputAmnt() +{ + return xInputBuf.getLength(); +} + +int Connection::getOutputAmnt() +{ + return xOutputBuf.getLength(); +} + +class Protocol *Connection::getProtocol() +{ + return pProtocol; +} + +void Connection::printInputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) +{ + printDataDebug( + (const unsigned char *)xInputBuf.getData(), + xInputBuf.getLength(), + "input", + lpPrefix, + fh, + nBytesMax + ); +} + +void Connection::printOutputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) +{ + printDataDebug( + (const unsigned char *)xOutputBuf.getData(), + xOutputBuf.getLength(), + "output", + lpPrefix, + fh, + nBytesMax + ); +} + +void Connection::printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ) +{ + if( nBytesMax > 0 ) + { + nDataLen = (nBytesMax32 && pData[j+k]<=128)?(pData[j+k]):('.') ); + } + fprintf( fh, "\n"); + j += kmax; + if( j >= nDataLen ) break; + } + fprintf( fh, lpPrefix ); + for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n"); +} + -- cgit v1.2.3