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 #define PORT_WANT_ERRNO
20 #include "port.h"
21
22 #define NETCONNECTION_INTERNAL
23 #include "netplay.h"
24 #include "packethandlers.h"
25
26 #include "netinput.h"
27 #include "netmisc.h"
28 #include "packetsenders.h"
29 #include "proto/npconfirm.h"
30 #include "proto/ready.h"
31 #include "proto/reset.h"
32 #include "libs/log.h"
33
34 #include "../../controls.h"
35 // for BATTLE_INPUT_STATE
36 #include "../../init.h"
37 // for NUM_PLAYERS
38 #include "../../globdata.h"
39 // for GLOBAL
40 #include "../melee.h"
41 // for various update functions.
42 #include "../meleeship.h"
43 // for MeleeShip
44 #include "../pickmele.h"
45 // for various update functions.
46 #include "libs/mathlib.h"
47 // for TFB_SeedRandom
48
49 #include <errno.h>
50
51
52 static bool
testNetState(bool condition,PacketType type)53 testNetState(bool condition, PacketType type) {
54 if (!condition) {
55 log_add(log_Error, "Packet of type '%s' received from wrong "
56 "state.", packetTypeData[type].name);
57 errno = EBADMSG;
58 }
59 return condition;
60 }
61
62 static int
versionCompare(int major1,int minor1,int patch1,int major2,int minor2,int patch2)63 versionCompare(int major1, int minor1, int patch1,
64 int major2, int minor2, int patch2) {
65 if (major1 < major2)
66 return -1;
67 if (major1 > major2)
68 return 1;
69
70 if (minor1 < minor2)
71 return -1;
72 if (minor1 > minor2)
73 return 1;
74
75 if (patch1 < patch2)
76 return -1;
77 if (patch1 > patch2)
78 return 1;
79
80 return 0;
81 }
82
83 int
PacketHandler_Init(NetConnection * conn,const Packet_Init * packet)84 PacketHandler_Init(NetConnection *conn, const Packet_Init *packet) {
85 if (conn->stateFlags.reset.localReset)
86 return 0;
87 if (conn->stateFlags.reset.remoteReset) {
88 errno = EBADMSG;
89 return -1;
90 }
91
92 if (!testNetState(conn->state == NetState_init &&
93 !conn->stateFlags.ready.remoteReady, PACKET_INIT))
94 return -1; // errno is set
95
96 if (packet->protoVersion.major != NETPLAY_PROTOCOL_VERSION_MAJOR ||
97 packet->protoVersion.minor != NETPLAY_PROTOCOL_VERSION_MINOR) {
98 sendAbort (conn, AbortReason_versionMismatch);
99 abortFeedback(conn, AbortReason_versionMismatch);
100 log_add(log_Error, "Protocol version %d.%d not supported.",
101 packet->protoVersion.major, packet->protoVersion.minor);
102 errno = ENOSYS;
103 return -1;
104 }
105
106 if (versionCompare(packet->uqmVersion.major, packet->uqmVersion.minor,
107 packet->uqmVersion.patch, NETPLAY_MIN_UQM_VERSION_MAJOR,
108 NETPLAY_MIN_UQM_VERSION_MINOR, NETPLAY_MIN_UQM_VERSION_PATCH)
109 < 0) {
110 sendAbort (conn, AbortReason_versionMismatch);
111 abortFeedback(conn, AbortReason_versionMismatch);
112 log_add(log_Error, "Remote side is running a version of UQM that "
113 "is too old (%d.%d.%d; %d.%d.%d is required).",
114 packet->uqmVersion.major, packet->uqmVersion.minor,
115 packet->uqmVersion.patch, NETPLAY_MIN_UQM_VERSION_MAJOR,
116 NETPLAY_MIN_UQM_VERSION_MINOR, NETPLAY_MIN_UQM_VERSION_PATCH);
117 errno = ENOSYS;
118 return -1;
119 }
120
121 Netplay_remoteReady(conn);
122
123 return 0;
124 }
125
126 int
PacketHandler_Ping(NetConnection * conn,const Packet_Ping * packet)127 PacketHandler_Ping(NetConnection *conn, const Packet_Ping *packet) {
128 if (!testNetState(conn->state > NetState_init, PACKET_PING))
129 return -1; // errno is set
130
131 sendAck(conn, packet->id);
132 return 0;
133 }
134
135 int
PacketHandler_Ack(NetConnection * conn,const Packet_Ack * packet)136 PacketHandler_Ack(NetConnection *conn, const Packet_Ack *packet) {
137 if (!testNetState(conn->state > NetState_init, PACKET_ACK))
138 return -1; // errno is set
139
140 (void) conn;
141 (void) packet;
142 return 0;
143 }
144
145 // Convert the side indication relative to a remote party to
146 // a local player number.
147 static inline int
localSide(NetConnection * conn,NetplaySide side)148 localSide(NetConnection *conn, NetplaySide side) {
149 if (side == NetplaySide_local) {
150 // "local" relative to the remote party.
151 return conn->player;
152 }
153
154 return 1 - conn->player;
155 }
156
157 int
PacketHandler_Ready(NetConnection * conn,const Packet_Ready * packet)158 PacketHandler_Ready(NetConnection *conn, const Packet_Ready *packet) {
159 if (conn->stateFlags.reset.localReset)
160 return 0;
161 if (conn->stateFlags.reset.remoteReset) {
162 errno = EBADMSG;
163 return -1;
164 }
165
166 if (!testNetState(readyFlagsMeaningful(conn->state) &&
167 !conn->stateFlags.ready.remoteReady, PACKET_READY))
168 return -1; // errno is set
169
170 Netplay_remoteReady(conn);
171
172 (void) packet;
173 // Its contents is not interesting.
174
175 return 0;
176 }
177
178 int
PacketHandler_Fleet(NetConnection * conn,const Packet_Fleet * packet)179 PacketHandler_Fleet(NetConnection *conn, const Packet_Fleet *packet) {
180 uint16 numShips = ntoh16(packet->numShips);
181 size_t i;
182 size_t len;
183 int player;
184 BattleStateData *battleStateData;
185
186 if (conn->stateFlags.reset.localReset)
187 return 0;
188 if (conn->stateFlags.reset.remoteReset) {
189 errno = EBADMSG;
190 return -1;
191 }
192
193 if (!testNetState(conn->state == NetState_inSetup, PACKET_FLEET))
194 return -1; // errno is set
195
196 player = localSide(conn, (NetplaySide) packet->side);
197
198 len = packetLength((const Packet *) packet);
199 if (sizeof packet + numShips * sizeof(packet->ships[0]) > len) {
200 // There is not enough room in the packet to contain all
201 // the ships it says it contains.
202 log_add(log_Warning, "Invalid fleet size. Specified size is %d, "
203 "actual size = %d",
204 numShips, (int) ((len - sizeof packet) / sizeof(packet->ships[0])));
205 errno = EBADMSG;
206 return -1;
207 }
208
209 battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
210
211 if (conn->stateFlags.handshake.localOk) {
212 Netplay_cancelConfirmation(conn);
213 confirmationCancelled(battleStateData->meleeState, conn->player);
214 }
215
216 for (i = 0; i < numShips; i++) {
217 MeleeShip ship = (MeleeShip) packet->ships[i].ship;
218 FleetShipIndex index = (FleetShipIndex) packet->ships[i].index;
219
220 if (!MeleeShip_valid(ship)) {
221 log_add (log_Warning, "Invalid ship type number %d (max = %d).\n",
222 ship, NUM_MELEE_SHIPS - 1);
223 errno = EBADMSG;
224 return -1;
225 }
226
227 if (index >= MELEE_FLEET_SIZE)
228 {
229 log_add (log_Warning, "Invalid ship position number %d "
230 "(max = %d).\n", index, MELEE_FLEET_SIZE - 1);
231 errno = EBADMSG;
232 return -1;
233 }
234
235 Melee_RemoteChange_ship (battleStateData->meleeState, conn,
236 player, index, ship);
237 }
238
239 // Padding data may follow; it is ignored.
240 return 0;
241 }
242
243 int
PacketHandler_TeamName(NetConnection * conn,const Packet_TeamName * packet)244 PacketHandler_TeamName(NetConnection *conn, const Packet_TeamName *packet) {
245 size_t nameLen;
246 int side;
247 BattleStateData *battleStateData;
248
249 if (conn->stateFlags.reset.localReset)
250 return 0;
251 if (conn->stateFlags.reset.remoteReset) {
252 errno = EBADMSG;
253 return -1;
254 }
255
256 if (!testNetState(conn->state == NetState_inSetup, PACKET_FLEET))
257 return -1; // errno is set
258
259 battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
260
261 if (conn->stateFlags.handshake.localOk) {
262 Netplay_cancelConfirmation(conn);
263 confirmationCancelled(battleStateData->meleeState, conn->player);
264 }
265
266 side = localSide(conn, (NetplaySide) packet->side);
267 nameLen = packetLength((const Packet *) packet)
268 - sizeof (Packet_TeamName) - 1;
269 // The -1 is for not counting the terminating '\0'.
270
271 {
272 char buf[MAX_TEAM_CHARS + 1];
273
274 if (nameLen > MAX_TEAM_CHARS)
275 nameLen = MAX_TEAM_CHARS;
276 memcpy (buf, (const char *) packet->name, nameLen);
277 buf[nameLen] = '\0';
278
279 Melee_RemoteChange_teamName(battleStateData->meleeState, conn,
280 side, buf);
281 }
282
283 // Padding data may follow; it is ignored.
284 return 0;
285 }
286
287 static void
handshakeComplete(NetConnection * conn)288 handshakeComplete(NetConnection *conn) {
289 assert(!conn->stateFlags.handshake.localOk);
290 assert(!conn->stateFlags.handshake.remoteOk);
291 assert(!conn->stateFlags.handshake.canceling);
292
293 assert(conn->state == NetState_inSetup);
294 NetConnection_setState(conn, NetState_preBattle);
295 }
296
297 int
PacketHandler_Handshake0(NetConnection * conn,const Packet_Handshake0 * packet)298 PacketHandler_Handshake0(NetConnection *conn,
299 const Packet_Handshake0 *packet) {
300 if (conn->stateFlags.reset.localReset)
301 return 0;
302 if (conn->stateFlags.reset.remoteReset) {
303 errno = EBADMSG;
304 return -1;
305 }
306
307 if (!testNetState(handshakeMeaningful(conn->state)
308 && !conn->stateFlags.handshake.remoteOk, PACKET_HANDSHAKE0))
309 return -1; // errno is set
310
311 conn->stateFlags.handshake.remoteOk = true;
312 if (conn->stateFlags.handshake.localOk &&
313 !conn->stateFlags.handshake.canceling)
314 sendHandshake1(conn);
315
316 (void) packet;
317 // Its contents is not interesting.
318
319 return 0;
320 }
321
322 int
PacketHandler_Handshake1(NetConnection * conn,const Packet_Handshake1 * packet)323 PacketHandler_Handshake1(NetConnection *conn,
324 const Packet_Handshake1 *packet) {
325 if (conn->stateFlags.reset.localReset)
326 return 0;
327 if (conn->stateFlags.reset.remoteReset) {
328 errno = EBADMSG;
329 return -1;
330 }
331
332 if (!testNetState(handshakeMeaningful(conn->state) &&
333 (conn->stateFlags.handshake.localOk ||
334 conn->stateFlags.handshake.canceling), PACKET_HANDSHAKE1))
335 return -1; // errno is set
336
337 if (conn->stateFlags.handshake.canceling) {
338 conn->stateFlags.handshake.remoteOk = true;
339 } else {
340 bool remoteWasOk = conn->stateFlags.handshake.remoteOk;
341
342 conn->stateFlags.handshake.localOk = false;
343 conn->stateFlags.handshake.remoteOk = false;
344
345 if (!remoteWasOk) {
346 // Received Handshake1 without prior Handshake0.
347 // A Handshake0 is implied, but we still need to confirm
348 // it with a Handshake1.
349 sendHandshake1(conn);
350 }
351
352 handshakeComplete(conn);
353 }
354
355 (void) packet;
356 // Its contents is not interesting.
357
358 return 0;
359 }
360
361 int
PacketHandler_HandshakeCancel(NetConnection * conn,const Packet_HandshakeCancel * packet)362 PacketHandler_HandshakeCancel(NetConnection *conn,
363 const Packet_HandshakeCancel *packet) {
364 if (conn->stateFlags.reset.localReset)
365 return 0;
366 if (conn->stateFlags.reset.remoteReset) {
367 errno = EBADMSG;
368 return -1;
369 }
370
371 if (!testNetState(handshakeMeaningful(conn->state)
372 && conn->stateFlags.handshake.remoteOk, PACKET_HANDSHAKECANCEL))
373 return -1; // errno is set
374
375 conn->stateFlags.handshake.remoteOk = false;
376 sendHandshakeCancelAck(conn);
377
378 (void) packet;
379 // Its contents is not interesting.
380
381 return 0;
382 }
383
384 int
PacketHandler_HandshakeCancelAck(NetConnection * conn,const Packet_HandshakeCancelAck * packet)385 PacketHandler_HandshakeCancelAck(NetConnection *conn,
386 const Packet_HandshakeCancelAck *packet) {
387 if (conn->stateFlags.reset.localReset)
388 return 0;
389 if (conn->stateFlags.reset.remoteReset) {
390 errno = EBADMSG;
391 return -1;
392 }
393
394 if (!testNetState(handshakeMeaningful(conn->state)
395 && conn->stateFlags.handshake.canceling,
396 PACKET_HANDSHAKECANCELACK))
397 return -1; // errno is set
398
399 conn->stateFlags.handshake.canceling = false;
400 if (conn->stateFlags.handshake.localOk) {
401 if (conn->stateFlags.handshake.remoteOk) {
402 sendHandshake1(conn);
403 } else
404 sendHandshake0(conn);
405 }
406
407 (void) packet;
408 // Its contents is not interesting.
409
410 return 0;
411 }
412
413 int
PacketHandler_SeedRandom(NetConnection * conn,const Packet_SeedRandom * packet)414 PacketHandler_SeedRandom(NetConnection *conn,
415 const Packet_SeedRandom *packet) {
416 BattleStateData *battleStateData;
417
418 if (conn->stateFlags.reset.localReset)
419 return 0;
420 if (conn->stateFlags.reset.remoteReset) {
421 errno = EBADMSG;
422 return -1;
423 }
424
425 if (!testNetState(conn->state == NetState_preBattle &&
426 !conn->stateFlags.discriminant, PACKET_SEEDRANDOM))
427 return -1; // errno is set
428
429 battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
430 updateRandomSeed (battleStateData->meleeState, conn->player,
431 ntoh32(packet->seed));
432
433 conn->stateFlags.agreement.randomSeed = true;
434 return 0;
435 }
436
437 int
PacketHandler_InputDelay(NetConnection * conn,const Packet_InputDelay * packet)438 PacketHandler_InputDelay(NetConnection *conn,
439 const Packet_InputDelay *packet) {
440 BattleStateData *battleStateData;
441 uint32 delay;
442
443 if (conn->stateFlags.reset.localReset)
444 return 0;
445 if (conn->stateFlags.reset.remoteReset) {
446 errno = EBADMSG;
447 return -1;
448 }
449
450 if (!testNetState(conn->state == NetState_preBattle, PACKET_INPUTDELAY))
451 return -1; // errno is set
452
453 battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
454 delay = ntoh32(packet->delay);
455 if (delay > BATTLE_FRAME_RATE) {
456 log_add(log_Error, "NETPLAY: [%d] Received absurdly large "
457 "input delay value (%d).", conn->player, delay);
458 return -1;
459 }
460 conn->stateFlags.inputDelay = delay;
461
462 return 0;
463 }
464
465 int
PacketHandler_SelectShip(NetConnection * conn,const Packet_SelectShip * packet)466 PacketHandler_SelectShip(NetConnection *conn,
467 const Packet_SelectShip *packet) {
468 bool updateResult;
469 BattleStateData *battleStateData;
470
471 if (conn->stateFlags.reset.localReset)
472 return 0;
473 if (conn->stateFlags.reset.remoteReset) {
474 errno = EBADMSG;
475 return -1;
476 }
477
478 if (!testNetState(conn->state == NetState_selectShip, PACKET_SELECTSHIP))
479 return -1; // errno is set
480
481 battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
482 updateResult = updateMeleeSelection(battleStateData->getMeleeState,
483 conn->player, ntoh16(packet->ship));
484 if (!updateResult)
485 {
486 errno = EBADMSG;
487 return -1;
488 }
489
490 return 0;
491 }
492
493 int
PacketHandler_BattleInput(NetConnection * conn,const Packet_BattleInput * packet)494 PacketHandler_BattleInput(NetConnection *conn,
495 const Packet_BattleInput *packet) {
496 BATTLE_INPUT_STATE input;
497 BattleInputBuffer *bib;
498
499 if (conn->stateFlags.reset.localReset)
500 return 0;
501 if (conn->stateFlags.reset.remoteReset) {
502 errno = EBADMSG;
503 return -1;
504 }
505
506 if (!testNetState(conn->state == NetState_inBattle ||
507 conn->state == NetState_endingBattle ||
508 conn->state == NetState_endingBattle2, PACKET_BATTLEINPUT))
509 return -1; // errno is set
510
511 input = (BATTLE_INPUT_STATE) packet->state;
512 bib = getBattleInputBuffer(conn->player);
513 if (!BattleInputBuffer_push(bib, input)) {
514 // errno is set
515 return -1;
516 }
517
518 return 0;
519 }
520
521 int
PacketHandler_FrameCount(NetConnection * conn,const Packet_FrameCount * packet)522 PacketHandler_FrameCount(NetConnection *conn,
523 const Packet_FrameCount *packet) {
524 BattleStateData *battleStateData;
525 BattleFrameCounter frameCount;
526
527 if (conn->stateFlags.reset.localReset)
528 return 0;
529 if (conn->stateFlags.reset.remoteReset) {
530 errno = EBADMSG;
531 return -1;
532 }
533
534 if (!testNetState(conn->state == NetState_endingBattle,
535 PACKET_FRAMECOUNT))
536 return -1; // errno is set
537
538 frameCount = (BattleFrameCounter) ntoh32(packet->frameCount);
539 #ifdef NETPLAY_DEBUG
540 log_add(log_Debug, "NETPLAY: [%d] <== Received battleFrameCount %u.",
541 conn->player, (unsigned int) frameCount);
542 #endif
543
544 battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
545 if (frameCount > battleStateData->endFrameCount)
546 battleStateData->endFrameCount = frameCount;
547 Netplay_remoteReady(conn);
548
549 return 0;
550 }
551
552 int
PacketHandler_Checksum(NetConnection * conn,const Packet_Checksum * packet)553 PacketHandler_Checksum(NetConnection *conn, const Packet_Checksum *packet) {
554 #ifdef NETPLAY_CHECKSUM
555 uint32 frameNr;
556 uint32 checksum;
557 size_t delay;
558 size_t interval;
559 #endif
560
561 if (conn->stateFlags.reset.localReset)
562 return 0;
563 if (conn->stateFlags.reset.remoteReset) {
564 errno = EBADMSG;
565 return -1;
566 }
567
568 if (!testNetState(NetState_battleActive(conn->state), PACKET_CHECKSUM))
569 return -1; // errno is set
570
571 #ifdef NETPLAY_CHECKSUM
572 frameNr = ntoh32(packet->frameNr);
573 checksum = ntoh32(packet->checksum);
574 interval = NetConnection_getChecksumInterval(conn);
575 delay = getBattleInputDelay();
576
577 if (frameNr % interval != 0) {
578 log_add(log_Warning, "NETPLAY: [%d] <== Received checksum "
579 "for frame %u, while we only expect checksums on frames "
580 "divisable by %u -- discarding.", conn->player,
581 (unsigned int) frameNr, (unsigned int) interval);
582 return 0;
583 // No need to close the connection; checksums are not
584 // essential.
585 }
586
587 // The checksum is sent at the beginning of a frame.
588 // If we're in frame n and have sent our input already,
589 // the remote side has got enough input to progress delay + 1 frames from
590 // frame n. The next frame is then n + delay + 1, for which we can
591 // receive a checksum.
592 if (frameNr > battleFrameCount + delay + 1) {
593 log_add(log_Warning, "NETPLAY: [%d] <== Received checksum "
594 "for a frame too far in the future (frame %u, current "
595 "is %u, input delay is %u) -- discarding.", conn->player,
596 (unsigned int) frameNr, (unsigned int) battleFrameCount, (unsigned int) delay);
597 return 0;
598 // No need to close the connection; checksums are not
599 // essential.
600 }
601
602 // We can progress delay more frames after the last frame for which we
603 // received input. If we call that frame n, we can complete frames
604 // n through n + delay - 1. While we are waiting for the next input,
605 // in frame n + delay, we will first receive the checksum that the
606 // remote side sent at the start of frame n + 1.
607 // In this situation frameNr is n + 1, and battleFrameCount is
608 // n + delay.
609 if (frameNr + delay < battleFrameCount) {
610 log_add(log_Warning, "NETPLAY: [%d] <== Received checksum "
611 "for a frame too far in the past (frame %u, current "
612 "is %u, input delay is %u) -- discarding.", conn->player,
613 (unsigned int) frameNr, (unsigned int) battleFrameCount, (unsigned int) delay);
614 return 0;
615 // No need to close the connection; checksums are not
616 // essential.
617 }
618
619 addRemoteChecksum(conn, frameNr, checksum);
620 #endif
621
622 #ifndef NETPLAY_CHECKSUM
623 (void) packet;
624 #endif
625 return 0;
626 }
627
628 int
PacketHandler_Abort(NetConnection * conn,const Packet_Abort * packet)629 PacketHandler_Abort(NetConnection *conn, const Packet_Abort *packet) {
630 abortFeedback(conn, packet->reason);
631
632 return -1;
633 // Close connection.
634 }
635
636 int
PacketHandler_Reset(NetConnection * conn,const Packet_Reset * packet)637 PacketHandler_Reset(NetConnection *conn, const Packet_Reset *packet) {
638 NetplayResetReason reason;
639
640 if (!testNetState(!conn->stateFlags.reset.remoteReset, PACKET_RESET))
641 return -1; // errno is set
642
643 reason = ntoh16(packet->reason);
644
645 Netplay_remoteReset(conn, reason);
646 return 0;
647 }
648
649
650