~ubuntu-branches/ubuntu/trusty/opusfile/trusty

« back to all changes in this revision

Viewing changes to src/http.c

  • Committer: Package Import Robot
  • Author(s): Ron Lee
  • Date: 2013-05-13 21:43:40 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20130513214340-9p3jj0irk8afk7kd
Tags: 0.2+20130513-1
* Snapshot release for unstable.
* Fixes the pkg-config file to avoid overlinking.  Closes: #707969
* Split the URL handling into a separate library, so that linking with
  openssl is only an issue for people who do need that functionality.
  The main opusfile library can now be linked with anything again.
  Closes:  #708008

Show diffs side-by-side

added added

removed removed

Lines of Context:
205
205
}
206
206
 
207
207
#if defined(OP_ENABLE_HTTP)
208
 
# include <sys/ioctl.h>
209
 
# include <sys/types.h>
210
 
# include <sys/socket.h>
 
208
# if defined(_WIN32)
 
209
#  include <winsock2.h>
 
210
#  include <ws2tcpip.h>
 
211
#  include <openssl/ssl.h>
 
212
#  include "winerrno.h"
 
213
 
 
214
typedef SOCKET op_sock;
 
215
 
 
216
#  define OP_INVALID_SOCKET (INVALID_SOCKET)
 
217
 
 
218
/*Vista and later support WSAPoll(), but we don't want to rely on that.
 
219
  Instead we re-implement it badly using select().
 
220
  Unfortunately, they define a conflicting struct pollfd, so we only define our
 
221
   own if it looks like that one has not already been defined.*/
 
222
#  if !defined(POLLIN)
 
223
/*Equivalent to POLLIN.*/
 
224
#   define POLLRDNORM (0x0100)
 
225
/*Priority band data can be read.*/
 
226
#   define POLLRDBAND (0x0200)
 
227
/*There is data to read.*/
 
228
#   define POLLIN     (POLLRDNORM|POLLRDBAND)
 
229
/* There is urgent data to read.*/
 
230
#   define POLLPRI    (0x0400)
 
231
/*Equivalent to POLLOUT.*/
 
232
#   define POLLWRNORM (0x0010)
 
233
/*Writing now will not block.*/
 
234
#   define POLLOUT    (POLLWRNORM)
 
235
/*Priority data may be written.*/
 
236
#   define POLLWRBAND (0x0020)
 
237
/*Error condition (output only).*/
 
238
#   define POLLERR    (0x0001)
 
239
/*Hang up (output only).*/
 
240
#   define POLLHUP    (0x0002)
 
241
/*Invalid request: fd not open (output only).*/
 
242
#   define POLLNVAL   (0x0004)
 
243
 
 
244
struct pollfd{
 
245
  /*File descriptor.*/
 
246
  op_sock fd;
 
247
  /*Requested events.*/
 
248
  short   events;
 
249
  /*Returned events.*/
 
250
  short   revents;
 
251
};
 
252
#  endif
 
253
 
 
254
/*But Winsock never defines nfds_t (it's simply hard-coded to ULONG).*/
 
255
typedef unsigned long nfds_t;
 
256
 
 
257
/*The usage of FD_SET() below is O(N^2).
 
258
  This is okay because select() is limited to 64 sockets in Winsock, anyway.
 
259
  In practice, we only ever call it with one or two sockets.*/
 
