1 /* $Id$ */ |
1 /* $Id$ */ |
2 |
2 |
3 #ifdef ENABLE_NETWORK |
3 #ifdef ENABLE_NETWORK |
4 |
4 |
5 #include "../../stdafx.h" |
5 #include "../../stdafx.h" |
6 #include "../../date.h" |
|
7 #include "../../debug.h" |
6 #include "../../debug.h" |
8 #include "../../macros.h" |
7 #include "../../macros.h" |
9 #include "../../newgrf_config.h" |
|
10 |
|
11 #include "os_abstraction.h" |
|
12 #include "config.h" |
|
13 #include "game.h" |
|
14 #include "packet.h" |
8 #include "packet.h" |
15 #include "udp.h" |
9 #include "udp.h" |
16 |
10 |
17 /** |
11 /** |
18 * @file udp.c Basic functions to receive and send UDP packets. |
12 * @file udp.c Basic functions to receive and send UDP packets. |
19 */ |
13 */ |
20 |
|
21 /** |
|
22 * Send a packet over UDP |
|
23 * @param udp the socket to send over |
|
24 * @param p the packet to send |
|
25 * @param recv the receiver (target) of the packet |
|
26 */ |
|
27 void NetworkSendUDP_Packet(SOCKET udp, Packet *p, struct sockaddr_in *recv) |
|
28 { |
|
29 int res; |
|
30 |
|
31 NetworkSend_FillPacketSize(p); |
|
32 |
|
33 /* Send the buffer */ |
|
34 res = sendto(udp, p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv)); |
|
35 |
|
36 /* Check for any errors, but ignore it otherwise */ |
|
37 if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR()); |
|
38 } |
|
39 |
14 |
40 /** |
15 /** |
41 * Start listening on the given host and port. |
16 * Start listening on the given host and port. |
42 * @param udp the place where the (references to the) UDP are stored |
17 * @param udp the place where the (references to the) UDP are stored |
43 * @param host the host (ip) to listen on |
18 * @param host the host (ip) to listen on |
44 * @param port the port to listen on |
19 * @param port the port to listen on |
45 * @param broadcast whether to allow broadcast sending/receiving |
20 * @param broadcast whether to allow broadcast sending/receiving |
46 * @return true if the listening succeeded |
21 * @return true if the listening succeeded |
47 */ |
22 */ |
48 bool NetworkUDPListen(SOCKET *udp, uint32 host, uint16 port, bool broadcast) |
23 bool NetworkUDPListen(SOCKET *udp, const uint32 host, const uint16 port, const bool broadcast) |
49 { |
24 { |
50 struct sockaddr_in sin; |
25 struct sockaddr_in sin; |
51 |
26 |
52 /* Make sure socket is closed */ |
27 /* Make sure socket is closed */ |
53 closesocket(*udp); |
28 NetworkUDPClose(udp); |
54 |
29 |
55 *udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
30 *udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
56 if (*udp == INVALID_SOCKET) { |
31 if (*udp == INVALID_SOCKET) { |
57 DEBUG(net, 0, "[udp] failed to start UDP listener"); |
32 DEBUG(net, 0, "[udp] failed to start UDP listener"); |
58 return false; |
33 return false; |
90 |
65 |
91 return true; |
66 return true; |
92 } |
67 } |
93 |
68 |
94 /** |
69 /** |
|
70 * Close the given UDP socket |
|
71 * @param udp the socket to close |
|
72 */ |
|
73 void NetworkUDPClose(SOCKET *udp) |
|
74 { |
|
75 if (*udp == INVALID_SOCKET) return; |
|
76 |
|
77 closesocket(*udp); |
|
78 *udp = INVALID_SOCKET; |
|
79 } |
|
80 |
|
81 |
|
82 /** |
|
83 * Send a packet over UDP |
|
84 * @param udp the socket to send over |
|
85 * @param p the packet to send |
|
86 * @param recv the receiver (target) of the packet |
|
87 */ |
|
88 void NetworkSendUDP_Packet(const SOCKET udp, Packet *p, const struct sockaddr_in *recv) |
|
89 { |
|
90 int res; |
|
91 |
|
92 NetworkSend_FillPacketSize(p); |
|
93 |
|
94 /* Send the buffer */ |
|
95 res = sendto(udp, p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv)); |
|
96 |
|
97 /* Check for any errors, but ignore it otherwise */ |
|
98 if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR()); |
|
99 } |
|
100 |
|
101 /** |
95 * Receive a packet at UDP level |
102 * Receive a packet at UDP level |
96 * @param udp the socket to receive the packet on |
103 * @param udp the socket to receive the packet on |
97 */ |
104 */ |
98 void NetworkUDPReceive(SOCKET udp) |
105 void NetworkUDPReceive(const SOCKET udp) |
99 { |
106 { |
100 struct sockaddr_in client_addr; |
107 struct sockaddr_in client_addr; |
101 socklen_t client_len; |
108 socklen_t client_len; |
102 int nbytes; |
109 int nbytes; |
103 Packet p; |
110 Packet p; |
107 client_len = sizeof(client_addr); |
114 client_len = sizeof(client_addr); |
108 |
115 |
109 /* Try to receive anything */ |
116 /* Try to receive anything */ |
110 nbytes = recvfrom(udp, p.buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len); |
117 nbytes = recvfrom(udp, p.buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len); |
111 |
118 |
112 /* We got some bytes for the base header of the packet. |
119 /* We got some bytes for the base header of the packet. */ |
113 * Assume we received the whole packet. */ |
|
114 if (nbytes > 2) { |
120 if (nbytes > 2) { |
115 NetworkRecv_ReadPacketSize(&p); |
121 NetworkRecv_ReadPacketSize(&p); |
|
122 |
|
123 /* If the size does not match the packet must be corrupted. |
|
124 * Otherwise it will be marked as corrupted later on. */ |
|
125 if (nbytes != p.size) { |
|
126 DEBUG(net, 1, "received a packet with mismatching size from %s:%d", |
|
127 inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); |
|
128 |
|
129 return; |
|
130 } |
116 |
131 |
117 /* Put the position on the right place */ |
132 /* Put the position on the right place */ |
118 p.pos = 2; |
133 p.pos = 2; |
119 p.next = NULL; |
134 p.next = NULL; |
120 |
135 |
121 /* Handle the packet */ |
136 /* Handle the packet */ |
122 NetworkHandleUDPPacket(&p, &client_addr); |
137 NetworkHandleUDPPacket(udp, &p, &client_addr); |
123 } |
138 } |
124 } |
139 } |
125 |
140 |
126 |
141 |
127 /** |
142 /** |
166 /* |
181 /* |
167 * Please observe the order. |
182 * Please observe the order. |
168 * The parts must be read in the same order as they are sent! |
183 * The parts must be read in the same order as they are sent! |
169 */ |
184 */ |
170 |
185 |
|
186 /* Update the documentation in udp.h on changes |
|
187 * to the NetworkGameInfo wire-protocol! */ |
171 |
188 |
172 /* NETWORK_GAME_INFO_VERSION = 4 */ |
189 /* NETWORK_GAME_INFO_VERSION = 4 */ |
173 { |
190 { |
174 /* Only send the GRF Identification (GRF_ID and MD5 checksum) of |
191 /* Only send the GRF Identification (GRF_ID and MD5 checksum) of |
175 * the GRFs that are needed, i.e. the ones that the server has |
192 * the GRFs that are needed, i.e. the ones that the server has |