diff options
Diffstat (limited to 'Sluift/sluift.cpp')
-rw-r--r-- | Sluift/sluift.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp index 5a9fbd5..895d90d 100644 --- a/Sluift/sluift.cpp +++ b/Sluift/sluift.cpp @@ -11,6 +11,7 @@ extern "C" { #include <iostream> #include <string> +#include <deque> #include <Swiften/Client/Client.h> #include <Swiften/Client/ClientXMLTracer.h> @@ -51,6 +52,8 @@ class SluiftClient { SluiftClient(const JID& jid, const std::string& password, bool debug = false) : tracer(NULL) { client = new Client(jid, password, &networkFactories); client->setAlwaysTrustCertificates(); + client->onMessageReceived.connect(boost::bind(&SluiftClient::handleIncomingEvent, this, _1)); + client->onPresenceReceived.connect(boost::bind(&SluiftClient::handleIncomingEvent, this, _1)); if (debug) { tracer = new ClientXMLTracer(client); } @@ -79,6 +82,10 @@ class SluiftClient { client->sendMessage(message); } + void sendPresence(const std::string& status) { + client->sendPresence(boost::make_shared<Presence>(status)); + } + void disconnect() { client->disconnect(); while (client->isActive()) { @@ -86,6 +93,10 @@ class SluiftClient { } } + void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os) { + client->setSoftwareVersion(name, version, os); + } + 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)); @@ -98,7 +109,31 @@ class SluiftClient { return softwareVersion; } + Stanza::ref getNextEvent() { + if (client->isActive() && !pendingEvents.empty()) { + Stanza::ref event = pendingEvents.front(); + pendingEvents.pop_front(); + return event; + } + while (client->isActive() && pendingEvents.empty()) { + processEvents(); + } + if (client->isActive()) { + assert(!pendingEvents.empty()); + Stanza::ref event = pendingEvents.front(); + pendingEvents.pop_front(); + return event; + } + else { + return Stanza::ref(); + } + } + private: + void handleIncomingEvent(Stanza::ref stanza) { + pendingEvents.push_back(stanza); + } + void processEvents() { eventLoop.runUntilEvents(); } @@ -120,6 +155,7 @@ class SluiftClient { ClientXMLTracer* tracer; boost::optional<SoftwareVersion> softwareVersion; ErrorPayload::ref error; + std::deque<Stanza::ref> pendingEvents; }; @@ -141,6 +177,19 @@ static int sluift_client_disconnect(lua_State *L) { return 0; } +static int sluift_client_set_version(lua_State *L) { + 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); + return 0; +} static int sluift_client_get_version(lua_State *L) { SluiftClient* client = getClient(L); @@ -167,6 +216,68 @@ static int sluift_client_send_message(lua_State *L) { return 0; } +static int sluift_client_send_presence(lua_State *L) { + getClient(L)->sendPresence(std::string(luaL_checkstring(L, 2))); + return 0; +} + +static int sluift_client_for_event (lua_State *L) { + SluiftClient* client = getClient(L); + luaL_checktype(L, 2, LUA_TFUNCTION); + while (true) { + Stanza::ref event = client->getNextEvent(); + if (!event) { + // We got disconnected + lua_pushnil(L); + lua_pushliteral(L, "disconnected"); + return 2; + } + else { + // Push the function on the stack + lua_pushvalue(L, 2); + + bool emitEvent = false; + if (Message::ref message = boost::dynamic_pointer_cast<Message>(event)) { + lua_createtable(L, 0, 3); + lua_pushliteral(L, "message"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, message->getFrom().toString().c_str()); + lua_setfield(L, -2, "from"); + lua_pushstring(L, message->getBody().c_str()); + lua_setfield(L, -2, "body"); + emitEvent = true; + } + else if (Presence::ref presence = boost::dynamic_pointer_cast<Presence>(event)) { + lua_createtable(L, 0, 3); + lua_pushliteral(L, "presence"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, presence->getFrom().toString().c_str()); + lua_setfield(L, -2, "from"); + lua_pushstring(L, presence->getStatus().c_str()); + lua_setfield(L, -2, "status"); + emitEvent = true; + } + else { + assert(false); + } + if (emitEvent) { + 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; + } + } + else { + // Remove the function from the stack again, since + // we're not calling the function + lua_pop(L, 1); + } + } + } +} + static int sluift_client_gc (lua_State *L) { SluiftClient* client = getClient(L); delete client; @@ -178,7 +289,10 @@ static const luaL_reg sluift_client_functions[] = { {"is_connected", sluift_client_is_connected}, {"disconnect", sluift_client_disconnect}, {"send_message", sluift_client_send_message}, + {"send_presence", sluift_client_send_presence}, + {"set_version", sluift_client_set_version}, {"get_version", sluift_client_get_version}, + {"for_event", sluift_client_for_event}, {"__gc", sluift_client_gc}, {NULL, NULL} }; |