connectiontcpbase.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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 ) ) || defined( __SYMBIAN32__ )
00028 # include <arpa/inet.h>
00029 # include <sys/types.h>
00030 # include <sys/socket.h>
00031 # include <sys/select.h>
00032 # include <netinet/in.h>
00033 # include <unistd.h>
00034 #elif ( defined( _WIN32 ) || defined( _WIN32_WCE ) ) && !defined( __SYMBIAN32__ )
00035 # include <winsock.h>
00036 typedef int socklen_t;
00037 #endif
00038
00039 #include <ctime>
00040
00041 #include <cstdlib>
00042 #include <string>
00043
00044 namespace gloox
00045 {
00046
00047 ConnectionTCPBase::ConnectionTCPBase( const LogSink& logInstance,
00048 const std::string& server, int port )
00049 : ConnectionBase( 0 ),
00050 m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
00051 m_totalBytesOut( 0 ), m_bufsize( 1024 ), m_cancel( true )
00052 {
00053 init( server, port );
00054 }
00055
00056 ConnectionTCPBase::ConnectionTCPBase( ConnectionDataHandler* cdh, const LogSink& logInstance,
00057 const std::string& server, int port )
00058 : ConnectionBase( cdh ),
00059 m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
00060 m_totalBytesOut( 0 ), m_bufsize( 1024 ), m_cancel( true )
00061 {
00062 init( server, port );
00063 }
00064
00065 void ConnectionTCPBase::init( const std::string& server, int port )
00066 {
00067
00068 prep::idna( server, m_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 util::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;
00090
00091 fd_set fds;
00092 struct timeval tv;
00093
00094 FD_ZERO( &fds );
00095
00096
00097 FD_SET( m_socket, &fds );
00098
00099 tv.tv_sec = timeout / 1000000;
00100 tv.tv_usec = timeout % 1000000;
00101
00102 return ( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 )
00103 && FD_ISSET( m_socket, &fds ) != 0 );
00104 }
00105
00106 ConnectionError ConnectionTCPBase::receive()
00107 {
00108 if( m_socket < 0 )
00109 return ConnNotConnected;
00110
00111 ConnectionError err = ConnNoError;
00112 while( !m_cancel && ( err = recv( 10 ) ) == ConnNoError )
00113 ;
00114 return err == ConnNoError ? ConnNotConnected : err;
00115 }
00116
00117 bool ConnectionTCPBase::send( const std::string& data )
00118 {
00119 m_sendMutex.lock();
00120
00121 if( data.empty() || ( m_socket < 0 ) )
00122 {
00123 m_sendMutex.unlock();
00124 return false;
00125 }
00126
00127 int sent = 0;
00128 for( size_t num = 0, len = data.length(); sent != -1 && num < len; num += sent )
00129 {
00130 sent = static_cast<int>( ::send( m_socket, (data.c_str()+num), (int)(len - num), 0 ) );
00131 }
00132
00133 m_totalBytesOut += (int)data.length();
00134
00135 m_sendMutex.unlock();
00136
00137 if( sent == -1 && m_handler )
00138 m_handler->handleDisconnect( this, ConnIoError );
00139
00140 return sent != -1;
00141 }
00142
00143 void ConnectionTCPBase::getStatistics( long int &totalIn, long int &totalOut )
00144 {
00145 totalIn = m_totalBytesIn;
00146 totalOut = m_totalBytesOut;
00147 }
00148
00149 void ConnectionTCPBase::cleanup()
00150 {
00151 if( !m_sendMutex.trylock() )
00152 return;
00153
00154 if( !m_recvMutex.trylock() )
00155 {
00156 m_sendMutex.unlock();
00157 return;
00158 }
00159
00160 if( m_socket >= 0 )
00161 {
00162 DNS::closeSocket( m_socket, m_logInstance );
00163 m_socket = -1;
00164 }
00165
00166 m_state = StateDisconnected;
00167 m_cancel = true;
00168 m_totalBytesIn = 0;
00169 m_totalBytesOut = 0;
00170
00171 m_recvMutex.unlock(),
00172 m_sendMutex.unlock();
00173 }
00174
00175 int ConnectionTCPBase::localPort() const
00176 {
00177 struct sockaddr local;
00178 socklen_t len = (socklen_t)sizeof( local );
00179 if( getsockname ( m_socket, &local, &len ) < 0 )
00180 return -1;
00181 else
00182 return ntohs( ((struct sockaddr_in *)&local)->sin_port );
00183 }
00184
00185 const std::string ConnectionTCPBase::localInterface() const
00186 {
00187 struct sockaddr_in local;
00188 socklen_t len = (socklen_t)sizeof( local );
00189 if( getsockname ( m_socket, (reinterpret_cast<struct sockaddr*>( &local )), &len ) < 0 )
00190 return EmptyString;
00191 else
00192 {
00193
00194
00195 return inet_ntoa( local.sin_addr );
00196 }
00197 }
00198
00199 }