/* ----------------------------------------------------------------------------- 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 &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 (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")); } //------------------------------------------------------------------------------