OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 channel; | 5 library channel; |
6 | 6 |
7 import 'dart:convert'; | 7 import 'dart:convert'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 | 9 |
10 import 'package:analysis_server/src/protocol.dart'; | 10 import 'package:analysis_server/src/protocol.dart'; |
11 | 11 |
12 /** | 12 /** |
13 * The abstract class [CommunicationChannel] defines the behavior of objects | 13 * The abstract class [ClientCommunicationChannel] defines the behavior of |
14 * that allow an [AnalysisServer] to receive [Request]s and to return both | 14 * objects that allows an object to send [Request]s to [AnalysisServer] and to |
15 * [Response]s and [Notification]s. | 15 * receive both [Response]s and [Notification]s. |
16 */ | 16 */ |
17 abstract class CommunicationChannel { | 17 abstract class ClientCommunicationChannel { |
| 18 /** |
| 19 * Listen to the channel for responses and notifications. |
| 20 * If a response is received, invoke the [onResponse] function. |
| 21 * If a notification is received, invoke the [onNotification] function. |
| 22 * If an error is encountered while trying to read from |
| 23 * the socket, invoke the [onError] function. If the socket is closed by the |
| 24 * client, invoke the [onDone] function. |
| 25 */ |
| 26 void listen(void onResponse(Response response), |
| 27 void onNotification(Notification notification), |
| 28 {void onError(), void onDone()}); |
| 29 |
| 30 /** |
| 31 * Send the given [request] to the server. |
| 32 */ |
| 33 void sendRequest(Request request); |
| 34 } |
| 35 |
| 36 /** |
| 37 * The abstract class [ServerCommunicationChannel] defines the behavior of |
| 38 * objects that allow an [AnalysisServer] to receive [Request]s and to return |
| 39 * both [Response]s and [Notification]s. |
| 40 */ |
| 41 abstract class ServerCommunicationChannel { |
18 /** | 42 /** |
19 * Listen to the channel for requests. If a request is received, invoke the | 43 * Listen to the channel for requests. If a request is received, invoke the |
20 * [onRequest] function. If an error is encountered while trying to read from | 44 * [onRequest] function. If an error is encountered while trying to read from |
21 * the socket, invoke the [onError] function. If the socket is closed by the | 45 * the socket, invoke the [onError] function. If the socket is closed by the |
22 * client, invoke the [onDone] function. | 46 * client, invoke the [onDone] function. |
23 */ | 47 */ |
24 void listen(void onRequest(Request request), {void onError(), void onDone()}); | 48 void listen(void onRequest(Request request), {void onError(), void onDone()}); |
25 | 49 |
26 /** | 50 /** |
27 * Send the given [notification] to the client. | 51 * Send the given [notification] to the client. |
28 */ | 52 */ |
29 void sendNotification(Notification notification); | 53 void sendNotification(Notification notification); |
30 | 54 |
31 /** | 55 /** |
32 * Send the given [request] to the server. | |
33 */ | |
34 void sendRequest(Request request); | |
35 | |
36 /** | |
37 * Send the given [response] to the client. | 56 * Send the given [response] to the client. |
38 */ | 57 */ |
39 void sendResponse(Response response); | 58 void sendResponse(Response response); |
40 } | 59 } |
41 | 60 |
42 /** | 61 /** |
43 * Instances of the class [WebSocketChannel] implement a [CommunicationChannel] | 62 * Instances of the class [WebSocketClientChannel] implement a |
44 * that uses a [WebSocket] to communicate with clients. | 63 * [ClientCommunicationChannel] that uses a [WebSocket] to communicate with |
| 64 * servers. |
45 */ | 65 */ |
46 class WebSocketChannel implements CommunicationChannel { | 66 class WebSocketClientChannel implements ClientCommunicationChannel { |
47 /** | 67 /** |
48 * The socket being wrapped. | 68 * The socket being wrapped. |
49 */ | 69 */ |
| 70 final WebSocket socket; |
| 71 |
| 72 final JsonEncoder jsonEncoder = const JsonEncoder(null); |
| 73 |
| 74 final JsonDecoder jsonDecoder = const JsonDecoder(null); |
| 75 |
| 76 /** |
| 77 * Initialize a newly create [WebSocket] wrapper to wrap the given [socket]. |
| 78 */ |
| 79 WebSocketClientChannel(this.socket); |
| 80 |
| 81 @override |
| 82 void listen(void onResponse(Response response), |
| 83 void onNotification(Notification notification), |
| 84 {void onError(), void onDone()}) { |
| 85 socket.listen((data) => _read(data, onResponse, onNotification), |
| 86 onError: onError, onDone: onDone); |
| 87 } |
| 88 |
| 89 @override |
| 90 void sendRequest(Request request) { |
| 91 socket.add(jsonEncoder.convert(request.toJson())); |
| 92 } |
| 93 |
| 94 /** |
| 95 * Read a request from the given [data] and use the given function to handle |
| 96 * the request. |
| 97 */ |
| 98 void _read(Object data, |
| 99 void onResponse(Response response), |
| 100 void onNotification(Notification notification)) { |
| 101 if (data is String) { |
| 102 // Parse the string as a JSON descriptor |
| 103 var json; |
| 104 try { |
| 105 json = jsonDecoder.convert(data); |
| 106 if (json is! Map) { |
| 107 return; |
| 108 } |
| 109 } catch (error) { |
| 110 return; |
| 111 } |
| 112 // Process the resulting structure as a response or notification. |
| 113 if (json[Notification.EVENT] != null) { |
| 114 Notification notification = new Notification.fromJson(json); |
| 115 if (notification != null) { |
| 116 onNotification(notification); |
| 117 } |
| 118 } else { |
| 119 Response response = new Response.fromJson(json); |
| 120 if (response != null) { |
| 121 onResponse(response); |
| 122 } |
| 123 } |
| 124 } |
| 125 } |
| 126 } |
| 127 |
| 128 /** |
| 129 * Instances of the class [WebSocketServerChannel] implement a |
| 130 * [ServerCommunicationChannel] that uses a [WebSocket] to communicate with |
| 131 * clients. |
| 132 */ |
| 133 class WebSocketServerChannel implements ServerCommunicationChannel { |
| 134 /** |
| 135 * The socket being wrapped. |
| 136 */ |
50 final WebSocket socket; | 137 final WebSocket socket; |
51 | 138 |
52 final JsonEncoder jsonEncoder = const JsonEncoder(null); | 139 final JsonEncoder jsonEncoder = const JsonEncoder(null); |
53 | 140 |
54 /** | 141 /** |
55 * Initialize a newly create [WebSocket] wrapper to wrap the given [socket]. | 142 * Initialize a newly create [WebSocket] wrapper to wrap the given [socket]. |
56 */ | 143 */ |
57 WebSocketChannel(this.socket); | 144 WebSocketServerChannel(this.socket); |
58 | 145 |
59 @override | 146 @override |
60 void listen(void onRequest(Request request), {void onError(), void onDone()})
{ | 147 void listen(void onRequest(Request request), {void onError(), void onDone()})
{ |
61 socket.listen((data) => | 148 socket.listen((data) => _readRequest(data, onRequest), onError: onError, |
62 _readRequest(data, onRequest), onError: onError, onDone: onDone); | 149 onDone: onDone); |
63 } | 150 } |
64 | 151 |
65 @override | 152 @override |
66 void sendNotification(Notification notification) { | 153 void sendNotification(Notification notification) { |
67 socket.add(jsonEncoder.convert(notification.toJson())); | 154 socket.add(jsonEncoder.convert(notification.toJson())); |
68 } | 155 } |
69 | 156 |
70 @override | 157 @override |
71 void sendRequest(Request request) { | |
72 socket.add(jsonEncoder.convert(request.toJson())); | |
73 } | |
74 | |
75 @override | |
76 void sendResponse(Response response) { | 158 void sendResponse(Response response) { |
77 socket.add(jsonEncoder.convert(response.toJson())); | 159 socket.add(jsonEncoder.convert(response.toJson())); |
78 } | 160 } |
79 | 161 |
80 /** | 162 /** |
81 * Read a request from the given [data] and use the given function to handle | 163 * Read a request from the given [data] and use the given function to handle |
82 * the request. | 164 * the request. |
83 */ | 165 */ |
84 void _readRequest(Object data, void onRequest(Request request)) { | 166 void _readRequest(Object data, void onRequest(Request request)) { |
85 if (data is List<int>) { | 167 if (data is List<int>) { |
86 sendResponse(new Response.invalidRequestFormat()); | 168 sendResponse(new Response.invalidRequestFormat()); |
87 return; | 169 return; |
88 } | 170 } |
89 if (data is String) { | 171 if (data is String) { |
90 // Parse the string as a JSON descriptor and process the resulting | 172 // Parse the string as a JSON descriptor and process the resulting |
91 // structure as a request. | 173 // structure as a request. |
92 Request request = new Request.fromString(data); | 174 Request request = new Request.fromString(data); |
93 if (request == null) { | 175 if (request == null) { |
94 sendResponse(new Response.invalidRequestFormat()); | 176 sendResponse(new Response.invalidRequestFormat()); |
95 return; | 177 return; |
96 } | 178 } |
97 onRequest(request); | 179 onRequest(request); |
98 } | 180 } |
99 } | 181 } |
100 } | 182 } |
OLD | NEW |