| 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 |