]> git.sesse.net Git - vlc/commitdiff
Add net_ListenUDP
authorRémi Denis-Courmont <rem@videolan.org>
Sun, 5 Nov 2006 19:20:52 +0000 (19:20 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Sun, 5 Nov 2006 19:20:52 +0000 (19:20 +0000)
include/network.h
src/network/io.c
src/network/udp.c

index 91676ccad333ba28548e2cc74541a824fe9de257..c45dc8e77715a353dc7c649592f00ef55e49f443 100644 (file)
@@ -83,12 +83,14 @@ struct network_socket_t
 };
 
 /* Portable networking layer communication */
+int net_Socket (vlc_object_t *obj, int family, int socktype, int proto);
+
 #define net_ConnectTCP(a, b, c) __net_ConnectTCP(VLC_OBJECT(a), b, c)
 #define net_OpenTCP(a, b, c) __net_ConnectTCP(VLC_OBJECT(a), b, c)
 VLC_EXPORT( int, __net_ConnectTCP, ( vlc_object_t *p_this, const char *psz_host, int i_port ) );
 
-VLC_EXPORT( int *, net_Listen, (vlc_object_t *p_this, const char *psz_host, int i_port,
-                 int family, int socktype, int protocol) );
+int *net_Listen (vlc_object_t *p_this, const char *psz_host, int i_port,
+                 int family, int socktype, int protocol);
 
 #define net_ListenTCP(a, b, c) __net_ListenTCP(VLC_OBJECT(a), b, c)
 VLC_EXPORT( int *, __net_ListenTCP, ( vlc_object_t *, const char *, int ) );
@@ -99,6 +101,8 @@ VLC_EXPORT( int, __net_Accept, ( vlc_object_t *, int *, mtime_t ) );
 #define net_ConnectUDP(a, b, c, d ) __net_ConnectUDP(VLC_OBJECT(a), b, c, d)
 VLC_EXPORT( int, __net_ConnectUDP, ( vlc_object_t *p_this, const char *psz_host, int i_port, int hlim ) );
 
+int net_ListenUDP1 (vlc_object_t *obj, const char *host, int port);
+
 #define net_OpenUDP(a, b, c, d, e ) __net_OpenUDP(VLC_OBJECT(a), b, c, d, e)
 VLC_EXPORT( int, __net_OpenUDP, ( vlc_object_t *p_this, const char *psz_bind, int i_bind, const char *psz_server, int i_server ) );
 
@@ -106,6 +110,8 @@ VLC_EXPORT( void, net_Close, ( int fd ) );
 VLC_EXPORT( void, net_ListenClose, ( int *fd ) );
 
 VLC_EXPORT( int, net_SetDSCP, ( int fd, uint8_t dscp ) );
+int net_Subscribe (vlc_object_t *obj, int fd, const struct sockaddr *addr,
+                   socklen_t addrlen);
 
 /* Functions to read from or write to the networking layer */
 struct virtual_socket_t
index 9a4248f9453ad0b414d03832e40778ff355e0c17..28812219f65a8fb93512dedf8a938406a443e9e4 100644 (file)
@@ -171,6 +171,15 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host, int i_port,
             }
         }
 
+        if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen))
+        {
+            if (net_Subscribe (p_this, fd, ptr->ai_addr, ptr->ai_addrlen))
+            {
+                net_Close (fd);
+                continue;
+            }
+        }
+
         /* Listen */
         switch (ptr->ai_socktype)
         {
index 61eb2722f2e08c48679fd586ace930c3aa99e3e6..08bcffd33d1d4f17f9d0ff0778ec0041e4ed19db 100644 (file)
@@ -31,6 +31,7 @@
 #include <vlc/vlc.h>
 
 #include <errno.h>
+#include <assert.h>
 
 #ifdef HAVE_SYS_TIME_H
 #    include <sys/time.h>
@@ -189,6 +190,80 @@ static int net_SetMcastOut (vlc_object_t *p_this, int fd, int family,
 }
 
 
+int net_Subscribe (vlc_object_t *obj, int fd, const struct sockaddr *addr,
+                   socklen_t addrlen)
+{
+    switch (addr->sa_family)
+    {
+#ifdef IP_ADD_MEMBERSHIP
+        case AF_INET:
+        {
+            const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
+            if (addrlen < sizeof (*v4))
+                return -1;
+
+            struct ip_mreq imr;
+            memset (&imr, 0, sizeof (imr));
+            memcpy (&imr.imr_multiaddr, &v4->sin_addr, 4);
+
+            /* FIXME: should use a different option for in and out */
+            char *iif = config_GetPsz (obj, "miface-addr");
+            if (iif != NULL)
+            {
+                if ((iif[0] != '\0') &&
+                    (inet_pton (AF_INET, iif, &imr.imr_interface) <= 0))
+                {
+                    msg_Err (obj, "invalid multicast interface address %s",
+                             iif);
+                    free (iif);
+                    return -1;
+                }
+                free (iif);
+            }
+
+            msg_Dbg (obj, "IP_ADD_MEMBERSHIP multicast request");
+
+            if (setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr,
+                            sizeof (imr)))
+            {
+                msg_Err (obj, "cannot join IPv4 multicast group (%s)",
+                         net_strerror (net_errno));
+                return -1;
+            }
+            return 0;
+        }
+#endif
+
+#ifdef IPV6_JOIN_GROUP
+        case AF_INET6:
+        {
+            const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
+            if (addrlen < sizeof (*v6))
+                return -1;
+
+            struct ipv6_mreq imr;
+            memset (&imr, 0, sizeof (imr));
+            imr.ipv6mr_interface = v6->sin6_scope_id;
+            memcpy (&imr.ipv6mr_multiaddr, &v6->sin6_addr, 16);
+
+            if (setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &imr,
+                            sizeof (imr)))
+            {
+                msg_Err (obj, "cannot join IPv6 multicast group (%s)",
+                         net_strerror (net_errno));
+                return -1;
+            }
+
+            return 0;
+        }
+#endif
+    }
+
+    msg_Err (obj, "Multicast not supported");
+    return -1;
+}
+
+
 int net_SetDSCP( int fd, uint8_t dscp )
 {
     struct sockaddr_storage addr;
@@ -326,6 +401,39 @@ int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
     return i_handle;
 }
 
+
+static inline
+int *__net_ListenUDP (vlc_object_t *obj, const char *host, int port)
+{
+    int *fdv = net_Listen (obj, host, port, 0, SOCK_DGRAM, IPPROTO_UDP);
+    if (fdv == NULL)
+        return NULL;
+
+    /* FIXME: handle multicast subscription */
+    return fdv;
+}
+
+
+int net_ListenUDP1 (vlc_object_t *obj, const char *host, int port)
+{
+    int *fdv = __net_ListenUDP (obj, host, port);
+    if (fdv == NULL)
+        return -1;
+
+    for (unsigned i = 1; fdv[i] != -1; i++)
+    {
+        msg_Warn (obj, "A socket has been dropped!");
+        net_Close (fdv[i]);
+    }
+
+    int fd = fdv[0];
+    assert (fd != -1);
+
+    free (fdv);
+    return fd;
+}
+
+
 /*****************************************************************************
  * __net_OpenUDP:
  *****************************************************************************