260
static int op_poll_win32(struct pollfd *_fds,nfds_t _nfds,int _timeout){
 
261
  struct timeval tv;
 
262
  fd_set         ifds;
 
263
  fd_set         ofds;
 
264
  fd_set         efds;
 
265
  nfds_t         i;
 
266
  int            ret;
 
267
  FD_ZERO(&ifds);
 
268
  FD_ZERO(&ofds);
 
269
  FD_ZERO(&efds);
 
270
  for(i=0;i<_nfds;i++){
 
271
    _fds[i].revents=0;
 
272
    if(_fds[i].events&POLLIN)FD_SET(_fds[i].fd,&ifds);
 
273
    if(_fds[i].events&POLLOUT)FD_SET(_fds[i].fd,&ofds);
 
274
    FD_SET(_fds[i].fd,&efds);
 
275
  }
 
276
  if(_timeout>=0){
 
277
    tv.tv_sec=_timeout/1000;
 
278
    tv.tv_usec=(_timeout%1000)*1000;
 
279
  }
 
280
  ret=select(-1,&ifds,&ofds,&efds,_timeout<0?NULL:&tv);
 
281
  if(ret>0){
 
282
    for(i=0;i<_nfds;i++){
 
283
      if(FD_ISSET(_fds[i].fd,&ifds))_fds[i].revents|=POLLIN;
 
284
      if(FD_ISSET(_fds[i].fd,&ofds))_fds[i].revents|=POLLOUT;
 
285
      /*This isn't correct: there are several different things that might have
 
286
         happened to a fd in efds, but I don't know a good way to distinguish
 
287
         them without more context from the caller.
 
288
        It's okay, because we don't actually check any of these bits, we just
 
289
         need _some_ bit set.*/
 
290
      if(FD_ISSET(_fds[i].fd,&efds))_fds[i].revents|=POLLHUP;
 
291
    }
 
292
  }
 
293
  return ret;
 
294
}
 
295
 
 
296
/*We define op_errno() to make it clear that it's not an l-value like normal
 
297
   errno is.*/
 
298
#  define op_errno() (WSAGetLastError()?WSAGetLastError()-WSABASEERR:0)
 
299
#  define op_reset_errno() (WSASetLastError(0))
 
300
 
 
301
/*The remaining functions don't get an op_ prefix even though they only
 
302
   operate on sockets, because we don't use non-socket I/O here, and this
 
303
   minimizes the changes needed to deal with Winsock.*/
 
304
#  define close(_fd) closesocket(_fd)
 
305
/*This relies on sizeof(u_long)==sizeof(int), which is always true on both
 
306
   Win32 and Win64.*/
 
307
#  define ioctl(_fd,_req,_arg) ioctlsocket(_fd,_req,(u_long *)(_arg))
 
308
#  define getsockopt(_fd,_level,_name,_val,_len) \
 
309
 getsockopt(_fd,_level,_name,(char *)(_val),_len)
 
310
#  define setsockopt(_fd,_level,_name,_val,_len) \
 
311
 setsockopt(_fd,_level,_name,(const char *)(_val),_len)
 
312
#  define poll(_fds,_nfds,_timeout) op_poll_win32(_fds,_nfds,_timeout)
 
313
 
 
314
#  if defined(_MSC_VER)
 
315
typedef ptrdiff_t ssize_t;
 
316
#  endif
 
317
 
 
318
/*Load certificates from the built-in certificate store.*/
 
319
int SSL_CTX_set_default_verify_paths_win32(SSL_CTX *_ssl_ctx);
 
320
#  define SSL_CTX_set_default_verify_paths \
 
321
 SSL_CTX_set_default_verify_paths_win32
 
322
 
 
323
# else
 
324
/*Normal Berkeley sockets.*/
 
325
#  include <sys/ioctl.h>
 
326
#  include <sys/types.h>
 
327
#  include <sys/socket.h>
 
328
#  include <arpa/inet.h>
 
329
#  include <netinet/in.h>
 
330
#  include <netinet/tcp.h>
 
331
#  include <fcntl.h>
 
332
#  include <netdb.h>
 
333
#  include <poll.h>
 
334
#  include <unistd.h>
 
335
#  include <openssl/ssl.h>
 
336
 
 
337
typedef int op_sock;
 
338
 
 
339
#  define OP_INVALID_SOCKET (-1)
 
340
 
 
341
#  define op_errno() (errno)
 
342
#  define op_reset_errno() (errno=0)
 
343
 
 
344
# endif
211
345
# include <sys/timeb.h>
212
 
# include <arpa/inet.h>
213
 
# include <netinet/in.h>
214
 
# include <netinet/tcp.h>
215
 
# include <fcntl.h>
216
 
