| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 class _HttpIncoming extends Stream<List<int>> { | 7 class _HttpIncoming extends Stream<List<int>> { |
| 8 final int _transferLength; | 8 final int _transferLength; |
| 9 final Completer _dataCompleter = new Completer(); | 9 final Completer _dataCompleter = new Completer(); |
| 10 Stream<List<int>> _stream; | 10 Stream<List<int>> _stream; |
| (...skipping 1806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1817 static const _IDLE = 1; | 1817 static const _IDLE = 1; |
| 1818 static const _CLOSING = 2; | 1818 static const _CLOSING = 2; |
| 1819 static const _DETACHED = 3; | 1819 static const _DETACHED = 3; |
| 1820 | 1820 |
| 1821 int _state = _IDLE; | 1821 int _state = _IDLE; |
| 1822 | 1822 |
| 1823 final Socket _socket; | 1823 final Socket _socket; |
| 1824 final _HttpServer _httpServer; | 1824 final _HttpServer _httpServer; |
| 1825 final _HttpParser _httpParser; | 1825 final _HttpParser _httpParser; |
| 1826 StreamSubscription _subscription; | 1826 StreamSubscription _subscription; |
| 1827 Timer _idleTimer; |
| 1827 | 1828 |
| 1828 Future _streamFuture; | 1829 Future _streamFuture; |
| 1829 | 1830 |
| 1830 _HttpConnection(Socket this._socket, _HttpServer this._httpServer) | 1831 _HttpConnection(Socket this._socket, _HttpServer this._httpServer) |
| 1831 : _httpParser = new _HttpParser.requestParser() { | 1832 : _httpParser = new _HttpParser.requestParser() { |
| 1833 _startTimeout(); |
| 1832 _socket.pipe(_httpParser); | 1834 _socket.pipe(_httpParser); |
| 1833 _subscription = _httpParser.listen( | 1835 _subscription = _httpParser.listen( |
| 1834 (incoming) { | 1836 (incoming) { |
| 1837 _stopTimeout(); |
| 1835 // If the incoming was closed, close the connection. | 1838 // If the incoming was closed, close the connection. |
| 1836 incoming.dataDone.then((closing) { | 1839 incoming.dataDone.then((closing) { |
| 1837 if (closing) destroy(); | 1840 if (closing) destroy(); |
| 1838 }); | 1841 }); |
| 1839 // Only handle one incoming request at the time. Keep the | 1842 // Only handle one incoming request at the time. Keep the |
| 1840 // stream paused until the request has been send. | 1843 // stream paused until the request has been send. |
| 1841 _subscription.pause(); | 1844 _subscription.pause(); |
| 1842 _state = _ACTIVE; | 1845 _state = _ACTIVE; |
| 1843 var outgoing = new _HttpOutgoing(_socket); | 1846 var outgoing = new _HttpOutgoing(_socket); |
| 1844 var response = new _HttpResponse(incoming.uri, | 1847 var response = new _HttpResponse(incoming.uri, |
| 1845 incoming.headers.protocolVersion, | 1848 incoming.headers.protocolVersion, |
| 1846 outgoing, | 1849 outgoing, |
| 1847 _httpServer.serverHeader); | 1850 _httpServer.serverHeader); |
| 1848 var request = new _HttpRequest(response, incoming, _httpServer, this); | 1851 var request = new _HttpRequest(response, incoming, _httpServer, this); |
| 1849 _streamFuture = outgoing.done | 1852 _streamFuture = outgoing.done |
| 1850 .then((_) { | 1853 .then((_) { |
| 1851 response.deadline = null; | 1854 response.deadline = null; |
| 1852 if (_state == _DETACHED) return; | 1855 if (_state == _DETACHED) return; |
| 1853 if (response.persistentConnection && | 1856 if (response.persistentConnection && |
| 1854 request.persistentConnection && | 1857 request.persistentConnection && |
| 1855 incoming.fullBodyRead) { | 1858 incoming.fullBodyRead) { |
| 1856 _state = _IDLE; | 1859 _state = _IDLE; |
| 1860 _startTimeout(); |
| 1857 // Resume the subscription for incoming requests as the | 1861 // Resume the subscription for incoming requests as the |
| 1858 // request is now processed. | 1862 // request is now processed. |
| 1859 _subscription.resume(); | 1863 _subscription.resume(); |
| 1860 } else { | 1864 } else { |
| 1861 // Close socket, keep-alive not used or body sent before | 1865 // Close socket, keep-alive not used or body sent before |
| 1862 // received data was handled. | 1866 // received data was handled. |
| 1863 destroy(); | 1867 destroy(); |
| 1864 } | 1868 } |
| 1865 }) | 1869 }) |
| 1866 .catchError((e) { | 1870 .catchError((e) { |
| 1867 destroy(); | 1871 destroy(); |
| 1868 }); | 1872 }); |
| 1869 response._ignoreBody = request.method == "HEAD"; | 1873 response._ignoreBody = request.method == "HEAD"; |
| 1870 response._httpRequest = request; | 1874 response._httpRequest = request; |
| 1871 _httpServer._handleRequest(request); | 1875 _httpServer._handleRequest(request); |
| 1872 }, | 1876 }, |
| 1873 onDone: () { | 1877 onDone: () { |
| 1874 destroy(); | 1878 destroy(); |
| 1875 }, | 1879 }, |
| 1876 onError: (error) { | 1880 onError: (error) { |
| 1877 // Ignore failed requests that was closed before headers was received. | 1881 // Ignore failed requests that was closed before headers was received. |
| 1878 destroy(); | 1882 destroy(); |
| 1879 }); | 1883 }); |
| 1880 } | 1884 } |
| 1881 | 1885 |
| 1886 void _startTimeout() { |
| 1887 assert(_state == _IDLE); |
| 1888 _stopTimeout(); |
| 1889 if (_httpServer.idleTimeout == null) return; |
| 1890 _idleTimer = new Timer(_httpServer.idleTimeout, () { |
| 1891 destroy(); |
| 1892 }); |
| 1893 } |
| 1894 |
| 1895 void _stopTimeout() { |
| 1896 if (_idleTimer != null) _idleTimer.cancel(); |
| 1897 } |
| 1898 |
| 1882 void destroy() { | 1899 void destroy() { |
| 1900 _stopTimeout(); |
| 1883 if (_state == _CLOSING || _state == _DETACHED) return; | 1901 if (_state == _CLOSING || _state == _DETACHED) return; |
| 1884 _state = _CLOSING; | 1902 _state = _CLOSING; |
| 1885 _socket.destroy(); | 1903 _socket.destroy(); |
| 1886 _httpServer._connectionClosed(this); | 1904 _httpServer._connectionClosed(this); |
| 1887 } | 1905 } |
| 1888 | 1906 |
| 1889 Future<Socket> detachSocket() { | 1907 Future<Socket> detachSocket() { |
| 1908 _stopTimeout(); |
| 1890 _state = _DETACHED; | 1909 _state = _DETACHED; |
| 1891 // Remove connection from server. | 1910 // Remove connection from server. |
| 1892 _httpServer._connectionClosed(this); | 1911 _httpServer._connectionClosed(this); |
| 1893 | 1912 |
| 1894 _HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming(); | 1913 _HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming(); |
| 1895 | 1914 |
| 1896 return _streamFuture.then((_) { | 1915 return _streamFuture.then((_) { |
| 1897 return new _DetachedSocket(_socket, detachedIncoming); | 1916 return new _DetachedSocket(_socket, detachedIncoming); |
| 1898 }); | 1917 }); |
| 1899 } | 1918 } |
| 1900 | 1919 |
| 1901 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); | 1920 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); |
| 1902 | 1921 |
| 1903 bool get _isActive => _state == _ACTIVE; | 1922 bool get _isActive => _state == _ACTIVE; |
| 1904 bool get _isIdle => _state == _IDLE; | 1923 bool get _isIdle => _state == _IDLE; |
| 1905 bool get _isClosing => _state == _CLOSING; | 1924 bool get _isClosing => _state == _CLOSING; |
| 1906 bool get _isDetached => _state == _DETACHED; | 1925 bool get _isDetached => _state == _DETACHED; |
| 1907 } | 1926 } |
| 1908 | 1927 |
| 1909 | 1928 |
| 1910 // HTTP server waiting for socket connections. | 1929 // HTTP server waiting for socket connections. |
| 1911 class _HttpServer extends Stream<HttpRequest> implements HttpServer { | 1930 class _HttpServer extends Stream<HttpRequest> implements HttpServer { |
| 1912 String serverHeader = _getHttpVersion(); | 1931 String serverHeader = _getHttpVersion(); |
| 1913 | 1932 |
| 1933 Duration idleTimeout = const Duration(seconds: 120); |
| 1934 |
| 1914 static Future<HttpServer> bind(address, int port, int backlog) { | 1935 static Future<HttpServer> bind(address, int port, int backlog) { |
| 1915 return ServerSocket.bind(address, port, backlog: backlog).then((socket) { | 1936 return ServerSocket.bind(address, port, backlog: backlog).then((socket) { |
| 1916 return new _HttpServer._(socket, true); | 1937 return new _HttpServer._(socket, true); |
| 1917 }); | 1938 }); |
| 1918 } | 1939 } |
| 1919 | 1940 |
| 1920 static Future<HttpServer> bindSecure(address, | 1941 static Future<HttpServer> bindSecure(address, |
| 1921 int port, | 1942 int port, |
| 1922 int backlog, | 1943 int backlog, |
| 1923 String certificate_name, | 1944 String certificate_name, |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2445 final Uri location; | 2466 final Uri location; |
| 2446 } | 2467 } |
| 2447 | 2468 |
| 2448 String _getHttpVersion() { | 2469 String _getHttpVersion() { |
| 2449 var version = Platform.version; | 2470 var version = Platform.version; |
| 2450 // Only include major and minor version numbers. | 2471 // Only include major and minor version numbers. |
| 2451 int index = version.indexOf('.', version.indexOf('.') + 1); | 2472 int index = version.indexOf('.', version.indexOf('.') + 1); |
| 2452 version = version.substring(0, index); | 2473 version = version.substring(0, index); |
| 2453 return 'Dart/$version (dart:io)'; | 2474 return 'Dart/$version (dart:io)'; |
| 2454 } | 2475 } |
| OLD | NEW |