From 641cb063bc71acc7f29d25b12c8713a8beb2018c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 22 Aug 2016 19:53:34 +0200 Subject: cTCPLink supports TLS out of the box. --- src/Bindings/LuaTCPLink.cpp | 270 ++++---------------------------------------- src/Bindings/LuaTCPLink.h | 54 --------- 2 files changed, 25 insertions(+), 299 deletions(-) (limited to 'src/Bindings') diff --git a/src/Bindings/LuaTCPLink.cpp b/src/Bindings/LuaTCPLink.cpp index 466240a7d..905dfc5ac 100644 --- a/src/Bindings/LuaTCPLink.cpp +++ b/src/Bindings/LuaTCPLink.cpp @@ -6,6 +6,8 @@ #include "Globals.h" #include "LuaTCPLink.h" #include "LuaServerHandle.h" +#include "../PolarSSL++/X509Cert.h" +#include "../PolarSSL++/CryptoKey.h" @@ -48,13 +50,6 @@ cLuaTCPLink::~cLuaTCPLink() bool cLuaTCPLink::Send(const AString & a_Data) { - // If running in SSL mode, push the data into the SSL context instead: - if (m_SslContext != nullptr) - { - m_SslContext->Send(a_Data); - return true; - } - // Safely grab a copy of the link: auto link = m_Link; if (link == nullptr) @@ -144,12 +139,6 @@ void cLuaTCPLink::Shutdown(void) cTCPLinkPtr link = m_Link; if (link != nullptr) { - if (m_SslContext != nullptr) - { - m_SslContext->NotifyClose(); - m_SslContext->ResetSelf(); - m_SslContext.reset(); - } link->Shutdown(); } } @@ -164,12 +153,6 @@ void cLuaTCPLink::Close(void) cTCPLinkPtr link = m_Link; if (link != nullptr) { - if (m_SslContext != nullptr) - { - m_SslContext->NotifyClose(); - m_SslContext->ResetSelf(); - m_SslContext.reset(); - } link->Close(); } @@ -186,46 +169,31 @@ AString cLuaTCPLink::StartTLSClient( const AString & a_OwnPrivKeyPassword ) { - // Check preconditions: - if (m_SslContext != nullptr) - { - return "TLS is already active on this link"; - } - if ( - (a_OwnCertData.empty() && !a_OwnPrivKeyData.empty()) || - (!a_OwnCertData.empty() && a_OwnPrivKeyData.empty()) - ) - { - return "Either provide both the certificate and private key, or neither"; - } - - // Create the SSL context: - m_SslContext.reset(new cLinkSslContext(*this)); - m_SslContext->Initialize(true); - - // Create the peer cert, if required: - if (!a_OwnCertData.empty() && !a_OwnPrivKeyData.empty()) + auto link = m_Link; + if (link != nullptr) { - auto OwnCert = std::make_shared(); - int res = OwnCert->Parse(a_OwnCertData.data(), a_OwnCertData.size()); - if (res != 0) + cX509CertPtr ownCert; + if (!a_OwnCertData.empty()) { - m_SslContext.reset(); - return Printf("Cannot parse peer certificate: -0x%x", res); + ownCert = std::make_shared(); + auto res = ownCert->Parse(a_OwnCertData.data(), a_OwnCertData.size()); + if (res != 0) + { + return Printf("Cannot parse client certificate: -0x%x", res); + } } - auto OwnPrivKey = std::make_shared(); - res = OwnPrivKey->ParsePrivate(a_OwnPrivKeyData.data(), a_OwnPrivKeyData.size(), a_OwnPrivKeyPassword); - if (res != 0) + cCryptoKeyPtr ownPrivKey; + if (!a_OwnPrivKeyData.empty()) { - m_SslContext.reset(); - return Printf("Cannot parse peer private key: -0x%x", res); + ownPrivKey = std::make_shared(); + auto res = ownPrivKey->ParsePrivate(a_OwnPrivKeyData.data(), a_OwnPrivKeyData.size(), a_OwnPrivKeyPassword); + if (res != 0) + { + return Printf("Cannot parse client private key: -0x%x", res); + } } - m_SslContext->SetOwnCert(OwnCert, OwnPrivKey); + return link->StartTLSClient(ownCert, ownPrivKey); } - m_SslContext->SetSelf(cLinkSslContextWPtr(m_SslContext)); - - // Start the handshake: - m_SslContext->Handshake(); return ""; } @@ -240,43 +208,25 @@ AString cLuaTCPLink::StartTLSServer( const AString & a_StartTLSData ) { - // Check preconditions: - if (m_SslContext != nullptr) - { - return "TLS is already active on this link"; - } - if (a_OwnCertData.empty() || a_OwnPrivKeyData.empty()) + auto link = m_Link; + if (link != nullptr) { - return "Provide the server certificate and private key"; - } - - // Create the SSL context: - m_SslContext.reset(new cLinkSslContext(*this)); - m_SslContext->Initialize(false); - // Create the peer cert: auto OwnCert = std::make_shared(); int res = OwnCert->Parse(a_OwnCertData.data(), a_OwnCertData.size()); if (res != 0) { - m_SslContext.reset(); return Printf("Cannot parse server certificate: -0x%x", res); } auto OwnPrivKey = std::make_shared(); res = OwnPrivKey->ParsePrivate(a_OwnPrivKeyData.data(), a_OwnPrivKeyData.size(), a_OwnPrivKeyPassword); if (res != 0) { - m_SslContext.reset(); return Printf("Cannot parse server private key: -0x%x", res); } - m_SslContext->SetOwnCert(OwnCert, OwnPrivKey); - m_SslContext->SetSelf(cLinkSslContextWPtr(m_SslContext)); - // Push the initial data: - m_SslContext->StoreReceivedData(a_StartTLSData.data(), a_StartTLSData.size()); - - // Start the handshake: - m_SslContext->Handshake(); + return link->StartTLSServer(OwnCert, OwnPrivKey, a_StartTLSData); + } return ""; } @@ -308,9 +258,6 @@ void cLuaTCPLink::Terminated(void) m_Link.reset(); } } - - // If the SSL context still exists, free it: - m_SslContext.reset(); } @@ -362,14 +309,6 @@ void cLuaTCPLink::OnLinkCreated(cTCPLinkPtr a_Link) void cLuaTCPLink::OnReceivedData(const char * a_Data, size_t a_Length) { - // If we're running in SSL mode, put the data into the SSL decryptor: - auto sslContext = m_SslContext; - if (sslContext != nullptr) - { - sslContext->StoreReceivedData(a_Data, a_Length); - return; - } - // Call the callback: m_Callbacks->CallTableFn("OnReceivedData", this, AString(a_Data, a_Length)); } @@ -380,13 +319,6 @@ void cLuaTCPLink::OnReceivedData(const char * a_Data, size_t a_Length) void cLuaTCPLink::OnRemoteClosed(void) { - // If running in SSL mode and there's data left in the SSL contect, report it: - auto sslContext = m_SslContext; - if (sslContext != nullptr) - { - sslContext->FlushBuffers(); - } - // Call the callback: m_Callbacks->CallTableFn("OnRemoteClosed", this); @@ -398,155 +330,3 @@ void cLuaTCPLink::OnRemoteClosed(void) -//////////////////////////////////////////////////////////////////////////////// -// cLuaTCPLink::cLinkSslContext: - -cLuaTCPLink::cLinkSslContext::cLinkSslContext(cLuaTCPLink & a_Link): - m_Link(a_Link) -{ -} - - - - - -void cLuaTCPLink::cLinkSslContext::SetSelf(cLinkSslContextWPtr a_Self) -{ - m_Self = a_Self; -} - - - - - -void cLuaTCPLink::cLinkSslContext::ResetSelf(void) -{ - m_Self.reset(); -} - - - - - -void cLuaTCPLink::cLinkSslContext::StoreReceivedData(const char * a_Data, size_t a_NumBytes) -{ - // Hold self alive for the duration of this function - cLinkSslContextPtr Self(m_Self); - - m_EncryptedData.append(a_Data, a_NumBytes); - - // Try to finish a pending handshake: - TryFinishHandshaking(); - - // Flush any cleartext data that can be "received": - FlushBuffers(); -} - - - - - -void cLuaTCPLink::cLinkSslContext::FlushBuffers(void) -{ - // Hold self alive for the duration of this function - cLinkSslContextPtr Self(m_Self); - - // If the handshake didn't complete yet, bail out: - if (!HasHandshaken()) - { - return; - } - - char Buffer[1024]; - int NumBytes; - while ((NumBytes = ReadPlain(Buffer, sizeof(Buffer))) > 0) - { - m_Link.ReceivedCleartextData(Buffer, static_cast(NumBytes)); - if (m_Self.expired()) - { - // The callback closed the SSL context, bail out - return; - } - } -} - - - - - -void cLuaTCPLink::cLinkSslContext::TryFinishHandshaking(void) -{ - // Hold self alive for the duration of this function - cLinkSslContextPtr Self(m_Self); - - // If the handshake hasn't finished yet, retry: - if (!HasHandshaken()) - { - Handshake(); - } - - // If the handshake succeeded, write all the queued plaintext data: - if (HasHandshaken()) - { - WritePlain(m_CleartextData.data(), m_CleartextData.size()); - m_CleartextData.clear(); - } -} - - - - - -void cLuaTCPLink::cLinkSslContext::Send(const AString & a_Data) -{ - // Hold self alive for the duration of this function - cLinkSslContextPtr Self(m_Self); - - // If the handshake hasn't completed yet, queue the data: - if (!HasHandshaken()) - { - m_CleartextData.append(a_Data); - TryFinishHandshaking(); - return; - } - - // The connection is all set up, write the cleartext data into the SSL context: - WritePlain(a_Data.data(), a_Data.size()); - FlushBuffers(); -} - - - - - -int cLuaTCPLink::cLinkSslContext::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) -{ - // Hold self alive for the duration of this function - cLinkSslContextPtr Self(m_Self); - - // If there's nothing queued in the buffer, report empty buffer: - if (m_EncryptedData.empty()) - { - return POLARSSL_ERR_NET_WANT_READ; - } - - // Copy as much data as possible to the provided buffer: - size_t BytesToCopy = std::min(a_NumBytes, m_EncryptedData.size()); - memcpy(a_Buffer, m_EncryptedData.data(), BytesToCopy); - m_EncryptedData.erase(0, BytesToCopy); - return static_cast(BytesToCopy); -} - - - - - -int cLuaTCPLink::cLinkSslContext::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) -{ - m_Link.m_Link->Send(a_Buffer, a_NumBytes); - return static_cast(a_NumBytes); -} - - - - diff --git a/src/Bindings/LuaTCPLink.h b/src/Bindings/LuaTCPLink.h index b8c886ef8..f4ca67018 100644 --- a/src/Bindings/LuaTCPLink.h +++ b/src/Bindings/LuaTCPLink.h @@ -10,7 +10,6 @@ #pragma once #include "../OSSupport/Network.h" -#include "../PolarSSL++/SslContext.h" #include "LuaState.h" @@ -90,54 +89,6 @@ public: ); protected: - // fwd: - class cLinkSslContext; - typedef SharedPtr cLinkSslContextPtr; - typedef WeakPtr cLinkSslContextWPtr; - - /** Wrapper around cSslContext that is used when this link is being encrypted by SSL. */ - class cLinkSslContext : - public cSslContext - { - cLuaTCPLink & m_Link; - - /** Buffer for storing the incoming encrypted data until it is requested by the SSL decryptor. */ - AString m_EncryptedData; - - /** Buffer for storing the outgoing cleartext data until the link has finished handshaking. */ - AString m_CleartextData; - - /** Shared ownership of self, so that this object can keep itself alive for as long as it needs. */ - cLinkSslContextWPtr m_Self; - - public: - cLinkSslContext(cLuaTCPLink & a_Link); - - /** Shares ownership of self, so that this object can keep itself alive for as long as it needs. */ - void SetSelf(cLinkSslContextWPtr a_Self); - - /** Removes the self ownership so that we can detect the SSL closure. */ - void ResetSelf(void); - - /** Stores the specified block of data into the buffer of the data to be decrypted (incoming from remote). - Also flushes the SSL buffers by attempting to read any data through the SSL context. */ - void StoreReceivedData(const char * a_Data, size_t a_NumBytes); - - /** Tries to read any cleartext data available through the SSL, reports it in the link. */ - void FlushBuffers(void); - - /** Tries to finish handshaking the SSL. */ - void TryFinishHandshaking(void); - - /** Sends the specified cleartext data over the SSL to the remote peer. - If the handshake hasn't been completed yet, queues the data for sending when it completes. */ - void Send(const AString & a_Data); - - // cSslContext overrides: - virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override; - virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override; - }; - /** The Lua table that holds the callbacks to be invoked. */ cLuaState::cTableRefPtr m_Callbacks; @@ -149,11 +100,6 @@ protected: /** The server that is responsible for this link, if any. */ cLuaServerHandleWPtr m_Server; - /** The SSL context used for encryption, if this link uses SSL. - If valid, the link uses encryption through this context. */ - cLinkSslContextPtr m_SslContext; - - /** 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); -- cgit v1.2.3 From 5ca371bb9a65cc322eb8327d81709985daefe173 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Tue, 23 Aug 2016 13:20:43 +0200 Subject: cUrlClient: Exported to Lua API. --- src/Bindings/LuaState.cpp | 11 ++ src/Bindings/LuaState.h | 24 +++ src/Bindings/ManualBindings_Network.cpp | 334 ++++++++++++++++++++++++++++++++ 3 files changed, 369 insertions(+) (limited to 'src/Bindings') diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index ec6bdb48a..81893c946 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -2139,6 +2139,17 @@ cLuaState * cLuaState::QueryCanonLuaState(void) +void cLuaState::LogApiCallParamFailure(const char * a_FnName, const char * a_ParamNames) +{ + LOGWARNING("%s: Cannot read params: %s, bailing out.", a_FnName, a_ParamNames); + LogStackTrace(); + LogStackValues("Values on the stack"); +} + + + + + int cLuaState::ReportFnCallErrors(lua_State * a_LuaState) { LOGWARNING("LUA: %s", lua_tostring(a_LuaState, -1)); diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index cb68b9a98..32d346a19 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -301,6 +301,26 @@ public: return cLuaState(m_Ref.GetLuaState()).CallTableFn(m_Ref, a_FnName, std::forward(args)...); } + /** Calls the Lua function stored under the specified name in the referenced table, if still available. + A "self" parameter is injected in front of all the given parameters and is set to the callback table. + Returns true if callback has been called. + Returns false if the Lua state isn't valid anymore, or the function doesn't exist. */ + template + bool CallTableFnWithSelf(const char * a_FnName, Args &&... args) + { + auto cs = m_CS; + if (cs == nullptr) + { + return false; + } + cCSLock Lock(*cs); + if (!m_Ref.IsValid()) + { + return false; + } + return cLuaState(m_Ref.GetLuaState()).CallTableFn(m_Ref, a_FnName, m_Ref, std::forward(args)...); + } + /** Set the contained reference to the table in the specified Lua state's stack position. If another table has been previously contained, it is unreferenced first. Returns true on success, false on failure (not a table at the specified stack pos). */ @@ -741,6 +761,10 @@ public: Returns nullptr if the canon Lua state cannot be queried. */ cLuaState * QueryCanonLuaState(void); + /** Outputs to log a warning about API call being unable to read its parameters from the stack, + logs the stack trace and stack values. */ + void LogApiCallParamFailure(const char * a_FnName, const char * a_ParamNames); + protected: cCriticalSection m_CS; diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp index c8565d23d..f59860938 100644 --- a/src/Bindings/ManualBindings_Network.cpp +++ b/src/Bindings/ManualBindings_Network.cpp @@ -2,6 +2,7 @@ // ManualBindings_Network.cpp // Implements the cNetwork-related API bindings for Lua +// Also implements the cUrlClient bindings #include "Globals.h" #include "LuaTCPLink.h" @@ -12,6 +13,7 @@ #include "LuaNameLookup.h" #include "LuaServerHandle.h" #include "LuaUDPEndpoint.h" +#include "../HTTP/UrlClient.h" @@ -903,6 +905,329 @@ static int tolua_cUDPEndpoint_Send(lua_State * L) +/** Used when the cUrlClient Lua request wants all the callbacks. +Maps each callback onto a Lua function callback in the callback table. */ +class cFullUrlClientCallbacks: + public cUrlClient::cCallbacks +{ +public: + /** Creates a new instance bound to the specified table of callbacks. */ + cFullUrlClientCallbacks(cLuaState::cTableRefPtr && a_Callbacks): + m_Callbacks(std::move(a_Callbacks)) + { + } + + + // cUrlClient::cCallbacks overrides: + virtual void OnConnected(cTCPLink & a_Link) override + { + // TODO: Cannot push a cTCPLink to Lua, need to translate via cLuaTCPLink + m_Callbacks->CallTableFnWithSelf("OnConnected", cLuaState::Nil, a_Link.GetRemoteIP(), a_Link.GetRemotePort()); + } + + + virtual bool OnCertificateReceived() override + { + // TODO: The received cert needs proper type specification from the underlying cUrlClient framework and in the Lua engine as well + bool res = true; + m_Callbacks->CallTableFnWithSelf("OnCertificateReceived", cLuaState::Return, res); + return res; + } + + + virtual void OnTlsHandshakeCompleted() override + { + m_Callbacks->CallTableFnWithSelf("OnTlsHandshakeCompleted"); + } + + + virtual void OnRequestSent() override + { + m_Callbacks->CallTableFnWithSelf("OnRequestSent"); + } + + + virtual void OnStatusLine(const AString & a_HttpVersion, int a_StatusCode, const AString & a_Rest) override + { + m_Callbacks->CallTableFnWithSelf("OnStatusLine", a_HttpVersion, a_StatusCode, a_Rest); + } + + + virtual void OnHeader(const AString & a_Key, const AString & a_Value) override + { + m_Callbacks->CallTableFnWithSelf("OnHeader", a_Key, a_Value); + m_Headers[a_Key] = a_Value; + } + + + virtual void OnHeadersFinished() override + { + m_Callbacks->CallTableFnWithSelf("OnHeadersFinished", m_Headers); + } + + + virtual void OnBodyData(const void * a_Data, size_t a_Size) override + { + m_Callbacks->CallTableFnWithSelf("OnBodyData", AString(reinterpret_cast(a_Data), a_Size)); + } + + + virtual void OnBodyFinished() override + { + m_Callbacks->CallTableFnWithSelf("OnBodyFinished"); + } + + + virtual void OnError(const AString & a_ErrorMsg) override + { + m_Callbacks->CallTableFnWithSelf("OnError", a_ErrorMsg); + } + + + virtual void OnRedirecting(const AString & a_NewLocation) override + { + m_Callbacks->CallTableFnWithSelf("OnRedirecting", a_NewLocation); + } + + +protected: + /** The Lua table containing the callbacks. */ + cLuaState::cTableRefPtr m_Callbacks; + + /** Accumulator for all the headers to be reported in the OnHeadersFinished() callback. */ + AStringMap m_Headers; +}; + + + + + +/** Used when the cUrlClient Lua request has just a single callback. +The callback is used to report the entire body at once, together with the HTTP headers, or to report an error: +callback("BodyContents", {headers}) +callback(nil, "ErrorMessage") +Accumulates the body contents into a single string until the body is finished. +Accumulates all HTTP headers into an AStringMap. */ +class cSimpleUrlClientCallbacks: + public cUrlClient::cCallbacks +{ +public: + /** Creates a new instance that uses the specified callback to report when request finishes. */ + cSimpleUrlClientCallbacks(cLuaState::cCallbackPtr && a_Callback): + m_Callback(std::move(a_Callback)) + { + } + + + virtual void OnHeader(const AString & a_Key, const AString & a_Value) override + { + m_Headers[a_Key] = a_Value; + } + + + virtual void OnBodyData(const void * a_Data, size_t a_Size) override + { + m_ResponseBody.append(reinterpret_cast(a_Data), a_Size); + } + + + virtual void OnBodyFinished() override + { + m_Callback->Call(m_ResponseBody, m_Headers); + } + + + virtual void OnError(const AString & a_ErrorMsg) override + { + m_Callback->Call(cLuaState::Nil, a_ErrorMsg); + } + + +protected: + + /** The callback to call when the request finishes. */ + cLuaState::cCallbackPtr m_Callback; + + /** The accumulator for the partial body data, so that OnBodyFinished() can send the entire thing at once. */ + AString m_ResponseBody; + + /** Accumulator for all the headers to be reported in the combined callback. */ + AStringMap m_Headers; +}; + + + + + +/** Common code shared among the cUrlClient request methods. +a_Method is the method name to be used in the request. +a_UrlStackIdx is the position on the Lua stack of the Url parameter. */ +static int tolua_cUrlClient_Request_Common(lua_State * a_LuaState, const AString & a_Method, int a_UrlStackIdx) +{ + // Check params: + cLuaState L(a_LuaState); + if (!L.CheckParamString(a_UrlStackIdx)) + { + return 0; + } + + // Read params: + AString url, requestBody; + AStringMap headers, options; + cLuaState::cTableRefPtr callbacks; + cLuaState::cCallbackPtr onCompleteBodyCallback; + if (!L.GetStackValues(a_UrlStackIdx, url)) + { + L.LogApiCallParamFailure("cUrlClient:Request()", Printf("URL (%d)", a_UrlStackIdx).c_str()); + L.Push(false); + L.Push("Invalid params"); + return 2; + } + cUrlClient::cCallbacksPtr urlClientCallbacks; + if (lua_istable(L, a_UrlStackIdx + 1)) + { + if (!L.GetStackValue(a_UrlStackIdx + 1, callbacks)) + { + L.LogApiCallParamFailure("cUrlClient:Request()", Printf("CallbacksTable (%d)", a_UrlStackIdx + 1).c_str()); + L.Push(false); + L.Push("Invalid Callbacks param"); + return 2; + } + urlClientCallbacks = cpp14::make_unique(std::move(callbacks)); + } + else if (lua_isfunction(L, a_UrlStackIdx + 1)) + { + if (!L.GetStackValue(a_UrlStackIdx + 1, onCompleteBodyCallback)) + { + L.LogApiCallParamFailure("cUrlClient:Request()", Printf("CallbacksFn (%d)", a_UrlStackIdx + 1).c_str()); + L.Push(false); + L.Push("Invalid OnCompleteBodyCallback param"); + return 2; + } + urlClientCallbacks = cpp14::make_unique(std::move(onCompleteBodyCallback)); + } + else + { + L.LogApiCallParamFailure("cUrlClient:Request()", Printf("Callbacks (%d)", a_UrlStackIdx + 1).c_str()); + L.Push(false); + L.Push("Invalid OnCompleteBodyCallback param"); + return 2; + } + if (!L.GetStackValues(a_UrlStackIdx + 2, cLuaState::cOptionalParam(headers), cLuaState::cOptionalParam(requestBody), cLuaState::cOptionalParam(options))) + { + L.LogApiCallParamFailure("cUrlClient:Request()", Printf("Header, Body or Options (%d, %d, %d)", a_UrlStackIdx + 2, a_UrlStackIdx + 3, a_UrlStackIdx + 4).c_str()); + L.Push(false); + L.Push("Invalid params"); + return 2; + } + + // Make the request: + auto res = cUrlClient::Request(a_Method, url, std::move(urlClientCallbacks), std::move(headers), std::move(requestBody), std::move(options)); + if (!res.first) + { + L.Push(false); + L.Push(res.second); + return 2; + } + L.Push(true); + return 1; +} + + + + + +/** Implements cUrlClient:Get() using cUrlClient::Request(). */ +static int tolua_cUrlClient_Delete(lua_State * a_LuaState) +{ + /* Function signatures: + cUrlClient:Delete(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + cUrlClient:Delete(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + */ + + return tolua_cUrlClient_Request_Common(a_LuaState, "DELETE", 2); +} + + + + + +/** Implements cUrlClient:Get() using cUrlClient::Request(). */ +static int tolua_cUrlClient_Get(lua_State * a_LuaState) +{ + /* Function signatures: + cUrlClient:Get(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + cUrlClient:Get(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + */ + + return tolua_cUrlClient_Request_Common(a_LuaState, "GET", 2); +} + + + + + +/** Implements cUrlClient:Post() using cUrlClient::Request(). */ +static int tolua_cUrlClient_Post(lua_State * a_LuaState) +{ + /* Function signatures: + cUrlClient:Post(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + cUrlClient:Post(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + */ + + return tolua_cUrlClient_Request_Common(a_LuaState, "POST", 2); +} + + + + + +/** Implements cUrlClient:Put() using cUrlClient::Request(). */ +static int tolua_cUrlClient_Put(lua_State * a_LuaState) +{ + /* Function signatures: + cUrlClient:Put(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + cUrlClient:Put(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + */ + + return tolua_cUrlClient_Request_Common(a_LuaState, "PUT", 2); +} + + + + + +/** Binds cUrlClient::Request(). */ +static int tolua_cUrlClient_Request(lua_State * a_LuaState) +{ + /* Function signatures: + cUrlClient:Request(Method, URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + cUrlClient:Request(Method, URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string + */ + + // Check that the Method param is a string: + cLuaState L(a_LuaState); + if (!L.CheckParamString(2)) + { + return 0; + } + + // Redirect the rest to the common code: + AString method; + if (!L.GetStackValue(2, method)) + { + L.LogApiCallParamFailure("cUrlClient:Request", "Method (2)"); + L.Push(cLuaState::Nil); + L.Push("Invalid params"); + return 2; + } + return tolua_cUrlClient_Request_Common(a_LuaState, method, 3); +} + + + + + //////////////////////////////////////////////////////////////////////////////// // Register the bindings: @@ -913,10 +1238,12 @@ void cManualBindings::BindNetwork(lua_State * tolua_S) tolua_usertype(tolua_S, "cServerHandle"); tolua_usertype(tolua_S, "cTCPLink"); tolua_usertype(tolua_S, "cUDPEndpoint"); + tolua_usertype(tolua_S, "cUrlClient"); tolua_cclass(tolua_S, "cNetwork", "cNetwork", "", nullptr); tolua_cclass(tolua_S, "cServerHandle", "cServerHandle", "", tolua_collect_cServerHandle); tolua_cclass(tolua_S, "cTCPLink", "cTCPLink", "", nullptr); tolua_cclass(tolua_S, "cUDPEndpoint", "cUDPEndpoint", "", tolua_collect_cUDPEndpoint); + tolua_cclass(tolua_S, "cUrlClient", "cUrlClient", "", nullptr); // Fill in the functions (alpha-sorted): tolua_beginmodule(tolua_S, "cNetwork"); @@ -953,6 +1280,13 @@ void cManualBindings::BindNetwork(lua_State * tolua_S) tolua_function(tolua_S, "Send", tolua_cUDPEndpoint_Send); tolua_endmodule(tolua_S); + tolua_beginmodule(tolua_S, "cUrlClient"); + tolua_function(tolua_S, "Delete", tolua_cUrlClient_Delete); + tolua_function(tolua_S, "Get", tolua_cUrlClient_Get); + tolua_function(tolua_S, "Post", tolua_cUrlClient_Post); + tolua_function(tolua_S, "Put", tolua_cUrlClient_Put); + tolua_function(tolua_S, "Request", tolua_cUrlClient_Request); + tolua_endmodule(tolua_S); } -- cgit v1.2.3