macgyver 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }