Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

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 // FIXME check return value?
00069     prep::idna( server, m_server );
00070     m_port = port;
00071     m_buf = (char*)calloc( m_bufsize + 1, sizeof( char ) );
00072   }
00073 
00074   ConnectionTCPBase::~ConnectionTCPBase()
00075   {
00076     cleanup();
00077     free( m_buf );
00078     m_buf = 0;
00079   }
00080 
00081   void ConnectionTCPBase::disconnect()
00082   {
00083     MutexGuard rm( m_recvMutex );
00084     m_cancel = true;
00085   }
00086 
00087   bool ConnectionTCPBase::dataAvailable( int timeout )
00088   {
00089     if( m_socket < 0 )
00090       return true; // let recv() catch the closed fd
00091 
00092     fd_set fds;
00093     struct timeval tv;
00094 
00095     FD_ZERO( &fds );
00096     FD_SET( m_socket, &fds );
00097 
00098     tv.tv_sec = timeout / 1000000;
00099     tv.tv_usec = timeout % 1000000;
00100 
00101     return ( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 )
00102              && FD_ISSET( m_socket, &fds ) != 0 );
00103   }
00104 
00105   ConnectionError ConnectionTCPBase::receive()
00106   {
00107     if( m_socket < 0 )
00108       return ConnNotConnected;
00109 
00110     ConnectionError err = ConnNoError;
00111     while( !m_cancel && ( err = recv( 10 ) ) == ConnNoError )
00112       ;
00113     return err == ConnNoError ? ConnNotConnected : err;
00114   }
00115 
00116   bool ConnectionTCPBase::send( const std::string& data )
00117   {
00118     m_sendMutex.lock();
00119 
00120     if( data.empty() || ( m_socket < 0 ) )
00121     {
00122       m_sendMutex.unlock();
00123       return false;
00124     }
00125 
00126     int sent = 0;
00127     for( size_t num = 0, len = data.length(); sent != -1 && num < len; num += sent )
00128     {
00129 #ifdef SKYOS
00130       sent = ::send( m_socket, (unsigned char*)(data.c_str()+num), len - num, 0 );
00131 #else
00132       sent = ::send( m_socket, (data.c_str()+num), len - num, 0 );
00133 #endif
00134     }
00135 
00136     m_totalBytesOut += data.length();
00137 
00138     m_sendMutex.unlock();
00139 
00140     if( sent == -1 && m_handler )
00141       m_handler->handleDisconnect( this, ConnIoError );
00142 
00143     return sent != -1;
00144   }
00145 
00146   void ConnectionTCPBase::getStatistics( int &totalIn, int &totalOut )
00147   {
00148     totalIn = m_totalBytesIn;
00149     totalOut = m_totalBytesOut;
00150   }
00151 
00152   void ConnectionTCPBase::cleanup()
00153   {
00154     if( m_socket >= 0 )
00155     {
00156       DNS::closeSocket( m_socket );
00157       m_socket = -1;
00158     }
00159 
00160     MutexGuard sm( m_sendMutex );
00161     MutexGuard rm( m_recvMutex );
00162     m_state = StateDisconnected;
00163     m_cancel = true;
00164     m_totalBytesIn = 0;
00165     m_totalBytesOut = 0;
00166   }
00167 
00168 }

Generated on Mon Oct 13 10:45:10 2008 for gloox by  doxygen 1.4.1