diff options
Diffstat (limited to 'Sluift/sluift.cpp')
-rw-r--r-- | Sluift/sluift.cpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp new file mode 100644 index 0000000..cab5361 --- /dev/null +++ b/Sluift/sluift.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +extern "C" { + #include "sluift.h" + #include <lauxlib.h> +} + +#include <iostream> +#include <string> + +#include <Swiften/Client/Client.h> +#include <Swiften/Client/ClientXMLTracer.h> +#include <Swiften/JID/JID.h> +#include <Swiften/EventLoop/DummyEventLoop.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Base/sleep.h> +#include <Swiften/Elements/SoftwareVersion.h> +#include <Swiften/Queries/Requests/GetSoftwareVersionRequest.h> + +using namespace Swift; + +#define SLUIFT_CLIENT "SluiftClient*" + +/******************************************************************************* + * Helper classes + ******************************************************************************/ + +DummyEventLoop eventLoop; +BoostNetworkFactories networkFactories(&eventLoop); + +class SluiftClient { + public: + SluiftClient(const JID& jid, const std::string& password) { + client = new Client(jid, password, &networkFactories); + client->setAlwaysTrustCertificates(); + tracer = new ClientXMLTracer(client); + } + + ~SluiftClient() { + delete tracer; + delete client; + } + + void connect() { + client->connect(); + while (client->isActive() && !client->isAvailable()) { + processEvents(); + } + } + + bool isConnected() const { + return client->isAvailable(); + } + + void sendMessage(const JID& to, const std::string& body) { + Message::ref message = boost::make_shared<Message>(); + message->setTo(to); + message->setBody(body); + client->sendMessage(message); + } + + void disconnect() { + client->disconnect(); + while (client->isActive()) { + processEvents(); + } + } + + boost::optional<SoftwareVersion> getSoftwareVersion(const JID& jid) { + GetSoftwareVersionRequest::ref request = GetSoftwareVersionRequest::create(jid, client->getIQRouter()); + request->onResponse.connect(boost::bind(&SluiftClient::handleSoftwareVersionResponse, this, _1, _2)); + softwareVersion.reset(); + error.reset(); + request->send(); + while (!softwareVersion && !error) { + processEvents(); + } + return softwareVersion; + } + + private: + void processEvents() { + Swift::sleep(100); + eventLoop.processEvents(); + } + + void handleSoftwareVersionResponse(boost::shared_ptr<SoftwareVersion> version, ErrorPayload::ref error) { + if (error) { + this->error = error; + } + else if (version) { + this->softwareVersion = *version; + } + else { + this->softwareVersion = SoftwareVersion("", "", ""); + } + } + + private: + Client* client; + ClientXMLTracer* tracer; + boost::optional<SoftwareVersion> softwareVersion; + ErrorPayload::ref error; +}; + + +/******************************************************************************* + * Client functions. + ******************************************************************************/ + +static inline SluiftClient* getClient(lua_State* L) { + return *reinterpret_cast<SluiftClient**>(luaL_checkudata(L, 1, SLUIFT_CLIENT)); +} + +static int sluift_client_is_connected(lua_State *L) { + lua_pushboolean(L, getClient(L)->isConnected()); + return 1; +} + +static int sluift_client_disconnect(lua_State *L) { + getClient(L)->disconnect(); + return 0; +} + + +static int sluift_client_get_version(lua_State *L) { + SluiftClient* client = getClient(L); + JID jid(std::string(luaL_checkstring(L, 2))); + + boost::optional<SoftwareVersion> version = client->getSoftwareVersion(jid); + if (version) { + lua_createtable(L, 0, 3); + lua_pushstring(L, version->getName().c_str()); + lua_setfield(L, -2, "name"); + lua_pushstring(L, version->getVersion().c_str()); + lua_setfield(L, -2, "version"); + lua_pushstring(L, version->getOS().c_str()); + lua_setfield(L, -2, "os"); + } + else { + lua_pushnil(L); + } + return 1; +} + +static int sluift_client_send_message(lua_State *L) { + getClient(L)->sendMessage(std::string(luaL_checkstring(L, 2)), luaL_checkstring(L, 3)); + return 0; +} + +static int sluift_client_gc (lua_State *L) { + SluiftClient* client = getClient(L); + delete client; + return 0; +} + + +static const luaL_reg sluift_client_functions[] = { + {"is_connected", sluift_client_is_connected}, + {"disconnect", sluift_client_disconnect}, + {"send_message", sluift_client_send_message}, + {"get_version", sluift_client_get_version}, + {"__gc", sluift_client_gc}, + {NULL, NULL} +}; + +/******************************************************************************* + * Module functions + ******************************************************************************/ + +static int sluift_connect(lua_State *L) { + JID jid(std::string(luaL_checkstring(L, 1))); + std::string password(luaL_checkstring(L, 2)); + + SluiftClient** client = reinterpret_cast<SluiftClient**>(lua_newuserdata(L, sizeof(SluiftClient*))); + luaL_getmetatable(L, SLUIFT_CLIENT); + lua_setmetatable(L, -2); + + *client = new SluiftClient(jid, password); + (*client)->connect(); + if (!(*client)->isConnected()) { + lua_pushnil(L); + } + return 1; +} + +static const luaL_reg sluift_functions[] = { + {"connect", sluift_connect}, + {NULL, NULL} +}; + + +/******************************************************************************* + * Module registration + ******************************************************************************/ + +SLUIFT_API int luaopen_sluift(lua_State *L) { + // Register functions + luaL_register(L, "sluift", sluift_functions); + + // Register the client metatable + luaL_newmetatable(L, SLUIFT_CLIENT); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + luaL_register(L, NULL, sluift_client_functions); + + return 1; +} |