summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier CrĂȘte <olivier.crete@collabora.com>2014-09-30 23:10:53 -0400
committerOlivier CrĂȘte <olivier.crete@collabora.com>2014-09-30 23:45:21 -0400
commitc383af72e3846f30ea40f1807b892c36544404c4 (patch)
tree8c5ab48126d683fbdae860de493fc16718c2bb9a
parente47f5a979764c17d59432f2b7b35a89798b1d2ed (diff)
downloadgupnp-igd-c383af72e3846f30ea40f1807b892c36544404c4.tar.gz
Add function to remove the port using the local port
-rw-r--r--libgupnp-igd/gupnp-simple-igd-priv.h7
-rw-r--r--libgupnp-igd/gupnp-simple-igd-thread.c63
-rw-r--r--libgupnp-igd/gupnp-simple-igd.c74
-rw-r--r--libgupnp-igd/gupnp-simple-igd.h6
-rw-r--r--tests/gtest/gupnp-simple-igd.c20
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",