]> git.sesse.net Git - vlc/blobdiff - src/stream_output/sap.c
Fail when trying to advertise a stream with an out-of-scope address
[vlc] / src / stream_output / sap.c
index c3ea39226c309a4d156e12cda4ac31496d62598b..7a354f1b540dc5511946e6e2acca0d2565135294 100644 (file)
@@ -19,7 +19,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
 #include <vlc/sout.h>
 
 #include "network.h"
-#if defined( WIN32 ) || defined( UNDER_CE )
-#   if defined(UNDER_CE) && defined(sockaddr_storage)
-#       undef sockaddr_storage
-#   endif
-#   include <winsock2.h>
-#   include <ws2tcpip.h>
-#else
-#   include <netdb.h>
-#   include <arpa/inet.h>
-#endif
 #include "charset.h"
 
 /* SAP is always on that port */
@@ -67,7 +57,6 @@ struct sap_address_t
 {
     char *psz_address;
     char psz_machine[NI_MAXNUMERICHOST];
-    int i_port;
     int i_rfd; /* Read socket */
     int i_wfd; /* Write socket */
 
@@ -98,7 +87,6 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
 
 static int announce_SAPAnnounceDel( sap_handler_t *p_sap,
                              session_descriptor_t *p_session );
-static char *convert_to_utf8( struct sap_handler_t *p_this, char *psz_local );
 
 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
 
@@ -112,7 +100,6 @@ static char *convert_to_utf8( struct sap_handler_t *p_this, char *psz_local );
 sap_handler_t *announce_SAPHandlerCreate( announce_handler_t *p_announce )
 {
     sap_handler_t *p_sap;
-    char *psz_charset;
 
     p_sap = vlc_object_create( p_announce, sizeof( sap_handler_t ) );
 
@@ -124,12 +111,6 @@ sap_handler_t *announce_SAPHandlerCreate( announce_handler_t *p_announce )
 
     vlc_mutex_init( p_sap, &p_sap->object_lock );
 
-    vlc_current_charset( &psz_charset );
-    p_sap->iconvHandle = vlc_iconv_open( "UTF-8", psz_charset );
-    free( psz_charset );
-    if( p_sap->iconvHandle == (vlc_iconv_t)(-1) )
-        msg_Warn( p_sap, "Unable to do requested conversion" );
-
     p_sap->pf_add = announce_SAPAnnounceAdd;
     p_sap->pf_del = announce_SAPAnnounceDel;
 
@@ -188,9 +169,6 @@ void announce_SAPHandlerDestroy( sap_handler_t *p_sap )
         FREE( p_address );
     }
 
-    if( p_sap->iconvHandle != (vlc_iconv_t)(-1) )
-        vlc_iconv_close( p_sap->iconvHandle );
-
     /* Free the structure */
     vlc_object_destroy( p_sap );
 }
@@ -293,7 +271,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
         vlc_mutex_unlock( &p_sap->object_lock );
         vlc_freeaddrinfo( res );
         msg_Err( p_sap, "Unsupported address family of size %d > %u",
-                 res->ai_addrlen, sizeof( addr ) );
+                 res->ai_addrlen, (unsigned) sizeof( addr ) );
         return VLC_EGENERIC;
     }
 
@@ -339,11 +317,25 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
             if ((ipv4 & 0xfffc0000) == 0xefc00000)
                 ipv4 =  0xefc3ffff;
             else
+            if ((ipv4 & 0xff000000) == 0xef000000)
+                ipv4 = 0;
+            else
             /* other addresses => 224.2.127.254 */
                 ipv4 = 0xe0027ffe;
+
+            if( ipv4 == 0 )
+            {
+                msg_Err( p_sap, "Out-of-scope multicast address "
+                        "not supported by SAP: %s", p_session->psz_uri );
+                vlc_mutex_unlock( &p_sap->object_lock );
+                vlc_freeaddrinfo( res );
+                return VLC_EGENERIC;
+            }
+
+            ((struct sockaddr_in *)&addr)->sin_addr.s_addr = htonl( ipv4 );
             break;
         }
