lm_connection.c
changeset 11 a8c6460d612b
parent 10 aed141accdd9
child 12 63f06a23c235
equal deleted inserted replaced
10:aed141accdd9 11:a8c6460d612b
    16 /// connection), then authenticate to the server.
    16 /// connection), then authenticate to the server.
    17 
    17 
    18 /// connection state
    18 /// connection state
    19 /// Stirng, representing current connection state.
    19 /// Stirng, representing current connection state.
    20 /// G:
    20 /// G:
    21 const string2enum_t llm_connection_state[] = {
    21 const string2enum_t state_lm_connection[] = {
    22 	{ "closed",         LM_CONNECTION_STATE_CLOSED         },
    22 	{ "closed",         LM_CONNECTION_STATE_CLOSED         },
    23 	{ "opening",        LM_CONNECTION_STATE_OPENING        },
    23 	{ "opening",        LM_CONNECTION_STATE_OPENING        },
    24 	{ "open",           LM_CONNECTION_STATE_OPEN           },
    24 	{ "open",           LM_CONNECTION_STATE_OPEN           },
    25 	{ "authenticating", LM_CONNECTION_STATE_AUTHENTICATING },
    25 	{ "authenticating", LM_CONNECTION_STATE_AUTHENTICATING },
    26 	{ "authenticated",  LM_CONNECTION_STATE_AUTHENTICATED  },
    26 	{ "authenticated",  LM_CONNECTION_STATE_AUTHENTICATED  },
    29 
    29 
    30 /// handler priority
    30 /// handler priority
    31 /// String, according to which handler will be placed into one
    31 /// String, according to which handler will be placed into one
    32 /// of three handler groups.
    32 /// of three handler groups.
    33 /// G:
    33 /// G:
    34 const string2enum_t llm_handler_priority[] = {
    34 const string2enum_t priority_lm_handler[] = {
    35 	{ "last",   LM_HANDLER_PRIORITY_LAST   },
    35 	{ "last",   LM_HANDLER_PRIORITY_LAST   },
    36 	{ "normal", LM_HANDLER_PRIORITY_NORMAL },
    36 	{ "normal", LM_HANDLER_PRIORITY_NORMAL },
    37 	{ "first",  LM_HANDLER_PRIORITY_FIRST  },
    37 	{ "first",  LM_HANDLER_PRIORITY_FIRST  },
    38 	{ NULL,     0                          }, // XXX
    38 	{ NULL,     0                          }, // XXX
    39 };
    39 };
    57 
    57 
    58 /// lm.connection.new
    58 /// lm.connection.new
    59 /// Creates a new connection (closed).
    59 /// Creates a new connection (closed).
    60 /// A: string (server name), lightuserdata (C glib main context object, optional)
    60 /// A: string (server name), lightuserdata (C glib main context object, optional)
    61 /// R: lm connection object
    61 /// R: lm connection object
    62 static int llm_connection_new (lua_State *L)
    62 static int new_lm_connection (lua_State *L)
    63 {
    63 {
    64 	const char *server = luaL_checkstring (L, 1);
    64 	const char *server = luaL_checkstring (L, 1);
    65 	LmConnection *connection;
    65 	LmConnection *connection;
    66 	if (lua_gettop (L) < 2)
    66 	if (lua_gettop (L) < 2)
    67 		connection = lm_connection_new (server);
    67 		connection = lm_connection_new (server);
    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 	}
    71 	}
    72 	llm_connection_bless (L, connection);
    72 	bless_lm_connection (L, connection);
    73 	lm_connection_unref (connection);
    73 	lm_connection_unref (connection);
    74 	D ("Connection %X created", (int) 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.
    80 /// Note: it adds a reference to connection.
    80 /// Note: it adds a reference to connection.
    81 /// A: lightuserdata (C lm connection object)
    81 /// A: lightuserdata (C 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 bless_lua_lm_connection (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 	bless_lm_connection (L, (LmConnection *) lua_touserdata (L, 1));
    87 	return 1;
    87 	return 1;
    88 }
    88 }
    89 
    89 
    90 /// connection callback function
    90 /// connection callback function
    91 /// User function, that will be called on connection establishment operation end,
    91 /// User function, that will be called on connection establishment operation end,
    92 /// eg. successful/unsuccessful opening or authentication.
    92 /// eg. successful/unsuccessful opening or authentication.
    93 /// A: lm connection object, boolean (success)
    93 /// A: lm connection object, boolean (success)
    94 static void llm_connection_callback (LmConnection *connection, int success, llm_callback_t *cb)
    94 static void callback_lm_connection (LmConnection *connection, int success, llm_callback_t *cb)
    95 {
    95 {
    96 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
    96 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
    97 	llm_connection_bless (cb->L, connection);
    97 	bless_lm_connection (cb->L, connection);
    98 	// XXX lm_connection_unref (connection);
    98 	// XXX lm_connection_unref (connection);
    99 	lua_pushboolean (cb->L, success);
    99 	lua_pushboolean (cb->L, success);
   100 	if (lua_pcall (cb->L, 2, 0, 0)) {
   100 	if (lua_pcall (cb->L, 2, 0, 0)) {
   101 		W ("Connection callback error: %s", lua_tostring (cb->L, -1));
   101 		W ("Connection callback error: %s", lua_tostring (cb->L, -1));
   102 		lua_pop (cb->L, 1);
   102 		lua_pop (cb->L, 1);
   105 
   105 
   106 /// connection:open
   106 /// connection:open
   107 /// Opens connection to the server and then calls callback function.
   107 /// Opens connection to the server and then calls callback function.
   108 /// A: connection callback function
   108 /// A: connection callback function
   109 /// R: lm connection object or nil, string (error message)
   109 /// R: lm connection object or nil, string (error message)
   110 static int llm_connection_open (lua_State *L)
   110 static int open_lm_connection (lua_State *L)
   111 {
   111 {
   112 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   112 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   113 	llm_callback_t *cb;
   113 	llm_callback_t *cb;
   114 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   114 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   115 	GError *err;
   115 	GError *err;
   116 	
   116 	
   117 	cb = luaL_malloc (L, sizeof (llm_callback_t));
   117 	cb = luaL_malloc (L, sizeof (llm_callback_t));
   118 	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   118 	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   119 	cb->L         = L;
   119 	cb->L         = L;
   120 
   120 
   121 	if (lm_connection_open (object->connection, (LmResultFunction) llm_connection_callback,
   121 	if (lm_connection_open (object->connection, (LmResultFunction) callback_lm_connection,
   122 				 cb, (GDestroyNotify) llm_callback_destroy, &err))
   122 				 cb, (GDestroyNotify) llm_callback_destroy, &err))
   123 		return 1;
   123 		return 1;
   124 	else {
   124 	else {
   125 		lua_pushnil (L);
   125 		lua_pushnil (L);
   126 		lua_pushstring (L, err->message);
   126 		lua_pushstring (L, err->message);
   131 
   131 
   132 /// connection:authenticate
   132 /// connection:authenticate
   133 /// Tries to authenticate against opened connection, then calls callback function.
   133 /// Tries to authenticate against opened connection, then calls callback function.
   134 /// A: string (username), string (password), string (resource), connection callback function
   134 /// A: string (username), string (password), string (resource), connection callback function
   135 /// R: lm connection object or nil, string (error message)
   135 /// R: lm connection object or nil, string (error message)
   136 static int llm_connection_authenticate (lua_State *L)
   136 static int authenticate_lm_connection (lua_State *L)
   137 {
   137 {
   138 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   138 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   139 	const char *username = luaL_checkstring (L, 2);
   139 	const char *username = luaL_checkstring (L, 2);
   140 	const char *password = luaL_checkstring (L, 3);
   140 	const char *password = luaL_checkstring (L, 3);
   141 	const char *resource = luaL_checkstring (L, 4);
   141 	const char *resource = luaL_checkstring (L, 4);
   147 	cb = luaL_malloc (L, sizeof (llm_callback_t));
   147 	cb = luaL_malloc (L, sizeof (llm_callback_t));
   148 	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   148 	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   149 	cb->L         = L;
   149 	cb->L         = L;
   150 
   150 
   151 	if (lm_connection_authenticate (object->connection, username, password, resource,
   151 	if (lm_connection_authenticate (object->connection, username, password, resource,
   152 						(LmResultFunction) llm_connection_callback, cb,
   152 						(LmResultFunction) callback_lm_connection, cb,
   153 						(GDestroyNotify) llm_callback_destroy, &err)) {
   153 						(GDestroyNotify) llm_callback_destroy, &err)) {
   154 		lua_pop (L, 3);
   154 		lua_pop (L, 3);
   155 		return 1;
   155 		return 1;
   156 	} else {
   156 	} else {
   157 		lua_pushnil (L);
   157 		lua_pushnil (L);
   163 
   163 
   164 /// connection:port
   164 /// connection:port
   165 /// Gets or sets server port to connect.
   165 /// Gets or sets server port to connect.
   166 /// A: integer (optional)
   166 /// A: integer (optional)
   167 /// R: integer (when called with no args) or lm connection object
   167 /// R: integer (when called with no args) or lm connection object
   168 static int llm_connection_port (lua_State *L)
   168 static int port_lm_connection (lua_State *L)
   169 {
   169 {
   170 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   170 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   171 	if (lua_gettop (L) > 1) { // Set
   171 	if (lua_gettop (L) > 1) { // Set
   172 		lm_connection_set_port (object->connection, luaL_checkint (L, 2));
   172 		lm_connection_set_port (object->connection, luaL_checkint (L, 2));
   173 		lua_pop (L, 1);
   173 		lua_pop (L, 1);
   179 
   179 
   180 /// connection:server
   180 /// connection:server
   181 /// Gets or sets server to connect to.
   181 /// Gets or sets server to connect to.
   182 /// A: string (optional, server name)
   182 /// A: string (optional, server name)
   183 /// R: string (when called with no args) or lm connection object
   183 /// R: string (when called with no args) or lm connection object
   184 static int llm_connection_server (lua_State *L)
   184 static int server_lm_connection (lua_State *L)
   185 {
   185 {
   186 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   186 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   187 	if (lua_gettop (L) > 1) { // Set
   187 	if (lua_gettop (L) > 1) { // Set
   188 		lm_connection_set_server (object->connection, luaL_checkstring (L, 2));
   188 		lm_connection_set_server (object->connection, luaL_checkstring (L, 2));
   189 		lua_pop (L, 1);
   189 		lua_pop (L, 1);
   195 
   195 
   196 /// connection:jid
   196 /// connection:jid
   197 /// Gets or sets jid for connection.
   197 /// Gets or sets jid for connection.
   198 /// A: string (optional)
   198 /// A: string (optional)
   199 /// R: string (when called with no args) or lm connection object
   199 /// R: string (when called with no args) or lm connection object
   200 static int llm_connection_jid (lua_State *L)
   200 static int jid_lm_connection (lua_State *L)
   201 {
   201 {
   202 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   202 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   203 	if (lua_gettop (L) > 1) { // Set
   203 	if (lua_gettop (L) > 1) { // Set
   204 		lm_connection_set_jid (object->connection, luaL_checkstring (L, 2));
   204 		lm_connection_set_jid (object->connection, luaL_checkstring (L, 2));
   205 		lua_pop (L, 1);
   205 		lua_pop (L, 1);
   213 /// Gets or sets keep alive packets rate for connection.
   213 /// Gets or sets keep alive packets rate for connection.
   214 /// 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
   215 /// loudmouth versions, that should have it according to documentation.
   215 /// loudmouth versions, that should have it according to documentation.
   216 /// integer (optional, seconds)
   216 /// integer (optional, seconds)
   217 /// integer (when called with no args) or lm connection object or nil, string (error message, when get function is not available in loudmouth)
   217 /// integer (when called with no args) or lm connection object or nil, string (error message, when get function is not available in loudmouth)
   218 static int llm_connection_keep_alive_rate (lua_State *L)
   218 static int keep_alive_rate_lm_connection (lua_State *L)
   219 {
   219 {
   220 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   220 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   221 	if (lua_gettop (L) > 1) { // Set
   221 	if (lua_gettop (L) > 1) { // Set
   222 		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));
   223 		lua_pop (L, 1);
   223 		lua_pop (L, 1);
   237 
   237 
   238 /// connection:proxy
   238 /// connection:proxy
   239 /// Gets or sets proxy server for connection.
   239 /// Gets or sets proxy server for connection.
   240 /// A: lm proxy object (optional)
   240 /// A: lm proxy object (optional)
   241 /// R: lm proxy object or nil (when called with no args) or lm connection object
   241 /// R: lm proxy object or nil (when called with no args) or lm connection object
   242 static int llm_connection_proxy (lua_State *L)
   242 static int proxy_lm_connection (lua_State *L)
   243 {
   243 {
   244 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   244 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   245 	if (lua_gettop (L) > 1) { // Set
   245 	if (lua_gettop (L) > 1) { // Set
   246 		llm_proxy_t *proxy = luaL_checklm_proxy (L, 2);
   246 		llm_proxy_t *proxy = luaL_checklm_proxy (L, 2);
   247 		lm_connection_set_proxy (object->connection, proxy->proxy);
   247 		lm_connection_set_proxy (object->connection, proxy->proxy);
   248 		lua_pop (L, 1);
   248 		lua_pop (L, 1);
   249 	} else { // Get
   249 	} else { // Get
   250 		LmProxy *proxy = lm_connection_get_proxy (object->connection);
   250 		LmProxy *proxy = lm_connection_get_proxy (object->connection);
   251 		lua_pop (L, 1);
   251 		lua_pop (L, 1);
   252 		if (proxy) {
   252 		if (proxy) {
   253 			llm_proxy_bless (L, proxy);
   253 			bless_lm_proxy (L, proxy);
   254 			// XXX lm_proxy_unref (proxy);
   254 			// XXX lm_proxy_unref (proxy);
   255 		} else
   255 		} else
   256 			lua_pushnil (L);
   256 			lua_pushnil (L);
   257 	}
   257 	}
   258 	return 1;
   258 	return 1;
   260 
   260 
   261 /// connection:ssl
   261 /// connection:ssl
   262 /// Gets or sets ssl object for connection.
   262 /// Gets or sets ssl object for connection.
   263 /// A: lm ssl object (optional)
   263 /// A: lm ssl object (optional)
   264 /// R: lm ssl object or nil (when called with no args) or lm connection object
   264 /// R: lm ssl object or nil (when called with no args) or lm connection object
   265 static int llm_connection_ssl (lua_State *L)
   265 static int ssl_lm_connection (lua_State *L)
   266 {
   266 {
   267 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   267 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   268 	if (lua_gettop (L) > 1) { // Set
   268 	if (lua_gettop (L) > 1) { // Set
   269 		llm_ssl_t *ssl = luaL_checklm_ssl (L, 2);
   269 		llm_ssl_t *ssl = luaL_checklm_ssl (L, 2);
   270 		lm_connection_set_ssl (object->connection, ssl->ssl);
   270 		lm_connection_set_ssl (object->connection, ssl->ssl);
   271 		lua_pop (L, 1);
   271 		lua_pop (L, 1);
   272 	} else { // Get
   272 	} else { // Get
   273 		LmSSL *ssl = lm_connection_get_ssl (object->connection);
   273 		LmSSL *ssl = lm_connection_get_ssl (object->connection);
   274 		lua_pop (L, 1);
   274 		lua_pop (L, 1);
   275 		if (ssl) {
   275 		if (ssl) {
   276 			llm_ssl_bless (L, ssl);
   276 			bless_lm_ssl (L, ssl);
   277 			// XXX lm_ssl_unref (ssl);
   277 			// XXX lm_ssl_unref (ssl);
   278 		} else
   278 		} else
   279 			lua_pushnil (L);
   279 			lua_pushnil (L);
   280 	}
   280 	}
   281 	return 1;
   281 	return 1;
   282 }
   282 }
   283 
   283 
   284 /// connection:close
   284 /// connection:close
   285 /// Close connection.
   285 /// Close connection.
   286 /// R: lm connection object or nil, string (error message)
   286 /// R: lm connection object or nil, string (error message)
   287 static int llm_connection_close (lua_State *L)
   287 static int close_lm_connection (lua_State *L)
   288 {
   288 {
   289 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   289 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   290 	GError *err = NULL;
   290 	GError *err = NULL;
   291 	if (lm_connection_close (object->connection, &err))
   291 	if (lm_connection_close (object->connection, &err))
   292 		return 1;
   292 		return 1;
   299 }
   299 }
   300 
   300 
   301 /// connection:status
   301 /// connection:status
   302 /// Returns string, describing connection state.
   302 /// Returns string, describing connection state.
   303 /// R: connection state
   303 /// R: connection state
   304 static int llm_connection_status (lua_State *L)
   304 static int status_lm_connection (lua_State *L)
   305 {
   305 {
   306 	llm_connection_t *connection = luaL_checklm_connection (L, 1);
   306 	llm_connection_t *connection = luaL_checklm_connection (L, 1);
   307 	luaL_pushenum (L, lm_connection_get_state (connection->connection), llm_connection_state);
   307 	luaL_pushenum (L, lm_connection_get_state (connection->connection), state_lm_connection);
   308 	return 1;
   308 	return 1;
   309 }
   309 }
   310 
   310 
   311 /// connection:send
   311 /// connection:send
   312 /// Sends message. If specified, handler function will be called upon receiving of response to this message.
   312 /// Sends message. If specified, handler function will be called upon receiving of response to this message.
   318 /// * connection, errmsg = connection:send ( message, function ( connection, message ) end )
   318 /// * connection, errmsg = connection:send ( message, function ( connection, message ) end )
   319 /// * connection, errmsg = connection:send ( message, handler )
   319 /// * connection, errmsg = connection:send ( message, handler )
   320 /// If connection is nil, errmsg contains error message.
   320 /// If connection is nil, errmsg contains error message.
   321 /// A: lm message object/string, message handler callback function/lm message handler object (optional)
   321 /// A: lm message object/string, message handler callback function/lm message handler object (optional)
   322 /// R: lm connection object or nil, string (error message)
   322 /// R: lm connection object or nil, string (error message)
   323 static int llm_connection_send (lua_State *L)
   323 static int send_lm_connection (lua_State *L)
   324 {
   324 {
   325 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   325 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   326 	int status;
   326 	int status;
   327 	GError *err = NULL;
   327 	GError *err = NULL;
   328 	if (lua_gettop (L) < 3) { // Send
   328 	if (lua_gettop (L) < 3) { // Send
   338 		LmMessageHandler *handler;
   338 		LmMessageHandler *handler;
   339 
   339 
   340 		cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   340 		cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   341 		cb->L         = L;
   341 		cb->L         = L;
   342 		handler = lm_message_handler_new (
   342 		handler = lm_message_handler_new (
   343 					(LmHandleMessageFunction)llm_message_handler_callback,
   343 					(LmHandleMessageFunction)callback_lm_handler,
   344 					cb, (GDestroyNotify)llm_callback_destroy);
   344 					cb, (GDestroyNotify)llm_callback_destroy);
   345 		status = lm_connection_send_with_reply (object->connection,
   345 		status = lm_connection_send_with_reply (object->connection,
   346 							message->message, handler, &err);
   346 							message->message, handler, &err);
   347 		lm_message_handler_unref (handler);
   347 		lm_message_handler_unref (handler);
   348 	} else { // Send w/reply, handler
   348 	} else { // Send w/reply, handler
   349 		llm_message_t *message = luaL_checklm_message (L, 2);
   349 		llm_message_t *message = luaL_checklm_message (L, 2);
   350 		llm_message_handler_t *handler = luaL_checklm_message_handler (L, 3);
   350 		llm_handler_t *handler = luaL_checklm_handler (L, 3);
   351 		status = lm_connection_send_with_reply (object->connection, message->message,
   351 		status = lm_connection_send_with_reply (object->connection, message->message,
   352 							handler->message_handler, &err);
   352 							handler->handler, &err);
   353 		lua_pop (L, 1);
   353 		lua_pop (L, 1);
   354 	};
   354 	};
   355 	lua_pop (L, 1);
   355 	lua_pop (L, 1);
   356 	if (status)
   356 	if (status)
   357 		return 1;
   357 		return 1;
   368 /// To unregister handler, omit the priority argument.
   368 /// To unregister handler, omit the priority argument.
   369 /// Handler function can be specified as plain function or message handler object.
   369 /// Handler function can be specified as plain function or message handler object.
   370 /// Though, you can unregister only a message handler object.
   370 /// Though, you can unregister only a message handler object.
   371 /// A: message handler callback function or lm message handler object, message type, handler priority (optional)
   371 /// A: message handler callback function or lm message handler object, message type, handler priority (optional)
   372 /// R: lm connection object
   372 /// R: lm connection object
   373 static int llm_connection_handler (lua_State *L)
   373 static int handler_lm_connection (lua_State *L)
   374 {
   374 {
   375 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   375 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   376 	int type = luaL_checkenum (L, 3, llm_message_type);
   376 	int type = luaL_checkenum (L, 3, type_lm_message);
   377 
   377 
   378 	if (lua_gettop (L) > 3) { // Register
   378 	if (lua_gettop (L) > 3) { // Register
   379 		int priority = luaL_checkenum (L, 4, llm_handler_priority);
   379 		int priority = luaL_checkenum (L, 4, priority_lm_handler);
   380 
   380 
   381 		if (lua_isfunction (L, 2)) { // Function
   381 		if (lua_isfunction (L, 2)) { // Function
   382 			LmMessageHandler *handler;
   382 			LmMessageHandler *handler;
   383 			llm_callback_t *cb = luaL_malloc (L, sizeof (llm_callback_t));
   383 			llm_callback_t *cb = luaL_malloc (L, sizeof (llm_callback_t));
   384 			lua_pushvalue (L, 2);
   384 			lua_pushvalue (L, 2);
   385 			cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   385 			cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   386 			cb->L         = L;
   386 			cb->L         = L;
   387 
   387 
   388 			handler = lm_message_handler_new (
   388 			handler = lm_message_handler_new (
   389 					(LmHandleMessageFunction)llm_message_handler_callback,
   389 					(LmHandleMessageFunction)callback_lm_handler,
   390 					cb, (GDestroyNotify)llm_callback_destroy);
   390 					cb, (GDestroyNotify)llm_callback_destroy);
   391 			lm_connection_register_message_handler (object->connection,
   391 			lm_connection_register_message_handler (object->connection,
   392 								handler, type, priority);
   392 								handler, type, priority);
   393 			lm_message_handler_unref (handler);
   393 			lm_message_handler_unref (handler);
   394 		} else { // Object
   394 		} else { // Object
   395 			llm_message_handler_t *handler = luaL_checklm_message_handler (L, 2);
   395 			llm_handler_t *handler = luaL_checklm_handler (L, 2);
   396 			lm_connection_register_message_handler (object->connection,
   396 			lm_connection_register_message_handler (object->connection,
   397 								handler->message_handler,
   397 								handler->handler,
   398 								type, priority);
   398 								type, priority);
   399 		}
   399 		}
   400 		lua_pop (L, 1);
   400 		lua_pop (L, 1);
   401 	} else { // Unregister
   401 	} else { // Unregister
   402 		llm_message_handler_t *handler = luaL_checklm_message_handler (L, 2);
   402 		llm_handler_t *handler = luaL_checklm_handler (L, 2);
   403 		lm_connection_unregister_message_handler (object->connection,
   403 		lm_connection_unregister_message_handler (object->connection,
   404 							  handler->message_handler,
   404 							  handler->handler,
   405 							  type);
   405 							  type);
   406 	}
   406 	}
   407 	lua_pop (L, 2);
   407 	lua_pop (L, 2);
   408 	return 1;
   408 	return 1;
   409 }
   409 }
   412 /// Function, that will be called when disconnection occurs.
   412 /// Function, that will be called when disconnection occurs.
   413 /// A: lm connection object, disconnect reason
   413 /// A: lm connection object, disconnect reason
   414 void llm_disconnect_callback (LmConnection *connection, LmDisconnectReason reason, llm_callback_t *cb)
   414 void llm_disconnect_callback (LmConnection *connection, LmDisconnectReason reason, llm_callback_t *cb)
   415 {
   415 {
   416 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   416 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   417 	llm_connection_bless (cb->L, connection);
   417 	bless_lm_connection (cb->L, connection);
   418 	// XXX lm_connection_unref (connection);
   418 	// XXX lm_connection_unref (connection);
   419 	luaL_pushenum (cb->L, reason, llm_disconnect_reason);
   419 	luaL_pushenum (cb->L, reason, llm_disconnect_reason);
   420 	if (lua_pcall (cb->L, 2, 0, 0)) {
   420 	if (lua_pcall (cb->L, 2, 0, 0)) {
   421 		W ("Disconnect callback error: %s", lua_tostring (cb->L, -1));
   421 		W ("Disconnect callback error: %s", lua_tostring (cb->L, -1));
   422 		lua_pop (cb->L, 1);
   422 		lua_pop (cb->L, 1);
   425 
   425 
   426 /// connection:ondisconnect
   426 /// connection:ondisconnect
   427 /// Sets callback, that will be called on connection disconnect.
   427 /// Sets callback, that will be called on connection disconnect.
   428 /// A: disconnect callback function
   428 /// A: disconnect callback function
   429 /// R: lm connection object
   429 /// R: lm connection object
   430 static int llm_connection_ondisconnect (lua_State *L)
   430 static int ondisconnect_lm_connection (lua_State *L)
   431 {
   431 {
   432 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   432 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   433 	llm_callback_t *cb;
   433 	llm_callback_t *cb;
   434 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   434 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
   435 
   435 
   444 }
   444 }
   445 
   445 
   446 /// connection:open_wait
   446 /// connection:open_wait
   447 /// Synchronous open call, that will block until connection will be opened.
   447 /// Synchronous open call, that will block until connection will be opened.
   448 /// R: lm connection object or nil, string (error message)
   448 /// R: lm connection object or nil, string (error message)
   449 static int llm_connection_open_wait (lua_State *L)
   449 static int open_wait_lm_connection (lua_State *L)
   450 {
   450 {
   451 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   451 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   452 	GError *err = NULL;
   452 	GError *err = NULL;
   453 	if (lm_connection_open_and_block (object->connection, &err))
   453 	if (lm_connection_open_and_block (object->connection, &err))
   454 		return 1;
   454 		return 1;
   462 
   462 
   463 /// connection:authenticate_wait
   463 /// connection:authenticate_wait
   464 /// Synchronous authentication call, that will wait until the end of authentication.
   464 /// Synchronous authentication call, that will wait until the end of authentication.
   465 /// A: string (username), string (password), string (resource)
   465 /// A: string (username), string (password), string (resource)
   466 /// R: lm connection object or nil, string (error message)
   466 /// R: lm connection object or nil, string (error message)
   467 static int llm_connection_authenticate_wait (lua_State *L)
   467 static int authenticate_wait_lm_connection (lua_State *L)
   468 {
   468 {
   469 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   469 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   470 	const char *username = luaL_checkstring (L, 2);
   470 	const char *username = luaL_checkstring (L, 2);
   471 	const char *password = luaL_checkstring (L, 3);
   471 	const char *password = luaL_checkstring (L, 3);
   472 	const char *resource = luaL_checkstring (L, 4);
   472 	const char *resource = luaL_checkstring (L, 4);
   484 
   484 
   485 /// connection:send_wait
   485 /// connection:send_wait
   486 /// Synchronous call, that will send message and wait for reply to it.
   486 /// Synchronous call, that will send message and wait for reply to it.
   487 /// A: lm message object
   487 /// A: lm message object
   488 /// R: lm message object or nil, string (error message)
   488 /// R: lm message object or nil, string (error message)
   489 static int llm_connection_send_wait (lua_State *L)
   489 static int send_wait_lm_connection (lua_State *L)
   490 {
   490 {
   491 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   491 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   492 	llm_message_t *message = luaL_checklm_message (L, 2);
   492 	llm_message_t *message = luaL_checklm_message (L, 2);
   493 	GError *err = NULL;
   493 	GError *err = NULL;
   494 	LmMessage *new = lm_connection_send_with_reply_and_block (object->connection,
   494 	LmMessage *new = lm_connection_send_with_reply_and_block (object->connection,
   497 		I ("Synchronous message sending failed: %s", err->message);
   497 		I ("Synchronous message sending failed: %s", err->message);
   498 		lua_pushnil (L);
   498 		lua_pushnil (L);
   499 		lua_pushstring (L, err->message);
   499 		lua_pushstring (L, err->message);
   500 		return 2;
   500 		return 2;
   501 	} else {
   501 	} else {
   502 		llm_message_bless (L, new);
   502 		bless_lm_message (L, new);
   503 		lm_message_unref (new); // XXX
   503 		lm_message_unref (new); // XXX
   504 		return 1;
   504 		return 1;
   505 	}
   505 	}
   506 }
   506 }
   507 
   507 
   508 /// connection:pointer
   508 /// connection:pointer
   509 /// Returns pointer to underlying C loudmouth structure.
   509 /// Returns pointer to underlying C loudmouth structure.
   510 /// R: lightuserdata
   510 /// R: lightuserdata
   511 static int llm_connection_pointer (lua_State *L)
   511 static int pointer_lm_connection (lua_State *L)
   512 {
   512 {
   513 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   513 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   514 	lua_pushlightuserdata (L, object->connection);
   514 	lua_pushlightuserdata (L, object->connection);
   515 	lua_remove (L, -2);
   515 	lua_remove (L, -2);
   516 	return 1;
   516 	return 1;
   517 }
   517 }
   518 
   518 
   519 static int llm_connection_gc (lua_State *L)
   519 static int gc_lm_connection (lua_State *L)
   520 {
   520 {
   521 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   521 	llm_connection_t *object = luaL_checklm_connection (L, 1);
   522 	D ("Connection %X gc called", (int) object);
   522 	D ("Connection %X gc called", (int) object);
   523 	lm_connection_unref (object->connection);
   523 	lm_connection_unref (object->connection);
   524 	return 0;
   524 	return 0;
   525 }
   525 }
   526 
   526 
   527 static const luaL_Reg llm_connection_reg_f[] = {
   527 static const luaL_Reg reg_f_lm_connection[] = {
   528 	{ "new",   llm_connection_new       },
   528 	{ "new",   new_lm_connection       },
   529 	{ "bless", llm_connection_bless_lua },
   529 	{ "bless", bless_lua_lm_connection },
   530 	{ NULL,    NULL                     },
   530 	{ NULL,    NULL                     },
   531 };
   531 };
   532 
   532 
   533 static const luaL_Reg llm_connection_reg_m[] = {
   533 static const luaL_Reg reg_m_lm_connection[] = {
   534 	{ "open",                llm_connection_open                },
   534 	{ "open",                open_lm_connection                },
   535 	{ "close",               llm_connection_close               },
   535 	{ "close",               close_lm_connection               },
   536 	{ "authenticate",        llm_connection_authenticate        },
   536 	{ "authenticate",        authenticate_lm_connection        },
   537 	{ "port",                llm_connection_port                },
   537 	{ "port",                port_lm_connection                },
   538 	{ "server",              llm_connection_server              },
   538 	{ "server",              server_lm_connection              },
   539 	{ "jid",                 llm_connection_jid                 },
   539 	{ "jid",                 jid_lm_connection                 },
   540 	{ "keep_alive_rate",     llm_connection_keep_alive_rate     },
   540 	{ "keep_alive_rate",     keep_alive_rate_lm_connection     },
   541 	{ "state",               llm_connection_status              },
   541 	{ "state",               status_lm_connection              },
   542 	{ "proxy",               llm_connection_proxy               },
   542 	{ "proxy",               proxy_lm_connection               },
   543 	{ "ssl",                 llm_connection_ssl                 },
   543 	{ "ssl",                 ssl_lm_connection                 },
   544 	{ "send",                llm_connection_send                },
   544 	{ "send",                send_lm_connection                },
   545 	{ "handler",             llm_connection_handler             },
   545 	{ "handler",             handler_lm_connection             },
   546 	{ "ondisconnect",        llm_connection_ondisconnect        },
   546 	{ "ondisconnect",        ondisconnect_lm_connection        },
   547 	{ "open_wait",           llm_connection_open_wait           },
   547 	{ "open_wait",           open_wait_lm_connection           },
   548 	{ "authenticate_wait",   llm_connection_authenticate_wait   },
   548 	{ "authenticate_wait",   authenticate_wait_lm_connection   },
   549 	{ "send_wait",           llm_connection_send_wait           },
   549 	{ "send_wait",           send_wait_lm_connection           },
   550 	{ "pointer",             llm_connection_pointer             },
   550 	{ "pointer",             pointer_lm_connection             },
   551 	{ "__gc",                llm_connection_gc                  },
   551 	{ "__gc",                gc_lm_connection                  },
   552 	{ NULL,                  NULL                               },
   552 	{ NULL,                  NULL                               },
   553 };
   553 };
   554 
   554 
   555 int luaopen_lm_connection (lua_State *L)
   555 int luaopen_lm_connection (lua_State *L)
   556 {
   556 {
   557 	luaL_newmetatable (L, "loudmouth.connection");
   557 	luaL_newmetatable (L, "loudmouth.connection");
   558 	lua_pushstring (L, "__index");
   558 	lua_pushstring (L, "__index");
   559 	lua_pushvalue (L, -2);
   559 	lua_pushvalue (L, -2);
   560 	lua_settable (L, -3);
   560 	lua_settable (L, -3);
   561 	luaL_register (L, NULL, llm_connection_reg_m);
   561 	luaL_register (L, NULL, reg_m_lm_connection);
   562 	lua_pop (L, 1);
   562 	lua_pop (L, 1);
   563 	luaL_register (L, "lm.connection", llm_connection_reg_f);
   563 	luaL_register (L, "lm.connection", reg_f_lm_connection);
   564 	return 1;
   564 	return 1;
   565 }
   565 }
   566 
   566