gloox  1.0.1
connectiontcpserver.cpp
1 /*
2  Copyright (c) 2004-2012 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 "config.h"
18 
19 #include "connectiontcpserver.h"
20 #include "connectiontcpclient.h"
21 #include "connectionhandler.h"
22 #include "dns.h"
23 #include "logsink.h"
24 #include "mutex.h"
25 #include "mutexguard.h"
26 #include "util.h"
27 
28 #ifdef __MINGW32__
29 # include <winsock.h>
30 #endif
31 
32 #if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
33 # include <netinet/in.h>
34 # include <arpa/nameser.h>
35 # include <resolv.h>
36 # include <netdb.h>
37 # include <arpa/inet.h>
38 # include <sys/socket.h>
39 # include <sys/un.h>
40 # include <sys/select.h>
41 # include <unistd.h>
42 # include <errno.h>
43 #endif
44 
45 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
46 # include <winsock.h>
47 #elif defined( _WIN32_WCE )
48 # include <winsock2.h>
49 #endif
50 
51 #include <cstdlib>
52 #include <string>
53 
54 #ifndef _WIN32_WCE
55 # include <sys/types.h>
56 #endif
57 
58 namespace gloox
59 {
60 
62  const std::string& ip, int port )
63  : ConnectionTCPBase( 0, logInstance, ip, port ),
64  m_connectionHandler( ch )
65  {
66  }
67 
69  {
70  }
71 
73  {
74  return new ConnectionTCPServer( m_connectionHandler, m_logInstance, m_server, m_port );
75  }
76 
78  {
79  util::MutexGuard mg( &m_sendMutex );
80 
81  if( m_socket >= 0 || m_state > StateDisconnected )
82  return ConnNoError;
83 
85 
86  if( m_socket < 0 )
87  m_socket = DNS::getSocket( m_logInstance );
88 
89  if( m_socket < 0 )
90  return ConnIoError;
91 
92 #ifdef HAVE_SETSOCKOPT
93  int buf = 0;
94 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
95  int bufbytes = sizeof( int );
96 #else
97  socklen_t bufbytes = sizeof( int );
98 #endif
99  if( ( getsockopt( m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&buf, &bufbytes ) != -1 ) &&
100  ( m_bufsize > buf ) )
101  setsockopt( m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&m_bufsize, sizeof( m_bufsize ) );
102 
103  if( ( getsockopt( m_socket, SOL_SOCKET, SO_SNDBUF, (char*)&buf, &bufbytes ) != -1 ) &&
104  ( m_bufsize > buf ) )
105  setsockopt( m_socket, SOL_SOCKET, SO_SNDBUF, (char*)&m_bufsize, sizeof( m_bufsize ) );
106 #endif
107 
108  struct sockaddr_in local;
109  local.sin_family = AF_INET;
110  local.sin_port = static_cast<unsigned short int>( htons( m_port ) );
111  local.sin_addr.s_addr = m_server.empty() ? INADDR_ANY : inet_addr( m_server.c_str() );
112  memset( local.sin_zero, '\0', 8 );
113 
114  if( bind( m_socket, (struct sockaddr*)&local, sizeof( struct sockaddr ) ) < 0 )
115  {
116  std::string message = "bind() to " + ( m_server.empty() ? std::string( "*" ) : m_server )
117  + " (" + inet_ntoa( local.sin_addr ) + ":" + util::int2string( m_port ) + ") failed. "
118 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
119  "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
120 #else
121  "errno: " + util::int2string( errno );
122 #endif
123  m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
124 
125  return ConnIoError;
126  }
127 
128  if( listen( m_socket, 10 ) < 0 )
129  {
130  std::string message = "listen on " + ( m_server.empty() ? std::string( "*" ) : m_server )
131  + " (" + inet_ntoa( local.sin_addr ) + ":" + util::int2string( m_port ) + ") failed. "
132 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
133  "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
134 #else
135  "errno: " + util::int2string( errno );
136 #endif
137  m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
138 
139  return ConnIoError;
140  }
141 
142  m_cancel = false;
143  return ConnNoError;
144  }
145 
147  {
148  m_recvMutex.lock();
149 
150  if( m_cancel || m_socket < 0 || !m_connectionHandler )
151  {
152  m_recvMutex.unlock();
153  return ConnNotConnected;
154  }
155 
156  if( !dataAvailable( timeout ) )
157  {
158  m_recvMutex.unlock();
159  return ConnNoError;
160  }
161 
162  struct sockaddr_in they;
163  int sin_size = sizeof( struct sockaddr_in );
164 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
165  int newfd = static_cast<int>( accept( static_cast<SOCKET>( m_socket ), (struct sockaddr*)&they, &sin_size ) );
166 #else
167  int newfd = accept( m_socket, (struct sockaddr*)&they, (socklen_t*)&sin_size );
168 #endif
169 
170  m_recvMutex.unlock();
171 
172  ConnectionTCPClient* conn = new ConnectionTCPClient( m_logInstance, inet_ntoa( they.sin_addr ),
173  ntohs( they.sin_port ) );
174  conn->setSocket( newfd );
175  m_connectionHandler->handleIncomingConnection( this, conn );
176 
177  return ConnNoError;
178  }
179 
180 }