223 lines
6.9 KiB
C++
223 lines
6.9 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "squirrel_binding.h"
|
|
#include "script/script_variant.h"
|
|
#include "async/async_call_queue_thread.h"
|
|
#include "binding_helpers.h"
|
|
#include "sqstdblob.h"
|
|
|
|
using namespace GS;
|
|
using namespace GS::Script;
|
|
|
|
|
|
#if __PLATFORM_EMSCRIPTEN__ == 0
|
|
|
|
#include "network_enet/enet_network.h"
|
|
|
|
//------------------------------------------------------------------------------
|
|
struct ScriptPeerThread : public Network::Enet, public Threading::ASyncCallQueueThread
|
|
{
|
|
void OnIdle()
|
|
{ UpdateHost(); }
|
|
|
|
//----------------------------------------------------------------------
|
|
struct VMThreadData
|
|
{
|
|
SquirrelVM *vm;
|
|
|
|
void OnPeerConnection(void *peer)
|
|
{
|
|
if (peer && vm->SetupFunctionCall("OnPeerConnection"))
|
|
{
|
|
vm->PushVariant(Script::Variant(peer, typetag_Peer));
|
|
vm->DoFunctionCall();
|
|
}
|
|
}
|
|
void OnPacketReceived(void *peer, const Array <char> &packet)
|
|
{
|
|
if (peer && vm->SetupFunctionCall("OnPacketReceived"))
|
|
{
|
|
vm->PushVariant(Script::Variant(peer, typetag_Peer));
|
|
vm->PushVariant(Script::Variant((const void *)packet.c_ptr(), packet.GetSize()));
|
|
vm->DoFunctionCall();
|
|
}
|
|
}
|
|
void OnConnectionClosed(void *peer)
|
|
{
|
|
if (peer && vm->SetupFunctionCall("OnConnectionClosed"))
|
|
{
|
|
vm->PushVariant(Script::Variant(peer, typetag_Peer));
|
|
vm->DoFunctionCall();
|
|
}
|
|
}
|
|
|
|
// To be executed from the VM thread.
|
|
ASync::CallQueue task_queue;
|
|
|
|
VMThreadData(SquirrelVM *v) : vm(v) {}
|
|
};
|
|
|
|
VMThreadData vm_thread;
|
|
//----------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------
|
|
void OnPeerConnection(void *peer)
|
|
{ vm_thread.task_queue.QueueMemberCall(&vm_thread, &VMThreadData::OnPeerConnection, peer); }
|
|
void OnPacketReceived(void *peer, const void *data, size_t size)
|
|
{ vm_thread.task_queue.QueueMemberCall(&vm_thread, &VMThreadData::OnPacketReceived, peer, Array <char> (size, (const char *)data)); }
|
|
void OnConnectionClosed(void *peer)
|
|
{ vm_thread.task_queue.QueueMemberCall(&vm_thread, &VMThreadData::OnConnectionClosed, peer); }
|
|
//----------------------------------------------------------------------
|
|
|
|
ScriptPeerThread(SquirrelVM *v) : vm_thread(v) {}
|
|
};
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
SQInteger PeerNetOpenServer(HSQUIRRELVM vm)
|
|
{
|
|
__SQ_GETSTART(2)
|
|
__SQ_GETSTRING(ip)
|
|
__SQ_GETINT(port)
|
|
__SQ_GETEND
|
|
|
|
ScriptPeerThread *t = new ScriptPeerThread(GetVMObject(vm));
|
|
if (t == NULL)
|
|
return sq_throwerror(vm, "Failed to allocate peer network controller.");
|
|
|
|
t->Start();
|
|
t->QueueMemberCall(t, &ScriptPeerThread::OpenServer, String(ip), port);
|
|
|
|
__SQ_RETURNMANAGEDSAFEPTR(t, typetag_PeerController)
|
|
}
|
|
SQInteger PeerNetOpenClient(HSQUIRRELVM vm)
|
|
{
|
|
__SQ_GETSTART(2)
|
|
__SQ_GETSTRING(ip)
|
|
__SQ_GETINT(port)
|
|
__SQ_GETEND
|
|
|
|
ScriptPeerThread *t = new ScriptPeerThread(GetVMObject(vm));
|
|
if (t == NULL)
|
|
return sq_throwerror(vm, "Failed to allocate peer network controller.");
|
|
|
|
t->Start();
|
|
t->QueueMemberCall(t, &ScriptPeerThread::OpenClient, String(ip), port);
|
|
|
|
__SQ_RETURNMANAGEDSAFEPTR(t, typetag_PeerController)
|
|
}
|
|
SQInteger PeerNetUpdate(HSQUIRRELVM vm)
|
|
{
|
|
__SQ_GETSINGLESAFEPTR(t, ScriptPeerThread, typetag_PeerController)
|
|
t->vm_thread.task_queue.ExecuteAll();
|
|
__SQ_RETURN
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
SQInteger PeerNetSendString(HSQUIRRELVM vm)
|
|
{
|
|
__SQ_GETSTART(3)
|
|
__SQ_GETSAFEPTR(t, ScriptPeerThread, typetag_PeerController)
|
|
__SQ_GETSAFEPTR(peer, ENetPeer *, typetag_Peer)
|
|
__SQ_GETSTRING(data)
|
|
__SQ_GETEND
|
|
t->QueueMemberCall(t, &ScriptPeerThread::SendString, peer, String(data));
|
|
__SQ_RETURN
|
|
}
|
|
SQInteger PeerNetBroadcastString(HSQUIRRELVM vm)
|
|
{
|
|
__SQ_GETSTART(2)
|
|
__SQ_GETSAFEPTR(t, ScriptPeerThread, typetag_PeerController)
|
|
__SQ_GETSTRING(data)
|
|
__SQ_GETEND
|
|
t->QueueMemberCall(t, &ScriptPeerThread::BroadcastString, String(data));
|
|
__SQ_RETURN
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
#else
|
|
|
|
SQInteger PeerNetOpenServer(HSQUIRRELVM vm)
|
|
{ return 0; }
|
|
SQInteger PeerNetOpenClient(HSQUIRRELVM vm)
|
|
{ return 0; }
|
|
SQInteger PeerNetUpdate(HSQUIRRELVM vm)
|
|
{ return 0; }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
SQInteger PeerNetSendString(HSQUIRRELVM vm)
|
|
{ return 0; }
|
|
SQInteger PeerNetBroadcastString(HSQUIRRELVM vm)
|
|
{ return 0; }
|
|
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------------
|
|
void RegisterINetBinding(HSQUIRRELVM vm)
|
|
{
|
|
/*#
|
|
Topic: Peer Network
|
|
Desc: Implement a peer-to-peer network.
|
|
Type: PeerController
|
|
#*/
|
|
|
|
/*#
|
|
Section: PeerNetHandshake
|
|
Desc: Handshaking
|
|
#*/
|
|
/*#
|
|
Func: PeerNetOpenServer
|
|
Proto: PeerController:String ip,int port
|
|
Desc: Open a listening server connection on a given ip address and port.
|
|
Note: A server connection is usually opened on the local host ip "127.0.0.1".
|
|
Example:
|
|
// Start a peer server on the local host on port 8000.
|
|
PeerNetOpenServer("127.0.0.1", 8000)
|
|
#*/
|
|
sq_register(vm, PeerNetOpenServer, "PeerNetOpenServer", _SC(".si"));
|
|
/*#
|
|
Func: PeerNetOpenClient
|
|
Proto: PeerController:String ip,int port
|
|
Desc: Open a client connection to a given ip address and port.
|
|
Example:
|
|
// Connect client to peer server on the remote address 192.168.0.12 on port 8000.
|
|
PeerNetOpenClient("192.168.0.12", 8000)
|
|
#*/
|
|
sq_register(vm, PeerNetOpenClient, "PeerNetOpenClient", _SC(".ss"));
|
|
/*#
|
|
Section: PeerNetCommunication
|
|
Desc: Communication
|
|
#*/
|
|
/*#
|
|
Func: PeerNetSendString
|
|
Proto: void:PeerController controller,Peer peer,String data
|
|
Desc: Send a string to a specific peer controller.
|
|
Example:
|
|
// Send the HELLO string to a specific peer.
|
|
PeerNetSendString(controller, peer, "HELLO")
|
|
#*/
|
|
sq_register(vm, PeerNetSendString, "PeerNetSendString", _SC(".xxs"));
|
|
/*#
|
|
Func: PeerNetBroadcastString
|
|
Proto: void:PeerController controller,String data
|
|
Desc: Send a string to all peer controllers connected to this controller.
|
|
Example:
|
|
// Broadcast the HELLO string to all connected peers.
|
|
PeerNetBroadcastString(controller, "HELLO")
|
|
#*/
|
|
sq_register(vm, PeerNetBroadcastString, "PeerNetBroadcastString", _SC(".xs"));
|
|
/*#
|
|
Func: PeerNetUpdate
|
|
Proto: void:PeerController controller
|
|
Desc: Dispatch all pending network events for a controller to the global handler functions.
|
|
#*/
|
|
sq_register(vm, PeerNetUpdate, "PeerNetUpdate", _SC(".x"));
|
|
}
|
|
//------------------------------------------------------------------------------
|