Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
netui.cpp
Go to the documentation of this file.
1 #include <config.h>
2 #include <map>
3 
4 #include "networking/const.h"
5 #include "netui.h"
6 #include "vsnet_serversocket.h"
7 #include "vsnet_oss.h"
8 #include "vsnet_debug.h"
9 #include "vsnet_headers.h"
10 
11 static void static_initNetwork()
12 {
13 #if defined (_WIN32) && !defined (__CYGWIN__)
14  static bool first_time = true;
15  if (first_time) {
16  first_time = false;
17 
18  COUT<<"Initializing Winsock"<<std::endl;
19  WORD wVersionRequested = MAKEWORD( 1, 1 );
20  WSADATA wsaData;
21  int res = WSAStartup( wVersionRequested, &wsaData );
22  if (res != 0)
23  COUT<<"Error initializing Winsock"<<std::endl;
24  }
25 #endif
26 }
27 
28 AddressIP NetUIBase::lookupHost( const char *host, unsigned short port )
29 {
31 
32  AddressIP remote_ip;
33  memset( &remote_ip, 0, sizeof (AddressIP) );
34 
35  struct hostent *he = NULL;
36  //Gets the host info for host
37  if (host[0] < 48 || host[0] > 57) {
38  COUT<<"Resolving host name... ";
39  if ( ( he = gethostbyname( host ) ) == NULL ) {
40  cerr<<"Could not resolve hostname"<<std::endl;
41  return AddressIP();
42  }
43  memcpy( &remote_ip.sin_addr.s_addr, he->h_addr_list[0], he->h_length );
44  cerr<<"found : "<<inet_ntoa( remote_ip.sin_addr )<<std::endl;
45  } else if (VsnetOSS::inet_aton( host, &remote_ip.sin_addr ) == 0) {
46  COUT<<"Error inet_aton"<<std::endl;
47  return AddressIP();
48  }
49  //Store it in srv_ip struct
50  remote_ip.sin_port = htons( port );
51  remote_ip.sin_family = AF_INET;
52  return remote_ip;
53 }
54 //#ifdef _WIN32
55 //int NONBLOCKING_CONNECT=0;
56 //#else
58 //#endif
59 
60 bool bindFd( int fd, const AddressIP &remote_ip )
61 {
62  return bind( fd, (sockaddr*) &remote_ip, sizeof (struct sockaddr_in) ) != SOCKET_ERROR;
63 }
64 
65 int NetUIBase::createClientSocket( const AddressIP &remote_ip, bool isTCP, bool isHTTP )
66 {
68 
69  int local_fd;
70  if ( ( local_fd = VsnetOSS::socket( PF_INET, isTCP ? SOCK_STREAM : SOCK_DGRAM, 0 ) ) == -1 ) {
71  COUT<<"Could not create socket"<<std::endl;
72  return -1;
73  }
74  if (isTCP) {
75  COUT<<"Connecting to "<<inet_ntoa( remote_ip.sin_addr )<<" on port "<<ntohs( remote_ip.sin_port )<<std::endl;
76  //NETFIXME: Always doing nonblocking because it's good for your health.
77  //Plus, we use select() for every read/write, so it should be safe.
78  if (NONBLOCKING_CONNECT) //&&isHTTP) {
79  VsnetOSS::set_blocking( local_fd, false ); //Connect may hang... we don't want that.
80  //No, it really is good for your health. You don't have to stare at
81  //the screen for 3 minutes until the OS times out the connection.
82 
83 #if defined (_WIN32) && !defined (__CYGWIN__)
84  if (::connect( local_fd, (sockaddr*) &remote_ip, sizeof (struct sockaddr) ) == SOCKET_ERROR)
85 #else
86  if (::connect( local_fd, (sockaddr*) &remote_ip, sizeof (struct sockaddr) ) < 0)
87 #endif
88  {
89 #if defined (_WIN32) && !defined (__CYGWIN__)
90  int lasterr = WSAGetLastError();
91  if (lasterr != WSAEINPROGRESS && lasterr != WSAEWOULDBLOCK)
92 #else
93  if (errno != EINPROGRESS && errno != EWOULDBLOCK)
94 #endif
95  {
96  perror( "Can't connect to server " );
97  VsnetOSS::close_socket( local_fd );
98  return -1;
99  }
100  }
101  } else
102  //binds socket
103  if ( !bindFd( local_fd, remote_ip ) ) {
104  perror( "Can't bind socket" );
105  VsnetOSS::close_socket( local_fd );
106  return -1;
107  }
108  return local_fd;
109 }
110 
111 int NetUIBase::createServerSocket( const AddressIP &local_ip, bool isTCP )
112 {
113  if (!isTCP)
114  return createClientSocket( local_ip, false, false );
116 
117  int local_fd;
118  if ( ( local_fd = VsnetOSS::socket( PF_INET, SOCK_STREAM, 0 ) ) == -1 ) {
119  COUT<<"Could not create socket"<<std::endl;
120  return -1;
121  }
122  int newval = 1;
123  char *buf = (char*) &newval;
124  setsockopt( local_fd, SOL_SOCKET, SO_REUSEADDR, buf, sizeof (int) );
125 
126  //binds socket
127  COUT<<"Bind on "<<ntohl( local_ip.sin_addr.s_addr )<<", port "
128  <<ntohs( local_ip.sin_port )<<std::endl;
129  if (bind( local_fd, (sockaddr*) &local_ip, sizeof (struct sockaddr_in) ) == SOCKET_ERROR) {
130  perror( "Problem binding socket" );
131  VsnetOSS::close_socket( local_fd );
132  return -1;
133  }
134  COUT<<"Accepting max : "<<SOMAXCONN<<std::endl;
135  if (listen( local_fd, SOMAXCONN ) == SOCKET_ERROR) {
136  perror( "Problem listening on socket" );
137  VsnetOSS::close_socket( local_fd );
138  return -1;
139  }
140  return local_fd;
141 }
142 
143 /*
144  *************************************************************
145  *************************************************************
146  **** Create (and bind) a socket on host ***
147  *************************************************************
148  */
149 
150 //Creates and bind the socket designed to receive coms
151 //host == NULL -> localhost
152 
153 SOCKETALT NetUITCP::createSocket( const char *host, unsigned short srv_port, SocketSet &set )
154 {
155  COUT<<"enter "<<__PRETTY_FUNCTION__<<std::endl;
156  //If port is not given, use the defaults ones --> do not work with specified ones yet... well, didn't try
157  if (srv_port == 0)
158  srv_port = SERVER_PORT;
159  AddressIP remote_ip = NetUIBase::lookupHost( host, srv_port );
160  if (remote_ip.sin_port == 0) {
161  SOCKETALT ret;
162  return ret;
163  }
164  int local_fd = NetUIBase::createClientSocket( remote_ip, true, false );
165  if (local_fd == -1) {
166  SOCKETALT ret; //( -1, SOCKETALT::TCP, remote_ip );
167  return ret;
168  }
169  COUT<<"Connected to "<<inet_ntoa( remote_ip.sin_addr )<<":"<<srv_port<<std::endl;
170 
171  SOCKETALT ret( local_fd, SOCKETALT::TCP, remote_ip, set );
172  if (ret.set_nonblock() == false)
173  COUT<<"WARNING: TCP client socket may be in blocking mode"<<std::endl;
174  COUT<<"SOCKETALT FD: "<<ret.get_fd()<<std::endl;
175  return ret;
176 }
177 
179 {
180  COUT<<"enter "<<__PRETTY_FUNCTION__<<std::endl;
181  //If port is not given, use the defaults ones --> do not work with specified ones yet... well, didn't try
182  if (port == 0) port = SERVER_PORT;
183  AddressIP local_ip = NetUIBase::lookupHost( "0.0.0.0", port );
184  if (local_ip.sin_port == 0)
185  return NULL;
186  int local_fd = NetUIBase::createServerSocket( local_ip, true );
187  if (local_fd == -1)
188  return NULL;
189  COUT<<"Listening on socket "<<local_fd<<std::endl
190  <<"*** ServerSocket FD : "<<local_fd<<std::endl;
191  return new ServerSocketTCP( local_fd, local_ip, set );
192 }
193 
194 /*
195  *************************************************************
196  **** Create (and bind) a socket on host ***
197  *************************************************************
198  */
199 
200 //Creates and bind the socket designed to receive coms
201 //host == NULL -> localhost
202 
203 typedef std::map< AddressIP, SOCKETALT >UDP_pool_type;
205 
206 SOCKETALT NetUIUDP::createSocket( const char *host, unsigned short srv_port, unsigned short clt_port, SocketSet &set )
207 {
208  COUT<<" enter "<<__PRETTY_FUNCTION__<<std::endl;
210  //If port is not given, use the defaults ones --> do not work with specified ones yet... well, didn't try
211  if (srv_port == 0) srv_port = SERVER_PORT;
212  if (clt_port == 0) clt_port = SERVER_PORT;
213  AddressIP remote_ip = NetUIBase::lookupHost( host, srv_port );
214  AddressIP local_ip = NetUIBase::lookupHost( "0.0.0.0", clt_port );
215 
216  UDP_pool_type::iterator iter( UDP_pool.find( local_ip ) );
217  if ( iter != UDP_pool.end() ) {
218  SOCKETALT ret( (*iter).second );
219  //bindFd(ret.get_fd(), local_ip); // Don't care if it fails... could be binding on itself.
220  ret.setSet( &set );
221  ret.setRemoteAddress( remote_ip );
222  return ret;
223  }
224  int local_fd = NetUIBase::createClientSocket( local_ip, false, false );
225  if (local_fd == -1) {
226  SOCKETALT ret;
227  return ret;
228  }
229  SOCKETALT ret( local_fd, SOCKETALT::UDP, remote_ip, set );
230  ret.setLocalAddress( local_ip );
231  if (ret.set_nonblock() == false)
232  COUT<<"Could not set socket to nonblocking state";
233  //ret.disconnect( "Could not set socket to nonblocking state" );
234  //SOCKETALT ret; // ( -1, SOCKETALT::UDP, remote_ip );
235  //return ret;
236  COUT<<"Bind on localhost, "<<ret<<std::endl;
237  return ret;
238 }
239 
241 {
242  COUT<<"enter "<<__PRETTY_FUNCTION__<<std::endl;
244  //If port is not given, use the defaults ones --> do not work with specified ones yet... well, didn't try
245  if (port == 0) port = SERVER_PORT;
246  AddressIP local_ip = NetUIBase::lookupHost( "0.0.0.0", port );
247  int local_fd = NetUIBase::createServerSocket( local_ip, false );
248  if (local_fd == -1) {
249  SOCKETALT ret;
250  return ret;
251  }
252  SOCKETALT ret( local_fd, SOCKETALT::UDP, local_ip, set );
253  ret.setLocalAddress( local_ip );
254  if (ret.set_nonblock() == false)
255  COUT<<"Setting server socket mode to nonblocking failed";
256  //ret.disconnect( "Setting server socket mode to nonblocking failed", true );
257  //SOCKETALT ret;
258  //return ret;
259 
260  COUT<<"Bind on localhost, "<<ret<<std::endl;
261  return ret;
262 }
263 
265 {
266  if ( udp.valid() )
267  UDP_pool[udp.getLocalAddress()] = udp;
268  udp.setSet( NULL );
269 }
270 
271 /*
272  * // This is as simple as NetUI (factory) functions *SHOULD* be.
273  * SOCKETALT NetUIHTTP::createSocket(const char* uri, SocketSet &set)
274  * {
275  * COUT << "enter " << __PRETTY_FUNCTION__ << std::endl;
276  * SOCKETALT ret( uri, set );
277  * return ret;
278  * }
279  */
280