diff options
Diffstat (limited to 'src/uqm/supermelee/netplay/proto')
-rw-r--r-- | src/uqm/supermelee/netplay/proto/Makeinfo | 2 | ||||
-rw-r--r-- | src/uqm/supermelee/netplay/proto/npconfirm.c | 81 | ||||
-rw-r--r-- | src/uqm/supermelee/netplay/proto/npconfirm.h | 36 | ||||
-rw-r--r-- | src/uqm/supermelee/netplay/proto/ready.c | 106 | ||||
-rw-r--r-- | src/uqm/supermelee/netplay/proto/ready.h | 38 | ||||
-rw-r--r-- | src/uqm/supermelee/netplay/proto/reset.c | 166 | ||||
-rw-r--r-- | src/uqm/supermelee/netplay/proto/reset.h | 41 |
7 files changed, 470 insertions, 0 deletions
diff --git a/src/uqm/supermelee/netplay/proto/Makeinfo b/src/uqm/supermelee/netplay/proto/Makeinfo new file mode 100644 index 0000000..1d9739c --- /dev/null +++ b/src/uqm/supermelee/netplay/proto/Makeinfo @@ -0,0 +1,2 @@ +uqm_CFILES="npconfirm.c ready.c reset.c" +uqm_HFILES="npconfirm.h ready.h reset.h" diff --git a/src/uqm/supermelee/netplay/proto/npconfirm.c b/src/uqm/supermelee/netplay/proto/npconfirm.c new file mode 100644 index 0000000..6929219 --- /dev/null +++ b/src/uqm/supermelee/netplay/proto/npconfirm.c @@ -0,0 +1,81 @@ +/* + * Copyright 2006 Serge van den Boom <svdb@stack.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define NETCONNECTION_INTERNAL +#include "../netplay.h" +#include "npconfirm.h" + +#include "types.h" +#include "../netmisc.h" +#include "../packetsenders.h" + +#include <assert.h> +#include <errno.h> + +int +Netplay_confirm(NetConnection *conn) { + assert(handshakeMeaningful(NetConnection_getState(conn))); + + if (conn->stateFlags.handshake.localOk) { + // Already confirmed + errno = EINVAL; + return -1; + } + + conn->stateFlags.handshake.localOk = true; + + if (conn->stateFlags.handshake.canceling) { + // If a previous confirmation was cancelled, but the cancel + // is not acknowledged yet, we don't have to send anything yet. + // The handshake0 packet will be sent when the acknowledgement + // arrives. + } else if (conn->stateFlags.handshake.remoteOk) { + // A Handshake0 is implied by the following Handshake1. + sendHandshake1(conn); + } else { + sendHandshake0(conn); + } + + return 0; +} + +int +Netplay_cancelConfirmation(NetConnection *conn) { + assert(handshakeMeaningful(NetConnection_getState(conn))); + + if (!conn->stateFlags.handshake.localOk) { + // Not confirmed, or already canceling. + errno = EINVAL; + return -1; + } + + conn->stateFlags.handshake.localOk = false; + if (conn->stateFlags.handshake.canceling) { + // If previous cancellation is still waiting to be acknowledged, + // the confirmation we are cancelling here, has not actually been + // sent yet. By setting the localOk flag to false, it is + // cancelled, without the need for any packets to be sent. + } else { + conn->stateFlags.handshake.canceling = true; + sendHandshakeCancel(conn); + } + + return 0; +} + + diff --git a/src/uqm/supermelee/netplay/proto/npconfirm.h b/src/uqm/supermelee/netplay/proto/npconfirm.h new file mode 100644 index 0000000..1ae58f5 --- /dev/null +++ b/src/uqm/supermelee/netplay/proto/npconfirm.h @@ -0,0 +1,36 @@ +/* + * Copyright 2006 Serge van den Boom <svdb@stack.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UQM_SUPERMELEE_NETPLAY_PROTO_NPCONFIRM_H_ +#define UQM_SUPERMELEE_NETPLAY_PROTO_NPCONFIRM_H_ + +#include "../netplay.h" +#include "../netconnection.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +int Netplay_confirm(NetConnection *conn); +int Netplay_cancelConfirmation(NetConnection *conn); + +#if defined(__cplusplus) +} +#endif + +#endif /* UQM_SUPERMELEE_NETPLAY_PROTO_NPCONFIRM_H_ */ diff --git a/src/uqm/supermelee/netplay/proto/ready.c b/src/uqm/supermelee/netplay/proto/ready.c new file mode 100644 index 0000000..e9f8c58 --- /dev/null +++ b/src/uqm/supermelee/netplay/proto/ready.c @@ -0,0 +1,106 @@ +/* + * Copyright 2006 Serge van den Boom <svdb@stack.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define NETCONNECTION_INTERNAL +#include "../netplay.h" +#include "ready.h" + +#include "types.h" +#include "../netmisc.h" +#include "../packetsenders.h" + +#include <assert.h> + +static void +Netplay_bothReady(NetConnection *conn) { + NetConnection_ReadyCallback callback; + void *readyArg; + + assert(conn->readyCallback != NULL); + + callback = conn->readyCallback; + readyArg = conn->readyCallbackArg; + + NetConnection_setReadyCallback(conn, NULL, NULL); + // Clear the readyCallback field before performing the callback, + // so that it can be set again from inside the callback + // function. + + callback(conn, readyArg); +} + +// If notifyRemote is set, a 'Ready' message will be sent to the other side. +// returns true iff both sides are ready. +// Inside the callback function, ready flags may be set for a possible +// next Ready communication. +bool +Netplay_localReady(NetConnection *conn, NetConnection_ReadyCallback callback, + void *readyArg, bool notifyRemote) { + assert(readyFlagsMeaningful(NetConnection_getState(conn))); + assert(!conn->stateFlags.ready.localReady); + assert(callback != NULL); + + NetConnection_setReadyCallback(conn, callback, readyArg); + + if (notifyRemote) + sendReady(conn); + if (!conn->stateFlags.ready.remoteReady) { + conn->stateFlags.ready.localReady = true; + return false; + } + + // Reset ready flags: + conn->stateFlags.ready.remoteReady = false; + + // Trigger the callback. + Netplay_bothReady(conn); + return true; +} + +// returns true iff both sides are ready. +bool +Netplay_remoteReady(NetConnection *conn) { + assert(readyFlagsMeaningful(NetConnection_getState(conn))); + // This is supposed to be already verified by the calling + // function. + assert(!conn->stateFlags.ready.remoteReady); + + if (!conn->stateFlags.ready.localReady) { + conn->stateFlags.ready.remoteReady = true; + return false; + } + + // Reset ready flags: + conn->stateFlags.ready.localReady = false; + + // Trigger the callback. + Netplay_bothReady(conn); + return true; +} + +bool +Netplay_isLocalReady(const NetConnection *conn) { + return conn->stateFlags.ready.localReady; +} + +bool +Netplay_isRemoteReady(const NetConnection *conn) { + return conn->stateFlags.ready.remoteReady; +} + + diff --git a/src/uqm/supermelee/netplay/proto/ready.h b/src/uqm/supermelee/netplay/proto/ready.h new file mode 100644 index 0000000..3521557 --- /dev/null +++ b/src/uqm/supermelee/netplay/proto/ready.h @@ -0,0 +1,38 @@ +/* + * Copyright 2006 Serge van den Boom <svdb@stack.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UQM_SUPERMELEE_NETPLAY_PROTO_READY_H_ +#define UQM_SUPERMELEE_NETPLAY_PROTO_READY_H_ + +#include "../netconnection.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +bool Netplay_localReady(NetConnection *conn, + NetConnection_ReadyCallback callback, void *arg, bool notifyRemote); +bool Netplay_remoteReady(NetConnection *conn); +bool Netplay_isLocalReady(const NetConnection *conn); +bool Netplay_isRemoteReady(const NetConnection *conn); + +#if defined(__cplusplus) +} +#endif + +#endif /* UQM_SUPERMELEE_NETPLAY_PROTO_READY_H_ */ diff --git a/src/uqm/supermelee/netplay/proto/reset.c b/src/uqm/supermelee/netplay/proto/reset.c new file mode 100644 index 0000000..82483b1 --- /dev/null +++ b/src/uqm/supermelee/netplay/proto/reset.c @@ -0,0 +1,166 @@ +/* + * Copyright 2006 Serge van den Boom <svdb@stack.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// See doc/devel/netplay/protocol + +#define NETCONNECTION_INTERNAL +#include "../netplay.h" +#include "reset.h" + +#include "types.h" +#include "../packetsenders.h" +#include "../../melee.h" + // For resetFeedback. + +#include <assert.h> + +// Reset packets are sent to indicate that a game is to be reset. +// i.e. the game is to return to the SuperMelee fleet setup menu. +// The reset will occur when a reset packet has both been sent and +// received. When a reset packet is received and the local side had not +// sent a reset packet itself, the local side will confirm the reset. +// When both sides initiate a reset simultaneously, the reset packets +// of each side will act as a confirmation for the other side. +// +// When a reset packet has been sent, no further gameplay packets should be +// sent until the game has been reset. Non-gameplay packets such as 'ping' +// are allowed. +// When a reset packet has been received, all further incoming gameplay +// packets are ignored until the game has been reset. +// +// conn->stateFlags.reset.localReset is set when a reset packet is sent. +// conn->stateFlags.reset.remoteReset is set when a reset packet is +// received. +// +// When either localReset or remoteReset gets set and the other flag isn't +// set, Netplay_connectionReset() gets called. +// +// As soon as the following three conditions are met, the reset callback is +// called and the localReset and remoteReset flags are cleared. +// - conn->stateFlags.reset.localReset is set +// - conn->stateFlags.reset.remoteReset is set +// - the reset callback is non-NULL. +// +// Elsewhere in the UQM source: +// When the local side causes a reset, it calls Netplay_localReset(). +// When a remote reset packet is received, Netplay_remoteReset() is called +// (which will sent a reset packet back as confirmation, as required). +// At the end of melee, the reset callback is set (for each connection), +// and the game will wait until the reset callback for each connection has +// been called (when the forementioned conditions have become true) +// (or until the connection is terminated). + + +// This function is called when one side initiates a reset. +static void +Netplay_connectionReset(NetConnection *conn, NetplayResetReason reason, + bool byRemote) { + switch (NetConnection_getState(conn)) { + case NetState_unconnected: + case NetState_connecting: + case NetState_init: + case NetState_inSetup: + break; + case NetState_preBattle: + case NetState_interBattle: + case NetState_selectShip: + case NetState_inBattle: + case NetState_endingBattle: + case NetState_endingBattle2: + resetFeedback(conn, reason, byRemote); + break; + } +} + +static void +Netplay_doConnectionResetCallback(NetConnection *conn) { + NetConnection_ResetCallback callback; + void *resetArg; + + callback = conn->resetCallback; + resetArg = conn->resetCallbackArg; + + NetConnection_setResetCallback(conn, NULL, NULL); + // Clear the resetCallback field before performing the callback, + // so that it can be set again from inside the callback + // function. + callback(conn, resetArg); +} + +static void +Netplay_resetConditionTriggered(NetConnection *conn) { + if (conn->resetCallback == NULL) + return; + + if (!conn->stateFlags.reset.localReset || + !conn->stateFlags.reset.remoteReset) + return; + + conn->stateFlags.reset.localReset = false; + conn->stateFlags.reset.remoteReset = false; + + Netplay_doConnectionResetCallback(conn); +} + +void +Netplay_setResetCallback(NetConnection *conn, + NetConnection_ResetCallback callback, void *resetArg) { + NetConnection_setResetCallback(conn, callback, resetArg); + + Netplay_resetConditionTriggered(conn); +} + +void +Netplay_localReset(NetConnection *conn, NetplayResetReason reason) { + assert(!conn->stateFlags.reset.localReset); + + conn->stateFlags.reset.localReset = true; + if (conn->stateFlags.reset.remoteReset) { + // Both sides have initiated/confirmed the reset. + Netplay_resetConditionTriggered(conn); + } else { + sendReset(conn, reason); + Netplay_connectionReset(conn, reason, false); + } +} + +void +Netplay_remoteReset(NetConnection *conn, NetplayResetReason reason) { + assert(!conn->stateFlags.reset.remoteReset); + // Should already be checked when the packet arrives. + + conn->stateFlags.reset.remoteReset = true; + if (!conn->stateFlags.reset.localReset) { + sendReset(conn, reason); + conn->stateFlags.reset.localReset = true; + Netplay_connectionReset(conn, reason, true); + } + + Netplay_resetConditionTriggered(conn); +} + +bool +Netplay_isLocalReset(const NetConnection *conn) { + return conn->stateFlags.reset.localReset; +} + +bool +Netplay_isRemoteReset(const NetConnection *conn) { + return conn->stateFlags.reset.remoteReset; +} + diff --git a/src/uqm/supermelee/netplay/proto/reset.h b/src/uqm/supermelee/netplay/proto/reset.h new file mode 100644 index 0000000..e16b1d1 --- /dev/null +++ b/src/uqm/supermelee/netplay/proto/reset.h @@ -0,0 +1,41 @@ +/* + * Copyright 2006 Serge van den Boom <svdb@stack.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UQM_SUPERMELEE_NETPLAY_PROTO_RESET_H_ +#define UQM_SUPERMELEE_NETPLAY_PROTO_RESET_H_ + +#include "../netconnection.h" +#include "../packet.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +void Netplay_setResetCallback(NetConnection *conn, + NetConnection_ResetCallback callback, void *resetArg); +void Netplay_localReset(NetConnection *conn, NetplayResetReason reason); +void Netplay_remoteReset(NetConnection *conn, NetplayResetReason reason); +bool Netplay_isLocalReset(const NetConnection *conn); +bool Netplay_isRemoteReset(const NetConnection *conn); + +#if defined(__cplusplus) +} +#endif + +#endif /* UQM_SUPERMELEE_NETPLAY_PROTO_RESET_H_ */ + |