// 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" #include "LuaServerHandle.h" 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(); } 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 and shut it down: cTCPLinkPtr Link = m_Link; if (Link != nullptr) { Link->Shutdown(); } Terminated(); } void cLuaTCPLink::Close(void) { // If the link is still open, close it: cTCPLinkPtr Link = m_Link; if (Link != nullptr) { 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); } // 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: 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() ); } Terminated(); } 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()); } Terminated(); }