[gvfs] afp: add GVfsAfpConnection which handles the DSI connection
- From: Christian Kellner <gicmo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] afp: add GVfsAfpConnection which handles the DSI connection
- Date: Thu, 25 Aug 2011 19:21:01 +0000 (UTC)
commit 73e0352e827216575822d54cf1c1eb9f220bf2e1
Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
Date: Sun May 29 00:38:42 2011 +0200
afp: add GVfsAfpConnection which handles the DSI connection
daemon/Makefile.am | 4 +-
daemon/gvfsafpconnection.c | 306 ++++++++++++++++++++++++++++++++++++++++++++
daemon/gvfsafpconnection.h | 61 +++++++++
daemon/gvfsbackendafp.c | 35 +++++
daemon/gvfsbackendafp.h | 4 +
5 files changed, 409 insertions(+), 1 deletions(-)
---
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 269a458..9256e74 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -475,7 +475,9 @@ gvfsd_afc_LDADD = \
gvfsd_afp_SOURCES = \
gvfsbackendafp.c gvfsbackendafp.h \
daemon-main.c daemon-main.h \
- daemon-main-generic.c
+ daemon-main-generic.c \
+ gvfsafpconnection.h \
+ gvfsafpconnection.c
gvfsd_afp_CPPFLAGS = \
-DBACKEND_HEADER=gvfsbackendafp.h \
diff --git a/daemon/gvfsafpconnection.c b/daemon/gvfsafpconnection.c
new file mode 100644
index 0000000..8aa2ed0
--- /dev/null
+++ b/daemon/gvfsafpconnection.c
@@ -0,0 +1,306 @@
+ /* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) Carl-Anton Ingmarsson 2011 <ca ingmarsson gmail com>
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
+ */
+
+
+#include "gvfsafpconnection.h"
+
+
+
+G_DEFINE_TYPE (GVfsAfpConnection, g_vfs_afp_connection, G_TYPE_OBJECT);
+
+struct _GVfsAfpConnectionPrivate
+{
+ GIOStream *conn;
+
+ guint16 request_id;
+
+ guint32 kRequestQuanta;
+ guint32 kServerReplayCacheSize;
+};
+
+typedef enum
+{
+ DSI_CLOSE_SESSION = 1,
+ DSI_COMMAND = 2,
+ DSI_GET_STATUS = 3,
+ DSI_OPEN_SESSION = 4,
+ DSI_TICKLE = 5,
+ DSI_WRITE = 6
+} DsiCommand;
+
+static guint16
+get_request_id (GVfsAfpConnection *afp_connection)
+{
+ GVfsAfpConnectionPrivate *priv = afp_connection->priv;
+
+ return priv->request_id++;
+}
+static char *
+read_reply_sync (GVfsAfpConnection *afp_connection,
+ guint8 *flags,
+ DsiCommand *command,
+ guint16 *request_id,
+ gsize *len,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVfsAfpConnectionPrivate *priv = afp_connection->priv;
+
+ typedef struct {
+ guint8 flags;
+ guint8 command;
+ guint16 requestID;
+ union {
+ guint32 errorCode;
+ guint32 writeOffset;
+ };
+ guint32 totalDataLength;
+ guint32 reserved;
+ } DSIHeader;
+
+ GInputStream *input;
+ DSIHeader dsi_header;
+ gsize read_count;
+ char *data;
+
+ input = g_io_stream_get_input_stream (priv->conn);
+
+ read_count = sizeof (DSIHeader);
+ while (read_count > 0)
+ {
+ gsize bytes_read;
+
+ bytes_read = g_input_stream_read (input,
+ &dsi_header + (sizeof (DSIHeader) - read_count),
+ read_count, cancellable, error);
+ if (bytes_read == -1)
+ return NULL;
+
+ read_count -= bytes_read;
+ }
+ dsi_header.requestID = GUINT16_FROM_BE (dsi_header.requestID);
+ dsi_header.totalDataLength = GUINT32_FROM_BE (dsi_header.totalDataLength);
+
+ *flags = dsi_header.flags;
+ *command = dsi_header.command;
+ *request_id = dsi_header.requestID;
+
+ data = g_malloc (dsi_header.totalDataLength);
+ read_count = dsi_header.totalDataLength;
+ while (read_count > 0)
+ {
+ gsize bytes_read;
+
+ bytes_read = g_input_stream_read (input,
+ data + (dsi_header.totalDataLength - read_count),
+ read_count, cancellable, error);
+ if (bytes_read == -1)
+ {
+ g_free (data);
+ return NULL;
+ }
+
+ read_count -= bytes_read;
+ }
+
+ *len = dsi_header.totalDataLength;
+ return data;
+}
+
+static gboolean
+send_request_sync (GVfsAfpConnection *afp_connection,
+ DsiCommand command,
+ gsize len,
+ char *data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVfsAfpConnectionPrivate *priv = afp_connection->priv;
+
+ typedef struct {
+ guint8 flags;
+ guint8 command;
+ guint16 requestID;
+ union {
+ guint32 errorCode;
+ guint32 writeOffset;
+ };
+ guint32 totalDataLength;
+ guint32 reserved;
+ } DSIHeader;
+
+ GOutputStream *output;
+ DSIHeader dsi_header;
+ gsize write_count;
+
+ output = g_io_stream_get_output_stream (priv->conn);
+
+ dsi_header.flags = 0x00;
+ dsi_header.command = command;
+ dsi_header.requestID = GUINT16_TO_BE (get_request_id (afp_connection));
+ dsi_header.writeOffset = 0;
+ dsi_header.totalDataLength = 0;
+ dsi_header.reserved = 0;
+
+ write_count = sizeof (DSIHeader);
+ while (write_count > 0)
+ {
+ gsize bytes_written;
+
+ bytes_written = g_output_stream_write (output,
+ &dsi_header + (sizeof (DSIHeader) - write_count),
+ write_count, cancellable, error);
+ if (bytes_written == -1)
+ return FALSE;
+
+ write_count -= bytes_written;
+ }
+
+ write_count = len;
+ while (write_count > 0)
+ {
+ gsize bytes_written;
+
+ bytes_written = g_output_stream_write (output, data + (len - write_count),
+ write_count, cancellable, error);
+ if (bytes_written == -1)
+ return FALSE;
+
+ write_count -= bytes_written;
+ }
+
+ return TRUE;
+}
+
+GVfsAfpConnection *
+g_vfs_afp_connection_new (GSocketConnectable *addr,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVfsAfpConnection *afp_connection;
+ GVfsAfpConnectionPrivate *priv;
+
+ GSocketClient *client;
+
+ char *reply;
+ guint8 flags;
+ DsiCommand command;
+ guint16 request_id;
+ gsize len;
+ guint pos;
+
+ afp_connection = g_object_new (G_VFS_TYPE_AFP_CONNECTION, NULL);
+ priv = afp_connection->priv;
+
+ client = g_socket_client_new ();
+ priv->conn = G_IO_STREAM (g_socket_client_connect (client, addr, cancellable, error));
+ g_object_unref (client);
+
+ if (!priv->conn)
+ goto error;
+
+ if (!send_request_sync (afp_connection, DSI_OPEN_SESSION, 0, NULL,
+ cancellable, error))
+ goto error;
+
+ reply = read_reply_sync (afp_connection, &flags, &command, &request_id, &len,
+ cancellable, error);
+ if (!reply)
+ goto error;
+
+ pos = 0;
+ while ((len - pos) > 2)
+ {
+ guint8 optionType;
+ guint8 optionLength;
+
+ optionType = reply[pos++];
+ optionLength = reply[pos++];
+
+ switch (optionType)
+ {
+
+ case 0x00:
+ if (optionLength == 4 && (len - pos) >= 4)
+ priv->kRequestQuanta = GUINT32_FROM_BE (*(guint32 *)(reply + pos));
+
+ break;
+
+ case 0x02:
+ if (optionLength == 4 && (len - pos) >= 4)
+ priv->kServerReplayCacheSize = GUINT32_FROM_BE (*(guint32 *)(reply + pos));
+
+ break;
+
+
+ default:
+ g_debug ("Unknown DSI option\n");
+ }
+
+ pos += optionLength;
+ }
+
+ return afp_connection;
+
+error:
+ g_object_unref (afp_connection);
+ return NULL;
+}
+
+static void
+g_vfs_afp_connection_init (GVfsAfpConnection *afp_connection)
+{
+ GVfsAfpConnectionPrivate *priv;
+
+ afp_connection->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (afp_connection,
+ G_VFS_TYPE_AFP_CONNECTION,
+ GVfsAfpConnectionPrivate);
+
+ priv->conn = NULL;
+ priv->request_id = 0;
+
+ priv->kRequestQuanta = -1;
+ priv->kServerReplayCacheSize = -1;
+}
+
+static void
+g_vfs_afp_connection_finalize (GObject *object)
+{
+ GVfsAfpConnection *afp_connection = (GVfsAfpConnection *)object;
+ GVfsAfpConnectionPrivate *priv = afp_connection->priv;
+
+ if (priv->conn)
+ g_object_unref (priv->conn);
+
+ G_OBJECT_CLASS (g_vfs_afp_connection_parent_class)->finalize (object);
+}
+
+static void
+g_vfs_afp_connection_class_init (GVfsAfpConnectionClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GVfsAfpConnectionPrivate));
+
+ object_class->finalize = g_vfs_afp_connection_finalize;
+}
+
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h
new file mode 100644
index 0000000..86df653
--- /dev/null
+++ b/daemon/gvfsafpconnection.h
@@ -0,0 +1,61 @@
+ /* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) Carl-Anton Ingmarsson 2011 <ca ingmarsson gmail com>
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
+ */
+
+#ifndef _GVFSAFPCONNECTION_H_
+#define _GVFSAFPCONNECTION_H_
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_AFP_CONNECTION (g_vfs_afp_connection_get_type ())
+#define G_VFS_AFP_CONNECTION(obj) (G_VFS_TYPE_CHECK_INSTANCE_CAST ((obj), G_VFS_TYPE_VFS_AFP_CONNECTION, GVfsAfpConnection))
+#define G_VFS_AFP_CONNECTION_CLASS(klass) (G_VFS_TYPE_CHECK_CLASS_CAST ((klass), G_VFS_TYPE_VFS_AFP_CONNECTION, GVfsAfpConnectionClass))
+#define G_IS_VFS_AFP_CONNECTION(obj) (G_VFS_TYPE_CHECK_INSTANCE_TYPE ((obj), G_VFS_TYPE_VFS_AFP_CONNECTION))
+#define G_IS_VFS_AFP_CONNECTION_CLASS(klass) (G_VFS_TYPE_CHECK_CLASS_TYPE ((klass), G_VFS_TYPE_VFS_AFP_CONNECTION))
+#define G_VFS_AFP_CONNECTION_GET_CLASS(obj) (G_VFS_TYPE_INSTANCE_GET_CLASS ((obj), G_VFS_TYPE_VFS_AFP_CONNECTION, GVfsAfpConnectionClass))
+
+typedef struct _GVfsAfpConnectionClass GVfsAfpConnectionClass;
+typedef struct _GVfsAfpConnection GVfsAfpConnection;
+typedef struct _GVfsAfpConnectionPrivate GVfsAfpConnectionPrivate;
+
+struct _GVfsAfpConnectionClass
+{
+ GObjectClass parent_class;
+};
+
+struct _GVfsAfpConnection
+{
+ GObject parent_instance;
+
+ GVfsAfpConnectionPrivate *priv;
+};
+
+GType g_vfs_afp_connection_get_type (void) G_GNUC_CONST;
+
+GVfsAfpConnection *
+g_vfs_afp_connection_new (GSocketConnectable *addr,
+ GCancellable *cancellable,
+ GError **error);
+G_END_DECLS
+
+#endif /* _GVFSAFPCONNECTION_H_ */
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index 154c41e..c893a5f 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -35,6 +35,39 @@
G_DEFINE_TYPE (GVfsBackendAfp, g_vfs_backend_afp, G_VFS_TYPE_BACKEND);
+static void
+do_unmount (GVfsBackend * backend,
+ GVfsJobUnmount *job,
+ GMountUnmountFlags flags,
+ GMountSource *mount_source)
+{
+ GVfsBackendAfp *afp = G_VFS_BACKEND_AFP (backend);
+
+ g_object_unref (afp->conn);
+}
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
+
+ GError *err;
+
+ err = NULL;
+ afp_backend->conn = g_vfs_afp_connection_new (afp_backend->addr,
+ G_VFS_JOB (job)->cancellable,
+ &err);
+ if (!afp_backend->conn)
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), err);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+}
+
static gboolean
try_mount (GVfsBackend *backend,
GVfsJobMount *job,
@@ -93,5 +126,7 @@ g_vfs_backend_afp_class_init (GVfsBackendAfpClass *klass)
object_class->finalize = g_vfs_backend_afp_finalize;
backend_class->try_mount = try_mount;
+ backend_class->mount = do_mount;
+ backend_class->unmount = do_unmount;
}
diff --git a/daemon/gvfsbackendafp.h b/daemon/gvfsbackendafp.h
index 230c7f6..ac9cd12 100644
--- a/daemon/gvfsbackendafp.h
+++ b/daemon/gvfsbackendafp.h
@@ -25,6 +25,8 @@
#include <gvfsbackend.h>
+#include "gvfsafpconnection.h"
+
G_BEGIN_DECLS
#define G_VFS_TYPE_BACKEND_AFP (g_vfs_backend_afp_get_type ())
@@ -48,6 +50,8 @@ struct _GVfsBackendAfp
GSocketConnectable *addr;
char *user;
+
+ GVfsAfpConnection *conn;
};
GType g_vfs_backend_afp_get_type (void) G_GNUC_CONST;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]