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 )
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;
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 }