mirror of
https://github.com/Oibaf66/frodo-wii.git
synced 2024-11-13 07:05:12 +01:00
Add versioning to the peer list
This commit is contained in:
parent
94cb9bb1df
commit
5ab6b38e6c
119
Src/Network.cpp
119
Src/Network.cpp
@ -86,6 +86,7 @@ Network::Network(const char *remote_host, int port, bool is_master)
|
||||
exit(1);
|
||||
}
|
||||
this->network_connection_state = CONN_CONNECT_TO_BROKER;
|
||||
this->connection_error_message = "Connection OK";
|
||||
}
|
||||
|
||||
Network::~Network()
|
||||
@ -543,8 +544,10 @@ bool Network::ReceiveUpdate(NetworkUpdate *dst, size_t total_sz,
|
||||
return false;
|
||||
|
||||
if (this->DeMarshalAllData((NetworkUpdate*)p, actual_sz,
|
||||
&has_stop) == false)
|
||||
&has_stop) == false) {
|
||||
printf("Demarshal error\n");
|
||||
return false;
|
||||
}
|
||||
sz_left -= actual_sz;
|
||||
p = p + actual_sz;
|
||||
} while (!has_stop);
|
||||
@ -659,6 +662,7 @@ bool Network::MarshalData(NetworkUpdate *p)
|
||||
peer->public_port = htons(peer->public_port);
|
||||
peer->is_master = htons(peer->is_master);
|
||||
peer->server_id = htonl(peer->server_id);
|
||||
peer->version = htonl(peer->version);
|
||||
}
|
||||
lp->n_peers = htonl(lp->n_peers);
|
||||
lp->your_port = htons(lp->your_port);
|
||||
@ -670,6 +674,7 @@ bool Network::MarshalData(NetworkUpdate *p)
|
||||
/* The rest is simply ignored */
|
||||
pi->is_master = htons(pi->is_master);
|
||||
pi->key = htons(pi->key);
|
||||
pi->version = htonl(pi->version);
|
||||
} break;
|
||||
default:
|
||||
/* Unknown data... */
|
||||
@ -750,6 +755,7 @@ bool Network::DeMarshalData(NetworkUpdate *p)
|
||||
peer->public_port = ntohs(peer->public_port);
|
||||
peer->is_master = ntohs(peer->is_master);
|
||||
peer->server_id = ntohl(peer->server_id);
|
||||
peer->version = ntohl(peer->version);
|
||||
}
|
||||
lp->your_port = ntohs(lp->your_port);
|
||||
} break;
|
||||
@ -838,6 +844,7 @@ bool Network::ConnectToBroker()
|
||||
|
||||
pi->is_master = this->is_master;
|
||||
pi->key = ThePrefs.NetworkKey;
|
||||
pi->version = FRODO_NETWORK_PROTOCOL_VERSION;
|
||||
strcpy((char*)pi->name, ThePrefs.NetworkName);
|
||||
this->AddNetworkUpdate(ud);
|
||||
out = this->SendUpdate();
|
||||
@ -882,7 +889,7 @@ void Network::SendPingAck(int seq)
|
||||
this->ResetNetworkUpdate();
|
||||
}
|
||||
|
||||
bool Network::WaitForPeerAddress()
|
||||
network_connection_error_t Network::WaitForPeerAddress()
|
||||
{
|
||||
NetworkUpdateListPeers *pi;
|
||||
struct timeval tv;
|
||||
@ -892,16 +899,16 @@ bool Network::WaitForPeerAddress()
|
||||
|
||||
this->ResetNetworkUpdate();
|
||||
if (this->ReceiveUpdate(&tv) == false)
|
||||
return false;
|
||||
return AGAIN_ERROR;
|
||||
if (this->ud->type == PING)
|
||||
{
|
||||
NetworkUpdatePingAck *p = (NetworkUpdatePingAck*)ud->data;
|
||||
/* Send ack and go back to this state again */
|
||||
this->SendPingAck(p->seq);
|
||||
return false;
|
||||
return AGAIN_ERROR;
|
||||
}
|
||||
if (this->ud->type != LIST_PEERS)
|
||||
return false;
|
||||
return SERVER_GARBAGE_ERROR;
|
||||
|
||||
pi = (NetworkUpdateListPeers *)this->ud->data;
|
||||
if (pi->n_peers != 1)
|
||||
@ -909,8 +916,10 @@ bool Network::WaitForPeerAddress()
|
||||
fprintf(stderr, "There is something wrong with the server: Got %d peers on master connect\n"
|
||||
"Contact Simon Kagstrom and ask him to correct it\n",
|
||||
pi->n_peers);
|
||||
return false;
|
||||
return SERVER_GARBAGE_ERROR;
|
||||
}
|
||||
if (pi->peers[0].version != FRODO_NETWORK_PROTOCOL_VERSION)
|
||||
return VERSION_ERROR;
|
||||
|
||||
/* Setup the peer info */
|
||||
char buf[128];
|
||||
@ -918,9 +927,13 @@ bool Network::WaitForPeerAddress()
|
||||
/* Not sure what to do if this fails */
|
||||
this->IpToStr(buf, pi->peers[0].public_ip);
|
||||
printf("Converted ip to %s:%d\n", buf, pi->peers[0].public_port);
|
||||
return this->InitSockaddr(&this->connection_addr, buf,
|
||||
pi->peers[0].public_port);
|
||||
|
||||
if (this->InitSockaddr(&this->connection_addr, buf,
|
||||
pi->peers[0].public_port) == false)
|
||||
{
|
||||
printf("Init sockaddr error\n");
|
||||
return SERVER_GARBAGE_ERROR;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool Network::SelectPeer(uint32 id)
|
||||
@ -938,7 +951,7 @@ bool Network::SelectPeer(uint32 id)
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Network::WaitForPeerList()
|
||||
network_connection_error_t Network::WaitForPeerList()
|
||||
{
|
||||
NetworkUpdateListPeers *pi;
|
||||
struct timeval tv;
|
||||
@ -949,41 +962,47 @@ bool Network::WaitForPeerList()
|
||||
|
||||
this->ResetNetworkUpdate();
|
||||
if (this->ReceiveUpdate(&tv) == false)
|
||||
return false;
|
||||
return AGAIN_ERROR;
|
||||
if (this->ud->type == PING)
|
||||
{
|
||||
NetworkUpdatePingAck *p = (NetworkUpdatePingAck*)ud->data;
|
||||
/* Send ack and go back to this state again */
|
||||
this->SendPingAck(p->seq);
|
||||
return false;
|
||||
return AGAIN_ERROR;
|
||||
}
|
||||
if (ud->type != LIST_PEERS)
|
||||
return false;
|
||||
return SERVER_GARBAGE_ERROR;
|
||||
|
||||
pi = (NetworkUpdateListPeers *)this->ud->data;
|
||||
msgs = (const char**)calloc(pi->n_peers + 1, sizeof(const char*));
|
||||
|
||||
for (int i = 0; i < pi->n_peers; i++) {
|
||||
msgs[i] = (const char*)pi->peers[i].name;
|
||||
if (pi->peers[i].version != FRODO_NETWORK_PROTOCOL_VERSION)
|
||||
{
|
||||
free(msgs);
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
}
|
||||
int sel = menu_select(msgs, NULL);
|
||||
free(msgs);
|
||||
|
||||
/* FIXME! What to do here??? */
|
||||
if (sel < 0)
|
||||
return false;
|
||||
return SERVER_GARBAGE_ERROR;
|
||||
/* Setup the peer info */
|
||||
char buf[128];
|
||||
uint16 port = pi->peers[sel].public_port;
|
||||
|
||||
/* Not sure what to do if this fails */
|
||||
this->IpToStr(buf, pi->peers[sel].public_ip);
|
||||
printf("Converted ip to %s:%d\n", buf, port);
|
||||
|
||||
/* Finally tell the broker who we selected */
|
||||
this->SelectPeer(pi->peers[sel].server_id);
|
||||
return this->InitSockaddr(&this->connection_addr, buf,
|
||||
port);
|
||||
if (this->InitSockaddr(&this->connection_addr, buf,
|
||||
port) == false)
|
||||
return SERVER_GARBAGE_ERROR;
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool Network::WaitForPeerReply()
|
||||
@ -1016,8 +1035,10 @@ bool Network::ConnectToPeer()
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Network::ConnectFSM()
|
||||
network_connection_error_t Network::ConnectFSM()
|
||||
{
|
||||
network_connection_error_t err;
|
||||
|
||||
/* See http://www.brynosaurus.com/pub/net/p2pnat/ for how this works.
|
||||
*
|
||||
* For the server ("master"):
|
||||
@ -1050,20 +1071,23 @@ bool Network::ConnectFSM()
|
||||
}
|
||||
break;
|
||||
case CONN_WAIT_FOR_PEER_ADDRESS:
|
||||
if (this->WaitForPeerAddress() == false)
|
||||
return false;
|
||||
this->network_connection_state = CONN_CONNECT_TO_PEER;
|
||||
err = this->WaitForPeerAddress();
|
||||
if (err == OK)
|
||||
this->network_connection_state = CONN_CONNECT_TO_PEER;
|
||||
else
|
||||
return err;
|
||||
break;
|
||||
case CONN_WAIT_FOR_PEER_LIST:
|
||||
/* Also tells the broker that we want to connect */
|
||||
if (this->WaitForPeerList() == false)
|
||||
return false;
|
||||
this->network_connection_state = CONN_CONNECT_TO_PEER;
|
||||
err = this->WaitForPeerList();
|
||||
if (err == OK)
|
||||
this->network_connection_state = CONN_CONNECT_TO_PEER;
|
||||
else
|
||||
return err;
|
||||
break;
|
||||
case CONN_CONNECT_TO_PEER:
|
||||
printf("Connecting to peer\n");
|
||||
if (this->ConnectToPeer() == false)
|
||||
return false;
|
||||
return AGAIN_ERROR;
|
||||
/* Allow some transit time */
|
||||
sleep(1);
|
||||
this->network_connection_state = CONN_WAIT_FOR_PEER_REPLY;
|
||||
@ -1071,21 +1095,19 @@ bool Network::ConnectFSM()
|
||||
case CONN_WAIT_FOR_PEER_REPLY:
|
||||
/* Connect again in case the first sent was dropped on
|
||||
* its way to the peer */
|
||||
printf("Connecting to peer again\n");
|
||||
if (this->ConnectToPeer() == false)
|
||||
return false;
|
||||
printf("Waiting for peer reply\n");
|
||||
if (this->WaitForPeerReply() == false)
|
||||
return false;
|
||||
printf("Got peer reply\n");
|
||||
this->network_connection_state = CONN_CONNECTED;
|
||||
return AGAIN_ERROR;
|
||||
if (this->WaitForPeerReply() == true)
|
||||
this->network_connection_state = CONN_CONNECTED;
|
||||
else
|
||||
return AGAIN_ERROR;
|
||||
break;
|
||||
case CONN_CONNECTED:
|
||||
default:
|
||||
return true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
return true;;
|
||||
return AGAIN_ERROR;
|
||||
}
|
||||
|
||||
bool Network::Connect()
|
||||
@ -1117,10 +1139,31 @@ bool Network::Connect()
|
||||
if (SDL_GetKeyState(NULL)[SDLK_ESCAPE])
|
||||
return false;
|
||||
|
||||
if (this->network_connection_state == CONN_CONNECTED)
|
||||
return true;
|
||||
/* Run the state machine */
|
||||
this->ConnectFSM();
|
||||
switch (this->ConnectFSM())
|
||||
{
|
||||
case OK:
|
||||
return true;
|
||||
case AGAIN_ERROR:
|
||||
break;
|
||||
case VERSION_ERROR:
|
||||
menu_print_font(real_screen, 255,255,0, 30, 70,
|
||||
"Your frodo is too old.");
|
||||
menu_print_font(real_screen, 255,255,0, 30, 90,
|
||||
"See http://frodo-wii.googlecode.com");
|
||||
sleep(1);
|
||||
return false;
|
||||
case SERVER_GARBAGE_ERROR:
|
||||
menu_print_font(real_screen, 255,255,0, 30, 70,
|
||||
"Network error");
|
||||
sleep(1);
|
||||
return false;
|
||||
default:
|
||||
menu_print_font(real_screen, 255,255,0, 30, 70,
|
||||
"Unknown network error");
|
||||
sleep(1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -8,6 +8,8 @@
|
||||
#endif
|
||||
#include <SDL.h>
|
||||
|
||||
#define FRODO_NETWORK_PROTOCOL_VERSION 2
|
||||
|
||||
#define FRODO_NETWORK_MAGIC 0x1976
|
||||
|
||||
#define NETWORK_UPDATE_SIZE (256 * 1024)
|
||||
@ -46,8 +48,18 @@ typedef enum
|
||||
|
||||
/* Client-only */
|
||||
CONN_WAIT_FOR_PEER_LIST,
|
||||
|
||||
FAILED,
|
||||
} network_connection_state_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OK = 0,
|
||||
AGAIN_ERROR,
|
||||
VERSION_ERROR,
|
||||
SERVER_GARBAGE_ERROR,
|
||||
} network_connection_error_t;
|
||||
|
||||
struct NetworkUpdate
|
||||
{
|
||||
uint16 magic; /* Should be 0x1976 */
|
||||
@ -69,7 +81,6 @@ struct NetworkUpdateJoystick
|
||||
uint8 val;
|
||||
};
|
||||
|
||||
|
||||
struct NetworkUpdateSelectPeer
|
||||
{
|
||||
uint32 server_id;
|
||||
@ -101,6 +112,7 @@ struct NetworkUpdatePeerInfo
|
||||
uint16 is_master;
|
||||
uint8 name[32]; /* "SIMON", "LINDA" etc */
|
||||
uint32 server_id; /* Used by the server */
|
||||
uint32 version; /* Version number */
|
||||
};
|
||||
|
||||
struct NetworkUpdateListPeers
|
||||
@ -176,6 +188,8 @@ public:
|
||||
|
||||
bool Connect();
|
||||
|
||||
network_connection_error_t ConnectFSM();
|
||||
|
||||
/**
|
||||
* Disconnect from the other end. You should delete the object
|
||||
* after having done this.
|
||||
@ -292,14 +306,12 @@ protected:
|
||||
|
||||
bool WaitForPeerReply();
|
||||
|
||||
bool WaitForPeerList();
|
||||
network_connection_error_t WaitForPeerList();
|
||||
|
||||
bool WaitForPeerAddress();
|
||||
network_connection_error_t WaitForPeerAddress();
|
||||
|
||||
bool SelectPeer(uint32 id);
|
||||
|
||||
bool ConnectFSM();
|
||||
|
||||
size_t FillNetworkBuffer(NetworkUpdate *p);
|
||||
|
||||
NetworkUpdate *GetNext(NetworkUpdate *p)
|
||||
@ -334,6 +346,8 @@ protected:
|
||||
int sock;
|
||||
struct sockaddr_in connection_addr;
|
||||
|
||||
const char *connection_error_message;
|
||||
|
||||
network_connection_state_t network_connection_state;
|
||||
|
||||
/* Sound */
|
||||
|
@ -3,6 +3,7 @@
|
||||
import socket, struct, syslog, time, thread, ip2country, sys
|
||||
import SocketServer, stats
|
||||
|
||||
FRODO_NETWORK_PROTOCOL_VERSION = 2
|
||||
FRODO_NETWORK_MAGIC = 0x1976
|
||||
|
||||
CONNECT_TO_BROKER = 99 # Hello, broker
|
||||
@ -132,6 +133,7 @@ class ConnectToBrokerPacket(Packet):
|
||||
self._is_master = struct.unpack(">H", data[46:48])[0]
|
||||
self.name = struct.unpack("32s", data[48:48+32])[0]
|
||||
self.server_id = struct.unpack(">L", data[80:84])[0]
|
||||
self.version = struct.unpack(">L", data[84:88])[0]
|
||||
|
||||
self.name = self.name[0:self.name.find('\0')]
|
||||
|
||||
@ -155,17 +157,18 @@ class ListPeersPacket(Packet):
|
||||
def add_peer(self, peer):
|
||||
self.peers.append(peer)
|
||||
self.n_peers = self.n_peers + 1
|
||||
self.size = self.size + 76
|
||||
self.size = self.size + 80
|
||||
|
||||
def marshal(self):
|
||||
out = struct.pack(">L16sHxx", self.n_peers, "", 0)
|
||||
|
||||
for peer in self.peers:
|
||||
out = out + struct.pack(">HH16s16sHH31sBL",
|
||||
# Force the version - we don't allow old stuff
|
||||
out = out + struct.pack(">HH16s16sHH31sBLL",
|
||||
0, peer.public_port, "",
|
||||
peer.public_ip, peer.key,
|
||||
peer.is_master, "%s (%s)" % (peer.name, peer.country),
|
||||
0, peer.id)
|
||||
0, peer.id, FRODO_NETWORK_PROTOCOL_VERSION)
|
||||
|
||||
return Packet.marshal(self) + out
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user