mirror of
https://github.com/Oibaf66/frodo-wii.git
synced 2024-11-14 07:35:12 +01:00
Implemented broker communication (untested, might not compile)
This commit is contained in:
parent
debf526c38
commit
b2ca587041
242
Src/Network.cpp
242
Src/Network.cpp
@ -21,6 +21,7 @@
|
||||
#include "sysdeps.h"
|
||||
#include "Network.h"
|
||||
#include "Display.h"
|
||||
#include "menu.h"
|
||||
|
||||
#define N_SQUARES_W 16
|
||||
#define N_SQUARES_H 8
|
||||
@ -75,6 +76,7 @@ Network::Network(const char *remote_host, int port, bool is_master)
|
||||
fprintf(stderr, "Could not init the socket\n");
|
||||
exit(1);
|
||||
}
|
||||
this->network_connection_state = CONNECT_TO_BROKER;
|
||||
}
|
||||
|
||||
Network::~Network()
|
||||
@ -565,14 +567,6 @@ void Network::AddNetworkUpdate(NetworkUpdate *update)
|
||||
this->cur_ud = (NetworkUpdate*)next;
|
||||
}
|
||||
|
||||
void Network::MangleIp(uint8 *ip)
|
||||
{
|
||||
ip[0] = ~ip[0];
|
||||
ip[1] = ~ip[1];
|
||||
ip[2] = ~ip[2];
|
||||
ip[3] = ~ip[3];
|
||||
}
|
||||
|
||||
bool Network::MarshalData(NetworkUpdate *p)
|
||||
{
|
||||
switch (p->type)
|
||||
@ -598,11 +592,8 @@ bool Network::MarshalData(NetworkUpdate *p)
|
||||
peer->private_port = htons(peer->private_port);
|
||||
peer->public_port = htons(peer->public_port);
|
||||
peer->is_master = htons(peer->is_master);
|
||||
this->MangleIp(peer->private_ip);
|
||||
this->MangleIp(peer->public_ip);
|
||||
}
|
||||
lp->n_peers = htonl(lp->n_peers);
|
||||
this->MangleIp(lp->your_ip);
|
||||
lp->your_port = htons(lp->your_port);
|
||||
} break;
|
||||
default:
|
||||
@ -671,10 +662,7 @@ bool Network::DeMarshalData(NetworkUpdate *p)
|
||||
peer->private_port = ntohs(peer->private_port);
|
||||
peer->public_port = ntohs(peer->public_port);
|
||||
peer->is_master = ntohs(peer->is_master);
|
||||
this->MangleIp(peer->private_ip);
|
||||
this->MangleIp(peer->public_ip);
|
||||
}
|
||||
this->MangleIp(lp->your_ip);
|
||||
lp->your_port = ntohs(lp->your_port);
|
||||
} break;
|
||||
default:
|
||||
@ -747,44 +735,220 @@ bool Network::DecodeUpdate(uint8 *screen, uint8 *js)
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Network::WaitForConnection()
|
||||
bool Network::ConnectToBroker()
|
||||
{
|
||||
NetworkUpdate *ud = InitNetworkUpdate(this->ud, CONNECT_TO_BROKER,
|
||||
sizeof(NetworkUpdate) + sizeof(NetworkUpdatePeerInfo));
|
||||
NetworkUpdatePeerInfo *pi = (NetworkUpdatePeerInfo *)ud->data;
|
||||
bool out;
|
||||
|
||||
pi->is_master = this->is_master;
|
||||
pi->key = 5;
|
||||
this->AddNetworkUpdate(ud);
|
||||
out = this->SendUpdate();
|
||||
this->ResetNetworkUpdate();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Network::IpToStr(char *dst, uint8 *ip_in)
|
||||
{
|
||||
int ip[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
char tmp[3];
|
||||
const char *endp;
|
||||
|
||||
tmp[0] = ip_in[i * 2];
|
||||
tmp[1] = ip_in[i * 2 + 1];
|
||||
tmp[2] = '\0';
|
||||
ip[i] = strtoul(tmp, &endp, 16);
|
||||
if (endp == tmp)
|
||||
return false;
|
||||
}
|
||||
sprintf(dst, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Network::WaitForPeerAddress()
|
||||
{
|
||||
NetworkUpdateListPeers *pi;
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
/* See http://www.brynosaurus.com/pub/net/p2pnat/ for how this works.
|
||||
* To do here:
|
||||
*
|
||||
* 1. Send connect to the broker
|
||||
* 2. Wait for broker to return the peer connection info (private
|
||||
* and public address)
|
||||
* 3. Until connected:
|
||||
* 3.1 Send connection message to peer
|
||||
* 3.2 Wait for reply from peer
|
||||
*/
|
||||
if (this->ReceiveUpdate(&tv) == true)
|
||||
return true;
|
||||
this->ResetNetworkUpdate();
|
||||
if (this->ReceiveUpdate(&tv) == false)
|
||||
return false;
|
||||
if (ud->type != PEER_LIST)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
pi = (NetworkUpdateListPeers *)this->ud->data;
|
||||
if (pi->n_peers != 1)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* Setup the peer info */
|
||||
char buf[128];
|
||||
|
||||
/* Not sure what to do if this fails */
|
||||
this->IpToStr(buf, pi->peers[0].public_ip);
|
||||
return this->InitSockaddr(this->connection_addr, buf,
|
||||
pi->peers[0].public_port);
|
||||
|
||||
}
|
||||
|
||||
bool Network::WaitForPeerList()
|
||||
{
|
||||
NetworkUpdateListPeers *pi;
|
||||
struct timeval tv;
|
||||
const char **msgs;
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
this->ResetNetworkUpdate();
|
||||
if (this->ReceiveUpdate(&tv) == false)
|
||||
return false;
|
||||
if (ud->type != PEER_LIST)
|
||||
return false;
|
||||
|
||||
pi = (NetworkUpdateListPeers *)this->ud->data;
|
||||
msgs = (const char**)calloc(pi->n_peers + 1, sizeof(const char*));
|
||||
|
||||
for (int i = 0; pi->n_peers; i++) {
|
||||
msgs[i] = pi->peers[i].name;
|
||||
}
|
||||
int sel = menu_select(msgs, NULL);
|
||||
free(msgs);
|
||||
|
||||
/* FIXME! What to do here??? */
|
||||
if (sel < 0)
|
||||
return false;
|
||||
/* Setup the peer info */
|
||||
char buf[128];
|
||||
|
||||
/* Not sure what to do if this fails */
|
||||
this->IpToStr(buf, pi->peers[sel].public_ip);
|
||||
return this->InitSockaddr(this->connection_addr, buf,
|
||||
pi->peers[sel].public_port);
|
||||
|
||||
}
|
||||
|
||||
bool Network::WaitForPeerReply()
|
||||
{
|
||||
struct timeval tv;
|
||||
const char **msgs;
|
||||
|
||||
tv.tv_sec = 3;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
this->ResetNetworkUpdate();
|
||||
if (this->ReceiveUpdate(&tv) == false)
|
||||
return false;
|
||||
|
||||
if (this->ud->type != CONNECT_TO_PEER)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Network::ConnectToPeer()
|
||||
{
|
||||
/*
|
||||
* To do here:
|
||||
NetworkUpdate *ud = InitNetworkUpdate(this->ud, CONNECT_TO_PEER,
|
||||
sizeof(NetworkUpdate));
|
||||
|
||||
this->AddNetworkUpdate(ud);
|
||||
out = this->SendUpdate();
|
||||
this->ResetNetworkUpdate();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Network::ConnectFSM()
|
||||
{
|
||||
/* See http://www.brynosaurus.com/pub/net/p2pnat/ for how this works.
|
||||
*
|
||||
* 1. Send connect to the broker
|
||||
* 2. Wait for the broker to return list of peers
|
||||
* 3. Tell the broker who to connect to
|
||||
* 4. Wait for broker to return the peer connection info (private
|
||||
* and public address)
|
||||
* 5. Until connected:
|
||||
* 5.1 Send connection message to peer
|
||||
* 5.2 Wait for reply from peer
|
||||
* For the server ("master"):
|
||||
* 1. Send connect to the broker
|
||||
* 2. Wait for broker to return the peer connection info (private
|
||||
* and public address)
|
||||
* 3. Until connected:
|
||||
* 3.1 Send connection message to peer
|
||||
* 3.2 Wait for reply from peer
|
||||
*
|
||||
* For the client:
|
||||
* 1. Send connect to the broker
|
||||
* 2. Wait for the broker to return list of peers
|
||||
* 3. Tell the broker who to connect to
|
||||
* 4. Wait for broker to return the peer connection info (private
|
||||
* and public address)
|
||||
* 5. Until connected:
|
||||
* 5.1 Send connection message to peer
|
||||
* 5.2 Wait for reply from peer
|
||||
*/
|
||||
return this->SendUpdate();
|
||||
switch(this->network_connection_state)
|
||||
{
|
||||
case CONNECT_TO_BROKER:
|
||||
if (this->ConnectToBroker() == true)
|
||||
{
|
||||
if (this->is_master)
|
||||
this->network_connection_state = WAIT_FOR_PEER_ADDRESS;
|
||||
else
|
||||
this->network_connection_state = WAIT_FOR_PEER_LIST;
|
||||
}
|
||||
break;
|
||||
case WAIT_FOR_PEER_ADDRESS:
|
||||
if (this->WaitForPeerAddress() == false)
|
||||
return false;
|
||||
this->network_connection_state = CONNECT_TO_PEER;
|
||||
break;
|
||||
case WAIT_FOR_PEER_LIST:
|
||||
if (this->WaitForPeerList() == false)
|
||||
return false;
|
||||
this->network_connection_state = CONNECT_TO_PEER;
|
||||
break;
|
||||
case CONNECT_TO_PEER:
|
||||
if (this->ConnectToPeer() == false)
|
||||
return false;
|
||||
/* Allow some transit time */
|
||||
sleep(1);
|
||||
this->network_connection_state = WAIT_FOR_PEER_REPLY;
|
||||
break;
|
||||
case WAIT_FOR_PEER_REPLY:
|
||||
/* Connect again in case the first sent was dropped on
|
||||
* its way to the peer */
|
||||
if (this->ConnectToPeer() == false)
|
||||
return false;
|
||||
if (this->WaitForPeerReply() == false)
|
||||
return false;
|
||||
this->network_connection_state = CONNECTED;
|
||||
break;
|
||||
case CONNECTED:
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;;
|
||||
}
|
||||
|
||||
bool Network::Connect()
|
||||
{
|
||||
for (int i = 0; i < this->is_master ? 120 : 10; i++ )
|
||||
{
|
||||
if (this->network_connection_state == CONNECTED)
|
||||
return true;
|
||||
/* Run the state machine */
|
||||
this->ConnectFSM();
|
||||
}
|
||||
|
||||
return false;a
|
||||
}
|
||||
|
||||
void Network::Disconnect()
|
||||
|
@ -15,9 +15,9 @@
|
||||
enum
|
||||
{
|
||||
/* Connection-related messages */
|
||||
HELLO = 99, /* Hello, broker */
|
||||
CONNECT_TO_BROKER = 99, /* Hello, broker */
|
||||
LIST_PEERS = 98, /* List of peers */
|
||||
PEER_CONNECT = 97, /* A peer wants to connect */
|
||||
CONNECT_TO_PEER = 97, /* A peer wants to connect */
|
||||
DISCONNECT = 96, /* Disconnect from a peer */
|
||||
PING = 95, /* (broker) are you alive? */
|
||||
ACK = 94, /* Answer to broker */
|
||||
@ -34,8 +34,9 @@ enum
|
||||
ENTER_MENU = 8,
|
||||
};
|
||||
|
||||
enum
|
||||
typedef enum
|
||||
{
|
||||
CONNECTED,
|
||||
CONNECT_TO_BROKER,
|
||||
WAIT_FOR_PEER_ADDRESS,
|
||||
CONNECT_TO_PEER,
|
||||
@ -43,7 +44,7 @@ enum
|
||||
|
||||
/* Client-only */
|
||||
WAIT_FOR_PEER_LIST,
|
||||
};
|
||||
} network_connection_state_t;
|
||||
|
||||
struct NetworkUpdate
|
||||
{
|
||||
@ -83,8 +84,10 @@ struct NetworkUpdatePeerInfo
|
||||
uint16 private_port;
|
||||
uint16 public_port;
|
||||
|
||||
uint8 private_ip[4]; /* Wii isn't ipv6 capable anyway AFAIK */
|
||||
uint8 public_ip[4];
|
||||
/* Encoded as hex numbers in a string - c0a80a02\0 -> 192.168.10.2.
|
||||
* Some more space to fit IPv6 stuff */
|
||||
uint8 private_ip[16];
|
||||
uint8 public_ip[16];
|
||||
|
||||
uint16 key; /* Random value to separate same names */
|
||||
uint16 is_master;
|
||||
@ -94,7 +97,7 @@ struct NetworkUpdatePeerInfo
|
||||
struct NetworkUpdateListPeers
|
||||
{
|
||||
uint32 n_peers;
|
||||
uint8 your_ip[4];
|
||||
uint8 your_ip[16];
|
||||
uint16 your_port;
|
||||
uint8 d[2]; /* Pad to 4 bytes */
|
||||
|
||||
@ -157,15 +160,13 @@ public:
|
||||
|
||||
static bool CheckNewConnection();
|
||||
|
||||
bool WaitForConnection();
|
||||
|
||||
bool ConnectToPeer();
|
||||
|
||||
Uint8 *GetScreen()
|
||||
{
|
||||
return this->screen;
|
||||
}
|
||||
|
||||
bool Connect();
|
||||
|
||||
/**
|
||||
* Disconnect from the other end. You should delete the object
|
||||
* after having done this.
|
||||
@ -255,7 +256,10 @@ protected:
|
||||
|
||||
virtual bool Select(int sock, struct timeval *tv);
|
||||
|
||||
void MangleIp(uint8 *ip);
|
||||
bool IpToStr(char *dst, uint8 *ip);
|
||||
|
||||
bool InitSockaddr (struct sockaddr_in *name,
|
||||
const char *hostname, uint16_t port);
|
||||
|
||||
bool MarshalData(NetworkUpdate *ud);
|
||||
|
||||
@ -265,6 +269,18 @@ protected:
|
||||
|
||||
bool DeMarshalData(NetworkUpdate *ud);
|
||||
|
||||
bool ConnectToBroker();
|
||||
|
||||
bool ConnectToPeer();
|
||||
|
||||
bool WaitForPeerReply();
|
||||
|
||||
bool WaitForPeerList();
|
||||
|
||||
bool WaitForPeerAddress();
|
||||
|
||||
bool ConnectFSM();
|
||||
|
||||
NetworkUpdate *GetNext(NetworkUpdate *p)
|
||||
{
|
||||
return (NetworkUpdate*)((Uint8*)p + p->size);
|
||||
@ -292,7 +308,9 @@ protected:
|
||||
|
||||
/* Connection to the peer */
|
||||
int sock;
|
||||
struct sockaddr_in connection_addr; /* Points to either of the above */
|
||||
struct sockaddr_in connection_addr;
|
||||
|
||||
network_connection_state_t network_connection_state;
|
||||
|
||||
/* Sound */
|
||||
static uint8 sample_buf[NETWORK_SOUND_BUF_SIZE];
|
||||
|
Loading…
Reference in New Issue
Block a user