Pol  Revision:cb584c9
sockio.cpp
Go to the documentation of this file.
1 
7 #include "sockio.h"
8 
9 #ifdef __unix__
10 #include <sys/utsname.h>
11 
12 struct utsname my_utsname;
13 #endif
14 
15 #include <cstdio>
16 #include <cstring>
17 #include <fcntl.h>
18 #include <stdexcept>
19 #include <string>
20 
21 #include "../clib/clib.h"
22 #include "../clib/clib_endian.h"
23 #include "../clib/logfacility.h"
24 #include "../clib/strutil.h"
25 #include "globals/network.h"
26 #include "sockets.h"
27 
28 
29 namespace Pol
30 {
31 namespace Network
32 {
33 void set_ip_address( const char* ip )
34 {
35  strzcpy( Core::networkManager.ipaddr_str, ip, sizeof Core::networkManager.ipaddr_str );
36  POLLOG_INFO << "Internet IP address is " << Core::networkManager.ipaddr_str << "\n";
37 }
38 void set_lan_address( const char* ip )
39 {
40  strzcpy( Core::networkManager.lanaddr_str, ip, sizeof Core::networkManager.lanaddr_str );
41  POLLOG_INFO << "LAN IP address is " << Core::networkManager.lanaddr_str << "\n";
42 }
43 
44 void search_name( const char* hostname )
45 {
46  struct sockaddr_in server;
47  POLLOG_INFO << "hostname is " << hostname << "\n";
48  struct hostent* he = gethostbyname( hostname );
49  for ( int i = 0; ( he != nullptr ) && ( he->h_addr_list[i] != nullptr ); ++i )
50  {
51  memcpy( &server.sin_addr, he->h_addr_list[i], he->h_length );
52 
53  const in_addr ad = server.sin_addr;
54  const char* adstr = inet_ntoa( ad );
55  POLLOG_INFO << "address: " << adstr << "\n";
56 
57 #ifdef _WIN32
58  const unsigned long ip = ad.S_un.S_addr;
59 #else
60  const unsigned long ip = ad.s_addr;
61 #endif
62  // Careful: IPs are reversed (i.e. 1.0.168.192)
63  if ( ( ip & 0x0000ffff ) == 0x0000a8c0 || // 192.168.0.0/16
64  ( ip & 0x0000f0ff ) == 0x000010ac || // 172.16.0.0/12
65  ( ip & 0x000000ff ) == 0x0000000a ) // 10.0.0.0/8
66  {
67  if ( !Core::networkManager.lanaddr_str[0] )
68  set_lan_address( adstr );
69  }
70  else if ( ( ip & 0x000000ff ) == 0x0000007f ) // 127.0.0.0/8
71  {
72  ;
73  }
74  else
75  {
76  if ( !Core::networkManager.ipaddr_str[0] )
77  set_ip_address( adstr );
78  }
79  }
80 }
81 
82 
83 #ifdef _WIN32
84 #define WSOCK_VERSION 0x0101
85 WSADATA wsa_data;
86 #endif
87 
89 {
90 #ifdef _WIN32
91  int res;
92 
93  res = WSAStartup( WSOCK_VERSION, &wsa_data );
94  if ( res < 0 )
95  {
96  POLLOG_ERROR << "Error starting Winsock 1.1: " << res << "\n";
97  return -1;
98  }
99 #endif
100 
101  if ( gethostname( Core::networkManager.hostname, sizeof Core::networkManager.hostname ) )
102  {
103  POLLOG_ERROR << "gethostname failed: " << socket_errno << "\n";
104  }
105  search_name( Core::networkManager.hostname );
106 
107 #ifdef __unix__
108  uname( &my_utsname );
109  search_name( my_utsname.nodename );
110 #endif
111 
112  return 0;
113 }
114 
115 
117 {
118 #ifdef _WIN32
119  int res;
120 
121  res = WSACleanup();
122  if ( res < 0 )
123  {
124  POLLOG_ERROR << "Error stopping Winsock 1.1: " << res << "\n";
125  return -1;
126  }
127 #endif
128  return 0;
129 }
130 
132 {
133  int tcp_nodelay = 1;
134  int res =
135  setsockopt( sck, IPPROTO_TCP, TCP_NODELAY, (const char*)&tcp_nodelay, sizeof( tcp_nodelay ) );
136  if ( res < 0 )
137  {
138  throw std::runtime_error( "Unable to setsockopt (TCP_NODELAY) on listening socket, res=" +
139  Clib::decint( res ) );
140  }
141 }
142 
144 {
145 #ifdef _WIN32
146  u_long nonblocking = 1;
147  int res = ioctlsocket( sck, FIONBIO, &nonblocking );
148 #else
149  int flags = fcntl( sck, F_GETFL );
150  flags |= O_NONBLOCK;
151  int res = fcntl( sck, F_SETFL, flags );
152 #endif
153  if ( res < 0 )
154  {
155  throw std::runtime_error( "Unable to set socket to nonblocking mode, res=" +
156  Clib::decint( res ) );
157  }
158 }
159 SOCKET open_listen_socket( unsigned short port )
160 {
161  int res;
162  SOCKET sck;
163 
164  sck = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
165  if ( sck == INVALID_SOCKET )
166  {
167  throw std::runtime_error( "Unable to create listening socket" );
168  }
169 
170  apply_socket_options( sck );
171 
172 #ifndef WIN32
173  int reuse_opt = 1;
174  res = setsockopt( sck, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_opt, sizeof( reuse_opt ) );
175  if ( res < 0 )
176  {
177  throw std::runtime_error( "Unable to setsockopt (SO_REUSEADDR) on listening socket, res = " +
178  Clib::decint( res ) );
179  }
180 #endif
181 
182 #define DISABLE_NAGLE_ALGORITHM 0
183 #if DISABLE_NAGLE_ALGORITHM
184  disable_nagle( sck );
185 #endif
186 
187  struct sockaddr_in connection;
188  connection.sin_family = AF_INET;
189  connection.sin_addr.s_addr = INADDR_ANY;
190  connection.sin_port = ctBEu16( port );
191  memset( connection.sin_zero, 0, sizeof( connection.sin_zero ) ); // for completeness
192 
193  res = bind( sck, (struct sockaddr*)&connection, sizeof connection );
194  if ( res < 0 )
195  {
196  // Aug. 16, 2006. Austin
197  // Added the port number that failed.
198  std::string tmp_error = "Unable to bind listening socket. Port(" + Clib::decint( port ) +
199  ") Res=" + Clib::decint( res );
200  throw std::runtime_error( tmp_error );
201  }
202 
203  res = listen( sck, SOMAXCONN );
204  if ( res < 0 )
205  {
206  throw std::runtime_error( "Listen failed, res=" + Clib::decint( res ) );
207  }
208 
209  return sck;
210 }
211 
212 const char* AddressToString( struct sockaddr* addr )
213 {
214 #if 0 && defined( _WIN32 )
215  // this requires Winsock 2! Ouch.
216  static char buf[ 80 ];
217  DWORD len = sizeof buf;
218  if (WSAAddressToString( addr, sizeof *addr,
219  nullptr, // protocol
220  buf, &len ) != SOCKET_ERROR)
221  {
222  return buf;
223  }
224  else
225  {
226  return "(display error)";
227  }
228 #else
229  struct sockaddr_in* in_addr = (struct sockaddr_in*)addr;
230  if ( addr->sa_family == AF_INET )
231  return inet_ntoa( in_addr->sin_addr );
232  else
233  return "(display error)";
234 #endif
235 }
236 
238  : listen_socket( INVALID_SOCKET ),
239  listen_fd(),
240  listen_timeout( {0, 0} ),
241  recv_fd(),
242  err_fd(),
243  send_fd(),
244  select_timeout( {0, 0} )
245 {
246  FD_ZERO( &listen_fd );
247  FD_ZERO( &recv_fd );
248  FD_ZERO( &err_fd );
249  FD_ZERO( &send_fd );
250 }
251 }
252 }
void set_ip_address(const char *ip)
Definition: sockio.cpp:33
void apply_socket_options(SOCKET sck)
Definition: sockio.cpp:143
#define INVALID_SOCKET
Definition: wnsckt.h:12
int SOCKET
Definition: wnsckt.h:10
#define POLLOG_INFO
Definition: logfacility.h:213
std::string decint(unsigned short v)
Definition: strutil.cpp:64
#define ctBEu16(x)
Definition: clib_endian.h:46
void set_lan_address(const char *ip)
Definition: sockio.cpp:38
typedef DWORD(WINAPI *__SymGetOptions)(VOID)
int init_sockets_library(void)
Definition: sockio.cpp:88
#define POLLOG_ERROR
Definition: logfacility.h:207
int deinit_sockets_library(void)
Definition: sockio.cpp:116
NetworkManager networkManager
Definition: network.cpp:28
#define socket_errno
Definition: wnsckt.cpp:34
const char * AddressToString(struct sockaddr *addr)
Definition: sockio.cpp:212
SOCKET open_listen_socket(unsigned short port)
Definition: sockio.cpp:159
void disable_nagle(SOCKET sck)
Definition: sockio.cpp:131
struct timeval select_timeout
Definition: sockio.h:40
void search_name(const char *hostname)
Definition: sockio.cpp:44
#define strzcpy
Definition: clib.h:154
Definition: berror.cpp:12