]> git.sesse.net Git - vlc/blobdiff - plugins/access/http.c
plugins/access/http.c: backported my last commit on request from sam
[vlc] / plugins / access / http.c
index 142ceca50828068c208ba96edba86c84f95be2e7..8408010a90c002b94887c8772fe849e33ee53153 100644 (file)
@@ -2,7 +2,7 @@
  * http.c: HTTP access plug-in
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: http.c,v 1.5 2002/03/19 05:49:30 sam Exp $
+ * $Id: http.c,v 1.10.2.3 2002/07/25 20:22:17 sigmunau Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
 #   include <io.h>
 #endif
 
+#ifdef WIN32
+#   include <winsock2.h>
+#   include <ws2tcpip.h>
+#   ifndef IN_MULTICAST
+#       define IN_MULTICAST(a) IN_CLASSD(a)
+#   endif
+#else
+#   include <sys/socket.h>
+#endif
+
 #include "stream_control.h"
 #include "input_ext-intf.h"
 #include "input_ext-dec.h"
@@ -51,6 +61,7 @@
  *****************************************************************************/
 static void input_getfunctions( function_list_t * );
 static int  HTTPOpen       ( struct input_thread_s * );
+static void HTTPClose      ( struct input_thread_s * );
 static int  HTTPSetProgram ( struct input_thread_s * , pgrm_descriptor_t * );  
 static void HTTPSeek       ( struct input_thread_s *, off_t );
 
@@ -61,7 +72,7 @@ MODULE_CONFIG_START
 MODULE_CONFIG_STOP
  
 MODULE_INIT_START
-    SET_DESCRIPTION( "HTTP access plug-in" )
+    SET_DESCRIPTION( _("HTTP access plug-in") )
     ADD_CAPABILITY( ACCESS, 0 )
     ADD_SHORTCUT( "http" )
     ADD_SHORTCUT( "http4" )
@@ -84,7 +95,7 @@ static void input_getfunctions( function_list_t * p_function_list )
 #define input p_function_list->functions.access
     input.pf_open             = HTTPOpen;
     input.pf_read             = input_FDNetworkRead;
-    input.pf_close            = input_FDClose;
+    input.pf_close            = HTTPClose;
     input.pf_set_program      = HTTPSetProgram;
     input.pf_set_area         = NULL;
     input.pf_seek             = HTTPSeek;
@@ -102,6 +113,7 @@ typedef struct _input_socket_s
     char *              psz_network;
     network_socket_t    socket_desc;
     char                psz_buffer[256];
+    char *              psz_name;
 } _input_socket_t;
 
 /*****************************************************************************
@@ -113,6 +125,8 @@ static int HTTPConnect( input_thread_t * p_input, off_t i_tell )
     struct module_s *   p_network;
     char                psz_buffer[256];
     byte_t *            psz_parser;
+    int                 i_returncode, i;
+    char *              psz_return_alpha;
 
     /* Find an appropriate network module */
     p_network = module_Need( MODULE_CAPABILITY_NETWORK,
@@ -130,44 +144,89 @@ static int HTTPConnect( input_thread_t * p_input, off_t i_tell )
 #   define HTTP_USERAGENT "User-Agent: " COPYRIGHT_MESSAGE "\r\n"
 #   define HTTP_END       "\r\n"
  
-    snprintf( psz_buffer, sizeof(psz_buffer),
-              "%s"
-              "Range: bytes=%lld-\r\n"
-              HTTP_USERAGENT HTTP_END,
-              p_access_data->psz_buffer, i_tell );
+    if ( p_input->stream.b_seekable )
+    {
+         snprintf( psz_buffer, sizeof(psz_buffer),
+                   "%s"
+                   "Range: bytes=%lld-\r\n"
+                   HTTP_USERAGENT HTTP_END,
+                   p_access_data->psz_buffer, i_tell );
+    }
+    else
+    {
+         snprintf( psz_buffer, sizeof(psz_buffer),
+                   "%s"
+                   HTTP_USERAGENT HTTP_END,
+                   p_access_data->psz_buffer, i_tell );
+    }
     psz_buffer[sizeof(psz_buffer) - 1] = '\0';
 
     /* Send GET ... */
-    if( write( p_access_data->_socket.i_handle, psz_buffer,
-               strlen( psz_buffer ) ) == (-1) )
+    if( send( p_access_data->_socket.i_handle, psz_buffer,
+               strlen( psz_buffer ), 0 ) == (-1) )
     {
         intf_ErrMsg( "http error: cannot send request (%s)", strerror(errno) );
-        input_FDClose( p_input );
+        input_FDNetworkClose( p_input );
         return( -1 );
     }
 
     /* Prepare the input thread for reading. */ 
     p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
     /* FIXME: we shouldn't have to do that ! */
-    p_input->pf_read = input_FDRead;
+    p_input->pf_read = input_FDNetworkRead;
 
     while( !input_FillBuffer( p_input ) )
     {
         if( p_input->b_die || p_input->b_error )
         {
-            input_FDClose( p_input );
+            input_FDNetworkClose( p_input );
             return( -1 );
         }
     }
 
     /* Parse HTTP header. */
 #define MAX_LINE 1024
+    /* get the returncode */
+    if( input_Peek( p_input, &psz_parser, MAX_LINE ) <= 0 )
+    {
+        intf_ErrMsg( "not enough data" );
+        input_FDNetworkClose( p_input );
+        return( -1 );
+    }
+
+    if( !strncmp( psz_parser, "HTTP/1.",
+                  strlen("HTTP/1.") ) )
+    {
+        psz_parser += strlen("HTTP 1.") + 2;
+        i_returncode = atoi( psz_parser );
+        intf_WarnMsg( 3, "HTTP server replied: %i", i_returncode );
+        psz_parser += 4;
+        for ( i = 0; psz_parser[i] != '\r' || psz_parser[i+1] != '\n'; i++ )
+        {
+            ;
+        }
+        psz_return_alpha = malloc( i + 1 );
+        memcpy( psz_return_alpha, psz_parser, i );
+        psz_return_alpha[i] = '\0';
+    }
+    else
+    {
+        intf_ErrMsg( "http error: invalid http reply" );
+        return -1;
+    }
+    
+    if ( i_returncode >= 400 ) /* something is wrong */
+    {
+        intf_ErrMsg( "http error: %i %s", i_returncode, psz_return_alpha );
+        return -1;
+    }
+
     for( ; ; ) 
     {
         if( input_Peek( p_input, &psz_parser, MAX_LINE ) <= 0 )
         {
             intf_ErrMsg( "http error: not enough data" );
-            input_FDClose( p_input );
+            input_FDNetworkClose( p_input );
             return( -1 );
         }
 
@@ -182,10 +241,15 @@ static int HTTPConnect( input_thread_t * p_input, off_t i_tell )
                       strlen("Content-Length: ") ) )
         {
             psz_parser += strlen("Content-Length: ");
-            /* FIXME : this won't work for 64-bit lengths */
             vlc_mutex_lock( &p_input->stream.stream_lock );
+#ifdef HAVE_ATOLL
+            p_input->stream.p_selected_area->i_size = atoll( psz_parser )
+                                                        + i_tell;
+#else
+            /* FIXME : this won't work for 64-bit lengths */
             p_input->stream.p_selected_area->i_size = atoi( psz_parser )
                                                         + i_tell;
+#endif
             vlc_mutex_unlock( &p_input->stream.stream_lock );
         }
 
