mirror of
https://github.com/Oibaf66/frodo-wii.git
synced 2024-11-22 19:39:24 +01:00
Refactored the network implementation. It's now based on a
singleton/factory pattern where peers are equal (almost!). This has simplified the code a bit and also in theory allows clients to "re-export" connections to third/fourth/... parties.
This commit is contained in:
parent
2ab9d452dc
commit
8c73c900df
10
Src/C64.h
10
Src/C64.h
@ -41,6 +41,13 @@
|
||||
#include "ROlib.h"
|
||||
#endif
|
||||
|
||||
/* Network connection type */
|
||||
enum
|
||||
{
|
||||
NONE,
|
||||
MASTER,
|
||||
CLIENT
|
||||
};
|
||||
|
||||
// Sizes of memory areas
|
||||
const int C64_RAM_SIZE = 0x10000;
|
||||
@ -185,10 +192,9 @@ public:
|
||||
#endif
|
||||
#ifdef HAVE_SDL
|
||||
VirtualKeyboard *virtual_keyboard;
|
||||
NetworkServer *network_server;
|
||||
NetworkClient *network_client;
|
||||
char server_hostname[255];
|
||||
int server_port;
|
||||
int network_connection_type;
|
||||
TTF_Font *menu_font;
|
||||
|
||||
bool fake_key_sequence;
|
||||
|
145
Src/C64_SDL.h
145
Src/C64_SDL.h
@ -95,20 +95,21 @@ void C64::c64_ctor1(void)
|
||||
}
|
||||
|
||||
this->virtual_keyboard = new VirtualKeyboard(real_screen, this->menu_font);
|
||||
this->network_server = NULL;
|
||||
this->network_client = NULL;
|
||||
|
||||
strncpy(this->server_hostname, "localhost",
|
||||
sizeof(this->server_hostname));
|
||||
this->server_port = 19760;
|
||||
this->network_connection_type = NONE;
|
||||
|
||||
if (fixme_tmp_network_server)
|
||||
this->network_server = new NetworkServer(this->server_port);
|
||||
if (fixme_tmp_network_server) {
|
||||
Network::StartListener(this->server_port);
|
||||
this->network_connection_type = MASTER;
|
||||
}
|
||||
if (fixme_tmp_network_client)
|
||||
{
|
||||
strcpy(this->server_hostname, fixme_tmp_network_client);
|
||||
this->network_client = new NetworkClient(this->server_hostname,
|
||||
this->server_port);
|
||||
Network::ConnectTo(this->server_hostname, this->server_port);
|
||||
this->network_connection_type = CLIENT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,16 +318,16 @@ void C64::networking_menu(Prefs *np)
|
||||
{
|
||||
char buf[2][255];
|
||||
const char *network_client_messages[] = {
|
||||
"Start network server", /* 0 */
|
||||
"Listen for connections",/* 0 */
|
||||
buf[0], /* 1 */
|
||||
buf[1], /* 2 */
|
||||
"Connect to server", /* 3 */
|
||||
"Connect to remote", /* 3 */
|
||||
NULL,
|
||||
};
|
||||
|
||||
snprintf(buf[0], 255, "Server hostname (now %s)",
|
||||
snprintf(buf[0], 255, "Remote hostname (now %s)",
|
||||
this->server_hostname);
|
||||
snprintf(buf[1], 255, "Server port (now %d)",
|
||||
snprintf(buf[1], 255, "Port (now %d)",
|
||||
this->server_port);
|
||||
opt = menu_select(real_screen, this->menu_font,
|
||||
network_client_messages, NULL);
|
||||
@ -342,22 +343,12 @@ void C64::networking_menu(Prefs *np)
|
||||
this->server_port = atoi(m);
|
||||
}
|
||||
else if (opt == 0) {
|
||||
/* Cannot be both client and server */
|
||||
if (this->network_client != NULL) {
|
||||
delete this->network_client;
|
||||
this->network_client = NULL;
|
||||
Network::StartListener(this->server_port);
|
||||
this->network_connection_type = MASTER;
|
||||
}
|
||||
this->network_server = new NetworkServer(this->server_port);
|
||||
}
|
||||
else if (opt == 3)
|
||||
{
|
||||
if (this->network_server != NULL) {
|
||||
delete this->network_server;
|
||||
this->network_server = NULL;
|
||||
}
|
||||
|
||||
this->network_client = new NetworkClient(this->server_hostname,
|
||||
this->server_port);
|
||||
else if (opt == 3) {
|
||||
Network::ConnectTo(this->server_hostname, this->server_port);
|
||||
this->network_connection_type = CLIENT;
|
||||
}
|
||||
} while (opt == 1 || opt == 2);
|
||||
|
||||
@ -566,43 +557,67 @@ void C64::network_vblank()
|
||||
Uint32 now = SDL_GetTicks();
|
||||
#endif
|
||||
|
||||
if (this->network_server) {
|
||||
/* Perhaps accept a new connection */
|
||||
this->network_server->CheckNewConnection();
|
||||
Network::CheckNewConnection();
|
||||
|
||||
for (int i = 0; i < this->network_server->n_clients; i++) {
|
||||
for (int i = 0; i < Network::n_peers; i++) {
|
||||
Uint8 *master = this->TheDisplay->BitmapBase();
|
||||
NetworkClient *remote = this->network_server->clients[i];
|
||||
Network *remote = Network::peers[i];
|
||||
uint8 *js;
|
||||
static bool has_throttled;
|
||||
|
||||
remote->Tick( now - last_time_update );
|
||||
/* Has the client sent any data? */
|
||||
if (remote->ReceiveUpdate() == true)
|
||||
if (this->quit_thyself)
|
||||
{
|
||||
uint8 *js = &TheCIA1->Joystick2;
|
||||
|
||||
if (ThePrefs.JoystickSwap)
|
||||
js = &TheCIA1->Joystick1;
|
||||
if (remote->DecodeUpdate(NULL, js, true) == false)
|
||||
{
|
||||
/* Disconnect or sending crap, remove this guy! */
|
||||
this->network_server->RemoveClient(remote);
|
||||
remote->Disconnect();
|
||||
continue;
|
||||
}
|
||||
remote->ResetNetworkUpdate();
|
||||
|
||||
remote->Tick( now - last_time_update );
|
||||
if (this->network_connection_type == MASTER) {
|
||||
if (ThePrefs.JoystickSwap)
|
||||
js = &TheCIA1->Joystick1;
|
||||
else
|
||||
js = &TheCIA1->Joystick2;
|
||||
} else {
|
||||
if (ThePrefs.JoystickSwap)
|
||||
js = &TheCIA1->Joystick2;
|
||||
else
|
||||
js = &TheCIA1->Joystick1;
|
||||
}
|
||||
if (remote->ThrottleTraffic()) {
|
||||
|
||||
/* Has the peer sent any data? */
|
||||
if (remote->ReceiveUpdate() == true)
|
||||
{
|
||||
if (remote->DecodeUpdate(remote->GetScreen(), js) == false)
|
||||
{
|
||||
/* Disconnect or sending crap, remove this guy! */
|
||||
Network::RemovePeer(remote);
|
||||
continue;
|
||||
}
|
||||
if (this->network_connection_type == CLIENT)
|
||||
this->TheDisplay->Update(remote->GetScreen());
|
||||
}
|
||||
remote->ResetNetworkUpdate();
|
||||
|
||||
/* Perhaps send updates to the other side (what is determinted by
|
||||
* if this is the master or not) */
|
||||
remote->EncodeJoystickUpdate(*js);
|
||||
remote->EncodeDisplay(master, remote->GetScreen());
|
||||
|
||||
if (this->network_connection_type == MASTER &&
|
||||
remote->ThrottleTraffic()) {
|
||||
/* Skip this frame if the data rate is too high */
|
||||
has_throttled = true;
|
||||
continue;
|
||||
}
|
||||
remote->EncodeDisplay(master, remote->screen);
|
||||
|
||||
if (remote->SendUpdate() == false)
|
||||
{
|
||||
/* Disconnect or broken data */
|
||||
printf("Could not send update\n");
|
||||
this->network_server->RemoveClient(remote);
|
||||
Network::RemovePeer(remote);
|
||||
}
|
||||
else
|
||||
remote->ResetNetworkUpdate();
|
||||
|
||||
if (1)
|
||||
@ -618,44 +633,7 @@ void C64::network_vblank()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this->network_client) {
|
||||
Uint8 js = TheCIA1->Joystick2;
|
||||
|
||||
if (this->quit_thyself)
|
||||
{
|
||||
this->network_client->Disconnect();
|
||||
delete this->network_client;
|
||||
this->network_client = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perhaps send joystick data */
|
||||
if (this->network_client->cur_joystick_data != js)
|
||||
{
|
||||
this->network_client->EncodeJoystickUpdate(js);
|
||||
this->network_client->SendUpdate();
|
||||
this->network_client->cur_joystick_data = js;
|
||||
this->network_client->ResetNetworkUpdate();
|
||||
}
|
||||
|
||||
if (this->network_client->ReceiveUpdate())
|
||||
{
|
||||
/* Got something? */
|
||||
if (this->network_client->DecodeUpdate(this->network_client->screen) == true)
|
||||
{
|
||||
TheDisplay->Update(this->network_client->screen);
|
||||
this->network_client->ResetNetworkUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disconnect or broken data */
|
||||
this->network_client->Disconnect();
|
||||
delete this->network_client;
|
||||
this->network_client = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
last_time_update = now;
|
||||
}
|
||||
|
||||
@ -693,7 +671,7 @@ void C64::VBlank(bool draw_frame)
|
||||
j2 &= joykey;
|
||||
#endif
|
||||
|
||||
if (this->network_server)
|
||||
if (this->network_connection_type == MASTER)
|
||||
{
|
||||
/* Only poll one joystick for network servers */
|
||||
if (ThePrefs.JoystickSwap)
|
||||
@ -712,7 +690,7 @@ void C64::VBlank(bool draw_frame)
|
||||
TheCIA2->CountTOD();
|
||||
|
||||
// Update window if needed
|
||||
if (draw_frame && this->network_client == NULL) {
|
||||
if (draw_frame && this->network_connection_type != CLIENT) {
|
||||
TheDisplay->Update();
|
||||
}
|
||||
|
||||
@ -778,6 +756,7 @@ void C64::VBlank(bool draw_frame)
|
||||
ThePrefs.Save(PREFS_PATH);
|
||||
}
|
||||
this->network_vblank();
|
||||
|
||||
#if defined(GEKKO)
|
||||
now = ticks_to_millisecs(gettime());
|
||||
#else
|
||||
|
@ -227,13 +227,11 @@ void C64Display::Update(uint8 *src_pixels)
|
||||
}
|
||||
|
||||
draw_string(real_screen, 0, 0, networktraffic_string, black, fill_gray);
|
||||
if (this->TheC64->network_server) {
|
||||
for (int i = 0; i < this->TheC64->network_server->n_clients; i++)
|
||||
for (int i = 0; i < Network::n_peers; i++)
|
||||
{
|
||||
NetworkClient *client = this->TheC64->network_server->clients[i];
|
||||
Network *peer = Network::peers[i];
|
||||
|
||||
client->DrawTransferredBlocks(real_screen);
|
||||
}
|
||||
peer->DrawTransferredBlocks(real_screen);
|
||||
}
|
||||
SDL_Flip(real_screen);
|
||||
}
|
||||
|
107
Src/Network.cpp
107
Src/Network.cpp
@ -36,10 +36,13 @@
|
||||
#define RLE_SIZE ( RAW_SIZE * 4 + 8)
|
||||
#define DIFF_SIZE ( RAW_SIZE * 4 + 8)
|
||||
|
||||
Network::Network()
|
||||
Network::Network(int sock, bool is_master)
|
||||
{
|
||||
const size_t size = NETWORK_UPDATE_SIZE;
|
||||
|
||||
this->sock = sock;
|
||||
this->is_master = is_master;
|
||||
|
||||
/* "big enough" buffer */
|
||||
this->ud = (NetworkUpdate*)malloc( size );
|
||||
this->tmp_ud = (NetworkUpdate*)malloc( size );
|
||||
@ -59,6 +62,12 @@ Network::Network()
|
||||
this->square_updated = (Uint32*)malloc( N_SQUARES_W * N_SQUARES_H * sizeof(Uint32));
|
||||
assert(this->square_updated);
|
||||
memset(this->square_updated, 0, N_SQUARES_W * N_SQUARES_H * sizeof(Uint32));
|
||||
|
||||
this->screen = (Uint8 *)malloc(DISPLAY_X * DISPLAY_Y);
|
||||
assert(this->screen);
|
||||
|
||||
/* Assume black screen */
|
||||
memset(this->screen, 0, DISPLAY_X * DISPLAY_Y);
|
||||
}
|
||||
|
||||
Network::~Network()
|
||||
@ -69,6 +78,9 @@ Network::~Network()
|
||||
free(this->raw_buf);
|
||||
free(this->rle_buf);
|
||||
free(this->diff_buf);
|
||||
free(this->screen);
|
||||
|
||||
this->CloseSocket();
|
||||
}
|
||||
|
||||
void Network::Tick(int ms)
|
||||
@ -223,8 +235,10 @@ bool Network::CompareSquare(Uint8 *a, Uint8 *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t Network::EncodeDisplay(Uint8 *master, Uint8 *remote)
|
||||
void Network::EncodeDisplay(Uint8 *master, Uint8 *remote)
|
||||
{
|
||||
if (!this->is_master)
|
||||
return;
|
||||
for ( int sq = 0; sq < N_SQUARES_H * N_SQUARES_W; sq++ )
|
||||
{
|
||||
Uint8 *p_master = &master[ SQUARE_TO_Y(sq) * DISPLAY_X + SQUARE_TO_X(sq) ];
|
||||
@ -366,11 +380,14 @@ void Network::EncodeJoystickUpdate(Uint8 v)
|
||||
{
|
||||
struct NetworkUpdate *dst = this->cur_ud;
|
||||
|
||||
if (this->is_master || this->cur_joystick_data == v)
|
||||
return;
|
||||
dst->type = JOYSTICK_UPDATE;
|
||||
dst->u.joystick.val = v;
|
||||
dst->size = sizeof(NetworkUpdate);
|
||||
|
||||
this->AddNetworkUpdate(dst);
|
||||
this->cur_joystick_data = v;
|
||||
}
|
||||
|
||||
|
||||
@ -436,26 +453,20 @@ void Network::DrawTransferredBlocks(SDL_Surface *screen)
|
||||
}
|
||||
}
|
||||
|
||||
bool Network::ReceiveUpdate(int sock)
|
||||
bool Network::ReceiveUpdate()
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
return this->ReceiveUpdate(this->ud, sock, &tv);
|
||||
return this->ReceiveUpdate(this->ud, &tv);
|
||||
}
|
||||
|
||||
|
||||
bool Network::ReceiveUpdateBlock(int sock)
|
||||
{
|
||||
return this->ReceiveUpdate(this->ud, sock, NULL);
|
||||
}
|
||||
|
||||
bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv)
|
||||
bool Network::ReceiveUpdate(NetworkUpdate *dst, struct timeval *tv)
|
||||
{
|
||||
Uint8 *pp = (Uint8*)dst;
|
||||
NetworkUpdate *p;
|
||||
|
||||
if (this->Select(sock, tv) == false)
|
||||
if (this->Select(this->sock, tv) == false)
|
||||
return false;
|
||||
/* Receive until the stop */
|
||||
do
|
||||
@ -463,7 +474,7 @@ bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv)
|
||||
p = (NetworkUpdate*)pp;
|
||||
|
||||
/* Receive the header */
|
||||
if (this->ReceiveData((void*)p, sock, sizeof(NetworkUpdate)) == false)
|
||||
if (this->ReceiveData((void*)p, this->sock, sizeof(NetworkUpdate)) == false)
|
||||
return false;
|
||||
|
||||
pp = pp + sizeof(NetworkUpdate);
|
||||
@ -474,7 +485,7 @@ bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv)
|
||||
{
|
||||
size_t sz_diff = sz - sizeof(NetworkUpdate);
|
||||
|
||||
if (this->ReceiveData((void*)pp, sock, sz_diff) == false)
|
||||
if (this->ReceiveData((void*)pp, this->sock, sz_diff) == false)
|
||||
return false;
|
||||
pp = pp + sz_diff;
|
||||
}
|
||||
@ -485,12 +496,16 @@ bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Network::SendUpdate(int sock)
|
||||
bool Network::SendUpdate()
|
||||
{
|
||||
NetworkUpdate *src = this->ud;
|
||||
NetworkUpdate *stop = this->cur_ud;
|
||||
size_t sz;
|
||||
|
||||
/* Nothing to send, that's OK */
|
||||
if ( src == stop )
|
||||
return true;
|
||||
|
||||
/* Add a stop at the end of the update */
|
||||
stop->type = STOP;
|
||||
stop->u.stop.val = STOP;
|
||||
@ -503,7 +518,7 @@ bool Network::SendUpdate(int sock)
|
||||
sz = this->GetNetworkUpdateSize();
|
||||
if (sz <= 0)
|
||||
return false;
|
||||
if (this->SendData((void*)src, sock, sz) == false)
|
||||
if (this->SendData((void*)src, this->sock, sz) == false)
|
||||
return false;
|
||||
this->traffic += sz;
|
||||
|
||||
@ -585,7 +600,7 @@ bool Network::DeMarshalData(NetworkUpdate *p)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Network::DecodeUpdate(uint8 *screen, uint8 *js, bool server)
|
||||
bool Network::DecodeUpdate(uint8 *screen, uint8 *js)
|
||||
{
|
||||
NetworkUpdate *p = this->ud;
|
||||
bool out = true;
|
||||
@ -597,13 +612,15 @@ bool Network::DecodeUpdate(uint8 *screen, uint8 *js, bool server)
|
||||
case DISPLAY_UPDATE_RAW:
|
||||
case DISPLAY_UPDATE_RLE:
|
||||
case DISPLAY_UPDATE_DIFF:
|
||||
if (screen == NULL)
|
||||
/* No screen updates _to_ the master */
|
||||
if (this->is_master)
|
||||
break;
|
||||
if (this->DecodeDisplayUpdate(screen, p) == false)
|
||||
out = false;
|
||||
break;
|
||||
case JOYSTICK_UPDATE:
|
||||
if (js)
|
||||
/* No joystick updates _from_ the master */
|
||||
if (js && this->is_master)
|
||||
*js = p->u.joystick.val;
|
||||
break;
|
||||
case DISCONNECT:
|
||||
@ -618,56 +635,32 @@ bool Network::DecodeUpdate(uint8 *screen, uint8 *js, bool server)
|
||||
return out;
|
||||
}
|
||||
|
||||
void NetworkServer::AddClient(int sock)
|
||||
void Network::AddPeer(Network *peer)
|
||||
{
|
||||
NetworkClient *cli = new NetworkClient(sock);
|
||||
|
||||
this->clients[this->n_clients] = cli;
|
||||
this->n_clients++;
|
||||
Network::peers[Network::n_peers] = peer;
|
||||
Network::n_peers++;
|
||||
}
|
||||
|
||||
void NetworkServer::RemoveClient(NetworkClient *client)
|
||||
void Network::RemovePeer(Network *peer)
|
||||
{
|
||||
for (int i = 0; i < this->n_clients; i++)
|
||||
for (int i = 0; i < Network::n_peers; i++)
|
||||
{
|
||||
if (this->clients[i] == client)
|
||||
if (Network::peers[i] == peer)
|
||||
{
|
||||
if (i < this->n_clients - 1)
|
||||
if (i < Network::n_peers - 1)
|
||||
{
|
||||
/* Swap with last */
|
||||
this->clients[i] = this->clients[this->n_clients - 1];
|
||||
Network::peers[i] = Network::peers[Network::n_peers - 1];
|
||||
}
|
||||
delete client;
|
||||
this->n_clients--;
|
||||
delete peer;
|
||||
Network::n_peers--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Not found */
|
||||
}
|
||||
|
||||
void NetworkClient::Init()
|
||||
{
|
||||
this->screen = (Uint8 *)malloc(DISPLAY_X * DISPLAY_Y);
|
||||
assert(this->screen);
|
||||
|
||||
/* Assume black screen */
|
||||
memset(this->screen, 0, DISPLAY_X * DISPLAY_Y);
|
||||
}
|
||||
|
||||
|
||||
NetworkClient::NetworkClient(int sock)
|
||||
{
|
||||
this->Init();
|
||||
this->sock = sock;
|
||||
}
|
||||
|
||||
NetworkClient::~NetworkClient()
|
||||
{
|
||||
free(this->screen);
|
||||
this->CloseSocket(this->sock);
|
||||
}
|
||||
|
||||
void NetworkClient::Disconnect()
|
||||
void Network::Disconnect()
|
||||
{
|
||||
NetworkUpdate *disconnect= this->cur_ud;
|
||||
size_t sz;
|
||||
@ -677,6 +670,12 @@ void NetworkClient::Disconnect()
|
||||
disconnect->size = sizeof(NetworkUpdate);
|
||||
this->AddNetworkUpdate(disconnect);
|
||||
this->SendUpdate();
|
||||
|
||||
Network::RemovePeer(this);
|
||||
}
|
||||
|
||||
int Network::n_peers;
|
||||
int Network::listen_sock;
|
||||
Network *Network::peers[MAX_NETWORK_PEERS];
|
||||
|
||||
#include "NetworkUnix.h"
|
||||
|
109
Src/Network.h
109
Src/Network.h
@ -8,6 +8,8 @@
|
||||
#endif
|
||||
#include <SDL.h>
|
||||
|
||||
#define MAX_NETWORK_PEERS 8
|
||||
|
||||
#define NETWORK_UPDATE_SIZE (256 * 1024)
|
||||
enum
|
||||
{
|
||||
@ -49,16 +51,16 @@ struct NetworkUpdate
|
||||
class Network
|
||||
{
|
||||
public:
|
||||
Network();
|
||||
Network(int sock, bool is_master);
|
||||
|
||||
~Network();
|
||||
|
||||
size_t EncodeDisplay(Uint8 *master, Uint8 *remote);
|
||||
void EncodeDisplay(Uint8 *master, Uint8 *remote);
|
||||
|
||||
void EncodeJoystickUpdate(Uint8 v);
|
||||
|
||||
|
||||
bool DecodeUpdate(uint8 *screen, uint8 *js = NULL, bool server = false);
|
||||
bool DecodeUpdate(uint8 *screen, uint8 *js = NULL);
|
||||
|
||||
void ResetNetworkUpdate(void);
|
||||
|
||||
@ -78,13 +80,41 @@ public:
|
||||
|
||||
void Tick(int ms);
|
||||
|
||||
void CloseSocket(int sock);
|
||||
void CloseSocket();
|
||||
|
||||
bool SendUpdate(int sock);
|
||||
bool SendUpdate();
|
||||
|
||||
bool ReceiveUpdate(int sock);
|
||||
bool ReceiveUpdate();
|
||||
|
||||
bool ReceiveUpdateBlock(int sock);
|
||||
static bool StartListener(int port);
|
||||
|
||||
static bool CheckNewConnection();
|
||||
|
||||
static bool ConnectTo(const char *hostname, int port);
|
||||
|
||||
bool isConnected()
|
||||
{
|
||||
return this->sock >= 0;
|
||||
}
|
||||
|
||||
Uint8 *GetScreen()
|
||||
{
|
||||
return this->screen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the other end. You should delete the object
|
||||
* after having done this.
|
||||
*/
|
||||
void Disconnect();
|
||||
|
||||
static void AddPeer(Network *who);
|
||||
|
||||
static void RemovePeer(Network *peer);
|
||||
|
||||
/* Listener-related */
|
||||
static Network *peers[MAX_NETWORK_PEERS];
|
||||
static int n_peers;
|
||||
|
||||
protected:
|
||||
size_t DecodeSoundUpdate(struct NetworkUpdate *src, char *buf);
|
||||
@ -150,7 +180,7 @@ protected:
|
||||
bool DecodeDisplayRaw(Uint8 *screen, struct NetworkUpdate *src,
|
||||
int x, int y);
|
||||
|
||||
bool ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv);
|
||||
bool ReceiveUpdate(NetworkUpdate *dst, struct timeval *tv);
|
||||
|
||||
bool ReceiveData(void *dst, int sock, size_t sz);
|
||||
|
||||
@ -181,72 +211,17 @@ protected:
|
||||
int time_since_last_reset;
|
||||
int target_kbps;
|
||||
int kbps;
|
||||
};
|
||||
|
||||
class NetworkClient : public Network
|
||||
{
|
||||
public:
|
||||
NetworkClient(int sock);
|
||||
|
||||
~NetworkClient();
|
||||
|
||||
NetworkClient(const char *hostname, int port);
|
||||
|
||||
bool isConnected()
|
||||
{
|
||||
return this->sock >= 0;
|
||||
}
|
||||
|
||||
bool SendUpdate()
|
||||
{
|
||||
return ((Network*)this)->SendUpdate(this->sock);
|
||||
}
|
||||
|
||||
bool ReceiveUpdate()
|
||||
{
|
||||
return ((Network*)this)->ReceiveUpdate(this->sock);
|
||||
}
|
||||
|
||||
bool ReceiveUpdateBlock()
|
||||
{
|
||||
return ((Network*)this)->ReceiveUpdateBlock(this->sock);
|
||||
}
|
||||
|
||||
bool ReceiveData(void *dst, int sock, size_t sz);
|
||||
|
||||
/**
|
||||
* Disconnect from the other end. You should delete the object
|
||||
* after having done this.
|
||||
*/
|
||||
void Disconnect();
|
||||
|
||||
Uint8 *screen;
|
||||
int joystick_port;
|
||||
bool is_master; /* Some peers are more equal than others */
|
||||
Uint8 cur_joystick_data;
|
||||
private:
|
||||
void Init();
|
||||
|
||||
/* Connection to the peer */
|
||||
int sock;
|
||||
};
|
||||
|
||||
#define MAX_NETWORK_CLIENTS 8
|
||||
|
||||
class NetworkServer : public Network
|
||||
{
|
||||
public:
|
||||
NetworkServer(int port);
|
||||
|
||||
bool CheckNewConnection();
|
||||
|
||||
NetworkClient *clients[MAX_NETWORK_CLIENTS];
|
||||
int n_clients;
|
||||
|
||||
void RemoveClient(NetworkClient *client);
|
||||
|
||||
private:
|
||||
void AddClient(int sock);
|
||||
|
||||
int listen_sock;
|
||||
/* Listener-related */
|
||||
static int listen_sock;
|
||||
};
|
||||
|
||||
#endif /* NETWORK_H */
|
||||
|
@ -66,36 +66,44 @@ bool init_sockaddr (struct sockaddr_in *name,
|
||||
}
|
||||
|
||||
|
||||
NetworkServer::NetworkServer(int port) : Network()
|
||||
bool Network::StartListener(int port)
|
||||
{
|
||||
this->n_clients = 0;
|
||||
this->listen_sock = make_socket(port);
|
||||
Network::listen_sock = make_socket(port);
|
||||
|
||||
if (listen(this->listen_sock, MAX_NETWORK_CLIENTS) < 0)
|
||||
if (Network::listen_sock < 0)
|
||||
return false;
|
||||
if (listen(Network::listen_sock, MAX_NETWORK_PEERS) < 0)
|
||||
{
|
||||
perror("listen");
|
||||
exit(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkServer::CheckNewConnection()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Network::CheckNewConnection()
|
||||
{
|
||||
struct timeval tv;
|
||||
struct sockaddr_in client_name;
|
||||
struct sockaddr_in peer_name;
|
||||
size_t size;
|
||||
int client_sock;
|
||||
int peer_sock;
|
||||
fd_set listen_fds;
|
||||
Network *peer;
|
||||
|
||||
/* Not initialized yet */
|
||||
if (Network::listen_sock <= 0)
|
||||
return false;
|
||||
|
||||
/* No more than that thanks... */
|
||||
if (this->n_clients >= MAX_NETWORK_CLIENTS)
|
||||
if (Network::n_peers >= MAX_NETWORK_PEERS)
|
||||
return false;
|
||||
|
||||
FD_ZERO(&listen_fds);
|
||||
FD_SET(this->listen_sock, &listen_fds);
|
||||
FD_SET(Network::listen_sock, &listen_fds);
|
||||
|
||||
/* If something connects, create a new client */
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
int v = select(this->listen_sock + 1, &listen_fds, NULL, NULL, &tv);
|
||||
int v = select(Network::listen_sock + 1, &listen_fds, NULL, NULL, &tv);
|
||||
|
||||
if ( v < 0)
|
||||
{
|
||||
@ -105,33 +113,32 @@ bool NetworkServer::CheckNewConnection()
|
||||
else if ( v == 0 )
|
||||
return false;
|
||||
|
||||
size = sizeof(client_name);
|
||||
client_sock = accept(this->listen_sock, (struct sockaddr*)&client_name, &size);
|
||||
if (client_sock < 0)
|
||||
size = sizeof(peer_name);
|
||||
peer_sock = accept(Network::listen_sock, (struct sockaddr*)&peer_name, &size);
|
||||
if (peer_sock < 0)
|
||||
{
|
||||
fprintf(stderr, "Accepting client failed\n");
|
||||
fprintf(stderr, "Accepting peer failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* And add the new one! */
|
||||
this->AddClient(client_sock);
|
||||
Network::AddPeer(new Network(peer_sock, true));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NetworkClient::NetworkClient(const char *hostname, int port)
|
||||
bool Network::ConnectTo(const char *hostname, int port)
|
||||
{
|
||||
/* Again from glibc docs */
|
||||
struct sockaddr_in servername;
|
||||
|
||||
this->Init();
|
||||
int sock;
|
||||
|
||||
/* Create the socket. */
|
||||
this->sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||
if (this->sock < 0)
|
||||
sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
perror ("socket (client)");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
set_sock_opts(sock);
|
||||
@ -142,8 +149,12 @@ NetworkClient::NetworkClient(const char *hostname, int port)
|
||||
sizeof (servername)) != 0)
|
||||
{
|
||||
perror ("connect (client)");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
Network::AddPeer( new Network(sock, false) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Network::ReceiveData(void *dst, int sock, size_t sz)
|
||||
@ -198,7 +209,7 @@ bool Network::Select(int sock, struct timeval *tv)
|
||||
return v > 0;
|
||||
}
|
||||
|
||||
void Network::CloseSocket(int sock)
|
||||
void Network::CloseSocket()
|
||||
{
|
||||
close(sock);
|
||||
close(this->sock);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user