bindings/ruby/rblm-connection.c
author Mikael Hallendal <micke@imendio.com>
Thu, 10 Apr 2008 21:14:27 +0200
changeset 389 95287bd6f233
parent 388 4eec2cf1fa08
permissions -rw-r--r--
Added support for add_message_handler to ruby bindings

#include "rblm.h"
#include "rblm-private.h"

VALUE lm_cConnection;

VALUE conn_set_server (VALUE self, VALUE server);

/* -- START of GMainContext hack -- 
 * This is a hack to get the GMainContext from a ruby VALUE, this will break if
 * internals change in Ruby/GLib.
 */
typedef struct {
    gpointer boxed;
    gboolean own;
    gsize    type;
} boxed_holder;

static GMainContext *
rb_lm_hack_get_main_context_from_rval (VALUE ctx_rval)
{
	boxed_holder *holder;

	Data_Get_Struct (ctx_rval, boxed_holder, holder);

	return holder->boxed;
}
/* -- END of GMainContext hack -- */

LmConnection *
rb_lm_connection_from_ruby_object (VALUE obj)
{
	LmConnection *conn;

	if (!rb_lm__is_kind_of (obj, lm_cConnection)) {
		rb_raise (rb_eTypeError, "not a LmConnection");
	}

	Data_Get_Struct (obj, LmConnection, conn);

	return conn;
}

void
conn_free (LmConnection *self)
{
	lm_connection_unref (self);
}

VALUE
conn_allocate (VALUE klass)
{
	return Data_Wrap_Struct (klass, NULL, conn_free, NULL);
}

VALUE
conn_initialize (int argc, VALUE *argv, VALUE self)
{
	LmConnection *conn;
	char         *srv_str = NULL;
	VALUE         server, context;

	rb_scan_args (argc, argv, "02", &server, &context);

	if (!NIL_P (context)) {
		GMainContext *ctx;

		ctx = rb_lm_hack_get_main_context_from_rval (context);

		conn = lm_connection_new_with_context (NULL, ctx);
	} else {
		conn = lm_connection_new (NULL);
	}

	DATA_PTR (self) = conn;

	if (!NIL_P (server)) {
		conn_set_server (self, server);
	}

	return self;
}

static void
open_callback (LmConnection *conn, gboolean success, gpointer user_data)
{
	rb_funcall((VALUE)user_data, rb_intern ("call"), 1,
		   GBOOL2RVAL (success));
}

VALUE
conn_open (int argc, VALUE *argv, VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);
	VALUE         func;

	rb_scan_args (argc, argv, "0&", &func);
	if (NIL_P (func)) {
		func = rb_block_proc ();
	}

	return GBOOL2RVAL (lm_connection_open (conn, open_callback, 
					       (gpointer) func, NULL, NULL));
}

VALUE
conn_close (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return GBOOL2RVAL (lm_connection_close (conn, NULL));
}

static void
auth_callback (LmConnection *conn, gboolean success, gpointer user_data)
{
	rb_funcall((VALUE)user_data, rb_intern ("call"), 1,
		   GBOOL2RVAL (success));
}

VALUE
conn_auth (int argc, VALUE *argv, VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);
	VALUE         name, password, resource, func; 

	rb_scan_args (argc, argv, "21&", &name, &password, &resource, &func);
	if (NIL_P (func)) {
		func = rb_block_proc ();
	}

	return GBOOL2RVAL (lm_connection_authenticate (conn, 
						       StringValuePtr (name),
						       StringValuePtr (password), 
						       StringValuePtr (resource),
						       auth_callback,
						       (gpointer) func, NULL,
						       NULL));
}

VALUE
conn_set_keep_alive_rate (VALUE self, VALUE rate)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	lm_connection_set_keep_alive_rate (conn, NUM2UINT (rate));

	return Qnil;
}

/*
 * VALUE
conn_get_keep_alive_rate (VALUE self)
{
	LmConnection *connection;
} */

VALUE
conn_is_open (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return GBOOL2RVAL (lm_connection_is_open (conn));
}

VALUE
conn_is_authenticated (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return GBOOL2RVAL (lm_connection_is_authenticated (conn));
}

VALUE
conn_get_server (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return rb_str_new2 (lm_connection_get_server (conn));
}

VALUE
conn_set_server (VALUE self, VALUE server)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	if (!rb_respond_to (server, rb_intern ("to_s"))) {
		rb_raise (rb_eArgError, "server should respond to to_s");
	} else {
		VALUE str_val = rb_funcall (server, rb_intern ("to_s"), 0);
		lm_connection_set_server (conn, StringValuePtr (str_val));
	}

	return Qnil;
}

VALUE
conn_get_jid (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return rb_str_new2 (lm_connection_get_jid (conn));
}