@@ -215,7 +279,8 @@ static int HTTPConnect( input_thread_t * p_input, off_t i_tell )
 static int HTTPOpen( input_thread_t * p_input )
 {
     _input_socket_t *   p_access_data;
-    char *              psz_parser = p_input->psz_name;
+    char *              psz_name = strdup(p_input->psz_name);
+    char *              psz_parser = psz_name;
     char *              psz_server_addr = "";
     char *              psz_server_port = "";
     char *              psz_path = "";
@@ -226,9 +291,11 @@ static int HTTPOpen( input_thread_t * p_input )
     if( p_access_data == NULL )
     {
         intf_ErrMsg( "http error: Out of memory" );
+        free(psz_name);
         return( -1 );
     }
 
+    p_access_data->psz_name = psz_name;
     p_access_data->psz_network = "";
     if( config_GetIntVariable( "ipv4" ) )
     {
@@ -292,6 +359,7 @@ static int HTTPOpen( input_thread_t * p_input )
             intf_ErrMsg( "input error: cannot parse server port near %s",
                          psz_parser );
             free( p_input->p_access_data );
+            free( psz_name );
             return( -1 );
         }
     }
@@ -305,6 +373,7 @@ static int HTTPOpen( input_thread_t * p_input )
     {
         intf_ErrMsg( "input error: no server given" );
         free( p_input->p_access_data );
+        free( psz_name );
         return( -1 );
     }
 
@@ -367,6 +436,7 @@ static int HTTPOpen( input_thread_t * p_input )
         {
             intf_ErrMsg( "input error: http_proxy environment variable is invalid !" );
             free( p_input->p_access_data );
+            free( psz_name );
             return( -1 );
         }
 
@@ -375,7 +445,7 @@ static int HTTPOpen( input_thread_t * p_input )
         p_access_data->socket_desc.i_server_port = i_proxy_port;
 
         snprintf( p_access_data->psz_buffer, sizeof(p_access_data->psz_buffer),
-                  "GET http://%s:%d/%s HTTP/1.1\r\n",
+                  "GET http://%s:%d/%s\r\n HTTP/1.0\r\n",
                   psz_server_addr, i_server_port, psz_path );
     }
     else
@@ -396,14 +466,29 @@ static int HTTPOpen( input_thread_t * p_input )
 
     vlc_mutex_lock( &p_input->stream.stream_lock );
     p_input->stream.b_pace_control = 1;
-    p_input->stream.b_seekable = 0;
+    p_input->stream.b_seekable = 1;
     p_input->stream.p_selected_area->i_tell = 0;
     p_input->stream.p_selected_area->i_size = 0;
     p_input->stream.i_method = INPUT_METHOD_NETWORK;
     vlc_mutex_unlock( &p_input->stream.stream_lock );
     p_input->i_mtu = 0;
  
-    return( HTTPConnect( p_input, 0 ) );
+    if( HTTPConnect( p_input, 0 ) )
+    {
+        char * psz_pos = strstr(p_access_data->psz_buffer, "HTTP/1.1");
+        p_input->stream.b_seekable = 0;
+        psz_pos[7] = '0';
+        return( HTTPConnect( p_input, 0 ) );
+    }
+    return 0;
+}
+
+/*****************************************************************************
+ * HTTPClose: free unused data structures
+ *****************************************************************************/
+static void HTTPClose( input_thread_t * p_input )
+{
+    input_FDNetworkClose( p_input );
 }
 
 /*****************************************************************************