macgyver 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +20 -0
  5. data/README.md +45 -0
  6. data/Rakefile +1 -0
  7. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Growl +0 -0
  8. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Growl +0 -0
  9. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/Growl.h +5 -0
  10. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h +551 -0
  11. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h +341 -0
  12. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Resources/Info.plist +40 -0
  13. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/_CodeSignature/CodeResources +34 -0
  14. data/assets/MacGap.app/Contents/Info.plist +48 -0
  15. data/assets/MacGap.app/Contents/MacOS/MacGap +0 -0
  16. data/assets/MacGap.app/Contents/PkgInfo +1 -0
  17. data/assets/MacGap.app/Contents/Resources/_debugger.js +1718 -0
  18. data/assets/MacGap.app/Contents/Resources/_http_agent.js +310 -0
  19. data/assets/MacGap.app/Contents/Resources/_http_client.js +533 -0
  20. data/assets/MacGap.app/Contents/Resources/_http_common.js +222 -0
  21. data/assets/MacGap.app/Contents/Resources/_http_incoming.js +194 -0
  22. data/assets/MacGap.app/Contents/Resources/_http_outgoing.js +597 -0
  23. data/assets/MacGap.app/Contents/Resources/_http_server.js +510 -0
  24. data/assets/MacGap.app/Contents/Resources/_linklist.js +76 -0
  25. data/assets/MacGap.app/Contents/Resources/_stream_duplex.js +69 -0
  26. data/assets/MacGap.app/Contents/Resources/_stream_passthrough.js +41 -0
  27. data/assets/MacGap.app/Contents/Resources/_stream_readable.js +900 -0
  28. data/assets/MacGap.app/Contents/Resources/_stream_transform.js +204 -0
  29. data/assets/MacGap.app/Contents/Resources/_stream_writable.js +456 -0
  30. data/assets/MacGap.app/Contents/Resources/_tls_legacy.js +887 -0
  31. data/assets/MacGap.app/Contents/Resources/_tls_wrap.js +831 -0
  32. data/assets/MacGap.app/Contents/Resources/application.icns +0 -0
  33. data/assets/MacGap.app/Contents/Resources/assert.js +326 -0
  34. data/assets/MacGap.app/Contents/Resources/buffer.js +724 -0
  35. data/assets/MacGap.app/Contents/Resources/child_process.js +1107 -0
  36. data/assets/MacGap.app/Contents/Resources/cluster.js +613 -0
  37. data/assets/MacGap.app/Contents/Resources/console.js +108 -0
  38. data/assets/MacGap.app/Contents/Resources/constants.js +22 -0
  39. data/assets/MacGap.app/Contents/Resources/crypto.js +691 -0
  40. data/assets/MacGap.app/Contents/Resources/dgram.js +459 -0
  41. data/assets/MacGap.app/Contents/Resources/dns.js +274 -0
  42. data/assets/MacGap.app/Contents/Resources/domain.js +292 -0
  43. data/assets/MacGap.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
  44. data/assets/MacGap.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  45. data/assets/MacGap.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
  46. data/assets/MacGap.app/Contents/Resources/en.lproj/Window.nib +0 -0
  47. data/assets/MacGap.app/Contents/Resources/events.js +312 -0
  48. data/assets/MacGap.app/Contents/Resources/freelist.js +43 -0
  49. data/assets/MacGap.app/Contents/Resources/fs.js +1732 -0
  50. data/assets/MacGap.app/Contents/Resources/http.js +119 -0
  51. data/assets/MacGap.app/Contents/Resources/https.js +134 -0
  52. data/assets/MacGap.app/Contents/Resources/module.js +529 -0
  53. data/assets/MacGap.app/Contents/Resources/net.js +1378 -0
  54. data/assets/MacGap.app/Contents/Resources/nodelike.js +195 -0
  55. data/assets/MacGap.app/Contents/Resources/os.js +64 -0
  56. data/assets/MacGap.app/Contents/Resources/path.js +517 -0
  57. data/assets/MacGap.app/Contents/Resources/public/index.html +38 -0
  58. data/assets/MacGap.app/Contents/Resources/punycode.js +507 -0
  59. data/assets/MacGap.app/Contents/Resources/querystring.js +206 -0
  60. data/assets/MacGap.app/Contents/Resources/readline.js +1311 -0
  61. data/assets/MacGap.app/Contents/Resources/repl.js +945 -0
  62. data/assets/MacGap.app/Contents/Resources/smalloc.js +90 -0
  63. data/assets/MacGap.app/Contents/Resources/stream.js +127 -0
  64. data/assets/MacGap.app/Contents/Resources/string_decoder.js +189 -0
  65. data/assets/MacGap.app/Contents/Resources/sys.js +24 -0
  66. data/assets/MacGap.app/Contents/Resources/timers.js +568 -0
  67. data/assets/MacGap.app/Contents/Resources/tls.js +220 -0
  68. data/assets/MacGap.app/Contents/Resources/tty.js +129 -0
  69. data/assets/MacGap.app/Contents/Resources/url.js +693 -0
  70. data/assets/MacGap.app/Contents/Resources/util.js +688 -0
  71. data/assets/MacGap.app/Contents/Resources/vm.js +73 -0
  72. data/assets/MacGap.app/Contents/Resources/zlib.js +524 -0
  73. data/assets/index.html +38 -0
  74. data/bin/macgyver +104 -0
  75. data/macgyver.gemspec +19 -0
  76. data/test/public/index.html +27 -0
  77. metadata +121 -0
