gloox 1.0
connectiontcpserver.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 "connectiontcpserver.h"
00018 #include "connectiontcpclient.h"
00019 #include "connectionhandler.h"
00020 #include "dns.h"
00021 #include "logsink.h"
00022 #include "mutex.h"
00023 #include "mutexguard.h"
00024 #include "util.h"
00025 
00026 #ifdef __MINGW32__
00027 # include <winsock.h>
00028 #endif
00029 
00030 #if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
00031 # include <netinet/in.h>
00032 # include <arpa/nameser.h>
00033 # include <resolv.h>
00034 # include <netdb.h>
00035 # include <arpa/inet.h>
00036 # include <sys/socket.h>
00037 # include <sys/un.h>
00038 # include <sys/select.h>
00039 # include <unistd.h>
00040 # include <errno.h>
00041 #endif
00042 
00043 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
00044 # include <winsock.h>
00045 #elif defined( _WIN32_WCE )
00046 # include <winsock2.h>
00047 #endif
00048 
00049 #include <cstdlib>
00050 #include <string>
00051 
00052 #ifndef _WIN32_WCE
00053 # include <sys/types.h>
00054 #endif
00055 
00056 namespace gloox
00057 {
00058 
00059   ConnectionTCPServer::ConnectionTCPServer( ConnectionHandler* ch, const LogSink& logInstance,
00060                                             const std::string& ip, int port )
00061     : ConnectionTCPBase( 0, logInstance, ip, port ),
00062       m_connectionHandler( ch )
00063   {
00064   }
00065 
00066   ConnectionTCPServer::~ConnectionTCPServer()
00067   {
00068   }
00069 
00070   ConnectionBase* ConnectionTCPServer::newInstance() const
00071   {
00072     return new ConnectionTCPServer( m_connectionHandler, m_logInstance, m_server, m_port );
00073   }
00074 
00075   ConnectionError ConnectionTCPServer::connect()
00076   {
00077     util::MutexGuard mg( &m_sendMutex );
00078 
00079     if( m_socket >= 0 || m_state > StateDisconnected )
00080       return ConnNoError;
00081 
00082     m_state = StateConnecting;
00083 
00084     if( m_socket < 0 )
00085       m_socket = DNS::getSocket( m_logInstance );
00086 
00087     if( m_socket < 0 )
00088       return ConnIoError;
00089 
00090     struct sockaddr_in local;
00091     local.sin_family = AF_INET;
00092     local.sin_port = static_cast<unsigned short int>( htons( m_port ) );
00093     local.sin_addr.s_addr = m_server.empty() ? INADDR_ANY : inet_addr( m_server.c_str() );
00094     memset( local.sin_zero, '\0', 8 );
00095 
00096     if( bind( m_socket, (struct sockaddr*)&local, sizeof( struct sockaddr ) ) < 0 )
00097     {
00098       std::string message = "bind() to " + ( m_server.empty() ? std::string( "*" ) : m_server )
00099           + " (" + inet_ntoa( local.sin_addr ) + ":" + util::int2string( m_port ) + ") failed. "
00100 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
00101           "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
00102 #else
00103           "errno: " + util::int2string( errno );
00104 #endif
00105       m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
00106 
00107       return ConnIoError;
00108     }
00109 
00110     if( listen( m_socket, 10 ) < 0 )
00111     {
00112       std::string message = "listen on " + ( m_server.empty() ? std::string( "*" ) : m_server )
00113           + " (" + inet_ntoa( local.sin_addr ) + ":" + util::int2string( m_port ) + ") failed. "
00114 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
00115           "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
00116 #else
00117           "errno: " + util::int2string( errno );
00118 #endif
00119       m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
00120 
00121       return ConnIoError;
00122     }
00123 
00124     m_cancel = false;
00125     return ConnNoError;
00126   }
00127 
00128   ConnectionError ConnectionTCPServer::recv( int timeout )
00129   {
00130     m_recvMutex.lock();
00131 
00132     if( m_cancel || m_socket < 0 || !m_connectionHandler )
00133     {
00134       m_recvMutex.unlock();
00135       return ConnNotConnected;
00136     }
00137 
00138     if( !dataAvailable( timeout ) )
00139     {
00140       m_recvMutex.unlock();
00141       return ConnNoError;
00142     }
00143 
00144     struct sockaddr_in they;
00145     int sin_size = sizeof( struct sockaddr_in );
00146 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
00147     int newfd = static_cast<int>( accept( static_cast<SOCKET>( m_socket ), (struct sockaddr*)&they, &sin_size ) );
00148 #else
00149     int newfd = accept( m_socket, (struct sockaddr*)&they, (socklen_t*)&sin_size );
00150 #endif
00151 
00152     m_recvMutex.unlock();
00153 
00154     ConnectionTCPClient* conn = new ConnectionTCPClient( m_logInstance, inet_ntoa( they.sin_addr ),
00155                                                          ntohs( they.sin_port ) );
00156     conn->setSocket( newfd );
00157     m_connectionHandler->handleIncomingConnection( this, conn );
00158 
00159     return ConnNoError;
00160   }
00161 
00162 }