gloox 1.0.27
connectiontcpserver.cpp
1/*
2 Copyright (c) 2004-2023 by Jakob Schröter <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 <winsock2.h>
30# include <ws2tcpip.h>
31#endif
32
33#if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
34# include <netinet/in.h>
35# include <arpa/nameser.h>
36# include <resolv.h>
37# include <netdb.h>
38# include <arpa/inet.h>
39# include <string.h>
40# include <sys/socket.h>
41# include <sys/un.h>
42# include <sys/select.h>
43# include <unistd.h>
44# include <errno.h>
45#endif
46
47#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
48# include <winsock2.h>
49# include <ws2tcpip.h>
50#elif defined( _WIN32_WCE )
51# include <winsock2.h>
52#endif
53
54#include <cstdlib>
55#include <string>
56
57#ifndef _WIN32_WCE
58# include <sys/types.h>
59#endif
60
61// remove for 1.1
62#ifndef INVALID_SOCKET
63# define INVALID_SOCKET -1
64#endif
65
66namespace gloox
67{
68
70 const std::string& ip, int port )
71 : ConnectionTCPBase( 0, logInstance, ip, port ),
72 m_connectionHandler( ch )
73 {
74 }
75
79
81 {
82 return new ConnectionTCPServer( m_connectionHandler, m_logInstance, m_server, m_port );
83 }
84
86 {
87 util::MutexGuard mg( &m_sendMutex );
88
89 if( m_socket >= 0 || m_state > StateDisconnected )
90 return ConnNoError;
91
93
94 if( m_socket < 0 )
95 m_socket = DNS::getSocket( m_logInstance );
96
97 if( m_socket < 0 )
98 return ConnIoError;
99
100#ifdef HAVE_SETSOCKOPT
101 int buf = 0;
102#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
103 int bufbytes = sizeof( int );
104#else
105 socklen_t bufbytes = sizeof( int );
106#endif
107 if( ( getsockopt( m_socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char*>( &buf ), &bufbytes ) != -1 ) && ( m_bufsize > buf ) )
108 setsockopt( m_socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>( &m_bufsize ), sizeof( m_bufsize ) );
109
110 if( ( getsockopt( m_socket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>( &buf ), &bufbytes ) != -1 ) && ( m_bufsize > buf ) )
111 setsockopt( m_socket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>( &m_bufsize ), sizeof( m_bufsize ) );
112#endif
113
114 int status = 0;
115 int err = 0;
116 struct addrinfo hints;
117 struct addrinfo *res;
118
119 memset( &hints, 0, sizeof hints );
120 hints.ai_family = AF_UNSPEC;
121 hints.ai_socktype = SOCK_STREAM;
122 hints.ai_flags = AI_PASSIVE;
123 status = getaddrinfo( m_server.empty() ? 0 : m_server.c_str(), util::int2string( m_port ).c_str(), &hints, &res );
124 if( status != 0 )
125 {
126 err = errno;
127 std::string message = "getaddrinfo() for " + ( m_server.empty() ? std::string( "*" ) : m_server )
128 + " (" + util::int2string( m_port ) + ") failed. "
129#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
130 "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
131#else
132 + strerror( err ) + " (errno: " + util::int2string( err ) + ")";
133#endif
134 m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
135
136 DNS::closeSocket( m_socket, m_logInstance );
137 return ConnIoError;
138 }
139
140 if( bind( m_socket, res->ai_addr, res->ai_addrlen ) < 0 )
141 {
142 err = errno;
143 std::string message = "bind() to " + ( m_server.empty() ? std::string( "*" ) : m_server )
144 + " (" + /*inet_ntoa( local.sin_addr ) + ":" +*/ util::int2string( m_port ) + ") failed. "
145#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
146 "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
147#else
148 + strerror( err ) + " (errno: " + util::int2string( err ) + ")";
149#endif
150 m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
151
152 DNS::closeSocket( m_socket, m_logInstance );
153 return ConnIoError;
154 }
155
156 if( listen( m_socket, 10 ) < 0 )
157 {
158 err = errno;
159 std::string message = "listen() on " + ( m_server.empty() ? std::string( "*" ) : m_server )
160 + " (" + /*inet_ntoa( local.sin_addr ) +*/ ":" + util::int2string( m_port ) + ") failed. "
161#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
162 "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
163#else
164 + strerror( err ) + " (errno: " + util::int2string( err ) + ")";
165#endif
166 m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
167
168 DNS::closeSocket( m_socket, m_logInstance );
169 return ConnIoError;
170 }
171
172 m_cancel = false;
173 return ConnNoError;
174 }
175
177 {
178 m_recvMutex.lock();
179
180 if( m_cancel || m_socket < 0 || !m_connectionHandler )
181 {
182 m_recvMutex.unlock();
183 return ConnNotConnected;
184 }
185
186 if( !dataAvailable( timeout ) )
187 {
188 m_recvMutex.unlock();
189 return ConnNoError;
190 }
191
192 struct sockaddr_storage they;
193 int addr_size = sizeof( struct sockaddr_storage );
194#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
195 int newfd = static_cast<int>( accept( static_cast<SOCKET>( m_socket ), reinterpret_cast<struct sockaddr*>( &they ), &addr_size ) );
196#else
197 int newfd = accept( m_socket, reinterpret_cast<struct sockaddr*>( &they ), reinterpret_cast<socklen_t*>( &addr_size ) );
198#endif
199
200 m_recvMutex.unlock();
201
202 char buffer[INET6_ADDRSTRLEN];
203 char portstr[NI_MAXSERV];
204 int err = getnameinfo( reinterpret_cast<struct sockaddr*>( &they ), addr_size, buffer, sizeof( buffer ),
205 portstr, sizeof( portstr ), NI_NUMERICHOST | NI_NUMERICSERV );
206 if( err )
207 return ConnIoError;
208
209 ConnectionTCPClient* conn = new ConnectionTCPClient( m_logInstance, buffer,
210 atoi( portstr ) );
211 conn->setSocket( newfd );
212 m_connectionHandler->handleIncomingConnection( this, conn );
213
214 return ConnNoError;
215 }
216
217}
An abstract base class for a connection.
ConnectionState m_state
This is an abstract base class to receive incoming connection attempts. Do not confuse this with Conn...
virtual void handleIncomingConnection(ConnectionBase *server, ConnectionBase *connection)=0
This is a base class for a simple TCP connection.
This is an implementation of a simple TCP connection.
This is an implementation of a simple listening TCP connection.
ConnectionTCPServer(ConnectionHandler *ch, const LogSink &logInstance, const std::string &ip, int port)
virtual ConnectionError recv(int timeout=-1)
virtual ConnectionBase * newInstance() const
virtual ConnectionError connect()
static int getSocket(const LogSink &logInstance)
Definition dns.cpp:339
static void closeSocket(int fd, const LogSink &logInstance)
Definition dns.cpp:518
An implementation of log sink and source.
Definition logsink.h:39
void dbg(LogArea area, const std::string &message) const
Definition logsink.h:66
A simple implementation of a mutex guard.
Definition mutexguard.h:32
The namespace for the gloox library.
Definition adhoc.cpp:28
ConnectionError
Definition gloox.h:684
@ ConnNotConnected
Definition gloox.h:715
@ ConnNoError
Definition gloox.h:685
@ ConnIoError
Definition gloox.h:696
@ LogAreaClassConnectionTCPServer
Definition gloox.h:1063
@ StateDisconnected
Definition gloox.h:642
@ StateConnecting
Definition gloox.h:643