1 /*
2 * Copyright 2006 Serge van den Boom <svdb@stack.nl>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include "netplay.h"
20 #include "packet.h"
21
22 #include "uqmversion.h"
23
24 #include "netrcv.h"
25 #include "packethandlers.h"
26
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31
32 #define DEFINE_PACKETDATA(name) \
33 { \
34 /* .len = */ sizeof (Packet_##name), \
35 /* .handler = */ (PacketHandler) PacketHandler_##name, \
36 /* .name = */ #name, \
37 }
38 PacketTypeData packetTypeData[PACKET_NUM] = {
39 DEFINE_PACKETDATA(Init),
40 DEFINE_PACKETDATA(Ping),
41 DEFINE_PACKETDATA(Ack),
42 DEFINE_PACKETDATA(Ready),
43 DEFINE_PACKETDATA(Fleet),
44 DEFINE_PACKETDATA(TeamName),
45 DEFINE_PACKETDATA(Handshake0),
46 DEFINE_PACKETDATA(Handshake1),
47 DEFINE_PACKETDATA(HandshakeCancel),
48 DEFINE_PACKETDATA(HandshakeCancelAck),
49 DEFINE_PACKETDATA(SeedRandom),
50 DEFINE_PACKETDATA(InputDelay),
51 DEFINE_PACKETDATA(SelectShip),
52 DEFINE_PACKETDATA(BattleInput),
53 DEFINE_PACKETDATA(FrameCount),
54 DEFINE_PACKETDATA(Checksum),
55 DEFINE_PACKETDATA(Abort),
56 DEFINE_PACKETDATA(Reset),
57 };
58
59 static inline void *
Packet_alloc(size_t size)60 Packet_alloc(size_t size) {
61 return malloc(size);
62 }
63
64 static Packet *
Packet_create(PacketType type,size_t extraSize)65 Packet_create(PacketType type, size_t extraSize) {
66 Packet *result;
67 size_t len;
68
69 // Alignment requirement.
70 assert(extraSize % 4 == 0);
71
72 len = packetTypeData[type].len + extraSize;
73 result = Packet_alloc(len);
74 result->header.len = hton16((uint16) len);
75 result->header.type = hton16((uint16) type);
76 return result;
77 }
78
79 void
Packet_delete(Packet * packet)80 Packet_delete(Packet *packet) {
81 free(packet);
82 }
83
84 Packet_Init *
Packet_Init_create(void)85 Packet_Init_create(void) {
86 Packet_Init *packet = (Packet_Init *) Packet_create(PACKET_INIT, 0);
87
88 packet->protoVersion.major = NETPLAY_PROTOCOL_VERSION_MAJOR;
89 packet->protoVersion.minor = NETPLAY_PROTOCOL_VERSION_MINOR;
90 packet->padding0 = 0;
91 packet->uqmVersion.major = UQM_MAJOR_VERSION;
92 packet->uqmVersion.minor = UQM_MINOR_VERSION;
93 packet->uqmVersion.patch = UQM_PATCH_VERSION;
94 packet->padding1 = 0;
95 return packet;
96 }
97
98 Packet_Ping *
Packet_Ping_create(uint32 id)99 Packet_Ping_create(uint32 id) {
100 Packet_Ping *packet = (Packet_Ping *) Packet_create(PACKET_PING, 0);
101
102 packet->id = hton32(id);
103 return packet;
104 }
105
106 Packet_Ack *
Packet_Ack_create(uint32 id)107 Packet_Ack_create(uint32 id) {
108 Packet_Ack *packet = (Packet_Ack *) Packet_create(PACKET_ACK, 0);
109
110 packet->id = hton32(id);
111 return packet;
112 }
113
114 Packet_Ready *
Packet_Ready_create(void)115 Packet_Ready_create(void) {
116 Packet_Ready *packet = (Packet_Ready *) Packet_create(PACKET_READY, 0);
117
118 return packet;
119 }
120
121 // The fleet itself still needs to be filled by the caller.
122 // This function takes care of the necessary padding; it is allocated,
123 // and filled with zero chars.
124 Packet_Fleet *
Packet_Fleet_create(NetplaySide side,size_t numShips)125 Packet_Fleet_create(NetplaySide side, size_t numShips) {
126 Packet_Fleet *packet;
127 size_t fleetSize;
128 size_t extraSize;
129
130 fleetSize = numShips * sizeof (FleetEntry);
131 extraSize = (fleetSize + 3) & ~0x03;
132 packet = (Packet_Fleet *) Packet_create(PACKET_FLEET, extraSize);
133 packet->side = (uint8) side;
134 packet->padding = 0;
135 packet->numShips = hton16((uint16) numShips);
136 memset((char *) packet + sizeof (Packet_Fleet) + fleetSize,
137 '\0', extraSize - fleetSize);
138
139 return packet;
140 }
141
142 // 'size' is the number of bytes (not characters) in 'name', excluding
143 // a possible terminating '\0'. A '\0' will be included in the packet though.
144 // This function takes care of the required padding.
145 Packet_TeamName *
Packet_TeamName_create(NetplaySide side,const char * name,size_t size)146 Packet_TeamName_create(NetplaySide side, const char *name, size_t size) {
147 Packet_TeamName *packet;
148 size_t extraSize;
149
150 extraSize = ((size + 1) + 3) & ~0x03;
151 // The +1 is for the '\0'.
152 packet = (Packet_TeamName *) Packet_create(PACKET_TEAMNAME, extraSize);
153 packet->side = (uint8) side;
154 packet->padding = 0;
155 memcpy(packet->name, name, size);
156 memset((char *) packet + sizeof (Packet_TeamName) + size, '\0',
157 extraSize - size);
158 // This takes care of the terminating '\0', as well as the
159 // padding.
160
161 return packet;
162 }
163
164 Packet_Handshake0 *
Packet_Handshake0_create(void)165 Packet_Handshake0_create(void) {
166 Packet_Handshake0 *packet =
167 (Packet_Handshake0 *) Packet_create(PACKET_HANDSHAKE0, 0);
168 return packet;
169 }
170
171 Packet_Handshake1 *
Packet_Handshake1_create(void)172 Packet_Handshake1_create(void) {
173 Packet_Handshake1 *packet =
174 (Packet_Handshake1 *) Packet_create(PACKET_HANDSHAKE1, 0);
175 return packet;
176 }
177
178 Packet_HandshakeCancel *
Packet_HandshakeCancel_create(void)179 Packet_HandshakeCancel_create(void) {
180 Packet_HandshakeCancel *packet =
181 (Packet_HandshakeCancel *) Packet_create(
182 PACKET_HANDSHAKECANCEL, 0);
183 return packet;
184 }
185
186 Packet_HandshakeCancelAck *
Packet_HandshakeCancelAck_create(void)187 Packet_HandshakeCancelAck_create(void) {
188 Packet_HandshakeCancelAck *packet =
189 (Packet_HandshakeCancelAck *) Packet_create(
190 PACKET_HANDSHAKECANCELACK, 0);
191 return packet;
192 }
193
194 Packet_SeedRandom *
Packet_SeedRandom_create(uint32 seed)195 Packet_SeedRandom_create(uint32 seed) {
196 Packet_SeedRandom *packet =
197 (Packet_SeedRandom *) Packet_create(PACKET_SEEDRANDOM, 0);
198
199 packet->seed = hton32(seed);
200 return packet;
201 }
202
203 Packet_InputDelay *
Packet_InputDelay_create(uint32 delay)204 Packet_InputDelay_create(uint32 delay) {
205 Packet_InputDelay *packet =
206 (Packet_InputDelay *) Packet_create(PACKET_INPUTDELAY, 0);
207
208 packet->delay = hton32(delay);
209 return packet;
210 }
211
212 Packet_SelectShip *
Packet_SelectShip_create(uint16 ship)213 Packet_SelectShip_create(uint16 ship) {
214 Packet_SelectShip *packet =
215 (Packet_SelectShip *) Packet_create(PACKET_SELECTSHIP, 0);
216 packet->ship = hton16(ship);
217 packet->padding = 0;
218 return packet;
219 }
220
221 Packet_BattleInput *
Packet_BattleInput_create(uint8 state)222 Packet_BattleInput_create(uint8 state) {
223 Packet_BattleInput *packet =
224 (Packet_BattleInput *) Packet_create(PACKET_BATTLEINPUT, 0);
225 packet->state = (uint8) state;
226 packet->padding0 = 0;
227 packet->padding1 = 0;
228 return packet;
229 }
230
231 Packet_FrameCount *
Packet_FrameCount_create(uint32 frameCount)232 Packet_FrameCount_create(uint32 frameCount) {
233 Packet_FrameCount *packet =
234 (Packet_FrameCount *) Packet_create(PACKET_FRAMECOUNT, 0);
235 packet->frameCount = hton32(frameCount);
236 return packet;
237 }
238
239 Packet_Checksum *
Packet_Checksum_create(uint32 frameNr,uint32 checksum)240 Packet_Checksum_create(uint32 frameNr, uint32 checksum) {
241 Packet_Checksum *packet =
242 (Packet_Checksum *) Packet_create(PACKET_CHECKSUM, 0);
243 packet->frameNr = hton32(frameNr);
244 packet->checksum = hton32(checksum);
245 return packet;
246 }
247
248 Packet_Abort *
Packet_Abort_create(uint16 reason)249 Packet_Abort_create(uint16 reason) {
250 Packet_Abort *packet = (Packet_Abort *) Packet_create(PACKET_ABORT, 0);
251 packet->reason = hton16(reason);
252 return packet;
253 }
254
255 Packet_Reset *
Packet_Reset_create(uint16 reason)256 Packet_Reset_create(uint16 reason) {
257 Packet_Reset *packet = (Packet_Reset *) Packet_create(PACKET_RESET, 0);
258 packet->reason = hton16(reason);
259 return packet;
260 }
261
262
263
264