VALUE
conn_set_jid (VALUE self, VALUE jid)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	if (!rb_respond_to (jid, rb_intern ("to_s"))) {
		rb_raise (rb_eArgError, "jid should respond to to_s");
	} else {
		VALUE str_val = rb_funcall (jid, rb_intern ("to_s"), 0);
		lm_connection_set_jid (conn, StringValuePtr (str_val));
	}

	return Qnil;
}

VALUE
conn_get_port (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return UINT2NUM (lm_connection_get_port (conn));
}

VALUE
conn_set_port (VALUE self, VALUE port)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	lm_connection_set_port (conn, NUM2UINT (port));

	return Qnil;
}

VALUE
conn_get_ssl (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return LMSSL2RVAL (lm_connection_get_ssl (conn));
}

VALUE
conn_set_ssl (VALUE self, VALUE ssl_rval)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);
	LmSSL        *ssl  = rb_lm_ssl_from_ruby_object (ssl_rval);

	lm_connection_set_ssl (conn, ssl);

	return Qnil;
}

VALUE
conn_get_proxy (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return LMPROXY2RVAL (lm_connection_get_proxy (conn));
}

VALUE
conn_set_proxy (VALUE self, VALUE proxy_rval)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);
	LmProxy      *proxy = rb_lm_proxy_from_ruby_object (proxy_rval);

	lm_connection_set_proxy (conn, proxy);

	return Qnil;
}

VALUE
conn_send (VALUE self, VALUE msg)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);
	LmMessage    *m = rb_lm_message_from_ruby_object (msg);

	return GBOOL2RVAL (lm_connection_send (conn, m, NULL));
}

VALUE
conn_get_state (VALUE self)
{
	LmConnection *conn = rb_lm_connection_from_ruby_object (self);

	return INT2FIX (lm_connection_get_state (conn));
}

static LmHandlerResult
msg_handler_cb (LmMessageHandler *handler,
		LmConnection     *connection,
		LmMessage        *message,
		gpointer          user_data)
{
	rb_funcall ((VALUE)user_data, rb_intern ("call"), 1, 
		    LMMESSAGE2RVAL (message));

	return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
}

VALUE
conn_add_msg_handler (int argc, VALUE *argv, VALUE self)
{
	LmConnection     *conn = rb_lm_connection_from_ruby_object (self);
	VALUE             type, func;
	LmMessageHandler *handler;

	rb_scan_args (argc, argv, "1&", &type, &func);
	if (NIL_P (func)) {
		func = rb_block_proc ();
	}

	handler = lm_message_handler_new (msg_handler_cb, (gpointer) func, NULL);

	lm_connection_register_message_handler (conn, handler,
						rb_lm_message_type_from_ruby_object (type),
						LM_HANDLER_PRIORITY_NORMAL);
	lm_message_handler_unref (handler);

	return Qnil;
}

void
Init_lm_connection (VALUE lm_mLM)
{
	lm_cConnection = rb_define_class_under (lm_mLM, "Connection", 
						rb_cObject);

	rb_define_alloc_func (lm_cConnection, conn_allocate);

	rb_define_method (lm_cConnection, "initialize", conn_initialize, -1);
	rb_define_method (lm_cConnection, "open", conn_open, -1);
	rb_define_method (lm_cConnection, "close", conn_close, 0);
	rb_define_method (lm_cConnection, "authenticate", conn_auth, -1);
	rb_define_method (lm_cConnection, "keep_alive_rate=", conn_set_keep_alive_rate, 1);
	/* rb_define_method (lm_cConnection, "keep_alive_rate", conn_get_keep_alive_rate, 0); */
	rb_define_method (lm_cConnection, "open?", conn_is_open, 0);
	rb_define_method (lm_cConnection, "authenticated?", conn_is_authenticated, 0);
	rb_define_method (lm_cConnection, "server", conn_get_server, 0);
	rb_define_method (lm_cConnection, "server=", conn_set_server, 1);
	rb_define_method (lm_cConnection, "jid", conn_get_jid, 0);
	rb_define_method (lm_cConnection, "jid=", conn_set_jid, 1);
	rb_define_method (lm_cConnection, "port", conn_get_port, 0);
	rb_define_method (lm_cConnection, "port=", conn_set_port, 1);

	rb_define_method (lm_cConnection, "ssl", conn_get_ssl, 0);
	rb_define_method (lm_cConnection, "ssl=", conn_set_ssl, 1);
	rb_define_method (lm_cConnection, "proxy", conn_get_proxy, 0);
	rb_define_method (lm_cConnection, "proxy=", conn_set_proxy, 1);

	/* Use one send message and check if there is a block passed? */
	
	rb_define_method (lm_cConnection, "send", conn_send, 1);
	/*
	rb_define_method (lm_cConnection, "send_with_reply", conn_send_with_reply, -1);
	rb_define_method (lm_cConnection, "send_raw", conn_send_raw, 1);
	*/

	rb_define_method (lm_cConnection, "state", conn_get_state, 0);
	rb_define_method (lm_cConnection, "add_message_handler", conn_add_msg_handler, -1);
}