26 ADVERTISE_NORMAL_INTERVAL = 30000, // interval between advertising in ticks (15 minutes) |
26 ADVERTISE_NORMAL_INTERVAL = 30000, // interval between advertising in ticks (15 minutes) |
27 ADVERTISE_RETRY_INTERVAL = 300, // readvertise when no response after this many ticks (9 seconds) |
27 ADVERTISE_RETRY_INTERVAL = 300, // readvertise when no response after this many ticks (9 seconds) |
28 ADVERTISE_RETRY_TIMES = 3 // give up readvertising after this much failed retries |
28 ADVERTISE_RETRY_TIMES = 3 // give up readvertising after this much failed retries |
29 }; |
29 }; |
30 |
30 |
31 #define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, const struct sockaddr_in *client_addr) |
31 NetworkUDPSocketHandler *_udp_client_socket; ///< udp client socket |
32 |
32 NetworkUDPSocketHandler *_udp_server_socket; ///< udp server socket |
33 static NetworkClientState _udp_cs; |
33 NetworkUDPSocketHandler *_udp_master_socket; ///< udp master socket |
34 |
34 |
35 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER) |
35 #define DEF_UDP_RECEIVE_COMMAND(cls, type) void cls ##NetworkUDPSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p, const struct sockaddr_in *client_addr) |
|
36 |
|
37 ///*** Communication with the masterserver ***/ |
|
38 |
|
39 class MasterNetworkUDPSocketHandler : public NetworkUDPSocketHandler { |
|
40 protected: |
|
41 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER); |
|
42 public: |
|
43 virtual ~MasterNetworkUDPSocketHandler() {} |
|
44 }; |
|
45 |
|
46 DEF_UDP_RECEIVE_COMMAND(Master, PACKET_UDP_MASTER_ACK_REGISTER) |
|
47 { |
|
48 _network_advertise_retries = 0; |
|
49 DEBUG(net, 2, "[udp] advertising on master server successfull"); |
|
50 |
|
51 /* We are advertised, but we don't want to! */ |
|
52 if (!_network_advertise) NetworkUDPRemoveAdvertise(); |
|
53 } |
|
54 |
|
55 ///*** Communication with clients (we are server) ***/ |
|
56 |
|
57 class ServerNetworkUDPSocketHandler : public NetworkUDPSocketHandler { |
|
58 protected: |
|
59 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER); |
|
60 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO); |
|
61 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS); |
|
62 public: |
|
63 virtual ~ServerNetworkUDPSocketHandler() {} |
|
64 }; |
|
65 |
|
66 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_FIND_SERVER) |
36 { |
67 { |
37 Packet *packet; |
68 Packet *packet; |
38 // Just a fail-safe.. should never happen |
69 // Just a fail-safe.. should never happen |
39 if (!_network_udp_server) |
70 if (!_network_udp_server) |
40 return; |
71 return; |
48 _network_game_info.map_set = _opt.landscape; |
79 _network_game_info.map_set = _opt.landscape; |
49 _network_game_info.companies_on = ActivePlayerCount(); |
80 _network_game_info.companies_on = ActivePlayerCount(); |
50 _network_game_info.spectators_on = NetworkSpectatorCount(); |
81 _network_game_info.spectators_on = NetworkSpectatorCount(); |
51 _network_game_info.grfconfig = _grfconfig; |
82 _network_game_info.grfconfig = _grfconfig; |
52 |
83 |
53 NetworkSend_NetworkGameInfo(packet, &_network_game_info); |
84 this->Send_NetworkGameInfo(packet, &_network_game_info); |
54 |
85 |
55 // Let the client know that we are here |
86 // Let the client know that we are here |
56 NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr); |
87 this->SendPacket(packet, client_addr); |
57 |
88 |
58 free(packet); |
89 free(packet); |
59 |
90 |
60 DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr)); |
91 DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr)); |
61 } |
92 } |
62 |
93 |
63 void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) |
94 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_DETAIL_INFO) |
64 { |
95 { |
65 /* Find the matching GRF file */ |
96 NetworkClientState *cs; |
66 const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum); |
97 NetworkClientInfo *ci; |
67 if (f == NULL) { |
98 Packet *packet; |
68 /* Don't know the GRF, so mark game incompatible and the (possibly) |
99 Player *player; |
69 * already resolved name for this GRF (another server has sent the |
100 byte current = 0; |
70 * name of the GRF already */ |
101 int i; |
71 config->name = FindUnknownGRFName(config->grfid, config->md5sum, true); |
102 |
72 SETBIT(config->flags, GCF_NOT_FOUND); |
103 // Just a fail-safe.. should never happen |
73 } else { |
104 if (!_network_udp_server) return; |
74 config->filename = f->filename; |
105 |
75 config->name = f->name; |
106 packet = NetworkSend_Init(PACKET_UDP_SERVER_DETAIL_INFO); |
76 config->info = f->info; |
107 |
77 } |
108 /* Send the amount of active companies */ |
78 SETBIT(config->flags, GCF_COPY); |
109 NetworkSend_uint8 (packet, NETWORK_COMPANY_INFO_VERSION); |
79 } |
110 NetworkSend_uint8 (packet, ActivePlayerCount()); |
80 |
111 |
81 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE) |
112 /* Fetch the latest version of everything */ |
|
113 NetworkPopulateCompanyInfo(); |
|
114 |
|
115 /* Go through all the players */ |
|
116 FOR_ALL_PLAYERS(player) { |
|
117 /* Skip non-active players */ |
|
118 if (!player->is_active) continue; |
|
119 |
|
120 current++; |
|
121 |
|
122 /* Send the information */ |
|
123 NetworkSend_uint8(packet, current); |
|
124 |
|
125 NetworkSend_string(packet, _network_player_info[player->index].company_name); |
|
126 NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year); |
|
127 NetworkSend_uint64(packet, _network_player_info[player->index].company_value); |
|
128 NetworkSend_uint64(packet, _network_player_info[player->index].money); |
|
129 NetworkSend_uint64(packet, _network_player_info[player->index].income); |
|
130 NetworkSend_uint16(packet, _network_player_info[player->index].performance); |
|
131 |
|
132 /* Send 1 if there is a passord for the company else send 0 */ |
|
133 if (_network_player_info[player->index].password[0] != '\0') { |
|
134 NetworkSend_uint8(packet, 1); |
|
135 } else { |
|
136 NetworkSend_uint8(packet, 0); |
|
137 } |
|
138 |
|
139 for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) |
|
140 NetworkSend_uint16(packet, _network_player_info[player->index].num_vehicle[i]); |
|
141 |
|
142 for (i = 0; i < NETWORK_STATION_TYPES; i++) |
|
143 NetworkSend_uint16(packet, _network_player_info[player->index].num_station[i]); |
|
144 |
|
145 /* Find the clients that are connected to this player */ |
|
146 FOR_ALL_CLIENTS(cs) { |
|
147 ci = DEREF_CLIENT_INFO(cs); |
|
148 if (ci->client_playas == player->index) { |
|
149 /* The uint8 == 1 indicates that a client is following */ |
|
150 NetworkSend_uint8(packet, 1); |
|
151 NetworkSend_string(packet, ci->client_name); |
|
152 NetworkSend_string(packet, ci->unique_id); |
|
153 NetworkSend_uint32(packet, ci->join_date); |
|
154 } |
|
155 } |
|
156 /* Also check for the server itself */ |
|
157 ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX); |
|
158 if (ci->client_playas == player->index) { |
|
159 /* The uint8 == 1 indicates that a client is following */ |
|
160 NetworkSend_uint8(packet, 1); |
|
161 NetworkSend_string(packet, ci->client_name); |
|
162 NetworkSend_string(packet, ci->unique_id); |
|
163 NetworkSend_uint32(packet, ci->join_date); |
|
164 } |
|
165 |
|
166 /* Indicates end of client list */ |
|
167 NetworkSend_uint8(packet, 0); |
|
168 } |
|
169 |
|
170 /* And check if we have any spectators */ |
|
171 FOR_ALL_CLIENTS(cs) { |
|
172 ci = DEREF_CLIENT_INFO(cs); |
|
173 if (!IsValidPlayer(ci->client_playas)) { |
|
174 /* The uint8 == 1 indicates that a client is following */ |
|
175 NetworkSend_uint8(packet, 1); |
|
176 NetworkSend_string(packet, ci->client_name); |
|
177 NetworkSend_string(packet, ci->unique_id); |
|
178 NetworkSend_uint32(packet, ci->join_date); |
|
179 } |
|
180 } |
|
181 |
|
182 /* Also check for the server itself */ |
|
183 ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX); |
|
184 if (!IsValidPlayer(ci->client_playas)) { |
|
185 /* The uint8 == 1 indicates that a client is following */ |
|
186 NetworkSend_uint8(packet, 1); |
|
187 NetworkSend_string(packet, ci->client_name); |
|
188 NetworkSend_string(packet, ci->unique_id); |
|
189 NetworkSend_uint32(packet, ci->join_date); |
|
190 } |
|
191 |
|
192 /* Indicates end of client list */ |
|
193 NetworkSend_uint8(packet, 0); |
|
194 |
|
195 this->SendPacket(packet, client_addr); |
|
196 free(packet); |
|
197 } |
|
198 |
|
199 /** |
|
200 * A client has requested the names of some NewGRFs. |
|
201 * |
|
202 * Replying this can be tricky as we have a limit of SEND_MTU bytes |
|
203 * in the reply packet and we can send up to 100 bytes per NewGRF |
|
204 * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name). |
|
205 * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it |
|
206 * could be that a packet overflows. To stop this we only reply |
|
207 * with the first N NewGRFs so that if the first N + 1 NewGRFs |
|
208 * would be sent, the packet overflows. |
|
209 * in_reply and in_reply_count are used to keep a list of GRFs to |
|
210 * send in the reply. |
|
211 */ |
|
212 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_GET_NEWGRFS) |
|
213 { |
|
214 uint8 num_grfs; |
|
215 uint i; |
|
216 |
|
217 const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT]; |
|
218 Packet *packet; |
|
219 uint8 in_reply_count = 0; |
|
220 uint packet_len = 0; |
|
221 |
|
222 DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); |
|
223 |
|
224 num_grfs = NetworkRecv_uint8 (&this->cs, p); |
|
225 if (num_grfs > NETWORK_MAX_GRF_COUNT) return; |
|
226 |
|
227 for (i = 0; i < num_grfs; i++) { |
|
228 GRFConfig c; |
|
229 const GRFConfig *f; |
|
230 |
|
231 this->Recv_GRFIdentifier(p, &c); |
|
232 |
|
233 /* Find the matching GRF file */ |
|
234 f = FindGRFConfig(c.grfid, c.md5sum); |
|
235 if (f == NULL) continue; // The GRF is unknown to this server |
|
236 |
|
237 /* If the reply might exceed the size of the packet, only reply |
|
238 * the current list and do not send the other data. |
|
239 * The name could be an empty string, if so take the filename. */ |
|
240 packet_len += sizeof(c.grfid) + sizeof(c.md5sum) + |
|
241 min(strlen((f->name != NULL && strlen(f->name) > 0) ? f->name : f->filename) + 1, (size_t)NETWORK_GRF_NAME_LENGTH); |
|
242 if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply |
|
243 break; |
|
244 } |
|
245 in_reply[in_reply_count] = f; |
|
246 in_reply_count++; |
|
247 } |
|
248 |
|
249 if (in_reply_count == 0) return; |
|
250 |
|
251 packet = NetworkSend_Init(PACKET_UDP_SERVER_NEWGRFS); |
|
252 NetworkSend_uint8 (packet, in_reply_count); |
|
253 for (i = 0; i < in_reply_count; i++) { |
|
254 char name[NETWORK_GRF_NAME_LENGTH]; |
|
255 |
|
256 /* The name could be an empty string, if so take the filename */ |
|
257 ttd_strlcpy(name, (in_reply[i]->name != NULL && strlen(in_reply[i]->name) > 0) ? |
|
258 in_reply[i]->name : in_reply[i]->filename, sizeof(name)); |
|
259 this->Send_GRFIdentifier(packet, in_reply[i]); |
|
260 NetworkSend_string(packet, name); |
|
261 } |
|
262 |
|
263 this->SendPacket(packet, client_addr); |
|
264 free(packet); |
|
265 } |
|
266 |
|
267 ///*** Communication with servers (we are client) ***/ |
|
268 |
|
269 class ClientNetworkUDPSocketHandler : public NetworkUDPSocketHandler { |
|
270 protected: |
|
271 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE); |
|
272 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST); |
|
273 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS); |
|
274 virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config); |
|
275 public: |
|
276 virtual ~ClientNetworkUDPSocketHandler() {} |
|
277 }; |
|
278 |
|
279 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_RESPONSE) |
82 { |
280 { |
83 extern const char _openttd_revision[]; |
281 extern const char _openttd_revision[]; |
84 NetworkGameList *item; |
282 NetworkGameList *item; |
85 |
283 |
86 // Just a fail-safe.. should never happen |
284 // Just a fail-safe.. should never happen |
87 if (_network_udp_server || _udp_cs.has_quit) return; |
285 if (_network_udp_server) return; |
88 |
286 |
89 DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port)); |
287 DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); |
90 |
288 |
91 // Find next item |
289 // Find next item |
92 item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port)); |
290 item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port)); |
93 |
291 |
94 NetworkRecv_NetworkGameInfo(&_udp_cs, p, &item->info); |
292 this->Recv_NetworkGameInfo(p, &item->info); |
95 |
293 |
96 item->info.compatible = true; |
294 item->info.compatible = true; |
97 { |
295 { |
98 /* Checks whether there needs to be a request for names of GRFs and makes |
296 /* Checks whether there needs to be a request for names of GRFs and makes |
99 * the request if necessary. GRFs that need to be requested are the GRFs |
297 * the request if necessary. GRFs that need to be requested are the GRFs |
147 item->online = true; |
345 item->online = true; |
148 |
346 |
149 UpdateNetworkGameWindow(false); |
347 UpdateNetworkGameWindow(false); |
150 } |
348 } |
151 |
349 |
152 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO) |
350 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_MASTER_RESPONSE_LIST) |
153 { |
|
154 NetworkClientState *cs; |
|
155 NetworkClientInfo *ci; |
|
156 Packet *packet; |
|
157 Player *player; |
|
158 byte current = 0; |
|
159 int i; |
|
160 |
|
161 // Just a fail-safe.. should never happen |
|
162 if (!_network_udp_server) return; |
|
163 |
|
164 packet = NetworkSend_Init(PACKET_UDP_SERVER_DETAIL_INFO); |
|
165 |
|
166 /* Send the amount of active companies */ |
|
167 NetworkSend_uint8 (packet, NETWORK_COMPANY_INFO_VERSION); |
|
168 NetworkSend_uint8 (packet, ActivePlayerCount()); |
|
169 |
|
170 /* Fetch the latest version of everything */ |
|
171 NetworkPopulateCompanyInfo(); |
|
172 |
|
173 /* Go through all the players */ |
|
174 FOR_ALL_PLAYERS(player) { |
|
175 /* Skip non-active players */ |
|
176 if (!player->is_active) continue; |
|
177 |
|
178 current++; |
|
179 |
|
180 /* Send the information */ |
|
181 NetworkSend_uint8(packet, current); |
|
182 |
|
183 NetworkSend_string(packet, _network_player_info[player->index].company_name); |
|
184 NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year); |
|
185 NetworkSend_uint64(packet, _network_player_info[player->index].company_value); |
|
186 NetworkSend_uint64(packet, _network_player_info[player->index].money); |
|
187 NetworkSend_uint64(packet, _network_player_info[player->index].income); |
|
188 NetworkSend_uint16(packet, _network_player_info[player->index].performance); |
|
189 |
|
190 /* Send 1 if there is a passord for the company else send 0 */ |
|
191 if (_network_player_info[player->index].password[0] != '\0') { |
|
192 NetworkSend_uint8(packet, 1); |
|
193 } else { |
|
194 NetworkSend_uint8(packet, 0); |
|
195 } |
|
196 |
|
197 for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) |
|
198 NetworkSend_uint16(packet, _network_player_info[player->index].num_vehicle[i]); |
|
199 |
|
200 for (i = 0; i < NETWORK_STATION_TYPES; i++) |
|
201 NetworkSend_uint16(packet, _network_player_info[player->index].num_station[i]); |
|
202 |
|
203 /* Find the clients that are connected to this player */ |
|
204 FOR_ALL_CLIENTS(cs) { |
|
205 ci = DEREF_CLIENT_INFO(cs); |
|
206 if (ci->client_playas == player->index) { |
|
207 /* The uint8 == 1 indicates that a client is following */ |
|
208 NetworkSend_uint8(packet, 1); |
|
209 NetworkSend_string(packet, ci->client_name); |
|
210 NetworkSend_string(packet, ci->unique_id); |
|
211 NetworkSend_uint32(packet, ci->join_date); |
|
212 } |
|
213 } |
|
214 /* Also check for the server itself */ |
|
215 ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX); |
|
216 if (ci->client_playas == player->index) { |
|
217 /* The uint8 == 1 indicates that a client is following */ |
|
218 NetworkSend_uint8(packet, 1); |
|
219 NetworkSend_string(packet, ci->client_name); |
|
220 NetworkSend_string(packet, ci->unique_id); |
|
221 NetworkSend_uint32(packet, ci->join_date); |
|
222 } |
|
223 |
|
224 /* Indicates end of client list */ |
|
225 NetworkSend_uint8(packet, 0); |
|
226 } |
|
227 |
|
228 /* And check if we have any spectators */ |
|
229 FOR_ALL_CLIENTS(cs) { |
|
230 ci = DEREF_CLIENT_INFO(cs); |
|
231 if (!IsValidPlayer(ci->client_playas)) { |
|
232 /* The uint8 == 1 indicates that a client is following */ |
|
233 NetworkSend_uint8(packet, 1); |
|
234 NetworkSend_string(packet, ci->client_name); |
|
235 NetworkSend_string(packet, ci->unique_id); |
|
236 NetworkSend_uint32(packet, ci->join_date); |
|
237 } |
|
238 } |
|
239 |
|
240 /* Also check for the server itself */ |
|
241 ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX); |
|
242 if (!IsValidPlayer(ci->client_playas)) { |
|
243 /* The uint8 == 1 indicates that a client is following */ |
|
244 NetworkSend_uint8(packet, 1); |
|
245 NetworkSend_string(packet, ci->client_name); |
|
246 NetworkSend_string(packet, ci->unique_id); |
|
247 NetworkSend_uint32(packet, ci->join_date); |
|
248 } |
|
249 |
|
250 /* Indicates end of client list */ |
|
251 NetworkSend_uint8(packet, 0); |
|
252 |
|
253 NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr); |
|
254 |
|
255 free(packet); |
|
256 } |
|
257 |
|
258 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST) |
|
259 { |
351 { |
260 int i; |
352 int i; |
261 struct in_addr ip; |
353 struct in_addr ip; |
262 uint16 port; |
354 uint16 port; |
263 uint8 ver; |
355 uint8 ver; |
266 * then an uint16 which indicates how many |
358 * then an uint16 which indicates how many |
267 * ip:port pairs are in this packet, after that |
359 * ip:port pairs are in this packet, after that |
268 * an uint32 (ip) and an uint16 (port) for each pair |
360 * an uint32 (ip) and an uint16 (port) for each pair |
269 */ |
361 */ |
270 |
362 |
271 ver = NetworkRecv_uint8(&_udp_cs, p); |
363 ver = NetworkRecv_uint8(&this->cs, p); |
272 |
364 |
273 if (_udp_cs.has_quit) return; |
365 if (this->cs.has_quit) return; |
274 |
366 |
275 if (ver == 1) { |
367 if (ver == 1) { |
276 for (i = NetworkRecv_uint16(&_udp_cs, p); i != 0 ; i--) { |
368 for (i = NetworkRecv_uint16(&this->cs, p); i != 0 ; i--) { |
277 ip.s_addr = TO_LE32(NetworkRecv_uint32(&_udp_cs, p)); |
369 ip.s_addr = TO_LE32(NetworkRecv_uint32(&this->cs, p)); |
278 port = NetworkRecv_uint16(&_udp_cs, p); |
370 port = NetworkRecv_uint16(&this->cs, p); |
279 NetworkUDPQueryServer(inet_ntoa(ip), port); |
371 NetworkUDPQueryServer(inet_ntoa(ip), port); |
280 } |
372 } |
281 } |
373 } |
282 } |
374 } |
283 |
375 |
284 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER) |
376 /** The return of the client's request of the names of some NewGRFs */ |
285 { |
377 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_NEWGRFS) |
286 _network_advertise_retries = 0; |
|
287 DEBUG(net, 2, "[udp] advertising on master server successfull"); |
|
288 |
|
289 /* We are advertised, but we don't want to! */ |
|
290 if (!_network_advertise) NetworkUDPRemoveAdvertise(); |
|
291 } |
|
292 |
|
293 /** |
|
294 * A client has requested the names of some NewGRFs. |
|
295 * |
|
296 * Replying this can be tricky as we have a limit of SEND_MTU bytes |
|
297 * in the reply packet and we can send up to 100 bytes per NewGRF |
|
298 * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name). |
|
299 * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it |
|
300 * could be that a packet overflows. To stop this we only reply |
|
301 * with the first N NewGRFs so that if the first N + 1 NewGRFs |
|
302 * would be sent, the packet overflows. |
|
303 * in_reply and in_reply_count are used to keep a list of GRFs to |
|
304 * send in the reply. |
|
305 */ |
|
306 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS) |
|
307 { |
378 { |
308 uint8 num_grfs; |
379 uint8 num_grfs; |
309 uint i; |
380 uint i; |
310 |
381 |
311 const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT]; |
382 DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); |
312 Packet *packet; |
383 |
313 uint8 in_reply_count = 0; |
384 num_grfs = NetworkRecv_uint8 (&this->cs, p); |
314 uint packet_len = 0; |
|
315 |
|
316 /* Just a fail-safe.. should never happen */ |
|
317 if (_udp_cs.has_quit) return; |
|
318 |
|
319 DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); |
|
320 |
|
321 num_grfs = NetworkRecv_uint8 (&_udp_cs, p); |
|
322 if (num_grfs > NETWORK_MAX_GRF_COUNT) return; |
|
323 |
|
324 for (i = 0; i < num_grfs; i++) { |
|
325 GRFConfig c; |
|
326 const GRFConfig *f; |
|
327 |
|
328 NetworkRecv_GRFIdentifier(&_udp_cs, p, &c); |
|
329 |
|
330 /* Find the matching GRF file */ |
|
331 f = FindGRFConfig(c.grfid, c.md5sum); |
|
332 if (f == NULL) continue; // The GRF is unknown to this server |
|
333 |
|
334 /* If the reply might exceed the size of the packet, only reply |
|
335 * the current list and do not send the other data. |
|
336 * The name could be an empty string, if so take the filename. */ |
|
337 packet_len += sizeof(c.grfid) + sizeof(c.md5sum) + |
|
338 min(strlen((f->name != NULL && strlen(f->name) > 0) ? f->name : f->filename) + 1, (size_t)NETWORK_GRF_NAME_LENGTH); |
|
339 if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply |
|
340 break; |
|
341 } |
|
342 in_reply[in_reply_count] = f; |
|
343 in_reply_count++; |
|
344 } |
|
345 |
|
346 if (in_reply_count == 0) return; |
|
347 |
|
348 packet = NetworkSend_Init(PACKET_UDP_SERVER_NEWGRFS); |
|
349 NetworkSend_uint8 (packet, in_reply_count); |
|
350 for (i = 0; i < in_reply_count; i++) { |
|
351 char name[NETWORK_GRF_NAME_LENGTH]; |
|
352 |
|
353 /* The name could be an empty string, if so take the filename */ |
|
354 ttd_strlcpy(name, (in_reply[i]->name != NULL && strlen(in_reply[i]->name) > 0) ? |
|
355 in_reply[i]->name : in_reply[i]->filename, sizeof(name)); |
|
356 NetworkSend_GRFIdentifier(packet, in_reply[i]); |
|
357 NetworkSend_string(packet, name); |
|
358 } |
|
359 |
|
360 NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr); |
|
361 free(packet); |
|
362 } |
|
363 |
|
364 /** The return of the client's request of the names of some NewGRFs */ |
|
365 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS) |
|
366 { |
|
367 uint8 num_grfs; |
|
368 uint i; |
|
369 |
|
370 /* Just a fail-safe.. should never happen */ |
|
371 if (_udp_cs.has_quit) return; |
|
372 |
|
373 DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port)); |
|
374 |
|
375 num_grfs = NetworkRecv_uint8 (&_udp_cs, p); |
|
376 if (num_grfs > NETWORK_MAX_GRF_COUNT) return; |
385 if (num_grfs > NETWORK_MAX_GRF_COUNT) return; |
377 |
386 |
378 for (i = 0; i < num_grfs; i++) { |
387 for (i = 0; i < num_grfs; i++) { |
379 char *unknown_name; |
388 char *unknown_name; |
380 char name[NETWORK_GRF_NAME_LENGTH]; |
389 char name[NETWORK_GRF_NAME_LENGTH]; |
381 GRFConfig c; |
390 GRFConfig c; |
382 |
391 |
383 NetworkRecv_GRFIdentifier(&_udp_cs, p, &c); |
392 this->Recv_GRFIdentifier(p, &c); |
384 NetworkRecv_string(&_udp_cs, p, name, sizeof(name)); |
393 NetworkRecv_string(&this->cs, p, name, sizeof(name)); |
385 |
394 |
386 /* An empty name is not possible under normal circumstances |
395 /* An empty name is not possible under normal circumstances |
387 * and causes problems when showing the NewGRF list. */ |
396 * and causes problems when showing the NewGRF list. */ |
388 if (strlen(name) == 0) continue; |
397 if (strlen(name) == 0) continue; |
389 |
398 |
395 ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH); |
404 ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH); |
396 } |
405 } |
397 } |
406 } |
398 } |
407 } |
399 |
408 |
400 /** |
409 void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) |
401 * Every type of UDP packet should only be received by a single socket; |
410 { |
402 * The socket communicating with the masterserver should receive the |
411 /* Find the matching GRF file */ |
403 * game information of some 'random' host. |
412 const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum); |
404 */ |
413 if (f == NULL) { |
405 typedef struct NetworkUDPPacketAndSocket { |
414 /* Don't know the GRF, so mark game incompatible and the (possibly) |
406 void (*callback)(Packet *p, const struct sockaddr_in *client_addr); |
415 * already resolved name for this GRF (another server has sent the |
407 SOCKET *incoming_socket; |
416 * name of the GRF already */ |
408 } NetworkUPDPacketAndSocket; |
417 config->name = FindUnknownGRFName(config->grfid, config->md5sum, true); |
409 |
418 SETBIT(config->flags, GCF_NOT_FOUND); |
410 static const NetworkUPDPacketAndSocket _network_udp_packet[PACKET_UDP_END] = { |
|
411 { RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER), &_udp_server_socket }, |
|
412 { RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE), &_udp_client_socket }, |
|
413 { RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO), &_udp_server_socket }, |
|
414 { NULL, NULL }, |
|
415 { NULL, NULL }, |
|
416 { RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER), &_udp_master_socket }, |
|
417 { NULL, NULL }, |
|
418 { RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST), &_udp_client_socket }, |
|
419 { NULL, NULL }, |
|
420 { RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS), &_udp_server_socket }, |
|
421 { RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS), &_udp_client_socket }, |
|
422 }; |
|
423 |
|
424 void NetworkHandleUDPPacket(const SOCKET udp, Packet *p, const struct sockaddr_in *client_addr) |
|
425 { |
|
426 byte type; |
|
427 |
|
428 /* Fake a client, so we can see when there is an illegal packet */ |
|
429 _udp_cs.socket = INVALID_SOCKET; |
|
430 _udp_cs.has_quit = false; |
|
431 |
|
432 type = NetworkRecv_uint8(&_udp_cs, p); |
|
433 |
|
434 if (type < PACKET_UDP_END && *_network_udp_packet[type].incoming_socket == udp && !_udp_cs.has_quit) { |
|
435 _network_udp_packet[type].callback(p, client_addr); |
|
436 } else { |
419 } else { |
437 if (*_network_udp_packet[type].incoming_socket != udp) { |
420 config->filename = f->filename; |
438 DEBUG(net, 0, "[udp] received packet on wrong port from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port)); |
421 config->name = f->name; |
439 } else if (!_udp_cs.has_quit) { |
422 config->info = f->info; |
440 DEBUG(net, 0, "[udp] received invalid packet type %d from %s:%d", type, inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port)); |
423 } |
441 } else { |
424 SETBIT(config->flags, GCF_COPY); |
442 DEBUG(net, 0, "[udp] received illegal packet from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port)); |
425 } |
443 } |
|
444 } |
|
445 } |
|
446 |
|
447 |
426 |
448 // Close UDP connection |
427 // Close UDP connection |
449 void NetworkUDPStop(void) |
428 void NetworkUDPCloseAll(void) |
450 { |
429 { |
451 DEBUG(net, 1, "[udp] closed listeners"); |
430 DEBUG(net, 1, "[udp] closed listeners"); |
452 |
431 |
453 if (_network_udp_server) { |
432 _udp_server_socket->Close(); |
454 NetworkUDPClose(&_udp_server_socket); |
433 _udp_master_socket->Close(); |
455 NetworkUDPClose(&_udp_master_socket); |
434 _udp_client_socket->Close(); |
456 } else { |
|
457 NetworkUDPClose(&_udp_client_socket); |
|
458 } |
|
459 |
435 |
460 _network_udp_server = false; |
436 _network_udp_server = false; |
461 _network_udp_broadcast = 0; |
437 _network_udp_broadcast = 0; |
462 } |
438 } |
463 |
439 |
464 // Broadcast to all ips |
440 // Broadcast to all ips |
465 static void NetworkUDPBroadCast(SOCKET udp) |
441 static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket) |
466 { |
442 { |
467 Packet* p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER); |
443 Packet* p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER); |
468 uint i; |
444 uint i; |
469 |
445 |
470 for (i = 0; _broadcast_list[i] != 0; i++) { |
446 for (i = 0; _broadcast_list[i] != 0; i++) { |