| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 part of dart.io; | |
| 6 | |
| 7 class _SocketInputStream implements InputStream { | |
| 8 _SocketInputStream(Socket socket) : _socket = socket { | |
| 9 if (_socket._closed) _closed = true; | |
| 10 _socket.onClosed = _onClosed; | |
| 11 } | |
| 12 | |
| 13 List<int> read([int len]) { | |
| 14 return _socket.read(len); | |
| 15 } | |
| 16 | |
| 17 int readInto(List<int> buffer, [int offset = 0, int len]) { | |
| 18 if (_closed) return null; | |
| 19 if (len == null) len = buffer.length; | |
| 20 if (offset < 0) throw new StreamException("Illegal offset $offset"); | |
| 21 if (len < 0) throw new StreamException("Illegal length $len"); | |
| 22 return _socket.readList(buffer, offset, len); | |
| 23 } | |
| 24 | |
| 25 int available() => _socket.available(); | |
| 26 | |
| 27 void pipe(OutputStream output, {bool close: true}) { | |
| 28 _pipe(this, output, close: close); | |
| 29 } | |
| 30 | |
| 31 void close() { | |
| 32 if (!_closed) { | |
| 33 _socket.close(); | |
| 34 } | |
| 35 } | |
| 36 | |
| 37 bool get closed => _closed; | |
| 38 | |
| 39 void set onData(void callback()) { | |
| 40 _socket._onData = callback; | |
| 41 } | |
| 42 | |
| 43 void set onClosed(void callback()) { | |
| 44 _clientCloseHandler = callback; | |
| 45 _socket._onClosed = _onClosed; | |
| 46 } | |
| 47 | |
| 48 void set onError(void callback(e)) { | |
| 49 _onError = callback; | |
| 50 } | |
| 51 | |
| 52 void _onClosed() { | |
| 53 _closed = true; | |
| 54 if (_clientCloseHandler != null) { | |
| 55 _clientCloseHandler(); | |
| 56 } | |
| 57 } | |
| 58 | |
| 59 bool _onSocketError(e) { | |
| 60 close(); | |
| 61 if (_onError != null) { | |
| 62 _onError(e); | |
| 63 return true; | |
| 64 } else { | |
| 65 return false; | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 Socket _socket; | |
| 70 bool _closed = false; | |
| 71 Function _clientCloseHandler; | |
| 72 Function _onError; | |
| 73 } | |
| 74 | |
| 75 | |
| 76 class _SocketOutputStream | |
| 77 extends _BaseOutputStream implements OutputStream { | |
| 78 _SocketOutputStream(Socket socket) | |
| 79 : _socket = socket, _pendingWrites = new _BufferList(); | |
| 80 | |
| 81 bool write(List<int> buffer, [bool copyBuffer = true]) { | |
| 82 return _write(buffer, 0, buffer.length, copyBuffer); | |
| 83 } | |
| 84 | |
| 85 bool writeFrom(List<int> buffer, [int offset = 0, int len]) { | |
| 86 return _write( | |
| 87 buffer, offset, (len == null) ? buffer.length - offset : len, true); | |
| 88 } | |
| 89 | |
| 90 void flush() { | |
| 91 // Nothing to do on a socket output stream. | |
| 92 } | |
| 93 | |
| 94 void close() { | |
| 95 if (_closing) return; | |
| 96 _closing = true; | |
| 97 if (!_pendingWrites.isEmpty) { | |
| 98 // Mark the socket for close when all data is written. | |
| 99 _socket._onWrite = _onWrite; | |
| 100 } else { | |
| 101 // Close the socket for writing. | |
| 102 _socket._closeWrite(); | |
| 103 _closed = true; | |
| 104 // Invoke the callback asynchronously. | |
| 105 Timer.run(() { | |
| 106 if (_onClosed != null) _onClosed(); | |
| 107 }); | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 void destroy() { | |
| 112 _socket._onWrite = null; | |
| 113 _pendingWrites.clear(); | |
| 114 _socket.close(); | |
| 115 _closed = true; | |
| 116 } | |
| 117 | |
| 118 bool get closed => _closed; | |
| 119 | |
| 120 void set onNoPendingWrites(void callback()) { | |
| 121 _onNoPendingWrites = callback; | |
| 122 if (_onNoPendingWrites != null) { | |
| 123 _socket._onWrite = _onWrite; | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 void set onClosed(void callback()) { | |
| 128 _onClosed = callback; | |
| 129 } | |
| 130 | |
| 131 bool _write(List<int> buffer, int offset, int len, bool copyBuffer) { | |
| 132 if (_closing || _closed) { | |
| 133 if (_error) return false; | |
| 134 _error = true; | |
| 135 var e = new StreamException.streamClosed(); | |
| 136 if (_onError != null) { | |
| 137 _onError(e); | |
| 138 return false; | |
| 139 } else { | |
| 140 throw e; | |
| 141 } | |
| 142 } | |
| 143 int bytesWritten = 0; | |
| 144 if (_pendingWrites.isEmpty) { | |
| 145 // If nothing is buffered write as much as possible and buffer | |
| 146 // the rest. | |
| 147 try { | |
| 148 bytesWritten = _socket.writeList(buffer, offset, len); | |
| 149 if (bytesWritten == len) return true; | |
| 150 } catch (e) { | |
| 151 if (_error) return false; | |
| 152 _error = true; | |
| 153 if (_onError != null) { | |
| 154 _onError(e); | |
| 155 return false; | |
| 156 } else { | |
| 157 throw e; | |
| 158 } | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 // Place remaining data on the pending writes queue. | |
| 163 int notWrittenOffset = offset + bytesWritten; | |
| 164 if (copyBuffer) { | |
| 165 List<int> newBuffer = | |
| 166 buffer.getRange(notWrittenOffset, len - bytesWritten); | |
| 167 _pendingWrites.add(newBuffer); | |
| 168 } else { | |
| 169 assert(offset + len == buffer.length); | |
| 170 _pendingWrites.add(buffer, notWrittenOffset); | |
| 171 } | |
| 172 _socket._onWrite = _onWrite; | |
| 173 return false; | |
| 174 } | |
| 175 | |
| 176 void _onWrite() { | |
| 177 // Write as much buffered data to the socket as possible. | |
| 178 while (!_pendingWrites.isEmpty) { | |
| 179 List<int> buffer = _pendingWrites.first; | |
| 180 int offset = _pendingWrites.index; | |
| 181 int bytesToWrite = buffer.length - offset; | |
| 182 int bytesWritten; | |
| 183 try { | |
| 184 bytesWritten = _socket.writeList(buffer, offset, bytesToWrite); | |
| 185 } catch (e) { | |
| 186 _pendingWrites.clear(); | |
| 187 if (_onError != null) _onError(e); | |
| 188 return; | |
| 189 } | |
| 190 _pendingWrites.removeBytes(bytesWritten); | |
| 191 if (bytesWritten < bytesToWrite) { | |
| 192 _socket._onWrite = _onWrite; | |
| 193 return; | |
| 194 } | |
| 195 } | |
| 196 | |
| 197 // All buffered data was written. | |
| 198 if (_closing) { | |
| 199 _socket._closeWrite(); | |
| 200 _closed = true; | |
| 201 if (_onClosed != null) { | |
| 202 _onClosed(); | |
| 203 } | |
| 204 } else { | |
| 205 if (_onNoPendingWrites != null) _onNoPendingWrites(); | |
| 206 } | |
| 207 if (_onNoPendingWrites == null) { | |
| 208 _socket._onWrite = null; | |
| 209 } else { | |
| 210 _socket._onWrite = _onWrite; | |
| 211 } | |
| 212 } | |
| 213 | |
| 214 bool _onSocketError(e) { | |
| 215 destroy(); | |
| 216 if (_error) return true; | |
| 217 if (_onError != null) { | |
| 218 _onError(e); | |
| 219 return true; | |
| 220 } else { | |
| 221 throw e; | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 Socket _socket; | |
| 226 _BufferList _pendingWrites; | |
| 227 Function _onNoPendingWrites; | |
| 228 Function _onClosed; | |
| 229 bool _closing = false; | |
| 230 bool _closed = false; | |
| 231 bool _error = false; | |
| 232 } | |
| OLD | NEW |