OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 | 5 |
6 class _SocketBase { | 6 class _SocketBase { |
7 // Bit flags used when communicating between the eventhandler and | 7 // Bit flags used when communicating between the eventhandler and |
8 // dart code. The EVENT flags are used to indicate events of | 8 // dart code. The EVENT flags are used to indicate events of |
9 // interest when sending a message from dart code to the | 9 // interest when sending a message from dart code to the |
10 // eventhandler. When receiving a message from the eventhandler the | 10 // eventhandler. When receiving a message from the eventhandler the |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 if (eventHandler != null) { | 57 if (eventHandler != null) { |
58 // Unregister the out handler before executing it. | 58 // Unregister the out handler before executing it. |
59 if (i == _OUT_EVENT) _setHandler(i, null); | 59 if (i == _OUT_EVENT) _setHandler(i, null); |
60 | 60 |
61 // Don't call the in handler if there is no data available | 61 // Don't call the in handler if there is no data available |
62 // after all. | 62 // after all. |
63 if ((i == _IN_EVENT) && (this is _Socket) && (available() == 0)) { | 63 if ((i == _IN_EVENT) && (this is _Socket) && (available() == 0)) { |
64 continue; | 64 continue; |
65 } | 65 } |
66 if (i == _ERROR_EVENT) { | 66 if (i == _ERROR_EVENT) { |
67 eventHandler(new SocketIOException("")); | 67 eventHandler(new SocketIOException("", _getError())); |
68 close(); | 68 close(); |
69 } else { | 69 } else { |
70 eventHandler(); | 70 eventHandler(); |
71 } | 71 } |
72 } | 72 } |
73 } | 73 } |
74 } | 74 } |
75 _canActivateHandlers = true; | 75 _canActivateHandlers = true; |
76 _activateHandlers(); | 76 _activateHandlers(); |
77 } | 77 } |
(...skipping 11 matching lines...) Expand all Loading... |
89 _closedRead && | 89 _closedRead && |
90 _handlerMask == 0 && | 90 _handlerMask == 0 && |
91 _handler != null) { | 91 _handler != null) { |
92 _handler.close(); | 92 _handler.close(); |
93 _handler = null; | 93 _handler = null; |
94 } else { | 94 } else { |
95 _activateHandlers(); | 95 _activateHandlers(); |
96 } | 96 } |
97 } | 97 } |
98 | 98 |
| 99 OSError _getError() native "Socket_GetError"; |
99 int _getPort() native "Socket_GetPort"; | 100 int _getPort() native "Socket_GetPort"; |
100 | 101 |
101 void set onError(void callback(Exception e)) { | 102 void set onError(void callback(Exception e)) { |
102 _setHandler(_ERROR_EVENT, callback); | 103 _setHandler(_ERROR_EVENT, callback); |
103 } | 104 } |
104 | 105 |
105 void _activateHandlers() { | 106 void _activateHandlers() { |
106 if (_canActivateHandlers && (_id >= 0)) { | 107 if (_canActivateHandlers && (_id >= 0)) { |
107 if (_handlerMask == 0) { | 108 if (_handlerMask == 0) { |
108 if (_handler != null) { | 109 if (_handler != null) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 | 179 |
179 void _sendToEventHandler(int data) { | 180 void _sendToEventHandler(int data) { |
180 if (_handler === null) { | 181 if (_handler === null) { |
181 _handler = new ReceivePort(); | 182 _handler = new ReceivePort(); |
182 _handler.receive((var message, ignored) { _multiplex(message); }); | 183 _handler.receive((var message, ignored) { _multiplex(message); }); |
183 } | 184 } |
184 assert(_id >= 0); | 185 assert(_id >= 0); |
185 _EventHandler._sendData(_id, _handler, data); | 186 _EventHandler._sendData(_id, _handler, data); |
186 } | 187 } |
187 | 188 |
| 189 bool _reportError(error, String message) { |
| 190 // For all errors we close the socket, call the error handler and |
| 191 // disable further calls of the error handler. |
| 192 close(); |
| 193 var onError = _handlerMap[_ERROR_EVENT]; |
| 194 if (onError != null) { |
| 195 if (error is OSError) { |
| 196 onError(new SocketIOException(message, error)); |
| 197 } else if (error is List) { |
| 198 assert(_isErrorResponse(error)); |
| 199 switch (error[0]) { |
| 200 case _FileUtils.kIllegalArgumentResponse: |
| 201 onError(new IllegalArgumentException()); |
| 202 break; |
| 203 case _FileUtils.kOSErrorResponse: |
| 204 onError(new SocketIOException( |
| 205 message, new OSError(error[2], error[1]))); |
| 206 break; |
| 207 default: |
| 208 onError(new Exception("Unknown error")); |
| 209 break; |
| 210 } |
| 211 } else { |
| 212 onError(new SocketIOException(message)); |
| 213 } |
| 214 } |
| 215 } |
| 216 |
188 int hashCode() => _hashCode; | 217 int hashCode() => _hashCode; |
189 | 218 |
190 abstract bool _isListenSocket(); | 219 abstract bool _isListenSocket(); |
191 abstract bool _isPipe(); | 220 abstract bool _isPipe(); |
192 | 221 |
193 // Socket id is set from native. -1 indicates that the socket was closed. | 222 // Socket id is set from native. -1 indicates that the socket was closed. |
194 int _id; | 223 int _id; |
195 | 224 |
196 // Dedicated ReceivePort for socket events. | 225 // Dedicated ReceivePort for socket events. |
197 ReceivePort _handler; | 226 ReceivePort _handler; |
(...skipping 19 matching lines...) Expand all Loading... |
217 | 246 |
218 | 247 |
219 class _ServerSocket extends _SocketBase implements ServerSocket { | 248 class _ServerSocket extends _SocketBase implements ServerSocket { |
220 // Constructor for server socket. First a socket object is allocated | 249 // Constructor for server socket. First a socket object is allocated |
221 // in which the native socket is stored. After that _createBind | 250 // in which the native socket is stored. After that _createBind |
222 // is called which creates a file descriptor and binds the given address | 251 // is called which creates a file descriptor and binds the given address |
223 // and port to the socket. Null is returned if file descriptor creation or | 252 // and port to the socket. Null is returned if file descriptor creation or |
224 // bind failed. | 253 // bind failed. |
225 factory _ServerSocket(String bindAddress, int port, int backlog) { | 254 factory _ServerSocket(String bindAddress, int port, int backlog) { |
226 _ServerSocket socket = new _ServerSocket._internal(); | 255 _ServerSocket socket = new _ServerSocket._internal(); |
227 if (!socket._createBindListen(bindAddress, port, backlog)) { | 256 var result = socket._createBindListen(bindAddress, port, backlog); |
| 257 if (result is OSError) { |
228 socket.close(); | 258 socket.close(); |
229 return null; | 259 throw new SocketIOException("Failed to create server socket", result); |
230 } | 260 } |
| 261 assert(result); |
231 if (port != 0) { | 262 if (port != 0) { |
232 socket._port = port; | 263 socket._port = port; |
233 } | 264 } |
234 return socket; | 265 return socket; |
235 } | 266 } |
236 | 267 |
237 _ServerSocket._internal(); | 268 _ServerSocket._internal(); |
238 | 269 |
239 bool _accept(Socket socket) native "ServerSocket_Accept"; | 270 bool _accept(Socket socket) native "ServerSocket_Accept"; |
240 | 271 |
241 bool _createBindListen(String bindAddress, int port, int backlog) | 272 bool _createBindListen(String bindAddress, int port, int backlog) |
242 native "ServerSocket_CreateBindListen"; | 273 native "ServerSocket_CreateBindListen"; |
243 | 274 |
244 void set onConnection(void callback(Socket connection)) { | 275 void set onConnection(void callback(Socket connection)) { |
245 _clientConnectionHandler = callback; | 276 _clientConnectionHandler = callback; |
246 _setHandler(_IN_EVENT, | 277 _setHandler(_IN_EVENT, |
247 _clientConnectionHandler != null ? _connectionHandler : null); | 278 _clientConnectionHandler != null ? _connectionHandler : null); |
248 } | 279 } |
249 | 280 |
250 void _connectionHandler() { | 281 void _connectionHandler() { |
251 if (_id >= 0) { | 282 if (_id >= 0) { |
252 _Socket socket = new _Socket._internal(); | 283 _Socket socket = new _Socket._internal(); |
253 if (_accept(socket)) _clientConnectionHandler(socket); | 284 var result = _accept(socket); |
| 285 if (result is OSError) { |
| 286 _reportError(result, "Accept failed"); |
| 287 } else { |
| 288 _clientConnectionHandler(socket); |
| 289 } |
254 } | 290 } |
255 } | 291 } |
256 | 292 |
257 bool _isListenSocket() => true; | 293 bool _isListenSocket() => true; |
258 bool _isPipe() => false; | 294 bool _isPipe() => false; |
259 | 295 |
260 var _clientConnectionHandler; | 296 var _clientConnectionHandler; |
261 } | 297 } |
262 | 298 |
263 | 299 |
264 class _Socket extends _SocketBase implements Socket { | 300 class _Socket extends _SocketBase implements Socket { |
265 static final kSuccessResponse = 0; | 301 static final kSuccessResponse = 0; |
266 static final kIllegalArgumentResponse = 1; | 302 static final kIllegalArgumentResponse = 1; |
267 static final kOSErrorResponse = 2; | 303 static final kOSErrorResponse = 2; |
268 | 304 |
269 static final kHostNameLookup = 0; | 305 static final kHostNameLookup = 0; |
270 | 306 |
271 // Constructs a new socket. During the construction an asynchronous | 307 // Constructs a new socket. During the construction an asynchronous |
272 // host name lookup is initiated. The returned socket is not yet | 308 // host name lookup is initiated. The returned socket is not yet |
273 // connected but ready for registration of callbacks. | 309 // connected but ready for registration of callbacks. |
274 factory _Socket(String host, int port) { | 310 factory _Socket(String host, int port) { |
275 Socket socket = new _Socket._internal(); | 311 Socket socket = new _Socket._internal(); |
276 _ensureSocketService(); | 312 _ensureSocketService(); |
277 List request = new List(2); | 313 List request = new List(2); |
278 request[0] = kHostNameLookup; | 314 request[0] = kHostNameLookup; |
279 request[1] = host; | 315 request[1] = host; |
280 _socketService.call(request).then((response) { | 316 _socketService.call(request).then((response) { |
281 if (socket._isErrorResponse(response)) { | 317 if (socket._isErrorResponse(response)) { |
282 socket._reportError(response, "Failed host name lookup"); | 318 socket._reportError(response, "Failed host name lookup"); |
283 } else { | 319 } else{ |
284 if (!socket._createConnect(response, port)) { | 320 var result = socket._createConnect(response, port); |
| 321 if (result is OSError) { |
285 socket.close(); | 322 socket.close(); |
286 socket._reportError(null, "Connection failed"); | 323 socket._reportError(result, "Connection failed"); |
287 } else { | 324 } else { |
288 socket._activateHandlers(); | 325 socket._activateHandlers(); |
289 } | 326 } |
290 } | 327 } |
291 }); | 328 }); |
292 return socket; | 329 return socket; |
293 } | 330 } |
294 | 331 |
295 _Socket._internal(); | 332 _Socket._internal(); |
296 _Socket._internalReadOnly() : _pipe = true { super._closedWrite = true; } | 333 _Socket._internalReadOnly() : _pipe = true { super._closedWrite = true; } |
(...skipping 17 matching lines...) Expand all Loading... |
314 if (offset < 0) { | 351 if (offset < 0) { |
315 throw new IndexOutOfRangeException(offset); | 352 throw new IndexOutOfRangeException(offset); |
316 } | 353 } |
317 if (bytes < 0) { | 354 if (bytes < 0) { |
318 throw new IndexOutOfRangeException(bytes); | 355 throw new IndexOutOfRangeException(bytes); |
319 } | 356 } |
320 if ((offset + bytes) > buffer.length) { | 357 if ((offset + bytes) > buffer.length) { |
321 throw new IndexOutOfRangeException(offset + bytes); | 358 throw new IndexOutOfRangeException(offset + bytes); |
322 } | 359 } |
323 int result = _readList(buffer, offset, bytes); | 360 int result = _readList(buffer, offset, bytes); |
324 if (result < 0) { | 361 if (result is OSError) { |
325 _reportError(null, "Read failed"); | 362 _reportError(result, "Read failed"); |
| 363 return -1; |
326 } | 364 } |
327 return result; | 365 return result; |
328 } | 366 } |
329 throw new | 367 throw new |
330 SocketIOException("Error: readList failed - invalid socket handle"); | 368 SocketIOException("Error: readList failed - invalid socket handle"); |
331 } | 369 } |
332 | 370 |
333 int _readList(List<int> buffer, int offset, int bytes) | 371 int _readList(List<int> buffer, int offset, int bytes) |
334 native "Socket_ReadList"; | 372 native "Socket_ReadList"; |
335 | 373 |
(...skipping 25 matching lines...) Expand all Loading... |
361 for (int i = 0; i < bytes; i++) { | 399 for (int i = 0; i < bytes; i++) { |
362 int value = buffer[j]; | 400 int value = buffer[j]; |
363 if (value is! int) { | 401 if (value is! int) { |
364 throw new FileIOException( | 402 throw new FileIOException( |
365 "List element is not an integer at index $j"); | 403 "List element is not an integer at index $j"); |
366 } | 404 } |
367 outBuffer[i] = value; | 405 outBuffer[i] = value; |
368 j++; | 406 j++; |
369 } | 407 } |
370 } | 408 } |
371 var bytes_written = _writeList(outBuffer, outOffset, bytes); | 409 var result = _writeList(outBuffer, outOffset, bytes); |
372 if (bytes_written < 0) { | 410 if (result is OSError) { |
373 // If writing fails we return 0 as the number of bytes and | 411 // If writing fails we return 0 as the number of bytes and |
374 // report the error on the error handler. | 412 // report the error on the error handler. |
375 bytes_written = 0; | 413 result = 0; |
376 _reportError(null, "Write failed"); | 414 _reportError(result, "Write failed"); |
377 } | 415 } |
378 return bytes_written; | 416 return result; |
379 } | 417 } |
380 throw new | 418 throw new SocketIOException("writeList failed - invalid socket handle"); |
381 SocketIOException("Error: writeList failed - invalid socket handle"); | |
382 } | 419 } |
383 | 420 |
384 int _writeList(List<int> buffer, int offset, int bytes) | 421 int _writeList(List<int> buffer, int offset, int bytes) |
385 native "Socket_WriteList"; | 422 native "Socket_WriteList"; |
386 | 423 |
387 bool _isErrorResponse(response) { | 424 bool _isErrorResponse(response) { |
388 return response is List && response[0] != _FileUtils.kSuccessResponse; | 425 return response is List && response[0] != _FileUtils.kSuccessResponse; |
389 } | 426 } |
390 | 427 |
391 bool _reportError(response, String message) { | |
392 if (response != null) { | |
393 assert(_isErrorResponse(response)); | |
394 } | |
395 // For all errors we close the socket, call the error handler and | |
396 // disable further calls of the error handler. | |
397 close(); | |
398 var onError = _handlerMap[_ERROR_EVENT]; | |
399 if (onError != null) { | |
400 if (response != null) { | |
401 switch (response[0]) { | |
402 case _FileUtils.kIllegalArgumentResponse: | |
403 onError(new IllegalArgumentException()); | |
404 break; | |
405 case _FileUtils.kOSErrorResponse: | |
406 onError(new SocketIOException( | |
407 message, new OSError(response[2], response[1]))); | |
408 break; | |
409 default: | |
410 onError(new Exception("Unknown error")); | |
411 break; | |
412 } | |
413 } else { | |
414 onError(new SocketIOException(message)); | |
415 } | |
416 } | |
417 } | |
418 | |
419 bool _createConnect(String host, int port) native "Socket_CreateConnect"; | 428 bool _createConnect(String host, int port) native "Socket_CreateConnect"; |
420 | 429 |
421 void set onWrite(void callback()) { | 430 void set onWrite(void callback()) { |
422 if (_outputStream != null) throw new StreamException( | 431 if (_outputStream != null) throw new StreamException( |
423 "Cannot set write handler when output stream is used"); | 432 "Cannot set write handler when output stream is used"); |
424 _clientWriteHandler = callback; | 433 _clientWriteHandler = callback; |
425 _updateOutHandler(); | 434 _updateOutHandler(); |
426 } | 435 } |
427 | 436 |
428 void set onConnect(void callback()) { | 437 void set onConnect(void callback()) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 } | 537 } |
529 | 538 |
530 bool _seenFirstOutEvent = false; | 539 bool _seenFirstOutEvent = false; |
531 bool _pipe = false; | 540 bool _pipe = false; |
532 Function _clientConnectHandler; | 541 Function _clientConnectHandler; |
533 Function _clientWriteHandler; | 542 Function _clientWriteHandler; |
534 SocketInputStream _inputStream; | 543 SocketInputStream _inputStream; |
535 SocketOutputStream _outputStream; | 544 SocketOutputStream _outputStream; |
536 static SendPort _socketService; | 545 static SendPort _socketService; |
537 } | 546 } |
OLD | NEW |