@@ -0,0 +1,1378 @@
1
+ // Copyright Joyent, Inc. and other Node contributors.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a
4
+ // copy of this software and associated documentation files (the
5
+ // "Software"), to deal in the Software without restriction, including
6
+ // without limitation the rights to use, copy, modify, merge, publish,
7
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ // persons to whom the Software is furnished to do so, subject to the
9
+ // following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included
12
+ // in all copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ var events = require('events');
23
+ var stream = require('stream');
24
+ var timers = require('timers');
25
+ var util = require('util');
26
+ var assert = require('assert');
27
+ var cares = process.binding('cares_wrap');
28
+ var uv = process.binding('uv');
29
+
30
+ var cluster;
31
+ var errnoException = util._errnoException;
32
+
33
+ function noop() {}
34
+
35
+ // constructor for lazy loading
36
+ function createPipe() {
37
+ var Pipe = process.binding('pipe_wrap').Pipe;
38
+ return new Pipe();
39
+ }
40
+
41
+ // constructor for lazy loading
42
+ function createTCP() {
43
+ var TCP = process.binding('tcp_wrap').TCP;
44
+ return new TCP();
45
+ }
46
+
47
+
48
+ function createHandle(fd) {
49
+ var tty = process.binding('tty_wrap');
50
+ var type = tty.guessHandleType(fd);
51
+ if (type === 'PIPE') return createPipe();
52
+ if (type === 'TCP') return createTCP();
53
+ throw new TypeError('Unsupported fd type: ' + type);
54
+ }
55
+
56
+
57
+ var debug = util.debuglog('net');
58
+
59
+ function isPipeName(s) {
60
+ return util.isString(s) && toNumber(s) === false;
61
+ }
62
+
63
+
64
+ exports.createServer = function() {
65
+ return new Server(arguments[0], arguments[1]);
66
+ };
67
+
68
+
69
+ // Target API:
70
+ //
71
+ // var s = net.connect({port: 80, host: 'google.com'}, function() {
72
+ // ...
73
+ // });
74
+ //
75
+ // There are various forms:
76
+ //
77
+ // connect(options, [cb])
78
+ // connect(port, [host], [cb])
79
+ // connect(path, [cb]);
80
+ //
81
+ exports.connect = exports.createConnection = function() {
82
+ var args = normalizeConnectArgs(arguments);
83
+ debug('createConnection', args);
84
+ var s = new Socket(args[0]);
85
+ return Socket.prototype.connect.apply(s, args);
86
+ };
87
+
88
+ // Returns an array [options] or [options, cb]
89
+ // It is the same as the argument of Socket.prototype.connect().
90
+ function normalizeConnectArgs(args) {
91
+ var options = {};
92
+
93
+ if (util.isObject(args[0])) {
94
+ // connect(options, [cb])
95
+ options = args[0];
96
+ } else if (isPipeName(args[0])) {
97
+ // connect(path, [cb]);
98
+ options.path = args[0];
99
+ } else {
100
+ // connect(port, [host], [cb])
101
+ options.port = args[0];
102
+ if (util.isString(args[1])) {
103
+ options.host = args[1];
104
+ }
105
+ }
106
+
107
+ var cb = args[args.length - 1];
108
+ return util.isFunction(cb) ? [options, cb] : [options];
109
+ }
110
+ exports._normalizeConnectArgs = normalizeConnectArgs;
111
+
112
+
113
+ // called when creating new Socket, or when re-using a closed Socket
114
+ function initSocketHandle(self) {
115
+ self.destroyed = false;
116
+ self.errorEmitted = false;
117
+ self.bytesRead = 0;
118
+ self._bytesDispatched = 0;
119
+
120
+ // Handle creation may be deferred to bind() or connect() time.
121
+ if (self._handle) {
122
+ self._handle.owner = self;
123
+ self._handle.onread = onread;
124
+
125
+ // If handle doesn't support writev - neither do we
126
+ if (!self._handle.writev)
127
+ self._writev = null;
128
+ }
129
+ }
130
+
131
+ function Socket(options) {
132
+ if (!(this instanceof Socket)) return new Socket(options);
133
+
134
+ this._connecting = false;
135
+ this._hadError = false;
136
+ this._handle = null;
137
+ this._host = null;
138
+
139
+ if (util.isNumber(options))
140
+ options = { fd: options }; // Legacy interface.
141
+ else if (util.isUndefined(options))
142
+ options = {};
143
+
144
+ stream.Duplex.call(this, options);
145
+
146
+ if (options.handle) {
147
+ this._handle = options.handle; // private
148
+ } else if (!util.isUndefined(options.fd)) {
149
+ this._handle = createHandle(options.fd);
150
+ this._handle.open(options.fd);
151
+ this.readable = options.readable !== false;
152
+ this.writable = options.writable !== false;
153
+ } else {
154
+ // these will be set once there is a connection
155
+ this.readable = this.writable = false;
156
+ }
157
+
158
+ // shut down the socket when we're finished with it.
159
+ this.on('finish', onSocketFinish);
160
+ this.on('_socketEnd', onSocketEnd);
161
+
162
+ initSocketHandle(this);
163
+
164
+ this._pendingData = null;
165
+ this._pendingEncoding = '';
166
+
167
+ // handle strings directly
168
+ this._writableState.decodeStrings = false;
169
+
170
+ // default to *not* allowing half open sockets
171
+ this.allowHalfOpen = options && options.allowHalfOpen || false;
172
+
173
+ // if we have a handle, then start the flow of data into the
174
+ // buffer. if not, then this will happen when we connect
175
+ if (this._handle && options.readable !== false)
176
+ this.read(0);
177
+ }
178
+ util.inherits(Socket, stream.Duplex);
179
+
180
+ // the user has called .end(), and all the bytes have been
181
+ // sent out to the other side.
182
+ // If allowHalfOpen is false, or if the readable side has
183
+ // ended already, then destroy.
184
+ // If allowHalfOpen is true, then we need to do a shutdown,
185
+ // so that only the writable side will be cleaned up.
186
+ function onSocketFinish() {
187
+ // If still connecting - defer handling 'finish' until 'connect' will happen
188
+ if (this._connecting) {
189
+ debug('osF: not yet connected');
190
+ return this.once('connect', onSocketFinish);
191
+ }
192
+
193
+ debug('onSocketFinish');
194
+ if (!this.readable || this._readableState.ended) {
195
+ debug('oSF: ended, destroy', this._readableState);
196
+ return this.destroy();
197
+ }
198
+
199
+ debug('oSF: not ended, call shutdown()');
200
+
201
+ // otherwise, just shutdown, or destroy() if not possible
202
+ if (!this._handle || !this._handle.shutdown)
203
+ return this.destroy();
204
+
205
+ var req = { oncomplete: afterShutdown };
206
+ var err = this._handle.shutdown(req);
207
+
208
+ if (err)
209
+ return this._destroy(errnoException(err, 'shutdown'));
210
+ }
211
+
212
+
213
+ function afterShutdown(status, handle, req) {
214
+ var self = handle.owner;
215
+
216
+ debug('afterShutdown destroyed=%j', self.destroyed,
217
+ self._readableState);
218
+
219
+ // callback may come after call to destroy.
220
+ if (self.destroyed)
221
+ return;
222
+
223
+ if (self._readableState.ended) {
224
+ debug('readableState ended, destroying');
225
+ self.destroy();
226
+ } else {
227
+ self.once('_socketEnd', self.destroy);
228
+ }
229
+ }
230
+
231
+ // the EOF has been received, and no more bytes are coming.
232
+ // if the writable side has ended already, then clean everything
233
+ // up.
234
+ function onSocketEnd() {
235
+ // XXX Should not have to do as much crap in this function.
236
+ // ended should already be true, since this is called *after*
237
+ // the EOF errno and onread has eof'ed
238
+ debug('onSocketEnd', this._readableState);
239
+ this._readableState.ended = true;
240
+ if (this._readableState.endEmitted) {
241
+ this.readable = false;
242
+ maybeDestroy(this);
243
+ } else {
244
+ this.once('end', function() {
245
+ this.readable = false;
246
+ maybeDestroy(this);
247
+ });
248
+ this.read(0);
249
+ }
250
+
251
+ if (!this.allowHalfOpen) {
252
+ this.write = writeAfterFIN;
253
+ this.destroySoon();
254
+ }
255
+ }
256
+
257
+ // Provide a better error message when we call end() as a result
258
+ // of the other side sending a FIN. The standard 'write after end'
259
+ // is overly vague, and makes it seem like the user's code is to blame.
260
+ function writeAfterFIN(chunk, encoding, cb) {
261
+ if (util.isFunction(encoding)) {
262
+ cb = encoding;
263
+ encoding = null;
264
+ }
265
+
266
+ var er = new Error('This socket has been ended by the other party');
267
+ er.code = 'EPIPE';
268
+ var self = this;
269
+ // TODO: defer error events consistently everywhere, not just the cb
270
+ self.emit('error', er);
271
+ if (util.isFunction(cb)) {
272
+ process.nextTick(function() {
273
+ cb(er);
274
+ });
275
+ }
276
+ }
277
+
278
+ exports.Socket = Socket;
279
+ exports.Stream = Socket; // Legacy naming.
280
+
281
+ Socket.prototype.read = function(n) {
282
+ if (n === 0)
283
+ return stream.Readable.prototype.read.call(this, n);
284
+
285
+ this.read = stream.Readable.prototype.read;
286
+ this._consuming = true;
287
+ return this.read(n);
288
+ };
289
+
290
+
291
+ Socket.prototype.listen = function() {
292
+ debug('socket.listen');
293
+ var self = this;
294
+ self.on('connection', arguments[0]);
295
+ listen(self, null, null, null);
296
+ };
297
+
298
+
299
+ Socket.prototype.setTimeout = function(msecs, callback) {
300
+ if (msecs > 0 && !isNaN(msecs) && isFinite(msecs)) {
301
+ timers.enroll(this, msecs);
302
+ timers._unrefActive(this);
303
+ if (callback) {
304
+ this.once('timeout', callback);
305
+ }
306
+ } else if (msecs === 0) {
307
+ timers.unenroll(this);
308
+ if (callback) {
309
+ this.removeListener('timeout', callback);
310
+ }
311
+ }
312
+ };
313
+
314
+
315
+ Socket.prototype._onTimeout = function() {
316
+ debug('_onTimeout');
317
+ this.emit('timeout');
318
+ };
319
+
320
+
321
+ Socket.prototype.setNoDelay = function(enable) {
322
+ // backwards compatibility: assume true when `enable` is omitted
323
+ if (this._handle && this._handle.setNoDelay)
324
+ this._handle.setNoDelay(util.isUndefined(enable) ? true : !!enable);
325
+ };
326
+
327
+
328
+ Socket.prototype.setKeepAlive = function(setting, msecs) {
329
+ if (this._handle && this._handle.setKeepAlive)
330
+ this._handle.setKeepAlive(setting, ~~(msecs / 1000));
331
+ };
332
+
333
+
334
+ Socket.prototype.address = function() {
335
+ if (this._handle && this._handle.getsockname) {
336
+ var out = {};
337
+ var err = this._handle.getsockname(out);
338
+ // TODO(bnoordhuis) Check err and throw?
339
+ return out;
340
+ }
341
+ return null;
342
+ };
343
+
344
+
345
+ Object.defineProperty(Socket.prototype, 'readyState', {
346
+ get: function() {
347
+ if (this._connecting) {
348
+ return 'opening';
349
+ } else if (this.readable && this.writable) {
350
+ return 'open';
351
+ } else if (this.readable && !this.writable) {
352
+ return 'readOnly';
353
+ } else if (!this.readable && this.writable) {
354
+ return 'writeOnly';
355
+ } else {
356
+ return 'closed';
357
+ }
358
+ }
359
+ });
360
+
361
+
362
+ Object.defineProperty(Socket.prototype, 'bufferSize', {
363
+ get: function() {
364
+ if (this._handle) {
365
+ return this._handle.writeQueueSize + this._writableState.length;
366
+ }
367
+ }
368
+ });
369
+
370
+
371
+ // Just call handle.readStart until we have enough in the buffer
372
+ Socket.prototype._read = function(n) {
373
+ debug('_read');
374
+
375
+ if (this._connecting || !this._handle) {
376
+ debug('_read wait for connection');
377
+ this.once('connect', this._read.bind(this, n));
378
+ } else if (!this._handle.reading) {
379
+ // not already reading, start the flow
380
+ debug('Socket._read readStart');
381
+ this._handle.reading = true;
382
+ var err = this._handle.readStart();
383
+ if (err)
384
+ this._destroy(errnoException(err, 'read'));
385
+ }
386
+ };
387
+
388
+
389
+ Socket.prototype.end = function(data, encoding) {
390
+ stream.Duplex.prototype.end.call(this, data, encoding);
391
+ this.writable = false;
392
+ DTRACE_NET_STREAM_END(this);
393
+
394
+ // just in case we're waiting for an EOF.
395
+ if (this.readable && !this._readableState.endEmitted)
396
+ this.read(0);
397
+ else
398
+ maybeDestroy(this);
399
+ };
400
+
401
+
402
+ // Call whenever we set writable=false or readable=false
403
+ function maybeDestroy(socket) {
404
+ if (!socket.readable &&
405
+ !socket.writable &&
406
+ !socket.destroyed &&
407
+ !socket._connecting &&
408
+ !socket._writableState.length) {
409
+ socket.destroy();
410
+ }
411
+ }
412
+
413
+
414
+ Socket.prototype.destroySoon = function() {
415
+ if (this.writable)
416
+ this.end();
417
+
418
+ if (this._writableState.finished)
419
+ this.destroy();
420
+ else
421
+ this.once('finish', this.destroy);
422
+ };
423
+
424
+
425
+ Socket.prototype._destroy = function(exception, cb) {
426
+ debug('destroy');
427
+
428
+ var self = this;
429
+
430
+ function fireErrorCallbacks() {
431
+ if (cb) cb(exception);
432
+ if (exception && !self.errorEmitted) {
433
+ process.nextTick(function() {
434
+ self.emit('error', exception);
435
+ });
436
+ self.errorEmitted = true;
437
+ }
438
+ };
439
+
440
+ if (this.destroyed) {
441
+ debug('already destroyed, fire error callbacks');
442
+ fireErrorCallbacks();
443
+ return;
444
+ }
445
+
446
+ self._connecting = false;
447
+
448
+ this.readable = this.writable = false;
449
+
450
+ timers.unenroll(this);
451
+
452
+ debug('close');
453
+ if (this._handle) {
454
+ if (this !== process.stderr)
455
+ debug('close handle');
456
+ var isException = exception ? true : false;
457
+ this._handle.close(function() {
458
+ debug('emit close');
459
+ self.emit('close', isException);
460
+ });
461
+ this._handle.onread = noop;
462
+ this._handle = null;
463
+ }
464
+
465
+ fireErrorCallbacks();
466
+ this.destroyed = true;
467
+
468
+ if (this.server) {
469
+ COUNTER_NET_SERVER_CONNECTION_CLOSE(this);
470
+ debug('has server');
471
+ this.server._connections--;
472
+ if (this.server._emitCloseIfDrained) {
473
+ this.server._emitCloseIfDrained();
474
+ }
475
+ }
476
+ };
477
+
478
+
479
+ Socket.prototype.destroy = function(exception) {
480
+ debug('destroy', exception);
481
+ this._destroy(exception);
482
+ };
483
+
484
+
485
+ // This function is called whenever the handle gets a
486
+ // buffer, or when there's an error reading.
487
+ function onread(nread, buffer) {
488
+ var handle = this;
489
+ var self = handle.owner;
490
+ assert(handle === self._handle, 'handle != self._handle');
491
+
492
+ timers._unrefActive(self);
493
+
494
+ debug('onread', nread);
495
+
496
+ if (nread > 0) {
497
+ debug('got data');
498
+
499
+ // read success.
500
+ // In theory (and in practice) calling readStop right now
501
+ // will prevent this from being called again until _read() gets
502
+ // called again.
503
+
504
+ // if it's not enough data, we'll just call handle.readStart()
505
+ // again right away.
506
+ self.bytesRead += nread;
507
+
508
+ // Optimization: emit the original buffer with end points
509
+ var ret = self.push(buffer);
510
+
511
+ if (handle.reading && !ret) {
512
+ handle.reading = false;
513
+ debug('readStop');
514
+ var err = handle.readStop();
515
+ if (err)
516
+ self._destroy(errnoException(err, 'read'));
517
+ }
518
+ return;
519
+ }
520
+
521
+ // if we didn't get any bytes, that doesn't necessarily mean EOF.
522
+ // wait for the next one.
523
+ if (nread === 0) {
524
+ debug('not any data, keep waiting');
525
+ return;
526
+ }
527
+
528
+ // Error, possibly EOF.
529
+ if (nread !== uv.UV_EOF) {
530
+ return self._destroy(errnoException(nread, 'read'));
531
+ }
532
+
533
+ debug('EOF');
534
+
535
+ if (self._readableState.length === 0) {
536
+ self.readable = false;
537
+ maybeDestroy(self);
538
+ }
539
+
540
+ // push a null to signal the end of data.
541
+ self.push(null);
542
+
543
+ // internal end event so that we know that the actual socket
544
+ // is no longer readable, and we can start the shutdown
545
+ // procedure. No need to wait for all the data to be consumed.
546
+ self.emit('_socketEnd');
547
+ }
548
+
549
+
550
+ Socket.prototype._getpeername = function() {
551
+ if (!this._handle || !this._handle.getpeername) {
552
+ return {};
553
+ }
554
+ if (!this._peername) {
555
+ var out = {};
556
+ var err = this._handle.getpeername(out);
557
+ if (err) return {}; // FIXME(bnoordhuis) Throw?
558
+ this._peername = out;
559
+ }
560
+ return this._peername;
561
+ };
562
+
563
+
564
+ Socket.prototype.__defineGetter__('remoteAddress', function() {
565
+ return this._getpeername().address;
566
+ });
567
+
568
+
569
+ Socket.prototype.__defineGetter__('remotePort', function() {
570
+ return this._getpeername().port;
571
+ });
572
+
573
+
574
+ Socket.prototype._getsockname = function() {
575
+ if (!this._handle || !this._handle.getsockname) {
576
+ return {};
577
+ }
578
+ if (!this._sockname) {
579
+ var out = {};
580
+ var err = this._handle.getsockname(out);
581
+ if (err) return {}; // FIXME(bnoordhuis) Throw?
582
+ this._sockname = out;
583
+ }
584
+ return this._sockname;
585
+ };
586
+
587
+
588
+ Socket.prototype.__defineGetter__('localAddress', function() {
589
+ return this._getsockname().address;
590
+ });
591
+
592
+
593
+ Socket.prototype.__defineGetter__('localPort', function() {
594
+ return this._getsockname().port;
595
+ });
596
+
597
+
598
+ Socket.prototype.write = function(chunk, encoding, cb) {
599
+ if (!util.isString(chunk) && !util.isBuffer(chunk))
600
+ throw new TypeError('invalid data');
601
+ return stream.Duplex.prototype.write.apply(this, arguments);
602
+ };
603
+
604
+
605
+ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
606
+ // If we are still connecting, then buffer this for later.
607
+ // The Writable logic will buffer up any more writes while
608
+ // waiting for this one to be done.
609
+ if (this._connecting) {
610
+ this._pendingData = data;
611
+ this._pendingEncoding = encoding;
612
+ this.once('connect', function() {
613
+ this._writeGeneric(writev, data, encoding, cb);
614
+ });
615
+ return;
616
+ }
617
+ this._pendingData = null;
618
+ this._pendingEncoding = '';
619
+
620
+ timers._unrefActive(this);
621
+
622
+ if (!this._handle) {
623
+ this._destroy(new Error('This socket is closed.'), cb);
624
+ return false;
625
+ }
626
+
627
+ var req = { oncomplete: afterWrite };
628
+ var err;
629
+
630
+ if (writev) {
631
+ var chunks = new Array(data.length << 1);
632
+ for (var i = 0; i < data.length; i++) {
633
+ var entry = data[i];
634
+ var chunk = entry.chunk;
635
+ var enc = entry.encoding;
636
+ chunks[i * 2] = chunk;
637
+ chunks[i * 2 + 1] = enc;
638
+ }
639
+ err = this._handle.writev(req, chunks);
640
+
641
+ // Retain chunks
642
+ if (err === 0) req._chunks = chunks;
643
+ } else {
644
+ var enc;
645
+ if (util.isBuffer(data)) {
646
+ req.buffer = data; // Keep reference alive.
647
+ enc = 'buffer';
648
+ } else {
649
+ enc = encoding;
650
+ }
651
+ err = createWriteReq(req, this._handle, data, enc);
652
+ }
653
+
654
+ if (err)
655
+ return this._destroy(errnoException(err, 'write'), cb);
656
+
657
+ this._bytesDispatched += req.bytes;
658
+
659
+ // If it was entirely flushed, we can write some more right now.
660
+ // However, if more is left in the queue, then wait until that clears.
661
+ if (this._handle.writeQueueSize === 0)
662
+ cb();
663
+ else
664
+ req.cb = cb;
665
+ };
666
+
667
+
668
+ Socket.prototype._writev = function(chunks, cb) {
669
+ this._writeGeneric(true, chunks, '', cb);
670
+ };
671
+
672
+
673
+ Socket.prototype._write = function(data, encoding, cb) {
674
+ this._writeGeneric(false, data, encoding, cb);
675
+ };
676
+
677
+ // Important: this should have the same values as in src/stream_wrap.h
678
+ function getEncodingId(encoding) {
679
+ switch (encoding) {
680
+ case 'buffer':
681
+ return 0;
682
+
683
+ case 'utf8':
684
+ case 'utf-8':
685
+ return 1;
686
+
687
+ case 'ascii':
688
+ return 2;
689
+
690
+ case 'ucs2':
691
+ case 'ucs-2':
692
+ case 'utf16le':
693
+ case 'utf-16le':
694
+ return 3;
695
+
696
+ default:
697
+ return 0;
698
+ }
699
+ }
700
+
701
+ function createWriteReq(req, handle, data, encoding) {
702
+ switch (encoding) {
703
+ case 'buffer':
704
+ return handle.writeBuffer(req, data);
705
+
706
+ case 'utf8':
707
+ case 'utf-8':
708
+ return handle.writeUtf8String(req, data);
709
+
710
+ case 'ascii':
711
+ return handle.writeAsciiString(req, data);
712
+
713
+ case 'ucs2':
714
+ case 'ucs-2':
715
+ case 'utf16le':
716
+ case 'utf-16le':
717
+ return handle.writeUcs2String(req, data);
718
+
719
+ default:
720
+ return handle.writeBuffer(req, new Buffer(data, encoding));
721
+ }
722
+ }
723
+
724
+
725
+ Socket.prototype.__defineGetter__('bytesWritten', function() {
726
+ var bytes = this._bytesDispatched,
727
+ state = this._writableState,
728
+ data = this._pendingData,
729
+ encoding = this._pendingEncoding;
730
+
731
+ state.buffer.forEach(function(el) {
732
+ if (util.isBuffer(el.chunk))
733
+ bytes += el.chunk.length;
734
+ else
735
+ bytes += Buffer.byteLength(el.chunk, el.encoding);
736
+ });
737
+
738
+ if (data) {
739
+ if (util.isBuffer(data))
740
+ bytes += data.length;
741
+ else
742
+ bytes += Buffer.byteLength(data, encoding);
743
+ }
744
+
745
+ return bytes;
746
+ });
747
+
748
+
749
+ function afterWrite(status, handle, req) {
750
+ var self = handle.owner;
751
+ if (self !== process.stderr && self !== process.stdout)
752
+ debug('afterWrite', status);
753
+
754
+ // callback may come after call to destroy.
755
+ if (self.destroyed) {
756
+ debug('afterWrite destroyed');
757
+ return;
758
+ }
759
+
760
+ if (status < 0) {
761
+ var ex = errnoException(status, 'write');
762
+ debug('write failure', ex);
763
+ self._destroy(ex, req.cb);
764
+ return;
765
+ }
766
+
767
+ timers._unrefActive(self);
768
+
769
+ if (self !== process.stderr && self !== process.stdout)
770
+ debug('afterWrite call cb');
771
+
772
+ if (req.cb)
773
+ req.cb.call(self);
774
+ }
775
+
776
+
777
+ function connect(self, address, port, addressType, localAddress) {
778
+ // TODO return promise from Socket.prototype.connect which
779
+ // wraps _connectReq.
780
+
781
+ assert.ok(self._connecting);
782
+
783
+ var err;
784
+ if (localAddress) {
785
+ if (addressType == 6) {
786
+ err = self._handle.bind6(localAddress);
787
+ } else {
788
+ err = self._handle.bind(localAddress);
789
+ }
790
+
791
+ if (err) {
792
+ self._destroy(errnoException(err, 'bind'));
793
+ return;
794
+ }
795
+ }
796
+
797
+ var req = { oncomplete: afterConnect };
798
+ if (addressType === 6 || addressType === 4) {
799
+ port = port | 0;
800
+ if (port <= 0 || port > 65535)
801
+ throw new RangeError('Port should be > 0 and < 65536');
802
+
803
+ if (addressType === 6) {
804
+ err = self._handle.connect6(req, address, port);
805
+ } else if (addressType === 4) {
806
+ err = self._handle.connect(req, address, port);
807
+ }
808
+ } else {
809
+ err = self._handle.connect(req, address, afterConnect);
810
+ }
811
+
812
+ if (err) {
813
+ self._destroy(errnoException(err, 'connect'));
814
+ }
815
+ }
816
+
817
+
818
+ Socket.prototype.connect = function(options, cb) {
819
+ if (this.write !== Socket.prototype.write)
820
+ this.write = Socket.prototype.write;
821
+
822
+ if (!util.isObject(options)) {
823
+ // Old API:
824
+ // connect(port, [host], [cb])
825
+ // connect(path, [cb]);
826
+ var args = normalizeConnectArgs(arguments);
827
+ return Socket.prototype.connect.apply(this, args);
828
+ }
829
+
830
+ if (this.destroyed) {
831
+ this._readableState.reading = false;
832
+ this._readableState.ended = false;
833
+ this._writableState.ended = false;
834
+ this._writableState.ending = false;
835
+ this._writableState.finished = false;
836
+ this.destroyed = false;
837
+ this._handle = null;
838
+ }
839
+
840
+ var self = this;
841
+ var pipe = !!options.path;
842
+ debug('pipe', pipe, options.path);
843
+
844
+ if (!this._handle) {
845
+ this._handle = pipe ? createPipe() : createTCP();
846
+ initSocketHandle(this);
847
+ }
848
+
849
+ if (util.isFunction(cb)) {
850
+ self.once('connect', cb);
851
+ }
852
+
853
+ timers._unrefActive(this);
854
+
855
+ self._connecting = true;
856
+ self.writable = true;
857
+
858
+ if (pipe) {
859
+ connect(self, options.path);
860
+
861
+ } else if (!options.host) {
862
+ debug('connect: missing host');
863
+ self._host = '127.0.0.1';
864
+ connect(self, self._host, options.port, 4);
865
+
866
+ } else {
867
+ var host = options.host;
868
+ var family = options.family || 4;
869
+ debug('connect: find host ' + host);
870
+ self._host = host;
871
+ require('dns').lookup(host, family, function(err, ip, addressType) {
872
+ self.emit('lookup', err, ip, addressType);
873
+
874
+ // It's possible we were destroyed while looking this up.
875
+ // XXX it would be great if we could cancel the promise returned by
876
+ // the look up.
877
+ if (!self._connecting) return;
878
+
879
+ if (err) {
880
+ // net.createConnection() creates a net.Socket object and
881
+ // immediately calls net.Socket.connect() on it (that's us).
882
+ // There are no event listeners registered yet so defer the
883
+ // error event to the next tick.
884
+ process.nextTick(function() {
885
+ self.emit('error', err);
886
+ self._destroy();
887
+ });
888
+ } else {
889
+ timers._unrefActive(self);
890
+
891
+ addressType = addressType || 4;
892
+
893
+ // node_net.cc handles null host names graciously but user land
894
+ // expects remoteAddress to have a meaningful value
895
+ ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1');
896
+
897
+ connect(self, ip, options.port, addressType, options.localAddress);
898
+ }
899
+ });
900
+ }
901
+ return self;
902
+ };
903
+
904
+
905
+ Socket.prototype.ref = function() {
906
+ if (this._handle)
907
+ this._handle.ref();
908
+ };
909
+
910
+
911
+ Socket.prototype.unref = function() {
912
+ if (this._handle)
913
+ this._handle.unref();
914
+ };
915
+
916
+
917
+
918
+ function afterConnect(status, handle, req, readable, writable) {
919
+ var self = handle.owner;
920
+
921
+ // callback may come after call to destroy
922
+ if (self.destroyed) {
923
+ return;
924
+ }
925
+
926
+ assert(handle === self._handle, 'handle != self._handle');
927
+
928
+ debug('afterConnect');
929
+
930
+ assert.ok(self._connecting);
931
+ self._connecting = false;
932
+
933
+ if (status == 0) {
934
+ self.readable = readable;
935
+ self.writable = writable;
936
+ timers._unrefActive(self);
937
+
938
+ self.emit('connect');
939
+
940
+ // start the first read, or get an immediate EOF.
941
+ // this doesn't actually consume any bytes, because len=0.
942
+ if (readable)
943
+ self.read(0);
944
+
945
+ } else {
946
+ self._connecting = false;
947
+ self._destroy(errnoException(status, 'connect'));
948
+ }
949
+ }
950
+
951
+
952
+ function Server(/* [ options, ] listener */) {
953
+ if (!(this instanceof Server)) return new Server(arguments[0], arguments[1]);
954
+ events.EventEmitter.call(this);
955
+
956
+ var self = this;
957
+
958
+ var options;
959
+
960
+ if (util.isFunction(arguments[0])) {
961
+ options = {};
962
+ self.on('connection', arguments[0]);
963
+ } else {
964
+ options = arguments[0] || {};
965
+
966
+ if (util.isFunction(arguments[1])) {
967
+ self.on('connection', arguments[1]);
968
+ }
969
+ }
970
+
971
+ this._connections = 0;
972
+
973
+ Object.defineProperty(this, 'connections', {
974
+ get: util.deprecate(function() {
975
+
976
+ if (self._usingSlaves) {
977
+ return null;
978
+ }
979
+ return self._connections;
980
+ }, 'connections property is deprecated. Use getConnections() method'),
981
+ set: util.deprecate(function(val) {
982
+ return (self._connections = val);
983
+ }, 'connections property is deprecated. Use getConnections() method'),
984
+ configurable: true, enumerable: true
985
+ });
986
+
987
+ this._handle = null;
988
+ this._usingSlaves = false;
989
+ this._slaves = [];
990
+
991
+ this.allowHalfOpen = options.allowHalfOpen || false;
992
+ }
993
+ util.inherits(Server, events.EventEmitter);
994
+ exports.Server = Server;
995
+
996
+
997
+ function toNumber(x) { return (x = Number(x)) >= 0 ? x : false; }
998
+
999
+
1000
+ var createServerHandle = exports._createServerHandle =
1001
+ function(address, port, addressType, fd) {
1002
+ var err = 0;
1003
+ // assign handle in listen, and clean up if bind or listen fails
1004
+ var handle;
1005
+
1006
+ if (util.isNumber(fd) && fd >= 0) {
1007
+ try {
1008
+ handle = createHandle(fd);
1009
+ }
1010
+ catch (e) {
1011
+ // Not a fd we can listen on. This will trigger an error.
1012
+ debug('listen invalid fd=' + fd + ': ' + e.message);
1013
+ return uv.UV_EINVAL;
1014
+ }
1015
+ handle.open(fd);
1016
+ handle.readable = true;
1017
+ handle.writable = true;
1018
+ return handle;
1019
+
1020
+ } else if (port == -1 && addressType == -1) {
1021
+ handle = createPipe();
1022
+ if (process.platform === 'win32') {
1023
+ var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES);
1024
+ if (!isNaN(instances)) {
1025
+ handle.setPendingInstances(instances);
1026
+ }
1027
+ }
1028
+ } else {
1029
+ handle = createTCP();
1030
+ }
1031
+
1032
+ if (address || port) {
1033
+ debug('bind to ' + address);
1034
+ if (addressType == 6) {
1035
+ err = handle.bind6(address, port);
1036
+ } else {
1037
+ err = handle.bind(address, port);
1038
+ }
1039
+ }
1040
+
1041
+ if (err) {
1042
+ handle.close();
1043
+ return err;
1044
+ }
1045
+
1046
+ return handle;
1047
+ };
1048
+
1049
+
1050
+ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) {
1051
+ debug('listen2', address, port, addressType, backlog);
1052
+ var self = this;
1053
+
1054
+ // If there is not yet a handle, we need to create one and bind.
1055
+ // In the case of a server sent via IPC, we don't need to do this.
1056
+ if (!self._handle) {
1057
+ debug('_listen2: create a handle');
1058
+ var rval = createServerHandle(address, port, addressType, fd);
1059
+ if (util.isNumber(rval)) {
1060
+ var error = errnoException(rval, 'listen');
1061
+ process.nextTick(function() {
1062
+ self.emit('error', error);
1063
+ });
1064
+ return;
1065
+ }
1066
+ self._handle = rval;
1067
+ } else {
1068
+ debug('_listen2: have a handle already');
1069
+ }
1070
+
1071
+ self._handle.onconnection = onconnection;
1072
+ self._handle.owner = self;
1073
+
1074
+ // Use a backlog of 512 entries. We pass 511 to the listen() call because
1075
+ // the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1);
1076
+ // which will thus give us a backlog of 512 entries.
1077
+ var err = self._handle.listen(backlog || 511);
1078
+
1079
+ if (err) {
1080
+ var ex = errnoException(err, 'listen');
1081
+ self._handle.close();
1082
+ self._handle = null;
1083
+ process.nextTick(function() {
1084
+ self.emit('error', ex);
1085
+ });
1086
+ return;
1087
+ }
1088
+
1089
+ // generate connection key, this should be unique to the connection
1090
+ this._connectionKey = addressType + ':' + address + ':' + port;
1091
+
1092
+ process.nextTick(function() {
1093
+ self.emit('listening');
1094
+ });
1095
+ };
1096
+
1097
+
1098
+ function listen(self, address, port, addressType, backlog, fd) {
1099
+ if (!cluster) cluster = require('cluster');
1100
+
1101
+ if (cluster.isMaster) {
1102
+ self._listen2(address, port, addressType, backlog, fd);
1103
+ return;
1104
+ }
1105
+
1106
+ cluster._getServer(self, address, port, addressType, fd, cb);
1107
+
1108
+ function cb(err, handle) {
1109
+ // EADDRINUSE may not be reported until we call listen(). To complicate
1110
+ // matters, a failed bind() followed by listen() will implicitly bind to
1111
+ // a random port. Ergo, check that the socket is bound to the expected
1112
+ // port before calling listen().
1113
+ //
1114
+ // FIXME(bnoordhuis) Doesn't work for pipe handles, they don't have a
1115
+ // getsockname() method. Non-issue for now, the cluster module doesn't
1116
+ // really support pipes anyway.
1117
+ if (err === 0 && port > 0 && handle.getsockname) {
1118
+ var out = {};
1119
+ err = handle.getsockname(out);
1120
+ if (err === 0 && port !== out.port)
1121
+ err = uv.UV_EADDRINUSE;
1122
+ }
1123
+
1124
+ if (err)
1125
+ return self.emit('error', errnoException(err, 'bind'));
1126
+
1127
+ self._handle = handle;
1128
+ self._listen2(address, port, addressType, backlog, fd);
1129
+ }
1130
+ }
1131
+
1132
+
1133
+ Server.prototype.listen = function() {
1134
+ var self = this;
1135
+
1136
+ var lastArg = arguments[arguments.length - 1];
1137
+ if (util.isFunction(lastArg)) {
1138
+ self.once('listening', lastArg);
1139
+ }
1140
+
1141
+ var port = toNumber(arguments[0]);
1142
+
1143
+ // The third optional argument is the backlog size.
1144
+ // When the ip is omitted it can be the second argument.
1145
+ var backlog = toNumber(arguments[1]) || toNumber(arguments[2]);
1146
+
1147
+ var TCP = process.binding('tcp_wrap').TCP;
1148
+
1149
+ if (arguments.length == 0 || util.isFunction(arguments[0])) {
1150
+ // Bind to a random port.
1151
+ listen(self, '0.0.0.0', 0, null, backlog);
1152
+
1153
+ } else if (arguments[0] && util.isObject(arguments[0])) {
1154
+ var h = arguments[0];
1155
+ if (h._handle) {
1156
+ h = h._handle;
1157
+ } else if (h.handle) {
1158
+ h = h.handle;
1159
+ }
1160
+ if (h instanceof TCP) {
1161
+ self._handle = h;
1162
+ listen(self, null, -1, -1, backlog);
1163
+ } else if (util.isNumber(h.fd) && h.fd >= 0) {
1164
+ listen(self, null, null, null, backlog, h.fd);
1165
+ } else {
1166
+ throw new Error('Invalid listen argument: ' + h);
1167
+ }
1168
+ } else if (isPipeName(arguments[0])) {
1169
+ // UNIX socket or Windows pipe.
1170
+ var pipeName = self._pipeName = arguments[0];
1171
+ listen(self, pipeName, -1, -1, backlog);
1172
+
1173
+ } else if (util.isUndefined(arguments[1]) ||
1174
+ util.isFunction(arguments[1]) ||
1175
+ util.isNumber(arguments[1])) {
1176
+ // The first argument is the port, no IP given.
1177
+ listen(self, '0.0.0.0', port, 4, backlog);
1178
+
1179
+ } else {
1180
+ // The first argument is the port, the second an IP.
1181
+ require('dns').lookup(arguments[1], function(err, ip, addressType) {
1182
+ if (err) {
1183
+ self.emit('error', err);
1184
+ } else {
1185
+ listen(self, ip || '0.0.0.0', port, ip ? addressType : 4, backlog);
1186
+ }
1187
+ });
1188
+ }
1189
+ return self;
1190
+ };
1191
+
1192
+ Server.prototype.address = function() {
1193
+ if (this._handle && this._handle.getsockname) {
1194
+ var out = {};
1195
+ var err = this._handle.getsockname(out);
1196
+ // TODO(bnoordhuis) Check err and throw?
1197
+ return out;
1198
+ } else if (this._pipeName) {
1199
+ return this._pipeName;
1200
+ } else {
1201
+ return null;
1202
+ }
1203
+ };
1204
+
1205
+ function onconnection(err, clientHandle) {
1206
+ var handle = this;
1207
+ var self = handle.owner;
1208
+
1209
+ debug('onconnection');
1210
+
1211
+ if (err) {
1212
+ self.emit('error', errnoException(err, 'accept'));
1213
+ return;
1214
+ }
1215
+
1216
+ if (self.maxConnections && self._connections >= self.maxConnections) {
1217
+ clientHandle.close();
1218
+ return;
1219
+ }
1220
+
1221
+ var socket = new Socket({
1222
+ handle: clientHandle,
1223
+ allowHalfOpen: self.allowHalfOpen
1224
+ });
1225
+ socket.readable = socket.writable = true;
1226
+
1227
+
1228
+ self._connections++;
1229
+ socket.server = self;
1230
+
1231
+ DTRACE_NET_SERVER_CONNECTION(socket);
1232
+ COUNTER_NET_SERVER_CONNECTION(socket);
1233
+ self.emit('connection', socket);
1234
+ }
1235
+
1236
+
1237
+ Server.prototype.getConnections = function(cb) {
1238
+ function end(err, connections) {
1239
+ process.nextTick(function() {
1240
+ cb(err, connections);
1241
+ });
1242
+ }
1243
+
1244
+ if (!this._usingSlaves) {
1245
+ return end(null, this._connections);
1246
+ }
1247
+
1248
+ // Poll slaves
1249
+ var left = this._slaves.length,
1250
+ total = this._connections;
1251
+
1252
+ function oncount(err, count) {
1253
+ if (err) {
1254
+ left = -1;
1255
+ return end(err);
1256
+ }
1257
+
1258
+ total += count;
1259
+ if (--left === 0) return end(null, total);
1260
+ }
1261
+
1262
+ this._slaves.forEach(function(slave) {
1263
+ slave.getConnections(oncount);
1264
+ });
1265
+ };
1266
+
1267
+
1268
+ Server.prototype.close = function(cb) {
1269
+ function onSlaveClose() {
1270
+ if (--left !== 0) return;
1271
+
1272
+ self._connections = 0;
1273
+ self._emitCloseIfDrained();
1274
+ }
1275
+
1276
+ if (!this._handle) {
1277
+ // Throw error. Follows net_legacy behaviour.
1278
+ throw new Error('Not running');
1279
+ }
1280
+
1281
+ if (cb) {
1282
+ this.once('close', cb);
1283
+ }
1284
+ this._handle.close();
1285
+ this._handle = null;
1286
+
1287
+ if (this._usingSlaves) {
1288
+ var self = this,
1289
+ left = this._slaves.length;
1290
+
1291
+ // Increment connections to be sure that, even if all sockets will be closed
1292
+ // during polling of slaves, `close` event will be emitted only once.
1293
+ this._connections++;
1294
+
1295
+ // Poll slaves
1296
+ this._slaves.forEach(function(slave) {
1297
+ slave.close(onSlaveClose);
1298
+ });
1299
+ } else {
1300
+ this._emitCloseIfDrained();
1301
+ }
1302
+
1303
+ return this;
1304
+ };
1305
+
1306
+ Server.prototype._emitCloseIfDrained = function() {
1307
+ debug('SERVER _emitCloseIfDrained');
1308
+ var self = this;
1309
+
1310
+ if (self._handle || self._connections) {
1311
+ debug('SERVER handle? %j connections? %d',
1312
+ !!self._handle, self._connections);
1313
+ return;
1314
+ }
1315
+
1316
+ process.nextTick(function() {
1317
+ debug('SERVER: emit close');
1318
+ self.emit('close');
1319
+ });
1320
+ };
1321
+
1322
+
1323
+ Server.prototype.listenFD = util.deprecate(function(fd, type) {
1324
+ return this.listen({ fd: fd });
1325
+ }, 'listenFD is deprecated. Use listen({fd: <number>}).');
1326
+
1327
+ Server.prototype._setupSlave = function(socketList) {
1328
+ this._usingSlaves = true;
1329
+ this._slaves.push(socketList);
1330
+ };
1331
+
1332
+ Server.prototype.ref = function() {
1333
+ if (this._handle)
1334
+ this._handle.ref();
1335
+ };
1336
+
1337
+ Server.prototype.unref = function() {
1338
+ if (this._handle)
1339
+ this._handle.unref();
1340
+ };
1341
+
1342
+
1343
+ // TODO: isIP should be moved to the DNS code. Putting it here now because
1344
+ // this is what the legacy system did.
1345
+ exports.isIP = cares.isIP;
1346
+
1347
+
1348
+ exports.isIPv4 = function(input) {
1349
+ return exports.isIP(input) === 4;
1350
+ };
1351
+
1352
+
1353
+ exports.isIPv6 = function(input) {
1354
+ return exports.isIP(input) === 6;
1355
+ };
1356
+
1357
+
1358
+ if (process.platform === 'win32') {
1359
+ var simultaneousAccepts;
1360
+
1361
+ exports._setSimultaneousAccepts = function(handle) {
1362
+ if (util.isUndefined(handle)) {
1363
+ return;
1364
+ }
1365
+
1366
+ if (util.isUndefined(simultaneousAccepts)) {
1367
+ simultaneousAccepts = (process.env.NODE_MANY_ACCEPTS &&
1368
+ process.env.NODE_MANY_ACCEPTS !== '0');
1369
+ }
1370
+
1371
+ if (handle._simultaneousAccepts !== simultaneousAccepts) {
1372
+ handle.setSimultaneousAccepts(simultaneousAccepts);
1373
+ handle._simultaneousAccepts = simultaneousAccepts;
1374
+ }
1375
+ };
1376
+ } else {
1377
+ exports._setSimultaneousAccepts = function(handle) {};
1378
+ }