Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 } | |
| OLD | NEW |