Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Side by Side Diff: runtime/bin/sync_socket_patch.dart

Issue 2803543006: Added synchronous socket implementation to dart:io. (Closed)
Patch Set: Small fix for MacOS Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
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.
4
5 @patch
6 class RawSynchronousSocket {
7 @patch
8 static RawSynchronousSocket connectSync(host, int port) {
9 return _RawSynchronousSocket.connectSync(host, port);
10 }
11 }
12
13 class _RawSynchronousSocket implements RawSynchronousSocket {
14 final _NativeSynchronousSocket _socket;
15
16 _RawSynchronousSocket(this._socket) {}
17
18 static RawSynchronousSocket connectSync(host, int port) {
19 _throwOnBadPort(port);
20 return new _RawSynchronousSocket(
21 _NativeSynchronousSocket.connectSync(host, port));
22 }
23
24 InternetAddress get address => _socket.address;
25 int get port => _socket.port;
26 InternetAddress get remoteAddress => _socket.remoteAddress;
27 int get remotePort => _socket.remotePort;
28
29 int available() => _socket.available;
30
31 void closeSync() => _socket.closeSync();
32
33 int readIntoSync(List<int> buffer, [int start = 0, int end]) =>
34 _socket.readIntoSync(buffer, start, end);
35
36 List<int> readSync(int bytes) => _socket.readSync(bytes);
37
38 void shutdown(SocketDirection direction) => _socket.shutdown(direction);
39
40 void writeFromSync(List<int> buffer, [int start = 0, int end]) =>
41 _socket.writeFromSync(buffer, start, end);
42 }
43
44 // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing
45 // implicit constructor.
46 class _NativeSynchronousSocketNativeWrapper extends NativeFieldWrapperClass1 {}
47
48 // The _NativeSynchronousSocket class encapsulates a synchronous OS socket.
49 class _NativeSynchronousSocket extends _NativeSynchronousSocketNativeWrapper {
50 // Socket close state.
51 bool isClosed = false;
52 bool isClosedRead = false;
53 bool isClosedWrite = false;
54
55 // Holds the address used to connect the socket.
56 InternetAddress localAddress;
57
58 // Holds the port of the socket, 0 if not known.
59 int localPort = 0;
60
61 _ReadWriteResourceInfo resourceInfo;
zra 2017/04/07 16:29:41 It looks like you need to call _SocketResourceInfo
bkonyi 2017/04/10 19:20:06 Added SocketClosed() call in CloseSync()
62
63 InternetAddress get address => localAddress;
64 int get available => nativeAvailable();
65
66 int get port {
67 if (localPort != 0) return localPort;
zra 2017/04/07 16:29:41 Please put single line ifs in {}
bkonyi 2017/04/10 19:20:06 Done.
68 if (isClosed) throw const SocketException.closed();
69 var result = nativeGetPort();
70 if (result is OSError) throw result;
71 return localPort = result;
72 }
73
74 InternetAddress get remoteAddress {
75 if (isClosed) throw const SocketException.closed();
76 var result = nativeGetRemotePeer();
77 if (result is OSError) throw result;
78 var addr = result[0];
79 var type = new InternetAddressType._from(addr[0]);
80 return new _InternetAddress(addr[1], null, addr[2]);
81 }
82
83 int get remotePort {
84 if (isClosed) throw const SocketException.closed();
85 var result = nativeGetRemotePeer();
86 if (result is OSError) throw result;
87 return result[1];
88 }
89
90 static _NativeSynchronousSocket connectSync(host, int port) {
zra 2017/04/07 16:29:41 statics like this that generate an instance I thin
bkonyi 2017/04/10 19:20:06 Ah, I wasn't sure where static methods like this s
91 List<_InternetAddress> addresses = null;
92 var error = null;
93 if (host is _InternetAddress) {
94 addresses = [host];
95 } else {
96 try {
97 addresses = lookup(host);
98 } catch (e) {
99 error = e;
100 }
101 if (error != null || addresses == null || addresses.isEmpty) {
102 throw createError(error, "Failed host lookup: '$host'");
103 }
104 }
105 assert(addresses is List);
106 var it = addresses.iterator;
107 _NativeSynchronousSocket connectNext() {
108 if (!it.moveNext()) {
109 // Could not connect. Throw the first connection error we encountered.
110 assert(error != null);
111 throw error;
112 }
113 var address = it.current;
114 var socket = new _NativeSynchronousSocket();
115 socket.localAddress = address;
116 var result = socket.nativeCreateConnectSync(address._in_addr, port);
117 if (result is OSError) {
118 // Keep first error, if present.
119 if (error == null) {
120 int errorCode = result.errorCode;
zra 2017/04/07 16:29:40 errorCode doesn't appear to be used.
bkonyi 2017/04/10 19:20:06 Removed.
121 error = createError(result, "Connection failed", address, port);
122 }
123 return connectNext();
124 } else {
125 // Query the local port, for error messages.
126 try {
127 socket.port;
128 } catch (e) {
129 error = createError(e, "Connection failed", address, port);
zra 2017/04/07 16:29:41 if (error == null)
bkonyi 2017/04/10 19:20:05 Done.
130 return connectNext();
131 }
132 setupResourceInfo(socket);
133 }
134 return socket;
135 }
136
137 return connectNext();
138 }
139
140 void closeSync() {
141 if (!isClosed) {
142 nativeCloseSync();
143 isClosed = true;
144 }
145 }
146
147 // Create the appropriate error/exception from different returned
148 // error objects.
149 static createError(error, String message,
150 [InternetAddress address, int port]) {
151 if (error is OSError) {
152 return new SocketException(message,
153 osError: error, address: address, port: port);
154 } else {
155 return new SocketException(message, address: address, port: port);
156 }
157 }
158
159 static List<InternetAddress> lookup(String host,
160 {InternetAddressType type: InternetAddressType.ANY}) {
161 var response = nativeLookupRequest(host, type._value);
162 if (response is OSError) {
163 throw response;
164 }
165 // TODO(bkonyi) do we need this first empty element? Or is this something sp ecific
zra 2017/04/07 16:29:41 I don't see what this is used for either. Let's ge
bkonyi 2017/04/10 19:20:06 Done.
166 // for io_service?
167 return response.skip(1).map((result) {
168 var type = new InternetAddressType._from(result[0]);
169 return new _InternetAddress(result[1], host, result[2]);
170 }).toList();
171 }
172
173 int readIntoSync(List<int> buffer, int start, int end) {
zra 2017/04/07 16:29:40 This shouldn't be implemented on top of readSync.
bkonyi 2017/04/10 19:20:06 Done.
174 if (buffer == null) {
175 throw new ArgumentError("Illegal buffer: buffer cannot be null");
176 }
177 if (start != null && ((start >= buffer.length) || (start < 0))) {
178 throw new ArgumentError("Illegal start $start");
179 }
180 if ((start != null && end != null) &&
181 ((start > end) || (end > buffer.length))) {
182 throw new ArgumentError("Illegal range [$start, $end)");
183 }
184 int len = 0;
185 if (start == null) {
186 start = 0;
187 len = buffer.length;
188 } else if (end == null) {
189 len = buffer.length - start;
190 } else {
191 len = end - start;
192 }
193 List<int> result = readSync(len);
194 len = min(result.length, len);
195
196 for (int i = start; i < start + len; i++) {
197 buffer[i] = result[i - start];
198 }
199 return result.length;
200 }
201
202 List<int> readSync(int len) {
203 if (len != null && len <= 0) {
204 throw new ArgumentError("Illegal length $len");
205 }
206 if (isClosed) return null;
207 if (len == 0) return null;
208 var result = nativeRead(len);
209 if (result is OSError) {
210 throw result;
211 return null;
212 }
213 if (result != null) {
214 assert(resourceInfo != null);
215 if (resourceInfo != null) {
216 resourceInfo.totalRead += result.length;
217 }
218 }
219 assert(resourceInfo != null);
zra 2017/04/07 16:29:41 If you move this assert above if (result != null)
bkonyi 2017/04/10 19:20:06 Done.
220 if (resourceInfo != null) {
221 resourceInfo.didRead();
222 }
223 return result;
224 }
225
226 static void setupResourceInfo(_NativeSynchronousSocket socket) {
227 socket.resourceInfo = new _SocketResourceInfo(socket);
228 }
229
230 void shutdown(SocketDirection direction) {
231 if (!isClosed) {
zra 2017/04/07 16:29:41 if (isClosed) return then un-indent, here and bel
bkonyi 2017/04/10 19:20:06 Done.
232 switch (direction) {
233 case SocketDirection.RECEIVE:
234 shutdownRead();
235 break;
236 case SocketDirection.SEND:
237 shutdownWrite();
238 break;
239 case SocketDirection.BOTH:
240 closeSync();
241 break;
242 default:
243 throw new ArgumentError(direction);
244 }
245 }
246 }
247
248 void shutdownRead() {
249 if (!isClosed) {
250 if (isClosedWrite) {
251 closeSync();
252 } else {
253 nativeShutdownRead();
zra 2017/04/07 16:29:41 What if isClosedRead is already true?
bkonyi 2017/04/10 19:20:05 Then the native shutdown read method would be call
254 }
255 isClosedRead = true;
256 }
257 }
258
259 void shutdownWrite() {
260 if (!isClosed) {
261 if (isClosedRead) {
262 closeSync();
263 } else {
264 nativeShutdownWrite();
265 }
266 isClosedWrite = true;
267 }
268 }
269
270 void writeFromSync(List<int> buffer, int start, int end) {
zra 2017/04/07 16:29:41 Have a look at _RandomAccessFile.writeFromSync for
bkonyi 2017/04/10 19:20:05 Done.
271 if (isClosed) return;
272 int offset = start;
273 int bytes = null;
274 if (buffer is! List) throw new ArgumentError();
zra 2017/04/07 16:29:41 Please give an error message.
bkonyi 2017/04/10 19:20:06 Acknowledged.
275 if (offset == null) offset = 0;
276 if (end == null) {
zra 2017/04/07 16:29:41 Can you use RangeError.checkValidRange()?
bkonyi 2017/04/10 19:20:06 I didn't know that existed... super useful! Done.
277 if (offset > (buffer.length)) {
278 throw new RangeError.value(offset);
279 }
280 bytes = buffer.length - offset;
281 } else {
282 bytes = end - offset;
283 }
284 if (offset is! int || bytes is! int) {
zra 2017/04/07 16:29:40 This should probably be up at the top of the funct
bkonyi 2017/04/10 19:20:06 Acknowledged.
285 throw new ArgumentError("Invalid arguments to write on Socket");
286 }
287 if (bytes == 0) return;
288 if (offset < 0) throw new RangeError.value(offset);
289 if (bytes < 0) throw new RangeError.value(bytes);
290 if ((offset + bytes) > buffer.length) {
291 throw new RangeError.value(offset + bytes);
292 }
293 _BufferAndStart bufferAndStart =
294 _ensureFastAndSerializableByteData(buffer, offset, offset + bytes);
295 var result =
296 nativeWrite(bufferAndStart.buffer, bufferAndStart.start, bytes);
297 if (result is OSError) {
298 throw result;
299 }
300 // TODO(bkonyi) we don't currently handle short writes or reads.
301 // The result may be negative, if we forced a short write for testing
302 // purposes. Negate the result to get the actual number of bytes written.
303 if (result < 0) result = -result;
zra 2017/04/07 16:29:41 Let's remove this logic if it isn't supported.
bkonyi 2017/04/10 19:20:05 Done.
304 assert(resourceInfo != null);
305 if (resourceInfo != null) {
306 resourceInfo.addWrite(result);
307 }
308 }
309
310 // Native method declarations.
311 static nativeLookupRequest(host, int type)
312 native "SynchronousSocket_LookupRequest";
313 nativeCreateConnectSync(host, int port)
314 native "SynchronousSocket_CreateConnectSync";
315 nativeAvailable() native "SynchronousSocket_Available";
316 nativeCloseSync() native "SynchronousSocket_CloseSync";
317 int nativeGetPort() native "SynchronousSocket_GetPort";
318 List nativeGetRemotePeer() native "SynchronousSocket_GetRemotePeer";
319 nativeRead(int len) native "SynchronousSocket_Read";
320 nativeShutdownRead() native "SynchronousSocket_ShutdownRead";
321 nativeShutdownWrite() native "SynchronousSocket_ShutdownWrite";
322 nativeWrite(List<int> buffer, int offset, int bytes)
323 native "SynchronousSocket_WriteList";
324 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698