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: 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 TODO: Would it be possible for you to implement the
binding of Joystick directions to buttons? binding of Joystick directions to buttons?

View File

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

View File

@ -554,6 +554,78 @@ void C64::Run(void)
thread_func(); 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 * 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) { if (draw_frame && this->network_client == NULL) {
TheDisplay->Update(); TheDisplay->Update();
} }
static int frms = 1; this->network_vlbank();
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)
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) { if (this->have_a_break) {
int submenus[1]; int submenus[1];
int opt; int opt;

View File

@ -514,6 +514,7 @@ bool Network::MarshalData(NetworkUpdate *p)
case SOUND_UPDATE_RAW: case SOUND_UPDATE_RAW:
case SOUND_UPDATE_RLE: case SOUND_UPDATE_RLE:
case JOYSTICK_UPDATE: case JOYSTICK_UPDATE:
case DISCONNECT:
case STOP: case STOP:
break; break;
default: default:
@ -555,6 +556,7 @@ bool Network::DeMarshalData(NetworkUpdate *p)
case SOUND_UPDATE_RAW: case SOUND_UPDATE_RAW:
case SOUND_UPDATE_RLE: case SOUND_UPDATE_RLE:
case JOYSTICK_UPDATE: case JOYSTICK_UPDATE:
case DISCONNECT:
case STOP: case STOP:
/* Nothing to do, just bytes */ /* Nothing to do, just bytes */
break; break;
@ -569,6 +571,7 @@ bool Network::DeMarshalData(NetworkUpdate *p)
bool Network::DecodeUpdate(uint8 *screen) bool Network::DecodeUpdate(uint8 *screen)
{ {
NetworkUpdate *p = this->ud; NetworkUpdate *p = this->ud;
bool out = true;
while (p->type != STOP) while (p->type != STOP)
{ {
@ -577,13 +580,19 @@ bool Network::DecodeUpdate(uint8 *screen)
case DISPLAY_UPDATE_RAW: case DISPLAY_UPDATE_RAW:
case DISPLAY_UPDATE_RLE: case DISPLAY_UPDATE_RLE:
case DISPLAY_UPDATE_DIFF: case DISPLAY_UPDATE_DIFF:
this->DecodeDisplayUpdate(screen, p); if (this->DecodeDisplayUpdate(screen, p) == false)
out = false;
break;
case DISCONNECT:
out = false;
break; break;
default: default:
break; break;
} }
p = this->GetNext(p); p = this->GetNext(p);
} }
return out;
} }
void NetworkServer::AddClient(int sock) void NetworkServer::AddClient(int sock)
@ -594,6 +603,24 @@ void NetworkServer::AddClient(int sock)
this->n_clients++; 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() NetworkClient::NetworkClient(int sock) : Network()
{ {
@ -611,4 +638,16 @@ NetworkClient::~NetworkClient()
free(this->screen); 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" #include "NetworkUnix.h"

View File

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

View File

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