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