| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library channel; |
| |
| import 'dart:async'; |
| import 'dart:convert'; |
| import 'dart:io'; |
| |
| import 'protocol.dart'; |
| |
| /** |
| * The abstract class [CommunicationChannel] defines the behavior of objects |
| * that allow an [AnalysisServer] to receive [Request]s and to return both |
| * [Response]s and [Notification]s. |
| */ |
| abstract class CommunicationChannel { |
| /** |
| * Listen to the channel for requests. If a request is received, invoke the |
| * [onRequest] function. If an error is encountered while trying to read from |
| * the socket, invoke the [onError] function. If the socket is closed by the |
| * client, invoke the [onDone] function. |
| */ |
| void listen(void onRequest(Request request), {void onError(), void onDone()}); |
| |
| /** |
| * Send the given [notification] to the client. |
| */ |
| void sendNotification(Notification notification); |
| |
| /** |
| * Send the given [response] to the client. |
| */ |
| void sendResponse(Response response); |
| } |
| |
| /** |
| * Instances of the class [WebSocketChannel] implement a [CommunicationChannel] |
| * that uses a [WebSocket] to communicate with clients. |
| */ |
| class WebSocketChannel implements CommunicationChannel { |
| /** |
| * The socket being wrapped. |
| */ |
| final WebSocket socket; |
| |
| /** |
| * Initialize a newly create [WebSocket] wrapper to wrap the given [socket]. |
| */ |
| WebSocketChannel(this.socket); |
| |
| @override |
| void listen(void onRequest(Request request), {void onError(), void onDone()}) { |
| socket.listen((data) => _readRequest(data, onRequest), onError: onError, onDone: onDone); |
| } |
| |
| @override |
| void sendNotification(Notification notification) { |
| JsonEncoder encoder = const JsonEncoder(null); |
| socket.add(encoder.convert(notification.toJson())); |
| } |
| |
| @override |
| void sendResponse(Response response) { |
| JsonEncoder encoder = const JsonEncoder(null); |
| socket.add(encoder.convert(response.toJson())); |
| } |
| |
| /** |
| * Read a request from the given [data] and use the given function to handle |
| * the request. |
| */ |
| void _readRequest(Object data, void onRequest(Request request)) { |
| if (data is List<int>) { |
| sendResponse(new Response.invalidRequestFormat()); |
| return; |
| } |
| if (data is String) { |
| // Parse the string as a JSON descriptor and process the resulting |
| // structure as a request. |
| Request request = new Request.fromString(data); |
| if (request == null) { |
| sendResponse(new Response.invalidRequestFormat()); |
| return; |
| } |
| onRequest(request); |
| } |
| } |
| } |