| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library http_multi_server; | 5 library http_multi_server; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 | 9 |
| 10 import 'src/multi_headers.dart'; | 10 import 'src/multi_headers.dart'; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 HttpServer.bindSecure(address, port, backlog: backlog, | 121 HttpServer.bindSecure(address, port, backlog: backlog, |
| 122 certificateName: certificateName, | 122 certificateName: certificateName, |
| 123 requestClientCertificate: requestClientCertificate)); | 123 requestClientCertificate: requestClientCertificate)); |
| 124 } | 124 } |
| 125 | 125 |
| 126 /// A helper method for initializing loopback servers. | 126 /// A helper method for initializing loopback servers. |
| 127 /// | 127 /// |
| 128 /// [bind] should forward to either [HttpServer.bind] or | 128 /// [bind] should forward to either [HttpServer.bind] or |
| 129 /// [HttpServer.bindSecure]. | 129 /// [HttpServer.bindSecure]. |
| 130 static Future<HttpServer> _loopback(int port, | 130 static Future<HttpServer> _loopback(int port, |
| 131 Future<HttpServer> bind(InternetAddress address, int port)) { | 131 Future<HttpServer> bind(InternetAddress address, int port), |
| 132 [int remainingRetries]) { |
| 133 if (remainingRetries == null) remainingRetries = 5; |
| 134 |
| 132 return Future.wait([ | 135 return Future.wait([ |
| 133 supportsIpV6, | 136 supportsIpV6, |
| 134 bind(InternetAddress.LOOPBACK_IP_V4, port) | 137 bind(InternetAddress.LOOPBACK_IP_V4, port) |
| 135 ]).then((results) { | 138 ]).then((results) { |
| 136 var supportsIpV6 = results[0]; | 139 var supportsIpV6 = results[0]; |
| 137 var v4Server = results[1]; | 140 var v4Server = results[1]; |
| 138 | 141 |
| 139 if (!supportsIpV6) return v4Server; | 142 if (!supportsIpV6) return v4Server; |
| 140 | 143 |
| 141 // Reuse the IPv4 server's port so that if [port] is 0, both servers use | 144 // Reuse the IPv4 server's port so that if [port] is 0, both servers use |
| 142 // the same ephemeral port. | 145 // the same ephemeral port. |
| 143 return bind(InternetAddress.LOOPBACK_IP_V6, v4Server.port) | 146 return bind(InternetAddress.LOOPBACK_IP_V6, v4Server.port) |
| 144 .then((v6Server) { | 147 .then((v6Server) { |
| 145 return new HttpMultiServer([v4Server, v6Server]); | 148 return new HttpMultiServer([v4Server, v6Server]); |
| 146 }).catchError((error) { | 149 }).catchError((error) { |
| 147 if (error is! SocketException) throw error; | 150 if (error is! SocketException) throw error; |
| 148 if (error.osError.errno != _addressInUseErrno) throw error; | 151 if (error.osError.errno != _addressInUseErrno) throw error; |
| 149 if (port != 0) throw error; | 152 if (port != 0) throw error; |
| 153 if (remainingRetries == 0) throw error; |
| 150 | 154 |
| 151 // A port being available on IPv4 doesn't necessarily mean that the same | 155 // A port being available on IPv4 doesn't necessarily mean that the same |
| 152 // port is available on IPv6. If it's not (which is rare in practice), | 156 // port is available on IPv6. If it's not (which is rare in practice), |
| 153 // we try again until we find one that's available on both. | 157 // we try again until we find one that's available on both. |
| 154 v4Server.close(); | 158 v4Server.close(); |
| 155 return _loopback(port, bind); | 159 return _loopback(port, bind, remainingRetries - 1); |
| 156 }); | 160 }); |
| 157 }); | 161 }); |
| 158 } | 162 } |
| 159 | 163 |
| 160 Future close({bool force: false}) => | 164 Future close({bool force: false}) => |
| 161 Future.wait(_servers.map((server) => server.close(force: force))); | 165 Future.wait(_servers.map((server) => server.close(force: force))); |
| 162 | 166 |
| 163 /// Returns an HttpConnectionsInfo object summarizing the total number of | 167 /// Returns an HttpConnectionsInfo object summarizing the total number of |
| 164 /// current connections handled by all the servers. | 168 /// current connections handled by all the servers. |
| 165 HttpConnectionsInfo connectionsInfo() { | 169 HttpConnectionsInfo connectionsInfo() { |
| 166 var info = new HttpConnectionsInfo(); | 170 var info = new HttpConnectionsInfo(); |
| 167 for (var server in _servers) { | 171 for (var server in _servers) { |
| 168 var subInfo = server.connectionsInfo(); | 172 var subInfo = server.connectionsInfo(); |
| 169 info.total += subInfo.total; | 173 info.total += subInfo.total; |
| 170 info.active += subInfo.active; | 174 info.active += subInfo.active; |
| 171 info.idle += subInfo.idle; | 175 info.idle += subInfo.idle; |
| 172 info.closing += subInfo.closing; | 176 info.closing += subInfo.closing; |
| 173 } | 177 } |
| 174 return info; | 178 return info; |
| 175 } | 179 } |
| 176 } | 180 } |
| OLD | NEW |