Skip to content

Commit c4161f3

Browse files
committed
Add callback to socket.write()
1 parent c970968 commit c4161f3

4 files changed

Lines changed: 52 additions & 11 deletions

File tree

doc/api/net.markdown

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ context of the defined or default list of trusted CA certificates.
196196
Returns a JSON structure detailing the peer's certificate, containing a dictionary
197197
with keys for the certificate `'subject'`, `'issuer'`, `'valid_from'` and `'valid_to'`.
198198

199-
#### stream.write(data, [encoding])
199+
#### stream.write(data, [encoding], [callback])
200200

201201
Sends data on the stream. The second parameter specifies the encoding in the
202202
case of a string--it defaults to UTF8 encoding.
@@ -205,7 +205,10 @@ Returns `true` if the entire data was flushed successfully to the kernel
205205
buffer. Returns `false` if all or part of the data was queued in user memory.
206206
`'drain'` will be emitted when the buffer is again free.
207207

208-
#### stream.write(data, [encoding], [fileDescriptor])
208+
The optional `callback` parameter will be executed when the data is finally
209+
written out - this may not be immediately.
210+
211+
#### stream.write(data, [encoding], [fileDescriptor], [callback])
209212

210213
For UNIX sockets, it is possible to send a file descriptor through the
211214
stream. Simply add the `fileDescriptor` argument and listen for the `'fd'`

