commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
79
include/modules/io_net/io_net_client.cpp
Normal file
79
include/modules/io_net/io_net_client.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_net/io_net_client.h"
|
||||
#include "io_net/io_net_client_worker_thread.h"
|
||||
#include "ascii/parser.h"
|
||||
#include "container/nlist.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Net::GetCaps() const
|
||||
{ return IsCaseSensitive | CanRead | CanSeek; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Net::QueueTask(NetWorkerBaseTask &task)
|
||||
{
|
||||
if (!worker.QueueTask(task))
|
||||
__ERR__("Net::QueueTask failed.\n", false);
|
||||
|
||||
while (task.processed.Get() == 0) {}
|
||||
return asbool(task.success.Get());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Handle *Net::Open(const char *path, Mode mode)
|
||||
{
|
||||
NetWorkerOpenTask task(path, mode);
|
||||
return QueueTask(task) ? new NetHandle(this, task.handle) : NULL;
|
||||
}
|
||||
void Net::Close(Handle *h)
|
||||
{
|
||||
NetWorkerCloseTask task(((NetHandle *)h)->remote_id);
|
||||
QueueTask(task);
|
||||
}
|
||||
size_t Net::Tell(Handle *h)
|
||||
{
|
||||
NetWorkerTellTask task(((NetHandle *)h)->remote_id);
|
||||
return QueueTask(task) ? task.pos : 0;
|
||||
}
|
||||
size_t Net::Seek(Handle *h, ptrdiff_t offset, SeekRef ref)
|
||||
{
|
||||
NetWorkerSeekTask task(((NetHandle *)h)->remote_id, offset, ref);
|
||||
return QueueTask(task) ? task.pos : 0;
|
||||
}
|
||||
size_t Net::Read(Handle *h, void *data, size_t size)
|
||||
{
|
||||
NetWorkerReadTask task(((NetHandle *)h)->remote_id, data, size);
|
||||
return QueueTask(task) ? task.read_size : 0;
|
||||
}
|
||||
GS::String Net::Hash(const char *uri)
|
||||
{
|
||||
NetWorkerHashTask task(uri);
|
||||
return QueueTask(task) ? task.hash : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Net::IsConnected() const
|
||||
{ return worker.IsConnected(); }
|
||||
bool Net::Connect(const char *ip, int port)
|
||||
{ return worker.Start(ip, port); }
|
||||
void Net::Disconnect()
|
||||
{ worker.Stop(); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetHandle::~NetHandle()
|
||||
{ GetIOSystem()->Close(this); }
|
||||
//------------------------------------------------------------------------------
|
||||
297
include/modules/io_net/io_net_client_worker_thread.cpp
Normal file
297
include/modules/io_net/io_net_client_worker_thread.cpp
Normal file
@ -0,0 +1,297 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_net/io_net_client.h"
|
||||
#include "ascii/parser.h"
|
||||
#include "container/nlist.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
using namespace GS::Threading;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetWorkerThread::ProcessOpenTask(NetWorkerOpenTask &task)
|
||||
{
|
||||
if (!server_peer)
|
||||
__ERR__(__LOG_F__ << "No peer.\n", false)
|
||||
if (!SendString(server_peer, String("Open,") << task.path))
|
||||
__ERR__(__LOG_F__ << "SendString failed, server = '" << server_peer << "', task.path = '" << task.path << "'\n", false)
|
||||
|
||||
if (!WaitServerResponse())
|
||||
__ERR__(__LOG_F__ << "WaitServerResponse = false\n", false)
|
||||
|
||||
String answer(response.c_ptr(), response.GetSize());
|
||||
ClearServerResponse();
|
||||
|
||||
StringList args;
|
||||
if (answer.Split(",", args) != 2)
|
||||
__ERR__(__LOG_F__ << "NetWorkerThread Wrong arg count: " << answer << "\n", false)
|
||||
|
||||
if (args[0] != "Success")
|
||||
__ERR__(__LOG_F__ << "args[0] != Success ('" << args[0] << "')\n", false)
|
||||
|
||||
task.handle = args[1].Integer();
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessCloseTask(NetWorkerCloseTask &task)
|
||||
{
|
||||
if (!server_peer || !SendString(server_peer, String("Close,") << task.handle))
|
||||
return false;
|
||||
|
||||
if (WaitServerResponse()) // FIXME does not even check for success...
|
||||
ClearServerResponse();
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessSeekTask(NetWorkerSeekTask &task)
|
||||
{
|
||||
String seek_ref;
|
||||
switch (task.seek_ref)
|
||||
{
|
||||
case Base::SeekStart: seek_ref = "Start"; break;
|
||||
case Base::SeekCurrent: seek_ref = "Current"; break;
|
||||
case Base::SeekEnd: seek_ref = "End"; break;
|
||||
}
|
||||
if (!server_peer || !SendString(server_peer, String::Format("Seek,%d,%s,%d", task.offset, seek_ref.c_str(), task.handle)))
|
||||
return false;
|
||||
|
||||
if (!WaitServerResponse())
|
||||
return false;
|
||||
String answer(response.c_ptr(), response.GetSize());
|
||||
ClearServerResponse();
|
||||
|
||||
StringList args;
|
||||
if (answer.Split(",", args) != 2)
|
||||
return false;
|
||||
if (args[0] != "Success")
|
||||
return false;
|
||||
|
||||
task.pos = size_t(args[1].Integer());
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessTellTask(NetWorkerTellTask &task)
|
||||
{
|
||||
if (!server_peer || !SendString(server_peer, String("Tell,") << task.handle))
|
||||
return false;
|
||||
|
||||
if (!WaitServerResponse())
|
||||
return false;
|
||||
String answer(response.c_ptr(), response.GetSize());
|
||||
ClearServerResponse();
|
||||
|
||||
StringList args;
|
||||
if (answer.Split(",", args) != 2)
|
||||
return false;
|
||||
if (args[0] != "Success")
|
||||
return false;
|
||||
|
||||
task.pos = size_t(args[1].Integer());
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessReadTask(NetWorkerReadTask &task)
|
||||
{
|
||||
if (!server_peer || !SendString(server_peer, String::Format("Read,%d,%d", task.size, task.handle)))
|
||||
return false;
|
||||
|
||||
if (!WaitServerResponse())
|
||||
return false;
|
||||
|
||||
// Check success.
|
||||
if (Memory::Compare("Success,", response.c_ptr(), 8))
|
||||
return false; // failed
|
||||
|
||||
// Parse size.
|
||||
const char *p_size = response.c_ptr() + 8;
|
||||
const char *e_size = AsciiParser::Find(response.c_ptr() + 8, response.End(), ',');
|
||||
if (e_size == NULL)
|
||||
return false;
|
||||
task.read_size = size_t(String(p_size, e_size).Integer());
|
||||
|
||||
// Get data.
|
||||
const char *p_data = e_size + 1;
|
||||
if (task.read_size != size_t(response.End() - p_data))
|
||||
return false; // assert buffer size and reported size match
|
||||
if (task.read_size > task.size)
|
||||
return false; // prevent buffer overrun
|
||||
|
||||
Memory::Copy(task.data, p_data, task.read_size);
|
||||
|
||||
ClearServerResponse();
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessHashTask(NetWorkerHashTask &task)
|
||||
{
|
||||
if (!server_peer || !SendString(server_peer, String("Hash,") << task.path))
|
||||
return false;
|
||||
|
||||
if (!WaitServerResponse())
|
||||
return false;
|
||||
|
||||
// Check success.
|
||||
if (Memory::Compare("Success,", response.c_ptr(), 8))
|
||||
return false; // failed
|
||||
|
||||
// Grab hash.
|
||||
task.hash.Set(response.c_ptr() + 8);
|
||||
|
||||
ClearServerResponse();
|
||||
return true;
|
||||
}
|
||||
void NetWorkerThread::ProcessTask(NetWorkerBaseTask &task)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
switch (task.type)
|
||||
{
|
||||
case NetWorkerBaseTask::TypeOpen: success = ProcessOpenTask((NetWorkerOpenTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeClose: success = ProcessCloseTask((NetWorkerCloseTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeSeek: success = ProcessSeekTask((NetWorkerSeekTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeTell: success = ProcessTellTask((NetWorkerTellTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeRead: success = ProcessReadTask((NetWorkerReadTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeHash: success = ProcessHashTask((NetWorkerHashTask &)task); break;
|
||||
}
|
||||
|
||||
// [EJ] Full memory barrier required here.
|
||||
task.success.Set(success ? 1 : 0);
|
||||
task.processed.Set(1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetWorkerThread::QueueTask(NetWorkerBaseTask &task)
|
||||
{
|
||||
if (server_peer == NULL)
|
||||
return false; // [EJ] no queue when not connected
|
||||
|
||||
MutexLock lock(&task_mutex);
|
||||
return asbool(task_queue.Add(&task));
|
||||
}
|
||||
bool NetWorkerThread::CancelTask(NetWorkerBaseTask &task)
|
||||
{
|
||||
MutexLock lock(&task_mutex);
|
||||
return asbool(task_queue.Remove(&task));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetWorkerThread::OnPeerConnection(void *peer)
|
||||
{
|
||||
__LOG_V__ << "IO::Net: OnPeerConnection\n";
|
||||
|
||||
if (server_peer || (handshaking != 1)) // already connected
|
||||
{
|
||||
Disconnect(peer);
|
||||
return;
|
||||
}
|
||||
|
||||
SetPeerTimeout(peer, TimeoutVeryLong);
|
||||
SendString(peer, "RequestIOAccess");
|
||||
|
||||
++handshaking;
|
||||
}
|
||||
void NetWorkerThread::OnPacketReceived(void *peer, const void *data, size_t size)
|
||||
{
|
||||
// __LOG_V__ << "IO::Net: Packet received, handshaking = " << handshaking << ", data: " << String((const char *)data, (const char *)data + size) << "\n";
|
||||
|
||||
if (handshaking == 2)
|
||||
{
|
||||
if ((size == 8) && !GS::Memory::Compare(data, "Granted", size))
|
||||
{
|
||||
server_peer = peer;
|
||||
++handshaking;
|
||||
}
|
||||
else
|
||||
Disconnect(peer);
|
||||
}
|
||||
else
|
||||
if (server_peer == peer)
|
||||
ProcessIOPacket(data, size);
|
||||
}
|
||||
void NetWorkerThread::OnConnectionClosed(void *peer)
|
||||
{
|
||||
if (server_peer == peer)
|
||||
server_peer = NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetWorkerThread::ProcessIOPacket(const void *data, size_t size)
|
||||
{
|
||||
if (response.Allocate(size))
|
||||
Memory::Copy(response.c_ptr(), data, size);
|
||||
}
|
||||
bool NetWorkerThread::WaitServerResponse()
|
||||
{
|
||||
while (response.GetSize() == 0)
|
||||
{
|
||||
if (server_peer == NULL)
|
||||
return false;
|
||||
UpdateHost();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void NetWorkerThread::ClearServerResponse()
|
||||
{ response.Free(); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetWorkerThread::Execute()
|
||||
{
|
||||
Thread::SetName("GS::IO::NetWorkerThread");
|
||||
|
||||
handshaking = 1;
|
||||
|
||||
__LOG_V__ << "IO::Net - Client worker thread connecting to " << ip << " port " << port << ".\n";
|
||||
if (!OpenClient(ip, port))
|
||||
__ERRRAW__(__LOG_E__ << "Connection failed.\n");
|
||||
|
||||
__LOG_V__ << "IO::Net - Entering file server loop...\n";
|
||||
for (running.Set(1); running.Get() != 2; )
|
||||
{
|
||||
UpdateHost();
|
||||
|
||||
if (server_peer != NULL)
|
||||
{
|
||||
MutexLock lock(&task_mutex);
|
||||
while (NetWorkerBaseTask *task = task_queue.GetCount() > 0 ? task_queue.GetRoot()->Object() : NULL)
|
||||
{
|
||||
task_queue.RemoveAt(0);
|
||||
ProcessTask(*task);
|
||||
}
|
||||
|
||||
if (server_peer == NULL) // [EJ] if connection was lost during this run, drop all pending tasks.
|
||||
task_queue.Clear();
|
||||
}
|
||||
|
||||
Platform::Get().Sleep(1);
|
||||
}
|
||||
|
||||
handshaking = 0;
|
||||
|
||||
__LOG_V__ << "IO::Net - Client worker thread exiting.\n";
|
||||
running.Set(0);
|
||||
}
|
||||
bool NetWorkerThread::Start(const char *_ip, int _port)
|
||||
{
|
||||
ip = _ip;
|
||||
port = _port;
|
||||
return Thread::Start();
|
||||
}
|
||||
void NetWorkerThread::Stop()
|
||||
{
|
||||
if (running.Get() != 0)
|
||||
{
|
||||
running.Set(2);
|
||||
while (running.Get() != 0); // spinlock
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetWorkerThread::NetWorkerThread() : server_peer(0), handshaking(0) {}
|
||||
//------------------------------------------------------------------------------
|
||||
325
include/modules/io_net/io_net_server.cpp
Normal file
325
include/modules/io_net/io_net_server.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_net/io_net_server.h"
|
||||
#include "metafile/nml.h"
|
||||
#include "async/task_loop.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
// #define VERBOSE_LOG
|
||||
|
||||
|
||||
// @FIXME Rewrite communication with the controller thread using AsyncCallQueue.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetServer::Client *NetServer::GetClient(void *peer)
|
||||
{
|
||||
ListForeachPtr(Client *, client, clients)
|
||||
if (client->peer == peer)
|
||||
return client;
|
||||
return NULL;
|
||||
}
|
||||
int NetServer::GetClientFreeHandleIndex(const Client &client) const
|
||||
{
|
||||
int free_id = 0;
|
||||
ListForeachPtr(ClientHandleInfo *, i, client.handles)
|
||||
if (i->id >= free_id)
|
||||
free_id = i->id + 1;
|
||||
return free_id;
|
||||
}
|
||||
Handle *NetServer::GetClientHandle(const Client &client, int id) const
|
||||
{
|
||||
ListForeachPtr(ClientHandleInfo *, i, client.handles)
|
||||
if (i->id == id)
|
||||
return i->handle;
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetServer::ProcessCloseCommand(Client &client, GS::StringList &args)
|
||||
// Close,handle_id
|
||||
{
|
||||
if (args.GetCount() != 2)
|
||||
return false;
|
||||
|
||||
int id = args[1].Integer();
|
||||
|
||||
ClientHandleInfo *hi = NULL;
|
||||
ListForeachPtr(ClientHandleInfo *, i, client.handles)
|
||||
if (i->id == id)
|
||||
{
|
||||
hi = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hi == NULL)
|
||||
return false;
|
||||
|
||||
client.handles.Remove(hi);
|
||||
|
||||
#ifdef VERBOSE_LOG
|
||||
__LOG__ << "IO::NetServer: Close handle " << id << " (client total: " << client.handles.GetCount() << ").\n";
|
||||
#endif
|
||||
return SendString(client.peer, "Success");
|
||||
}
|
||||
bool NetServer::ProcessReadCommand(Client &client, GS::StringList &args)
|
||||
// Read,size,handle_id
|
||||
{
|
||||
if (args.GetCount() != 3)
|
||||
return false;
|
||||
|
||||
Handle *h = GetClientHandle(client, args[2].Integer());
|
||||
if (h == NULL)
|
||||
return false;
|
||||
|
||||
// Read data.
|
||||
size_t size = size_t(args[1].Integer());
|
||||
Array <char> data(size);
|
||||
size_t read_size = h->Read((void *)data, size);
|
||||
|
||||
// Format answer data (FIXME two allocations are not required for this).
|
||||
String answer = String::Format("Success,%d,", read_size);
|
||||
|
||||
Array <char> answer_data(answer.Len() + read_size);
|
||||
Memory::Copy(answer_data.c_ptr(), answer.c_str(), answer.Len());
|
||||
Memory::Copy(answer_data.c_ptr() + answer.Len(), data.c_ptr(), read_size);
|
||||
|
||||
return Send(client.peer, (void *)answer_data.c_ptr(), answer_data.GetSize());
|
||||
}
|
||||
bool NetServer::ProcessSeekCommand(Client &client, GS::StringList &args)
|
||||
// Seek,offset_from_start,ref,handle_id
|
||||
{
|
||||
if (args.GetCount() != 4)
|
||||
return false;
|
||||
|
||||
Handle *h = GetClientHandle(client, args[3].Integer());
|
||||
if (h == NULL)
|
||||
return false;
|
||||
|
||||
ptrdiff_t offset = ptrdiff_t(args[1].Integer());
|
||||
|
||||
Base::SeekRef seek_ref;
|
||||
if (args[2] == "Start")
|
||||
seek_ref = Base::SeekStart;
|
||||
else if (args[2] == "Current")
|
||||
seek_ref = Base::SeekCurrent;
|
||||
else if (args[2] == "End")
|
||||
seek_ref = Base::SeekEnd;
|
||||
else
|
||||
return false;
|
||||
|
||||
size_t r = h->Seek(offset, seek_ref);
|
||||
return SendString(client.peer, String::Format("Success,%d", r));
|
||||
}
|
||||
bool NetServer::ProcessTellCommand(Client &client, GS::StringList &args)
|
||||
// Tell,handle_id
|
||||
{
|
||||
if (args.GetCount() != 2)
|
||||
return false;
|
||||
|
||||
Handle *h = GetClientHandle(client, args[1].Integer());
|
||||
if (h == NULL)
|
||||
return false;
|
||||
|
||||
return SendString(client.peer, String::Format("Success,%d", h->Tell()));
|
||||
}
|
||||
bool NetServer::ProcessOpenCommand(Client &client, GS::StringList &args)
|
||||
// Open,path
|
||||
{
|
||||
if (args.GetCount() != 2)
|
||||
__ERR__(__LOG_E__ << "NetServer::ProcessOpenCommand(): incorrect argument count.\n", false)
|
||||
|
||||
int index = GetClientFreeHandleIndex(client);
|
||||
|
||||
AutoPtr <ClientHandleInfo> i(new ClientHandleInfo);
|
||||
i->id = index;
|
||||
i->name = args[1];
|
||||
i->handle = basefs->Open(i->name);
|
||||
if (i->handle.IsNull())
|
||||
return false; // __ERR__(__LOG_E__ << "NetServer::ProcessOpenCommand(): failed to open '" << i->name << "' on base filesystem.\n", false)
|
||||
|
||||
client.handles.Add(i.Detach());
|
||||
|
||||
#ifdef VERBOSE_LOG
|
||||
__LOG__ << "IO::NetServer: Open handle '" << args[1] << "' => " << index << " (client total: " << client.handles.GetCount() << ").\n";
|
||||
#endif
|
||||
return SendString(client.peer, String::Format("Success,%d", index));
|
||||
}
|
||||
bool NetServer::ProcessHashCommand(Client &client, GS::StringList &args)
|
||||
// Hash,path
|
||||
{
|
||||
if (args.GetCount() != 2)
|
||||
return false;
|
||||
|
||||
String hash = basefs->Hash(args[1]);
|
||||
if (hash.IsEmpty())
|
||||
return false;
|
||||
|
||||
return SendString(client.peer, String::Format("Success,%s", hash.c_str()));
|
||||
}
|
||||
bool NetServer::ProcessClientRequest(Client &client, const GS::String &data)
|
||||
{
|
||||
StringList args;
|
||||
data.Split(",", args);
|
||||
|
||||
bool r = false;
|
||||
|
||||
// Command dispatch.
|
||||
if (args[0] == "Open")
|
||||
r = ProcessOpenCommand(client, args);
|
||||
else if (args[0] == "Seek")
|
||||
r = ProcessSeekCommand(client, args);
|
||||
else if (args[0] == "Tell")
|
||||
r = ProcessTellCommand(client, args);
|
||||
else if (args[0] == "Read")
|
||||
r = ProcessReadCommand(client, args);
|
||||
else if (args[0] == "Close")
|
||||
r = ProcessCloseCommand(client, args);
|
||||
else if (args[0] == "Hash")
|
||||
r = ProcessHashCommand(client, args);
|
||||
|
||||
if (!r)
|
||||
SendString(client.peer, "Failed");
|
||||
return r;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetServer::GetStatistics(Statistics &stats)
|
||||
{
|
||||
Time t = Platform::Get().GetTime();
|
||||
|
||||
stats.connected = asbool(clients.GetCount());
|
||||
|
||||
Network::Enet::Statistics enet_stats;
|
||||
Network::Enet::GetStatistics(enet_stats);
|
||||
|
||||
if ((t - bandwidth_measure.time).toSec() > 2)
|
||||
{
|
||||
bandwidth = int((enet_stats.sent_data - bandwidth_measure.value) / (t - bandwidth_measure.time).toSec());
|
||||
|
||||
bandwidth_measure.time = t;
|
||||
bandwidth_measure.value = enet_stats.sent_data;
|
||||
}
|
||||
|
||||
stats.sent_data = enet_stats.sent_data;
|
||||
stats.bandwidth = bandwidth;
|
||||
|
||||
stats.packet_loss = 0;
|
||||
if (clients.GetCount() > 0)
|
||||
{
|
||||
ListForeachPtr(Client *, client, clients)
|
||||
stats.packet_loss += GetPeerPacketLossRatio(client->peer);
|
||||
stats.packet_loss /= clients.GetCount();
|
||||
}
|
||||
|
||||
// Handle statistics.
|
||||
int handle_count = 0;
|
||||
ListForeachPtr(Client *, client, clients)
|
||||
handle_count += client->handles.GetCount();
|
||||
|
||||
if (stats.handles.Allocate(handle_count))
|
||||
{
|
||||
handle_count = 0;
|
||||
ListForeachPtr(Client *, client, clients)
|
||||
ListForeachPtr(ClientHandleInfo *, i, client->handles)
|
||||
{
|
||||
Statistics::Handle *h = &stats.handles[handle_count++];
|
||||
h->name = i->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetServer::OnPeerConnection(void *peer)
|
||||
{
|
||||
__LOG_H__ << "IO::NetServer: OnPeerConnection\n";
|
||||
|
||||
__ASSERT__(GetClient(peer) == NULL);
|
||||
clients.Add(new Client(peer));
|
||||
|
||||
SetPeerTimeout(peer, TimeoutVeryLong);
|
||||
}
|
||||
void NetServer::OnPacketReceived(void *peer, const void *data, size_t size)
|
||||
{
|
||||
Client *client = GetClient(peer);
|
||||
__ASSERT__(client != NULL);
|
||||
|
||||
if (size > 512)
|
||||
{
|
||||
SendString(peer, "DataLengthError");
|
||||
return; // invalid
|
||||
}
|
||||
|
||||
String command((char *)data, (char *)data + size);
|
||||
|
||||
if (client->handshake_step == -1)
|
||||
ProcessClientRequest(*client, command);
|
||||
|
||||
else
|
||||
{
|
||||
switch (client->handshake_step)
|
||||
{
|
||||
case 0:
|
||||
if (command == "RequestIOAccess")
|
||||
{
|
||||
__LOG_V__ << "Granting client access.\n";
|
||||
client->handshake_step = -1;
|
||||
|
||||
SendString(peer, "Granted");
|
||||
}
|
||||
else
|
||||
Disconnect(peer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void NetServer::OnConnectionClosed(void *peer)
|
||||
{
|
||||
__LOG_H__ << "IO::NetServer: OnConnectionClosed\n";
|
||||
|
||||
Client *client = GetClient(peer);
|
||||
__ASSERT__(client != NULL);
|
||||
clients.Remove(client);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetServer::Start(const char *ip, int port)
|
||||
{
|
||||
__LOG_H__ << "IO::NetServer: Starting on " << ip << " port " << port << ".\n";
|
||||
return OpenServer(ip, port);
|
||||
}
|
||||
void NetServer::Stop()
|
||||
{
|
||||
__LOG_H__ << "IO::NetServer: Shutting down.\n";
|
||||
|
||||
// Disconnect all clients.
|
||||
ListForeachPtr(Client *, c, clients)
|
||||
Disconnect(c->peer);
|
||||
|
||||
StartTaskLoop(clients.GetCount() > 0, 2000)
|
||||
{
|
||||
UpdateHost();
|
||||
Platform::Get().Sleep(1);
|
||||
}
|
||||
EndTaskLoop
|
||||
|
||||
Close();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetServer::NetServer(Base *fs) : basefs(fs), bandwidth(0)
|
||||
{}
|
||||
NetServer::~NetServer()
|
||||
{ Stop(); }
|
||||
//------------------------------------------------------------------------------
|
||||
76
include/modules/io_net/io_net_server_thread.cpp
Normal file
76
include/modules/io_net/io_net_server_thread.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_net/io_net_server_thread.h"
|
||||
#include "filesystem/io_cfile.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetServerThread::Execute()
|
||||
{
|
||||
{
|
||||
Threading::MutexLock lock(&server_mutex);
|
||||
server = new NetServer(basefs);
|
||||
}
|
||||
|
||||
if (server->Start(ip.c_str(), port))
|
||||
for (state.Set(1); state.Get() != 2; )
|
||||
{
|
||||
{
|
||||
Threading::MutexLock lock(&server_mutex);
|
||||
server->UpdateHost();
|
||||
}
|
||||
Platform::Get().Sleep(1);
|
||||
}
|
||||
|
||||
{
|
||||
Threading::MutexLock lock(&server_mutex);
|
||||
server = NULL;
|
||||
}
|
||||
state.Set(0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetServerThread::Start(const char *_ip, int _port)
|
||||
{
|
||||
ip = _ip;
|
||||
port = _port;
|
||||
|
||||
if (!Thread::Start())
|
||||
return false;
|
||||
|
||||
while (state.Get() == 0)
|
||||
;
|
||||
|
||||
return asbool(state.Get() != -1);
|
||||
}
|
||||
void NetServerThread::Stop()
|
||||
{
|
||||
state.Set(2);
|
||||
while (state.Get() != 0); // spinlock
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetServerThread::GetStatistics(NetServer::Statistics &stats)
|
||||
{
|
||||
Threading::MutexLock lock(&server_mutex);
|
||||
if (server.IsValid())
|
||||
server->GetStatistics(stats);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetServerThread::~NetServerThread()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user