summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Sluift/sluift.cpp')
-rw-r--r--Sluift/sluift.cpp813
1 files changed, 179 insertions, 634 deletions
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index 722fb54..e6096a0 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -4,732 +4,277 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "sluift.h"
-#include <lauxlib.h>
+#include <Sluift/sluift.h>
+
+#include <lua.hpp>
-#include <iostream>
#include <string>
-#include <deque>
-#include <boost/assign/list_of.hpp>
+#include <boost/bind.hpp>
#include <boost/numeric/conversion/cast.hpp>
-
-#include <Swiften/Base/foreach.h>
-#include <Swiften/Swiften.h>
+#include <boost/assign/list_of.hpp>
#include "Watchdog.h"
-#include "ResponseSink.h"
-#include "Lua/Value.h"
-#include "ClientHelpers.h"
+#include <Sluift/Lua/Check.h>
+#include <Sluift/SluiftClient.h>
+#include <Sluift/globals.h>
+#include <Sluift/Lua/Exception.h>
+#include <Sluift/Lua/FunctionRegistration.h>
+#include <Swiften/Base/sleep.h>
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h>
+#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>
+#include <Swiften/Serializer/PayloadSerializer.h>
+#include <Sluift/Lua/Debug.h>
+#include <Swiften/StringCodecs/Base64.h>
+#include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
using namespace Swift;
-#define SLUIFT_CLIENT "SluiftClient*"
-
-/*******************************************************************************
- * Forward declarations
- ******************************************************************************/
-
-static bool debug = false;
-static int globalTimeout = 30000;
-
-/*******************************************************************************
- * Helper classes
- ******************************************************************************/
-
-static SimpleEventLoop eventLoop;
-static BoostNetworkFactories networkFactories(&eventLoop);
-
-
-class SluiftClient {
- public:
- SluiftClient(const JID& jid, const std::string& password, lua_State* L) : L(L), tracer(NULL) {
- client = new Client(jid, password, &networkFactories);
- client->setAlwaysTrustCertificates();
- client->onDisconnected.connect(boost::bind(&SluiftClient::handleDisconnected, this, _1));
- client->onMessageReceived.connect(boost::bind(&SluiftClient::handleIncomingEvent, this, _1));
- client->onPresenceReceived.connect(boost::bind(&SluiftClient::handleIncomingEvent, this, _1));
- client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SluiftClient::handleInitialRosterPopulated, this));
- if (debug) {
- tracer = new ClientXMLTracer(client);
- }
- }
-
- ~SluiftClient() {
- delete tracer;
- delete client;
- }
-
- Client* getClient() {
- return client;
- }
-
- ClientOptions& getOptions() {
- return options;
- }
-
- void connect() {
- rosterReceived = false;
- client->connect(options);
- }
-
- void connect(const std::string& host) {
- rosterReceived = false;
- options.manualHostname = host;
- client->connect(options);
- }
-
- void waitConnected() {
- Watchdog watchdog(globalTimeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut() && client->isActive() && !client->isAvailable()) {
- eventLoop.runUntilEvents();
- }
- if (watchdog.getTimedOut()) {
- client->disconnect();
- luaL_error(L, "Timeout while connecting");
- }
- }
-
- 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 sendPresence(const std::string& status) {
- client->sendPresence(boost::make_shared<Presence>(status));
- }
-
- boost::optional<std::string> sendQuery(const JID& jid, IQ::Type type, const std::string& data, int timeout) {
- rawRequestResponse.reset();
- RawRequest::ref request = RawRequest::create(type, jid, data, client->getIQRouter());
- boost::signals::scoped_connection c = request->onResponse.connect(boost::bind(&SluiftClient::handleRawRequestResponse, this, _1));
- request->send();
-
- Watchdog watchdog(timeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut() && !rawRequestResponse) {
- eventLoop.runUntilEvents();
- }
-
- if (watchdog.getTimedOut()) {
- return boost::optional<std::string>();
- }
- else {
- return *rawRequestResponse;
- }
- }
-
- void disconnect() {
- client->disconnect();
- while (client->isActive()) {
- eventLoop.runUntilEvents();
- }
- }
-
- void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os) {
- client->setSoftwareVersion(name, version, os);
- }
-
- Stanza::ref getNextEvent(int timeout) {
- if (!pendingEvents.empty()) {
- Stanza::ref event = pendingEvents.front();
- pendingEvents.pop_front();
- return event;
- }
- Watchdog watchdog(timeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut() && pendingEvents.empty() && client->isActive()) {
- eventLoop.runUntilEvents();
- }
- if (watchdog.getTimedOut() || !client->isActive()) {
- return Stanza::ref();
- }
- else if (!pendingEvents.empty()) {
- Stanza::ref event = pendingEvents.front();
- pendingEvents.pop_front();
- return event;
- }
- else {
- return Stanza::ref();
- }
- }
-
- std::vector<XMPPRosterItem> getRoster() {
- if (!rosterReceived) {
- // If we haven't requested it yet, request it for the first time
- client->requestRoster();
- }
- while (!rosterReceived) {
- eventLoop.runUntilEvents();
- }
- return client->getRoster()->getItems();
- }
-
- private:
- void handleIncomingEvent(Stanza::ref stanza) {
- pendingEvents.push_back(stanza);
- }
-
- void handleInitialRosterPopulated() {
- rosterReceived = true;
- }
-
- void handleRawRequestResponse(const std::string& response) {
- rawRequestResponse = response;
- }
-
- void handleDisconnected(const boost::optional<ClientError>& error) {
- if (error) {
- luaL_error(L, getClientErrorString(*error).c_str());
- }
- }
-
- private:
- lua_State* L;
- Client* client;
- ClientOptions options;
- ClientXMLTracer* tracer;
- bool rosterReceived;
- std::deque<Stanza::ref> pendingEvents;
- boost::optional<std::string> rawRequestResponse;
-};
-
-/*******************************************************************************
- * Client functions.
- ******************************************************************************/
-
-static inline SluiftClient* getClient(lua_State* L) {
- return *reinterpret_cast<SluiftClient**>(luaL_checkudata(L, 1, SLUIFT_CLIENT));
-}
-
-static int sluift_client_connect(lua_State *L) {
- SluiftClient* client = getClient(L);
- std::string host;
- if (lua_type(L, 2) != LUA_TNONE) {
- host = luaL_checkstring(L, 2);
+namespace Swift {
+ namespace Sluift {
+ SluiftGlobals globals;
}
- if (host.empty()) {
- client->connect();
- }
- else {
- client->connect(host);
- }
- client->waitConnected();
- return 1;
}
-static int sluift_client_async_connect(lua_State *L) {
- getClient(L)->connect();
- return 1;
-}
+extern "C" const char boot_lua[];
-static int sluift_client_wait_connected(lua_State *L) {
- getClient(L)->waitConnected();
- return 1;
-}
+/*******************************************************************************
+ * Module functions
+ ******************************************************************************/
-static int sluift_client_is_connected(lua_State *L) {
- lua_pushboolean(L, getClient(L)->isConnected());
- return 1;
-}
+SLUIFT_LUA_FUNCTION(Sluift, new_client) {
+ Lua::checkString(L, 1);
+ JID jid(std::string(Lua::checkString(L, 1)));
+ std::string password(Lua::checkString(L, 2));
-static int sluift_client_disconnect(lua_State *L) {
- getClient(L)->disconnect();
- return 1;
-}
+ SluiftClient** client = reinterpret_cast<SluiftClient**>(lua_newuserdata(L, sizeof(SluiftClient*)));
+ luaL_getmetatable(L, Lua::FunctionRegistry::getMetaTableNameForType("Client").c_str());
+ lua_setmetatable(L, -2);
-static int sluift_client_set_version(lua_State *L) {
- eventLoop.runOnce();
-
- SluiftClient* client = getClient(L);
- luaL_checktype(L, 2, LUA_TTABLE);
- lua_getfield(L, 2, "name");
- const char* rawName = lua_tostring(L, -1);
- lua_getfield(L, 2, "version");
- const char* rawVersion = lua_tostring(L, -1);
- lua_getfield(L, 2, "os");
- const char* rawOS = lua_tostring(L, -1);
- client->setSoftwareVersion(rawName ? rawName : "", rawVersion ? rawVersion : "", rawOS ? rawOS : "");
- lua_pop(L, 3);
- lua_pushvalue(L, 1);
+ *client = new SluiftClient(jid, password, &Sluift::globals.networkFactories, &Sluift::globals.eventLoop, &Sluift::globals);
return 1;
}
-static int sluift_client_get_contacts(lua_State *L) {
- eventLoop.runOnce();
-
- SluiftClient* client = getClient(L);
- Lua::Table contactsTable;
- foreach(const XMPPRosterItem& item, client->getRoster()) {
- std::string subscription;
- switch(item.getSubscription()) {
- case RosterItemPayload::None: subscription = "none"; break;
- case RosterItemPayload::To: subscription = "to"; break;
- case RosterItemPayload::From: subscription = "from"; break;
- case RosterItemPayload::Both: subscription = "both"; break;
- case RosterItemPayload::Remove: subscription = "remove"; break;
- }
- Lua::Value groups(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end()));
- Lua::Table itemTable = boost::assign::map_list_of
- ("jid", boost::make_shared<Lua::Value>(item.getJID().toString()))
- ("name", boost::make_shared<Lua::Value>(item.getName()))
- ("subscription", boost::make_shared<Lua::Value>(subscription))
- ("groups", boost::make_shared<Lua::Value>(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end())));
- contactsTable[item.getJID().toString()] = boost::make_shared<Lua::Value>(itemTable);
+SLUIFT_LUA_FUNCTION(Sluift, sha1) {
+ static boost::shared_ptr<CryptoProvider> crypto(PlatformCryptoProvider::create());
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
}
- pushValue(L, contactsTable);
+ size_t len;
+ const char* data = lua_tolstring(L, 1, &len);
+ ByteArray result = crypto->getSHA1Hash(createByteArray(data, len));
+ lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
return 1;
}
-static int sluift_client_get_version(lua_State *L) {
- SluiftClient* client = getClient(L);
- int timeout = -1;
- if (lua_type(L, 3) != LUA_TNONE) {
- timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
- }
-
- ResponseSink<SoftwareVersion> sink;
- GetSoftwareVersionRequest::ref request = GetSoftwareVersionRequest::create(std::string(luaL_checkstring(L, 2)), client->getClient()->getIQRouter());
- boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
- request->send();
-
- Watchdog watchdog(timeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut() && !sink.hasResponse()) {
- eventLoop.runUntilEvents();
- }
-
- ErrorPayload::ref error = sink.getResponseError();
- if (error || watchdog.getTimedOut()) {
- lua_pushnil(L);
- if (watchdog.getTimedOut()) {
- lua_pushstring(L, "Timeout");
- }
- else if (error->getCondition() == ErrorPayload::RemoteServerNotFound) {
- lua_pushstring(L, "Remote server not found");
- }
- // TODO
- else {
- lua_pushstring(L, "Error");
- }
- return 2;
- }
- else if (SoftwareVersion::ref version = sink.getResponsePayload()) {
- Lua::Table result = boost::assign::map_list_of
- ("name", boost::make_shared<Lua::Value>(version->getName()))
- ("version", boost::make_shared<Lua::Value>(version->getVersion()))
- ("os", boost::make_shared<Lua::Value>(version->getOS()));
- Lua::pushValue(L, result);
- }
- else {
- lua_pushnil(L);
+SLUIFT_LUA_FUNCTION(Sluift, sleep) {
+ Sluift::globals.eventLoop.runOnce();
+ int timeout = Lua::checkIntNumber(L, 1);
+ Watchdog watchdog(timeout, Sluift::globals.networkFactories.getTimerFactory());
+ while (!watchdog.getTimedOut()) {
+ Swift::sleep(boost::numeric_cast<unsigned int>(std::min(100, timeout)));
+ Sluift::globals.eventLoop.runOnce();
}
- return 1;
-}
-
-static int sluift_client_send_message(lua_State *L) {
- eventLoop.runOnce();
-
- getClient(L)->sendMessage(std::string(luaL_checkstring(L, 2)), luaL_checkstring(L, 3));
- lua_pushvalue(L, 1);
- return 1;
-}
-
-static int sluift_client_send_presence(lua_State *L) {
- eventLoop.runOnce();
-
- getClient(L)->sendPresence(std::string(luaL_checkstring(L, 2)));
- lua_pushvalue(L, 1);
return 0;
}
-static int sluift_client_get(lua_State *L) {
- SluiftClient* client = getClient(L);
- JID jid;
- std::string data;
- int timeout = -1;
- if (lua_type(L, 3) == LUA_TSTRING) {
- jid = JID(std::string(luaL_checkstring(L, 2)));
- data = std::string(luaL_checkstring(L, 3));
- if (lua_type(L, 4) != LUA_TNONE) {
- timeout = boost::numeric_cast<int>(luaL_checknumber(L, 4));
+static int sluift_index(lua_State* L) {
+ try {
+ std::string key(Lua::checkString(L, 2));
+ if (key == "debug") {
+ lua_pushboolean(L, Sluift::globals.debug);
+ return 1;
}
- }
- else {
- data = std::string(luaL_checkstring(L, 2));
- if (lua_type(L, 3) != LUA_TNONE) {
- timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
+ else if (key == "timeout") {
+ lua_pushnumber(L, Sluift::globals.timeout);
+ return 1;
}
+ throw Lua::Exception("Unknown property");
}
- boost::optional<std::string> result = client->sendQuery(jid, IQ::Get, data, timeout);
- if (result) {
- lua_pushstring(L, result->c_str());
- }
- else {
- lua_pushnil(L);
+ catch (const std::exception& e) {
+ return luaL_error(L, e.what());
}
- return 1;
}
-static int sluift_client_set(lua_State *L) {
- SluiftClient* client = getClient(L);
- JID jid;
- std::string data;
- int timeout = -1;
- if (lua_type(L, 3) == LUA_TSTRING) {
- jid = JID(std::string(luaL_checkstring(L, 2)));
- data = std::string(luaL_checkstring(L, 3));
- if (lua_type(L, 4) != LUA_TNONE) {
- timeout = boost::numeric_cast<int>(luaL_checknumber(L, 4));
+
+static int sluift_newindex(lua_State* L) {
+ try {
+ std::string key(Lua::checkString(L, 2));
+ if (key == "debug") {
+ Sluift::globals.debug = lua_toboolean(L, 3);
}
- }
- else {
- data = std::string(luaL_checkstring(L, 2));
- if (lua_type(L, 3) != LUA_TNONE) {
- timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
+ else if (key == "timeout") {
+ Sluift::globals.timeout = Lua::checkIntNumber(L, 3);
}
+ return 0;
}
- boost::optional<std::string> result = client->sendQuery(jid, IQ::Set, data, timeout);
- if (result) {
- lua_pushstring(L, result->c_str());
- }
- else {
- lua_pushnil(L);
- }
- return 1;
-}
-
-static int sluift_client_send(lua_State *L) {
- eventLoop.runOnce();
-
- getClient(L)->getClient()->sendData(std::string(luaL_checkstring(L, 2)));
- lua_pushvalue(L, 1);
- return 0;
-}
-
-static int sluift_client_set_options(lua_State* L) {
- SluiftClient* client = getClient(L);
- luaL_checktype(L, 2, LUA_TTABLE);
- lua_getfield(L, 2, "ack");
- if (!lua_isnil(L, -1)) {
- client->getOptions().useAcks = lua_toboolean(L, -1);
- }
- lua_getfield(L, 2, "compress");
- if (!lua_isnil(L, -1)) {
- client->getOptions().useStreamCompression = lua_toboolean(L, -1);
- }
- lua_getfield(L, 2, "tls");
- if (!lua_isnil(L, -1)) {
- bool useTLS = lua_toboolean(L, -1);
- client->getOptions().useTLS = (useTLS ? ClientOptions::UseTLSWhenAvailable : ClientOptions::NeverUseTLS);
+ catch (const std::exception& e) {
+ return luaL_error(L, e.what());
}
- lua_pushvalue(L, 1);
- return 0;
}
-static void pushEvent(lua_State* L, Stanza::ref event) {
- if (Message::ref message = boost::dynamic_pointer_cast<Message>(event)) {
- Lua::Table result = boost::assign::map_list_of
- ("type", boost::make_shared<Lua::Value>(std::string("message")))
- ("from", boost::make_shared<Lua::Value>(message->getFrom().toString()))
- ("body", boost::make_shared<Lua::Value>(message->getBody()));
- Lua::pushValue(L, result);
- }
- else if (Presence::ref presence = boost::dynamic_pointer_cast<Presence>(event)) {
- Lua::Table result = boost::assign::map_list_of
- ("type", boost::make_shared<Lua::Value>(std::string("presence")))
- ("from", boost::make_shared<Lua::Value>(presence->getFrom().toString()))
- ("status", boost::make_shared<Lua::Value>(presence->getStatus()));
- Lua::pushValue(L, result);
- }
- else {
- lua_pushnil(L);
+SLUIFT_LUA_FUNCTION(Sluift, from_xml) {
+ PayloadsParserTester parser;
+ if (!parser.parse(Lua::checkString(L, 1))) {
+ throw Lua::Exception("Error in XML");
}
+ return Sluift::globals.elementConvertor.convertToLua(L, parser.getPayload());
}
-static int sluift_client_for_event(lua_State *L) {
- eventLoop.runOnce();
-
- SluiftClient* client = getClient(L);
- luaL_checktype(L, 2, LUA_TFUNCTION);
- int timeout = -1;
- if (lua_type(L, 3) != LUA_TNONE) {
- timeout = boost::numeric_cast<int>(lua_tonumber(L, 3));
+SLUIFT_LUA_FUNCTION(Sluift, to_xml) {
+ static FullPayloadSerializerCollection serializers;
+ boost::shared_ptr<Payload> payload = Sluift::globals.elementConvertor.convertFromLua(L, 1);
+ if (!payload) {
+ throw Lua::Exception("Unrecognized XML");
}
-
- while (true) {
- Stanza::ref event = client->getNextEvent(timeout);
- if (!event) {
- // We got a timeout
- lua_pushnil(L);
- return 1;
- }
- else {
- // Push the function and event on the stack
- lua_pushvalue(L, 2);
- pushEvent(L, event);
- int oldTop = lua_gettop(L) - 2;
- lua_call(L, 1, LUA_MULTRET);
- int returnValues = lua_gettop(L) - oldTop;
- if (returnValues > 0) {
- lua_remove(L, -1 - returnValues);
- return returnValues;
- }
- }
- }
-}
-
-static int sluift_client_get_next_event(lua_State *L) {
- eventLoop.runOnce();
-
- SluiftClient* client = getClient(L);
- int timeout = -1;
- if (lua_type(L, 2) != LUA_TNONE) {
- timeout = boost::numeric_cast<int>(lua_tonumber(L, 2));
+ PayloadSerializer* serializer = serializers.getPayloadSerializer(payload);
+ if (!payload) {
+ throw Lua::Exception("Unrecognized XML");
}
- pushEvent(L, client->getNextEvent(timeout));
+ lua_pushstring(L, serializer->serialize(payload).c_str());
return 1;
}
-
-static int sluift_client_add_contact(lua_State* L) {
- eventLoop.runOnce();
- SluiftClient* client = getClient(L);
- RosterItemPayload item;
- if (lua_type(L, 2) == LUA_TTABLE) {
- lua_getfield(L, 2, "jid");
- const char* rawJID = lua_tostring(L, -1);
- if (rawJID) {
- item.setJID(std::string(rawJID));
- }
- lua_getfield(L, 2, "name");
- const char* rawName = lua_tostring(L, -1);
- if (rawName) {
- item.setName(rawName);
- }
- lua_getfield(L, 2, "groups");
- if (!lua_isnil(L, -1)) {
- if (lua_type(L, -1) == LUA_TTABLE) {
- for (size_t i = 1; i <= lua_objlen(L, -1); ++i) {
- lua_rawgeti(L, -1, boost::numeric_cast<int>(i));
- const char* rawGroup = lua_tostring(L, -1);
- if (rawGroup) {
- item.addGroup(rawGroup);
- }
- lua_pop(L, 1);
- }
- }
- else {
- return luaL_error(L, "Groups should be a table");
- }
- }
- }
- else {
- item.setJID(luaL_checkstring(L, 2));
- }
-
- client->getRoster();
- if (!client->getClient()->getRoster()->containsJID(item.getJID())) {
- RosterPayload::ref roster = boost::make_shared<RosterPayload>();
- roster->addItem(item);
-
- ResponseSink<RosterPayload> sink;
- SetRosterRequest::ref request = SetRosterRequest::create(roster, client->getClient()->getIQRouter());
- boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
- request->send();
- while (!sink.hasResponse()) {
- eventLoop.runUntilEvents();
- }
- if (sink.getResponseError()) {
- lua_pushboolean(L, false);
- return 1;
- }
+SLUIFT_LUA_FUNCTION(Sluift, hexify) {
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
}
- client->getClient()->getSubscriptionManager()->requestSubscription(item.getJID());
- lua_pushboolean(L, true);
+ size_t len;
+ const char* data = lua_tolstring(L, 1, &len);
+ lua_pushstring(L, Hexify::hexify(createByteArray(data, len)).c_str());
return 1;
}
-static int sluift_client_remove_contact(lua_State* L) {
- eventLoop.runOnce();
- SluiftClient* client = getClient(L);
- JID jid(luaL_checkstring(L, 2));
-
- RosterPayload::ref roster = boost::make_shared<RosterPayload>();
- roster->addItem(RosterItemPayload(JID(luaL_checkstring(L, 2)), "", RosterItemPayload::Remove));
- ResponseSink<RosterPayload> sink;
- SetRosterRequest::ref request = SetRosterRequest::create(roster, client->getClient()->getIQRouter());
- boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
- request->send();
- while (!sink.hasResponse()) {
- eventLoop.runUntilEvents();
+SLUIFT_LUA_FUNCTION(Sluift, unhexify) {
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
}
- lua_pushboolean(L, !sink.getResponseError());
+ ByteArray result = Hexify::unhexify(lua_tostring(L, 1));
+ lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
return 1;
}
-static int sluift_client_confirm_subscription(lua_State* L) {
- eventLoop.runOnce();
- SluiftClient* client = getClient(L);
- JID jid(luaL_checkstring(L, 2));
- client->getClient()->getSubscriptionManager()->confirmSubscription(jid);
- return 0;
-}
-
-static int sluift_client_cancel_subscription(lua_State* L) {
- eventLoop.runOnce();
- SluiftClient* client = getClient(L);
- JID jid(luaL_checkstring(L, 2));
- client->getClient()->getSubscriptionManager()->cancelSubscription(jid);
- 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[] = {
- {"connect", sluift_client_connect},
- {"async_connect", sluift_client_async_connect},
- {"wait_connected", sluift_client_wait_connected},
- {"is_connected", sluift_client_is_connected},
- {"disconnect", sluift_client_disconnect},
- {"send_message", sluift_client_send_message},
- {"send_presence", sluift_client_send_presence},
- {"get", sluift_client_get},
- {"set", sluift_client_set},
- {"send", sluift_client_send},
- {"set_version", sluift_client_set_version},
- {"get_contacts", sluift_client_get_contacts},
- {"get_version", sluift_client_get_version},
- {"set_options", sluift_client_set_options},
- {"for_event", sluift_client_for_event},
- {"get_next_event", sluift_client_get_next_event},
- {"add_contact", sluift_client_add_contact},
- {"remove_contact", sluift_client_remove_contact},
- {"confirm_subscription", sluift_client_confirm_subscription},
- {"cancel_subscription", sluift_client_cancel_subscription},
- {"__gc", sluift_client_gc},
- {NULL, NULL}
-};
/*******************************************************************************
- * Module functions
+ * JID Functions
******************************************************************************/
-static int sluift_new_client(lua_State *L) {
- luaL_checkstring(L, 1);
- 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, L);
- return 1;
-}
-
-static int sluift_jid_to_bare(lua_State *L) {
- JID jid(std::string(luaL_checkstring(L, 1)));
+SLUIFT_LUA_FUNCTION(JID, to_bare) {
+ JID jid(std::string(Lua::checkString(L, 1)));
lua_pushstring(L, jid.toBare().toString().c_str());
return 1;
}
-static int sluift_jid_node(lua_State *L) {
- JID jid(std::string(luaL_checkstring(L, 1)));
+SLUIFT_LUA_FUNCTION(JID, node) {
+ JID jid(std::string(Lua::checkString(L, 1)));
lua_pushstring(L, jid.getNode().c_str());
return 1;
}
-static int sluift_jid_domain(lua_State *L) {
- JID jid(std::string(luaL_checkstring(L, 1)));
+SLUIFT_LUA_FUNCTION(JID, domain) {
+ JID jid(std::string(Lua::checkString(L, 1)));
lua_pushstring(L, jid.getDomain().c_str());
return 1;
}
-static int sluift_jid_resource(lua_State *L) {
- JID jid(std::string(luaL_checkstring(L, 1)));
+SLUIFT_LUA_FUNCTION(JID, resource) {
+ JID jid(std::string(Lua::checkString(L, 1)));
lua_pushstring(L, jid.getResource().c_str());
return 1;
}
-static int sluift_sleep(lua_State *L) {
- eventLoop.runOnce();
-
- int timeout = boost::numeric_cast<int>(luaL_checknumber(L, 1));
- Watchdog watchdog(timeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut()) {
- Swift::sleep(boost::numeric_cast<unsigned int>(std::min(100, timeout)));
- eventLoop.runOnce();
- }
- return 0;
+SLUIFT_LUA_FUNCTION(JID, escape_node) {
+ lua_pushstring(L, JID::getEscapedNode(Lua::checkString(L, 1)).c_str());
+ return 1;
}
-static int sluift_index(lua_State *L) {
- std::string key(luaL_checkstring(L, 2));
- if (key == "debug") {
- lua_pushboolean(L, debug);
- return 1;
- }
- else if (key == "timeout") {
- lua_pushnumber(L, globalTimeout);
- return 1;
- }
- else {
- return luaL_error(L, "Invalid index");
+/*******************************************************************************
+ * Base64 Functions
+ ******************************************************************************/
+
+SLUIFT_LUA_FUNCTION(Base64, encode) {
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
}
+ size_t len;
+ const char* data = lua_tolstring(L, 1, &len);
+ lua_pushstring(L, Base64::encode(createByteArray(data, len)).c_str());
+ return 1;
}
-static int sluift_newindex(lua_State *L) {
- std::string key(luaL_checkstring(L, 2));
- if (key == "debug") {
- debug = lua_toboolean(L, 3);
- return 0;
- }
- else if (key == "timeout") {
- globalTimeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
- return 0;
- }
- else {
- return luaL_error(L, "Invalid index");
+SLUIFT_LUA_FUNCTION(Base64, decode) {
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
}
+ ByteArray result = Base64::decode(lua_tostring(L, 1));
+ lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
+ return 1;
}
-static const luaL_reg sluift_functions[] = {
- {"new_client", sluift_new_client},
- {"jid_to_bare", sluift_jid_to_bare},
- {"jid_node", sluift_jid_node},
- {"jid_domain", sluift_jid_domain},
- {"jid_resource", sluift_jid_resource},
- {"sleep", sluift_sleep},
- {NULL, NULL}
-};
-
-
/*******************************************************************************
* Module registration
******************************************************************************/
-SLUIFT_API int luaopen_sluift(lua_State *L) {
- // Register functions
+static const luaL_reg sluift_functions[] = { {NULL, NULL} };
+
+SLUIFT_API int luaopen_sluift(lua_State* L) {
+ // Initialize globals
+ Sluift::globals.debug = false;
+ Sluift::globals.timeout = -1;
+
luaL_register(L, "sluift", sluift_functions);
+
+ // Load bootstrap code
+ if (luaL_loadbuffer(L, boot_lua, strlen(boot_lua), "boot.lua") != 0) {
+ lua_error(L);
+ }
+ lua_call(L, 0, 1);
+ Sluift::globals.bootIndex = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ // Register functions
+ Lua::FunctionRegistry::getInstance().addFunctionsToTable(L, "Sluift");
+ Lua::FunctionRegistry::getInstance().createFunctionTable(L, "JID");
+ lua_setfield(L, -2, "jid");
+ Lua::FunctionRegistry::getInstance().createFunctionTable(L, "Base64");
+ lua_setfield(L, -2, "base64");
+
+ // Register convenience functions
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex);
+ lua_getfield(L, -1, "tprint");
+ lua_setfield(L, -3, "tprint");
+ lua_pop(L, 1);
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex);
+ lua_getfield(L, -1, "disco");
+ lua_setfield(L, -3, "disco");
+ lua_pop(L, 1);
+
+ // Set read only
lua_createtable(L, 0, 0);
lua_pushcclosure(L, sluift_index, 0);
lua_setfield(L, -2, "__index");
lua_pushcclosure(L, sluift_newindex, 0);
lua_setfield(L, -2, "__newindex");
lua_setmetatable(L, -2);
-
- // 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);
-
+
+ // Load client metatable
+ std::vector<std::string> tables = boost::assign::list_of("Client");
+ foreach (const std::string& table, tables) {
+ Lua::FunctionRegistry::getInstance().registerTypeMetaTable(L, table);
+ luaL_getmetatable(L, Lua::FunctionRegistry::getMetaTableNameForType(table).c_str());
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex);
+ lua_getfield(L, -1, table.c_str());
+ if (!lua_isnil(L, -1)) {
+ for (lua_pushnil(L); lua_next(L, -2); ) {
+ lua_pushvalue(L, -2);
+ lua_pushvalue(L, -2);
+ lua_settable(L, -7);
+ lua_pop(L, 1);
+ }
+ }
+ lua_pop(L, 2);
+ }
return 1;
}