gloox 1.0
|
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 }