OLD | NEW |
1 // Copyright (c) 2016 the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016 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 http2.multiprotocol_server; | 5 library http2.multiprotocol_server; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 | 9 |
10 import 'package:http2/transport.dart' as http2; | 10 import 'package:http2/transport.dart' as http2; |
11 | 11 |
12 import 'src/artificial_server_socket.dart'; | 12 import 'src/artificial_server_socket.dart'; |
13 | 13 |
14 /// Handles protocol negotiation with HTTP/1.1 and HTTP/2 clients. | 14 /// Handles protocol negotiation with HTTP/1.1 and HTTP/2 clients. |
15 /// | 15 /// |
16 /// Given a (host, port) pair and a [SecurityContext], [MultiProtocolHttpServer] | 16 /// Given a (host, port) pair and a [SecurityContext], [MultiProtocolHttpServer] |
17 /// will negotiate with the client whether HTTP/1.1 or HTTP/2 should be spoken. | 17 /// will negotiate with the client whether HTTP/1.1 or HTTP/2 should be spoken. |
18 /// | 18 /// |
19 /// The user must supply 2 callback functions to [startServing], which: | 19 /// The user must supply 2 callback functions to [startServing], which: |
20 /// * one handles HTTP/1.1 clients (called with a [HttpRequest]) | 20 /// * one handles HTTP/1.1 clients (called with a [HttpRequest]) |
21 /// * one handles HTTP/2 clients (called with a [http2.ServerTransportStream]) | 21 /// * one handles HTTP/2 clients (called with a [http2.ServerTransportStream]) |
22 class MultiProtocolHttpServer { | 22 class MultiProtocolHttpServer { |
23 final SecureServerSocket _serverSocket; | 23 final SecureServerSocket _serverSocket; |
| 24 final http2.ServerSettings _settings; |
24 | 25 |
25 _ServerSocketController _http11Controller; | 26 _ServerSocketController _http11Controller; |
26 HttpServer _http11Server; | 27 HttpServer _http11Server; |
27 | 28 |
28 StreamController<http2.ServerTransportStream> _http2Controller; | 29 StreamController<http2.ServerTransportStream> _http2Controller; |
29 Stream<http2.ServerTransportStream> _http2Server; | 30 Stream<http2.ServerTransportStream> _http2Server; |
30 Set<http2.ServerTransportConnection> _http2Connections = new Set(); | 31 Set<http2.ServerTransportConnection> _http2Connections = new Set(); |
31 | 32 |
32 MultiProtocolHttpServer._(this._serverSocket) { | 33 MultiProtocolHttpServer._(this._serverSocket, this._settings) { |
33 _http11Controller = new _ServerSocketController( | 34 _http11Controller = new _ServerSocketController( |
34 _serverSocket.address, _serverSocket.port); | 35 _serverSocket.address, _serverSocket.port); |
35 _http11Server = new HttpServer.listenOn(_http11Controller.stream); | 36 _http11Server = new HttpServer.listenOn(_http11Controller.stream); |
36 | 37 |
37 _http2Controller = new StreamController(); | 38 _http2Controller = new StreamController(); |
38 _http2Server = _http2Controller.stream; | 39 _http2Server = _http2Controller.stream; |
39 } | 40 } |
40 | 41 |
41 /// Binds a new [SecureServerSocket] with a security [context] at [port] and | 42 /// Binds a new [SecureServerSocket] with a security [context] at [port] and |
42 /// [address] (see [SecureServerSocket.bind] for a description of supported | 43 /// [address] (see [SecureServerSocket.bind] for a description of supported |
43 /// types for [address]). | 44 /// types for [address]). |
44 /// | 45 /// |
| 46 /// Optionally [settings] can be supplied which will be used for HTTP/2 |
| 47 /// clients. |
| 48 /// |
45 /// See also [startServing]. | 49 /// See also [startServing]. |
46 static Future<MultiProtocolHttpServer> bind(address, | 50 static Future<MultiProtocolHttpServer> bind( |
47 int port, | 51 address, int port, SecurityContext context, |
48 SecurityContext context) async { | 52 {http2.ServerSettings settings}) async { |
49 context.setAlpnProtocols(['h2', 'http/1.1'], true); | 53 context.setAlpnProtocols(['h2', 'http/1.1'], true); |
50 var secureServer = await SecureServerSocket.bind(address, port, context); | 54 var secureServer = await SecureServerSocket.bind(address, port, context); |
51 return new MultiProtocolHttpServer._(secureServer); | 55 return new MultiProtocolHttpServer._(secureServer, settings); |
52 } | 56 } |
53 | 57 |
54 /// The port this multi-protocol HTTP server runs on. | 58 /// The port this multi-protocol HTTP server runs on. |
55 int get port => _serverSocket.port; | 59 int get port => _serverSocket.port; |
56 | 60 |
57 /// The address this multi-protocol HTTP server runs on. | 61 /// The address this multi-protocol HTTP server runs on. |
58 InternetAddress get address => _serverSocket.address; | 62 InternetAddress get address => _serverSocket.address; |
59 | 63 |
60 /// Starts listening for HTTP/1.1 and HTTP/2 clients and calls the given | 64 /// Starts listening for HTTP/1.1 and HTTP/2 clients and calls the given |
61 /// callbacks for new clients. | 65 /// callbacks for new clients. |
62 /// | 66 /// |
63 /// It is expected that [callbackHttp11] and [callbackHttp2] will never throw | 67 /// It is expected that [callbackHttp11] and [callbackHttp2] will never throw |
64 /// an exception (i.e. these must take care of error handling themselves). | 68 /// an exception (i.e. these must take care of error handling themselves). |
65 void startServing(void callbackHttp11(HttpRequest request), | 69 void startServing(void callbackHttp11(HttpRequest request), |
66 void callbackHttp2(http2.ServerTransportStream stream), | 70 void callbackHttp2(http2.ServerTransportStream stream), |
67 {void onError(error, stack)}) { | 71 {void onError(error, stack)}) { |
68 // 1. Start listening on the real [SecureServerSocket]. | 72 // 1. Start listening on the real [SecureServerSocket]. |
69 _serverSocket.listen((SecureSocket socket) { | 73 _serverSocket.listen((SecureSocket socket) { |
70 var protocol = socket.selectedProtocol; | 74 var protocol = socket.selectedProtocol; |
71 if (protocol == null || protocol == 'http/1.1') { | 75 if (protocol == null || protocol == 'http/1.1') { |
72 _http11Controller.addHttp11Socket(socket); | 76 _http11Controller.addHttp11Socket(socket); |
73 } else if (protocol == 'h2') { | 77 } else if (protocol == 'h2') { |
74 var connection = new http2.ServerTransportConnection.viaSocket(socket); | 78 var connection = new http2.ServerTransportConnection.viaSocket( |
| 79 socket, settings: _settings); |
75 _http2Connections.add(connection); | 80 _http2Connections.add(connection); |
76 connection.incomingStreams.listen( | 81 connection.incomingStreams.listen( |
77 _http2Controller.add, | 82 _http2Controller.add, |
78 onError: onError, | 83 onError: onError, |
79 onDone: () => _http2Connections.remove(connection)); | 84 onDone: () => _http2Connections.remove(connection)); |
80 } else { | 85 } else { |
81 socket.destroy(); | 86 socket.destroy(); |
82 throw new Exception( | 87 throw new Exception( |
83 "Unexpected negotiated ALPN protocol: $protocol."); | 88 "Unexpected negotiated ALPN protocol: $protocol."); |
84 } | 89 } |
(...skipping 29 matching lines...) Expand all Loading... |
114 ArtificialServerSocket get stream { | 119 ArtificialServerSocket get stream { |
115 return new ArtificialServerSocket(address, port, _controller.stream); | 120 return new ArtificialServerSocket(address, port, _controller.stream); |
116 } | 121 } |
117 | 122 |
118 void addHttp11Socket(Socket socket) { | 123 void addHttp11Socket(Socket socket) { |
119 _controller.add(socket); | 124 _controller.add(socket); |
120 } | 125 } |
121 | 126 |
122 Future close() => _controller.close(); | 127 Future close() => _controller.close(); |
123 } | 128 } |
OLD | NEW |