mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* POLLOG* macros use the new formatting removed all old logging functions * removed old fmt lib from everything except StreamWriter removed unneeded functions * fixed review comments
231 lines
5.5 KiB
C++
231 lines
5.5 KiB
C++
/** @file
|
|
*
|
|
* @par History
|
|
*/
|
|
|
|
|
|
#include "sockio.h"
|
|
|
|
#ifdef __unix__
|
|
#include <sys/utsname.h>
|
|
|
|
struct utsname my_utsname;
|
|
#endif
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <fcntl.h>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
#include "../clib/clib.h"
|
|
#include "../clib/clib_endian.h"
|
|
#include "../clib/logfacility.h"
|
|
#include "../clib/network/sockets.h"
|
|
#include "../clib/strutil.h"
|
|
#include "globals/network.h"
|
|
|
|
|
|
namespace Pol
|
|
{
|
|
namespace Network
|
|
{
|
|
void set_ip_address( const char* ip )
|
|
{
|
|
Clib::stracpy( Core::networkManager.ipaddr_str, ip, sizeof Core::networkManager.ipaddr_str );
|
|
POLLOG_INFOLN( "Internet IP address is {}", Core::networkManager.ipaddr_str );
|
|
}
|
|
void set_lan_address( const char* ip )
|
|
{
|
|
Clib::stracpy( Core::networkManager.lanaddr_str, ip, sizeof Core::networkManager.lanaddr_str );
|
|
POLLOG_INFOLN( "LAN IP address is {}", Core::networkManager.lanaddr_str );
|
|
}
|
|
|
|
void search_name( const char* hostname )
|
|
{
|
|
struct sockaddr_in server;
|
|
POLLOG_INFOLN( "hostname is {}", hostname );
|
|
struct hostent* he = gethostbyname( hostname );
|
|
for ( int i = 0; ( he != nullptr ) && ( he->h_addr_list[i] != nullptr ); ++i )
|
|
{
|
|
memcpy( &server.sin_addr, he->h_addr_list[i], he->h_length );
|
|
|
|
const in_addr ad = server.sin_addr;
|
|
const char* adstr = inet_ntoa( ad );
|
|
POLLOG_INFOLN( "address: {}", adstr );
|
|
|
|
#ifdef _WIN32
|
|
const unsigned long ip = ad.S_un.S_addr;
|
|
#else
|
|
const unsigned long ip = ad.s_addr;
|
|
#endif
|
|
// Careful: IPs are reversed (i.e. 1.0.168.192)
|
|
if ( ( ip & 0x0000ffff ) == 0x0000a8c0 || // 192.168.0.0/16
|
|
( ip & 0x0000f0ff ) == 0x000010ac || // 172.16.0.0/12
|
|
( ip & 0x000000ff ) == 0x0000000a ) // 10.0.0.0/8
|
|
{
|
|
if ( !Core::networkManager.lanaddr_str[0] )
|
|
set_lan_address( adstr );
|
|
}
|
|
else if ( ( ip & 0x000000ff ) == 0x0000007f ) // 127.0.0.0/8
|
|
{
|
|
;
|
|
}
|
|
else
|
|
{
|
|
if ( !Core::networkManager.ipaddr_str[0] )
|
|
set_ip_address( adstr );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef _WIN32
|
|
#define WSOCK_VERSION 0x0101
|
|
WSADATA wsa_data;
|
|
#endif
|
|
|
|
int init_sockets_library( void )
|
|
{
|
|
#ifdef _WIN32
|
|
int res;
|
|
|
|
res = WSAStartup( WSOCK_VERSION, &wsa_data );
|
|
if ( res < 0 )
|
|
{
|
|
POLLOG_ERRORLN( "Error starting Winsock 1.1: {}", res );
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
if ( gethostname( Core::networkManager.hostname, sizeof Core::networkManager.hostname ) )
|
|
{
|
|
POLLOG_ERRORLN( "gethostname failed: {}", socket_errno );
|
|
}
|
|
search_name( Core::networkManager.hostname );
|
|
|
|
#ifdef __unix__
|
|
uname( &my_utsname );
|
|
search_name( my_utsname.nodename );
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int deinit_sockets_library( void )
|
|
{
|
|
#ifdef _WIN32
|
|
int res;
|
|
|
|
res = WSACleanup();
|
|
if ( res < 0 )
|
|
{
|
|
POLLOG_ERRORLN( "Error stopping Winsock 1.1: {}", res );
|
|
return -1;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
void disable_nagle( SOCKET sck )
|
|
{
|
|
int tcp_nodelay = 1;
|
|
int res =
|
|
setsockopt( sck, IPPROTO_TCP, TCP_NODELAY, (const char*)&tcp_nodelay, sizeof( tcp_nodelay ) );
|
|
if ( res < 0 )
|
|
{
|
|
throw std::runtime_error( "Unable to setsockopt (TCP_NODELAY) on listening socket, res=" +
|
|
Clib::tostring( res ) );
|
|
}
|
|
}
|
|
|
|
void apply_socket_options( SOCKET sck )
|
|
{
|
|
#ifdef _WIN32
|
|
u_long nonblocking = 1;
|
|
int res = ioctlsocket( sck, FIONBIO, &nonblocking );
|
|
#else
|
|
int flags = fcntl( sck, F_GETFL );
|
|
flags |= O_NONBLOCK;
|
|
int res = fcntl( sck, F_SETFL, flags );
|
|
#endif
|
|
if ( res < 0 )
|
|
{
|
|
throw std::runtime_error( "Unable to set socket to nonblocking mode, res=" +
|
|
Clib::tostring( res ) );
|
|
}
|
|
}
|
|
SOCKET open_listen_socket( unsigned short port )
|
|
{
|
|
int res;
|
|
SOCKET sck;
|
|
|
|
sck = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
|
|
if ( sck == INVALID_SOCKET )
|
|
{
|
|
throw std::runtime_error( "Unable to create listening socket" );
|
|
}
|
|
|
|
apply_socket_options( sck );
|
|
|
|
#ifndef WIN32
|
|
int reuse_opt = 1;
|
|
res = setsockopt( sck, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_opt, sizeof( reuse_opt ) );
|
|
if ( res < 0 )
|
|
{
|
|
throw std::runtime_error( "Unable to setsockopt (SO_REUSEADDR) on listening socket, res = " +
|
|
Clib::tostring( res ) );
|
|
}
|
|
#endif
|
|
|
|
#define DISABLE_NAGLE_ALGORITHM 0
|
|
#if DISABLE_NAGLE_ALGORITHM
|
|
disable_nagle( sck );
|
|
#endif
|
|
|
|
struct sockaddr_in connection;
|
|
connection.sin_family = AF_INET;
|
|
connection.sin_addr.s_addr = INADDR_ANY;
|
|
connection.sin_port = ctBEu16( port );
|
|
memset( connection.sin_zero, 0, sizeof( connection.sin_zero ) ); // for completeness
|
|
|
|
res = bind( sck, (struct sockaddr*)&connection, sizeof connection );
|
|
if ( res < 0 )
|
|
{
|
|
// Aug. 16, 2006. Austin
|
|
// Added the port number that failed.
|
|
std::string tmp_error = "Unable to bind listening socket. Port(" + Clib::tostring( port ) +
|
|
") Res=" + Clib::tostring( res );
|
|
throw std::runtime_error( tmp_error );
|
|
}
|
|
|
|
res = listen( sck, SOMAXCONN );
|
|
if ( res < 0 )
|
|
{
|
|
throw std::runtime_error( "Listen failed, res=" + Clib::tostring( res ) );
|
|
}
|
|
|
|
return sck;
|
|
}
|
|
|
|
std::string AddressToString( const sockaddr* addr )
|
|
{
|
|
if ( addr == nullptr )
|
|
return "(no address)";
|
|
|
|
if ( addr->sa_family != AF_INET )
|
|
return std::string( "(unknown address family " ) + std::to_string( addr->sa_family ) + ")";
|
|
|
|
const sockaddr_in* in_addr = reinterpret_cast<const sockaddr_in*>( addr );
|
|
|
|
char address[INET_ADDRSTRLEN] = {};
|
|
if ( inet_ntop( AF_INET, reinterpret_cast<const void*>( &in_addr->sin_addr ), address,
|
|
sizeof( address ) ) == nullptr )
|
|
return std::string( "(error - " + std::to_string( socket_errno ) + ")" );
|
|
|
|
return address;
|
|
}
|
|
|
|
} // namespace Network
|
|
} // namespace Pol
|