| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 // The close queue handles graceful closing of HTTP connections. When | 5 // The close queue handles graceful closing of HTTP connections. When |
| 6 // a connection is added to the queue it will enter a wait state | 6 // a connection is added to the queue it will enter a wait state |
| 7 // waiting for all data written and possibly socket shutdown from | 7 // waiting for all data written and possibly socket shutdown from |
| 8 // peer. | 8 // peer. |
| 9 class _CloseQueue { | 9 class _CloseQueue { |
| 10 _CloseQueue() : _q = new Set<_HttpConnectionBase>(); | 10 _CloseQueue() : _q = new Set<_HttpConnectionBase>(); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 if (connection == null) return true; | 93 if (connection == null) return true; |
| 94 return !headers[HttpHeaders.CONNECTION].some( | 94 return !headers[HttpHeaders.CONNECTION].some( |
| 95 (value) => value.toLowerCase() == "close"); | 95 (value) => value.toLowerCase() == "close"); |
| 96 } else { | 96 } else { |
| 97 if (connection == null) return false; | 97 if (connection == null) return false; |
| 98 return headers[HttpHeaders.CONNECTION].some( | 98 return headers[HttpHeaders.CONNECTION].some( |
| 99 (value) => value.toLowerCase() == "keep-alive"); | 99 (value) => value.toLowerCase() == "keep-alive"); |
| 100 } | 100 } |
| 101 } | 101 } |
| 102 | 102 |
| 103 X509Certificate get certificate { |
| 104 var socket = _httpConnection._socket as SecureSocket; |
| 105 return socket == null ? socket : socket.peerCertificate; |
| 106 } |
| 107 |
| 103 void set persistentConnection(bool persistentConnection) { | 108 void set persistentConnection(bool persistentConnection) { |
| 104 if (_outputStream != null) throw new HttpException("Header already sent"); | 109 if (_outputStream != null) throw new HttpException("Header already sent"); |
| 105 | 110 |
| 106 // Determine the value of the "Connection" header. | 111 // Determine the value of the "Connection" header. |
| 107 headers.remove(HttpHeaders.CONNECTION, "close"); | 112 headers.remove(HttpHeaders.CONNECTION, "close"); |
| 108 headers.remove(HttpHeaders.CONNECTION, "keep-alive"); | 113 headers.remove(HttpHeaders.CONNECTION, "keep-alive"); |
| 109 if (_protocolVersion == "1.1" && !persistentConnection) { | 114 if (_protocolVersion == "1.1" && !persistentConnection) { |
| 110 headers.add(HttpHeaders.CONNECTION, "close"); | 115 headers.add(HttpHeaders.CONNECTION, "close"); |
| 111 } else if (_protocolVersion == "1.0" && persistentConnection) { | 116 } else if (_protocolVersion == "1.0" && persistentConnection) { |
| 112 headers.add(HttpHeaders.CONNECTION, "keep-alive"); | 117 headers.add(HttpHeaders.CONNECTION, "keep-alive"); |
| (...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 | 998 |
| 994 _HttpServer._internal({ bool isSecure: false }) | 999 _HttpServer._internal({ bool isSecure: false }) |
| 995 : _secure = isSecure, | 1000 : _secure = isSecure, |
| 996 _connections = new Set<_HttpConnection>(), | 1001 _connections = new Set<_HttpConnection>(), |
| 997 _handlers = new List<_RequestHandlerRegistration>(), | 1002 _handlers = new List<_RequestHandlerRegistration>(), |
| 998 _closeQueue = new _CloseQueue(); | 1003 _closeQueue = new _CloseQueue(); |
| 999 | 1004 |
| 1000 void listen(String host, | 1005 void listen(String host, |
| 1001 int port, | 1006 int port, |
| 1002 {int backlog: 128, | 1007 {int backlog: 128, |
| 1003 String certificate_name}) { | 1008 String certificate_name, |
| 1009 bool requestClientCertificate: false}) { |
| 1004 if (_secure) { | 1010 if (_secure) { |
| 1005 listenOn(new SecureServerSocket(host, port, backlog, certificate_name)); | 1011 listenOn(new SecureServerSocket( |
| 1012 host, |
| 1013 port, |
| 1014 backlog, |
| 1015 certificate_name, |
| 1016 requestClientCertificate: requestClientCertificate)); |
| 1006 } else { | 1017 } else { |
| 1007 listenOn(new ServerSocket(host, port, backlog)); | 1018 listenOn(new ServerSocket(host, port, backlog)); |
| 1008 } | 1019 } |
| 1009 _closeServer = true; | 1020 _closeServer = true; |
| 1010 } | 1021 } |
| 1011 | 1022 |
| 1012 void listenOn(ServerSocket serverSocket) { | 1023 void listenOn(ServerSocket serverSocket) { |
| 1013 if (_secure && serverSocket is! SecureServerSocket) { | 1024 if (_secure && serverSocket is! SecureServerSocket) { |
| 1014 throw new HttpException( | 1025 throw new HttpException( |
| 1015 'HttpsServer.listenOn was called with non-secure server socket'); | 1026 'HttpsServer.listenOn was called with non-secure server socket'); |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1743 void _markReturned() { | 1754 void _markReturned() { |
| 1744 // Any activity on the socket while waiting in the pool will | 1755 // Any activity on the socket while waiting in the pool will |
| 1745 // invalidate the connection os that it is not reused. | 1756 // invalidate the connection os that it is not reused. |
| 1746 _socket.onData = _invalidate; | 1757 _socket.onData = _invalidate; |
| 1747 _socket.onClosed = _invalidate; | 1758 _socket.onClosed = _invalidate; |
| 1748 _socket.onError = (_) => _invalidate(); | 1759 _socket.onError = (_) => _invalidate(); |
| 1749 _returnTime = new Date.now(); | 1760 _returnTime = new Date.now(); |
| 1750 _httpClientConnection = null; | 1761 _httpClientConnection = null; |
| 1751 } | 1762 } |
| 1752 | 1763 |
| 1753 void _markRetreived() { | 1764 void _markRetrieved() { |
| 1754 _socket.onData = null; | 1765 _socket.onData = null; |
| 1755 _socket.onClosed = null; | 1766 _socket.onClosed = null; |
| 1756 _socket.onError = null; | 1767 _socket.onError = null; |
| 1757 _httpClientConnection = null; | 1768 _httpClientConnection = null; |
| 1758 } | 1769 } |
| 1759 | 1770 |
| 1760 void _close() { | 1771 void _close() { |
| 1761 _socket.onData = null; | 1772 _socket.onData = null; |
| 1762 _socket.onClosed = null; | 1773 _socket.onClosed = null; |
| 1763 _socket.onError = null; | 1774 _socket.onError = null; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 | 1903 |
| 1893 set authenticate(Future<bool> f(Uri url, String scheme, String realm)) { | 1904 set authenticate(Future<bool> f(Uri url, String scheme, String realm)) { |
| 1894 _authenticate = f; | 1905 _authenticate = f; |
| 1895 } | 1906 } |
| 1896 | 1907 |
| 1897 void addCredentials( | 1908 void addCredentials( |
| 1898 Uri url, String realm, HttpClientCredentials cr) { | 1909 Uri url, String realm, HttpClientCredentials cr) { |
| 1899 credentials.add(new _Credentials(url, realm, cr)); | 1910 credentials.add(new _Credentials(url, realm, cr)); |
| 1900 } | 1911 } |
| 1901 | 1912 |
| 1913 set sendClientCertificate(bool send) => _sendClientCertificate = send; |
| 1914 |
| 1915 set clientCertificate(String nickname) => _clientCertificate = nickname; |
| 1916 |
| 1902 set findProxy(String f(Uri uri)) => _findProxy = f; | 1917 set findProxy(String f(Uri uri)) => _findProxy = f; |
| 1903 | 1918 |
| 1904 void shutdown({bool force: false}) { | 1919 void shutdown({bool force: false}) { |
| 1905 if (force) _closeQueue.shutdown(); | 1920 if (force) _closeQueue.shutdown(); |
| 1906 _openSockets.forEach((String key, Queue<_SocketConnection> connections) { | 1921 _openSockets.forEach((String key, Queue<_SocketConnection> connections) { |
| 1907 while (!connections.isEmpty) { | 1922 while (!connections.isEmpty) { |
| 1908 _SocketConnection socketConn = connections.removeFirst(); | 1923 _SocketConnection socketConn = connections.removeFirst(); |
| 1909 socketConn._socket.close(); | 1924 socketConn._socket.close(); |
| 1910 } | 1925 } |
| 1911 }); | 1926 }); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 connectHost = proxy.host; | 2000 connectHost = proxy.host; |
| 1986 connectPort = proxy.port; | 2001 connectPort = proxy.port; |
| 1987 } | 2002 } |
| 1988 | 2003 |
| 1989 // If there are active connections for this key get the first one | 2004 // If there are active connections for this key get the first one |
| 1990 // otherwise create a new one. | 2005 // otherwise create a new one. |
| 1991 String key = _connectionKey(connectHost, connectPort); | 2006 String key = _connectionKey(connectHost, connectPort); |
| 1992 Queue socketConnections = _openSockets[key]; | 2007 Queue socketConnections = _openSockets[key]; |
| 1993 // Remove active connections that are not valid any more or of | 2008 // Remove active connections that are not valid any more or of |
| 1994 // the wrong type (HTTP or HTTPS). | 2009 // the wrong type (HTTP or HTTPS). |
| 1995 while (socketConnections != null && | 2010 if (socketConnections != null) { |
| 1996 !socketConnections.isEmpty && | 2011 while (!socketConnections.isEmpty) { |
| 1997 (!socketConnections.first._valid || | 2012 if (socketConnections.first._valid) { |
| 1998 secure != (socketConnections.first._socket is SecureSocket))) { | 2013 // If socket has the same properties, exit loop with found socket. |
| 1999 socketConnections.removeFirst()._close(); | 2014 var socket = socketConnections.first._socket; |
| 2015 if (!secure && socket is! SecureSocket) break; |
| 2016 if (secure && socket is SecureSocket && |
| 2017 _sendClientCertificate == socket.sendClientCertificate && |
| 2018 _clientCertificate == socket.certificateName) break; |
| 2019 } |
| 2020 socketConnections.removeFirst()._close(); |
| 2021 } |
| 2000 } | 2022 } |
| 2001 if (socketConnections == null || socketConnections.isEmpty) { | 2023 if (socketConnections == null || socketConnections.isEmpty) { |
| 2002 Socket socket = secure ? new SecureSocket(connectHost, connectPort) : | 2024 Socket socket = secure ? |
| 2003 new Socket(connectHost, connectPort); | 2025 new SecureSocket(connectHost, |
| 2026 connectPort, |
| 2027 sendClientCertificate: _sendClientCertificate, |
| 2028 certificateName: _clientCertificate) : |
| 2029 new Socket(connectHost, connectPort); |
| 2004 // Until the connection is established handle connection errors | 2030 // Until the connection is established handle connection errors |
| 2005 // here as the HttpClientConnection object is not yet associated | 2031 // here as the HttpClientConnection object is not yet associated |
| 2006 // with the socket. | 2032 // with the socket. |
| 2007 socket.onError = (e) { | 2033 socket.onError = (e) { |
| 2008 proxyIndex++; | 2034 proxyIndex++; |
| 2009 if (proxyIndex < proxyConfiguration.proxies.length) { | 2035 if (proxyIndex < proxyConfiguration.proxies.length) { |
| 2010 // Try the next proxy in the list. | 2036 // Try the next proxy in the list. |
| 2011 _establishConnection( | 2037 _establishConnection( |
| 2012 host, port, proxyConfiguration, proxyIndex, false, secure); | 2038 host, port, proxyConfiguration, proxyIndex, false, secure); |
| 2013 } else { | 2039 } else { |
| 2014 // Report the error through the HttpClientConnection object to | 2040 // Report the error through the HttpClientConnection object to |
| 2015 // the client. | 2041 // the client. |
| 2016 connection._onError(e); | 2042 connection._onError(e); |
| 2017 } | 2043 } |
| 2018 }; | 2044 }; |
| 2019 socket.onConnect = () { | 2045 socket.onConnect = () { |
| 2020 // When the connection is established, clear the error | 2046 // When the connection is established, clear the error |
| 2021 // callback as it will now be handled by the | 2047 // callback as it will now be handled by the |
| 2022 // HttpClientConnection object which will be associated with | 2048 // HttpClientConnection object which will be associated with |
| 2023 // the connected socket. | 2049 // the connected socket. |
| 2024 socket.onError = null; | 2050 socket.onError = null; |
| 2025 _SocketConnection socketConn = | 2051 _SocketConnection socketConn = |
| 2026 new _SocketConnection(connectHost, connectPort, socket); | 2052 new _SocketConnection(connectHost, connectPort, socket); |
| 2027 _activeSockets.add(socketConn); | 2053 _activeSockets.add(socketConn); |
| 2028 _connectionOpened(socketConn, connection, !proxy.isDirect); | 2054 _connectionOpened(socketConn, connection, !proxy.isDirect); |
| 2029 }; | 2055 }; |
| 2030 } else { | 2056 } else { |
| 2031 _SocketConnection socketConn = socketConnections.removeFirst(); | 2057 _SocketConnection socketConn = socketConnections.removeFirst(); |
| 2032 socketConn._markRetreived(); | 2058 socketConn._markRetrieved(); |
| 2033 _activeSockets.add(socketConn); | 2059 _activeSockets.add(socketConn); |
| 2034 new Timer(0, (ignored) => | 2060 new Timer(0, (ignored) => |
| 2035 _connectionOpened(socketConn, connection, !proxy.isDirect)); | 2061 _connectionOpened(socketConn, connection, !proxy.isDirect)); |
| 2036 | 2062 |
| 2037 // Get rid of eviction timer if there are no more active connections. | 2063 // Get rid of eviction timer if there are no more active connections. |
| 2038 if (socketConnections.isEmpty) _openSockets.remove(key); | 2064 if (socketConnections.isEmpty) _openSockets.remove(key); |
| 2039 if (_openSockets.isEmpty) _cancelEvictionTimer(); | 2065 if (_openSockets.isEmpty) _cancelEvictionTimer(); |
| 2040 } | 2066 } |
| 2041 } | 2067 } |
| 2042 | 2068 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2165 } | 2191 } |
| 2166 | 2192 |
| 2167 Function _onOpen; | 2193 Function _onOpen; |
| 2168 Map<String, Queue<_SocketConnection>> _openSockets; | 2194 Map<String, Queue<_SocketConnection>> _openSockets; |
| 2169 Set<_SocketConnection> _activeSockets; | 2195 Set<_SocketConnection> _activeSockets; |
| 2170 _CloseQueue _closeQueue; | 2196 _CloseQueue _closeQueue; |
| 2171 List<_Credentials> credentials; | 2197 List<_Credentials> credentials; |
| 2172 Timer _evictionTimer; | 2198 Timer _evictionTimer; |
| 2173 Function _findProxy; | 2199 Function _findProxy; |
| 2174 Function _authenticate; | 2200 Function _authenticate; |
| 2201 bool _sendClientCertificate = false; |
| 2202 String _clientCertificate; |
| 2175 bool _shutdown; // Has this HTTP client been shutdown? | 2203 bool _shutdown; // Has this HTTP client been shutdown? |
| 2176 } | 2204 } |
| 2177 | 2205 |
| 2178 | 2206 |
| 2179 class _HttpConnectionInfo implements HttpConnectionInfo { | 2207 class _HttpConnectionInfo implements HttpConnectionInfo { |
| 2180 String remoteHost; | 2208 String remoteHost; |
| 2181 int remotePort; | 2209 int remotePort; |
| 2182 int localPort; | 2210 int localPort; |
| 2183 } | 2211 } |
| 2184 | 2212 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2296 | 2324 |
| 2297 | 2325 |
| 2298 class _RedirectInfo implements RedirectInfo { | 2326 class _RedirectInfo implements RedirectInfo { |
| 2299 const _RedirectInfo(int this.statusCode, | 2327 const _RedirectInfo(int this.statusCode, |
| 2300 String this.method, | 2328 String this.method, |
| 2301 Uri this.location); | 2329 Uri this.location); |
| 2302 final int statusCode; | 2330 final int statusCode; |
| 2303 final String method; | 2331 final String method; |
| 2304 final Uri location; | 2332 final Uri location; |
| 2305 } | 2333 } |
| OLD | NEW |