-        
+
         default:
             vlc_mutex_unlock( &p_sap->object_lock );
             vlc_freeaddrinfo( res );
@@ -389,16 +381,14 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
             return VLC_ENOMEM;
         }
         p_address->psz_address = strdup( psz_addr );
-        p_address->i_port  =  9875;
-        p_address->i_wfd = net_OpenUDP( p_sap, "", 0, psz_addr,
-                                        p_address->i_port );
+        p_address->i_wfd = net_ConnectUDP( p_sap, psz_addr, SAP_PORT, 255 );
         if( p_address->i_wfd != -1 )
         {
             char *ptr;
 
             net_StopRecv( p_address->i_wfd );
-            net_GetSockAddress( p_sap, p_address->i_wfd,
-                                p_address->psz_machine, NULL );
+            net_GetSockAddress( p_address->i_wfd, p_address->psz_machine,
+                                NULL );
 
             /* removes scope if present */
             ptr = strchr( p_address->psz_machine, '%' );
@@ -408,8 +398,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
 
         if( p_sap->b_control == VLC_TRUE )
         {
-            p_address->i_rfd = net_OpenUDP( p_sap, psz_addr,
-                                            p_address->i_port, "", 0 );
+            p_address->i_rfd = net_OpenUDP( p_sap, psz_addr, SAP_PORT, "", 0 );
             if( p_address->i_rfd != -1 )
                 net_StopSend( p_address->i_rfd );
             p_address->i_buff = 0;
@@ -458,8 +447,20 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
     psz_head[2] = (i_hash & 0xFF00) >> 8; /* Msg id hash */
     psz_head[3] = (i_hash & 0xFF);        /* Msg id hash 2 */
 
-    inet_pton( b_ipv6 ? AF_INET6 : AF_INET, /* can't fail */
-               p_sap_session->p_address->psz_machine, psz_head + 4 );
+#if defined (HAVE_INET_PTON) || defined (WIN32)
+    if( b_ipv6 )
+    {
+        inet_pton( AF_INET6, /* can't fail */
+                   p_sap_session->p_address->psz_machine,
+                   psz_head + 4 );
+    }
+    else
+#endif
+    {
+        inet_pton( AF_INET, /* can't fail */
+                   p_sap_session->p_address->psz_machine,
+                   psz_head + 4 );
+    }
 
     memcpy( psz_head + (b_ipv6 ? 20 : 8), "application/sdp", 15 );
 
@@ -536,7 +537,7 @@ static int announce_SAPAnnounceDel( sap_handler_t *p_sap,
      * TODO: - address refcount
              - send a SAP deletion packet */
 
-    msg_Dbg( p_sap,"%i announces remaining", p_sap->i_sessions );
+    msg_Dbg( p_sap,"%i announcements remaining", p_sap->i_sessions );
 
     vlc_mutex_unlock( &p_sap->object_lock );
 
@@ -567,8 +568,8 @@ static int announce_SendSAPAnnounce( sap_handler_t *p_sap,
         if( i_ret != (int)p_session->i_length )
         {
             msg_Warn( p_sap, "SAP send failed on address %s (%i %i)",
-                   p_session->p_address->psz_address,
-                   i_ret, p_session->i_length );
+                      p_session->p_address->psz_address,
+                      i_ret, p_session->i_length );
         }
         p_session->i_last = p_session->i_next;
         p_session->i_next = p_session->i_last
@@ -591,13 +592,8 @@ static char *SDPGenerate( sap_handler_t *p_sap,
          *psz_sdp;
     char ipv;
 
-    psz_group = convert_to_utf8( p_sap, p_session->psz_group );
-    psz_name = convert_to_utf8( p_sap, p_session->psz_name );
-    if( psz_name == NULL )
-    {
-        FREE( psz_group );
-        return NULL;
-    }
+    psz_group = p_session->psz_group;
+    psz_name = p_session->psz_name;
 
     /* FIXME: really check that psz_uri is a real IP address
      * FIXME: make a common function to obtain a canonical IP address */
@@ -626,28 +622,21 @@ static char *SDPGenerate( sap_handler_t *p_sap,
                             "s=%s\r\n"
                             "t=0 0\r\n"
                             "c=IN IP%c %s/%d\r\n"
-                            "m=video %d udp %d\r\n"
+                            "m=video %d %s %d\r\n"
                             "a=tool:"PACKAGE_STRING"\r\n"
-                            "a=type:broadcast\r\n",
+                            "a=type:broadcast\r\n"
+                            "%s%s%s",
                             i_sdp_id, i_sdp_version,
                             ipv, p_addr->psz_machine,
-                            psz_name, ipv,
-                            psz_uri, p_session->i_ttl,
-                            p_session->i_port, p_session->i_payload ) == -1 )
-    {
-        free( psz_name );
-        FREE( psz_group );
+                            psz_name, ipv, psz_uri,
+                            /* FIXME: 1 is IPv4 default TTL, not that of IPv6 */
+                            p_session->i_ttl ?: (config_GetInt( p_sap, "ttl" ) ?: 1),
+                            p_session->i_port, 
+                            p_session->b_rtp ? "RTP/AVP" : "udp",
+                            p_session->i_payload,
+                            psz_group ? "a=x-plgroup:" : "",
+                            psz_group ? psz_group : "", psz_group ? "\r\n" : "" ) == -1 )
         return NULL;
-    }
-    
-    free( psz_name );
-
-    if( psz_group )
-    {
-        /* FIXME: this is illegal use of sprintf */
-        sprintf( psz_sdp, "%sa=x-plgroup:%s\r\n", psz_sdp, psz_group );
-        free( psz_group );
-    }
 
     msg_Dbg( p_sap, "Generated SDP (%i bytes):\n%s", strlen(psz_sdp),
              psz_sdp );
@@ -699,9 +688,7 @@ static int CalculateRate( sap_handler_t *p_sap, sap_address_t *p_address )
     }
 #ifdef EXTRA_DEBUG
     msg_Dbg( p_sap,"%s:%i : Rate=%i, Interval = %i s",
-                    p_address->psz_address,p_address->i_port,
-                    i_rate,
-                    p_address->i_interval );
+             p_address->psz_address,SAP_PORT, i_rate, p_address->i_interval );
 #endif
 
     p_address->b_ready = VLC_TRUE;
@@ -711,34 +698,3 @@ static int CalculateRate( sap_handler_t *p_sap, sap_address_t *p_address )
 
     return VLC_SUCCESS;
 }
-
-
-static char *convert_to_utf8( struct sap_handler_t *p_this, char *psz_local )
-{
-    char *psz_unicode, *psz_in, *psz_out;
-    size_t ret, i_in, i_out;
-
-    if( psz_local == NULL )
-        return NULL;
-    if ( p_this->iconvHandle == (vlc_iconv_t)(-1) )
-        return strdup( psz_local );
-
-    psz_in = psz_local;
-    i_in = strlen( psz_local );
-
-    i_out = 6 * i_in;
-    psz_unicode = malloc( i_out + 1 );
-    if( psz_unicode == NULL )
-        return strdup( psz_local );
-    psz_out = psz_unicode;
-
-    ret = vlc_iconv( p_this->iconvHandle,
-                     &psz_in, &i_in, &psz_out, &i_out);
-    if( ret == (size_t)(-1) || i_in )
-    {
-        msg_Warn( p_this, "Failed to convert \"%s\" to UTF-8", psz_local );
-        return strdup( psz_local );
-    }
-    *psz_out = '\0';
-    return psz_unicode;
-}