gloox 1.0

connectiontcpclient.cpp

00001 /*
00002   Copyright (c) 2004-2009 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 "connectiontcpclient.h"
00018 #include "dns.h"
00019 #include "logsink.h"
00020 #include "mutexguard.h"
00021 
00022 #ifdef __MINGW32__
00023 # include <winsock.h>
00024 #endif
00025 
00026 #if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
00027 # include <sys/types.h>
00028 # include <sys/socket.h>
00029 # include <sys/select.h>
00030 # include <unistd.h>
00031 #elif ( defined( _WIN32 ) || defined( _WIN32_WCE ) ) && !defined( __SYMBIAN32__ )
00032 # include <winsock.h>
00033 #endif
00034 
00035 #include <cstdlib>
00036 #include <string>
00037 
00038 namespace gloox
00039 {
00040 
00041   ConnectionTCPClient::ConnectionTCPClient( const LogSink& logInstance,
00042                                             const std::string& server, int port )
00043     : ConnectionTCPBase( logInstance, server, port )
00044   {
00045   }
00046 
00047   ConnectionTCPClient::ConnectionTCPClient( ConnectionDataHandler* cdh, const LogSink& logInstance,
00048                                             const std::string& server, int port )
00049     : ConnectionTCPBase( cdh, logInstance, server, port )
00050   {
00051   }
00052 
00053 
00054   ConnectionTCPClient::~ConnectionTCPClient()
00055   {
00056   }
00057 
00058   ConnectionBase* ConnectionTCPClient::newInstance() const
00059   {
00060     return new ConnectionTCPClient( m_handler, m_logInstance, m_server, m_port );
00061   }
00062 
00063   ConnectionError ConnectionTCPClient::connect()
00064   {
00065     m_sendMutex.lock();
00066 // FIXME CHECKME
00067     if( !m_handler )
00068     {
00069       m_sendMutex.unlock();
00070       return ConnNotConnected;
00071     }
00072 
00073     if( m_socket >= 0 && m_state > StateDisconnected )
00074     {
00075       m_sendMutex.unlock();
00076       return ConnNoError;
00077     }
00078 
00079     m_state = StateConnecting;
00080 
00081     if( m_socket < 0 )
00082     {
00083       if( m_port == -1 )
00084         m_socket = DNS::connect( m_server, m_logInstance );
00085       else
00086         m_socket = DNS::connect( m_server, m_port, m_logInstance );
00087     }
00088 
00089     m_sendMutex.unlock();
00090 
00091     if( m_socket < 0 )
00092     {
00093       switch( m_socket )
00094       {
00095         case -ConnConnectionRefused:
00096           m_logInstance.err( LogAreaClassConnectionTCPClient,
00097                              m_server + ": connection refused" );
00098           break;
00099         case -ConnDnsError:
00100           m_logInstance.err( LogAreaClassConnectionTCPClient,
00101                              m_server + ": host not found" );
00102           break;
00103         default:
00104           m_logInstance.err( LogAreaClassConnectionTCPClient,
00105                              "Unknown error condition" );
00106           break;
00107       }
00108       m_handler->handleDisconnect( this, (ConnectionError)-m_socket );
00109       return (ConnectionError)-m_socket;
00110     }
00111     else
00112     {
00113       m_state = StateConnected;
00114     }
00115 
00116     m_cancel = false;
00117     m_handler->handleConnect( this );
00118     return ConnNoError;
00119   }
00120 
00121   ConnectionError ConnectionTCPClient::recv( int timeout )
00122   {
00123     m_recvMutex.lock();
00124 
00125     if( m_cancel || m_socket < 0 )
00126     {
00127       m_recvMutex.unlock();
00128       return ConnNotConnected;
00129     }
00130 
00131     if( !dataAvailable( timeout ) )
00132     {
00133       m_recvMutex.unlock();
00134       return ConnNoError;
00135     }
00136 
00137     int size = static_cast<int>( ::recv( m_socket, m_buf, m_bufsize, 0 ) );
00138     if( size > 0 )
00139       m_totalBytesIn += size;
00140 
00141     m_recvMutex.unlock();
00142 
00143     if( size <= 0 )
00144     {
00145       ConnectionError error = ( size ? ConnIoError : ConnStreamClosed );
00146       if( m_handler )
00147         m_handler->handleDisconnect( this, error );
00148       return error;
00149     }
00150 
00151     m_buf[size] = '\0';
00152 
00153     if( m_handler )
00154       m_handler->handleReceivedData( this, std::string( m_buf, size ) );
00155 
00156     return ConnNoError;
00157   }
00158 
00159 }