From 360c632e36acfe8b271c3212feef9b6f93623ba1 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 28 Jan 2015 15:14:05 +0100 Subject: cNetwork: Exported the Connect() method and cTCPLink class to Lua. --- src/Bindings/CMakeLists.txt | 3 + src/Bindings/LuaState.cpp | 12 ++ src/Bindings/LuaState.h | 2 + src/Bindings/LuaTCPLink.cpp | 229 ++++++++++++++++++++++++++ src/Bindings/LuaTCPLink.h | 77 +++++++++ src/Bindings/ManualBindings.cpp | 3 +- src/Bindings/ManualBindings.h | 10 ++ src/Bindings/ManualBindings_Network.cpp | 279 ++++++++++++++++++++++++++++++++ 8 files changed, 614 insertions(+), 1 deletion(-) create mode 100644 src/Bindings/LuaTCPLink.cpp create mode 100644 src/Bindings/LuaTCPLink.h create mode 100644 src/Bindings/ManualBindings_Network.cpp (limited to 'src') diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt index d47579cd6..a72611f76 100644 --- a/src/Bindings/CMakeLists.txt +++ b/src/Bindings/CMakeLists.txt @@ -9,8 +9,10 @@ SET (SRCS DeprecatedBindings.cpp LuaChunkStay.cpp LuaState.cpp + LuaTCPLink.cpp LuaWindow.cpp ManualBindings.cpp + ManualBindings_Network.cpp ManualBindings_RankManager.cpp Plugin.cpp PluginLua.cpp @@ -24,6 +26,7 @@ SET (HDRS LuaChunkStay.h LuaFunctions.h LuaState.h + LuaTCPLink.h LuaWindow.h ManualBindings.h Plugin.h diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index 01d3ac687..4de34c88d 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -656,6 +656,18 @@ void cLuaState::Push(cItems * a_Items) +void cLuaState::Push(cLuaTCPLink * a_TCPLink) +{ + ASSERT(IsValid()); + + tolua_pushusertype(m_LuaState, a_TCPLink, "cTCPLink"); + m_NumCurrentFunctionArgs += 1; +} + + + + + void cLuaState::Push(cMonster * a_Monster) { ASSERT(IsValid()); diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index 97e6b47e1..0dcd248fe 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -59,6 +59,7 @@ class cTNTEntity; class cHopperEntity; class cBlockEntity; class cBoundingBox; +class cLuaTCPLink; typedef cBoundingBox * pBoundingBox; typedef cWorld * pWorld; @@ -202,6 +203,7 @@ public: void Push(cHopperEntity * a_Hopper); void Push(cItem * a_Item); void Push(cItems * a_Items); + void Push(cLuaTCPLink * a_TCPLink); void Push(cMonster * a_Monster); void Push(cPickup * a_Pickup); void Push(cPlayer * a_Player); diff --git a/src/Bindings/LuaTCPLink.cpp b/src/Bindings/LuaTCPLink.cpp new file mode 100644 index 000000000..f88aeff84 --- /dev/null +++ b/src/Bindings/LuaTCPLink.cpp @@ -0,0 +1,229 @@ + +// LuaTCPLink.cpp + +// Implements the cLuaTCPLink class representing a Lua wrapper for the cTCPLink class and the callbacks it needs + +#include "Globals.h" +#include "LuaTCPLink.h" + + + + + +cLuaTCPLink::cLuaTCPLink(cPluginLua & a_Plugin, int a_CallbacksTableStackPos): + m_Plugin(a_Plugin), + m_Callbacks(a_Plugin.GetLuaState(), a_CallbacksTableStackPos) +{ +} + + + + + +bool cLuaTCPLink::Send(const AString & a_Data) +{ + // Safely grab a copy of the link: + cTCPLinkPtr Link = m_Link; + if (Link == nullptr) + { + return false; + } + + // Send the data: + return Link->Send(a_Data); +} + + + + + +AString cLuaTCPLink::GetLocalIP(void) const +{ + // Safely grab a copy of the link: + cTCPLinkPtr Link = m_Link; + if (Link == nullptr) + { + return ""; + } + + // Get the IP address: + return Link->GetLocalIP(); +} + + + + + +UInt16 cLuaTCPLink::GetLocalPort(void) const +{ + // Safely grab a copy of the link: + cTCPLinkPtr Link = m_Link; + if (Link == nullptr) + { + return 0; + } + + // Get the port: + return Link->GetLocalPort(); +} + + + + + +AString cLuaTCPLink::GetRemoteIP(void) const +{ + // Safely grab a copy of the link: + cTCPLinkPtr Link = m_Link; + if (Link == nullptr) + { + return ""; + } + + // Get the IP address: + return Link->GetRemoteIP(); +} + + + + + +UInt16 cLuaTCPLink::GetRemotePort(void) const +{ + // Safely grab a copy of the link: + cTCPLinkPtr Link = m_Link; + if (Link == nullptr) + { + return 0; + } + + // Get the port: + return Link->GetRemotePort(); +} + + + + + +void cLuaTCPLink::Shutdown(void) +{ + // Safely grab a copy of the link: + cTCPLinkPtr Link = m_Link; + if (Link == nullptr) + { + return; + } + + // Shutdown: + Link->Shutdown(); +} + + + + + +void cLuaTCPLink::Close(void) +{ + // Safely grab a copy of the link: + cTCPLinkPtr Link = m_Link; + if (Link == nullptr) + { + return; + } + + // Close the link: + Link->Close(); +} + +void cLuaTCPLink::OnConnected(cTCPLink & a_Link) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Call the callback: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnConnected"), this)) + { + LOGINFO("cTCPLink OnConnected() callback failed in plugin %s.", m_Plugin.GetName().c_str()); + } +} + + + + + +void cLuaTCPLink::OnError(int a_ErrorCode, const AString & a_ErrorMsg) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Call the callback: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnError"), this, a_ErrorCode, a_ErrorMsg)) + { + LOGINFO("cTCPLink OnError() callback failed in plugin %s; the link error is %d (%s).", + m_Plugin.GetName().c_str(), a_ErrorCode, a_ErrorMsg.c_str() + ); + } +} + + + + + +void cLuaTCPLink::OnLinkCreated(cTCPLinkPtr a_Link) +{ + // Store the cTCPLink for later use: + m_Link = a_Link; +} + + + + + +void cLuaTCPLink::OnReceivedData(const char * a_Data, size_t a_Length) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Call the callback: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnReceivedData"), this, AString(a_Data, a_Length))) + { + LOGINFO("cTCPLink OnReceivedData callback failed in plugin %s.", m_Plugin.GetName().c_str()); + } +} + + + + + +void cLuaTCPLink::OnRemoteClosed(void) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Call the callback: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnRemoteClosed"), this)) + { + LOGINFO("cTCPLink OnRemoteClosed() callback failed in plugin %s.", m_Plugin.GetName().c_str()); + } + m_Link.reset(); +} + + + + diff --git a/src/Bindings/LuaTCPLink.h b/src/Bindings/LuaTCPLink.h new file mode 100644 index 000000000..54c1d2dbf --- /dev/null +++ b/src/Bindings/LuaTCPLink.h @@ -0,0 +1,77 @@ + +// LuaTCPLink.h + +// Declares the cLuaTCPLink class representing a Lua wrapper for the cTCPLink class and the callbacks it needs + + + + + +#pragma once + +#include "../OSSupport/Network.h" +#include "LuaState.h" +#include "PluginLua.h" + + + + + +class cLuaTCPLink: + public cNetwork::cConnectCallbacks, + public cTCPLink::cCallbacks +{ +public: + /** Creates a new instance of the link, attached to the specified lua state and wrapping the callbacks that are in a table at the specified stack pos. */ + cLuaTCPLink(cPluginLua & a_Plugin, int a_CallbacksTableStackPos); + + /** Sends the data contained in the string to the remote peer. + Returns true if successful, false on immediate failure (queueing the data failed or link not available). */ + bool Send(const AString & a_Data); + + /** Returns the IP address of the local endpoint of the connection. */ + AString GetLocalIP(void) const; + + /** Returns the port used by the local endpoint of the connection. */ + UInt16 GetLocalPort(void) const; + + /** Returns the IP address of the remote endpoint of the connection. */ + AString GetRemoteIP(void) const; + + /** Returns the port used by the remote endpoint of the connection. */ + UInt16 GetRemotePort(void) const; + + /** Closes the link gracefully. + The link will send any queued outgoing data, then it will send the FIN packet. + The link will still receive incoming data from remote until the remote closes the connection. */ + void Shutdown(void); + + /** Drops the connection without any more processing. + Sends the RST packet, queued outgoing and incoming data is lost. */ + void Close(void); + +protected: + /** The plugin for which the link is created. */ + cPluginLua & m_Plugin; + + /** The Lua table that holds the callbacks to be invoked. */ + cLuaState::cRef m_Callbacks; + + /** The underlying link representing the connection. + May be nullptr. */ + cTCPLinkPtr m_Link; + + // cNetwork::cConnectCallbacks overrides: + virtual void OnConnected(cTCPLink & a_Link) override; + virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; + + // cTCPLink::cCallbacks overrides: + virtual void OnLinkCreated(cTCPLinkPtr a_Link) override; + virtual void OnReceivedData(const char * a_Data, size_t a_Length) override; + virtual void OnRemoteClosed(void) override; + // The OnError() callback is shared with cNetwork::cConnectCallbacks +}; + + + + diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 56f2e73bc..24e3f0052 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -256,7 +256,7 @@ static int tolua_Base64Decode(lua_State * tolua_S) -static cPluginLua * GetLuaPlugin(lua_State * L) +cPluginLua * GetLuaPlugin(lua_State * L) { // Get the plugin identification out of LuaState: lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME); @@ -3556,6 +3556,7 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "md5", tolua_md5); BindRankManager(tolua_S); + BindNetwork(tolua_S); tolua_endmodule(tolua_S); } diff --git a/src/Bindings/ManualBindings.h b/src/Bindings/ManualBindings.h index 1b6e65654..74d24d5f5 100644 --- a/src/Bindings/ManualBindings.h +++ b/src/Bindings/ManualBindings.h @@ -1,6 +1,7 @@ #pragma once struct lua_State; +class cPluginLua; @@ -17,8 +18,17 @@ protected: /** Binds the manually implemented cRankManager glue code to tolua_S. Implemented in ManualBindings_RankManager.cpp. */ static void BindRankManager(lua_State * tolua_S); + + /** Binds the manually implemented cNetwork-related API to tolua_S. + Implemented in ManualBindings_Network.cpp. */ + static void BindNetwork(lua_State * tolua_S); }; +extern cPluginLua * GetLuaPlugin(lua_State * L); + + + + diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp new file mode 100644 index 000000000..882af4e9e --- /dev/null +++ b/src/Bindings/ManualBindings_Network.cpp @@ -0,0 +1,279 @@ + +// ManualBindings_Network.cpp + +// Implements the cNetwork-related API bindings for Lua + +#include "Globals.h" +#include "LuaTCPLink.h" +#include "ManualBindings.h" +#include "tolua++/include/tolua++.h" +#include "LuaState.h" +#include "LuaTCPLink.h" + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cNetwork API functions: + +/** Binds cNetwork::Connect */ +static int tolua_cNetwork_Connect(lua_State * L) +{ + // Function signature: + // cNetwork:Connect(Host, Port, Callbacks) -> bool + + cLuaState S(L); + if ( + !S.CheckParamUserTable(1, "cNetwork") || + !S.CheckParamString(2) || + !S.CheckParamNumber(3) || + !S.CheckParamTable(4) || + !S.CheckParamEnd(5) + ) + { + return 0; + } + + // Get the plugin instance: + cPluginLua * Plugin = GetLuaPlugin(L); + if (Plugin == nullptr) + { + // An error message has been already printed in GetLuaPlugin() + S.Push(false); + return 1; + } + + // Read the params: + AString Host; + int Port; + S.GetStackValues(2, Host, Port); + + // Check validity: + if ((Port < 0) || (Port > 65535)) + { + LOGWARNING("cNetwork:Connect() called with invalid port (%d), failing the request.", Port); + S.Push(false); + return 1; + } + + // Create the LuaTCPLink glue class: + auto Link = std::make_shared(*Plugin, 4); + + // Try to connect: + bool res = cNetwork::Connect(Host, static_cast(Port), Link, Link); + S.Push(res); + + return 1; +} + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cTCPLink bindings (routed through cLuaTCPLink): + +static int tolua_cTCPLink_Send(lua_State * L) +{ + // Function signature: + // LinkInstance:Send(DataString) -> bool + + cLuaState S(L); + if ( + !S.CheckParamUserType(1, "cTCPLink") || + !S.CheckParamString(2) || + !S.CheckParamEnd(3) + ) + { + return 0; + } + + // Get the link: + cLuaTCPLink * Link; + if (lua_isnil(L, 1)) + { + LOGWARNING("cTCPLink:Send(): invalid link object. Stack trace:"); + S.LogStackTrace(); + return 0; + } + Link = *static_cast(lua_touserdata(L, 1)); + + // Get the data to send: + AString Data; + S.GetStackValues(2, Data); + + // Send the data: + Link->Send(Data); + return 0; +} + + + + + +static int tolua_cTCPLink_GetLocalIP(lua_State * L) +{ + // Function signature: + // LinkInstance:GetLocalIP() -> string + + cLuaState S(L); + if ( + !S.CheckParamUserType(1, "cTCPLink") || + !S.CheckParamEnd(2) + ) + { + return 0; + } + + // Get the link: + cLuaTCPLink * Link; + if (lua_isnil(L, 1)) + { + LOGWARNING("cTCPLink:GetLocalIP(): invalid link object. Stack trace:"); + S.LogStackTrace(); + return 0; + } + Link = *static_cast(lua_touserdata(L, 1)); + + // Get the IP: + S.Push(Link->GetLocalIP()); + return 1; +} + + + + + +static int tolua_cTCPLink_GetLocalPort(lua_State * L) +{ + // Function signature: + // LinkInstance:GetLocalPort() -> number + + cLuaState S(L); + if ( + !S.CheckParamUserType(1, "cTCPLink") || + !S.CheckParamEnd(2) + ) + { + return 0; + } + + // Get the link: + cLuaTCPLink * Link; + if (lua_isnil(L, 1)) + { + LOGWARNING("cTCPLink:GetLocalPort(): invalid link object. Stack trace:"); + S.LogStackTrace(); + return 0; + } + Link = *static_cast(lua_touserdata(L, 1)); + + // Get the Port: + S.Push(Link->GetLocalPort()); + return 1; +} + + + + + +static int tolua_cTCPLink_GetRemoteIP(lua_State * L) +{ + // Function signature: + // LinkInstance:GetRemoteIP() -> string + + cLuaState S(L); + if ( + !S.CheckParamUserType(1, "cTCPLink") || + !S.CheckParamEnd(2) + ) + { + return 0; + } + + // Get the link: + cLuaTCPLink * Link; + if (lua_isnil(L, 1)) + { + LOGWARNING("cTCPLink:GetRemoteIP(): invalid link object. Stack trace:"); + S.LogStackTrace(); + return 0; + } + Link = *static_cast(lua_touserdata(L, 1)); + + // Get the IP: + S.Push(Link->GetRemoteIP()); + return 1; +} + + + + + +static int tolua_cTCPLink_GetRemotePort(lua_State * L) +{ + // Function signature: + // LinkInstance:GetRemotePort() -> number + + cLuaState S(L); + if ( + !S.CheckParamUserType(1, "cTCPLink") || + !S.CheckParamEnd(2) + ) + { + return 0; + } + + // Get the link: + cLuaTCPLink * Link; + if (lua_isnil(L, 1)) + { + LOGWARNING("cTCPLink:GetRemotePort(): invalid link object. Stack trace:"); + S.LogStackTrace(); + return 0; + } + Link = *static_cast(lua_touserdata(L, 1)); + + // Get the Port: + S.Push(Link->GetRemotePort()); + return 1; +} + + + + + +//////////////////////////////////////////////////////////////////////////////// +// Register the bindings: + +void ManualBindings::BindNetwork(lua_State * tolua_S) +{ + // Create the cNetwork API classes: + tolua_usertype(tolua_S, "cNetwork"); + tolua_cclass(tolua_S, "cNetwork", "cNetwork", "", nullptr); + tolua_usertype(tolua_S, "cTCPLink"); + tolua_cclass(tolua_S, "cTCPLink", "cTCPLink", "", nullptr); + + // Fill in the functions (alpha-sorted): + tolua_beginmodule(tolua_S, "cNetwork"); + tolua_function(tolua_S, "Connect", tolua_cNetwork_Connect); + /* + tolua_function(tolua_S, "HostnameToIP", tolua_cNetwork_HostnameToIP); + tolua_function(tolua_S, "IPToHostname", tolua_cNetwork_IPToHostname); + tolua_function(tolua_S, "Listen", tolua_cNetwork_Listen); + */ + tolua_endmodule(tolua_S); + + tolua_beginmodule(tolua_S, "cTCPLink"); + tolua_function(tolua_S, "Send", tolua_cTCPLink_Send); + tolua_function(tolua_S, "GetLocalIP", tolua_cTCPLink_GetLocalIP); + tolua_function(tolua_S, "GetLocalPort", tolua_cTCPLink_GetLocalPort); + tolua_function(tolua_S, "GetRemoteIP", tolua_cTCPLink_GetRemoteIP); + tolua_function(tolua_S, "GetRemotePort", tolua_cTCPLink_GetRemotePort); + tolua_endmodule(tolua_S); +} + + + + -- cgit v1.2.3 From e098728fa8986aea8997a183839c8fc91c4775f8 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 28 Jan 2015 15:14:35 +0100 Subject: cTCPLink: Fixed missing addresses on link connection. --- src/OSSupport/TCPLinkImpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/OSSupport/TCPLinkImpl.cpp b/src/OSSupport/TCPLinkImpl.cpp index f97db7582..88fb57838 100644 --- a/src/OSSupport/TCPLinkImpl.cpp +++ b/src/OSSupport/TCPLinkImpl.cpp @@ -221,6 +221,8 @@ void cTCPLinkImpl::EventCallback(bufferevent * a_BufferEvent, short a_What, void // Pending connection succeeded, call the connection callback: if (a_What & BEV_EVENT_CONNECTED) { + Self->UpdateLocalAddress(); + Self->UpdateRemoteAddress(); if (Self->m_ConnectCallbacks != nullptr) { Self->m_ConnectCallbacks->OnConnected(*Self); @@ -228,8 +230,6 @@ void cTCPLinkImpl::EventCallback(bufferevent * a_BufferEvent, short a_What, void Self->m_ConnectCallbacks.reset(); return; } - Self->UpdateLocalAddress(); - Self->UpdateRemoteAddress(); } // If the connection has been closed, call the link callback and remove the connection: -- cgit v1.2.3 From 17498a97a289119debdb651ab898ddea99e86ff9 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 29 Jan 2015 11:09:56 +0100 Subject: cNetwork: Exported lookup functions to Lua API. Also added an example in the NetworkTest plugin. --- src/Bindings/CMakeLists.txt | 2 + src/Bindings/LuaNameLookup.cpp | 88 +++++++++++++++++++++++++++++++++ src/Bindings/LuaNameLookup.h | 46 +++++++++++++++++ src/Bindings/LuaTCPLink.h | 3 +- src/Bindings/ManualBindings_Network.cpp | 83 ++++++++++++++++++++++++++++++- 5 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 src/Bindings/LuaNameLookup.cpp create mode 100644 src/Bindings/LuaNameLookup.h (limited to 'src') diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt index a72611f76..13428b5c6 100644 --- a/src/Bindings/CMakeLists.txt +++ b/src/Bindings/CMakeLists.txt @@ -8,6 +8,7 @@ SET (SRCS Bindings.cpp DeprecatedBindings.cpp LuaChunkStay.cpp + LuaNameLookup.cpp LuaState.cpp LuaTCPLink.cpp LuaWindow.cpp @@ -25,6 +26,7 @@ SET (HDRS DeprecatedBindings.h LuaChunkStay.h LuaFunctions.h + LuaNameLookup.h LuaState.h LuaTCPLink.h LuaWindow.h diff --git a/src/Bindings/LuaNameLookup.cpp b/src/Bindings/LuaNameLookup.cpp new file mode 100644 index 000000000..e52d8dbdc --- /dev/null +++ b/src/Bindings/LuaNameLookup.cpp @@ -0,0 +1,88 @@ + +// LuaNameLookup.cpp + +// Implements the cLuaNameLookup class used as the cNetwork API callbacks for name and IP lookups from Lua + +#include "Globals.h" +#include "LuaNameLookup.h" + + + + + +cLuaNameLookup::cLuaNameLookup(const AString & a_Query, cPluginLua & a_Plugin, int a_CallbacksTableStackPos): + m_Plugin(a_Plugin), + m_Callbacks(a_Plugin.GetLuaState(), a_CallbacksTableStackPos), + m_Query(a_Query) +{ +} + + + + + +void cLuaNameLookup::OnNameResolved(const AString & a_Name, const AString & a_IP) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Call the callback: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnNameResolved"), a_Name, a_IP)) + { + LOGINFO("cNetwork name lookup OnNameResolved callback failed in plugin %s looking up %s. %s resolves to %s.", + m_Plugin.GetName().c_str(), m_Query.c_str(), a_Name.c_str(), a_IP.c_str() + ); + } +} + + + + + +void cLuaNameLookup::OnError(int a_ErrorCode, const AString & a_ErrorMsg) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Call the callback: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnError"), m_Query, a_ErrorCode, a_ErrorMsg)) + { + LOGINFO("cNetwork name lookup OnError callback failed in plugin %s looking up %s. The error is %d (%s)", + m_Plugin.GetName().c_str(), m_Query.c_str(), a_ErrorCode, a_ErrorMsg.c_str() + ); + } +} + + + + + +void cLuaNameLookup::OnFinished(void) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Call the callback: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnFinished"), m_Query)) + { + LOGINFO("cNetwork name lookup OnFinished callback failed in plugin %s, looking up %s.", + m_Plugin.GetName().c_str(), m_Query.c_str() + ); + } +} + + + + diff --git a/src/Bindings/LuaNameLookup.h b/src/Bindings/LuaNameLookup.h new file mode 100644 index 000000000..8b456ad90 --- /dev/null +++ b/src/Bindings/LuaNameLookup.h @@ -0,0 +1,46 @@ + +// LuaNameLookup.h + +// Declares the cLuaNameLookup class used as the cNetwork API callbacks for name and IP lookups from Lua + + + + + +#pragma once + +#include "../OSSupport/Network.h" +#include "PluginLua.h" + + + + + +class cLuaNameLookup: + public cNetwork::cResolveNameCallbacks +{ +public: + /** Creates a new instance of the lookup callbacks for the specified query, + attached to the specified lua plugin and wrapping the callbacks that are in a table at the specified stack pos. */ + cLuaNameLookup(const AString & a_Query, cPluginLua & a_Plugin, int a_CallbacksTableStackPos); + +protected: + /** The plugin for which the link is created. */ + cPluginLua & m_Plugin; + + /** The Lua table that holds the callbacks to be invoked. */ + cLuaState::cRef m_Callbacks; + + /** The query used to start the lookup (either hostname or IP). */ + AString m_Query; + + + // cNetwork::cResolveNameCallbacks overrides: + virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) override; + virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; + virtual void OnFinished(void) override; +}; + + + + diff --git a/src/Bindings/LuaTCPLink.h b/src/Bindings/LuaTCPLink.h index 54c1d2dbf..125cc1b31 100644 --- a/src/Bindings/LuaTCPLink.h +++ b/src/Bindings/LuaTCPLink.h @@ -10,7 +10,6 @@ #pragma once #include "../OSSupport/Network.h" -#include "LuaState.h" #include "PluginLua.h" @@ -22,7 +21,7 @@ class cLuaTCPLink: public cTCPLink::cCallbacks { public: - /** Creates a new instance of the link, attached to the specified lua state and wrapping the callbacks that are in a table at the specified stack pos. */ + /** Creates a new instance of the link, attached to the specified plugin and wrapping the callbacks that are in a table at the specified stack pos. */ cLuaTCPLink(cPluginLua & a_Plugin, int a_CallbacksTableStackPos); /** Sends the data contained in the string to the remote peer. diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp index 882af4e9e..3123ef885 100644 --- a/src/Bindings/ManualBindings_Network.cpp +++ b/src/Bindings/ManualBindings_Network.cpp @@ -9,6 +9,7 @@ #include "tolua++/include/tolua++.h" #include "LuaState.h" #include "LuaTCPLink.h" +#include "LuaNameLookup.h" @@ -71,6 +72,86 @@ static int tolua_cNetwork_Connect(lua_State * L) +static int tolua_cNetwork_HostnameToIP(lua_State * L) +{ + // Function signature: + // cNetwork:HostnameToIP(Host, Callbacks) -> bool + + cLuaState S(L); + if ( + !S.CheckParamUserTable(1, "cNetwork") || + !S.CheckParamString(2) || + !S.CheckParamTable(3) || + !S.CheckParamEnd(4) + ) + { + return 0; + } + + // Get the plugin instance: + cPluginLua * Plugin = GetLuaPlugin(L); + if (Plugin == nullptr) + { + // An error message has been already printed in GetLuaPlugin() + S.Push(false); + return 1; + } + + // Read the params: + AString Host; + S.GetStackValue(2, Host); + + // Try to look up: + bool res = cNetwork::HostnameToIP(Host, std::make_shared(Host, *Plugin, 3)); + S.Push(res); + + return 1; +} + + + + + +static int tolua_cNetwork_IPToHostname(lua_State * L) +{ + // Function signature: + // cNetwork:IPToHostname(IP, Callbacks) -> bool + + cLuaState S(L); + if ( + !S.CheckParamUserTable(1, "cNetwork") || + !S.CheckParamString(2) || + !S.CheckParamTable(3) || + !S.CheckParamEnd(4) + ) + { + return 0; + } + + // Get the plugin instance: + cPluginLua * Plugin = GetLuaPlugin(L); + if (Plugin == nullptr) + { + // An error message has been already printed in GetLuaPlugin() + S.Push(false); + return 1; + } + + // Read the params: + AString Host; + S.GetStackValue(2, Host); + + // Try to look up: + bool res = cNetwork::IPToHostName(Host, std::make_shared(Host, *Plugin, 3)); + S.Push(res); + + return 1; +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cTCPLink bindings (routed through cLuaTCPLink): @@ -258,9 +339,9 @@ void ManualBindings::BindNetwork(lua_State * tolua_S) // Fill in the functions (alpha-sorted): tolua_beginmodule(tolua_S, "cNetwork"); tolua_function(tolua_S, "Connect", tolua_cNetwork_Connect); - /* tolua_function(tolua_S, "HostnameToIP", tolua_cNetwork_HostnameToIP); tolua_function(tolua_S, "IPToHostname", tolua_cNetwork_IPToHostname); + /* tolua_function(tolua_S, "Listen", tolua_cNetwork_Listen); */ tolua_endmodule(tolua_S); -- cgit v1.2.3 From 014b96adb33fa902072d9f35661bc4f5e7c323e8 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 30 Jan 2015 21:24:02 +0100 Subject: Exported cServerHandle and cNetwork:Listen to Lua. Also added an example to the NetworkTest plugin. --- src/Bindings/CMakeLists.txt | 2 + src/Bindings/LuaNameLookup.h | 2 +- src/Bindings/LuaServerHandle.cpp | 213 ++++++++++++++++++++++++++++++++ src/Bindings/LuaServerHandle.h | 89 +++++++++++++ src/Bindings/LuaState.cpp | 33 +++++ src/Bindings/LuaState.h | 9 ++ src/Bindings/LuaTCPLink.cpp | 97 +++++++++++++-- src/Bindings/LuaTCPLink.h | 21 ++++ src/Bindings/ManualBindings_Network.cpp | 157 ++++++++++++++++++++++- src/Globals.h | 1 + src/OSSupport/Network.h | 3 + 11 files changed, 613 insertions(+), 14 deletions(-) create mode 100644 src/Bindings/LuaServerHandle.cpp create mode 100644 src/Bindings/LuaServerHandle.h (limited to 'src') diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt index 13428b5c6..40b8d4bd9 100644 --- a/src/Bindings/CMakeLists.txt +++ b/src/Bindings/CMakeLists.txt @@ -9,6 +9,7 @@ SET (SRCS DeprecatedBindings.cpp LuaChunkStay.cpp LuaNameLookup.cpp + LuaServerHandle.cpp LuaState.cpp LuaTCPLink.cpp LuaWindow.cpp @@ -27,6 +28,7 @@ SET (HDRS LuaChunkStay.h LuaFunctions.h LuaNameLookup.h + LuaServerHandle.h LuaState.h LuaTCPLink.h LuaWindow.h diff --git a/src/Bindings/LuaNameLookup.h b/src/Bindings/LuaNameLookup.h index 8b456ad90..e4cdb9f53 100644 --- a/src/Bindings/LuaNameLookup.h +++ b/src/Bindings/LuaNameLookup.h @@ -25,7 +25,7 @@ public: cLuaNameLookup(const AString & a_Query, cPluginLua & a_Plugin, int a_CallbacksTableStackPos); protected: - /** The plugin for which the link is created. */ + /** The plugin for which the query is created. */ cPluginLua & m_Plugin; /** The Lua table that holds the callbacks to be invoked. */ diff --git a/src/Bindings/LuaServerHandle.cpp b/src/Bindings/LuaServerHandle.cpp new file mode 100644 index 000000000..7b82003bb --- /dev/null +++ b/src/Bindings/LuaServerHandle.cpp @@ -0,0 +1,213 @@ + +// LuaServerHandle.cpp + +// Implements the cLuaServerHandle class wrapping the cServerHandle functionality for Lua API + +#include "Globals.h" +#include "LuaServerHandle.h" +#include "LuaTCPLink.h" +#include "tolua++/include/tolua++.h" + + + + + +cLuaServerHandle::cLuaServerHandle(UInt16 a_Port, cPluginLua & a_Plugin, int a_CallbacksTableStackPos): + m_Plugin(a_Plugin), + m_Callbacks(a_Plugin.GetLuaState(), a_CallbacksTableStackPos), + m_Port(a_Port) +{ + LOGD("Creating LuaServerHandle at %p.", this); +} + + + + + + +cLuaServerHandle::~cLuaServerHandle() +{ + // If the server handle is still open, close it explicitly: + LOGD("Deleting LuaServerHandle at %p.", this); + Close(); +} + + + + + +void cLuaServerHandle::SetServerHandle(cServerHandlePtr a_ServerHandle, cLuaServerHandlePtr a_Self) +{ + ASSERT(m_ServerHandle == nullptr); // The handle can be set only once + + m_ServerHandle = a_ServerHandle; + m_Self = a_Self; +} + + + + + +void cLuaServerHandle::Close(void) +{ + LOGD("Closing LuaServerHandle at %p.", this); + + // Safely grab a copy of the server handle: + cServerHandlePtr ServerHandle = m_ServerHandle; + if (ServerHandle == nullptr) + { + return; + } + + // Close the underlying server handle: + ServerHandle->Close(); + + // Close all connections at this server: + cLuaTCPLinkPtrs Connections; + { + cCSLock Lock(m_CSConnections); + std::swap(Connections, m_Connections); + } + for (auto & conn: Connections) + { + conn->Close(); + } + Connections.clear(); + + // Allow the internal server handle to be deallocated: + m_ServerHandle.reset(); +} + + + + + +bool cLuaServerHandle::IsListening(void) +{ + // Safely grab a copy of the server handle: + cServerHandlePtr ServerHandle = m_ServerHandle; + if (ServerHandle == nullptr) + { + return false; + } + + // Query the underlying server handle: + return ServerHandle->IsListening(); +} + + + + + +void cLuaServerHandle::RemoveLink(cLuaTCPLink * a_Link) +{ + cCSLock Lock(m_CSConnections); + for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) + { + if (itr->get() == a_Link) + { + m_Connections.erase(itr); + break; + } + } // for itr - m_Connections[] +} + + + + + +void cLuaServerHandle::Release(void) +{ + // Close the server, if it isn't closed yet: + Close(); + + // Allow self to deallocate: + m_Self.reset(); +} + + + + + +cTCPLink::cCallbacksPtr cLuaServerHandle::OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) +{ + // If not valid anymore, drop the connection: + if (!m_Callbacks.IsValid()) + { + return nullptr; + } + + // Ask the plugin for link callbacks: + cPluginLua::cOperation Op(m_Plugin); + cLuaState::cRef LinkCallbacks; + if ( + !Op().Call(cLuaState::cTableRef(m_Callbacks, "OnIncomingConnection"), a_RemoteIPAddress, a_RemotePort, m_Port, cLuaState::Return, LinkCallbacks) || + !LinkCallbacks.IsValid() + ) + { + LOGINFO("cNetwork server (port %d) OnIncomingConnection callback failed in plugin %s. Dropping connection.", + m_Port, m_Plugin.GetName().c_str() + ); + return nullptr; + } + + // Create the link wrapper to use with the callbacks: + auto res = std::make_shared(m_Plugin, std::move(LinkCallbacks), m_Self); + + // Add the link to the list of our connections: + cCSLock Lock(m_CSConnections); + m_Connections.push_back(res); + + return res; +} + + + + + +void cLuaServerHandle::OnAccepted(cTCPLink & a_Link) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Notify the plugin: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnAccepted"), static_cast(a_Link.GetCallbacks().get()))) + { + LOGINFO("cNetwork server (port %d) OnAccepted callback failed in plugin %s, connection to %s:%d.", + m_Port, m_Plugin.GetName().c_str(), a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort() + ); + return; + } +} + + + + + +void cLuaServerHandle::OnError(int a_ErrorCode, const AString & a_ErrorMsg) +{ + // Check if we're still valid: + if (!m_Callbacks.IsValid()) + { + return; + } + + // Notify the plugin: + cPluginLua::cOperation Op(m_Plugin); + if (!Op().Call(cLuaState::cTableRef(m_Callbacks, "OnError"), a_ErrorCode, a_ErrorMsg)) + { + LOGINFO("cNetwork server (port %d) OnError callback failed in plugin %s. The error is %d (%s).", + m_Port, m_Plugin.GetName().c_str(), a_ErrorCode, a_ErrorMsg.c_str() + ); + return; + } +} + + + + + diff --git a/src/Bindings/LuaServerHandle.h b/src/Bindings/LuaServerHandle.h new file mode 100644 index 000000000..9325bca3e --- /dev/null +++ b/src/Bindings/LuaServerHandle.h @@ -0,0 +1,89 @@ + +// LuaServerHandle.h + +// Declares the cLuaServerHandle class wrapping the cServerHandle functionality for Lua API + + + + + +#pragma once + +#include "../OSSupport/Network.h" +#include "PluginLua.h" + + + + + +// fwd: +class cLuaTCPLink; +typedef SharedPtr cLuaTCPLinkPtr; +typedef std::vector cLuaTCPLinkPtrs; +class cLuaServerHandle; +typedef SharedPtr cLuaServerHandlePtr; + + + + +class cLuaServerHandle: + public cNetwork::cListenCallbacks +{ +public: + /** Creates a new instance of the server handle, + attached to the specified lua plugin and wrapping the (listen-) callbacks that are in a table at the specified stack pos. */ + cLuaServerHandle(UInt16 a_Port, cPluginLua & a_Plugin, int a_CallbacksTableStackPos); + + ~cLuaServerHandle(); + + /** Called by cNetwork::Listen()'s binding. + Sets the server handle around which this instance is wrapped, and a self SharedPtr for link management. */ + void SetServerHandle(cServerHandlePtr a_ServerHandle, cLuaServerHandlePtr a_Self); + + /** Terminates all connections and closes the listening socket. */ + void Close(void); + + /** Returns true if the server is currently listening. */ + bool IsListening(void); + + /** Removes the link from the list of links that the server is currently tracking. */ + void RemoveLink(cLuaTCPLink * a_Link); + + /** Called when Lua garbage-collects the object. + Releases the internal SharedPtr to self, so that the instance may be deallocated. */ + void Release(void); + +protected: + /** The plugin for which the server is created. */ + cPluginLua & m_Plugin; + + /** The Lua table that holds the callbacks to be invoked. */ + cLuaState::cRef m_Callbacks; + + /** The port on which the server is listening. + Used mainly for better error reporting. */ + UInt16 m_Port; + + /** The cServerHandle around which this instance is wrapped. */ + cServerHandlePtr m_ServerHandle; + + /** Protects m_Connections against multithreaded access. */ + cCriticalSection m_CSConnections; + + /** All connections that are currently active in this server. + Protected by m_CSConnections. */ + cLuaTCPLinkPtrs m_Connections; + + /** SharedPtr to self, given out to newly created links. */ + cLuaServerHandlePtr m_Self; + + + // cNetwork::cListenCallbacks overrides: + virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override; + virtual void OnAccepted(cTCPLink & a_Link) override; + virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; +}; + + + + diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index 4de34c88d..73b114599 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -656,6 +656,18 @@ void cLuaState::Push(cItems * a_Items) +void cLuaState::Push(cLuaServerHandle * a_ServerHandle) +{ + ASSERT(IsValid()); + + tolua_pushusertype(m_LuaState, a_ServerHandle, "cServerHandle"); + m_NumCurrentFunctionArgs += 1; +} + + + + + void cLuaState::Push(cLuaTCPLink * a_TCPLink) { ASSERT(IsValid()); @@ -970,6 +982,15 @@ void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal) +void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref) +{ + a_Ref.RefStack(*this, a_StackPos); +} + + + + + bool cLuaState::CallFunction(int a_NumResults) { ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first @@ -1539,6 +1560,18 @@ cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) : +cLuaState::cRef::cRef(cRef && a_FromRef): + m_LuaState(a_FromRef.m_LuaState), + m_Ref(a_FromRef.m_Ref) +{ + a_FromRef.m_LuaState = nullptr; + a_FromRef.m_Ref = LUA_REFNIL; +} + + + + + cLuaState::cRef::~cRef() { if (m_LuaState != nullptr) diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index 0dcd248fe..f68b022ea 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -60,6 +60,7 @@ class cHopperEntity; class cBlockEntity; class cBoundingBox; class cLuaTCPLink; +class cLuaServerHandle; typedef cBoundingBox * pBoundingBox; typedef cWorld * pWorld; @@ -84,6 +85,10 @@ public: /** Creates a reference in the specified LuaState for object at the specified StackPos */ cRef(cLuaState & a_LuaState, int a_StackPos); + + /** Moves the reference from the specified instance into a newly created instance. + The old instance is then "!IsValid()". */ + cRef(cRef && a_FromRef); ~cRef(); @@ -203,6 +208,7 @@ public: void Push(cHopperEntity * a_Hopper); void Push(cItem * a_Item); void Push(cItems * a_Items); + void Push(cLuaServerHandle * a_ServerHandle); void Push(cLuaTCPLink * a_TCPLink); void Push(cMonster * a_Monster); void Push(cPickup * a_Pickup); @@ -242,6 +248,9 @@ public: /** Retrieve value at a_StackPos, if it is a valid cWorld class. If not, a_Value is unchanged */ void GetStackValue(int a_StackPos, pWorld & a_Value); + + /** Store the value at a_StackPos as a reference. */ + void GetStackValue(int a_StackPos, cRef & a_Ref); /** Call the specified Lua function. Returns true if call succeeded, false if there was an error. diff --git a/src/Bindings/LuaTCPLink.cpp b/src/Bindings/LuaTCPLink.cpp index f88aeff84..6b8395806 100644 --- a/src/Bindings/LuaTCPLink.cpp +++ b/src/Bindings/LuaTCPLink.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "LuaTCPLink.h" +#include "LuaServerHandle.h" @@ -14,6 +15,47 @@ cLuaTCPLink::cLuaTCPLink(cPluginLua & a_Plugin, int a_CallbacksTableStackPos): m_Plugin(a_Plugin), m_Callbacks(a_Plugin.GetLuaState(), a_CallbacksTableStackPos) { + // Warn if the callbacks aren't valid: + if (!m_Callbacks.IsValid()) + { + LOGWARNING("cTCPLink in plugin %s: callbacks could not be retrieved", m_Plugin.GetName().c_str()); + cPluginLua::cOperation Op(m_Plugin); + Op().LogStackTrace(); + } +} + + + + + +cLuaTCPLink::cLuaTCPLink(cPluginLua & a_Plugin, cLuaState::cRef && a_CallbacksTableRef, cLuaServerHandleWPtr a_ServerHandle): + m_Plugin(a_Plugin), + m_Callbacks(std::move(a_CallbacksTableRef)), + m_Server(std::move(a_ServerHandle)) +{ + // Warn if the callbacks aren't valid: + if (!m_Callbacks.IsValid()) + { + LOGWARNING("cTCPLink in plugin %s: callbacks could not be retrieved", m_Plugin.GetName().c_str()); + cPluginLua::cOperation Op(m_Plugin); + Op().LogStackTrace(); + } +} + + + + + +cLuaTCPLink::~cLuaTCPLink() +{ + // If the link is still open, close it: + cTCPLinkPtr Link = m_Link; + if (Link != nullptr) + { + Link->Close(); + } + + Terminated(); } @@ -107,15 +149,14 @@ UInt16 cLuaTCPLink::GetRemotePort(void) const void cLuaTCPLink::Shutdown(void) { - // Safely grab a copy of the link: + // Safely grab a copy of the link and shut it down: cTCPLinkPtr Link = m_Link; - if (Link == nullptr) + if (Link != nullptr) { - return; + Link->Shutdown(); } - // Shutdown: - Link->Shutdown(); + Terminated(); } @@ -124,17 +165,48 @@ void cLuaTCPLink::Shutdown(void) void cLuaTCPLink::Close(void) { - // Safely grab a copy of the link: + // If the link is still open, close it: cTCPLinkPtr Link = m_Link; - if (Link == nullptr) + if (Link != nullptr) { - return; + Link->Close(); + } + + Terminated(); +} + + + + + +void cLuaTCPLink::Terminated(void) +{ + // Disable the callbacks: + if (m_Callbacks.IsValid()) + { + m_Callbacks.UnRef(); + } + + // If the managing server is still alive, let it know we're terminating: + auto Server = m_Server.lock(); + if (Server != nullptr) + { + Server->RemoveLink(this); } - // Close the link: - Link->Close(); + // If the link is still open, close it: + cTCPLinkPtr Link = m_Link; + if (Link != nullptr) + { + Link->Close(); + m_Link.reset(); + } } + + + + void cLuaTCPLink::OnConnected(cTCPLink & a_Link) { // Check if we're still valid: @@ -171,6 +243,8 @@ void cLuaTCPLink::OnError(int a_ErrorCode, const AString & a_ErrorMsg) m_Plugin.GetName().c_str(), a_ErrorCode, a_ErrorMsg.c_str() ); } + + Terminated(); } @@ -221,7 +295,8 @@ void cLuaTCPLink::OnRemoteClosed(void) { LOGINFO("cTCPLink OnRemoteClosed() callback failed in plugin %s.", m_Plugin.GetName().c_str()); } - m_Link.reset(); + + Terminated(); } diff --git a/src/Bindings/LuaTCPLink.h b/src/Bindings/LuaTCPLink.h index 125cc1b31..f2af911ec 100644 --- a/src/Bindings/LuaTCPLink.h +++ b/src/Bindings/LuaTCPLink.h @@ -16,6 +16,14 @@ +// fwd: +class cLuaServerHandle; +typedef WeakPtr cLuaServerHandleWPtr; + + + + + class cLuaTCPLink: public cNetwork::cConnectCallbacks, public cTCPLink::cCallbacks @@ -24,6 +32,11 @@ public: /** Creates a new instance of the link, attached to the specified plugin and wrapping the callbacks that are in a table at the specified stack pos. */ cLuaTCPLink(cPluginLua & a_Plugin, int a_CallbacksTableStackPos); + /** Creates a new instance of the link, attached to the specified plugin and wrapping the callbacks that are in the specified referenced table. */ + cLuaTCPLink(cPluginLua & a_Plugin, cLuaState::cRef && a_CallbacksTableRef, cLuaServerHandleWPtr a_Server); + + ~cLuaTCPLink(); + /** Sends the data contained in the string to the remote peer. Returns true if successful, false on immediate failure (queueing the data failed or link not available). */ bool Send(const AString & a_Data); @@ -60,6 +73,14 @@ protected: May be nullptr. */ cTCPLinkPtr m_Link; + /** The server that is responsible for this link, if any. */ + cLuaServerHandleWPtr m_Server; + + + /** Common code called when the link is considered as terminated. + Releases m_Link, m_Callbacks and this from m_Server, each when applicable. */ + void Terminated(void); + // cNetwork::cConnectCallbacks overrides: virtual void OnConnected(cTCPLink & a_Link) override; virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp index 3123ef885..24c8c73b8 100644 --- a/src/Bindings/ManualBindings_Network.cpp +++ b/src/Bindings/ManualBindings_Network.cpp @@ -10,6 +10,7 @@ #include "LuaState.h" #include "LuaTCPLink.h" #include "LuaNameLookup.h" +#include "LuaServerHandle.h" @@ -72,6 +73,7 @@ static int tolua_cNetwork_Connect(lua_State * L) +/** Binds cNetwork::HostnameToIP */ static int tolua_cNetwork_HostnameToIP(lua_State * L) { // Function signature: @@ -112,6 +114,7 @@ static int tolua_cNetwork_HostnameToIP(lua_State * L) +/** Binds cNetwork::IPToHostname */ static int tolua_cNetwork_IPToHostname(lua_State * L) { // Function signature: @@ -152,9 +155,66 @@ static int tolua_cNetwork_IPToHostname(lua_State * L) +/** Binds cNetwork::Listen */ +static int tolua_cNetwork_Listen(lua_State * L) +{ + // Function signature: + // cNetwork:Listen(Port, Callbacks) -> bool + + cLuaState S(L); + if ( + !S.CheckParamUserTable(1, "cNetwork") || + !S.CheckParamNumber(2) || + !S.CheckParamTable(3) || + !S.CheckParamEnd(4) + ) + { + return 0; + } + + // Get the plugin instance: + cPluginLua * Plugin = GetLuaPlugin(L); + if (Plugin == nullptr) + { + // An error message has been already printed in GetLuaPlugin() + S.Push(false); + return 1; + } + + // Read the params: + int Port; + S.GetStackValues(2, Port); + if ((Port < 0) || (Port > 65535)) + { + LOGWARNING("cNetwork:Listen() called with invalid port (%d), failing the request.", Port); + S.Push(false); + return 1; + } + UInt16 Port16 = static_cast(Port); + + // Create the LuaTCPLink glue class: + auto Srv = std::make_shared(Port16, *Plugin, 3); + + // Listen: + Srv->SetServerHandle(cNetwork::Listen(Port16, Srv), Srv); + + // Register the server to be garbage-collected by Lua: + tolua_pushusertype(L, Srv.get(), "cServerHandle"); + tolua_register_gc(L, lua_gettop(L)); + + // Return the server handle wrapper: + S.Push(Srv.get()); + return 1; +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cTCPLink bindings (routed through cLuaTCPLink): +/** Binds cLuaTCPLink::Send */ static int tolua_cTCPLink_Send(lua_State * L) { // Function signature: @@ -193,6 +253,7 @@ static int tolua_cTCPLink_Send(lua_State * L) +/** Binds cLuaTCPLink::GetLocalIP */ static int tolua_cTCPLink_GetLocalIP(lua_State * L) { // Function signature: @@ -226,6 +287,7 @@ static int tolua_cTCPLink_GetLocalIP(lua_State * L) +/** Binds cLuaTCPLink::GetLocalPort */ static int tolua_cTCPLink_GetLocalPort(lua_State * L) { // Function signature: @@ -259,6 +321,7 @@ static int tolua_cTCPLink_GetLocalPort(lua_State * L) +/** Binds cLuaTCPLink::GetRemoteIP */ static int tolua_cTCPLink_GetRemoteIP(lua_State * L) { // Function signature: @@ -292,6 +355,7 @@ static int tolua_cTCPLink_GetRemoteIP(lua_State * L) +/** Binds cLuaTCPLink::GetRemotePort */ static int tolua_cTCPLink_GetRemotePort(lua_State * L) { // Function signature: @@ -325,6 +389,90 @@ static int tolua_cTCPLink_GetRemotePort(lua_State * L) +//////////////////////////////////////////////////////////////////////////////// +// cServerHandle bindings (routed through cLuaServerHandle): + +/** Called when Lua destroys the object instance. +Close the server and let it deallocate on its own (it's in a SharedPtr). */ +static int tolua_collect_cServerHandle(lua_State * L) +{ + cLuaServerHandle * Srv = static_cast(tolua_tousertype(L, 1, nullptr)); + Srv->Release(); + return 0; +} + + + + + +/** Binds cLuaServerHandle::Close */ +static int tolua_cServerHandle_Close(lua_State * L) +{ + // Function signature: + // ServerInstance:Close() + + cLuaState S(L); + if ( + !S.CheckParamUserType(1, "cServerHandle") || + !S.CheckParamEnd(2) + ) + { + return 0; + } + + // Get the server handle: + cLuaServerHandle * Srv; + if (lua_isnil(L, 1)) + { + LOGWARNING("cServerHandle:Close(): invalid server handle object. Stack trace:"); + S.LogStackTrace(); + return 0; + } + Srv = *static_cast(lua_touserdata(L, 1)); + + // Close it: + Srv->Close(); + return 0; +} + + + + + +/** Binds cLuaServerHandle::IsListening */ +static int tolua_cServerHandle_IsListening(lua_State * L) +{ + // Function signature: + // ServerInstance:IsListening() -> bool + + cLuaState S(L); + if ( + !S.CheckParamUserType(1, "cServerHandle") || + !S.CheckParamEnd(2) + ) + { + return 0; + } + + // Get the server handle: + cLuaServerHandle * Srv; + if (lua_isnil(L, 1)) + { + LOGWARNING("cServerHandle:IsListening(): invalid server handle object. Stack trace:"); + S.LogStackTrace(); + return 0; + } + Srv = *static_cast(lua_touserdata(L, 1)); + + // Close it: + S.Push(Srv->IsListening()); + return 1; +} + + + + + //////////////////////////////////////////////////////////////////////////////// // Register the bindings: @@ -335,15 +483,15 @@ void ManualBindings::BindNetwork(lua_State * tolua_S) tolua_cclass(tolua_S, "cNetwork", "cNetwork", "", nullptr); tolua_usertype(tolua_S, "cTCPLink"); tolua_cclass(tolua_S, "cTCPLink", "cTCPLink", "", nullptr); + tolua_usertype(tolua_S, "cServerHandle"); + tolua_cclass(tolua_S, "cServerHandle", "cServerHandle", "", tolua_collect_cServerHandle); // Fill in the functions (alpha-sorted): tolua_beginmodule(tolua_S, "cNetwork"); tolua_function(tolua_S, "Connect", tolua_cNetwork_Connect); tolua_function(tolua_S, "HostnameToIP", tolua_cNetwork_HostnameToIP); tolua_function(tolua_S, "IPToHostname", tolua_cNetwork_IPToHostname); - /* tolua_function(tolua_S, "Listen", tolua_cNetwork_Listen); - */ tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cTCPLink"); @@ -353,6 +501,11 @@ void ManualBindings::BindNetwork(lua_State * tolua_S) tolua_function(tolua_S, "GetRemoteIP", tolua_cTCPLink_GetRemoteIP); tolua_function(tolua_S, "GetRemotePort", tolua_cTCPLink_GetRemotePort); tolua_endmodule(tolua_S); + + tolua_beginmodule(tolua_S, "cServerHandle"); + tolua_function(tolua_S, "Close", tolua_cServerHandle_Close); + tolua_function(tolua_S, "IsListening", tolua_cServerHandle_IsListening); + tolua_endmodule(tolua_S); } diff --git a/src/Globals.h b/src/Globals.h index 654ede95f..29eaac871 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -381,6 +381,7 @@ void inline LOG(const char * a_Format, ...) // Unified shared ptr from before C++11. Also no silly undercores. #define SharedPtr std::shared_ptr +#define WeakPtr std::weak_ptr diff --git a/src/OSSupport/Network.h b/src/OSSupport/Network.h index cdf6ba0e9..e883dfb29 100644 --- a/src/OSSupport/Network.h +++ b/src/OSSupport/Network.h @@ -90,6 +90,9 @@ public: Sends the RST packet, queued outgoing and incoming data is lost. */ virtual void Close(void) = 0; + /** Returns the callbacks that are used. */ + cCallbacksPtr GetCallbacks(void) const { return m_Callbacks; } + protected: /** Callbacks to be used for the various situations. */ cCallbacksPtr m_Callbacks; -- cgit v1.2.3 From 0e769f12ac39e1ef587c1eb7af549c553cd8a330 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 30 Jan 2015 23:08:09 +0100 Subject: LuaServerHandle: Removed debugging output. --- src/Bindings/LuaServerHandle.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/Bindings/LuaServerHandle.cpp b/src/Bindings/LuaServerHandle.cpp index 7b82003bb..a84f894b5 100644 --- a/src/Bindings/LuaServerHandle.cpp +++ b/src/Bindings/LuaServerHandle.cpp @@ -17,7 +17,6 @@ cLuaServerHandle::cLuaServerHandle(UInt16 a_Port, cPluginLua & a_Plugin, int a_C m_Callbacks(a_Plugin.GetLuaState(), a_CallbacksTableStackPos), m_Port(a_Port) { - LOGD("Creating LuaServerHandle at %p.", this); } @@ -28,7 +27,6 @@ cLuaServerHandle::cLuaServerHandle(UInt16 a_Port, cPluginLua & a_Plugin, int a_C cLuaServerHandle::~cLuaServerHandle() { // If the server handle is still open, close it explicitly: - LOGD("Deleting LuaServerHandle at %p.", this); Close(); } @@ -50,8 +48,6 @@ void cLuaServerHandle::SetServerHandle(cServerHandlePtr a_ServerHandle, cLuaServ void cLuaServerHandle::Close(void) { - LOGD("Closing LuaServerHandle at %p.", this); - // Safely grab a copy of the server handle: cServerHandlePtr ServerHandle = m_ServerHandle; if (ServerHandle == nullptr) -- cgit v1.2.3 From adf0020cd41f6a947ef883c582dde74d67255b1f Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 6 Feb 2015 18:44:05 +0100 Subject: APIDump: Added cNetwork documentation. --- src/Bindings/ManualBindings_Network.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp index 24c8c73b8..902f687c8 100644 --- a/src/Bindings/ManualBindings_Network.cpp +++ b/src/Bindings/ManualBindings_Network.cpp @@ -218,7 +218,7 @@ static int tolua_cNetwork_Listen(lua_State * L) static int tolua_cTCPLink_Send(lua_State * L) { // Function signature: - // LinkInstance:Send(DataString) -> bool + // LinkInstance:Send(DataString) cLuaState S(L); if ( -- cgit v1.2.3