[Telepathy-commits] [telepathy-salut/master] GibberListener: when the port is 0, let a random port be chosen, returns this port. Add a unit test.
Alban Crequy
alban.crequy at collabora.co.uk
Thu Nov 6 05:03:19 PST 2008
---
lib/gibber/gibber-listener.c | 67 ++++++++++++++++++++++++++++-------------
lib/gibber/gibber-listener.h | 8 ++--
tests/check-gibber-listener.c | 23 +++++++++++++-
3 files changed, 72 insertions(+), 26 deletions(-)
diff --git a/lib/gibber/gibber-listener.c b/lib/gibber/gibber-listener.c
index 6e99c25..4f79cbf 100644
--- a/lib/gibber/gibber-listener.c
+++ b/lib/gibber/gibber-listener.c
@@ -193,8 +193,13 @@ add_listener (GibberListener *self, int family, int type, int protocol,
Listener *l;
GibberListenerPrivate *priv = self->priv;
char name [NI_MAXHOST], portname[NI_MAXSERV];
- struct sockaddr_storage baddress;
- socklen_t baddrlen;
+ union {
+ struct sockaddr addr;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage storage;
+ } baddress;
+ socklen_t baddrlen = sizeof (baddress);
fd = socket (family, type, protocol);
if (fd == -1)
@@ -256,21 +261,21 @@ add_listener (GibberListener *self, int family, int type, int protocol,
goto error;
}
- getsockname (fd, (struct sockaddr *)&baddress, &baddrlen);
- getnameinfo ((struct sockaddr *)&baddress, baddrlen, name, sizeof (name),
+ getsockname (fd, &baddress.addr, &baddrlen);
+ getnameinfo (&baddress.addr, baddrlen, name, sizeof (name),
portname, sizeof (portname), NI_NUMERICHOST | NI_NUMERICSERV);
DEBUG ( "Listening on %s port %s...", name, portname);
if (port != NULL)
{
- switch (((struct sockaddr *)&baddress)->sa_family)
+ switch (family)
{
case AF_INET:
- *port = ((struct sockaddr_in *) &baddress)->sin_port;
+ *port = g_ntohs (baddress.in.sin_port);
break;
case AF_INET6:
- *port = ((struct sockaddr_in6 *) &baddress)->sin6_port;
+ *port = g_ntohs (baddress.in6.sin6_port);
break;
default:
*port = 0;
@@ -295,16 +300,15 @@ error:
return FALSE;
}
-/* port: if 0, choose a random port
+/* port: if 0, choose a random port and set new_port
*/
static gboolean
-listen_tcp_af (GibberListener *listener, int port,
- GibberAddressFamily family, gboolean loopback, GError **error)
+listen_tcp_af (GibberListener *listener, int port, GibberAddressFamily family,
+ gboolean loopback, int *new_port, GError **error)
{
struct addrinfo req, *ans = NULL, *a;
GibberListenerPrivate *priv = listener->priv;
int ret;
- int new_port = 0;
gchar sport[6];
memset (&req, 0, sizeof (req));
@@ -338,24 +342,33 @@ listen_tcp_af (GibberListener *listener, int port,
goto error;
}
+ *new_port = 0;
for (a = ans ; a != NULL ; a = a->ai_next)
{
+ union {
+ struct sockaddr *addr;
+ struct sockaddr_storage *storage;
+ struct sockaddr_in *in;
+ struct sockaddr_in6 *in6;
+ } addr;
gboolean ret;
GError *terror = NULL;
+ addr.addr = a->ai_addr;
+
/* the caller let us choose a port and we are not in the first round */
- if (port == 0 && new_port != 0)
+ if (port == 0 && *new_port != 0)
{
if (a->ai_family == AF_INET)
- ((struct sockaddr_in *) a->ai_addr)->sin_port = port;
+ addr.in->sin_port = *new_port;
else if (a->ai_family == AF_INET6)
- ((struct sockaddr_in6 *) a->ai_addr)->sin6_port = port;
+ addr.in6->sin6_port = *new_port;
else
g_assert_not_reached ();
}
ret = add_listener (listener, a->ai_family, a->ai_socktype,
- a->ai_protocol, a->ai_addr, a->ai_addrlen, &new_port, &terror);
+ a->ai_protocol, a->ai_addr, a->ai_addrlen, new_port, &terror);
if (ret == FALSE)
{
@@ -389,20 +402,26 @@ error:
return FALSE;
}
-gboolean
+int
gibber_listener_listen_tcp (GibberListener *listener, int port, GError **error)
{
return gibber_listener_listen_tcp_af (listener, port, GIBBER_AF_ANY, error);
}
-gboolean
+int
gibber_listener_listen_tcp_af (GibberListener *listener, int port,
GibberAddressFamily family, GError **error)
{
- return listen_tcp_af (listener, port, family, FALSE, error);
+ int new_port = 0;
+ int ret = listen_tcp_af (listener, port, family, FALSE, &new_port, error);
+
+ if (ret == FALSE)
+ return 0;
+ else
+ return new_port;
}
-gboolean
+int
gibber_listener_listen_tcp_loopback (GibberListener *listener,
int port, GError **error)
{
@@ -410,11 +429,17 @@ gibber_listener_listen_tcp_loopback (GibberListener *listener,
GIBBER_AF_ANY, error);
}
-gboolean
+int
gibber_listener_listen_tcp_loopback_af (GibberListener *listener,
int port, GibberAddressFamily family, GError **error)
{
- return listen_tcp_af (listener, port, family, TRUE, error);
+ int new_port = 0;
+ int ret = listen_tcp_af (listener, port, family, TRUE, &new_port, error);
+
+ if (ret == FALSE)
+ return 0;
+ else
+ return new_port;
}
gboolean
diff --git a/lib/gibber/gibber-listener.h b/lib/gibber/gibber-listener.h
index 712b409..9c8d070 100644
--- a/lib/gibber/gibber-listener.h
+++ b/lib/gibber/gibber-listener.h
@@ -77,16 +77,16 @@ GType gibber_listener_get_type (void);
GibberListener *gibber_listener_new (void);
-gboolean gibber_listener_listen_tcp (GibberListener *listener,
+int gibber_listener_listen_tcp (GibberListener *listener,
int port, GError **error);
-gboolean gibber_listener_listen_tcp_af (GibberListener *listener,
+int gibber_listener_listen_tcp_af (GibberListener *listener,
int port, GibberAddressFamily family, GError **error);
-gboolean gibber_listener_listen_tcp_loopback (GibberListener *listener,
+int gibber_listener_listen_tcp_loopback (GibberListener *listener,
int port, GError **error);
-gboolean gibber_listener_listen_tcp_loopback_af (GibberListener *listener,
+int gibber_listener_listen_tcp_loopback_af (GibberListener *listener,
int port, GibberAddressFamily family, GError **error);
gboolean gibber_listener_listen_socket (GibberListener *listener,
diff --git a/tests/check-gibber-listener.c b/tests/check-gibber-listener.c
index 240c225..3e26ff3 100644
--- a/tests/check-gibber-listener.c
+++ b/tests/check-gibber-listener.c
@@ -80,6 +80,7 @@ START_TEST (test_tcp_listen)
{
GibberListener *listener_unix;
GibberListener *listener;
+ GibberListener *listener_without_port;
GibberListener *listener2;
GibberUnixTransport *unix_transport;
int port;
@@ -116,7 +117,27 @@ START_TEST (test_tcp_listen)
g_object_unref (listener_unix);
g_object_unref (unix_transport);
- /* tcp socket tests */
+ /* tcp socket tests without a specified port */
+ listener_without_port = gibber_listener_new ();
+ fail_if (listener_without_port == NULL);
+
+ g_signal_connect (listener_without_port, "new-connection",
+ G_CALLBACK (new_connection_cb), mainloop);
+
+ port = gibber_listener_listen_tcp (listener_without_port, 0, &error);
+ fail_if (port <= 0);
+
+ signalled = FALSE;
+ transport = connect_to_port (port, mainloop);
+ if (!signalled)
+ g_main_loop_run (mainloop);
+
+ fail_if (!got_connection, "Failed to connect");
+
+ g_object_unref (listener_without_port);
+ g_object_unref (transport);
+
+ /* tcp socket tests with a specified port */
listener = gibber_listener_new ();
fail_if (listener == NULL);
--
1.5.6.5
More information about the Telepathy-commits
mailing list