Index: pkg/analysis_server/lib/src/channel.dart |
diff --git a/pkg/analysis_server/lib/src/channel.dart b/pkg/analysis_server/lib/src/channel.dart |
index 859a393f5640987c28a02bdb1904168444d71240..e9fc95d859b85d8d43737a17fe3ba4c2e51504c3 100644 |
--- a/pkg/analysis_server/lib/src/channel.dart |
+++ b/pkg/analysis_server/lib/src/channel.dart |
@@ -10,11 +10,35 @@ import 'dart:io'; |
import 'package:analysis_server/src/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. |
+ * The abstract class [ClientCommunicationChannel] defines the behavior of |
+ * objects that allows an object to send [Request]s to [AnalysisServer] and to |
+ * receive both [Response]s and [Notification]s. |
*/ |
-abstract class CommunicationChannel { |
+abstract class ClientCommunicationChannel { |
+ /** |
+ * Listen to the channel for responses and notifications. |
+ * If a response is received, invoke the [onResponse] function. |
+ * If a notification is received, invoke the [onNotification] 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 onResponse(Response response), |
+ void onNotification(Notification notification), |
+ {void onError(), void onDone()}); |
+ |
+ /** |
+ * Send the given [request] to the server. |
+ */ |
+ void sendRequest(Request request); |
+} |
+ |
+/** |
+ * The abstract class [ServerCommunicationChannel] defines the behavior of |
+ * objects that allow an [AnalysisServer] to receive [Request]s and to return |
+ * both [Response]s and [Notification]s. |
+ */ |
+abstract class ServerCommunicationChannel { |
/** |
* 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 |
@@ -29,21 +53,84 @@ abstract class CommunicationChannel { |
void sendNotification(Notification notification); |
/** |
- * Send the given [request] to the server. |
+ * Send the given [response] to the client. |
*/ |
- void sendRequest(Request request); |
+ void sendResponse(Response response); |
+} |
+/** |
+ * Instances of the class [WebSocketClientChannel] implement a |
+ * [ClientCommunicationChannel] that uses a [WebSocket] to communicate with |
+ * servers. |
+ */ |
+class WebSocketClientChannel implements ClientCommunicationChannel { |
/** |
- * Send the given [response] to the client. |
+ * The socket being wrapped. |
*/ |
- void sendResponse(Response response); |
+ final WebSocket socket; |
+ |
+ final JsonEncoder jsonEncoder = const JsonEncoder(null); |
+ |
+ final JsonDecoder jsonDecoder = const JsonDecoder(null); |
+ |
+ /** |
+ * Initialize a newly create [WebSocket] wrapper to wrap the given [socket]. |
+ */ |
+ WebSocketClientChannel(this.socket); |
+ |
+ @override |
+ void listen(void onResponse(Response response), |
+ void onNotification(Notification notification), |
+ {void onError(), void onDone()}) { |
+ socket.listen((data) => _read(data, onResponse, onNotification), |
+ onError: onError, onDone: onDone); |
+ } |
+ |
+ @override |
+ void sendRequest(Request request) { |
+ socket.add(jsonEncoder.convert(request.toJson())); |
+ } |
+ |
+ /** |
+ * Read a request from the given [data] and use the given function to handle |
+ * the request. |
+ */ |
+ void _read(Object data, |
+ void onResponse(Response response), |
+ void onNotification(Notification notification)) { |
+ if (data is String) { |
+ // Parse the string as a JSON descriptor |
+ var json; |
+ try { |
+ json = jsonDecoder.convert(data); |
+ if (json is! Map) { |
+ return; |
+ } |
+ } catch (error) { |
+ return; |
+ } |
+ // Process the resulting structure as a response or notification. |
+ if (json[Notification.EVENT] != null) { |
+ Notification notification = new Notification.fromJson(json); |
+ if (notification != null) { |
+ onNotification(notification); |
+ } |
+ } else { |
+ Response response = new Response.fromJson(json); |
+ if (response != null) { |
+ onResponse(response); |
+ } |
+ } |
+ } |
+ } |
} |
/** |
- * Instances of the class [WebSocketChannel] implement a [CommunicationChannel] |
- * that uses a [WebSocket] to communicate with clients. |
+ * Instances of the class [WebSocketServerChannel] implement a |
+ * [ServerCommunicationChannel] that uses a [WebSocket] to communicate with |
+ * clients. |
*/ |
-class WebSocketChannel implements CommunicationChannel { |
+class WebSocketServerChannel implements ServerCommunicationChannel { |
/** |
* The socket being wrapped. |
*/ |
@@ -54,12 +141,12 @@ class WebSocketChannel implements CommunicationChannel { |
/** |
* Initialize a newly create [WebSocket] wrapper to wrap the given [socket]. |
*/ |
- WebSocketChannel(this.socket); |
+ WebSocketServerChannel(this.socket); |
@override |
void listen(void onRequest(Request request), {void onError(), void onDone()}) { |
- socket.listen((data) => |
- _readRequest(data, onRequest), onError: onError, onDone: onDone); |
+ socket.listen((data) => _readRequest(data, onRequest), onError: onError, |
+ onDone: onDone); |
} |
@override |
@@ -68,11 +155,6 @@ class WebSocketChannel implements CommunicationChannel { |
} |
@override |
- void sendRequest(Request request) { |
- socket.add(jsonEncoder.convert(request.toJson())); |
- } |
- |
- @override |
void sendResponse(Response response) { |
socket.add(jsonEncoder.convert(response.toJson())); |
} |