# include <netdb.h>
217
 
# include <poll.h>
218
 
# include <unistd.h>
219
 
# include <openssl/ssl.h>
220
346
# include <openssl/x509v3.h>
221
347
 
222
348
/*The maximum number of simultaneous connections.
581
707
  char             service[6];
582
708
  memset(&hints,0,sizeof(hints));
583
709
  hints.ai_socktype=SOCK_STREAM;
 
710
#if !defined(_WIN32)
584
711
  hints.ai_flags=AI_NUMERICSERV;
 
712
#endif
585
713
  OP_ASSERT(_port<=65535U);
586
714
  sprintf(service,"%u",_port);
587
715
  if(OP_LIKELY(!getaddrinfo(_host,service,&hints,&addrs)))return addrs;
588
716
  return NULL;
589
717
}
590
718
 
591
 
static int op_sock_set_nonblocking(int _fd,int _nonblocking){
 
719
static int op_sock_set_nonblocking(op_sock _fd,int _nonblocking){
 
720
#if !defined(_WIN32)
592
721
  int flags;
593
722
  flags=fcntl(_fd,F_GETFL);
594
723
  if(OP_UNLIKELY(flags<0))return flags;
595
724
  if(_nonblocking)flags|=O_NONBLOCK;
596
725
  else flags&=~O_NONBLOCK;
597
726
  return fcntl(_fd,F_SETFL,flags);
 
727
#else
 
728
  return ioctl(_fd,FIONBIO,&_nonblocking);
 
729
#endif
598
730
}
599
731
 
600
732
/*Disable/enable write coalescing if we can.
601
733
  We always send whole requests at once and always parse the response headers
602
734
   before sending another one, so normally write coalescing just causes added
603
735
   delay.*/
604
 
