From d869b157f0d3eee5d4964878b3990df98a07e020 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 18 Jan 2014 10:27:41 +0100
Subject: Sluift: Refactor global debug & timeout options.

Use regular table values on the sluift table.
Enable enabling tracing on a client after the fact.

Change-Id: Iaa2bea61bdadf0b8dec4951654c402b7133c1151

diff --git a/Sluift/SluiftClient.cpp b/Sluift/SluiftClient.cpp
index 257eec1..8c0213e 100644
--- a/Sluift/SluiftClient.cpp
+++ b/Sluift/SluiftClient.cpp
@@ -23,11 +23,9 @@ SluiftClient::SluiftClient(
 		const JID& jid, 
 		const std::string& password, 
 		NetworkFactories* networkFactories, 
-		SimpleEventLoop* eventLoop,
-		SluiftGlobals* globals) :
+		SimpleEventLoop* eventLoop) :
 			networkFactories(networkFactories), 
 			eventLoop(eventLoop),
-			globals(globals),
 			tracer(NULL) {
 	client = new Client(jid, password, networkFactories);
 	client->setAlwaysTrustCertificates();
@@ -46,9 +44,6 @@ SluiftClient::~SluiftClient() {
 void SluiftClient::connect() {
 	rosterReceived = false;
 	disconnectedError = boost::optional<ClientError>();
-	if (globals->debug) {
-		tracer = new ClientXMLTracer(client, options.boshURL.isEmpty()? false: true);
-	}
 	client->connect(options);
 }
 
@@ -57,14 +52,21 @@ void SluiftClient::connect(const std::string& host, int port) {
 	options.manualHostname = host;
 	options.manualPort = port;
 	disconnectedError = boost::optional<ClientError>();
-	if (globals->debug) {
+	client->connect(options);
+}
+
+void SluiftClient::setTraceEnabled(bool b) {
+	if (b && !tracer) {
 		tracer = new ClientXMLTracer(client, options.boshURL.isEmpty()? false: true);
 	}
-	client->connect(options);
+	else if (!b && tracer) {
+		delete tracer;
+		tracer = NULL;
+	}
 }
 
-void SluiftClient::waitConnected() {
-	Watchdog watchdog(globals->timeout, networkFactories->getTimerFactory());
+void SluiftClient::waitConnected(int timeout) {
+	Watchdog watchdog(timeout, networkFactories->getTimerFactory());
 	while (!watchdog.getTimedOut() && client->isActive() && !client->isAvailable()) {
 		eventLoop->runUntilEvents();
 	}
diff --git a/Sluift/SluiftClient.h b/Sluift/SluiftClient.h
index 60eae16..f0192e4 100644
--- a/Sluift/SluiftClient.h
+++ b/Sluift/SluiftClient.h
@@ -12,7 +12,6 @@
 #include <boost/function.hpp>
 
 #include <Swiften/Client/ClientOptions.h>
-#include <Sluift/globals.h>
 #include <Swiften/Elements/IQ.h>
 #include <Swiften/Elements/Message.h>
 #include <Swiften/Elements/Presence.h>
@@ -62,8 +61,7 @@ namespace Swift {
 					const JID& jid, 
 					const std::string& password, 
 					NetworkFactories* networkFactories, 
-					SimpleEventLoop* eventLoop, 
-					SluiftGlobals* globals);
+					SimpleEventLoop* eventLoop);
 			~SluiftClient();
 
 			Client* getClient() {
@@ -76,8 +74,9 @@ namespace Swift {
 
 			void connect();
 			void connect(const std::string& host, int port);
-			void waitConnected();
+			void waitConnected(int timeout);
 			bool isConnected() const;
+			void setTraceEnabled(bool b);
 
 			template<typename T>
 				Sluift::Response sendPubSubRequest(
@@ -119,7 +118,6 @@ namespace Swift {
 		private:
 			NetworkFactories* networkFactories;
 			SimpleEventLoop* eventLoop;
-			SluiftGlobals* globals;
 			Client* client;
 			ClientOptions options;
 			ClientXMLTracer* tracer;
diff --git a/Sluift/SluiftGlobals.h b/Sluift/SluiftGlobals.h
index 0d8e637..5de7cfe 100644
--- a/Sluift/SluiftGlobals.h
+++ b/Sluift/SluiftGlobals.h
@@ -13,14 +13,17 @@
 
 namespace Swift {
 	struct SluiftGlobals {
-		SluiftGlobals() : networkFactories(&eventLoop), interruptRequested(0) {}
+		SluiftGlobals() : 
+			networkFactories(&eventLoop), 
+			coreLibIndex(-1),
+			moduleLibIndex(-1),
+			interruptRequested(0) {}
 
-		int timeout;
-		bool debug;
 		LuaElementConvertors elementConvertor;
 		SimpleEventLoop eventLoop;
 		BoostNetworkFactories networkFactories;
 		int coreLibIndex;
+		int moduleLibIndex;
 		sig_atomic_t interruptRequested;
 	};
 }
diff --git a/Sluift/client.cpp b/Sluift/client.cpp
index 9cb5090..cdbc591 100644
--- a/Sluift/client.cpp
+++ b/Sluift/client.cpp
@@ -41,6 +41,22 @@ static inline SluiftClient* getClient(lua_State* L) {
 	return *Lua::checkUserData<SluiftClient>(L, 1);
 }
 
+static inline int getGlobalTimeout(lua_State* L) {
+	lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.moduleLibIndex);
+	lua_getfield(L, -1, "timeout");
+	int result = boost::numeric_cast<int>(lua_tointeger(L, -1));
+	lua_pop(L, 2);
+	return result;
+}
+
+static inline bool getGlobalDebug(lua_State* L) {
+	lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.moduleLibIndex);
+	lua_getfield(L, -1, "debug");
+	int result = lua_toboolean(L, -1);
+	lua_pop(L, 2);
+	return result;
+}
+
 SLUIFT_LUA_FUNCTION(Client, async_connect) {
 	SluiftClient* client = getClient(L);
 
@@ -54,17 +70,29 @@ SLUIFT_LUA_FUNCTION(Client, async_connect) {
 			port = *portInt;
 		}
 	}
+	client->setTraceEnabled(getGlobalDebug(L));
 	client->connect(host, port);
 	return 0;
 }
 
 SLUIFT_LUA_FUNCTION_WITH_HELP(
+		Client, set_trace_enabled,
+		"Enable/disable tracing of the data sent/received.\n\n.",
+		"self\n"
+		"enable  a boolean specifying whether to enable/disable tracing",
+		""
+) {
+	getClient(L)->setTraceEnabled(lua_toboolean(L, 1));
+	return 0;
+}
+
+SLUIFT_LUA_FUNCTION_WITH_HELP(
 		Client, wait_connected,
 		"Block until the client is connected.\n\nThis is useful after an `async_connect`.",
 		"self",
 		""
 ) {
-	getClient(L)->waitConnected();
+	getClient(L)->waitConnected(getGlobalTimeout(L));
 	return 0;
 }
 
@@ -274,7 +302,7 @@ static int sendQuery(lua_State* L, IQ::Type type) {
 		to = JID(*toString);
 	}
 
-	int timeout = Sluift::globals.timeout;
+	int timeout = getGlobalTimeout(L);
 	if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) {
 		timeout = *timeoutInt;
 	}
@@ -306,7 +334,7 @@ SLUIFT_LUA_FUNCTION(Client, query_pubsub) {
 		to = JID(*toString);
 	}
 
-	int timeout = Sluift::globals.timeout;
+	int timeout = getGlobalTimeout(L);
 	if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) {
 		timeout = *timeoutInt;
 	}
@@ -520,7 +548,7 @@ SLUIFT_LUA_FUNCTION(Client, get_next_event) {
 	Sluift::globals.eventLoop.runOnce();
 	SluiftClient* client = getClient(L);
 
-	int timeout = Sluift::globals.timeout;
+	int timeout = getGlobalTimeout(L);
 	boost::optional<SluiftClient::Event::Type> type;
 	int condition = 0;
 	if (lua_istable(L, 2)) {
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index 39b92fc..08ffd92 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -70,7 +70,7 @@ SLUIFT_LUA_FUNCTION_WITH_HELP(
 	lua_setmetatable(L, -3);
 	lua_pop(L, 1);
 
-	*client = new SluiftClient(jid, password, &Sluift::globals.networkFactories, &Sluift::globals.eventLoop, &Sluift::globals);
+	*client = new SluiftClient(jid, password, &Sluift::globals.networkFactories, &Sluift::globals.eventLoop);
 	return 1;
 }
 
@@ -115,41 +115,6 @@ SLUIFT_LUA_FUNCTION_WITH_HELP(
 	return 1;
 }
 
-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 if (key == "timeout") {
-			lua_pushnumber(L, Sluift::globals.timeout);
-			return 1;
-		}
-		return 0;
-	}
-	catch (const std::exception& e) {
-		return luaL_error(L, e.what());
-	}
-}
-
-
-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 if (key == "timeout") {
-			Sluift::globals.timeout = Lua::checkIntNumber(L, 3);
-		}
-		return 0;
-	}
-	catch (const std::exception& e) {
-		return luaL_error(L, e.what());
-	}
-}
-
 SLUIFT_LUA_FUNCTION_WITH_HELP(
 		Sluift, from_xml,
 		"Convert a raw XML string into a structured representation.",
@@ -314,11 +279,15 @@ SLUIFT_LUA_FUNCTION(IDN, stringprep) {
 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;
-
+	// Initialize & store the module table
 	luaL_register(L, lua_tostring(L, 1), sluift_functions);
+	lua_pushinteger(L, -1);
+	lua_setfield(L, -2, "timeout");
+	lua_pushboolean(L, 0);
+	lua_setfield(L, -2, "debug");
+
+	lua_pushvalue(L, -1);
+	Sluift::globals.moduleLibIndex = luaL_ref(L, LUA_REGISTRYINDEX);
 
 	// Load core lib code
 	if (luaL_loadbuffer(L, core_lua, core_lua_size, "core.lua") != 0) {
@@ -346,14 +315,6 @@ SLUIFT_API int luaopen_sluift(lua_State* L) {
 	}
 	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);
-	
 	// Load client metatable
 	lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex);
 	std::vector<std::string> tables = boost::assign::list_of("Client");
-- 
cgit v0.10.2-6-g49f6