diff options
-rw-r--r-- | Sluift/linit.c | 2 | ||||
-rw-r--r-- | Sluift/sluift.cpp | 122 | ||||
-rw-r--r-- | Swiften/EventLoop/SimpleEventLoop.cpp | 11 | ||||
-rw-r--r-- | Swiften/EventLoop/SimpleEventLoop.h | 2 | ||||
-rw-r--r-- | Swiften/QA/ScriptedTests/SendMessage.lua | 4 |
5 files changed, 83 insertions, 58 deletions
diff --git a/Sluift/linit.c b/Sluift/linit.c index 0114c12..14299b3 100644 --- a/Sluift/linit.c +++ b/Sluift/linit.c @@ -25,6 +25,8 @@ static const char tprint[] = " tostring (key), tostring(value)))\n" " end\n" " end\n" + " elseif type(tt) == \"nil\" then\n" + " io.write(\"nil\\n\")\n" " else\n" " io.write(tt .. \"\\n\")\n" " end\n" diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp index 086fb2a..fd7b695 100644 --- a/Sluift/sluift.cpp +++ b/Sluift/sluift.cpp @@ -18,6 +18,8 @@ extern "C" { #include <Swiften/JID/JID.h> #include <Swiften/EventLoop/SimpleEventLoop.h> #include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/TimerFactory.h> +#include <Swiften/Network/Timer.h> #include <Swiften/Base/sleep.h> #include <Swiften/Elements/SoftwareVersion.h> #include <Swiften/Queries/Requests/GetSoftwareVersionRequest.h> @@ -40,6 +42,39 @@ bool debug = false; SimpleEventLoop eventLoop; BoostNetworkFactories networkFactories(&eventLoop); +class Watchdog { + public: + Watchdog(int timeout) : timedOut(false) { + if (timeout > 0) { + timer = networkFactories.getTimerFactory()->createTimer(timeout); + timer->start(); + timer->onTick.connect(boost::bind(&Watchdog::handleTimerTick, this)); + } + else if (timeout == 0) { + timedOut = true; + } + } + + ~Watchdog() { + if (timer) { + timer->stop(); + } + } + + bool getTimedOut() const { + return timedOut; + } + + private: + void handleTimerTick() { + timedOut = true; + } + + private: + Timer::ref timer; + bool timedOut; +}; + class SluiftException { public: SluiftException(const std::string& reason) : reason(reason) { @@ -83,7 +118,7 @@ class SluiftClient { void waitConnected() { while (client->isActive() && !client->isAvailable()) { - processEvents(); + eventLoop.runUntilEvents(); } } @@ -105,7 +140,7 @@ class SluiftClient { void disconnect() { client->disconnect(); while (client->isActive()) { - processEvents(); + eventLoop.runUntilEvents(); } } @@ -120,35 +155,36 @@ class SluiftClient { error.reset(); request->send(); while (!softwareVersion && !error) { - processEvents(); + eventLoop.runUntilEvents(); } return softwareVersion; } - Stanza::ref getNextEvent() { - if (client->isActive() && !pendingEvents.empty()) { + Stanza::ref getNextEvent(int timeout) { + eventLoop.runOnce(); + if (!pendingEvents.empty()) { Stanza::ref event = pendingEvents.front(); pendingEvents.pop_front(); return event; } - while (client->isActive() && pendingEvents.empty()) { - processEvents(); + Watchdog watchdog(timeout); + while (!watchdog.getTimedOut() && pendingEvents.empty()) { + eventLoop.runUntilEvents(); + } + if (watchdog.getTimedOut()) { + return Stanza::ref(); } - if (client->isActive()) { - assert(!pendingEvents.empty()); + else { Stanza::ref event = pendingEvents.front(); pendingEvents.pop_front(); return event; } - else { - return Stanza::ref(); - } } std::vector<XMPPRosterItem> getRoster() { client->requestRoster(); while (!rosterReceived) { - processEvents(); + eventLoop.runUntilEvents(); } return client->getRoster()->getItems(); } @@ -162,10 +198,6 @@ class SluiftClient { rosterReceived = true; } - void processEvents() { - eventLoop.runUntilEvents(); - } - void handleSoftwareVersionResponse(boost::shared_ptr<SoftwareVersion> version, ErrorPayload::ref error) { if (error) { this->error = error; @@ -224,11 +256,6 @@ class SluiftClient { std::deque<Stanza::ref> pendingEvents; }; -#define CHECK_CLIENT_CONNECTED(client, L) \ - if (!(*client)->isConnected()) { \ - lua_pushnil(L); \ - } - /******************************************************************************* * Client functions. ******************************************************************************/ @@ -331,17 +358,6 @@ static int sluift_client_get_roster(lua_State *L) { lua_setfield(L, -2, item.getJID().toString().c_str()); } - /*boost::optional<SoftwareVersion> version = client->getSoftwareVersion(jid); - if (version) { - lua_pushstring(L, version->getName().c_str()); - 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"); - } - */ return 1; } catch (const SluiftException& e) { @@ -395,23 +411,25 @@ static int sluift_client_set_options(lua_State* L) { return 0; } -static int sluift_client_for_event (lua_State *L) { +static int sluift_client_for_event(lua_State *L) { try { SluiftClient* client = getClient(L); luaL_checktype(L, 2, LUA_TFUNCTION); + int timeout = -1; + if (lua_type(L, 3) != LUA_TNONE) { + timeout = lua_tonumber(L, 3); + } + while (true) { - Stanza::ref event = client->getNextEvent(); + Stanza::ref event = client->getNextEvent(timeout); if (!event) { - // We got disconnected + // We got a timeout lua_pushnil(L); - lua_pushliteral(L, "disconnected"); - return 2; + return 1; } else { - // Push the function on the stack + // Push the function and event 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"); @@ -420,7 +438,6 @@ static int sluift_client_for_event (lua_State *L) { 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); @@ -430,24 +447,17 @@ static int sluift_client_for_event (lua_State *L) { lua_setfield(L, -2, "from"); lua_pushstring(L, presence->getStatus().c_str()); lua_setfield(L, -2, "status"); - emitEvent = true; } else { assert(false); + lua_pushnil(L); } - 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); + 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; } } } diff --git a/Swiften/EventLoop/SimpleEventLoop.cpp b/Swiften/EventLoop/SimpleEventLoop.cpp index 2d71544..b77639c 100644 --- a/Swiften/EventLoop/SimpleEventLoop.cpp +++ b/Swiften/EventLoop/SimpleEventLoop.cpp @@ -44,6 +44,17 @@ void SimpleEventLoop::doRun(bool breakAfterEvents) { } } +void SimpleEventLoop::runOnce() { + std::vector<Event> events; + { + boost::unique_lock<boost::mutex> lock(eventsMutex_); + events.swap(events_); + } + foreach(const Event& event, events) { + handleEvent(event); + } +} + void SimpleEventLoop::stop() { postEvent(boost::bind(&SimpleEventLoop::doStop, this)); } diff --git a/Swiften/EventLoop/SimpleEventLoop.h b/Swiften/EventLoop/SimpleEventLoop.h index bdffa3d..6fb3f53 100644 --- a/Swiften/EventLoop/SimpleEventLoop.h +++ b/Swiften/EventLoop/SimpleEventLoop.h @@ -27,6 +27,8 @@ namespace Swift { doRun(true); } + void runOnce(); + void stop(); virtual void post(const Event& event); diff --git a/Swiften/QA/ScriptedTests/SendMessage.lua b/Swiften/QA/ScriptedTests/SendMessage.lua index a3f1917..8c54d00 100644 --- a/Swiften/QA/ScriptedTests/SendMessage.lua +++ b/Swiften/QA/ScriptedTests/SendMessage.lua @@ -33,12 +33,12 @@ received_message = client2:for_event(function(event) if event["type"] == "message" and event["from"] == client1_jid then return event["body"] end - end) + end, 10000) assert(received_message == "Hello") print "Retrieving the roster" roster = client1:get_roster() -table.foreach(roster, print) +tprint(roster) client1:disconnect() client2:disconnect() |