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