connectiontcpserver.cpp
/*
Copyright (c) 2004-2023 by Jakob Schröter <js@camaya.net>
This file is part of the gloox library. http://camaya.net/gloox
This software is distributed under a license. The full license
agreement can be found in the file LICENSE in this distribution.
This software may not be copied, modified, sold or distributed
other than expressed in the named license agreement.
This software is distributed without any warranty.
*/
#include "gloox.h"
#include "config.h"
#include "connectiontcpserver.h"
#include "connectiontcpclient.h"
#include "connectionhandler.h"
#include "dns.h"
#include "logsink.h"
#include "mutex.h"
#include "mutexguard.h"
#include "util.h"
#ifdef __MINGW32__
# include <winsock2.h>
# include <ws2tcpip.h>
#endif
#if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
# include <netinet/in.h>
# include <arpa/nameser.h>
# include <resolv.h>
# include <netdb.h>
# include <arpa/inet.h>
# include <string.h>
# include <sys/socket.h>
# include <sys/un.h>
# include <sys/select.h>
# include <unistd.h>
# include <errno.h>
#endif
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
# include <winsock2.h>
# include <ws2tcpip.h>
#elif defined( _WIN32_WCE )
# include <winsock2.h>
#endif
#include <cstdlib>
#include <string>
#ifndef _WIN32_WCE
# include <sys/types.h>
#endif
// remove for 1.1
#ifndef INVALID_SOCKET
# define INVALID_SOCKET -1
#endif
namespace gloox
{
ConnectionTCPServer::ConnectionTCPServer( ConnectionHandler* ch, const LogSink& logInstance,
const std::string& ip, int port )
: ConnectionTCPBase( 0, logInstance, ip, port ),
m_connectionHandler( ch )
{
}
ConnectionTCPServer::~ConnectionTCPServer()
{
}
ConnectionBase* ConnectionTCPServer::newInstance() const
{
return new ConnectionTCPServer( m_connectionHandler, m_logInstance, m_server, m_port );
}
ConnectionError ConnectionTCPServer::connect()
{
util::MutexGuard mg( &m_sendMutex );
if( m_socket >= 0 || m_state > StateDisconnected )
return ConnNoError;
m_state = StateConnecting;
if( m_socket < 0 )
m_socket = DNS::getSocket( m_logInstance );
if( m_socket < 0 )
return ConnIoError;
#ifdef HAVE_SETSOCKOPT
int buf = 0;
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
int bufbytes = sizeof( int );
#else
socklen_t bufbytes = sizeof( int );
#endif
if( ( getsockopt( m_socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char*>( &buf ), &bufbytes ) != -1 ) && ( m_bufsize > buf ) )
setsockopt( m_socket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>( &m_bufsize ), sizeof( m_bufsize ) );
if( ( getsockopt( m_socket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>( &buf ), &bufbytes ) != -1 ) && ( m_bufsize > buf ) )
setsockopt( m_socket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>( &m_bufsize ), sizeof( m_bufsize ) );
#endif
int status = 0;
int err = 0;
struct addrinfo hints;
struct addrinfo *res;
memset( &hints, 0, sizeof hints );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
status = getaddrinfo( m_server.empty() ? 0 : m_server.c_str(), util::int2string( m_port ).c_str(), &hints, &res );
if( status != 0 )
{
err = errno;
std::string message = "getaddrinfo() for " + ( m_server.empty() ? std::string( "*" ) : m_server )
+ " (" + util::int2string( m_port ) + ") failed. "
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
"WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
#else
+ strerror( err ) + " (errno: " + util::int2string( err ) + ")";
#endif
m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
DNS::closeSocket( m_socket, m_logInstance );
return ConnIoError;
}
if( bind( m_socket, res->ai_addr, res->ai_addrlen ) < 0 )
{
err = errno;
std::string message = "bind() to " + ( m_server.empty() ? std::string( "*" ) : m_server )
+ " (" + /*inet_ntoa( local.sin_addr ) + ":" +*/ util::int2string( m_port ) + ") failed. "
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
"WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
#else
+ strerror( err ) + " (errno: " + util::int2string( err ) + ")";
#endif
m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
DNS::closeSocket( m_socket, m_logInstance );
return ConnIoError;
}
if( listen( m_socket, 10 ) < 0 )
{
err = errno;
std::string message = "listen() on " + ( m_server.empty() ? std::string( "*" ) : m_server )
+ " (" + /*inet_ntoa( local.sin_addr ) +*/ ":" + util::int2string( m_port ) + ") failed. "
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
"WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
#else
+ strerror( err ) + " (errno: " + util::int2string( err ) + ")";
#endif
m_logInstance.dbg( LogAreaClassConnectionTCPServer, message );
DNS::closeSocket( m_socket, m_logInstance );
return ConnIoError;
}
m_cancel = false;
return ConnNoError;
}
ConnectionError ConnectionTCPServer::recv( int timeout )
{
m_recvMutex.lock();
if( m_cancel || m_socket < 0 || !m_connectionHandler )
{
m_recvMutex.unlock();
return ConnNotConnected;
}
if( !dataAvailable( timeout ) )
{
m_recvMutex.unlock();
return ConnNoError;
}
struct sockaddr_storage they;
int addr_size = sizeof( struct sockaddr_storage );
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
int newfd = static_cast<int>( accept( static_cast<SOCKET>( m_socket ), reinterpret_cast<struct sockaddr*>( &they ), &addr_size ) );
#else
int newfd = accept( m_socket, reinterpret_cast<struct sockaddr*>( &they ), reinterpret_cast<socklen_t*>( &addr_size ) );
#endif
m_recvMutex.unlock();
char buffer[INET6_ADDRSTRLEN];
char portstr[NI_MAXSERV];
int err = getnameinfo( reinterpret_cast<struct sockaddr*>( &they ), addr_size, buffer, sizeof( buffer ),
portstr, sizeof( portstr ), NI_NUMERICHOST | NI_NUMERICSERV );
if( err )
return ConnIoError;
ConnectionTCPClient* conn = new ConnectionTCPClient( m_logInstance, buffer,
atoi( portstr ) );
conn->setSocket( newfd );
m_connectionHandler->handleIncomingConnection( this, conn );
return ConnNoError;
}
}
gloox::ConnectionBase
An abstract base class for a connection.
Definition connectionbase.h:35
gloox::ConnectionBase::m_state
ConnectionState m_state
Definition connectionbase.h:155
gloox::ConnectionBase::port
int port() const
Definition connectionbase.h:121
gloox::ConnectionBase::m_port
int m_port
Definition connectionbase.h:161
gloox::ConnectionBase::m_server
std::string m_server
Definition connectionbase.h:158
gloox::ConnectionHandler
This is an abstract base class to receive incoming connection attempts. Do not confuse this with Conn...
Definition connectionhandler.h:34
gloox::ConnectionTCPBase::setSocket
void setSocket(int socket)
Definition connectiontcpbase.h:103
gloox::ConnectionTCPBase::ConnectionTCPBase
ConnectionTCPBase(const LogSink &logInstance, const std::string &server, int port=-1)
Definition connectiontcpbase.cpp:53
gloox::ConnectionTCPClient
This is an implementation of a simple TCP connection.
Definition connectiontcpclient.h:37
gloox::ConnectionTCPServer::ConnectionTCPServer
ConnectionTCPServer(ConnectionHandler *ch, const LogSink &logInstance, const std::string &ip, int port)
Definition connectiontcpserver.cpp:69
gloox::ConnectionTCPServer::recv
virtual ConnectionError recv(int timeout=-1)
Definition connectiontcpserver.cpp:176
gloox::ConnectionTCPServer::~ConnectionTCPServer
virtual ~ConnectionTCPServer()
Definition connectiontcpserver.cpp:76
gloox::ConnectionTCPServer::newInstance
virtual ConnectionBase * newInstance() const
Definition connectiontcpserver.cpp:80
gloox::ConnectionTCPServer::connect
virtual ConnectionError connect()
Definition connectiontcpserver.cpp:85
gloox::DNS::getSocket
static int getSocket(const LogSink &logInstance)
Definition dns.cpp:339
gloox::DNS::closeSocket
static void closeSocket(int fd, const LogSink &logInstance)
Definition dns.cpp:518
gloox::LogSink
An implementation of log sink and source.
Definition logsink.h:39
gloox::util::MutexGuard
A simple implementation of a mutex guard.
Definition mutexguard.h:32
gloox
The namespace for the gloox library.
Definition adhoc.cpp:28
gloox::ConnectionError
ConnectionError
Definition gloox.h:684
gloox::ConnNotConnected
@ ConnNotConnected
Definition gloox.h:715
gloox::ConnNoError
@ ConnNoError
Definition gloox.h:685
gloox::ConnIoError
@ ConnIoError
Definition gloox.h:696
gloox::LogAreaClassConnectionTCPServer
@ LogAreaClassConnectionTCPServer
Definition gloox.h:1063
gloox::StateDisconnected
@ StateDisconnected
Definition gloox.h:642
gloox::StateConnecting
@ StateConnecting
Definition gloox.h:643