static void op_sock_set_tcp_nodelay(int _fd,int _nodelay){
 
736
static void op_sock_set_tcp_nodelay(op_sock _fd,int _nodelay){
605
737
# if defined(TCP_NODELAY)&&(defined(IPPROTO_TCP)||defined(SOL_TCP))
606
738
#  if defined(IPPROTO_TCP)
607
739
#   define OP_SO_LEVEL IPPROTO_TCP
615
747
# endif
616
748
}
617
749
 
 
750
#if defined(_WIN32)
 
751
static void op_init_winsock(){
 
752
  static LONG    count;
 
753
  static WSADATA wsadata;
 
754
  if(InterlockedIncrement(&count)==1)WSAStartup(0x0202,&wsadata);
 
755
}
 
756
#endif
 
757
 
618
758
/*A single physical connection to an HTTP server.
619
759
  We may have several of these open at once.*/
620
760
struct OpusHTTPConn{
640
780
  /*The estimated throughput of this connection, in bytes/s.*/
641
781
  opus_int64    read_rate;
642
782
  /*The socket we're reading from.*/
643
 
  int           fd;
 
783
  op_sock       fd;
644
784
  /*The number of remaining requests we are allowed on this connection.*/
645
785
  int           nrequests_left;
646
786
  /*The chunk size to use for pipelining requests.*/
651
791
  _conn->next_pos=-1;
652
792
  _conn->ssl_conn=NULL;
653
793
  _conn->next=NULL;
654
 
  _conn->fd=-1;
 
794
  _conn->fd=OP_INVALID_SOCKET;
655
795
}
656
796
 
657
797
static void op_http_conn_clear(OpusHTTPConn *_conn){
658
798
  if(_conn->ssl_conn!=NULL)SSL_free(_conn->ssl_conn);
659
799
  /*SSL frees the BIO for us.*/
660
 
  if(_conn->fd>=0)close(_conn->fd);
 
800
  if(_conn->fd!=OP_INVALID_SOCKET)close(_conn->fd);
661
801
}
662
802
 
663
803
/*The global stream state.*/
713
853
 
714
854
static void op_http_stream_init(OpusHTTPStream *_stream){
715
855
  OpusHTTPConn **pnext;
716
 
  int ci;
 
856
  int            ci;
717
857
  pnext=&_stream->free_head;
718
858
  for(ci=0;ci<OP_NCONNS_MAX;ci++){
719
859
    op_http_conn_init(_stream->conns+ci);
756
896
  op_http_conn_clear(_conn);
757
897
  _conn->next_pos=-1;
758
898
  _conn->ssl_conn=NULL;
759
 
  _conn->fd=-1;
 
899
  _conn->fd=OP_INVALID_SOCKET;
760
900
  OP_ASSERT(*_pnext==_conn);
761
901
  *_pnext=_conn->next;
762
902
  _conn->next=_stream->free_head;
802
942
    }
803
943
    else{
804
944
      ssize_t ret;
805
 
      errno=0;
806
 
      ret=write(fd.fd,_buf,_buf_size);
 
945
      op_reset_errno();
 
946
      ret=send(fd.fd,_buf,_buf_size,0);
807
947
      if(ret>0){
808
948
        _buf+=ret;
809
949
        _buf_size-=ret;
810
950
        continue;
811
951
      }
812
 
      err=errno;
 
952
      err=op_errno();
813
953
      if(err!=EAGAIN&&err!=EWOULDBLOCK)return OP_FALSE;
814
954
      fd.events=POLLOUT;
815
955
    }
855
995
  opus_int64   read_rate;
856
996
  read_delta_bytes=_conn->read_bytes;
857
997
  if(read_delta_bytes<=0)return;
858
 
  OP_ALWAYS_TRUE(!ftime(&read_time));
 
998
  ftime(&read_time);
859
999
  read_delta_ms=op_time_diff_ms(&read_time,&_conn->read_time);
860
1000
  read_rate=_conn->read_rate;
861
1001
  read_delta_ms=OP_MAX(read_delta_ms,1);
912
1052
    }
913
1053
    else{
914
1054
      ssize_t ret;
915
 
      errno=0;
916
 
      ret=read(fd.fd,_buf+nread,_buf_size-nread);
 
1055
      op_reset_errno();
 
1056
      ret=recv(fd.fd,_buf+nread,_buf_size-nread,0);
917
1057
      OP_ASSERT(ret<=_buf_size-nread);
918
1058
      if(ret>0){
919
1059
        /*Read some data.
925
1065
      /*If we already read some data or the connection was closed, return
926
1066
         right now.*/
927
1067
      if(ret==0||nread>0)break;
928
 
      err=errno;
 
1068
      err=op_errno();
929
1069
      if(err!=EAGAIN&&err!=EWOULDBLOCK)return OP_EREAD;
930
1070
      fd.events=POLLIN;
931
1071
    }
944
1084
/*Tries to look at the pending data for a connection without consuming it.
945
1085
  [out] _buf: Returns the data at which we're peeking.
946
1086
  _buf_size:  The size of the buffer.*/
947
 
static int op_http_conn_peek(OpusHTTPConn *_conn,
948
 
 char *_buf,int _buf_size){
 
1087
static int op_http_conn_peek(OpusHTTPConn *_conn,char *_buf,int _buf_size){
949
1088
  struct pollfd   fd;
950
1089
  SSL            *ssl_conn;
951
1090
  int             ret;
964
1103
      else return 0;
965
1104
    }
966
1105
    else{
967
 
      errno=0;
 
1106
      op_reset_errno();
968
1107
      ret=(int)recv(fd.fd,_buf,_buf_size,MSG_PEEK);
969
1108
      /*Either saw some data or the connection was closed.*/
970
1109
      if(ret>=0)return ret;
971
 
      err=errno;
 
1110
      err=op_errno();
972
1111
      if(err!=EAGAIN&&err!=EWOULDBLOCK)return 0;
973
1112
      fd.events=POLLIN;
974
1113
    }
1192
1331
static opus_int64 op_http_parse_nonnegative_int64(const char **_next,
1193
1332
 const char *_cdr){
1194
1333
  const char *next;
1195
 
  opus_int64  content_length;
 
1334
  opus_int64  ret;
1196
1335
  int         i;
1197
1336
  next=_cdr+strspn(_cdr,OP_HTTP_DIGIT);
1198
1337
  *_next=next;
1199
1338
  if(OP_UNLIKELY(next<=_cdr))return OP_FALSE;
1200
1339
  while(*_cdr=='0')_cdr++;
1201
1340
  if(OP_UNLIKELY(next-_cdr>19))return OP_EIMPL;
1202
 
  content_length=0;
 
1341
  ret=0;
1203
1342
  for(i=0;i<next-_cdr;i++){
1204
1343
    int digit;
1205
1344
    digit=_cdr[i]-'0';
1206
1345
    /*Check for overflow.*/
1207
 
    if(OP_UNLIKELY(content_length>(OP_INT64_MAX-9)/10+(digit<=7))){
1208
 
      return OP_EIMPL;
1209
 
    }
1210
 
    content_length=content_length*10+digit;
 
1346
    if(OP_UNLIKELY(ret>(OP_INT64_MAX-9)/10+(digit<=7)))return OP_EIMPL;
 
1347
    ret=ret*10+digit;
1211
1348
  }
1212
 
  return content_length;
 
1349
  return ret;
1213
1350
}
1214
1351
 
1215
1352
static opus_int64 op_http_parse_content_length(const char *_cdr){
1295
1432
typedef int (*op_ssl_step_func)(SSL *_ssl_conn);
1296
1433
 
1297
1434
/*Try to run an SSL function to completion (blocking if necessary).*/
1298
 
static int op_do_ssl_step(SSL *_ssl_conn,int _fd,op_ssl_step_func _step){
 
1435
static int op_do_ssl_step(SSL *_ssl_conn,op_sock _fd,op_ssl_step_func _step){
1299
1436
  struct pollfd fd;
1300
1437
  fd.fd=_fd;
1301
1438
  for(;;){
1390
1527
/*Establish a CONNECT tunnel and pipeline the start of the TLS handshake for
1391
1528
   proxying https URL requests.*/
1392
1529
int op_http_conn_establish_tunnel(OpusHTTPStream *_stream,
1393
 
 OpusHTTPConn *_conn,int _fd,SSL *_ssl_conn,BIO *_ssl_bio){
 
1530
 OpusHTTPConn *_conn,op_sock _fd,SSL *_ssl_conn,BIO *_ssl_bio){
1394
1531
  BIO  *retry_bio;
1395
1532
  char *status_code;
1396
1533
  char *next;
1507
1644
/*Verify the server's hostname matches the certificate they presented using
1508
1645
   the procedure from Section 6 of RFC 6125.
1509
1646
  Return: 0 if the certificate doesn't match, and a non-zero value if it does.*/
1510
 
static int op_http_verify_hostname(OpusHTTPStream *_stream,
1511
 
 SSL *_ssl_conn){
 
1647
static int op_http_verify_hostname(OpusHTTPStream *_stream,SSL *_ssl_conn){
1512
1648
  X509                   *peer_cert;
1513
1649
  STACK_OF(GENERAL_NAME) *san_names;
1514
1650
  char                   *host;
1576
1712
       equivalent) of a URI or deriving the application service type from the
1577
1713
       scheme of a URI) ..."
1578
1714
      We don't have a way to check (without relying on DNS records, which might
1579
 
       be subverted), if this address is fully-qualified.
 
1715
       be subverted) if this address is fully-qualified.
1580
1716
      This is particularly problematic when using a CONNECT tunnel, as it is
1581
1717
       the server that does DNS lookup, not us.
1582
1718
      However, we are certain that if the hostname has no '.', it is definitely
1660
1796
 
1661
1797
/*Perform the TLS handshake on a new connection.*/
1662
1798
int op_http_conn_start_tls(OpusHTTPStream *_stream,OpusHTTPConn *_conn,
1663
 
 int _fd,SSL *_ssl_conn){
 
1799
 op_sock _fd,SSL *_ssl_conn){
1664
1800
  SSL_SESSION *ssl_session;
1665
1801
  BIO         *ssl_bio;
1666
1802
  int          skip_certificate_check;
1724
1860
          OP_FALSE If the connection failed and there were no more addresses
1725
1861
                    left to try.
1726
1862
                    *_addr will be set to NULL in this case.*/
1727
 
static int op_sock_connect_next(int _fd,
 
1863
static int op_sock_connect_next(op_sock _fd,
1728
1864
 struct addrinfo **_addr,int _ai_family){
1729
1865
  struct addrinfo *addr;
 
1866
  int err;
1730
1867
  addr=*_addr;
1731
1868
  for(;;){
1732
1869
    /*Move to the next address of the requested type.*/
1735
1872
    /*No more: failure.*/
1736
1873
    if(addr==NULL)return OP_FALSE;
1737
1874
    if(connect(_fd,addr->ai_addr,addr->ai_addrlen)>=0)return 1;
1738
 
    if(OP_LIKELY(errno==EINPROGRESS))return 0;
 
1875
    err=op_errno();
 
1876
    /*Winsock will set WSAEWOULDBLOCK.*/
 
1877
    if(OP_LIKELY(err==EINPROGRESS||err==EWOULDBLOCK))return 0;
1739
1878
    addr=addr->ai_next;
1740
1879
  }
1741
1880
}
1780
1919
  _stream->free_head=_conn->next;
1781
1920
  _conn->next=_stream->lru_head;
1782
1921
  _stream->lru_head=_conn;
1783
 
  OP_ALWAYS_TRUE(!ftime(_start_time));
 
1922
  ftime(_start_time);
1784
1923
  *&_conn->read_time=*_start_time;
1785
1924
  _conn->read_bytes=0;
1786
1925
  _conn->read_rate=0;
1789
1928
    ai_family=addrs[pi]->ai_family;
1790
1929
    fds[pi].fd=socket(ai_family,SOCK_STREAM,addrs[pi]->ai_protocol);
1791
1930
    fds[pi].events=POLLOUT;
1792
 
    if(OP_LIKELY(fds[pi].fd>=0)){
 
1931
    if(OP_LIKELY(fds[pi].fd!=OP_INVALID_SOCKET)){
1793
1932
      if(OP_LIKELY(op_sock_set_nonblocking(fds[pi].fd,1)>=0)){
1794
1933
        ret=op_sock_connect_next(fds[pi].fd,addrs+pi,ai_family);
1795
1934
        if(OP_UNLIKELY(ret>0)){
1820
1959
      /*Some platforms will return the pending error in &err and return 0.
1821
1960
        Others will put it in errno and return -1.*/
1822
1961
      ret=getsockopt(fds[pi].fd,SOL_SOCKET,SO_ERROR,&err,&errlen);
1823
 
      if(ret<0)err=errno;
 
1962
      if(ret<0)err=op_errno();
1824
1963
      /*Success!*/
1825
1964
      if(err==0||err==EISCONN)break;
1826
1965
      /*Move on to the next address for this protocol.*/
1862
2001
      SSL_free(ssl_conn);
1863
2002
    }
1864
2003
    close(fds[pi].fd);
1865
 
    _conn->fd=-1;
 
2004
    _conn->fd=OP_INVALID_SOCKET;
1866
2005
    return OP_FALSE;
1867
2006
  }
1868
2007
  /*Just a normal non-SSL connection.*/
1897
2036
    s1=_src[3*i+1];
1898
2037
    s2=_src[3*i+2];
1899
2038
    _dst[4*i+0]=BASE64_TABLE[s0>>2];
1900
 
    _dst[4*i+1]=BASE64_TABLE[s0&3<<4|s1>>4];
1901
 
    _dst[4*i+2]=BASE64_TABLE[s1&15<<2|s2>>6];
 
2039
    _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4|s1>>4];
 
2040
    _dst[4*i+2]=BASE64_TABLE[(s1&15)<<2|s2>>6];
1902
2041
    _dst[4*i+3]=BASE64_TABLE[s2&63];
1903
2042
  }
1904
2043
  _len-=3*i;
1905
2044
  if(_len==1){
1906
2045
    s0=_src[3*i+0];
1907
2046
    _dst[4*i+0]=BASE64_TABLE[s0>>2];
1908
 
    _dst[4*i+1]=BASE64_TABLE[s0&3<<4];
 
2047
    _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4];
1909
2048
    _dst[4*i+2]='=';
1910
2049
    _dst[4*i+3]='=';
1911
2050
    i++;
1914
2053
    s0=_src[3*i+0];
1915
2054
    s1=_src[3*i+1];
1916
2055
    _dst[4*i+0]=BASE64_TABLE[s0>>2];
1917
 
    _dst[4*i+1]=BASE64_TABLE[s0&3<<4|s1>>4];
1918
 
    _dst[4*i+2]=BASE64_TABLE[s1&15<<2];
 
2056
    _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4|s1>>4];
 
2057
    _dst[4*i+2]=BASE64_TABLE[(s1&15)<<2];
1919
2058
    _dst[4*i+3]='=';
1920
2059
    i++;
1921
2060
  }
2002
2141
     out that last_host!=NULL implies we've already taken one trip through the
2003
2142
     loop.*/
2004
2143
  last_port=0;
 
2144
#if defined(_WIN32)
 
2145
  op_init_winsock();
 
2146
#endif
2005
2147
  ret=op_parse_url(&_stream->url,_url);
2006
2148
  if(OP_UNLIKELY(ret<0))return ret;
2007
2149
  for(nredirs=0;nredirs<OP_REDIRECT_LIMIT;nredirs++){
2162
2304
    if(OP_UNLIKELY(ret<0))return ret;
2163
2305
    ret=op_http_conn_read_response(_stream->conns+0,&_stream->response);
2164
2306
    if(OP_UNLIKELY(ret<0))return ret;
2165
 
    OP_ALWAYS_TRUE(!ftime(&end_time));
 
2307
    ftime(&end_time);
2166
2308
    next=op_http_parse_status_line(&v1_1_compat,&status_code,
2167
2309
     _stream->response.buf);
2168
2310
    if(OP_UNLIKELY(next==NULL))return OP_FALSE;
2200
2342
          ret=op_http_parse_content_range(&range_first,&range_last,
2201
2343
           &range_length,cdr);
2202
2344
          if(OP_UNLIKELY(ret<0))return ret;
2203
 
          /*"A response with satus code 206 (Partial Content) MUST NOTE
 
2345
          /*"A response with satus code 206 (Partial Content) MUST NOT
2204
2346
             include a Content-Range field with a byte-range-resp-spec of
2205
2347
             '*'."*/
2206
2348
          if(status_code[2]=='6'
2306
2448
      /*302 Found*/
2307
2449
      case '2':
2308
2450
      /*307 Temporary Redirect*/
2309
 
      case '7':break;
 
2451
      case '7':
 
2452
      /*308 Permanent Redirect (defined by draft-reschke-http-status-308-07).*/
 
2453
      case '8':break;
2310
2454
      /*305 Use Proxy: "The Location field gives the URI of the proxy."
2311
2455
        TODO: This shouldn't actually be that hard to do.*/
2312
2456
      case '5':return OP_EIMPL;
2314
2458
         originally requested resource."
2315
2459
        304 Not Modified: "The 304 response MUST NOT contain a message-body."
2316
2460
        306 (Unused)
2317
 
        308...309 are not yet defined, so we don't know how to handle them.*/
 
2461
        309 is not yet defined, so we don't know how to handle it.*/
2318
2462
      default:return OP_FALSE;
2319
2463
    }
2320
2464
    _url=NULL;
2500
2644
}
2501
2645
 
2502
2646
/*Open a new connection that will start reading at byte offset _pos.
2503
 
  _pos:        The byte offset to start readiny from.
 
2647
  _pos:        The byte offset to start reading from.
2504
2648
  _chunk_size: The number of bytes to ask for in the initial request, or -1 to
2505
2649
                request the rest of the resource.
2506
2650
               This may be more bytes than remain, in which case it will be
2518
2662
  if(OP_UNLIKELY(ret<0))return ret;
2519
2663
  ret=op_http_conn_handle_response(_stream,_conn);
2520
2664
  if(OP_UNLIKELY(ret!=0))return OP_FALSE;
2521
 
  OP_ALWAYS_TRUE(!ftime(&end_time));
 
2665
  ftime(&end_time);
2522
2666
  _stream->cur_conni=_conn-_stream->conns;
2523
2667
  OP_ASSERT(_stream->cur_conni>=0&&_stream->cur_conni<OP_NCONNS_MAX);
2524
2668
  /*The connection has been successfully opened.
2811
2955
    op_http_conn_read_rate_update(stream->conns+ci);
2812
2956
    *&seek_time=*&stream->conns[ci].read_time;
2813
2957
  }
2814
 
  else OP_ALWAYS_TRUE(!ftime(&seek_time));
 
2958
  else ftime(&seek_time);
2815
2959
  /*If we seeked past the end of the stream, just disable the active
2816
2960
     connection.*/
2817
2961
  if(pos>=content_length){
3069
3213
 
3070
3214
void *op_url_stream_create(OpusFileCallbacks *_cb,
3071
3215
 const char *_url,...){
3072
 
  va_list ap;
 
3216
  va_list  ap;
 
3217
  void    *ret;
3073
3218
  va_start(ap,_url);
3074
 
  return op_url_stream_vcreate(_cb,_url,ap);
 
3219
  ret=op_url_stream_vcreate(_cb,_url,ap);
 
3220
  va_end(ap);
 
3221
  return ret;
 
3222
}
 
3223
 
 
3224
/*Convenience routines to open/test URLs in a single step.*/
 
3225
 
 
3226
OggOpusFile *op_vopen_url(const char *_url,int *_error,va_list _ap){
 
3227
  OpusFileCallbacks  cb;
 
3228
  OggOpusFile       *of;
 
3229
  void              *source;
 
3230
  source=op_url_stream_vcreate(&cb,_url,_ap);
 
3231
  if(OP_UNLIKELY(source==NULL)){
 
3232
    if(_error!=NULL)*_error=OP_EFAULT;
 
3233
    return NULL;
 
3234
  }
 
3235
  of=op_open_callbacks(source,&cb,NULL,0,_error);
 
3236
  if(OP_UNLIKELY(of==NULL))(*cb.close)(source);
 
3237
  return of;
 
3238
}
 
3239
 
 
3240
OggOpusFile *op_open_url(const char *_url,int *_error,...){
 
3241
  OggOpusFile *ret;
 
3242
  va_list      ap;
 
3243
  va_start(ap,_error);
 
3244
  ret=op_vopen_url(_url,_error,ap);
 
3245
  va_end(ap);
 
3246
  return ret;
 
3247
}
 
3248
 
 
3249
OggOpusFile *op_vtest_url(const char *_url,int *_error,va_list _ap){
 
3250
  OpusFileCallbacks  cb;
 
3251
  OggOpusFile       *of;
 
3252
  void              *source;
 
3253
  source=op_url_stream_vcreate(&cb,_url,_ap);
 
3254
  if(OP_UNLIKELY(source==NULL)){
 
3255
    if(_error!=NULL)*_error=OP_EFAULT;
 
3256
    return NULL;
 
3257
  }
 
3258
  of=op_test_callbacks(source,&cb,NULL,0,_error);
 
3259
  if(OP_UNLIKELY(of==NULL))(*cb.close)(source);
 
3260
  return of;
 
3261
}
 
3262
 
 
3263
OggOpusFile *op_test_url(const char *_url,int *_error,...){
 
3264
  OggOpusFile *ret;
 
3265
  va_list      ap;
 
3266
  va_start(ap,_error);
 
3267
  ret=op_vtest_url(_url,_error,ap);
 
3268
  va_end(ap);
 
3269
  return ret;
3075
3270
}