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