[ostree/wip/metalinks] WIP: metalink code



commit 864c95078728bcdde5f2bb65fcaa05331803c2f5
Author: Colin Walters <walters verbum org>
Date:   Thu Jul 31 18:50:19 2014 -0400

    WIP: metalink code

 Makefile-libostree.am           |    2 +
 src/libostree/ostree-metalink.c |  299 +++++++++++++++++++++++++++++++++++++++
 src/libostree/ostree-metalink.h |   62 ++++++++
 3 files changed, 363 insertions(+), 0 deletions(-)
---
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index 1b75600..e7b141a 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -112,6 +112,8 @@ if USE_LIBSOUP
 libostree_1_la_SOURCES += \
        src/libostree/ostree-fetcher.h \
        src/libostree/ostree-fetcher.c \
+       src/libostree/ostree-metalink.h \
+       src/libostree/ostree-metalink.c \
        src/libostree/ostree-repo-pull.c \
        $(NULL)
 libostree_1_la_CFLAGS += $(OT_INTERNAL_SOUP_CFLAGS)
diff --git a/src/libostree/ostree-metalink.c b/src/libostree/ostree-metalink.c
new file mode 100644
index 0000000..7a7e4b7
--- /dev/null
+++ b/src/libostree/ostree-metalink.c
@@ -0,0 +1,299 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2014 Colin Walters <walters verbum org>
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include "ostree-metalink.h"
+
+#include "otutil.h"
+#include "libgsystem.h"
+
+typedef enum {
+  OSTREE_METALINK_STATE_INITIAL,
+  OSTREE_METALINK_STATE_METALINK,
+  OSTREE_METALINK_STATE_FILES,
+  OSTREE_METALINK_STATE_FILE,
+  OSTREE_METALINK_STATE_SIZE,
+  OSTREE_METALINK_STATE_VERIFICATION,
+  OSTREE_METALINK_STATE_HASH,
+  OSTREE_METALINK_STATE_RESOURCES,
+  OSTREE_METALINK_STATE_URL,
+
+  OSTREE_METALINK_STATE_PASSTHROUGH, /* Ignoring unknown elements */
+  OSTREE_METALINK_STATE_ERROR
+} OstreeMetalinkState;
+
+struct OstreeMetalink
+{
+  GObject parent_instance;
+
+  OstreeMetalink *fetcher;
+
+  guint passthrough_depth;
+  OstreeMetalinkState passthrough_previous;
+
+  char *file_name;
+  guint64 size;
+  guint verification_known :1;
+  GChecksumType verification_type;
+  char *verification_value;
+
+  GPtrArray *urls;
+
+  OstreeMetalinkState state;
+};
+
+G_DEFINE_TYPE (OstreeMetalink, _ostree_metalink, G_TYPE_OBJECT)
+
+static void
+state_transition (OstreeMetalink       *self,
+                  OstreeMetalinkState   new_state)
+{
+  g_assert (self->state != new_state);
+  self->state = new_state;
+}
+
+static void
+unknown_element (OstreeMetalink         *self,
+                 const char             *element_name,
+                 GError                **error)
+{
+  state_transition (self, OSTREE_METALINK_STATE_PASSTHROUGH);
+  g_assert (self->passthrough_depth == 0);
+}
+
+static void
+metalink_parser_start (GMarkupParseContext  *context,
+                       const gchar          *element_name,
+                       const gchar         **attribute_names,
+                       const gchar         **attribute_values,
+                       gpointer              user_data,
+                       GError              **error)
+{
+  OstreeMetalink *self = user_data;
+
+  switch (self->state)
+    {
+    case OSTREE_METALINK_STATE_INITIAL:
+      if (strcmp (element_name, "metalink") == 0)
+        state_transition (self, OSTREE_METALINK_STATE_METALINK);
+      else
+        unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_METALINK:
+      if (strcmp (element_name, "files") == 0)
+        state_transition (self, OSTREE_METALINK_STATE_FILES);
+      else
+        unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_FILES:
+      if (strcmp (element_name, "file") == 0)
+        {
+          const char *file_name;
+
+          state_transition (self, OSTREE_METALINK_STATE_FILE);
+
+          g_clear_pointer (&self->file_name, g_free);
+          if (!g_markup_collect_attributes (element_name,
+                                            attribute_names,
+                                            attribute_values,
+                                            error,
+                                            G_MARKUP_COLLECT_STRING,
+                                            "name",
+                                            &file_name,
+                                            G_MARKUP_COLLECT_INVALID))
+            goto out;
+
+          self->file_name = g_strdup (file_name);
+        }
+      else
+        unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_FILE:
+      if (strcmp (element_name, "size") == 0)
+        state_transition (self, OSTREE_METALINK_STATE_SIZE);
+      else if (strcmp (element_name, "verification") == 0)
+        state_transition (self, OSTREE_METALINK_STATE_VERIFICATION);
+      else if (strcmp (element_name, "resources") == 0)
+        state_transition (self, OSTREE_METALINK_STATE_RESOURCES);
+      else
+        unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_SIZE:
+      unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_VERIFICATION:
+      if (strcmp (element_name, "hash") == 0)
+        {
+          gs_free char *verification_type_str = NULL;
+
+          state_transition (self, OSTREE_METALINK_STATE_HASH);
+          if (!g_markup_collect_attributes (element_name,
+                                            attribute_names,
+                                            attribute_values,
+                                            error,
+                                            G_MARKUP_COLLECT_STRING,
+                                            "name",
+                                            &verification_type_str,
+                                            G_MARKUP_COLLECT_INVALID))
+            goto out;
+
+          /* Only accept sha256/sha512 */
+          self->verification_known = TRUE;
+          if (strcmp (verification_type_str, "sha256") == 0)
+            self->verification_type = G_CHECKSUM_SHA256;
+          else if (strcmp (verification_type_str, "sha512") == 0)
+            self->verification_type = G_CHECKSUM_SHA512;
+          else
+            self->verification_known = FALSE;
+        }
+      else
+        unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_HASH:
+      unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_RESOURCES:
+      if (strcmp (element_name, "url") == 0)
+        {
+          const char *protocol;
+
+          if (!g_markup_collect_attributes (element_name,
+                                            attribute_names,
+                                            attribute_values,
+                                            error,
+                                            G_MARKUP_COLLECT_STRING,
+                                            "protocol",
+                                            &protocol,
+                                            G_MARKUP_COLLECT_INVALID))
+            goto out;
+
+          /* Ignore non-HTTP resources */
+          if (!(strcmp (protocol, "http") == 0 || strcmp (protocol, "https") == 0))
+            state_transition (self, OSTREE_METALINK_STATE_PASSTHROUGH);
+          else
+            state_transition (self, OSTREE_METALINK_STATE_URL);
+        }
+      else
+        unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_URL:
+      unknown_element (self, element_name, error);
+      break;
+    case OSTREE_METALINK_STATE_PASSTHROUGH:
+      self->passthrough_depth++;
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+ out:
+  return;
+}
+
+static void
+metalink_parser_end (GMarkupParseContext  *context,
+                     const gchar          *element_name,
+                     gpointer              user_data,
+                     GError              **error)
+{
+  OstreeMetalink *self = user_data;
+}
+
+static void
+metalink_parser_text (GMarkupParseContext *context,
+                      const gchar         *text,
+                      gsize                text_len,
+                      gpointer             user_data,
+                      GError             **error)
+{
+  OstreeMetalink *self = user_data;
+
+  switch (self->state)
+    {
+    case OSTREE_METALINK_STATE_INITIAL:
+      break;
+    case OSTREE_METALINK_STATE_METALINK:
+      break;
+    case OSTREE_METALINK_STATE_FILES:
+      break;
+    case OSTREE_METALINK_STATE_FILE:
+      break;
+    case OSTREE_METALINK_STATE_SIZE:
+      {
+        gs_free char *duped = g_strndup (text, text_len);
+        self->size = g_ascii_strtoull (duped, NULL, 10);
+      }
+      break;
+    case OSTREE_METALINK_STATE_VERIFICATION:
+      break;
+    case OSTREE_METALINK_STATE_HASH:
+      {
+        g_clear_pointer (&self->verification_value, g_free);
+        self->verification_value = g_strndup (text, text_len);
+      }
+      break;
+    case OSTREE_METALINK_STATE_RESOURCES:
+      break;
+    case OSTREE_METALINK_STATE_URL:
+      break;
+    case OSTREE_METALINK_STATE_PASSTHROUGH:
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+ out:
+  return;
+}
+
+static void
+_ostree_metalink_finalize (GObject *object)
+{
+  OstreeMetalink *self;
+
+  self = OSTREE_METALINK (object);
+
+  G_OBJECT_CLASS (_ostree_metalink_parent_class)->finalize (object);
+}
+
+static void
+_ostree_metalink_class_init (OstreeMetalinkClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = _ostree_metalink_finalize;
+}
+
+static void
+_ostree_metalink_init (OstreeMetalink *self)
+{
+  self->urls = g_ptr_array_new_with_free_func (g_free);
+}
+
+OstreeMetalink *
+_ostree_metalink_new (OstreeFetcher  *fetcher,
+                      const char     *requested_file,
+                      guint64         max_size,
+                      SoupURI        *uri)
+{
+  OstreeMetalink *self = (OstreeMetalink*)g_object_new (OSTREE_TYPE_METALINK, NULL);
+ 
+  return self;
+}
diff --git a/src/libostree/ostree-metalink.h b/src/libostree/ostree-metalink.h
new file mode 100644
index 0000000..bb81292
--- /dev/null
+++ b/src/libostree/ostree-metalink.h
@@ -0,0 +1,62 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2014 Colin Walters <walters verbum org>
+ *
+ * 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.
+ */
+
+#pragma once
+
+#ifndef __GI_SCANNER__
+
+#include "ostree-fetcher.h"
+
+G_BEGIN_DECLS
+
+#define OSTREE_TYPE_METALINK         (_ostree_metalink_get_type ())
+#define OSTREE_METALINK(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), OSTREE_TYPE_METALINK, OstreeMetalink))
+#define OSTREE_METALINK_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), OSTREE_TYPE_METALINK, 
OstreeMetalinkClass))
+#define OSTREE_IS_METALINK(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_METALINK))
+#define OSTREE_IS_METALINK_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_METALINK))
+#define OSTREE_METALINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OSTREE_TYPE_METALINK, 
OstreeMetalinkClass))
+
+typedef struct OstreeMetalinkClass   OstreeMetalinkClass;
+typedef struct OstreeMetalink   OstreeMetalink;
+
+struct OstreeMetalinkClass
+{
+  GObjectClass parent_class;
+};
+
+GType   _ostree_metalink_get_type (void) G_GNUC_CONST;
+
+OstreeMetalink *_ostree_metalink_new (OstreeFetcher  *fetcher,
+                                      const char     *requested_file,
+                                      guint64         max_size,
+                                      SoupURI        *uri);
+
+void _ostree_metalink_request_async (OstreeMetalink         *self,
+                                     GCancellable          *cancellable,
+                                     GAsyncReadyCallback    callback,
+                                     gpointer               user_data);
+
+GFile *_ostree_metalink_request_finish (OstreeMetalink         *self,
+                                        GAsyncResult          *result,
+                                        GError               **error);
+
+G_END_DECLS
+
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]