Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(639)

Side by Side Diff: lib/http_multi_server.dart

Issue 993743002: Recover gracefully if a matching port is unavailable. (Closed) Base URL: git@github.com:dart-lang/http_multi_server@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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';
11 import 'src/utils.dart'; 11 import 'src/utils.dart';
12 12
13 /// The error code for an error caused by a port already being in use.
14 final _addressInUseErrno = _computeAddressInUseErrno();
15 int _computeAddressInUseErrno() {
16 if (Platform.isWindows) return 10048;
17 if (Platform.isMacOS) return 48;
18 assert(Platform.isLinux);
19 return 98;
20 }
21
13 /// An implementation of `dart:io`'s [HttpServer] that wraps multiple servers 22 /// An implementation of `dart:io`'s [HttpServer] that wraps multiple servers
14 /// and forwards methods to all of them. 23 /// and forwards methods to all of them.
15 /// 24 ///
16 /// This is useful for serving the same application on multiple network 25 /// This is useful for serving the same application on multiple network
17 /// interfaces while still having a unified way of controlling the servers. In 26 /// interfaces while still having a unified way of controlling the servers. In
18 /// particular, it supports serving on both the IPv4 and IPv6 loopback addresses 27 /// particular, it supports serving on both the IPv4 and IPv6 loopback addresses
19 /// using [HttpMultiServer.loopback]. 28 /// using [HttpMultiServer.loopback].
20 class HttpMultiServer extends StreamView<HttpRequest> implements HttpServer { 29 class HttpMultiServer extends StreamView<HttpRequest> implements HttpServer {
21 /// The wrapped servers. 30 /// The wrapped servers.
22 final Set<HttpServer> _servers; 31 final Set<HttpServer> _servers;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 var supportsIpV6 = results[0]; 136 var supportsIpV6 = results[0];
128 var v4Server = results[1]; 137 var v4Server = results[1];
129 138
130 if (!supportsIpV6) return v4Server; 139 if (!supportsIpV6) return v4Server;
131 140
132 // Reuse the IPv4 server's port so that if [port] is 0, both servers use 141 // Reuse the IPv4 server's port so that if [port] is 0, both servers use
133 // the same ephemeral port. 142 // the same ephemeral port.
134 return bind(InternetAddress.LOOPBACK_IP_V6, v4Server.port) 143 return bind(InternetAddress.LOOPBACK_IP_V6, v4Server.port)
135 .then((v6Server) { 144 .then((v6Server) {
136 return new HttpMultiServer([v4Server, v6Server]); 145 return new HttpMultiServer([v4Server, v6Server]);
146 }).catchError((error) {
147 if (error is! SocketException) throw error;
148 if (error.osError.errno != _addressInUseErrno) throw error;
149 if (port != 0) throw error;
150
151 // 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),
153 // we try again until we find one that's available on both.
154 v4Server.close();
155 return _loopback(port, bind);
skybrian 2015/03/09 22:34:57 Retrying forever will cause the program to spin wh
nweiz 2015/03/09 23:38:15 https://codereview.chromium.org/992843002/
137 }); 156 });
138 }); 157 });
139 } 158 }
140 159
141 Future close({bool force: false}) => 160 Future close({bool force: false}) =>
142 Future.wait(_servers.map((server) => server.close(force: force))); 161 Future.wait(_servers.map((server) => server.close(force: force)));
143 162
144 /// Returns an HttpConnectionsInfo object summarizing the total number of 163 /// Returns an HttpConnectionsInfo object summarizing the total number of
145 /// current connections handled by all the servers. 164 /// current connections handled by all the servers.
146 HttpConnectionsInfo connectionsInfo() { 165 HttpConnectionsInfo connectionsInfo() {
147 var info = new HttpConnectionsInfo(); 166 var info = new HttpConnectionsInfo();
148 for (var server in _servers) { 167 for (var server in _servers) {
149 var subInfo = server.connectionsInfo(); 168 var subInfo = server.connectionsInfo();
150 info.total += subInfo.total; 169 info.total += subInfo.total;
151 info.active += subInfo.active; 170 info.active += subInfo.active;
152 info.idle += subInfo.idle; 171 info.idle += subInfo.idle;
153 info.closing += subInfo.closing; 172 info.closing += subInfo.closing;
154 } 173 }
155 return info; 174 return info;
156 } 175 }
157 } 176 }
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698