Disconnection code, some refactoring, sock opts (broken)

This commit is contained in:
simon.kagstrom 2009-01-29 18:04:31 +00:00
parent 0a40441b46
commit f8f469ddaa
6 changed files with 144 additions and 46 deletions

View File

@ -1,4 +1,7 @@
version 7:
TODO: Add ability to select files to load from disks in
a menu
TODO: Would it be possible for you to implement the
binding of Joystick directions to buttons?

View File

@ -199,6 +199,8 @@ public:
bool prefs_changed;
char save_game_name[256];
void network_vlbank();
void select_disc(Prefs *np);
void select_fake_key_sequence(Prefs *np);
void start_fake_key_sequence(const char *str);

View File

@ -554,6 +554,78 @@ void C64::Run(void)
thread_func();
}
void C64::network_vlbank()
{
#if defined(GEKKO)
Uint32 now = ticks_to_millisecs(gettime());
#else
Uint32 now = SDL_GetTicks();
#endif
static int frms = 1;
frms--;
if (this->network_server && frms == 0) {
static uint32_t last_time_update;
static size_t bytes_sent;
frms = 6;
/* Perhaps accept a new connection */
this->network_server->CheckNewConnection();
for (int i = 0; i < this->network_server->n_clients; i++) {
Uint8 *master = this->TheDisplay->BitmapBase();
NetworkClient *remote = this->network_server->clients[i];
remote->EncodeDisplay(master, remote->screen);
if (remote->SendUpdate() == false)
{
/* Disconnect or broken data */
printf("Could not send update\n");
this->network_server->RemoveClient(remote);
}
else
{
remote->ResetNetworkUpdate();
bytes_sent += remote->GetBytesSent();
}
}
if (now - last_time_update > 300)
{
TheDisplay->NetworkTrafficMeter(((bytes_sent * 1000.0) /
((float)now - last_time_update)) / 1024.0);
for (int i = 0; i < this->network_server->n_clients; i++)
this->network_server->clients[i]->ResetBytesSent();
bytes_sent = 0;
last_time_update = now;
}
}
else if (this->network_client) {
if (this->quit_thyself)
{
this->network_client->Disconnect();
delete this->network_client;
this->network_client = NULL;
}
else if (this->network_client->ReceiveUpdateBlock())
{
/* 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;
}
}
}
}
/*
* Vertical blank: Poll keyboard and joysticks, update window
*/
@ -595,47 +667,8 @@ void C64::VBlank(bool draw_frame)
if (draw_frame && this->network_client == NULL) {
TheDisplay->Update();
}
static int frms = 1;
frms--;
if (this->network_server && frms == 0) {
static uint32_t last_time_update;
static size_t bytes_sent;
this->network_vlbank();
frms = 6;
/* Perhaps accept a new connection */
this->network_server->CheckNewConnection();
for (int i = 0; i < this->network_server->n_clients; i++) {
Uint8 *master = this->TheDisplay->BitmapBase();
NetworkClient *remote = this->network_server->clients[i];
remote->EncodeDisplay(master, remote->screen);
if (remote->SendUpdate() == false)
printf("Oh no! Could not send update\n");
remote->ResetNetworkUpdate();
bytes_sent += remote->GetBytesSent();
}
if (now - last_time_update > 300)
{
TheDisplay->NetworkTrafficMeter(((bytes_sent * 1000.0) /
((float)now - last_time_update)) / 1024.0);
for (int i = 0; i < this->network_server->n_clients; i++)
this->network_server->clients[i]->ResetBytesSent();
bytes_sent = 0;
last_time_update = now;
}
}
else if (this->network_client) {
/* Got something? */
if (this->network_client->ReceiveUpdateBlock())
{
this->network_client->DecodeUpdate(
this->network_client->screen);
TheDisplay->Update(this->network_client->screen);
this->network_client->ResetNetworkUpdate();
}
}
if (this->have_a_break) {
int submenus[1];
int opt;

View File

@ -514,6 +514,7 @@ bool Network::MarshalData(NetworkUpdate *p)
case SOUND_UPDATE_RAW:
case SOUND_UPDATE_RLE:
case JOYSTICK_UPDATE:
case DISCONNECT:
case STOP:
break;
default:
@ -555,6 +556,7 @@ bool Network::DeMarshalData(NetworkUpdate *p)
case SOUND_UPDATE_RAW:
case SOUND_UPDATE_RLE:
case JOYSTICK_UPDATE:
case DISCONNECT:
case STOP:
/* Nothing to do, just bytes */
break;
@ -569,6 +571,7 @@ bool Network::DeMarshalData(NetworkUpdate *p)
bool Network::DecodeUpdate(uint8 *screen)
{
NetworkUpdate *p = this->ud;
bool out = true;
while (p->type != STOP)
{
@ -577,13 +580,19 @@ bool Network::DecodeUpdate(uint8 *screen)
case DISPLAY_UPDATE_RAW:
case DISPLAY_UPDATE_RLE:
case DISPLAY_UPDATE_DIFF:
this->DecodeDisplayUpdate(screen, p);
if (this->DecodeDisplayUpdate(screen, p) == false)
out = false;
break;
case DISCONNECT:
out = false;
break;
default:
break;
}
p = this->GetNext(p);
}
return out;
}
void NetworkServer::AddClient(int sock)
@ -594,6 +603,24 @@ void NetworkServer::AddClient(int sock)
this->n_clients++;
}
void NetworkServer::RemoveClient(NetworkClient *client)
{
for (int i = 0; i < this->n_clients; i++)
{
if (this->clients[i] == client)
{
if (i < this->n_clients - 1)
{
/* Swap with last */
this->clients[i] = this->clients[this->n_clients - 1];
}
delete this->clients[i];
this->n_clients--;
return;
}
}
/* Not found */
}
NetworkClient::NetworkClient(int sock) : Network()
{
@ -611,4 +638,16 @@ NetworkClient::~NetworkClient()
free(this->screen);
}
void NetworkClient::Disconnect()
{
NetworkUpdate *disconnect= this->cur_ud;
size_t sz;
/* Add a stop at the end of the update */
disconnect->type = DISCONNECT;
disconnect->size = sizeof(NetworkUpdate);
this->AddNetworkUpdate(disconnect);
this->SendUpdate();
}
#include "NetworkUnix.h"

View File

@ -15,6 +15,7 @@ enum
SOUND_UPDATE_RLE = 5,
KEYBOARD_UPDATE = 6,
JOYSTICK_UPDATE = 7,
DISCONNECT = 8,
};
struct NetworkUpdate
@ -195,6 +196,12 @@ public:
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;
private:
@ -213,6 +220,8 @@ public:
NetworkClient *clients[MAX_NETWORK_CLIENTS];
int n_clients;
void RemoveClient(NetworkClient *client);
private:
void AddClient(int sock);

View File

@ -4,12 +4,25 @@
#include <netinet/in.h>
#include <netdb.h>
static int set_sock_opts(int sock)
{
struct timeval tv;
int d = 1;
memset(&tv, 0, sizeof(tv));
tv.tv_sec = 2;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
&tv, sizeof(struct timeval));
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
&tv, sizeof(struct timeval));
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR, &d, sizeof(int));
}
/* From glibc docs */
static int make_socket (uint16_t port)
{
struct sockaddr_in name;
int sock;
int d = 1;
/* Create the socket. */
sock = socket (PF_INET, SOCK_STREAM, 0);
@ -19,10 +32,7 @@ static int make_socket (uint16_t port)
exit (EXIT_FAILURE);
}
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR, &d, sizeof(int)) < 0) {
perror("setsockopt");
exit(1);
}
set_sock_opts(sock);
/* Give the socket a name. */
name.sin_family = AF_INET;
@ -122,6 +132,8 @@ NetworkClient::NetworkClient(const char *hostname, int port)
return;
}
set_sock_opts(sock);
/* Connect to the server. */
init_sockaddr (&servername, hostname, port);
if (connect(sock, (struct sockaddr *) &servername,