diff --git a/include/vlc_network.h b/include/vlc_network.h
index 0a51a12..a8895a8 100644
--- a/include/vlc_network.h
+++ b/include/vlc_network.h
@@ -142,6 +142,8 @@ struct virtual_socket_t
     int (*pf_send) ( void *, const void *, int );
 };
 
+VLC_EXPORT( ssize_t, net_Poll, ( vlc_object_t *p_this, int fd, size_t i_timeout ) );
+#define net_Poll(a,b,c) net_Poll(VLC_OBJECT(a),b,c)
 VLC_EXPORT( ssize_t, net_Read, ( vlc_object_t *p_this, int fd, const v_socket_t *, void *p_data, size_t i_data, bool b_retry ) );
 #define net_Read(a,b,c,d,e,f) net_Read(VLC_OBJECT(a),b,c,d,e,f)
 VLC_EXPORT( ssize_t, net_Write, ( vlc_object_t *p_this, int fd, const v_socket_t *, const void *p_data, size_t i_data ) );
diff --git a/modules/access/http.c b/modules/access/http.c
index 90e465b..65b9806 100644
--- a/modules/access/http.c
+++ b/modules/access/http.c
@@ -92,6 +92,11 @@ static void Close( vlc_object_t * );
     "Automatically try to reconnect to the stream in case of a sudden " \
     "disconnect." )
 
+#define TIMEOUT_TEXT N_("Network timeout")
+#define TIMEOUT_LONGTEXT N_( \
+    "Try to read for the given number of ms. If there's no data then fail. " \
+    "0 means to wait forever." )
+
 #define CONTINUOUS_TEXT N_("Continuous stream")
 #define CONTINUOUS_LONGTEXT N_("Read a file that is " \
     "being constantly updated (for example, a JPG file on a server). " \
@@ -128,6 +133,8 @@ vlc_module_begin ()
         change_safe()
     add_bool( "http-reconnect", false, NULL, RECONNECT_TEXT,
               RECONNECT_LONGTEXT, true )
+    add_integer( "http-timeout", 0, NULL, TIMEOUT_TEXT,
+              TIMEOUT_LONGTEXT, true )
     add_bool( "http-continuous", false, NULL, CONTINUOUS_TEXT,
               CONTINUOUS_LONGTEXT, true )
         change_safe()
@@ -201,6 +208,7 @@ struct access_sys_t
 
     bool b_seekable;
     bool b_reconnect;
+    int i_timeout;
     bool b_continuous;
     bool b_pace_control;
     bool b_persist;
@@ -501,6 +509,14 @@ static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
     p_sys->b_reconnect = var_InheritBool( p_access, "http-reconnect" );
     p_sys->b_continuous = var_InheritBool( p_access, "http-continuous" );
 
+    p_sys->i_timeout = var_CreateGetInteger( p_access, "http-timeout" );
+    if( p_sys->i_timeout > 0 && p_sys->i_timeout < 500 ) {
+        /* at least 500ms */
+        msg_Warn( p_access, "given timeout too low - setting 500ms" );
+        p_sys->i_timeout = 500;
+        var_SetInteger( p_access, "http-timeout", p_sys->i_timeout );
+    }
+
 connect:
     /* Connect */
     switch( Connect( p_access, 0 ) )
@@ -834,7 +850,16 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
             i_len = i_next;
     }
 
-    i_read = net_Read( p_access, p_sys->fd, p_sys->p_vs, p_buffer, i_len, false );
+    /* check for data */
+    if( p_sys->i_timeout <= 0 || ( i_read = net_Poll( p_access, p_sys->fd, p_sys->i_timeout ) ) > 0 )
+    {
+        /* timeout is disabled or there's data available */
+        i_read = net_Read( p_access, p_sys->fd, p_sys->p_vs, p_buffer, i_len, false );
+    }
+    else
+    {
+        msg_Dbg( p_access, "read timed out");
+    }
 
     if( i_read > 0 )
     {
@@ -910,10 +935,15 @@ static int ReadICYMeta( access_t *p_access )
     uint8_t buffer;
     char *p, *psz_meta;
     int i_read;
+    bool b_success;
 
     /* Read meta data length */
-    i_read = net_Read( p_access, p_sys->fd, p_sys->p_vs, &buffer, 1,
-                       true );
+    if( p_sys->i_timeout <= 0 || ( i_read = net_Poll( p_access, p_sys->fd, p_sys->i_timeout ) ) > 0 )
+    {
+        i_read = net_Read( p_access, p_sys->fd, p_sys->p_vs, &buffer, 1,
+                           true );
+    }
+
     if( i_read <= 0 )
         return VLC_EGENERIC;
     if( buffer == 0 )
@@ -923,9 +953,20 @@ static int ReadICYMeta( access_t *p_access )
     /* msg_Dbg( p_access, "ICY meta size=%u", i_read); */
 
     psz_meta = malloc( i_read + 1 );
-    if( net_Read( p_access, p_sys->fd, p_sys->p_vs,
-                  (uint8_t *)psz_meta, i_read, true ) != i_read )
+
+    b_success = false;
+    if( p_sys->i_timeout <= 0 || net_Poll( p_access, p_sys->fd, p_sys->i_timeout ) > 0 )
+    {
+        if( net_Read( p_access, p_sys->fd, p_sys->p_vs,
+                      (uint8_t *)psz_meta, i_read, true ) == i_read )
+        {
+            b_success = true;
+        }
+    }
+
+    if( !b_success )
     {
+        /* something went wrong */
         free( psz_meta );
         return VLC_EGENERIC;
     }
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 4994225..701882d 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -275,6 +275,7 @@ net_Gets
 net_Listen
 net_ListenClose
 net_OpenDgram
+net_Poll
 net_Printf
 net_Read
 net_SetCSCov
diff --git a/src/network/io.c b/src/network/io.c
index 2defe31..1959036 100644
--- a/src/network/io.c
+++ b/src/network/io.c
@@ -244,6 +244,30 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host,
     return sockv;
 }
 
+#undef net_Poll
+/*****************************************************************************
+ * net_Poll:
+ *****************************************************************************
+ * Polls the socket to see if there's data available. If timeout is set this
+ * function can be used to implement net_Read timeouts (see http access
+ * module).
+ *****************************************************************************/
+ssize_t
+net_Poll (vlc_object_t *restrict p_this, int fd, size_t i_timeout)
+{
+    struct pollfd ufd[2] = {
+        { .fd = fd,                           .events = POLLIN },
+        { .fd = vlc_object_waitpipe (p_this), .events = POLLIN },
+    };
+
+    if (ufd[1].fd == -1)
+        return -1; /* vlc_object_waitpipe() sets errno */
+
+    ufd[0].revents = ufd[1].revents = 0;
+
+    return poll (ufd, sizeof (ufd) / sizeof (ufd[0]), i_timeout);
+}
+
 #undef net_Read
 /*****************************************************************************
  * net_Read:
