diff --git a/ChangeLog b/ChangeLog index 878cf34e48..97e692c098 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2004-06-12 Zaheer Abbas Merali + + * gst/tcp/gsttcpclientsink.c: (gst_tcpclientsink_init_send): + * gst/tcp/gsttcpclientsink.h: + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_init_receive): + * gst/tcp/gsttcpclientsrc.h: + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_init), + (gst_tcpserversink_handle_server_read), + (gst_tcpserversink_init_send): + * gst/tcp/gsttcpserversink.h: + * gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_init_receive): + * gst/tcp/gsttcpserversrc.h: + Modified the tcp plugins so they are portable (IPv4,IPv6, any future + version of IP) + 2004-06-12 Zaheer Abbas Merali * configure.ac: diff --git a/common b/common index 2188863468..1af22afdec 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 21888634686506a6938e435f9c4fd5a9f20ccc3e +Subproject commit 1af22afdec71295108f882c828e08f10d8a3e94b diff --git a/gst/tcp/gsttcpclientsink.c b/gst/tcp/gsttcpclientsink.c index 89cc299ce9..e4c1a340a9 100644 --- a/gst/tcp/gsttcpclientsink.c +++ b/gst/tcp/gsttcpclientsink.c @@ -302,8 +302,9 @@ gst_tcpclientsink_get_property (GObject * object, guint prop_id, GValue * value, static gboolean gst_tcpclientsink_init_send (GstTCPClientSink * this) { - int ret; - gchar *ip; + int ret, error; + gchar *tempport; + struct addrinfo hints, *res, *ressave; /* reset caps_sent flag */ this->caps_sent = FALSE; @@ -311,46 +312,51 @@ gst_tcpclientsink_init_send (GstTCPClientSink * this) /* create sending client socket */ GST_DEBUG_OBJECT (this, "opening sending client socket to %s:%d", this->host, this->port); - if ((this->sock_fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) { - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM); + + memset (&hints, 0, sizeof (struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + tempport = g_strdup_printf ("%d", this->port); + error = getaddrinfo (this->host, tempport, &hints, &res); + g_free (tempport); + if (error != 0) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, + (_("Error getting address info (%s:%d): %s"), this->host, this->port, + gai_strerror (error)), (NULL)); return FALSE; } + + ressave = res; + + this->sock_fd = -1; + + while (res) { + this->sock_fd = socket (res->ai_family, res->ai_socktype, res->ai_protocol); + if (this->sock_fd >= 0) { + ret = connect (this->sock_fd, res->ai_addr, res->ai_addrlen); + if (ret == 0) + break; + close (this->sock_fd); + this->sock_fd = -1; + } + res = res->ai_next; + } + freeaddrinfo (ressave); + + if (errno == ECONNREFUSED) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, + (_("Connection to %s:%d refused."), this->host, this->port), (NULL)); + return FALSE; + } + + if (this->sock_fd == -1) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } + GST_DEBUG_OBJECT (this, "opened sending client socket with fd %d", this->sock_fd); - /* look up name if we need to */ - ip = gst_tcp_host_to_ip (GST_ELEMENT (this), this->host); - if (!ip) - return FALSE; - GST_DEBUG_OBJECT (this, "IP address for host %s is %s", this->host, ip); - - /* connect to server */ - memset (&this->server_sin, 0, sizeof (this->server_sin)); - this->server_sin.sin_family = AF_INET; /* network socket */ - this->server_sin.sin_port = htons (this->port); /* on port */ - this->server_sin.sin_addr.s_addr = inet_addr (ip); /* on host ip */ - - GST_DEBUG_OBJECT (this, "connecting to server"); - ret = connect (this->sock_fd, (struct sockaddr *) &this->server_sin, - sizeof (this->server_sin)); - - if (ret) { - switch (errno) { - case ECONNREFUSED: - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, - (_("Connection to %s:%d refused."), this->host, this->port), - (NULL)); - return FALSE; - break; - default: - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), - ("connect to %s:%d failed: %s", this->host, this->port, - g_strerror (errno))); - return FALSE; - break; - } - } - GST_FLAG_SET (this, GST_TCPCLIENTSINK_OPEN); this->data_written = 0; diff --git a/gst/tcp/gsttcpclientsink.h b/gst/tcp/gsttcpclientsink.h index 9cd657ac86..722203f888 100644 --- a/gst/tcp/gsttcpclientsink.h +++ b/gst/tcp/gsttcpclientsink.h @@ -73,7 +73,6 @@ struct _GstTCPClientSink { /* server information */ int port; gchar *host; - struct sockaddr_in server_sin; /* socket */ int sock_fd; diff --git a/gst/tcp/gsttcpclientsrc.c b/gst/tcp/gsttcpclientsrc.c index 2b833adbad..44741bee72 100644 --- a/gst/tcp/gsttcpclientsrc.c +++ b/gst/tcp/gsttcpclientsrc.c @@ -393,51 +393,60 @@ gst_tcpclientsrc_get_property (GObject * object, guint prop_id, GValue * value, static gboolean gst_tcpclientsrc_init_receive (GstTCPClientSrc * this) { - int ret; - gchar *ip; + int ret, error; + gchar *tempport; + + struct addrinfo hints, *res, *ressave; /* create receiving client socket */ GST_DEBUG_OBJECT (this, "opening receiving client socket to %s:%d", this->host, this->port); - if ((this->sock_fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) { + + memset (&hints, 0, sizeof (struct addrinfo)); + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + tempport = g_strdup_printf ("%d", this->port); + + error = getaddrinfo (this->host, tempport, &hints, &res); + g_free (tempport); + if (error != 0) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, + (_("Error getting address info (%s:%d): %s"), this->host, this->port, + gai_strerror (error)), (NULL)); + return FALSE; + } + + ressave = res; + + this->sock_fd = -1; + while (res) { + this->sock_fd = socket (res->ai_family, res->ai_socktype, res->ai_protocol); + if (this->sock_fd >= 0) { + ret = connect (this->sock_fd, res->ai_addr, res->ai_addrlen); + if (ret == 0) + break; + close (this->sock_fd); + this->sock_fd = -1; + } + res = res->ai_next; + } + freeaddrinfo (ressave); + + if (errno == ECONNREFUSED) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, + (_("Connection to %s:%d refused."), this->host, this->port), (NULL)); + return FALSE; + } + + if (this->sock_fd == -1) { GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM); return FALSE; } GST_DEBUG_OBJECT (this, "opened receiving client socket with fd %d", this->sock_fd); - /* look up name if we need to */ - ip = gst_tcp_host_to_ip (GST_ELEMENT (this), this->host); - if (!ip) - return FALSE; - GST_DEBUG_OBJECT (this, "IP address for host %s is %s", this->host, ip); - - /* connect to server */ - memset (&this->server_sin, 0, sizeof (this->server_sin)); - this->server_sin.sin_family = AF_INET; /* network socket */ - this->server_sin.sin_port = htons (this->port); /* on port */ - this->server_sin.sin_addr.s_addr = inet_addr (ip); /* on host ip */ - - GST_DEBUG_OBJECT (this, "connecting to server"); - ret = connect (this->sock_fd, (struct sockaddr *) &this->server_sin, - sizeof (this->server_sin)); - - if (ret) { - switch (errno) { - case ECONNREFUSED: - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, - (_("Connection to %s:%d refused."), this->host, this->port), - (NULL)); - return FALSE; - break; - default: - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), - ("connect to %s:%d failed: %s", this->host, this->port, - g_strerror (errno))); - return FALSE; - break; - } - } this->send_discont = TRUE; this->buffer_after_discont = NULL; diff --git a/gst/tcp/gsttcpclientsrc.h b/gst/tcp/gsttcpclientsrc.h index 414082b03e..234677ef62 100644 --- a/gst/tcp/gsttcpclientsrc.h +++ b/gst/tcp/gsttcpclientsrc.h @@ -62,7 +62,6 @@ struct _GstTCPClientSrc { /* server information */ int port; gchar *host; - struct sockaddr_in server_sin; /* socket */ int sock_fd; diff --git a/gst/tcp/gsttcpserversink.c b/gst/tcp/gsttcpserversink.c index 42780a1ac4..ea58ef6de0 100644 --- a/gst/tcp/gsttcpserversink.c +++ b/gst/tcp/gsttcpserversink.c @@ -29,6 +29,8 @@ #include #endif +#include + #include "gsttcpserversink.h" #include "gsttcp-marshal.h" @@ -187,6 +189,7 @@ gst_tcpserversink_init (GstTCPServerSink * this) this->protocol = GST_TCP_PROTOCOL_TYPE_NONE; this->clock = NULL; + this->host = NULL; } static void @@ -208,8 +211,11 @@ gst_tcpserversink_handle_server_read (GstTCPServerSink * sink) { /* new client */ int client_sock_fd; - struct sockaddr_in client_address; + struct sockaddr_storage client_address; int client_address_len; + char clienthost[NI_MAXHOST]; + char clientservice[NI_MAXSERV]; + int error; client_sock_fd = accept (sink->server_sock_fd, (struct sockaddr *) &client_address, @@ -220,11 +226,19 @@ gst_tcpserversink_handle_server_read (GstTCPServerSink * sink) return FALSE; } FD_SET (client_sock_fd, &(sink->clientfds)); - GST_DEBUG_OBJECT (sink, "added new client ip %s with fd %d", - inet_ntoa (client_address.sin_addr), client_sock_fd); + error = getnameinfo ((struct sockaddr *) &client_address, client_address_len, + clienthost, sizeof (clienthost), clientservice, + sizeof (clientservice), NI_NUMERICHOST); + if (error != 0) { + GST_DEBUG_OBJECT (sink, "added new client address %s with fd %d", + clienthost, client_sock_fd); + } else { + GST_DEBUG_OBJECT (sink, "problem error received from getnameinfo: %d", + error); + } g_signal_emit (G_OBJECT (sink), gst_tcpserversink_signals[SIGNAL_CLIENT_ADDED], 0, - inet_ntoa (client_address.sin_addr), client_sock_fd); + g_strdup (clienthost), client_sock_fd); return TRUE; } @@ -546,15 +560,49 @@ gst_tcpserversink_get_property (GObject * object, guint prop_id, GValue * value, static gboolean gst_tcpserversink_init_send (GstTCPServerSink * this) { - int ret; + int ret, error; + struct addrinfo hints, *res, *ressave; + char *tempport; - /* create sending server socket */ - if ((this->server_sock_fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) { - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM); + + /* name the socket */ + memset (&hints, 0, sizeof (struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + tempport = g_strdup_printf ("%d", this->server_port); + + error = getaddrinfo (this->host, tempport, &hints, &res); + g_free (tempport); + if (error != 0) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("getaddrinfo failed: %s", gai_strerror (error))); + return FALSE; + } + ressave = res; + + /* Try open socket with each address getaddrinfo returned, until getting + a valid listening socket */ + this->server_sock_fd = -1; + while (res) { + this->server_sock_fd = + socket (res->ai_family, res->ai_socktype, res->ai_protocol); + if (this->server_sock_fd >= 0) { + ret = bind (this->server_sock_fd, res->ai_addr, res->ai_addrlen); + if (ret == 0) + break; + close (this->server_sock_fd); + this->server_sock_fd = -1; + } + res = res->ai_next; + } + freeaddrinfo (ressave); + + if (this->server_sock_fd < 0) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("bind failed: %s", g_strerror (errno))); return FALSE; } - GST_DEBUG_OBJECT (this, "opened sending server socket with fd %d", - this->server_sock_fd); /* make address reusable */ if (setsockopt (this->server_sock_fd, SOL_SOCKET, SO_REUSEADDR, &ret, @@ -570,28 +618,6 @@ gst_tcpserversink_init_send (GstTCPServerSink * this) ("Could not setsockopt: %s", g_strerror (errno))); return FALSE; } - - /* name the socket */ - memset (&this->server_sin, 0, sizeof (this->server_sin)); - this->server_sin.sin_family = AF_INET; /* network socket */ - this->server_sin.sin_port = htons (this->server_port); /* on port */ - this->server_sin.sin_addr.s_addr = htonl (INADDR_ANY); /* for hosts */ - - /* bind it */ - GST_DEBUG_OBJECT (this, "binding server socket to address"); - ret = bind (this->server_sock_fd, (struct sockaddr *) &this->server_sin, - sizeof (this->server_sin)); - - if (ret) { - switch (errno) { - default: - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), - ("bind failed: %s", g_strerror (errno))); - return FALSE; - break; - } - } - /* set the server socket to nonblocking */ fcntl (this->server_sock_fd, F_SETFL, O_NONBLOCK); diff --git a/gst/tcp/gsttcpserversink.h b/gst/tcp/gsttcpserversink.h index 4499623684..37e5984f7c 100644 --- a/gst/tcp/gsttcpserversink.h +++ b/gst/tcp/gsttcpserversink.h @@ -73,7 +73,6 @@ struct _GstTCPServerSink { /* server information */ int server_port; gchar *host; - struct sockaddr_in server_sin; /* socket */ int server_sock_fd; diff --git a/gst/tcp/gsttcpserversrc.c b/gst/tcp/gsttcpserversrc.c index 115a330d4c..dd5e5948ee 100644 --- a/gst/tcp/gsttcpserversrc.c +++ b/gst/tcp/gsttcpserversrc.c @@ -456,18 +456,50 @@ gst_tcpserversrc_get_property (GObject * object, guint prop_id, GValue * value, static gboolean gst_tcpserversrc_init_receive (GstTCPServerSrc * this) { - int ret; + int ret, error; + struct addrinfo hints, *res, *ressave; + gchar *tempport; + struct sockaddr_storage client_address; + int client_address_len; - /* reset caps_received flag */ - this->caps_received = FALSE; + /* name the socket */ + memset (&hints, 0, sizeof (struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + tempport = g_strdup_printf ("%d", this->server_port); - /* create the server listener socket */ - if ((this->server_sock_fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) { - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM); + error = getaddrinfo (this->host, tempport, &hints, &res); + g_free (tempport); + if (error != 0) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("getaddrinfo failed: %s", gai_strerror (error))); + return FALSE; + } + ressave = res; + + /* Try open socket with each address getaddrinfo returned, until getting + a valid listening socket */ + this->server_sock_fd = -1; + while (res) { + this->server_sock_fd = + socket (res->ai_family, res->ai_socktype, res->ai_protocol); + if (this->server_sock_fd >= 0) { + ret = bind (this->server_sock_fd, res->ai_addr, res->ai_addrlen); + if (ret == 0) + break; + close (this->server_sock_fd); + this->server_sock_fd = -1; + } + res = res->ai_next; + } + freeaddrinfo (ressave); + + if (this->server_sock_fd < 0) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("bind failed: %s", g_strerror (errno))); return FALSE; } - GST_DEBUG_OBJECT (this, "opened receiving server socket with fd %d", - this->server_sock_fd); /* make address reusable */ if (setsockopt (this->server_sock_fd, SOL_SOCKET, SO_REUSEADDR, &ret, @@ -477,35 +509,8 @@ gst_tcpserversrc_init_receive (GstTCPServerSrc * this) return FALSE; } - /* name the socket */ - memset (&this->server_sin, 0, sizeof (this->server_sin)); - this->server_sin.sin_family = AF_INET; /* network socket */ - this->server_sin.sin_port = htons (this->server_port); /* on port */ - if (this->host) { - gchar *host = gst_tcp_host_to_ip (GST_ELEMENT (this), this->host); - - if (!host) - return FALSE; - - this->server_sin.sin_addr.s_addr = inet_addr (host); - g_free (host); - } else - this->server_sin.sin_addr.s_addr = htonl (INADDR_ANY); - - /* bind it */ - GST_DEBUG_OBJECT (this, "binding server socket to address"); - ret = bind (this->server_sock_fd, (struct sockaddr *) &this->server_sin, - sizeof (this->server_sin)); - - if (ret) { - switch (errno) { - default: - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), - ("bind failed: %s", g_strerror (errno))); - return FALSE; - break; - } - } + /* reset caps_received flag */ + this->caps_received = FALSE; GST_DEBUG_OBJECT (this, "listening on server socket %d with queue of %d", this->server_sock_fd, TCP_BACKLOG); @@ -519,8 +524,8 @@ gst_tcpserversrc_init_receive (GstTCPServerSrc * this) somewhere else */ GST_DEBUG_OBJECT (this, "waiting for client"); this->client_sock_fd = - accept (this->server_sock_fd, (struct sockaddr *) &this->client_sin, - &this->client_sin_len); + accept (this->server_sock_fd, (struct sockaddr *) &client_address, + &client_address_len); if (this->client_sock_fd == -1) { GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), ("Could not accept client on server socket: %s", g_strerror (errno))); diff --git a/gst/tcp/gsttcpserversrc.h b/gst/tcp/gsttcpserversrc.h index fbc9e3618a..4645118a22 100644 --- a/gst/tcp/gsttcpserversrc.h +++ b/gst/tcp/gsttcpserversrc.h @@ -72,8 +72,6 @@ struct _GstTCPServerSrc { int server_sock_fd; /* client information */ - struct sockaddr_in client_sin; - socklen_t client_sin_len; int client_sock_fd; /* number of bytes we've gotten */