[gupnp-igd] Add function to remove the port using the local port



commit c383af72e3846f30ea40f1807b892c36544404c4
Author: Olivier Crête <olivier crete collabora com>
Date:   Tue Sep 30 23:10:53 2014 -0400

    Add function to remove the port using the local port

 libgupnp-igd/gupnp-simple-igd-priv.h   |    7 +++
 libgupnp-igd/gupnp-simple-igd-thread.c |   63 ++++++++++++++++++++++++++-
 libgupnp-igd/gupnp-simple-igd.c        |   74 +++++++++++++++++++++++++++++--
 libgupnp-igd/gupnp-simple-igd.h        |    6 +++
 tests/gtest/gupnp-simple-igd.c         |   20 ++++++++-
 5 files changed, 163 insertions(+), 7 deletions(-)
---
diff --git a/libgupnp-igd/gupnp-simple-igd-priv.h b/libgupnp-igd/gupnp-simple-igd-priv.h
index 34d4cb1..0081b78 100644
--- a/libgupnp-igd/gupnp-simple-igd-priv.h
+++ b/libgupnp-igd/gupnp-simple-igd-priv.h
@@ -51,6 +51,13 @@ struct _GUPnPSimpleIgdClass
   void (*remove_port) (GUPnPSimpleIgd *self,
       const gchar *protocol,
       guint external_port);
+
+  void (*remove_port_local) (GUPnPSimpleIgd *self,
+      const gchar *protocol,
+      const gchar *local_ip,
+      guint16 local_port);
+
+  /*< private >*/
 };
 
 #endif /* __GUPNP_SIMPLE_IGD_PRIV_H__ */
diff --git a/libgupnp-igd/gupnp-simple-igd-thread.c b/libgupnp-igd/gupnp-simple-igd-thread.c
index 0adb64d..178c9f2 100644
--- a/libgupnp-igd/gupnp-simple-igd-thread.c
+++ b/libgupnp-igd/gupnp-simple-igd-thread.c
@@ -109,6 +109,10 @@ static void gupnp_simple_igd_thread_add_port (GUPnPSimpleIgd *self,
 static void gupnp_simple_igd_thread_remove_port (GUPnPSimpleIgd *self,
     const gchar *protocol,
     guint external_port);
+static void gupnp_simple_igd_thread_remove_port_local (GUPnPSimpleIgd *self,
+    const gchar *protocol,
+    const gchar *local_ip,
+    guint16 local_port);
 
 
 struct AddRemovePortData {
@@ -138,6 +142,8 @@ gupnp_simple_igd_thread_class_init (GUPnPSimpleIgdThreadClass *klass)
 
   simple_igd_class->add_port = gupnp_simple_igd_thread_add_port;
   simple_igd_class->remove_port = gupnp_simple_igd_thread_remove_port;
+  simple_igd_class->remove_port_local =
+      gupnp_simple_igd_thread_remove_port_local;
 }
 
 
@@ -282,7 +288,7 @@ thread_func (gpointer dat)
   struct thread_data *data = dat;
   GMainLoop *loop = g_main_loop_new (data->context, FALSE);
 
-  g_main_context_push_thread_default(data->context);
+  g_main_context_push_thread_default (data->context);
 
   g_mutex_lock (data->mutex);
   data->loop = loop;
@@ -295,6 +301,8 @@ thread_func (gpointer dat)
   data->all_mappings_deleted = TRUE;
   g_mutex_unlock (data->mutex);
 
+  g_main_context_pop_thread_default (data->context);
+
   g_main_loop_unref (loop);
 
   thread_data_dec (data);
@@ -394,6 +402,31 @@ remove_port_idle_func (gpointer user_data)
   return FALSE;
 }
 
