mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
gst/udp/gstudpnetutils.*: Provide a bunch of helper methods to deal with IPv4 and IPv6 transparently.
Original commit message from CVS: Patch by: Bruno Santos <brunof at ua dot pt> * gst/udp/gstudpnetutils.c: (gst_udp_get_addr), (gst_udp_join_group), (gst_udp_leave_group), (gst_udp_is_multicast): * gst/udp/gstudpnetutils.h: Provide a bunch of helper methods to deal with IPv4 and IPv6 transparently. * gst/udp/gstmultiudpsink.c: (gst_multiudpsink_class_init), (gst_multiudpsink_init), (gst_multiudpsink_set_property), (gst_multiudpsink_get_property), (join_multicast), (gst_multiudpsink_init_send), (gst_multiudpsink_add_internal), (gst_multiudpsink_remove): * gst/udp/gstmultiudpsink.h: Add multicast TTL and loopback properties. Use the helper methods to implement ip4 and ip6. * gst/udp/gstudpsrc.c: (gst_udpsrc_create), (gst_udpsrc_start): * gst/udp/gstudpsrc.h: Use the helper methods to implement ip4 and ip6. Fixes #515962.
This commit is contained in:
parent
94fb1d9870
commit
570718c2fe
7 changed files with 301 additions and 105 deletions
25
ChangeLog
25
ChangeLog
|
@ -1,3 +1,28 @@
|
|||
2008-05-21 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||
|
||||
Patch by: Bruno Santos <brunof at ua dot pt>
|
||||
|
||||
* gst/udp/gstudpnetutils.c: (gst_udp_get_addr),
|
||||
(gst_udp_join_group), (gst_udp_leave_group),
|
||||
(gst_udp_is_multicast):
|
||||
* gst/udp/gstudpnetutils.h:
|
||||
Provide a bunch of helper methods to deal with IPv4 and IPv6
|
||||
transparently.
|
||||
|
||||
* gst/udp/gstmultiudpsink.c: (gst_multiudpsink_class_init),
|
||||
(gst_multiudpsink_init), (gst_multiudpsink_set_property),
|
||||
(gst_multiudpsink_get_property), (join_multicast),
|
||||
(gst_multiudpsink_init_send), (gst_multiudpsink_add_internal),
|
||||
(gst_multiudpsink_remove):
|
||||
* gst/udp/gstmultiudpsink.h:
|
||||
Add multicast TTL and loopback properties.
|
||||
Use the helper methods to implement ip4 and ip6.
|
||||
|
||||
* gst/udp/gstudpsrc.c: (gst_udpsrc_create), (gst_udpsrc_start):
|
||||
* gst/udp/gstudpsrc.h:
|
||||
Use the helper methods to implement ip4 and ip6.
|
||||
Fixes #515962.
|
||||
|
||||
2008-05-21 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||
|
||||
Patch by: Patrick Radizi <patrick dot radizi at axis dot com>
|
||||
|
|
|
@ -81,6 +81,8 @@ enum
|
|||
#define DEFAULT_SOCK -1
|
||||
#define DEFAULT_CLIENTS NULL
|
||||
#define DEFAULT_AUTO_MULTICAST TRUE
|
||||
#define DEFAULT_TTL 64
|
||||
#define DEFAULT_LOOP TRUE
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -91,7 +93,9 @@ enum
|
|||
PROP_CLOSEFD,
|
||||
PROP_SOCK,
|
||||
PROP_CLIENTS,
|
||||
PROP_AUTO_MULTICAST
|
||||
PROP_AUTO_MULTICAST,
|
||||
PROP_TTL,
|
||||
PROP_LOOP
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
|
@ -292,6 +296,14 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
|
|||
"Automatically join/leave multicast groups",
|
||||
"Automatically join/leave the multicast groups, FALSE means user"
|
||||
" has to do it himself", DEFAULT_AUTO_MULTICAST, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, PROP_TTL,
|
||||
g_param_spec_int ("ttl", "Multicast TTL",
|
||||
"Used for setting the multicast TTL parameter",
|
||||
0, 255, DEFAULT_TTL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, PROP_LOOP,
|
||||
g_param_spec_boolean ("loop", "Multicast Loopback",
|
||||
"Used for setting the multicast loop parameter. TRUE = enable,"
|
||||
" FALSE = disable", DEFAULT_LOOP, G_PARAM_READWRITE));
|
||||
|
||||
gstelement_class->change_state = gst_multiudpsink_change_state;
|
||||
|
||||
|
@ -316,6 +328,8 @@ gst_multiudpsink_init (GstMultiUDPSink * sink)
|
|||
sink->closefd = DEFAULT_CLOSEFD;
|
||||
sink->externalfd = (sink->sockfd != -1);
|
||||
sink->auto_multicast = DEFAULT_AUTO_MULTICAST;
|
||||
sink->ttl = DEFAULT_TTL;
|
||||
sink->loop = DEFAULT_LOOP;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -473,6 +487,12 @@ gst_multiudpsink_set_property (GObject * object, guint prop_id,
|
|||
case PROP_AUTO_MULTICAST:
|
||||
udpsink->auto_multicast = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_TTL:
|
||||
udpsink->ttl = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_LOOP:
|
||||
udpsink->loop = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -510,6 +530,12 @@ gst_multiudpsink_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_AUTO_MULTICAST:
|
||||
g_value_set_boolean (value, udpsink->auto_multicast);
|
||||
break;
|
||||
case PROP_TTL:
|
||||
g_value_set_int (value, udpsink->ttl);
|
||||
break;
|
||||
case PROP_LOOP:
|
||||
g_value_set_boolean (value, udpsink->loop);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -517,33 +543,13 @@ gst_multiudpsink_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
}
|
||||
|
||||
static void
|
||||
join_multicast (GstUDPClient * client)
|
||||
join_multicast (GstUDPClient * client, gboolean loop, int ttl)
|
||||
{
|
||||
unsigned char ttl = 64;
|
||||
unsigned char loop = 1;
|
||||
|
||||
/* Joining the multicast group */
|
||||
/* FIXME, can we use multicast and unicast over the same
|
||||
* socket? if not, search for socket of this multicast group or
|
||||
* create a new one. */
|
||||
if (setsockopt (*(client->sock), IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&(client->multi_addr), sizeof (client->multi_addr)) < 0)
|
||||
perror ("setsockopt IP_ADD_MEMBERSHIP\n");
|
||||
if (setsockopt (*(client->sock), IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
|
||||
sizeof (ttl)) < 0)
|
||||
perror ("setsockopt IP_MULTICAST_TTL\n");
|
||||
if (setsockopt (*(client->sock), IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
|
||||
sizeof (loop)) < 0)
|
||||
perror ("setsockopt IP_MULTICAST_LOOP\n");
|
||||
}
|
||||
|
||||
static void
|
||||
leave_multicast (GstUDPClient * client)
|
||||
{
|
||||
if (setsockopt (*(client->sock), IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
||||
&(client->multi_addr), sizeof (client->multi_addr)) < 0)
|
||||
GST_WARNING ("setsockopt IP_DROP_MEMBERSHIP failed '%s'",
|
||||
g_strerror (errno));
|
||||
gst_udp_join_group (*(client->sock), loop, ttl, &client->theiraddr);
|
||||
}
|
||||
|
||||
/* create a socket for sending to remote machine */
|
||||
|
@ -557,6 +563,7 @@ gst_multiudpsink_init_send (GstMultiUDPSink * sink)
|
|||
|
||||
if (sink->sockfd == -1) {
|
||||
/* create sender socket */
|
||||
if ((sink->sock = socket (AF_INET6, SOCK_DGRAM, 0)) == -1)
|
||||
if ((sink->sock = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
goto no_socket;
|
||||
|
||||
|
@ -580,8 +587,8 @@ gst_multiudpsink_init_send (GstMultiUDPSink * sink)
|
|||
|
||||
for (clients = sink->clients; clients; clients = g_list_next (clients)) {
|
||||
client = (GstUDPClient *) clients->data;
|
||||
if (client->multi_addr.imr_multiaddr.s_addr && sink->auto_multicast)
|
||||
join_multicast (client);
|
||||
if (gst_udp_is_multicast (&client->theiraddr) && sink->auto_multicast)
|
||||
join_multicast (client, sink->loop, sink->ttl);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
|
@ -612,8 +619,6 @@ static void
|
|||
gst_multiudpsink_add_internal (GstMultiUDPSink * sink, const gchar * host,
|
||||
gint port, gboolean lock)
|
||||
{
|
||||
struct hostent *he;
|
||||
struct in_addr addr;
|
||||
GstUDPClient *client;
|
||||
GTimeVal now;
|
||||
|
||||
|
@ -623,42 +628,19 @@ gst_multiudpsink_add_internal (GstMultiUDPSink * sink, const gchar * host,
|
|||
client->port = port;
|
||||
client->sock = &sink->sock;
|
||||
|
||||
memset (&client->theiraddr, 0, sizeof (client->theiraddr));
|
||||
memset (&client->multi_addr, 0, sizeof (client->multi_addr));
|
||||
client->theiraddr.sin_family = AF_INET; /* host byte order */
|
||||
client->theiraddr.sin_port = g_htons (port); /* short, network byte order */
|
||||
if (gst_udp_get_addr (host, port, &client->theiraddr) < 0)
|
||||
goto getaddrinfo_error;
|
||||
|
||||
g_get_current_time (&now);
|
||||
client->connect_time = GST_TIMEVAL_TO_TIME (now);
|
||||
|
||||
/* if its an IP address */
|
||||
if (inet_aton (host, &addr)) {
|
||||
/* check if its a multicast address */
|
||||
if ((g_ntohl (addr.s_addr) & 0xf0000000) == 0xe0000000) {
|
||||
if (*client->sock > 0 && gst_udp_is_multicast (&client->theiraddr) &&
|
||||
sink->auto_multicast) {
|
||||
GST_DEBUG_OBJECT (sink, "multicast address detected");
|
||||
client->multi_addr.imr_multiaddr.s_addr = addr.s_addr;
|
||||
client->multi_addr.imr_interface.s_addr = INADDR_ANY;
|
||||
|
||||
client->theiraddr.sin_addr = client->multi_addr.imr_multiaddr;
|
||||
|
||||
join_multicast (client, sink->loop, sink->ttl);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (sink, "normal address detected");
|
||||
client->theiraddr.sin_addr = *((struct in_addr *) &addr);
|
||||
}
|
||||
/* if init_send has already been called, set sockopts for multicast */
|
||||
if (*client->sock > 0 && client->multi_addr.imr_multiaddr.s_addr &&
|
||||
sink->auto_multicast)
|
||||
join_multicast (client);
|
||||
}
|
||||
/* we dont need to lookup for localhost */
|
||||
else if (strcmp (host, "localhost") == 0 && inet_aton ("127.0.0.1", &addr)) {
|
||||
client->theiraddr.sin_addr = *((struct in_addr *) &addr);
|
||||
}
|
||||
/* if its a hostname */
|
||||
else if ((he = gethostbyname (host))) {
|
||||
client->theiraddr.sin_addr = *((struct in_addr *) he->h_addr);
|
||||
} else {
|
||||
goto host_error;
|
||||
}
|
||||
|
||||
if (lock)
|
||||
|
@ -673,9 +655,9 @@ gst_multiudpsink_add_internal (GstMultiUDPSink * sink, const gchar * host,
|
|||
return;
|
||||
|
||||
/* ERRORS */
|
||||
host_error:
|
||||
getaddrinfo_error:
|
||||
{
|
||||
GST_WARNING_OBJECT (sink, "hostname lookup error?");
|
||||
GST_WARNING_OBJECT (sink, "getaddrinfo lookup error?");
|
||||
g_free (client->host);
|
||||
g_free (client);
|
||||
return;
|
||||
|
@ -728,9 +710,9 @@ gst_multiudpsink_remove (GstMultiUDPSink * sink, const gchar * host, gint port)
|
|||
g_get_current_time (&now);
|
||||
client->disconnect_time = GST_TIMEVAL_TO_TIME (now);
|
||||
|
||||
if (*(client->sock) != -1 && client->multi_addr.imr_multiaddr.s_addr
|
||||
if (*(client->sock) != -1 && gst_udp_is_multicast (&client->theiraddr)
|
||||
&& sink->auto_multicast)
|
||||
leave_multicast (client);
|
||||
gst_udp_leave_group (*(client->sock), &client->theiraddr);
|
||||
|
||||
/* Unlock to emit signal before we delete the actual client */
|
||||
g_mutex_unlock (sink->client_lock);
|
||||
|
|
|
@ -40,8 +40,7 @@ typedef struct _GstMultiUDPSinkClass GstMultiUDPSinkClass;
|
|||
typedef struct {
|
||||
int *sock;
|
||||
|
||||
struct sockaddr_in theiraddr;
|
||||
struct ip_mreq multi_addr;
|
||||
struct sockaddr_storage theiraddr;
|
||||
|
||||
gchar *host;
|
||||
gint port;
|
||||
|
@ -72,6 +71,8 @@ struct _GstMultiUDPSink {
|
|||
gboolean externalfd;
|
||||
|
||||
gboolean auto_multicast;
|
||||
gint ttl;
|
||||
gboolean loop;
|
||||
};
|
||||
|
||||
struct _GstMultiUDPSinkClass {
|
||||
|
|
|
@ -22,21 +22,14 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "gstudpnetutils.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
int
|
||||
gst_udp_net_utils_win32_inet_aton (const char *c, struct in_addr *paddr)
|
||||
{
|
||||
paddr->s_addr = inet_addr (c);
|
||||
|
||||
if (paddr->s_addr == INADDR_NONE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_udp_net_utils_win32_wsa_startup (GstObject * obj)
|
||||
{
|
||||
|
@ -60,3 +53,178 @@ gst_udp_net_utils_win32_wsa_startup (GstObject * obj)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr)
|
||||
{
|
||||
struct addrinfo hints, *res, *nres;
|
||||
char service[NI_MAXSERV];
|
||||
int ret;
|
||||
|
||||
memset (&hints, 0, sizeof (hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
snprintf (service, sizeof (service) - 1, "%d", port);
|
||||
service[sizeof (service) - 1] = '\0';
|
||||
|
||||
if ((ret = getaddrinfo (hostname, (port == -1) ? NULL : service, &hints,
|
||||
&res)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nres = res;
|
||||
while (nres) {
|
||||
if (nres->ai_family == AF_INET || nres->ai_family == AF_INET6)
|
||||
break;
|
||||
nres = nres->ai_next;
|
||||
}
|
||||
|
||||
if (nres) {
|
||||
memcpy (addr, nres->ai_addr, nres->ai_addrlen);
|
||||
} else {
|
||||
errno = EAI_ADDRFAMILY;
|
||||
ret = -1;
|
||||
}
|
||||
freeaddrinfo (res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
gst_udp_join_group (int sockfd, gboolean loop, int ttl,
|
||||
struct sockaddr_storage *addr)
|
||||
{
|
||||
int ret = -1;
|
||||
int l = (loop == FALSE) ? 0 : 1;
|
||||
|
||||
switch (addr->ss_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
struct ip_mreq mreq4;
|
||||
|
||||
mreq4.imr_multiaddr.s_addr =
|
||||
((struct sockaddr_in *) addr)->sin_addr.s_addr;
|
||||
mreq4.imr_interface.s_addr = INADDR_ANY;
|
||||
|
||||
if ((ret =
|
||||
setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &l,
|
||||
sizeof (l))) < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret =
|
||||
setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
|
||||
sizeof (ttl))) < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret =
|
||||
setsockopt (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
(const void *) &mreq4, sizeof (mreq4))) < 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
memcpy (&mreq6.ipv6mr_multiaddr,
|
||||
&(((struct sockaddr_in6 *) addr)->sin6_addr),
|
||||
sizeof (struct in6_addr));
|
||||
mreq6.ipv6mr_interface = 0;
|
||||
|
||||
if ((ret =
|
||||
setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &l,
|
||||
sizeof (l))) < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret =
|
||||
setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl,
|
||||
sizeof (ttl))) < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret =
|
||||
setsockopt (sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
|
||||
(const void *) &mreq6, sizeof (mreq6))) < 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
gst_udp_leave_group (int sockfd, struct sockaddr_storage *addr)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
switch (addr->ss_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
struct ip_mreq mreq4;
|
||||
|
||||
mreq4.imr_multiaddr.s_addr =
|
||||
((struct sockaddr_in *) addr)->sin_addr.s_addr;
|
||||
mreq4.imr_interface.s_addr = INADDR_ANY;
|
||||
|
||||
if ((ret =
|
||||
setsockopt (sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
||||
(const void *) &mreq4, sizeof (mreq4))) < 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
memcpy (&mreq6.ipv6mr_multiaddr,
|
||||
&(((struct sockaddr_in6 *) addr)->sin6_addr),
|
||||
sizeof (struct in6_addr));
|
||||
mreq6.ipv6mr_interface = 0;
|
||||
|
||||
if ((ret =
|
||||
setsockopt (sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
|
||||
(const void *) &mreq6, sizeof (mreq6))) < 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
gst_udp_is_multicast (struct sockaddr_storage *addr)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
switch (addr->ss_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
|
||||
|
||||
ret = IN_MULTICAST (ntohl (addr4->sin_addr.s_addr));
|
||||
}
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
|
||||
|
||||
ret = IN6_IS_ADDR_MULTICAST (&addr6->sin6_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#define IOCTL_SOCKET ioctlsocket
|
||||
#define CLOSE_SOCKET(sock) closesocket(sock)
|
||||
#define setsockopt(sock,l,opt,val,len) setsockopt(sock,l,opt,(char *)(val),len)
|
||||
#define inet_aton(c,addr) gst_udp_net_utils_win32_inet_aton ((c),(addr))
|
||||
#define WSA_STARTUP(obj) gst_udp_net_utils_win32_wsa_startup(GST_OBJECT(obj))
|
||||
#define WSA_CLEANUP(obj) WSACleanup ()
|
||||
|
||||
|
@ -68,10 +67,15 @@
|
|||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
int gst_udp_net_utils_win32_inet_aton (const char *c, struct in_addr * addr);
|
||||
gboolean gst_udp_net_utils_win32_wsa_startup (GstObject * obj);
|
||||
|
||||
#endif
|
||||
|
||||
int gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr);
|
||||
int gst_udp_is_multicast (struct sockaddr_storage *addr);
|
||||
|
||||
int gst_udp_join_group (int sockfd, gboolean loop, int ttl, struct sockaddr_storage *addr);
|
||||
int gst_udp_leave_group (int sockfd, struct sockaddr_storage *addr);
|
||||
|
||||
#endif /* __GST_UDP_NET_UTILS_H__*/
|
||||
|
||||
|
|
|
@ -349,7 +349,7 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf)
|
|||
{
|
||||
GstUDPSrc *udpsrc;
|
||||
GstNetBuffer *outbuf;
|
||||
struct sockaddr_in tmpaddr;
|
||||
struct sockaddr_storage tmpaddr;
|
||||
socklen_t len;
|
||||
guint8 *pktdata;
|
||||
gint pktsize;
|
||||
|
@ -468,8 +468,28 @@ no_select:
|
|||
GST_BUFFER_DATA (outbuf) = pktdata;
|
||||
GST_BUFFER_SIZE (outbuf) = ret;
|
||||
|
||||
gst_netaddress_set_ip4_address (&outbuf->from, tmpaddr.sin_addr.s_addr,
|
||||
tmpaddr.sin_port);
|
||||
switch (tmpaddr.ss_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
gst_netaddress_set_ip4_address (&outbuf->from,
|
||||
((struct sockaddr_in *) &tmpaddr)->sin_addr.s_addr,
|
||||
((struct sockaddr_in *) &tmpaddr)->sin_port);
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
{
|
||||
guint8 ip6[16];
|
||||
|
||||
memcpy (ip6, &((struct sockaddr_in6 *) &tmpaddr)->sin6_addr,
|
||||
sizeof (ip6));
|
||||
gst_netaddress_set_ip6_address (&outbuf->from, ip6,
|
||||
((struct sockaddr_in *) &tmpaddr)->sin_port);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
goto receive_error;
|
||||
}
|
||||
|
||||
gst_buffer_set_caps (GST_BUFFER_CAST (outbuf), udpsrc->caps);
|
||||
|
||||
|
@ -681,7 +701,7 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
|
|||
{
|
||||
guint bc_val;
|
||||
gint reuse;
|
||||
struct sockaddr_in my_addr;
|
||||
struct sockaddr_storage my_addr;
|
||||
guint len;
|
||||
int port;
|
||||
GstUDPSrc *src;
|
||||
|
@ -690,12 +710,12 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
|
|||
|
||||
src = GST_UDPSRC (bsrc);
|
||||
|
||||
if (!inet_aton (src->multi_group, &(src->multi_addr.imr_multiaddr)))
|
||||
src->multi_addr.imr_multiaddr.s_addr = 0;
|
||||
|
||||
if (src->sockfd == -1) {
|
||||
/* need to allocate a socket */
|
||||
if ((ret = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
if ((ret =
|
||||
gst_udp_get_addr (src->multi_group, src->port, &src->myaddr)) < 0)
|
||||
goto getaddrinfo_error;
|
||||
if ((ret = socket (src->myaddr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
goto no_socket;
|
||||
|
||||
src->sock.fd = ret;
|
||||
|
@ -707,15 +727,6 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
|
|||
sizeof (reuse))) < 0)
|
||||
goto setsockopt_error;
|
||||
|
||||
memset (&src->myaddr, 0, sizeof (src->myaddr));
|
||||
src->myaddr.sin_family = AF_INET; /* host byte order */
|
||||
src->myaddr.sin_port = g_htons (src->port); /* short, network byte order */
|
||||
|
||||
if (src->multi_addr.imr_multiaddr.s_addr)
|
||||
src->myaddr.sin_addr.s_addr = src->multi_addr.imr_multiaddr.s_addr;
|
||||
else
|
||||
src->myaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
GST_DEBUG_OBJECT (src, "binding on port %d", src->port);
|
||||
if ((ret = bind (src->sock.fd, (struct sockaddr *) &src->myaddr,
|
||||
sizeof (src->myaddr))) < 0)
|
||||
|
@ -726,11 +737,9 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
|
|||
src->externalfd = TRUE;
|
||||
}
|
||||
|
||||
if (src->multi_addr.imr_multiaddr.s_addr) {
|
||||
src->multi_addr.imr_interface.s_addr = INADDR_ANY;
|
||||
if ((ret =
|
||||
setsockopt (src->sock.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&src->multi_addr, sizeof (src->multi_addr))) < 0)
|
||||
if (gst_udp_is_multicast (&src->myaddr)) {
|
||||
ret = gst_udp_join_group (src->sock.fd, TRUE, src->ttl, &src->myaddr);
|
||||
if (ret < 0)
|
||||
goto membership;
|
||||
}
|
||||
|
||||
|
@ -769,7 +778,9 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
|
|||
sizeof (bc_val))) < 0)
|
||||
goto no_broadcast;
|
||||
|
||||
port = g_ntohs (my_addr.sin_port);
|
||||
/* NOTE: sockaddr_in.sin_port works for ipv4 and ipv6 because sin_port
|
||||
* follows ss_family on both */
|
||||
port = ntohs (((struct sockaddr_in *) &my_addr)->sin_port);
|
||||
GST_DEBUG_OBJECT (src, "bound, on port %d", port);
|
||||
if (port != src->port) {
|
||||
src->port = port;
|
||||
|
@ -777,7 +788,7 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
|
|||
g_object_notify (G_OBJECT (src), "port");
|
||||
}
|
||||
|
||||
src->myaddr.sin_port = g_htons (src->port + 1);
|
||||
((struct sockaddr_in *) &src->myaddr)->sin_port = htons (src->port + 1);
|
||||
|
||||
if ((src->fdset = gst_poll_new (TRUE)) == NULL)
|
||||
goto no_fdset;
|
||||
|
@ -788,6 +799,12 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
|
|||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
getaddrinfo_error:
|
||||
{
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
|
||||
("getaddrinfo failed %d: %s (%d)", ret, g_strerror (errno), errno));
|
||||
return FALSE;
|
||||
}
|
||||
no_socket:
|
||||
{
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
||||
|
|
|
@ -68,8 +68,7 @@ struct _GstUDPSrc {
|
|||
GstPoll *fdset;
|
||||
gboolean externalfd;
|
||||
|
||||
struct sockaddr_in myaddr;
|
||||
struct ip_mreq multi_addr;
|
||||
struct sockaddr_storage myaddr;
|
||||
};
|
||||
|
||||
struct _GstUDPSrcClass {
|
||||
|
|
Loading…
Reference in a new issue