connectiontcpbase.cpp

00001 /*
00002   Copyright (c) 2004-2008 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 
00014 
00015 #include "gloox.h"
00016 
00017 #include "connectiontcpbase.h"
00018 #include "dns.h"
00019 #include "logsink.h"
00020 #include "prep.h"
00021 #include "mutexguard.h"
00022 
00023 #ifdef __MINGW32__
00024 # include <winsock.h>
00025 #endif
00026 
00027 #if !defined( WIN32 ) && !defined( _WIN32_WCE )
00028 # include <sys/types.h>
00029 # include <sys/socket.h>
00030 # include <sys/select.h>
00031 # include <unistd.h>
00032 #else
00033 # include <winsock.h>
00034 #endif
00035 
00036 #include <time.h>
00037 
00038 #include <cstdlib>
00039 #include <string>
00040 
00041 #ifndef _WIN32_WCE
00042 # include <sstream>
00043 #endif
00044 
00045 namespace gloox
00046 {
00047 
00048   ConnectionTCPBase::ConnectionTCPBase( const LogSink& logInstance,
00049                                         const std::string& server, int port )
00050     : ConnectionBase( 0 ),
00051       m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
00052       m_totalBytesOut( 0 ), m_bufsize( 1024 ), m_cancel( true )
00053   {
00054     init( server, port );
00055   }
00056 
00057   ConnectionTCPBase::ConnectionTCPBase( ConnectionDataHandler *cdh, const LogSink& logInstance,
00058                                         const std::string& server, int port )
00059     : ConnectionBase( cdh ),
00060       m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
00061       m_totalBytesOut( 0 ), m_bufsize( 1024 ), m_cancel( true )
00062   {
00063     init( server, port );
00064   }
00065 
00066   void ConnectionTCPBase::init( const std::string& server, int port )
00067   {
00068     m_server = prep::idna( server );
00069     m_port = port;
00070     m_buf = (char*)calloc( m_bufsize + 1, sizeof( char ) );
00071   }
00072 
00073   ConnectionTCPBase::~ConnectionTCPBase()
00074   {
00075     cleanup();
00076     free( m_buf );
00077     m_buf = 0;
00078   }
00079 
00080   void ConnectionTCPBase::disconnect()
00081   {
00082     MutexGuard rm( m_recvMutex );
00083     m_cancel = true;
00084   }
00085 
00086   bool ConnectionTCPBase::dataAvailable( int timeout )
00087   {
00088     if( m_socket < 0 )
00089       return true; // let recv() catch the closed fd
00090 
00091     fd_set fds;
00092     struct timeval tv;
00093 
00094     FD_ZERO( &fds );
00095     FD_SET( m_socket, &fds );
00096 
00097     tv.tv_sec = timeout / 1000000;
00098     tv.tv_usec = timeout % 1000000;
00099 
00100     return ( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 )
00101              && FD_ISSET( m_socket, &fds ) != 0 );
00102   }
00103 
00104   ConnectionError ConnectionTCPBase::receive()
00105   {
00106     if( m_socket < 0 )
00107       return ConnNotConnected;
00108 
00109     ConnectionError err = ConnNoError;
00110     while( !m_cancel && ( err = recv( 10 ) ) == ConnNoError )
00111       ;
00112     return err == ConnNoError ? ConnNotConnected : err;
00113   }
00114 
00115   bool ConnectionTCPBase::send( const std::string& data )
00116   {
00117     m_sendMutex.lock();
00118 
00119     if( data.empty() || ( m_socket < 0 ) )
00120     {
00121       m_sendMutex.unlock();
00122       return false;
00123     }
00124 
00125     int sent = 0;
00126     for( size_t num = 0, len = data.length(); sent != -1 && num < len; num += sent )
00127     {
00128 #ifdef SKYOS
00129       sent = ::send( m_socket, (unsigned char*)(data.c_str()+num), len - num, 0 );
00130 #else
00131       sent = ::send( m_socket, (data.c_str()+num), len - num, 0 );
00132 #endif
00133     }
00134 
00135     m_totalBytesOut += data.length();
00136 
00137     m_sendMutex.unlock();
00138 
00139     if( sent == -1 && m_handler )
00140       m_handler->handleDisconnect( this, ConnIoError );
00141 
00142     return sent != -1;
00143   }
00144 
00145   void ConnectionTCPBase::getStatistics( int &totalIn, int &totalOut )
00146   {
00147     totalIn = m_totalBytesIn;
00148     totalOut = m_totalBytesOut;
00149   }
00150 
00151   void ConnectionTCPBase::cleanup()
00152   {
00153     if( m_socket >= 0 )
00154     {
00155       DNS::closeSocket( m_socket );
00156       m_socket = -1;
00157     }
00158 
00159     MutexGuard sm( m_sendMutex );
00160     MutexGuard rm( m_recvMutex );
00161     m_state = StateDisconnected;
00162     m_cancel = true;
00163     m_totalBytesIn = 0;
00164     m_totalBytesOut = 0;
00165   }
00166 
00167 }

Generated on Fri Oct 10 15:26:11 2008 for gloox by  doxygen 1.5.6