gloox  1.0
connectiontcpserver.cpp
1 /*
2  Copyright (c) 2004-2009 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 
15 #include "gloox.h"
16 
17 #include "connectiontcpserver.h"
18 #include "connectiontcpclient.h"
19 #include "connectionhandler.h"
20 #include "dns.h"
21 #include "logsink.h"
22 #include "mutex.h"
23 #include "mutexguard.h"
24 #include "util.h"
25 
26 #ifdef __MINGW32__
27 # include <winsock.h>
28 #endif
29 
30 #if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
31 # include <netinet/in.h>
32 # include <arpa/nameser.h>
33 # include <resolv.h>
34 # include <netdb.h>
35 # include <arpa/inet.h>
36 # include <sys/socket.h>
37 # include <sys/un.h>
38 # include <sys/select.h>
39 # include <unistd.h>
40 # include <errno.h>
41 #endif
42 
43 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
44 # include <winsock.h>
45 #elif defined( _WIN32_WCE )
46 # include <winsock2.h>
47 #endif
48 
49 #include <cstdlib>
50 #include <string>
51 
52 #ifndef _WIN32_WCE
53 # include <sys/types.h>
54 #endif
55 
56 namespace gloox
57 {
58 
60  const std::string& ip, int port )
61  : ConnectionTCPBase( 0, logInstance, ip, port ),
62  m_connectionHandler( ch )
63  {
64  }
65 
67  {
68  }
69 
71  {
72  return new ConnectionTCPServer( m_connectionHandler, m_logInstance, m_server, m_port );
73  }
74 
76  {
77  util::MutexGuard mg( &m_sendMutex );
78 
79  if( m_socket >= 0 || m_state > StateDisconnected )
80  return ConnNoError;
81 
83 
84  if( m_socket < 0 )
85  m_socket = DNS::getSocket( m_logInstance );
86 
87  if( m_socket < 0 )
88  return ConnIoError;
89 
90  struct sockaddr_in local;
91  local.sin_family = AF_INET;
92  local.sin_port = static_cast<unsigned short int>( htons( m_port ) );
93  local.sin_addr.s_addr = m_server.empty() ? INADDR_ANY : inet_addr( m_server.c_str() );
94  memset( local.sin_zero, '\0', 8 );
95 
96  if( bind( m_socket, (struct sockaddr*)&local, sizeof( struct sockaddr ) ) < 0 )
97  {
98  std::string message = "bind() to " + ( m_server.empty() ? std::string( "*" ) : m_server )
99  + " (" + inet_ntoa( local.sin_addr ) + ":" + util::int2string( m_port ) + ") failed. "
100 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
101  "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
102 #else
103  "errno: " + util::int2string( errno );
104 #endif
105  m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
106 
107  return ConnIoError;
108  }
109 
110  if( listen( m_socket, 10 ) < 0 )
111  {
112  std::string message = "listen on " + ( m_server.empty() ? std::string( "*" ) : m_server )
113  + " (" + inet_ntoa( local.sin_addr ) + ":" + util::int2string( m_port ) + ") failed. "
114 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
115  "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
116 #else
117  "errno: " + util::int2string( errno );
118 #endif
119  m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
120 
121  return ConnIoError;
122  }
123 
124  m_cancel = false;
125  return ConnNoError;
126  }
127 
129  {
130  m_recvMutex.lock();
131 
132  if( m_cancel || m_socket < 0 || !m_connectionHandler )
133  {
134  m_recvMutex.unlock();
135  return ConnNotConnected;
136  }
137 
138  if( !dataAvailable( timeout ) )
139  {
140  m_recvMutex.unlock();
141  return ConnNoError;
142  }
143 
144  struct sockaddr_in they;
145  int sin_size = sizeof( struct sockaddr_in );
146 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
147  int newfd = static_cast<int>( accept( static_cast<SOCKET>( m_socket ), (struct sockaddr*)&they, &sin_size ) );
148 #else
149  int newfd = accept( m_socket, (struct sockaddr*)&they, (socklen_t*)&sin_size );
150 #endif
151 
152  m_recvMutex.unlock();
153 
154  ConnectionTCPClient* conn = new ConnectionTCPClient( m_logInstance, inet_ntoa( they.sin_addr ),
155  ntohs( they.sin_port ) );
156  conn->setSocket( newfd );
157  m_connectionHandler->handleIncomingConnection( this, conn );
158 
159  return ConnNoError;
160  }
161 
162 }