lib/net.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ function initStream(self) {
178178
self._writeQueue = [];
179179
self._writeQueueEncoding = [];
180180
self._writeQueueFD = [];
181+
self._writeQueueCallbacks = [];
181182

182183
self._writeWatcher = ioWatchers.alloc();
183184
self._writeWatcher.socket = self;
@@ -296,6 +297,7 @@ Stream.prototype.write = function(data /* [encoding], [fd], [cb] */) {
296297
this._writeQueue = [];
297298
this._writeQueueEncoding = [];
298299
this._writeQueueFD = [];
300+
this._writeQueueCallbacks = [];
299301
}
300302

301303
// Slow. There is already a write queue, so let's append to it.
@@ -311,9 +313,22 @@ Stream.prototype.write = function(data /* [encoding], [fd], [cb] */) {
311313
this._writeQueueEncoding[last] === encoding) {
312314
// optimization - concat onto last
313315
this._writeQueue[last] += data;
316+
317+
if (cb) {
318+
if (!this._writeQueueCallbacks[last]) {
319+
this._writeQueueCallbacks[last] = cb;
320+
} else {
321+
// awful
322+
this._writeQueueCallbacks[last] = function () {
323+
this._writeQueueCallbacks[last]();
324+
cb();
325+
};
326+
}
327+
}
314328
} else {
315329
this._writeQueue.push(data);
316330
this._writeQueueEncoding.push(encoding);
331+
this._writeQueueCallbacks.push(cb);
317332
}
318333

319334
if (fd != undefined) {
@@ -325,7 +340,7 @@ Stream.prototype.write = function(data /* [encoding], [fd], [cb] */) {
325340
// Fast.
326341
// The most common case. There is no write queue. Just push the data
327342
// directly to the socket.
328-
return this._writeOut(data, encoding, fd);
343+
return this._writeOut(data, encoding, fd, cb);
329344
}
330345
};
331346

@@ -337,7 +352,7 @@ Stream.prototype.write = function(data /* [encoding], [fd], [cb] */) {
337352
// 2. Write data to socket. Return true if flushed.
338353
// 3. Slice out remaining
339354
// 4. Unshift remaining onto _writeQueue. Return false.
340-
Stream.prototype._writeOut = function(data, encoding, fd) {
355+
Stream.prototype._writeOut = function(data, encoding, fd, cb) {
341356
if (!this.writable) {
342357
throw new Error('Stream is not writable');
343358
}
@@ -388,6 +403,7 @@ Stream.prototype._writeOut = function(data, encoding, fd) {
388403
// Unshift whatever didn't fit onto the buffer
389404
this._writeQueue.unshift(data.slice(charsWritten));
390405
this._writeQueueEncoding.unshift(encoding);
406+
this._writeQueueCallbacks.unshift(cb);
391407
this._writeWatcher.start();
392408
queuedData = true;
393409
}
@@ -416,6 +432,7 @@ Stream.prototype._writeOut = function(data, encoding, fd) {
416432
if (queuedData) {
417433
return false;
418434
} else {
435+
if (cb) cb();
419436
return true;
420437
}
421438
}
@@ -434,6 +451,7 @@ Stream.prototype._writeOut = function(data, encoding, fd) {
434451
// data should be the next thing to write.
435452
this._writeQueue.unshift(leftOver);
436453
this._writeQueueEncoding.unshift(null);
454+
this._writeQueueCallbacks.unshift(cb);
437455

438456
// If didn't successfully write any bytes, enqueue our fd and try again
439457
if (!bytesWritten) {
@@ -450,14 +468,15 @@ Stream.prototype.flush = function() {
450468
while (this._writeQueue && this._writeQueue.length) {
451469
var data = this._writeQueue.shift();
452470
var encoding = this._writeQueueEncoding.shift();
471+
var cb = this._writeQueueCallbacks.shift();
453472
var fd = this._writeQueueFD.shift();
454473

455474
if (data === END_OF_FILE) {
456475
this._shutdown();
457476
return true;
458477
}
459478

460-
var flushed = this._writeOut(data, encoding, fd);
479+
var flushed = this._writeOut(data, encoding, fd, cb);
461480
if (!flushed) return false;
462481
}
463482
if (this._writeWatcher) this._writeWatcher.stop();

test/simple/test-net-connect-buffer.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ var assert = require('assert');
33
var net = require('net');
44

55
var tcpPort = common.PORT;
6+
var fooWritten = false;
7+
var connectHappened = false;
68

79
var tcp = net.Server(function(s) {
810
tcp.close();
@@ -25,23 +27,35 @@ var tcp = net.Server(function(s) {
2527
process.exit(1);
2628
});
2729
});
28-
tcp.listen(tcpPort, startClient);
2930

30-
function startClient() {
31+
tcp.listen(common.PORT, function () {
3132
var socket = net.Stream();
3233

3334
console.log('Connecting to socket');
3435

3536
socket.connect(tcpPort);
3637

38+
3739
socket.on('connect', function() {
3840
console.log('socket connected');
41+
connectHappened = true;
3942
});
4043

4144
assert.equal('opening', socket.readyState);
4245

43-
assert.equal(false, socket.write('foo'));
46+
var r = socket.write('foo', function () {
47+
fooWritten = true;
48+
assert.ok(connectHappened);
49+
console.error("foo written");
50+
});
51+
52+
assert.equal(false, r);
4453
socket.end('bar');
4554

4655
assert.equal('opening', socket.readyState);
47-
}
56+
});
57+
58+
process.on('exit', function () {
59+
assert.ok(connectHappened);
60+
assert.ok(fooWritten);
61+
});

test/simple/test-net-pingpong.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ var tests_run = 0;
88
function pingPongTest(port, host) {
99
var N = 1000;
1010
var count = 0;
11+
var sentPongs = 0;
1112
var sent_final_ping = false;
1213

1314
var server = net.createServer({ allowHalfOpen: true }, function(socket) {
@@ -25,7 +26,10 @@ function pingPongTest(port, host) {
2526
assert.equal(true, socket.readable);
2627
assert.equal(true, count <= N);
2728
if (/PING/.exec(data)) {
28-
socket.write('PONG');
29+
socket.write('PONG', function () {
30+
sentPongs++;
31+
console.error('sent PONG');
32+
});
2933
}
3034
});
3135

@@ -85,8 +89,9 @@ function pingPongTest(port, host) {
8589
});
8690

8791
client.addListener('close', function() {
88-
console.log('client.endd');
92+
console.log('client.end');
8993
assert.equal(N + 1, count);
94+
assert.equal(N + 1, sentPongs);
9095
assert.equal(true, sent_final_ping);
9196
tests_run += 1;
9297
});

0 commit comments

Comments
 (0)