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:
simon.kagstrom 2009-02-01 19:47:21 +00:00
parent 2ab9d452dc
commit 8c73c900df
6 changed files with 233 additions and 265 deletions

View File

@ -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;

View File

@ -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) else if (opt == 3) {
{ Network::ConnectTo(this->server_hostname, this->server_port);
if (this->network_server != NULL) { this->network_connection_type = CLIENT;
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,97 +557,84 @@ 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 */ Network::CheckNewConnection();
this->network_server->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];
static bool has_throttled; uint8 *js;
static bool has_throttled;
remote->Tick( now - last_time_update ); if (this->quit_thyself)
/* Has the client sent any data? */ {
if (remote->ReceiveUpdate() == true) remote->Disconnect();
{ continue;
uint8 *js = &TheCIA1->Joystick2; }
if (ThePrefs.JoystickSwap) remote->Tick( now - last_time_update );
js = &TheCIA1->Joystick1; if (this->network_connection_type == MASTER) {
if (remote->DecodeUpdate(NULL, js, true) == false) if (ThePrefs.JoystickSwap)
{ js = &TheCIA1->Joystick1;
/* Disconnect or sending crap, remove this guy! */ else
this->network_server->RemoveClient(remote); js = &TheCIA1->Joystick2;
continue; } else {
} if (ThePrefs.JoystickSwap)
remote->ResetNetworkUpdate(); js = &TheCIA1->Joystick2;
} else
if (remote->ThrottleTraffic()) { js = &TheCIA1->Joystick1;
/* Skip this frame if the data rate is too high */ }
has_throttled = true;
continue; /* Has the peer sent any data? */
} if (remote->ReceiveUpdate() == true)
remote->EncodeDisplay(master, remote->screen); {
if (remote->SendUpdate() == false) if (remote->DecodeUpdate(remote->GetScreen(), js) == false)
{ {
/* Disconnect or broken data */ /* Disconnect or sending crap, remove this guy! */
printf("Could not send update\n"); Network::RemovePeer(remote);
this->network_server->RemoveClient(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;
}
if (remote->SendUpdate() == false)
{
/* Disconnect or broken data */
printf("Could not send update\n");
Network::RemovePeer(remote);
}
else
remote->ResetNetworkUpdate(); remote->ResetNetworkUpdate();
if (1) if (1)
{ {
static uint32_t last_traffic_update; static uint32_t last_traffic_update;
if (last_time_update - last_traffic_update > 300) if (last_time_update - last_traffic_update > 300)
{ {
TheDisplay->NetworkTrafficMeter(remote->GetKbps() / (8 * 1024.0), TheDisplay->NetworkTrafficMeter(remote->GetKbps() / (8 * 1024.0),
has_throttled); has_throttled);
last_traffic_update = now; last_traffic_update = now;
has_throttled = false; has_throttled = false;
} }
} }
} }
}
else if (this->network_client) {
Uint8 js = TheCIA1->Joystick2;
if (this->quit_thyself) last_time_update = now;
{
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; 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

View File

@ -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++) {
{ Network *peer = Network::peers[i];
NetworkClient *client = this->TheC64->network_server->clients[i];
client->DrawTransferredBlocks(real_screen); peer->DrawTransferredBlocks(real_screen);
}
} }
SDL_Flip(real_screen); SDL_Flip(real_screen);
} }

View File

@ -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"

View File

@ -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 */

View File

@ -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);
} }