OpenTTD
tcp_listen.h
Go to the documentation of this file.
1 /* $Id: tcp_listen.h 26046 2013-11-22 21:41:19Z rubidium $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
14 #ifndef NETWORK_CORE_TCP_LISTEN_H
15 #define NETWORK_CORE_TCP_LISTEN_H
16 
17 #include "tcp.h"
18 #include "../network.h"
19 #include "../../core/pool_type.hpp"
20 #include "../../debug.h"
21 #include "table/strings.h"
22 
23 #ifdef ENABLE_NETWORK
24 
31 template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet>
35 
36 public:
41  static void AcceptClient(SOCKET ls)
42  {
43  for (;;) {
44  struct sockaddr_storage sin;
45  memset(&sin, 0, sizeof(sin));
46  socklen_t sin_len = sizeof(sin);
47  SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
48  if (s == INVALID_SOCKET) return;
49 
50  SetNonBlocking(s); // XXX error handling?
51 
52  NetworkAddress address(sin, sin_len);
53  DEBUG(net, 1, "[%s] Client connected from %s on frame %d", Tsocket::GetName(), address.GetHostname(), _frame_counter);
54 
55  SetNoDelay(s); // XXX error handling?
56 
57  /* Check if the client is banned */
58  bool banned = false;
59  for (char **iter = _network_ban_list.Begin(); iter != _network_ban_list.End(); iter++) {
60  banned = address.IsInNetmask(*iter);
61  if (banned) {
62  Packet p(Tban_packet);
63  p.PrepareToSend();
64 
65  DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), *iter);
66 
67  if (send(s, (const char*)p.buffer, p.size, 0) < 0) {
68  DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR());
69  }
70  closesocket(s);
71  break;
72  }
73  }
74  /* If this client is banned, continue with next client */
75  if (banned) continue;
76 
77  /* Can we handle a new client? */
78  if (!Tsocket::AllowConnection()) {
79  /* no more clients allowed?
80  * Send to the client that we are full! */
81  Packet p(Tfull_packet);
82  p.PrepareToSend();
83 
84  if (send(s, (const char*)p.buffer, p.size, 0) < 0) {
85  DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR());
86  }
87  closesocket(s);
88 
89  continue;
90  }
91 
92  Tsocket::AcceptConnection(s, address);
93  }
94  }
95 
100  static bool Receive()
101  {
102  fd_set read_fd, write_fd;
103  struct timeval tv;
104 
105  FD_ZERO(&read_fd);
106  FD_ZERO(&write_fd);
107 
108 
109  Tsocket *cs;
110  FOR_ALL_ITEMS_FROM(Tsocket, idx, cs, 0) {
111  FD_SET(cs->sock, &read_fd);
112  FD_SET(cs->sock, &write_fd);
113  }
114 
115  /* take care of listener port */
116  for (SocketList::iterator s = sockets.Begin(); s != sockets.End(); s++) {
117  FD_SET(s->second, &read_fd);
118  }
119 
120  tv.tv_sec = tv.tv_usec = 0; // don't block at all.
121 #if !defined(__MORPHOS__) && !defined(__AMIGA__)
122  if (select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv) < 0) return false;
123 #else
124  if (WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL) < 0) return false;
125 #endif
126 
127  /* accept clients.. */
128  for (SocketList::iterator s = sockets.Begin(); s != sockets.End(); s++) {
129  if (FD_ISSET(s->second, &read_fd)) AcceptClient(s->second);
130  }
131 
132  /* read stuff from clients */
133  FOR_ALL_ITEMS_FROM(Tsocket, idx, cs, 0) {
134  cs->writable = !!FD_ISSET(cs->sock, &write_fd);
135  if (FD_ISSET(cs->sock, &read_fd)) {
136  cs->ReceivePackets();
137  }
138  }
139  return _networking;
140  }
141 
147  static bool Listen(uint16 port)
148  {
149  assert(sockets.Length() == 0);
150 
151  NetworkAddressList addresses;
152  GetBindAddresses(&addresses, port);
153 
154  for (NetworkAddress *address = addresses.Begin(); address != addresses.End(); address++) {
155  address->Listen(SOCK_STREAM, &sockets);
156  }
157 
158  if (sockets.Length() == 0) {
159  DEBUG(net, 0, "[server] could not start network: could not create listening socket");
160  NetworkError(STR_NETWORK_ERROR_SERVER_START);
161  return false;
162  }
163 
164  return true;
165  }
166 
168  static void CloseListeners()
169  {
170  for (SocketList::iterator s = sockets.Begin(); s != sockets.End(); s++) {
171  closesocket(s->second);
172  }
173  sockets.Clear();
174  DEBUG(net, 1, "[%s] closed listeners", Tsocket::GetName());
175  }
176 };
177 
178 template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet> SocketList TCPListenHandler<Tsocket, Tfull_packet, Tban_packet>::sockets;
179 
180 #endif /* ENABLE_NETWORK */
181 
182 #endif /* NETWORK_CORE_TCP_LISTEN_H */
bool _networking
are we in networking mode?
Definition: network.cpp:56
Internal entity of a packet.
Definition: packet.h:44
void GetBindAddresses(NetworkAddressList *addresses, uint16 port)
Get the addresses to bind to.
Definition: network.cpp:635
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:65
Template for TCP listeners.
Definition: tcp_listen.h:32
void Clear()
Remove all items from the list.
Wrapper for (un)resolved network addresses; there&#39;s no reason to transform a numeric IP to a string a...
Definition: address.h:31
const T * Begin() const
Get the pointer to the first item (const)
const T * End() const
Get the pointer behind the last valid item (const)
static SocketList sockets
List of sockets we listen on.
Definition: tcp_listen.h:34
static void AcceptClient(SOCKET ls)
Accepts clients from the sockets.
Definition: tcp_listen.h:41
uint Length() const
Get the number of items in the list.
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:56
static bool Receive()
Handle the receiving of packets.
Definition: tcp_listen.h:100
const char * GetHostname()
Get the hostname; in case it wasn&#39;t given the IPv4 dotted representation is given.
Definition: address.cpp:26
PacketSize size
The size of the whole packet for received packets.
Definition: packet.h:52
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:39
uint32 _frame_counter
The current frame.
Definition: network.cpp:72
static bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
bool IsInNetmask(char *netmask)
Checks whether this IP address is contained by the given netmask.
Definition: address.cpp:161
StringList _network_ban_list
The banned clients.
Definition: network.cpp:69
static void CloseListeners()
Close the sockets we&#39;re listening on.
Definition: tcp_listen.h:168
static bool SetNoDelay(SOCKET d)
Try to set the socket to not delay sending.
Basic functions to receive and send TCP packets.
static bool Listen(uint16 port)
Listen on a particular port.
Definition: tcp_listen.h:147