Made LmSocket into an interface and hooked up implementation of it in LmTcpSocket.
This design allows for the unit test framework to hook into it's mock socket
object in order to short cut the network communication.
--- a/loudmouth/Makefile.am Tue Jul 08 00:57:01 2008 +0300
+++ b/loudmouth/Makefile.am Wed Jul 09 15:56:07 2008 +0300
@@ -56,6 +56,8 @@
lm-sock.c \
lm-socket.c \
lm-socket.h \
+ lm-tcp-socket.c \
+ lm-tcp-socket.h \
lm-old-socket.c \
lm-old-socket.h \
asyncns.c \
--- a/loudmouth/lm-old-socket.h Tue Jul 08 00:57:01 2008 +0300
+++ b/loudmouth/lm-old-socket.h Wed Jul 09 15:56:07 2008 +0300
@@ -18,8 +18,8 @@
* Boston, MA 02111-1307, USA.
*/
-#ifndef __LM_SOCKET_H__
-#define __LM_SOCKET_H__
+#ifndef __LM_OLD_SOCKET_H__
+#define __LM_OLD_SOCKET_H__
#include <glib.h>
@@ -73,5 +73,5 @@
gboolean lm_old_socket_set_keepalive (LmOldSocket *socket, int delay);
gchar * lm_old_socket_get_local_host (LmOldSocket *socket);
-#endif /* __LM_SOCKET_H__ */
+#endif /* __LM_OLD_SOCKET_H__ */
--- a/loudmouth/lm-socket.c Tue Jul 08 00:57:01 2008 +0300
+++ b/loudmouth/lm-socket.c Wed Jul 09 15:56:07 2008 +0300
@@ -20,155 +20,87 @@
#include <config.h>
-#include "lm-marshal.h"
#include "lm-socket.h"
-#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), LM_TYPE_DUMMY, LmSocketPriv))
-
-typedef struct LmSocketPriv LmSocketPriv;
-struct LmSocketPriv {
- gint my_prop;
-};
+static void socket_base_init (LmSocketIface *iface);
-static void socket_finalize (GObject *object);
-static void socket_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec);
-static void socket_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec);
-
-G_DEFINE_TYPE (LmSocket, lm_socket, G_TYPE_OBJECT)
-
-enum {
- PROP_0,
- PROP_MY_PROP
-};
-
-enum {
- SIGNAL_NAME,
- LAST_SIGNAL
-};
+GType
+lm_socket_get_type (void)
+{
+ static GType iface_type = 0;
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void
-lm_socket_class_init (LmSocketClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- object_class->finalize = socket_finalize;
- object_class->get_property = socket_get_property;
- object_class->set_property = socket_set_property;
+ if (!iface_type) {
+ static const GTypeInfo iface_info = {
+ sizeof (LmSocketIface),
+ (GBaseInitFunc) socket_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
- g_object_class_install_property (object_class,
- PROP_MY_PROP,
- g_param_spec_string ("my-prop",
- "My Prop",
- "My Property",
- NULL,
- G_PARAM_READWRITE));
-
- signals[SIGNAL_NAME] =
- g_signal_new ("signal-name",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- lm_marshal_VOID__INT,
- G_TYPE_NONE,
- 1, G_TYPE_INT);
-
- g_type_class_add_private (object_class, sizeof (LmSocketPriv));
+ iface_type = g_type_register_static (G_TYPE_INTERFACE,
+ "LmSocketIface",
+ &iface_info,
+ 0);
+
+ g_type_interface_add_prerequisite (iface_type, G_TYPE_OBJECT);
+ }
+
+ return iface_type;
}
static void
-lm_socket_init (LmSocket *dummy)
-{
- LmSocketPriv *priv;
-
- priv = GET_PRIV (dummy);
-
-}
-
-static void
-socket_finalize (GObject *object)
+socket_base_init (LmSocketIface *iface)
{
- LmSocketPriv *priv;
-
- priv = GET_PRIV (object);
-
- (G_OBJECT_CLASS (lm_socket_parent_class)->finalize) (object);
-}
-
-static void
-socket_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec)
-{
- LmSocketPriv *priv;
-
- priv = GET_PRIV (object);
+ static gboolean initialized = FALSE;
- switch (param_id) {
- case PROP_MY_PROP:
- g_value_set_int (value, priv->my_prop);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- };
-}
-
-static void
-socket_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- LmSocketPriv *priv;
-
- priv = GET_PRIV (object);
-
- switch (param_id) {
- case PROP_MY_PROP:
- priv->my_prop = g_value_get_int (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- };
+ if (!initialized) {
+ /* create interface signals here. */
+ initialized = TRUE;
+ }
}
LmSocket *
lm_socket_new (const gchar *host, guint port)
{
+ g_return_val_if_fail (host != NULL, NULL);
+
return NULL;
}
/* Use DNS lookup to find the port and the host */
LmSocket *
-lm_socket_new_srv (const gchar *service)
+lm_socket_new_to_service (const gchar *service)
{
+ g_return_val_if_fail (service != NULL, NULL);
+
return NULL;
}
void
lm_socket_connect (LmSocket *socket)
{
+ g_return_if_fail (LM_IS_SOCKET (socket));
+
+
/* Initiate the connection process */
/* DNS lookup, connect thing, create IOchannel etc */
+ if (!LM_SOCKET_GET_IFACE(socket)->write) {
+ g_assert_not_reached ();
+ }
+
+ LM_SOCKET_GET_IFACE(socket)->connect (socket);
}
gboolean
-lm_socket_write (LmSocket *socket,
- gchar *data,
- gsize len)
+lm_socket_write (LmSocket *socket, gchar *buf, gsize len)
{
- return FALSE;
+ g_return_val_if_fail (LM_IS_SOCKET (socket), FALSE);
+ g_return_val_if_fail (buf != NULL, FALSE);
+
+ if (!LM_SOCKET_GET_IFACE(socket)->write) {
+ g_assert_not_reached ();
+ }
+
+ return LM_SOCKET_GET_IFACE(socket)->write (socket, buf, len);
}
gboolean
@@ -177,12 +109,25 @@
gsize buf_len,
gsize read_len)
{
- return FALSE;
+ g_return_val_if_fail (LM_IS_SOCKET (socket), FALSE);
+ g_return_val_if_fail (buf != NULL, FALSE);
+
+ if (!LM_SOCKET_GET_IFACE(socket)->read) {
+ g_assert_not_reached ();
+ }
+
+ return LM_SOCKET_GET_IFACE(socket)->read (socket, buf, buf_len, read_len);
}
void
lm_socket_disconnect (LmSocket *socket)
{
+ g_return_if_fail (LM_IS_SOCKET (socket));
+
+ if (!LM_SOCKET_GET_IFACE(socket)->disconnect) {
+ g_assert_not_reached ();
+ }
+
+ LM_SOCKET_GET_IFACE(socket)->disconnect (socket);
}
-
--- a/loudmouth/lm-socket.h Tue Jul 08 00:57:01 2008 +0300
+++ b/loudmouth/lm-socket.h Wed Jul 09 15:56:07 2008 +0300
@@ -23,43 +23,51 @@
#include <glib-object.h>
+#include "lm-message.h"
+#include "lm-internals.h"
+
G_BEGIN_DECLS
-#define LM_TYPE_DUMMY (lm_socket_get_type ())
-#define LM_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LM_TYPE_DUMMY, LmSocket))
-#define LM_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LM_TYPE_DUMMY, LmSocketClass))
-#define LM_IS_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LM_TYPE_DUMMY))
-#define LM_IS_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LM_TYPE_DUMMY))
-#define LM_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LM_TYPE_DUMMY, LmSocketClass))
+#define LM_TYPE_SOCKET (lm_socket_get_type())
+#define LM_SOCKET(o) (G_TYPE_CHECK_INSTANCE_CAST((o), LM_TYPE_SOCKET, LmSocket))
+#define LM_IS_SOCKET(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), LM_TYPE_SOCKET))
+#define LM_SOCKET_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE((o), LM_TYPE_SOCKET, LmSocketIface))
+
+typedef struct _LmSocket LmSocket;
+typedef struct _LmSocketIface LmSocketIface;
+
+struct _LmSocketIface {
+ GTypeInterface parent;
-typedef struct LmSocket LmSocket;
-typedef struct LmSocketClass LmSocketClass;
-
-struct LmSocket {
- GObject parent;
+ /* <vtable> */
+ void (*connect) (LmSocket *socket);
+ gboolean (*write) (LmSocket *socket,
+ gchar *buf,
+ gsize len);
+ gboolean (*read) (LmSocket *socket,
+ gchar *buf,
+ gsize buf_len,
+ gsize read_len);
+ void (*disconnect) (LmSocket *socket);
};
-struct LmSocketClass {
- GObjectClass parent_class;
-};
+GType lm_socket_get_type (void);
-GType lm_socket_get_type (void);
-
-LmSocket * lm_socket_new (const gchar *host,
- guint port);
+LmSocket * lm_socket_new (const gchar *host,
+ guint port);
/* Use DNS lookup to find the port and the host */
-LmSocket * lm_socket_new_srv (const gchar *service);
+LmSocket * lm_socket_new_to_service (const gchar *service);
/* All async functions so doesn't make a lot of sense to return anything */
-void lm_socket_connect (LmSocket *socket);
-gboolean lm_socket_write (LmSocket *socket,
- gchar *data,
- gsize len);
-gboolean lm_socket_read (LmSocket *socket,
- gchar *buf,
- gsize buf_len,
- gsize read_len);
-void lm_socket_disconnect (LmSocket *socket);
+void lm_socket_connect (LmSocket *socket);
+gboolean lm_socket_write (LmSocket *socket,
+ gchar *buf,
+ gsize len);
+gboolean lm_socket_read (LmSocket *socket,
+ gchar *buf,
+ gsize buf_len,
+ gsize read_len);
+void lm_socket_disconnect (LmSocket *socket);
G_END_DECLS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/loudmouth/lm-tcp-socket.c Wed Jul 09 15:56:07 2008 +0300
@@ -0,0 +1,195 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "lm-marshal.h"
+#include "lm-tcp-socket.h"
+#include "lm-socket.h"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), LM_TYPE_TCP_SOCKET, LmTcpSocketPriv))
+
+typedef struct LmTcpSocketPriv LmTcpSocketPriv;
+struct LmTcpSocketPriv {
+ gint my_prop;
+};
+
+static void tcp_socket_iface_init (LmSocketIface *iface);
+static void tcp_socket_finalize (GObject *object);
+static void tcp_socket_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void tcp_socket_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void tcp_socket_connect (LmSocket *socket);
+static gboolean tcp_socket_write (LmSocket *socket,
+ gchar *data,
+ gsize len);
+static gboolean tcp_socket_read (LmSocket *socket,
+ gchar *buf,
+ gsize buf_len,
+ gsize read_len);
+static void tcp_socket_disconnect (LmSocket *socket);
+
+G_DEFINE_TYPE_WITH_CODE (LmTcpSocket, lm_tcp_socket, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (LM_TYPE_SOCKET,
+ tcp_socket_iface_init))
+
+enum {
+ PROP_0,
+ PROP_MY_PROP
+};
+
+enum {
+ SIGNAL_NAME,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+lm_tcp_socket_class_init (LmTcpSocketClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = tcp_socket_finalize;
+ object_class->get_property = tcp_socket_get_property;
+ object_class->set_property = tcp_socket_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_MY_PROP,
+ g_param_spec_string ("my-prop",
+ "My Prop",
+ "My Property",
+ NULL,
+ G_PARAM_READWRITE));
+
+ signals[SIGNAL_NAME] =
+ g_signal_new ("signal-name",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ lm_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1, G_TYPE_INT);
+
+ g_type_class_add_private (object_class, sizeof (LmTcpSocketPriv));
+}
+
+static void
+tcp_socket_iface_init (LmSocketIface *iface)
+{
+ iface->connect = tcp_socket_connect;
+ iface->write = tcp_socket_write;
+ iface->read = tcp_socket_read;
+ iface->disconnect = tcp_socket_disconnect;
+}
+
+static void
+lm_tcp_socket_init (LmTcpSocket *dummy)
+{
+ LmTcpSocketPriv *priv;
+
+ priv = GET_PRIV (dummy);
+
+}
+
+static void
+tcp_socket_finalize (GObject *object)
+{
+ LmTcpSocketPriv *priv;
+
+ priv = GET_PRIV (object);
+
+ (G_OBJECT_CLASS (lm_tcp_socket_parent_class)->finalize) (object);
+}
+
+static void
+tcp_socket_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ LmTcpSocketPriv *priv;
+
+ priv = GET_PRIV (object);
+
+ switch (param_id) {
+ case PROP_MY_PROP:
+ g_value_set_int (value, priv->my_prop);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
+static void
+tcp_socket_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ LmTcpSocketPriv *priv;
+
+ priv = GET_PRIV (object);
+
+ switch (param_id) {
+ case PROP_MY_PROP:
+ priv->my_prop = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
+static void
+tcp_socket_connect (LmSocket *socket)
+{
+ /* Initiate the connection process */
+ /* DNS lookup, connect thing, create IOchannel etc */
+}
+
+static gboolean
+tcp_socket_write (LmSocket *socket, gchar *data, gsize len)
+{
+ return FALSE;
+}
+
+static gboolean
+tcp_socket_read (LmSocket *socket,
+ gchar *buf,
+ gsize buf_len,
+ gsize read_len)
+{
+ return FALSE;
+}
+
+static void
+tcp_socket_disconnect (LmSocket *socket)
+{
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/loudmouth/lm-tcp-socket.h Wed Jul 09 15:56:07 2008 +0300
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LM_TCP_SOCKET_H__
+#define __LM_TCP_SOCKET_H__
+
+#include <glib-object.h>
+
+#include "lm-socket.h"
+
+G_BEGIN_DECLS
+
+#define LM_TYPE_TCP_SOCKET (lm_tcp_socket_get_type ())
+#define LM_TCP_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LM_TYPE_TCP_SOCKET, LmTcpSocket))
+#define LM_TCP_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LM_TYPE_TCP_SOCKET, LmTcpSocketClass))
+#define LM_IS_TCP_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LM_TYPE_TCP_SOCKET))
+#define LM_IS_TCP_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LM_TYPE_TCP_SOCKET))
+#define LM_TCP_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LM_TYPE_TCP_SOCKET, LmTcpSocketClass))
+
+typedef struct LmTcpSocket LmTcpSocket;
+typedef struct LmTcpSocketClass LmTcpSocketClass;
+
+struct LmTcpSocket {
+ GObject parent;
+};
+
+struct LmTcpSocketClass {
+ GObjectClass parent_class;
+};
+
+GType lm_tcp_socket_get_type (void);
+
+G_END_DECLS
+
+#endif /* __LM_TCP_SOCKET_H__ */
+