+static gboolean
+remove_port_local_idle_func (gpointer user_data)
+{
+  struct AddRemovePortData *data = user_data;
+  GUPnPSimpleIgdClass *klass =
+      GUPNP_SIMPLE_IGD_CLASS (gupnp_simple_igd_thread_parent_class);
+  GUPnPSimpleIgdThread *self;
+
+  g_static_mutex_lock (&data->mutex);
+  self = data->self;
+  if (self)
+    g_object_ref (self);
+  g_static_mutex_unlock (&data->mutex);
+  if (!self)
+    return FALSE;
+
+  if (klass->remove_port_local)
+    klass->remove_port_local (GUPNP_SIMPLE_IGD (self), data->protocol,
+        data->local_ip, data->local_port);
+
+  g_object_unref (self);
+
+  return FALSE;
+}
+
 static void
 free_add_remove_port_data (gpointer user_data)
 {
@@ -481,6 +514,34 @@ gupnp_simple_igd_thread_remove_port (GUPnPSimpleIgd *self,
   g_main_context_wakeup (realself->priv->context);
 }
 
+static void
+gupnp_simple_igd_thread_remove_port_local (GUPnPSimpleIgd *self,
+    const gchar *protocol,
+    const gchar *local_ip,
+    guint16 local_port)
+{
+  GUPnPSimpleIgdThread *realself = GUPNP_SIMPLE_IGD_THREAD (self);
+  struct AddRemovePortData *data = g_slice_new0 (struct AddRemovePortData);
+  GSource *source;
+
+  g_static_mutex_init (&data->mutex);
+  data->self = realself;
+  data->protocol = g_strdup (protocol);
+  data->local_ip = g_strdup (local_ip);
+  data->local_port = local_port;
+  GUPNP_SIMPLE_IGD_THREAD_LOCK (realself);
+  g_ptr_array_add (realself->priv->add_remove_port_datas, data);
+  GUPNP_SIMPLE_IGD_THREAD_UNLOCK (realself);
+
+  source = g_idle_source_new ();
+  g_source_set_callback (source, remove_port_local_idle_func, data,
+      free_add_remove_port_data);
+  g_source_set_priority (source, G_PRIORITY_DEFAULT);
+  g_source_attach (source, realself->priv->context);
+  g_source_unref (source);
+  g_main_context_wakeup (realself->priv->context);
+}
+
 /**
  * gupnp_simple_igd_thread_new:
  *
diff --git a/libgupnp-igd/gupnp-simple-igd.c b/libgupnp-igd/gupnp-simple-igd.c
index 775c4d3..61d1e77 100644
--- a/libgupnp-igd/gupnp-simple-igd.c
+++ b/libgupnp-igd/gupnp-simple-igd.c
@@ -154,6 +154,10 @@ static void gupnp_simple_igd_add_port_real (GUPnPSimpleIgd *self,
 static void gupnp_simple_igd_remove_port_real (GUPnPSimpleIgd *self,
     const gchar *protocol,
     guint external_port);
+static void gupnp_simple_igd_remove_port_local_real (GUPnPSimpleIgd *self,
+    const gchar *protocol,
+    const gchar *local_ip,
+    guint16 local_port);
 
 GQuark
 gupnp_simple_igd_error_quark (void)
@@ -176,6 +180,7 @@ gupnp_simple_igd_class_init (GUPnPSimpleIgdClass *klass)
 
   klass->add_port = gupnp_simple_igd_add_port_real;
   klass->remove_port = gupnp_simple_igd_remove_port_real;
+  klass->remove_port_local = gupnp_simple_igd_remove_port_local_real;
 
   g_object_class_install_property (gobject_class,
       PROP_MAIN_CONTEXT,
@@ -852,9 +857,6 @@ gupnp_simple_igd_add_port_real (GUPnPSimpleIgd *self,
   struct Mapping *mapping = g_slice_new0 (struct Mapping);
   guint i;
 
-  g_return_if_fail (protocol && local_ip);
-  g_return_if_fail (!strcmp (protocol, "UDP") || !strcmp (protocol, "TCP"));
-
   mapping->protocol = g_strdup (protocol);
   mapping->requested_external_port = external_port;
   mapping->local_ip = g_strdup (local_ip);
@@ -902,8 +904,9 @@ gupnp_simple_igd_add_port_real (GUPnPSimpleIgd *self,
  * @description: The description that will appear in the router's table
  *
  * This adds a port to the router's forwarding table. The mapping will
- * be automatically refreshed by this object until it is either removed with
- * gupnp_simple_igd_remove_port() or the object disapears.
+ * be automatically refreshed by this object until it is either
+ * removed with gupnp_simple_igd_remove_port(),
+ * gupnp_simple_igd_remove_port_local() or the object disapears.
  *
  * If there is a problem, the #GUPnPSimpleIgd::error-mapping-port signal will
  * be emitted. If a router is found and a port is mapped correctly,
@@ -985,6 +988,67 @@ gupnp_simple_igd_remove_port (GUPnPSimpleIgd *self,
   klass->remove_port (self, protocol, external_port);
 }
 
+
+static void
+gupnp_simple_igd_remove_port_local_real (GUPnPSimpleIgd *self,
+    const gchar *protocol,
+    const gchar *local_ip,
+    guint16 local_port)
+{
+  struct Mapping *mapping = NULL;
+  guint i;
+
+  for (i = 0; i < self->priv->mappings->len; i++)
+  {
+    struct Mapping *tmpmapping = g_ptr_array_index (self->priv->mappings, i);
+    if (tmpmapping->local_port == local_port &&
+        !strcmp (tmpmapping->local_ip, local_ip) &&
+        !strcmp (tmpmapping->protocol, protocol))
+    {
+      mapping = tmpmapping;
+      break;
+    }
+  }
+  if (!mapping)
+    return;
+
+  g_ptr_array_remove_index_fast (self->priv->mappings, i);
+
+  free_mapping (self, mapping);
+}
+
+/**
+ * gupnp_simple_igd_remove_port_local:
+ * @self: The #GUPnPSimpleIgd object
+ * @protocol: the protocol "UDP" or "TCP" as given to
+ *  gupnp_simple_igd_add_port()
+ * @local_ip: The local ip on the internal device as was to
+ *  gupnp_simple_igd_add_port()
+ * @local_port: The port to try to open on the internal device as given to
+ *  gupnp_simple_igd_add_port()
+ *
+ * This tries to remove a port entry from the routers that was previously added
+ * with gupnp_simple_igd_add_port(). There is no indicated of success or failure
+ * it is a best effort mechanism. If it fails, the bindings will disapears after
+ * the lease duration set when the port where added.
+ */
+void
+gupnp_simple_igd_remove_port_local (GUPnPSimpleIgd *self,
+    const gchar *protocol,
+    const gchar *local_ip,
+    guint16 local_port)
+{
+  GUPnPSimpleIgdClass *klass = GUPNP_SIMPLE_IGD_GET_CLASS (self);
+
+  g_return_if_fail (protocol != NULL);
+  g_return_if_fail (local_ip != NULL);
+  g_return_if_fail (local_port != 0);
+
+  g_return_if_fail (klass->remove_port_local);
+
+  klass->remove_port_local (self, protocol, local_ip, local_port);
+}
+
 static void
 stop_proxymapping (struct ProxyMapping *pm, gboolean stop_renew)
 {
diff --git a/libgupnp-igd/gupnp-simple-igd.h b/libgupnp-igd/gupnp-simple-igd.h
index 96d096a..d0acd8f 100644
--- a/libgupnp-igd/gupnp-simple-igd.h
+++ b/libgupnp-igd/gupnp-simple-igd.h
@@ -100,6 +100,12 @@ gupnp_simple_igd_remove_port (GUPnPSimpleIgd *self,
     const gchar *protocol,
     guint external_port);
 
+void
+gupnp_simple_igd_remove_port_local (GUPnPSimpleIgd *self,
+    const gchar *protocol,
+    const gchar *local_ip,
+    guint16 local_port);
+
 
 gboolean
 gupnp_simple_igd_delete_all_mappings (GUPnPSimpleIgd *self);
diff --git a/tests/gtest/gupnp-simple-igd.c b/tests/gtest/gupnp-simple-igd.c
index fe2aa7f..9b32b2a 100644
--- a/tests/gtest/gupnp-simple-igd.c
+++ b/tests/gtest/gupnp-simple-igd.c
@@ -50,6 +50,7 @@ static GUPnPServiceInfo *pppservice = NULL;
 
 gboolean return_conflict = FALSE;
 gboolean dispose_removes = FALSE;
+gboolean local_remove = FALSE;
 gchar *invalid_ip = NULL;
 
 static void
@@ -210,8 +211,10 @@ mapped_external_port_cb (GUPnPSimpleIgd *igd, gchar *proto,
             !strcmp (external_ip, PPP_ADDRESS_SECOND)));
     if (dispose_removes)
       g_object_unref (igd);
+    else if (local_remove)
+      gupnp_simple_igd_remove_port_local (igd, proto, local_ip, local_port);
     else
-      gupnp_simple_igd_remove_port (igd, "UDP", requested_external_port);
+      gupnp_simple_igd_remove_port (igd, proto, requested_external_port);
   }
   else
   {
@@ -360,6 +363,19 @@ test_gupnp_simple_igd_default_ctx (void)
 }
 
 static void
+test_gupnp_simple_igd_default_ctx_local (void)
+{
+  GUPnPSimpleIgd *igd = gupnp_simple_igd_new ();
+
+  local_remove = TRUE;
+
+  run_gupnp_simple_igd_test (NULL, igd, INTERNAL_PORT);
+  g_object_unref (igd);
+
+  local_remove = FALSE;
+}
+
+static void
 test_gupnp_simple_igd_custom_ctx (void)
 {
   GMainContext *mainctx = g_main_context_new ();
@@ -463,6 +479,8 @@ int main (int argc, char **argv)
 
   g_test_add_func("/simpleigd/new", test_gupnp_simple_igd_new);
   g_test_add_func ("/simpleigd/default_ctx", test_gupnp_simple_igd_default_ctx);
+  g_test_add_func ("/simpleigd/default_ctx/remove_local",
+      test_gupnp_simple_igd_default_ctx_local);
   g_test_add_func ("/simpleigd/custom_ctx", test_gupnp_simple_igd_custom_ctx);
   g_test_add_func ("/simpleigd/thread", test_gupnp_simple_igd_thread);
   g_test_add_func ("/simpleigd/random/no_conflict",


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