lm_connection.c
changeset 6 90073cbb535d
parent 4 5770be2d5f3f
child 9 50f55d494efb
equal deleted inserted replaced
5:e617c9cf6dd3 6:90073cbb535d
     2 #include <lua.h>
     2 #include <lua.h>
     3 #include <lauxlib.h>
     3 #include <lauxlib.h>
     4 #include <glib.h>			// GDestroyNotify, GMainContext
     4 #include <glib.h>			// GDestroyNotify, GMainContext
     5 #include <loudmouth/loudmouth.h>
     5 #include <loudmouth/loudmouth.h>
     6 
     6 
       
     7 #include "config.h"
     7 #include "util.h"
     8 #include "util.h"
     8 #include "lm_types.h"
     9 #include "lm_types.h"
     9 #include "lm_message.h"
    10 #include "lm_message.h"
    10 #include "lm_message_handler.h"
    11 #include "lm_message_handler.h"
    11 
    12 
    60 /// R: lm connection object
    61 /// R: lm connection object
    61 static int llm_connection_new (lua_State *L)
    62 static int llm_connection_new (lua_State *L)
    62 {
    63 {
    63 	const char *server = luaL_checkstring (L, 1);
    64 	const char *server = luaL_checkstring (L, 1);
    64 	LmConnection *connection;
    65 	LmConnection *connection;
    65 	if (lua_gettop (L) < 2) {
    66 	if (lua_gettop (L) < 2)
    66 		connection = lm_connection_new (server);
    67 		connection = lm_connection_new (server);
    67 		lua_pop (L, 1);
    68 	else {
    68 	} else {
       
    69 		luaL_argcheck (L, lua_islightuserdata (L, 2), 2, "glib main context lightuserdata expected");
    69 		luaL_argcheck (L, lua_islightuserdata (L, 2), 2, "glib main context lightuserdata expected");
    70 		connection = lm_connection_new_with_context (server, (GMainContext *) lua_touserdata (L, 2));
    70 		connection = lm_connection_new_with_context (server, (GMainContext *) lua_touserdata (L, 2));
    71 		lua_pop (L, 2);
       
    72 	}
    71 	}
    73 	llm_connection_bless (L, connection);
    72 	llm_connection_bless (L, connection);
    74 	lm_connection_unref (connection);
    73 	lm_connection_unref (connection);
       
    74 	D ("Connection %X created", (int) connection);
    75 	return 1;
    75 	return 1;
    76 }
    76 }
    77 
    77 
    78 /// lm.connection.bless
    78 /// lm.connection.bless
    79 /// Blesses given pointer to lm connection object.
    79 /// Blesses given pointer to lm connection object.
    82 /// R: lm connection object
    82 /// R: lm connection object
    83 static int llm_connection_bless_lua (lua_State *L)
    83 static int llm_connection_bless_lua (lua_State *L)
    84 {
    84 {
    85 	luaL_argcheck (L, lua_islightuserdata (L, 1), 1, "loudmouth connection lightuserdata expected");
    85 	luaL_argcheck (L, lua_islightuserdata (L, 1), 1, "loudmouth connection lightuserdata expected");
    86 	llm_connection_bless (L, (LmConnection *) lua_touserdata (L, 1));
    86 	llm_connection_bless (L, (LmConnection *) lua_touserdata (L, 1));
    87 	lua_remove (L, -2);
       
    88 	return 1;
    87 	return 1;
    89 }
    88 }
    90 
    89 
    91 /// connection callback function
    90 /// connection callback function
    92 /// User function, that will be called on connection establishment operation end,
    91 /// User function, that will be called on connection establishment operation end,
    97 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
    96 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
    98 	llm_connection_bless (cb->L, connection);
    97 	llm_connection_bless (cb->L, connection);
    99 	// XXX lm_connection_unref (connection);
    98 	// XXX lm_connection_unref (connection);
   100 	lua_pushboolean (cb->L, success);
    99 	lua_pushboolean (cb->L, success);
   101 	if (lua_pcall (cb->L, 2, 0, 0)) {
   100 	if (lua_pcall (cb->L, 2, 0, 0)) {
   102 		// XXX lua_error (cb->L);
   101 		E ("Connection callback error: %s", lua_tostring (cb->L, -1));
   103 		lua_pop (cb->L, 1);
   102 		lua_pop (cb->L, 1);
   104 		return;
       
   105 	}
   103 	}
   106 }
   104 }
   107 
   105 
   108 /// connection:open
   106 /// connection:open
   109 /// Opens connection to the server and then calls callback function.
   107 /// Opens connection to the server and then calls callback function.
   110 /// A: connection callback function
   108 /// A: connection callback function
   111 /// R: boolean (success)
   109 /// R: lm connection object or nil, string (error message)
   112 static int llm_connection_open (lua_State *L)
   110 static int llm_connection_open (lua_State *L)
   113 {
   111 {
   114 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   112 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   115 	llm_callback_t *cb;
   113 	llm_callback_t *cb;
   116 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   114 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
       
   115 	GError *err;
   117 	
   116 	
   118 	cb = luaL_malloc (L, sizeof (llm_callback_t));
   117 	cb = luaL_malloc (L, sizeof (llm_callback_t));
   119 	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   118 	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   120 	cb->L         = L;
   119 	cb->L         = L;
   121 
   120 
   122 	lua_pushboolean (L, lm_connection_open (object->connection,
   121 	if (lm_connection_open (object->connection, (LmResultFunction) llm_connection_callback,
   123 						(LmResultFunction)llm_connection_callback, cb,
   122 				 cb, (GDestroyNotify) llm_callback_destroy, &err))
   124 						(GDestroyNotify)llm_callback_destroy, NULL));
   123 		return 1;
   125 	lua_remove (L, -2);
   124 	else {
   126 	return 1;
   125 		lua_pushnil (L);
       
   126 		lua_pushstring (L, err->message);
       
   127 		W ("Connection opening failed");
       
   128 		return 2;
       
   129 	}
   127 }
   130 }
   128 
   131 
   129 /// connection:authenticate
   132 /// connection:authenticate
   130 /// Tries to authenticate against opened connection, then calls callback function.
   133 /// Tries to authenticate against opened connection, then calls callback function.
   131 /// A: string (username), string (password), string (resource), connection callback function
   134 /// A: string (username), string (password), string (resource), connection callback function
   132 /// R: boolean (success)
   135 /// R: lm connection object or nil, string (error message)
   133 static int llm_connection_authenticate (lua_State *L)
   136 static int llm_connection_authenticate (lua_State *L)
   134 {
   137 {
   135 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   138 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   136 	const char *username = luaL_checkstring (L, 2);
   139 	const char *username = luaL_checkstring (L, 2);
   137 	const char *password = luaL_checkstring (L, 3);
   140 	const char *password = luaL_checkstring (L, 3);
   138 	const char *resource = luaL_checkstring (L, 4);
   141 	const char *resource = luaL_checkstring (L, 4);
   139 	llm_callback_t *cb;
   142 	llm_callback_t *cb;
   140 	int status;
   143 	int status;
       
   144 	GError *err = NULL;
   141 	luaL_argcheck (L, lua_isfunction (L, 5), 5, "function expected");
   145 	luaL_argcheck (L, lua_isfunction (L, 5), 5, "function expected");
   142 
   146 
   143 	cb = luaL_malloc (L, sizeof (llm_callback_t));
   147 	cb = luaL_malloc (L, sizeof (llm_callback_t));
   144 	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   148 	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   145 	cb->L         = L;
   149 	cb->L         = L;
   146 
   150 
   147 	status = lm_connection_authenticate (object->connection, username, password, resource,
   151 	if (lm_connection_authenticate (object->connection, username, password, resource,
   148 						(LmResultFunction)llm_connection_callback, cb,
   152 						(LmResultFunction) llm_connection_callback, cb,
   149 						(GDestroyNotify)llm_callback_destroy, NULL);
   153 						(GDestroyNotify) llm_callback_destroy, &err)) {
   150 	lua_pop (L, 4);
   154 		lua_pop (L, 3);
   151 	lua_pushboolean (L, status);
   155 		return 1;
   152 	return 1;
   156 	} else {
       
   157 		lua_pushnil (L);
       
   158 		lua_pushstring (L, err->message);
       
   159 		W ("Connection authentication failed: %s", err->message);
       
   160 		return 2;
       
   161 	}
   153 }
   162 }
   154 
   163 
   155 /// connection:port
   164 /// connection:port
   156 /// Gets or sets server port to connect.
   165 /// Gets or sets server port to connect.
   157 /// A: integer (optional)
   166 /// A: integer (optional)
   158 /// R: integer (when called with no args)
   167 /// R: integer (when called with no args) or lm connection object
   159 static int llm_connection_port (lua_State *L)
   168 static int llm_connection_port (lua_State *L)
   160 {
   169 {
   161 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   170 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   162 	if (lua_gettop (L) > 1) { // Set
   171 	if (lua_gettop (L) > 1) { // Set
   163 		lm_connection_set_port (object->connection, luaL_checkint (L, 2));
   172 		lm_connection_set_port (object->connection, luaL_checkint (L, 2));
   164 		lua_pop (L, 2);
   173 		lua_pop (L, 1);
   165 		return 0;
       
   166 	} else { // Get
   174 	} else { // Get
   167 		lua_pushnumber (L, lm_connection_get_port (object->connection));
   175 		lua_pushnumber (L, lm_connection_get_port (object->connection));
   168 		lua_remove (L, -2);
   176 	}
   169 		return 1;
   177 	return 1;
   170 	}
       
   171 }
   178 }
   172 
   179 
   173 /// connection:server
   180 /// connection:server
   174 /// Gets or sets server to connect to.
   181 /// Gets or sets server to connect to.
   175 /// A: string (optional, server name)
   182 /// A: string (optional, server name)
   176 /// R: string (when called with no args)
   183 /// R: string (when called with no args) or lm connection object
   177 static int llm_connection_server (lua_State *L)
   184 static int llm_connection_server (lua_State *L)
   178 {
   185 {
   179 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   186 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   180 	if (lua_gettop (L) > 1) { // Set
   187 	if (lua_gettop (L) > 1) { // Set
   181 		lm_connection_set_server (object->connection, luaL_checkstring (L, 2));
   188 		lm_connection_set_server (object->connection, luaL_checkstring (L, 2));
   182 		lua_pop (L, 2);
   189 		lua_pop (L, 1);
   183 		return 0;
       
   184 	} else { // Get
   190 	} else { // Get
   185 		lua_pushstring (L, lm_connection_get_server (object->connection));
   191 		lua_pushstring (L, lm_connection_get_server (object->connection));
   186 		lua_remove (L, -2);
   192 	}
   187 		return 1;
   193 	return 1;
   188 	}
       
   189 }
   194 }
   190 
   195 
   191 /// connection:jid
   196 /// connection:jid
   192 /// Gets or sets jid for connection.
   197 /// Gets or sets jid for connection.
   193 /// A: string (optional)
   198 /// A: string (optional)
   194 /// R: string (when called with no args)
   199 /// R: string (when called with no args) or lm connection object
   195 static int llm_connection_jid (lua_State *L)
   200 static int llm_connection_jid (lua_State *L)
   196 {
   201 {
   197 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   202 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   198 	if (lua_gettop (L) > 1) { // Set
   203 	if (lua_gettop (L) > 1) { // Set
   199 		lm_connection_set_jid (object->connection, luaL_checkstring (L, 2));
   204 		lm_connection_set_jid (object->connection, luaL_checkstring (L, 2));
   200 		lua_pop (L, 2);
   205 		lua_pop (L, 1);
   201 		return 0;
       
   202 	} else { // Get
   206 	} else { // Get
   203 		lua_pushstring (L, lm_connection_get_jid (object->connection));
   207 		lua_pushstring (L, lm_connection_get_jid (object->connection));
   204 		lua_remove (L, -2);
   208 	}
   205 		return 1;
   209 	return 1;
   206 	}
       
   207 }
   210 }
   208 
   211 
   209 /// connection:keep_alive_rate
   212 /// connection:keep_alive_rate
   210 /// Gets or sets keep alive packets rate for connection.
   213 /// Gets or sets keep alive packets rate for connection.
   211 /// Note, that on some platforms there is no get function even in
   214 /// Note, that on some platforms there is no get function even in
   212 /// loudmouth versions, that should have it according to documentation.
   215 /// loudmouth versions, that should have it according to documentation.
   213 /// integer (optional, seconds)
   216 /// integer (optional, seconds)
   214 /// integer (when called with no args)
   217 /// integer (when called with no args) or lm connection object or nil, string (error message, when get function is not available in loudmouth)
   215 static int llm_connection_keep_alive_rate (lua_State *L)
   218 static int llm_connection_keep_alive_rate (lua_State *L)
   216 {
   219 {
   217 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   220 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   218 	if (lua_gettop (L) > 1) { // Set
   221 	if (lua_gettop (L) > 1) { // Set
   219 		lm_connection_set_keep_alive_rate (object->connection, luaL_checkint (L, 2));
   222 		lm_connection_set_keep_alive_rate (object->connection, luaL_checkint (L, 2));
   220 		lua_pop (L, 2);
   223 		lua_pop (L, 1);
   221 		return 0;
   224 		return 1;
   222 	} else { // Get
   225 	} else { // Get
   223 #ifdef HAVE_LM_CONNECTION_GET_KEEP_ALIVE_RATE
   226 #ifdef HAVE_LM_CONNECTION_GET_KEEP_ALIVE_RATE
   224 		lua_pushnumber (L, lm_connection_get_keep_alive_rate (object->connection));
   227 		lua_pushnumber (L, lm_connection_get_keep_alive_rate (object->connection));
   225 		lua_remove (L, -2);
   228 		return 1;
   226 #else
   229 #else
   227 		lua_pop (L, 1);
   230 		E ("Sorry, your loudmouth have no get_keep_alive_rate ()");
   228 		lua_pushstring (L, "Sorry, your loudmouth have no get_keep_alive_rate");
   231 		lua_pushnil (L);
   229 		lua_error (L);
   232 		lua_pushstring (L, "Sorry, your loudmouth have no get_keep_alive_rate ()");
       
   233 		return 2;
   230 #endif
   234 #endif
   231 		return 1;
       
   232 	}
   235 	}
   233 }
   236 }
   234 
   237 
   235 /// connection:proxy
   238 /// connection:proxy
   236 /// Gets or sets proxy server for connection.
   239 /// Gets or sets proxy server for connection.
   237 /// A: lm proxy object (optional)
   240 /// A: lm proxy object (optional)
   238 /// R: lm proxy object or nil (when called with no args)
   241 /// R: lm proxy object or nil (when called with no args) or lm connection object
   239 static int llm_connection_proxy (lua_State *L)
   242 static int llm_connection_proxy (lua_State *L)
   240 {
   243 {
   241 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   244 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   242 	if (lua_gettop (L) > 1) { // Set
   245 	if (lua_gettop (L) > 1) { // Set
   243 		llm_proxy_t *proxy = luaL_checklm_proxy (L, 2);
   246 		llm_proxy_t *proxy = luaL_checklm_proxy (L, 2);
   244 		lm_connection_set_proxy (object->connection, proxy->proxy);
   247 		lm_connection_set_proxy (object->connection, proxy->proxy);
   245 		lua_pop (L, 2);
   248 		lua_pop (L, 1);
   246 		return 0;
       
   247 	} else { // Get
   249 	} else { // Get
   248 		LmProxy *proxy = lm_connection_get_proxy (object->connection);
   250 		LmProxy *proxy = lm_connection_get_proxy (object->connection);
   249 		lua_pop (L, 1);
   251 		lua_pop (L, 1);
   250 		if (proxy) {
   252 		if (proxy) {
   251 			llm_proxy_bless (L, proxy);
   253 			llm_proxy_bless (L, proxy);
   252 			// XXX lm_proxy_unref (proxy);
   254 			// XXX lm_proxy_unref (proxy);
   253 		} else
   255 		} else
   254 			lua_pushnil (L);
   256 			lua_pushnil (L);
   255 		return 1;
   257 	}
   256 	}
   258 	return 1;
   257 }
   259 }
   258 
   260 
   259 /// connection:ssl
   261 /// connection:ssl
   260 /// Gets or sets ssl object for connection.
   262 /// Gets or sets ssl object for connection.
   261 /// A: lm ssl object (optional)
   263 /// A: lm ssl object (optional)
   262 /// R: lm ssl object or nil (when called with no args)
   264 /// R: lm ssl object or nil (when called with no args) or lm connection object
   263 static int llm_connection_ssl (lua_State *L)
   265 static int llm_connection_ssl (lua_State *L)
   264 {
   266 {
   265 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   267 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   266 	if (lua_gettop (L) > 1) { // Set
   268 	if (lua_gettop (L) > 1) { // Set
   267 		llm_ssl_t *ssl = luaL_checklm_ssl (L, 2);
   269 		llm_ssl_t *ssl = luaL_checklm_ssl (L, 2);
   268 		lm_connection_set_ssl (object->connection, ssl->ssl);
   270 		lm_connection_set_ssl (object->connection, ssl->ssl);
   269 		lua_pop (L, 2);
   271 		lua_pop (L, 1);
   270 		return 0;
       
   271 	} else { // Get
   272 	} else { // Get
   272 		LmSSL *ssl = lm_connection_get_ssl (object->connection);
   273 		LmSSL *ssl = lm_connection_get_ssl (object->connection);
   273 		lua_pop (L, 1);
   274 		lua_pop (L, 1);
   274 		if (ssl) {
   275 		if (ssl) {
   275 			llm_ssl_bless (L, ssl);
   276 			llm_ssl_bless (L, ssl);
   276 			// XXX lm_ssl_unref (ssl);
   277 			// XXX lm_ssl_unref (ssl);
   277 		} else
   278 		} else
   278 			lua_pushnil (L);
   279 			lua_pushnil (L);
   279 		return 1;
   280 	}
   280 	}
   281 	return 1;
   281 }
   282 }
   282 
   283 
   283 /// connection:close
   284 /// connection:close
   284 /// Close connection.
   285 /// Close connection.
   285 /// R: boolean (success)
   286 /// R: lm connection object or nil, string (error message)
   286 static int llm_connection_close (lua_State *L)
   287 static int llm_connection_close (lua_State *L)
   287 {
   288 {
   288 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   289 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   289 	lua_pushboolean (L, lm_connection_close (object->connection, NULL));
   290 	GError *err = NULL;
   290 	lua_remove (L, -2);
   291 	if (lm_connection_close (object->connection, &err))
   291 	return 1;
   292 		return 1;
       
   293 	else {
       
   294 		W ("Connection close failed: %s", err->message);
       
   295 		lua_pushnil (L);
       
   296 		lua_pushstring (L, err->message);
       
   297 		return 2;
       
   298 	}
   292 }
   299 }
   293 
   300 
   294 /// connection:status
   301 /// connection:status
   295 /// Returns string, describing connection state.
   302 /// Returns string, describing connection state.
   296 /// R: connection state
   303 /// R: connection state
   297 static int llm_connection_status (lua_State *L)
   304 static int llm_connection_status (lua_State *L)
   298 {
   305 {
   299 	llm_connection_t *connection = luaL_checklm_connection (L, 1);
   306 	llm_connection_t *connection = luaL_checklm_connection (L, 1);
   300 	luaL_pushenum (L, lm_connection_get_state (connection->connection), llm_connection_state);
   307 	luaL_pushenum (L, lm_connection_get_state (connection->connection), llm_connection_state);
   301 	lua_remove (L, -2);
       
   302 	return 1;
   308 	return 1;
   303 }
   309 }
   304 
   310 
   305 /// connection:send
   311 /// connection:send
   306 /// Sends message (object). If specified, handler function will be called upon
   312 /// Sends message (object). If specified, handler function will be called upon
   307 /// receiving of response to that message.
   313 /// receiving of response to that message.
   308 /// Handler function can be either message handler object or just a function.
   314 /// Handler function can be either message handler object or just a function.
   309 /// A: lm message object, message handler callback function or lm message handler object (optional)
   315 /// A: lm message object, message handler callback function or lm message handler object (optional)
   310 /// R: boolean (success)
   316 /// R: lm connection object or nil, string (error message)
   311 static int llm_connection_send (lua_State *L)
   317 static int llm_connection_send (lua_State *L)
   312 {
   318 {
   313 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   319 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   314 	llm_message_t *message = luaL_checklm_message (L, 2);
   320 	llm_message_t *message = luaL_checklm_message (L, 2);
   315 	int status;
   321 	int status;
       
   322 	GError *err = NULL;
   316 	if (lua_gettop (L) < 3) // Send
   323 	if (lua_gettop (L) < 3) // Send
   317 		status = lm_connection_send (object->connection, message->message, NULL);
   324 		status = lm_connection_send (object->connection, message->message, &err);
   318 	else if (lua_isfunction (L, 3)) { // Send w/reply, func
   325 	else if (lua_isfunction (L, 3)) { // Send w/reply, func
   319 		llm_callback_t *cb = luaL_malloc (L, sizeof (llm_callback_t));
   326 		llm_callback_t *cb = luaL_malloc (L, sizeof (llm_callback_t));
   320 		LmMessageHandler *handler;
   327 		LmMessageHandler *handler;
   321 
   328 
   322 		cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   329 		cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   323 		cb->L = L;
   330 		cb->L = L;
   324 		handler = lm_message_handler_new (
   331 		handler = lm_message_handler_new (
   325 					(LmHandleMessageFunction)llm_message_handler_callback,
   332 					(LmHandleMessageFunction)llm_message_handler_callback,
   326 					cb, (GDestroyNotify)llm_callback_destroy);
   333 					cb, (GDestroyNotify)llm_callback_destroy);
   327 		status = lm_connection_send_with_reply (object->connection,
   334 		status = lm_connection_send_with_reply (object->connection,
   328 							message->message, handler, NULL);
   335 							message->message, handler, &err);
   329 		lm_message_handler_unref (handler);
   336 		lm_message_handler_unref (handler);
   330 	} else { // Send w/reply, handler
   337 	} else { // Send w/reply, handler
   331 		llm_message_handler_t *handler = luaL_checklm_message_handler (L, 3);
   338 		llm_message_handler_t *handler = luaL_checklm_message_handler (L, 3);
   332 		status = lm_connection_send_with_reply (object->connection, message->message,
   339 		status = lm_connection_send_with_reply (object->connection, message->message,
   333 							handler->message_handler, NULL);
   340 							handler->message_handler, &err);
   334 		lua_pop (L, 1);
   341 		lua_pop (L, 1);
   335 	};
   342 	};
   336 	lua_pop (L, 2);
   343 	lua_pop (L, 1);
   337 	lua_pushboolean (L, status);
   344 	if (status)
   338 	return 1;
   345 		return 1;
       
   346 	else {
       
   347 		W ("Message sending failed: %s", err->message);
       
   348 		lua_pushnil (L);
       
   349 		lua_pushstring (L, err->message);
       
   350 		return 2;
       
   351 	}
   339 }
   352 }
   340 
   353 
   341 /// connection:send_raw
   354 /// connection:send_raw
   342 /// Sends arbitrary string to opened connection.
   355 /// Sends arbitrary string to opened connection.
   343 /// A: string
   356 /// A: string
   344 /// R: boolean (status)
   357 /// R: lm connection object or nil, string (error message)
   345 static int llm_connection_send_raw (lua_State *L)
   358 static int llm_connection_send_raw (lua_State *L)
   346 {
   359 {
   347 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   360 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   348 	const char *string = luaL_checkstring (L, 2);
   361 	const char *string = luaL_checkstring (L, 2);
   349 	int status = lm_connection_send_raw (object->connection, string, NULL);
   362 	GError *err = NULL;
   350 	lua_pop (L, 2);
   363 	if (lm_connection_send_raw (object->connection, string, NULL)) {
   351 	lua_pushboolean (L, status);
   364 		lua_pop (L, 1);
   352 	return 1;
   365 		return 1;
       
   366 	} else {
       
   367 		W ("Raw message sending failed: %s", err->message);
       
   368 		lua_pushnil (L);
       
   369 		lua_pushstring (L, err->message);
       
   370 		return 2;
       
   371 	}
   353 }
   372 }
   354 
   373 
   355 /// connection:handler
   374 /// connection:handler
   356 /// Registers or unregisters handler function for a given type of messages.
   375 /// Registers or unregisters handler function for a given type of messages.
   357 /// To unregister handler, omit the priority argument.
   376 /// To unregister handler, omit the priority argument.
   358 /// Handler function can be specified as plain function or message handler object.
   377 /// Handler function can be specified as plain function or message handler object.
   359 /// Though, you can unregister only a message handler object.
   378 /// Though, you can unregister only a message handler object.
   360 /// A: message handler callback function or lm message handler object, message type, handler priority (optional)
   379 /// A: message handler callback function or lm message handler object, message type, handler priority (optional)
       
   380 /// R: lm connection object
   361 static int llm_connection_handler (lua_State *L)
   381 static int llm_connection_handler (lua_State *L)
   362 {
   382 {
   363 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   383 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   364 	int type = luaL_checkenum (L, 3, llm_message_type);
   384 	int type = luaL_checkenum (L, 3, llm_message_type);
   365 
   385 
   391 		lm_connection_unregister_message_handler (object->connection,
   411 		lm_connection_unregister_message_handler (object->connection,
   392 							  handler->message_handler,
   412 							  handler->message_handler,
   393 							  type);
   413 							  type);
   394 	}
   414 	}
   395 	lua_pop (L, 2);
   415 	lua_pop (L, 2);
   396 	return 0;
   416 	return 1;
   397 }
   417 }
   398 
   418 
   399 /// disconnect callback function
   419 /// disconnect callback function
   400 /// Function, that will be called when disconnection occurs.
   420 /// Function, that will be called when disconnection occurs.
   401 /// A: lm connection object, disconnect reason
   421 /// A: lm connection object, disconnect reason
   404 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   424 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   405 	llm_connection_bless (cb->L, connection);
   425 	llm_connection_bless (cb->L, connection);
   406 	// XXX lm_connection_unref (connection);
   426 	// XXX lm_connection_unref (connection);
   407 	luaL_pushenum (cb->L, reason, llm_disconnect_reason);
   427 	luaL_pushenum (cb->L, reason, llm_disconnect_reason);
   408 	if (lua_pcall (cb->L, 2, 0, 0)) {
   428 	if (lua_pcall (cb->L, 2, 0, 0)) {
   409 		// XXX lua_error (cb->L);
   429 		E ("Disconnect callback error: %s", lua_tostring (cb->L, -1));
   410 		lua_pop (cb->L, 1);
   430 		lua_pop (cb->L, 1);
   411 		return;
       
   412 	}
   431 	}
   413 }
   432 }
   414 
   433 
   415 /// connection:ondisconnect
   434 /// connection:ondisconnect
   416 /// Sets callback, that will be called on connection disconnect.
   435 /// Sets callback, that will be called on connection disconnect.
   417 /// A: disconnect callback function
   436 /// A: disconnect callback function
       
   437 /// R: lm connection object
   418 static int llm_connection_ondisconnect (lua_State *L)
   438 static int llm_connection_ondisconnect (lua_State *L)
   419 {
   439 {
   420 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   440 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   421 	llm_callback_t *cb;
   441 	llm_callback_t *cb;
   422 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   442 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   426 	cb->L          = L;
   446 	cb->L          = L;
   427 
   447 
   428 	lm_connection_set_disconnect_function (object->connection,
   448 	lm_connection_set_disconnect_function (object->connection,
   429 					       (LmDisconnectFunction)llm_disconnect_callback,
   449 					       (LmDisconnectFunction)llm_disconnect_callback,
   430 					       cb, (GDestroyNotify)llm_callback_destroy);
   450 					       cb, (GDestroyNotify)llm_callback_destroy);
   431 	lua_pop (L, 1);
   451 	return 1;
   432 	return 0;
       
   433 }
   452 }
   434 
   453 
   435 /// connection:open_wait
   454 /// connection:open_wait
   436 /// Synchronous open call, that will block until connection will be opened.
   455 /// Synchronous open call, that will block until connection will be opened.
   437 /// R: boolean (success)
   456 /// R: lm connection object or nil, string (error message)
   438 static int llm_connection_open_wait (lua_State *L)
   457 static int llm_connection_open_wait (lua_State *L)
   439 {
   458 {
   440 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   459 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   441 	lua_pushboolean (L, lm_connection_open_and_block (object->connection, NULL));
   460 	GError *err = NULL;
   442 	lua_remove (L, -2);
   461 	if (lm_connection_open_and_block (object->connection, &err))
   443 	return 1;
   462 		return 1;
       
   463 	else {
       
   464 		W ("Synchronous connection opening failed: %s", err->message);
       
   465 		lua_pushnil (L);
       
   466 		lua_pushstring (L, err->message);
       
   467 		return 2;
       
   468 	}
   444 }
   469 }
   445 
   470 
   446 /// connection:authenticate_wait
   471 /// connection:authenticate_wait
   447 /// Synchronous authentication call, that will wait until the end of authentication.
   472 /// Synchronous authentication call, that will wait until the end of authentication.
   448 /// A: string (username), string (password), string (resource)
   473 /// A: string (username), string (password), string (resource)
   449 /// R: boolean (success)
   474 /// R: lm connection object or nil, string (error message)
   450 static int llm_connection_authenticate_wait (lua_State *L)
   475 static int llm_connection_authenticate_wait (lua_State *L)
   451 {
   476 {
   452 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   477 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   453 	const char *username = luaL_checkstring (L, 2);
   478 	const char *username = luaL_checkstring (L, 2);
   454 	const char *password = luaL_checkstring (L, 3);
   479 	const char *password = luaL_checkstring (L, 3);
   455 	const char *resource = luaL_checkstring (L, 4);
   480 	const char *resource = luaL_checkstring (L, 4);
   456 	int status = lm_connection_authenticate_and_block (object->connection, username,
   481 	GError *err = NULL;
   457 								password, resource, NULL);
   482 	if (lm_connection_authenticate_and_block (object->connection, username,
   458 	lua_pop (L, 4);
   483 								password, resource, &err))
   459 	lua_pushboolean (L, status);
   484 		return 1;
   460 	return 1;
   485 	else {
       
   486 		W ("Synchronous authentication failed: %s", err->message);
       
   487 		lua_pushnil (L);
       
   488 		lua_pushstring (L, err->message);
       
   489 		return 2;
       
   490 	}
   461 }
   491 }
   462 
   492 
   463 /// connection:send_wait
   493 /// connection:send_wait
   464 /// Synchronous call, that will send message and wait for reply to it.
   494 /// Synchronous call, that will send message and wait for reply to it.
   465 /// A: lm message object
   495 /// A: lm message object
   466 /// R: lm message object or nil
   496 /// R: lm message object or nil, string (error message)
   467 static int llm_connection_send_wait (lua_State *L)
   497 static int llm_connection_send_wait (lua_State *L)
   468 {
   498 {
   469 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   499 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   470 	llm_message_t *message = luaL_checklm_message (L, 2);
   500 	llm_message_t *message = luaL_checklm_message (L, 2);
       
   501 	GError *err = NULL;
   471 	LmMessage *new = lm_connection_send_with_reply_and_block (object->connection,
   502 	LmMessage *new = lm_connection_send_with_reply_and_block (object->connection,
   472 									message->message, NULL);
   503 									message->message, &err);
   473 	lua_pop (L, 2);
   504 	if (!new) {
   474 	if (!new)
   505 		W ("Synchronous message sending failed: %s", err->message);
   475 		lua_pushnil (L);
   506 		lua_pushnil (L);
   476 	else {
   507 		lua_pushstring (L, err->message);
       
   508 		return 2;
       
   509 	} else {
   477 		llm_message_bless (L, new);
   510 		llm_message_bless (L, new);
   478 		lm_message_unref (new); // XXX
   511 		lm_message_unref (new); // XXX
   479 	}
   512 		return 1;
   480 	return 1;
   513 	}
   481 }
   514 }
   482 
   515 
   483 /// connection:pointer
   516 /// connection:pointer
   484 /// Returns pointer to underlying C loudmouth structure.
   517 /// Returns pointer to underlying C loudmouth structure.
   485 /// R: lightuserdata
   518 /// R: lightuserdata
   492 }
   525 }
   493 
   526 
   494 static int llm_connection_gc (lua_State *L)
   527 static int llm_connection_gc (lua_State *L)
   495 {
   528 {
   496 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   529 	llm_connection_t *object = luaL_checklm_connection (L, 1);
       
   530 	D ("Connection %X gc called", (int) object);
   497 	lm_connection_unref (object->connection);
   531 	lm_connection_unref (object->connection);
   498 	lua_pop (L, 1);
       
   499 	return 0;
   532 	return 0;
   500 }
   533 }
   501 
   534 
   502 static const luaL_Reg llm_connection_reg_f[] = {
   535 static const luaL_Reg llm_connection_reg_f[] = {
   503 	{ "new",   llm_connection_new       },
   536 	{ "new",   llm_connection_new       },