commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View 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); }
//------------------------------------------------------------------------------

View 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) {}
//------------------------------------------------------------------------------

View 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(); }
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------