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