summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Sluift/sluift.cpp')
-rw-r--r--Sluift/sluift.cpp114
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}
};