GValue *value,
GParamSpec *pspec);
-static void glib_mldonkey_dump_reply (GlibMldonkey *glibmldonkey);
+static gboolean glib_mldonkey_read_message (GlibMldonkey* glibmldonkey);
+static void glib_mldonkey_reply (GlibMldonkey *glibmldonkey, guint32 fopcode);
#define GLIB_MLDONKEY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GLIB_TYPE_MLDONKEY, GlibMldonkeyPrivate))
{
GSocketClient *sclient;
GSocketConnection *sconn;
+ GInputStream *istream;
+ GOutputStream *ostream;
+
+ gchar *username;
+ gchar *password;
};
G_DEFINE_TYPE (GlibMldonkey, glib_mldonkey, G_TYPE_OBJECT)
priv->sclient = NULL;
priv->sconn = NULL;
+ priv->istream = NULL;
+ priv->ostream = NULL;
+ priv->username = NULL;
+ priv->password = NULL;
}
/**
}
gboolean
-glib_mldonkey_connect (GlibMldonkey *glibmldonkey, const gchar *host_port)
+glib_mldonkey_connect (GlibMldonkey *glibmldonkey,
+ const gchar *host_port,
+ const gchar *username,
+ const gchar *password)
{
GError *error;
GlibMldonkeyPrivate *priv = GLIB_MLDONKEY_GET_PRIVATE (glibmldonkey);
+ priv->username = g_strdup (username);
+ priv->password = g_strdup (password);
+
priv->sclient = g_socket_client_new ();
g_socket_client_set_enable_proxy (priv->sclient, FALSE);
NULL,
&error);
if (priv->sconn == NULL
- || error != NULL)
+ || error != NULL
+ || !g_socket_connection_is_connected (priv->sconn))
{
g_warning ("Unable to connect to «%s»: %s.",
host_port,
return FALSE;
}
- if (g_socket_connection_is_connected (priv->sconn))
- {
- glib_mldonkey_dump_reply (glibmldonkey);
- return TRUE;
- }
- else
+ priv->istream = g_io_stream_get_input_stream (G_IO_STREAM (priv->sconn));
+ priv->ostream = g_io_stream_get_output_stream (G_IO_STREAM (priv->sconn));
+
+ while (glib_mldonkey_read_message (glibmldonkey))
{
- return FALSE;
}
+
+ return TRUE;
}
/* PRIVATE */
}
}
-static void
-glib_mldonkey_dump_reply (GlibMldonkey *glibmldonkey)
+typedef struct
+ {
+ guint16 fopcode;
+ guint32 length;
+ guint8 *data;
+ } GlibMldonkeyMessage;
+
+static guint16
+bytes2guint16 (const char *bytes)
+{
+ return (guint16)((bytes[1]<<8)|(bytes[0]));
+}
+
+static guint32
+bytes2guint32 (const char *bytes)
+{
+ return (guint32)((bytes[3]<<24)|(bytes[2]<<16)|(bytes[1]<<8)|(bytes[0]));
+}
+
+static gboolean
+glib_mldonkey_read_message (GlibMldonkey *glibmldonkey)
{
- GInputStream *istream;
- guint32 buf;
+ GlibMldonkeyMessage *msg;
+ guint16 buf16;
+ guint32 buf32;
+ gsize written;
GError *error;
+ guint16 l;
+
GlibMldonkeyPrivate *priv = GLIB_MLDONKEY_GET_PRIVATE (glibmldonkey);
- istream = g_io_stream_get_input_stream (G_IO_STREAM (priv->sconn));
+ msg = (GlibMldonkeyMessage *)g_new0 (GlibMldonkeyMessage, 1);
/* read first 4 byte, the content size */
- g_input_stream_read_all (istream,
- &buf,
- 4,
- NULL,
- NULL,
- &error);
- g_message ("content size: %d",GLONG_FROM_LE(buf));
+ error = NULL;
+ written = g_input_stream_read (priv->istream,
+ &buf32,
+ 4,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return FALSE;
+ }
+ msg->length = buf32 - 2;
+ g_message ("content size: %d", msg->length);
/* read next 2 byte, the function opcode */
- g_input_stream_read_all (istream,
- &buf,
- 2,
- NULL,
- NULL,
- &error);
- g_message ("function opcode: %d",GLONG_FROM_LE(buf));
-
- /* function 0 */
- g_input_stream_read_all (istream,
- &buf,
- 4,
- NULL,
- NULL,
- &error);
- g_message ("maximum protocol version: %d",GLONG_FROM_LE(buf));
- g_input_stream_read_all (istream,
- &buf,
- 4,
- NULL,
- NULL,
- &error);
- g_message ("maximum opcode gui: %d",GLONG_FROM_LE(buf));
- g_input_stream_read_all (istream,
- &buf,
- 4,
- NULL,
- NULL,
- &error);
- g_message ("maximum opcode core: %d",GLONG_FROM_LE(buf));
+ error = NULL;
+ written = g_input_stream_read (priv->istream,
+ &buf16,
+ 2,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return FALSE;
+ }
+ msg->fopcode = buf16;
+ g_message ("function opcode: %d", msg->fopcode);
+ /* the content */
+ error = NULL;
+ msg->data = (guint8 *)g_new0 (guint8, msg->length);
+ written = g_input_stream_read (priv->istream,
+ &msg->data[0],
+ msg->length,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error->message != NULL ? error->message : "no details");
+ return FALSE;
+ }
+ else
+ {
+ g_message ("written: %d", written);
+ }
+
+ switch (msg->fopcode)
+ {
+ case 0: /* CoreProtocol */
+ g_message ("maximum protocol version: %d", bytes2guint32 (msg->data));
+ g_message ("maximum opcode gui: %d", bytes2guint32 (msg->data + 4));
+ g_message ("maximum opcode core: %d", bytes2guint32 (msg->data + 8));
+
+ glib_mldonkey_reply (glibmldonkey, msg->fopcode);
+
+ break;
+
+ case 19: /* ConsoleMessage */
+ l = bytes2guint16 (msg->data);
+ g_message ("strlen %d", l);
+
+ break;
+
+ case 47: /* BadPassword */
+ g_warning ("Bad username/password");
+
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+glib_mldonkey_reply (GlibMldonkey *glibmldonkey, guint32 fopcode)
+{
+ gssize written;
+ guint16 buf16;
+ guint32 buf32;
+ GError *error;
+
+ GlibMldonkeyPrivate *priv = GLIB_MLDONKEY_GET_PRIVATE (glibmldonkey);
+
+ switch (fopcode)
+ {
+ case 0:
+ /* protocol version */
+ buf32 = 4 + 2 + 4;
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &buf32,
+ 4,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ buf16 = 0;
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &buf16,
+ 2,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ buf32 = 41;
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &buf32,
+ 4,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ /* password */
+ guint16 lname = strlen (priv->username);
+ guint16 lpassword = strlen (priv->password);
+
+ buf32 = 4 + 2 + 2 + lname + 2 + lpassword;
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &buf32,
+ 4,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ buf16 = 52;
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &buf16,
+ 2,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ buf16 = lname;
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &buf16,
+ 2,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &priv->username,
+ lname,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ buf16 = lpassword;
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &buf16,
+ 2,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ error = NULL;
+ written = g_output_stream_write (priv->ostream,
+ &priv->password,
+ lpassword,
+ NULL,
+ &error);
+ if (written < 1
+ || error != NULL)
+ {
+ g_warning ("error %s", error != NULL && error->message != NULL ? error->message : "no details");
+ return;
+ }
+
+ break;
+ }
}