[farsight2/master] Use internal stunalternd for testing
Olivier Crête
olivier.crete at collabora.co.uk
Wed Apr 15 15:29:22 PDT 2009
---
tests/check/Makefile.am | 9 +-
tests/check/transmitter/generic.c | 60 ------
tests/check/transmitter/generic.h | 8 -
tests/check/transmitter/rawudp.c | 56 +++++-
tests/check/transmitter/stunalternd.c | 350 +++++++++++++++++++++++++++++++++
tests/check/transmitter/stunalternd.h | 38 ++++
6 files changed, 448 insertions(+), 73 deletions(-)
create mode 100644 tests/check/transmitter/stunalternd.c
create mode 100644 tests/check/transmitter/stunalternd.h
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index 918f55c..75a934c 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -63,16 +63,19 @@ LDADD = \
$(GST_CHECK_LIBS) \
$(GST_LIBS)
-transmitter_rawudp_CFLAGS = $(AM_CFLAGS) $(GUPNP_CFLAGS)
+transmitter_rawudp_CFLAGS = $(AM_CFLAGS) $(GUPNP_CFLAGS) $(NICE_CFLAGS)
transmitter_rawudp_LDADD = $(LDADD) \
- $(GUPNP_LIBS)
+ $(GUPNP_LIBS) \
+ $(NICE_LIBS)
transmitter_rawudp_SOURCES = \
check-threadsafe.h \
transmitter/generic.c \
transmitter/generic.h \
transmitter/rawudp.c \
transmitter/rawudp-upnp.c \
- transmitter/rawudp-upnp.h
+ transmitter/rawudp-upnp.h \
+ transmitter/stunalternd.c \
+ transmitter/stunalternd.h
transmitter_multicast_CFLAGS = $(AM_CFLAGS)
diff --git a/tests/check/transmitter/generic.c b/tests/check/transmitter/generic.c
index f20aa55..c8ff8fb 100644
--- a/tests/check/transmitter/generic.c
+++ b/tests/check/transmitter/generic.c
@@ -32,7 +32,6 @@
#include "check-threadsafe.h"
#include "generic.h"
-
static void
_transmitter_error (FsTransmitter *transmitter, gint errorno, gchar *error_msg,
gchar *debug_msg, gpointer user_data)
@@ -242,62 +241,3 @@ teardown_stund (void)
stund_pid = 0;
}
-
-GPid stunalternd_pid = 0;
-
-static void
-setup_stunalternd_internal (gchar *argv[])
-{
- GError *error = NULL;
-
- stunalternd_pid = 0;
-
- if (!g_spawn_async (NULL, argv, NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL, &stunalternd_pid, &error))
- {
- g_debug ("Could not spawn stunalternd, skipping stun testing: %s",
- error->message);
- g_clear_error (&error);
- return;
- }
-}
-
-void
-setup_stunalternd_valid (void)
-{
- gchar *argv[] = {"stunalternd", "127.0.0.1", "3478", "3480", NULL};
- setup_stunalternd_internal (argv);
-}
-
-void
-setup_stunalternd_loop (void)
-{
- gchar *argv[] = {"stunalternd", "127.0.0.1", "3480", "3480", NULL};
- setup_stunalternd_internal (argv);
-}
-
-void
-teardown_stunalternd (void)
-{
- if (!stunalternd_pid)
- return;
-
- kill (stunalternd_pid, SIGTERM);
- waitpid (stunalternd_pid, NULL, 0);
- g_spawn_close_pid (stunalternd_pid);
- stunalternd_pid = 0;
-}
-
-void setup_stund_stunalternd (void)
-{
- setup_stund ();
- setup_stunalternd_valid ();
-}
-
-
-void teardown_stund_stunalternd (void)
-{
- teardown_stund ();
- teardown_stunalternd ();
-}
diff --git a/tests/check/transmitter/generic.h b/tests/check/transmitter/generic.h
index 642a2c4..200b4c8 100644
--- a/tests/check/transmitter/generic.h
+++ b/tests/check/transmitter/generic.h
@@ -39,16 +39,8 @@ gboolean bus_error_callback (GstBus *bus, GstMessage *message,
void test_transmitter_creation (gchar *transmitter_name);
extern GPid stund_pid;
-extern GPid stunalternd_pid;
void setup_stund (void);
void teardown_stund (void);
-void setup_stunalternd_valid (void);
-void setup_stunalternd_loop (void);
-void teardown_stunalternd (void);
-
-void setup_stund_stunalternd (void);
-void teardown_stund_stunalternd (void);
-
#endif /* __GENERIC_H__ */
diff --git a/tests/check/transmitter/rawudp.c b/tests/check/transmitter/rawudp.c
index ea60015..22afb29 100644
--- a/tests/check/transmitter/rawudp.c
+++ b/tests/check/transmitter/rawudp.c
@@ -35,6 +35,9 @@
#include "generic.h"
#include "transmitter/rawudp-upnp.h"
+#include "stunalternd.h"
+
+
gint buffer_count[2] = {0, 0};
GMainLoop *loop = NULL;
gint candidates[2] = {0, 0};
@@ -48,6 +51,7 @@ gboolean associate_on_source = TRUE;
gboolean pipeline_done = FALSE;
GStaticMutex pipeline_mod_mutex = G_STATIC_MUTEX_INIT;
+void *stun_alternd_data = NULL;
enum {
FLAG_HAS_STUN = 1 << 0,
@@ -809,7 +813,7 @@ GST_START_TEST (test_rawudptransmitter_run_stunalternd)
{
GParameter params[4];
- if (stund_pid <= 0 || stunalternd_pid <= 0)
+ if (stund_pid <= 0 || stun_alternd_data == NULL)
return;
memset (params, 0, sizeof (GParameter) * 4);
@@ -840,7 +844,7 @@ GST_START_TEST (test_rawudptransmitter_run_stun_altern_to_nowhere)
{
GParameter params[3];
- if (stunalternd_pid <= 0)
+ if (stun_alternd_data == NULL)
return;
/*
@@ -867,6 +871,54 @@ GST_START_TEST (test_rawudptransmitter_run_stun_altern_to_nowhere)
GST_END_TEST;
+void
+setup_stunalternd_valid (void)
+{
+ stun_alternd_data = stun_alternd_init (AF_INET,
+ "127.0.0.1", 3478, 3480);
+
+ if (!stun_alternd_data)
+ g_debug ("Could not spawn stunalternd,"
+ " skipping stun alternate server testing");
+}
+
+static void
+setup_stunalternd_loop (void)
+{
+ stun_alternd_data = stun_alternd_init (AF_INET,
+ "127.0.0.1", 3478, 3478);
+
+ if (!stun_alternd_data)
+ g_debug ("Could not spawn stunalternd,"
+ " skipping stun alternate server testing");
+}
+
+static void
+teardown_stunalternd (void)
+{
+ if (!stun_alternd_data)
+ return;
+
+ stun_alternd_stop (stun_alternd_data);
+ stun_alternd_data = NULL;
+}
+
+static void
+setup_stund_stunalternd (void)
+{
+ setup_stund ();
+ setup_stunalternd_valid ();
+}
+
+
+static void
+teardown_stund_stunalternd (void)
+{
+ teardown_stund ();
+ teardown_stunalternd ();
+}
+
+
static Suite *
rawudptransmitter_suite (void)
{
diff --git a/tests/check/transmitter/stunalternd.c b/tests/check/transmitter/stunalternd.c
new file mode 100644
index 0000000..19a8d95
--- /dev/null
+++ b/tests/check/transmitter/stunalternd.c
@@ -0,0 +1,350 @@
+/* Farsight 2 unit tests for FsRawUdpTransmitter
+ * This file is taken from the Nice GLib ICE library.
+ *
+ * (C) 2007-2009 Nokia Corporation
+ * @contributor: Rémi Denis-Courmont
+ * (C) 2008-2009 Collabora Ltd
+ * @author: Youness Alaoui <youness.alaoui at collabora.co.uk>
+ * @author: Olivier Crete <olivier.crete at collabora.co.uk>
+ *
+ * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <pthread.h>
+
+#ifndef SOL_IP
+# define SOL_IP IPPROTO_IP
+#endif
+
+#ifndef SOL_IPV6
+# define SOL_IPV6 IPPROTO_IPV6
+#endif
+
+#ifndef IPV6_RECVPKTINFO
+# define IPV6_RECVPKTINFO IPV6_PKTINFO
+#endif
+
+/** Default port for STUN binding discovery */
+#define IPPORT_STUN 3478
+
+#include <stun/stunagent.h>
+#include "stunalternd.h"
+
+static const uint16_t known_attributes[] = {
+ 0
+};
+
+/**
+ * Creates a listening socket
+ */
+int listen_socket (int fam, int type, int proto, unsigned int port)
+{
+ int yes = 1;
+ int fd = socket (fam, type, proto);
+ union {
+ struct sockaddr addr;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage storage;
+ } addr;
+ if (fd == -1)
+ {
+ perror ("Error opening IP port");
+ return -1;
+ }
+ if (fd < 3)
+ goto error;
+
+ memset (&addr, 0, sizeof (addr));
+ addr.storage.ss_family = fam;
+
+ switch (fam)
+ {
+ case AF_INET:
+ addr.in.sin_port = htons (port);
+ break;
+
+ case AF_INET6:
+ addr.in6.sin6_port = htons (port);
+ break;
+ }
+
+ if (bind (fd, (struct sockaddr *)&addr, sizeof (addr)))
+ {
+ perror ("Error opening IP port");
+ goto error;
+ }
+
+ if ((type == SOCK_DGRAM) || (type == SOCK_RAW))
+ {
+ switch (fam)
+ {
+ case AF_INET:
+ setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes));
+ break;
+
+ case AF_INET6:
+ setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes));
+ break;
+ }
+ }
+ else
+ {
+ if (listen (fd, INT_MAX))
+ {
+ perror ("Error opening IP port");
+ goto error;
+ }
+ }
+
+ return fd;
+
+error:
+ close (fd);
+ return -1;
+}
+
+
+/** Dequeue error from a socket if applicable */
+static int recv_err (int fd)
+{
+ struct msghdr hdr;
+ memset (&hdr, 0, sizeof (hdr));
+ return recvmsg (fd, &hdr, MSG_ERRQUEUE) >= 0;
+}
+
+
+/** Receives a message or dequeues an error from a socket */
+ssize_t recv_safe (int fd, struct msghdr *msg)
+{
+ ssize_t len = recvmsg (fd, msg, 0);
+ if (len == -1)
+ recv_err (fd);
+ else
+ if (msg->msg_flags & MSG_TRUNC)
+ {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ return len;
+}
+
+
+/** Sends a message through a socket */
+ssize_t send_safe (int fd, const struct msghdr *msg)
+{
+ ssize_t len;
+
+ do
+ len = sendmsg (fd, msg, 0);
+ while ((len == -1) && (recv_err (fd) == 0));
+
+ return len;
+}
+
+
+static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent,
+ struct sockaddr *alt_addr, socklen_t alt_addr_len)
+{
+ struct sockaddr_storage addr;
+ uint8_t buf[STUN_MAX_MESSAGE_SIZE];
+ char ctlbuf[256];
+ struct iovec iov = { buf, sizeof (buf) };
+ StunMessage request;
+ StunMessage response;
+ StunValidationStatus validation;
+ StunAgent *agent = NULL;
+
+ struct msghdr mh =
+ {
+ .msg_name = (struct sockaddr *)&addr,
+ .msg_namelen = sizeof (addr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = ctlbuf,
+ .msg_controllen = sizeof (ctlbuf)
+ };
+
+ size_t len = recv_safe (sock, &mh);
+ if (len == (size_t)-1)
+ return -1;
+
+ validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);
+
+ if (validation == STUN_VALIDATION_SUCCESS) {
+ agent = newagent;
+ }
+ else {
+ validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
+ agent = oldagent;
+ }
+
+ /* Unknown attributes */
+ if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE)
+ {
+ stun_agent_build_unknown_attributes_error (agent, &response, buf,
+ sizeof (buf), &request);
+ goto send_buf;
+ }
+
+ /* Mal-formatted packets */
+ if (validation != STUN_VALIDATION_SUCCESS ||
+ stun_message_get_class (&request) != STUN_REQUEST) {
+ return -1;
+ }
+
+ switch (stun_message_get_method (&request))
+ {
+ case STUN_BINDING:
+ stun_agent_init_error (agent, &response, buf, sizeof (buf), &request,
+ STUN_ERROR_TRY_ALTERNATE);
+ stun_message_append_addr (&response, STUN_ATTRIBUTE_ALTERNATE_SERVER,
+ alt_addr, alt_addr_len);
+ break;
+
+ default:
+ stun_agent_init_error (agent, &response, buf, sizeof (buf),
+ &request, STUN_ERROR_BAD_REQUEST);
+ }
+
+ iov.iov_len = stun_agent_finish_message (agent, &response, NULL, 0);
+send_buf:
+
+ len = send_safe (sock, &mh);
+ return (len < iov.iov_len) ? -1 : 0;
+}
+
+
+
+static int
+resolve_addr (char *server, unsigned int port, int family,
+ struct sockaddr *addr, socklen_t *addr_len)
+{
+ struct addrinfo hints, *res;
+ int ret = -1;
+ char portstr[10];
+
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ snprintf (portstr, 9, "%u", port);
+
+ ret = getaddrinfo (server, portstr, &hints, &res);
+ if (ret)
+ {
+ fprintf (stderr, "%s: %s:%s\n", server, portstr,
+ gai_strerror (ret));
+ return 0;
+ }
+
+ memcpy (addr, res->ai_addr, res->ai_addrlen);
+ *addr_len = res->ai_addrlen;
+
+ freeaddrinfo (res);
+
+ return 1;
+}
+
+struct thread_data {
+ pthread_t thread;
+ struct sockaddr_storage alt_addr;
+ socklen_t alt_addr_len;
+ StunAgent oldagent;
+ StunAgent newagent;
+ int sock;
+};
+
+void * stund_thread (void *data)
+{
+ struct thread_data *td = data;
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+ pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
+
+ for (;;)
+ dgram_process (td->sock, &td->oldagent, &td->newagent,
+ (struct sockaddr*) &td->alt_addr, td->alt_addr_len);
+
+
+ return NULL;
+}
+
+void *stun_alternd_init (int family, char *redirect_ip,
+ unsigned int redirect_port,
+ unsigned int listen_port)
+{
+ struct thread_data *td;
+
+ td = malloc (sizeof(struct thread_data));
+
+ if (!redirect_port)
+ redirect_port = IPPORT_STUN;
+
+ if (!listen_port)
+ listen_port = IPPORT_STUN;
+
+ if (!resolve_addr (redirect_ip, redirect_port, family,
+ (struct sockaddr *)&td->alt_addr, &td->alt_addr_len))
+ {
+ free (td);
+ return NULL;
+ }
+
+ td->sock = listen_socket (family, SOCK_DGRAM, IPPROTO_UDP, listen_port);
+ if (td->sock == -1)
+ {
+ free (td);
+ return NULL;
+ }
+
+ stun_agent_init (&td->oldagent, known_attributes,
+ STUN_COMPATIBILITY_RFC3489, 0);
+ stun_agent_init (&td->newagent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
+
+ pthread_create (&td->thread, NULL, stund_thread, td);
+
+ return td;
+}
+
+
+void stun_alternd_stop (void *data)
+{
+ struct thread_data *td = data;
+
+ pthread_cancel (td->thread);
+ pthread_join (td->thread, NULL);
+ free (data);
+}
diff --git a/tests/check/transmitter/stunalternd.h b/tests/check/transmitter/stunalternd.h
new file mode 100644
index 0000000..d5be290
--- /dev/null
+++ b/tests/check/transmitter/stunalternd.h
@@ -0,0 +1,38 @@
+/* Farsight 2 unit tests for FsRawUdpTransmitter
+ * This file is taken from the Nice GLib ICE library.
+ *
+ * (C) 2007-2009 Nokia Corporation
+ * @contributor: Rémi Denis-Courmont
+ * (C) 2008-2009 Collabora Ltd
+ * @author: Youness Alaoui <youness.alaoui at collabora.co.uk>
+ * @author: Olivier Crete <olivier.crete at collabora.co.uk>
+ *
+ * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __STUNALTERND_H__
+#define __STUNALTERND_H__
+
+#include <sys/socket.h>
+#include <pthread.h>
+
+void *stun_alternd_init (int family,
+ char *redirect_ip,
+ unsigned int redirect_port,
+ unsigned int listen_port);
+
+void stun_alternd_stop (void *data);
+
+#endif /* __STUNALTERND_H__ */
--
1.5.6.5
More information about the farsight-commits
mailing list