1
0
Fork 0

cNetwork: Exported the Connect() method and cTCPLink class to Lua.

This commit is contained in:
Mattes D 2015-01-28 15:14:05 +01:00
parent e7424adbf4
commit 360c632e36
8 changed files with 614 additions and 1 deletions

View File

@ -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

View File

@ -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());

View File

@ -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);

229
src/Bindings/LuaTCPLink.cpp Normal file
View File

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

77
src/Bindings/LuaTCPLink.h Normal file
View File

@ -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
};

View File

@ -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);
}

View File

@ -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);

View File

@ -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<cLuaTCPLink>(*Plugin, 4);
// Try to connect:
bool res = cNetwork::Connect(Host, static_cast<UInt16>(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<cLuaTCPLink **>(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<cLuaTCPLink **>(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<cLuaTCPLink **>(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<cLuaTCPLink **>(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<cLuaTCPLink **>(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);
}