postdoc 0.2.0.beta4 → 0.2.4
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.
- checksums.yaml +4 -4
- data/lib/postdoc.rb +50 -18
- metadata +24 -378
- data/lib/pdf.js +0 -27
- data/node_modules/agent-base/History.md +0 -113
- data/node_modules/agent-base/README.md +0 -145
- data/node_modules/agent-base/index.js +0 -160
- data/node_modules/agent-base/package.json +0 -35
- data/node_modules/agent-base/patch-core.js +0 -37
- data/node_modules/agent-base/test/ssl-cert-snakeoil.key +0 -15
- data/node_modules/agent-base/test/ssl-cert-snakeoil.pem +0 -12
- data/node_modules/agent-base/test/test.js +0 -673
- data/node_modules/async-limiter/LICENSE +0 -8
- data/node_modules/async-limiter/coverage/coverage.json +0 -1
- data/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html +0 -73
- data/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html +0 -246
- data/node_modules/async-limiter/coverage/lcov-report/base.css +0 -182
- data/node_modules/async-limiter/coverage/lcov-report/index.html +0 -73
- data/node_modules/async-limiter/coverage/lcov-report/prettify.css +0 -1
- data/node_modules/async-limiter/coverage/lcov-report/prettify.js +0 -1
- data/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- data/node_modules/async-limiter/coverage/lcov-report/sorter.js +0 -156
- data/node_modules/async-limiter/coverage/lcov.info +0 -74
- data/node_modules/async-limiter/index.js +0 -67
- data/node_modules/async-limiter/package.json +0 -35
- data/node_modules/async-limiter/readme.md +0 -132
- data/node_modules/balanced-match/LICENSE.md +0 -21
- data/node_modules/balanced-match/README.md +0 -91
- data/node_modules/balanced-match/index.js +0 -59
- data/node_modules/balanced-match/package.json +0 -49
- data/node_modules/brace-expansion/LICENSE +0 -21
- data/node_modules/brace-expansion/README.md +0 -129
- data/node_modules/brace-expansion/index.js +0 -201
- data/node_modules/brace-expansion/package.json +0 -47
- data/node_modules/buffer-from/index.js +0 -69
- data/node_modules/buffer-from/package.json +0 -16
- data/node_modules/buffer-from/readme.md +0 -69
- data/node_modules/buffer-from/test.js +0 -12
- data/node_modules/concat-map/LICENSE +0 -18
- data/node_modules/concat-map/README.markdown +0 -62
- data/node_modules/concat-map/example/map.js +0 -6
- data/node_modules/concat-map/index.js +0 -13
- data/node_modules/concat-map/package.json +0 -43
- data/node_modules/concat-map/test/map.js +0 -39
- data/node_modules/concat-stream/LICENSE +0 -24
- data/node_modules/concat-stream/index.js +0 -144
- data/node_modules/concat-stream/package.json +0 -55
- data/node_modules/concat-stream/readme.md +0 -102
- data/node_modules/core-util-is/LICENSE +0 -19
- data/node_modules/core-util-is/README.md +0 -3
- data/node_modules/core-util-is/float.patch +0 -604
- data/node_modules/core-util-is/lib/util.js +0 -107
- data/node_modules/core-util-is/package.json +0 -32
- data/node_modules/core-util-is/test.js +0 -68
- data/node_modules/debug/CHANGELOG.md +0 -395
- data/node_modules/debug/LICENSE +0 -19
- data/node_modules/debug/Makefile +0 -58
- data/node_modules/debug/README.md +0 -368
- data/node_modules/debug/karma.conf.js +0 -70
- data/node_modules/debug/node.js +0 -1
- data/node_modules/debug/package.json +0 -43
- data/node_modules/debug/src/browser.js +0 -195
- data/node_modules/debug/src/debug.js +0 -225
- data/node_modules/debug/src/index.js +0 -10
- data/node_modules/debug/src/node.js +0 -186
- data/node_modules/es6-promise/CHANGELOG.md +0 -151
- data/node_modules/es6-promise/LICENSE +0 -19
- data/node_modules/es6-promise/README.md +0 -97
- data/node_modules/es6-promise/auto.js +0 -4
- data/node_modules/es6-promise/dist/es6-promise.auto.js +0 -1181
- data/node_modules/es6-promise/dist/es6-promise.auto.map +0 -1
- data/node_modules/es6-promise/dist/es6-promise.auto.min.js +0 -1
- data/node_modules/es6-promise/dist/es6-promise.auto.min.map +0 -1
- data/node_modules/es6-promise/dist/es6-promise.js +0 -1179
- data/node_modules/es6-promise/dist/es6-promise.map +0 -1
- data/node_modules/es6-promise/dist/es6-promise.min.js +0 -1
- data/node_modules/es6-promise/dist/es6-promise.min.map +0 -1
- data/node_modules/es6-promise/es6-promise.d.ts +0 -81
- data/node_modules/es6-promise/lib/es6-promise.auto.js +0 -3
- data/node_modules/es6-promise/lib/es6-promise.js +0 -7
- data/node_modules/es6-promise/lib/es6-promise/-internal.js +0 -266
- data/node_modules/es6-promise/lib/es6-promise/asap.js +0 -119
- data/node_modules/es6-promise/lib/es6-promise/enumerator.js +0 -113
- data/node_modules/es6-promise/lib/es6-promise/polyfill.js +0 -35
- data/node_modules/es6-promise/lib/es6-promise/promise.js +0 -427
- data/node_modules/es6-promise/lib/es6-promise/promise/all.js +0 -52
- data/node_modules/es6-promise/lib/es6-promise/promise/race.js +0 -84
- data/node_modules/es6-promise/lib/es6-promise/promise/reject.js +0 -46
- data/node_modules/es6-promise/lib/es6-promise/promise/resolve.js +0 -48
- data/node_modules/es6-promise/lib/es6-promise/then.js +0 -32
- data/node_modules/es6-promise/lib/es6-promise/utils.js +0 -21
- data/node_modules/es6-promise/package.json +0 -75
- data/node_modules/es6-promisify/README.md +0 -89
- data/node_modules/es6-promisify/dist/promise.js +0 -73
- data/node_modules/es6-promisify/dist/promisify.js +0 -85
- data/node_modules/es6-promisify/package.json +0 -41
- data/node_modules/extract-zip/CONTRIBUTING.md +0 -1
- data/node_modules/extract-zip/LICENSE +0 -23
- data/node_modules/extract-zip/cli.js +0 -20
- data/node_modules/extract-zip/index.js +0 -205
- data/node_modules/extract-zip/node_modules/debug/CHANGELOG.md +0 -362
- data/node_modules/extract-zip/node_modules/debug/LICENSE +0 -19
- data/node_modules/extract-zip/node_modules/debug/Makefile +0 -50
- data/node_modules/extract-zip/node_modules/debug/README.md +0 -312
- data/node_modules/extract-zip/node_modules/debug/component.json +0 -19
- data/node_modules/extract-zip/node_modules/debug/karma.conf.js +0 -70
- data/node_modules/extract-zip/node_modules/debug/node.js +0 -1
- data/node_modules/extract-zip/node_modules/debug/package.json +0 -49
- data/node_modules/extract-zip/node_modules/debug/src/browser.js +0 -185
- data/node_modules/extract-zip/node_modules/debug/src/debug.js +0 -202
- data/node_modules/extract-zip/node_modules/debug/src/index.js +0 -10
- data/node_modules/extract-zip/node_modules/debug/src/inspector-log.js +0 -15
- data/node_modules/extract-zip/node_modules/debug/src/node.js +0 -248
- data/node_modules/extract-zip/package.json +0 -35
- data/node_modules/extract-zip/readme.md +0 -49
- data/node_modules/fd-slicer/CHANGELOG.md +0 -49
- data/node_modules/fd-slicer/LICENSE +0 -21
- data/node_modules/fd-slicer/README.md +0 -189
- data/node_modules/fd-slicer/index.js +0 -277
- data/node_modules/fd-slicer/package.json +0 -36
- data/node_modules/fd-slicer/test/test.js +0 -350
- data/node_modules/fs.realpath/LICENSE +0 -43
- data/node_modules/fs.realpath/README.md +0 -33
- data/node_modules/fs.realpath/index.js +0 -66
- data/node_modules/fs.realpath/old.js +0 -303
- data/node_modules/fs.realpath/package.json +0 -26
- data/node_modules/glob/LICENSE +0 -15
- data/node_modules/glob/README.md +0 -368
- data/node_modules/glob/changelog.md +0 -67
- data/node_modules/glob/common.js +0 -240
- data/node_modules/glob/glob.js +0 -790
- data/node_modules/glob/package.json +0 -43
- data/node_modules/glob/sync.js +0 -486
- data/node_modules/https-proxy-agent/History.md +0 -124
- data/node_modules/https-proxy-agent/README.md +0 -137
- data/node_modules/https-proxy-agent/index.js +0 -229
- data/node_modules/https-proxy-agent/package.json +0 -35
- data/node_modules/https-proxy-agent/test/ssl-cert-snakeoil.key +0 -15
- data/node_modules/https-proxy-agent/test/ssl-cert-snakeoil.pem +0 -12
- data/node_modules/https-proxy-agent/test/test.js +0 -342
- data/node_modules/inflight/LICENSE +0 -15
- data/node_modules/inflight/README.md +0 -37
- data/node_modules/inflight/inflight.js +0 -54
- data/node_modules/inflight/package.json +0 -29
- data/node_modules/inherits/LICENSE +0 -16
- data/node_modules/inherits/README.md +0 -42
- data/node_modules/inherits/inherits.js +0 -7
- data/node_modules/inherits/inherits_browser.js +0 -23
- data/node_modules/inherits/package.json +0 -29
- data/node_modules/isarray/Makefile +0 -6
- data/node_modules/isarray/README.md +0 -60
- data/node_modules/isarray/component.json +0 -19
- data/node_modules/isarray/index.js +0 -5
- data/node_modules/isarray/package.json +0 -45
- data/node_modules/isarray/test.js +0 -20
- data/node_modules/mime/CHANGELOG.md +0 -225
- data/node_modules/mime/CONTRIBUTING.md +0 -5
- data/node_modules/mime/LICENSE +0 -21
- data/node_modules/mime/Mime.js +0 -89
- data/node_modules/mime/README.md +0 -188
- data/node_modules/mime/cli.js +0 -10
- data/node_modules/mime/index.js +0 -4
- data/node_modules/mime/lite.js +0 -4
- data/node_modules/mime/package.json +0 -43
- data/node_modules/mime/src/README_js.md +0 -179
- data/node_modules/mime/src/build.js +0 -71
- data/node_modules/mime/src/test.js +0 -257
- data/node_modules/mime/types/other.json +0 -1
- data/node_modules/mime/types/standard.json +0 -1
- data/node_modules/minimatch/LICENSE +0 -15
- data/node_modules/minimatch/README.md +0 -209
- data/node_modules/minimatch/minimatch.js +0 -923
- data/node_modules/minimatch/package.json +0 -30
- data/node_modules/minimist/LICENSE +0 -18
- data/node_modules/minimist/example/parse.js +0 -2
- data/node_modules/minimist/index.js +0 -187
- data/node_modules/minimist/package.json +0 -40
- data/node_modules/minimist/readme.markdown +0 -73
- data/node_modules/minimist/test/dash.js +0 -24
- data/node_modules/minimist/test/default_bool.js +0 -20
- data/node_modules/minimist/test/dotted.js +0 -16
- data/node_modules/minimist/test/long.js +0 -31
- data/node_modules/minimist/test/parse.js +0 -318
- data/node_modules/minimist/test/parse_modified.js +0 -9
- data/node_modules/minimist/test/short.js +0 -67
- data/node_modules/minimist/test/whitespace.js +0 -8
- data/node_modules/mkdirp/LICENSE +0 -21
- data/node_modules/mkdirp/bin/cmd.js +0 -33
- data/node_modules/mkdirp/bin/usage.txt +0 -12
- data/node_modules/mkdirp/examples/pow.js +0 -6
- data/node_modules/mkdirp/index.js +0 -98
- data/node_modules/mkdirp/package.json +0 -27
- data/node_modules/mkdirp/readme.markdown +0 -100
- data/node_modules/mkdirp/test/chmod.js +0 -41
- data/node_modules/mkdirp/test/clobber.js +0 -38
- data/node_modules/mkdirp/test/mkdirp.js +0 -28
- data/node_modules/mkdirp/test/opts_fs.js +0 -29
- data/node_modules/mkdirp/test/opts_fs_sync.js +0 -27
- data/node_modules/mkdirp/test/perm.js +0 -32
- data/node_modules/mkdirp/test/perm_sync.js +0 -36
- data/node_modules/mkdirp/test/race.js +0 -37
- data/node_modules/mkdirp/test/rel.js +0 -32
- data/node_modules/mkdirp/test/return.js +0 -25
- data/node_modules/mkdirp/test/return_sync.js +0 -24
- data/node_modules/mkdirp/test/root.js +0 -19
- data/node_modules/mkdirp/test/sync.js +0 -32
- data/node_modules/mkdirp/test/umask.js +0 -28
- data/node_modules/mkdirp/test/umask_sync.js +0 -32
- data/node_modules/ms/index.js +0 -152
- data/node_modules/ms/license.md +0 -21
- data/node_modules/ms/package.json +0 -37
- data/node_modules/ms/readme.md +0 -51
- data/node_modules/once/LICENSE +0 -15
- data/node_modules/once/README.md +0 -79
- data/node_modules/once/once.js +0 -42
- data/node_modules/once/package.json +0 -33
- data/node_modules/path-is-absolute/index.js +0 -20
- data/node_modules/path-is-absolute/license +0 -21
- data/node_modules/path-is-absolute/package.json +0 -43
- data/node_modules/path-is-absolute/readme.md +0 -59
- data/node_modules/pend/LICENSE +0 -23
- data/node_modules/pend/README.md +0 -41
- data/node_modules/pend/index.js +0 -55
- data/node_modules/pend/package.json +0 -18
- data/node_modules/pend/test.js +0 -137
- data/node_modules/process-nextick-args/index.js +0 -44
- data/node_modules/process-nextick-args/license.md +0 -19
- data/node_modules/process-nextick-args/package.json +0 -25
- data/node_modules/process-nextick-args/readme.md +0 -18
- data/node_modules/progress/CHANGELOG.md +0 -115
- data/node_modules/progress/LICENSE +0 -22
- data/node_modules/progress/Makefile +0 -8
- data/node_modules/progress/README.md +0 -146
- data/node_modules/progress/index.js +0 -1
- data/node_modules/progress/lib/node-progress.js +0 -231
- data/node_modules/progress/package.json +0 -25
- data/node_modules/proxy-from-env/README.md +0 -131
- data/node_modules/proxy-from-env/index.js +0 -103
- data/node_modules/proxy-from-env/package.json +0 -35
- data/node_modules/proxy-from-env/test.js +0 -393
- data/node_modules/puppeteer/CONTRIBUTING.md +0 -206
- data/node_modules/puppeteer/DeviceDescriptors.js +0 -704
- data/node_modules/puppeteer/LICENSE +0 -202
- data/node_modules/puppeteer/README.md +0 -306
- data/node_modules/puppeteer/index.js +0 -28
- data/node_modules/puppeteer/install.js +0 -122
- data/node_modules/puppeteer/lib/Browser.js +0 -186
- data/node_modules/puppeteer/lib/BrowserFetcher.js +0 -279
- data/node_modules/puppeteer/lib/Connection.js +0 -246
- data/node_modules/puppeteer/lib/Coverage.js +0 -301
- data/node_modules/puppeteer/lib/Dialog.js +0 -84
- data/node_modules/puppeteer/lib/ElementHandle.js +0 -328
- data/node_modules/puppeteer/lib/EmulationManager.js +0 -89
- data/node_modules/puppeteer/lib/ExecutionContext.js +0 -232
- data/node_modules/puppeteer/lib/FrameManager.js +0 -997
- data/node_modules/puppeteer/lib/Input.js +0 -309
- data/node_modules/puppeteer/lib/Launcher.js +0 -310
- data/node_modules/puppeteer/lib/Multimap.js +0 -95
- data/node_modules/puppeteer/lib/NavigatorWatcher.js +0 -137
- data/node_modules/puppeteer/lib/NetworkManager.js +0 -796
- data/node_modules/puppeteer/lib/Page.js +0 -1098
- data/node_modules/puppeteer/lib/Pipe.js +0 -69
- data/node_modules/puppeteer/lib/Puppeteer.js +0 -60
- data/node_modules/puppeteer/lib/Target.js +0 -88
- data/node_modules/puppeteer/lib/TaskQueue.js +0 -17
- data/node_modules/puppeteer/lib/Tracing.js +0 -99
- data/node_modules/puppeteer/lib/USKeyboardLayout.js +0 -281
- data/node_modules/puppeteer/lib/helper.js +0 -248
- data/node_modules/puppeteer/node6/lib/Browser.js +0 -394
- data/node_modules/puppeteer/node6/lib/BrowserFetcher.js +0 -357
- data/node_modules/puppeteer/node6/lib/Connection.js +0 -350
- data/node_modules/puppeteer/node6/lib/Coverage.js +0 -561
- data/node_modules/puppeteer/node6/lib/Dialog.js +0 -136
- data/node_modules/puppeteer/node6/lib/ElementHandle.js +0 -796
- data/node_modules/puppeteer/node6/lib/EmulationManager.js +0 -115
- data/node_modules/puppeteer/node6/lib/ExecutionContext.js +0 -414
- data/node_modules/puppeteer/node6/lib/FrameManager.js +0 -1621
- data/node_modules/puppeteer/node6/lib/Input.js +0 -569
- data/node_modules/puppeteer/node6/lib/Launcher.js +0 -362
- data/node_modules/puppeteer/node6/lib/Multimap.js +0 -95
- data/node_modules/puppeteer/node6/lib/NavigatorWatcher.js +0 -163
- data/node_modules/puppeteer/node6/lib/NetworkManager.js +0 -1108
- data/node_modules/puppeteer/node6/lib/Page.js +0 -2242
- data/node_modules/puppeteer/node6/lib/Pipe.js +0 -69
- data/node_modules/puppeteer/node6/lib/Puppeteer.js +0 -60
- data/node_modules/puppeteer/node6/lib/Target.js +0 -114
- data/node_modules/puppeteer/node6/lib/TaskQueue.js +0 -17
- data/node_modules/puppeteer/node6/lib/Tracing.js +0 -177
- data/node_modules/puppeteer/node6/lib/USKeyboardLayout.js +0 -281
- data/node_modules/puppeteer/node6/lib/helper.js +0 -274
- data/node_modules/puppeteer/package.json +0 -61
- data/node_modules/readable-stream/CONTRIBUTING.md +0 -38
- data/node_modules/readable-stream/GOVERNANCE.md +0 -136
- data/node_modules/readable-stream/LICENSE +0 -47
- data/node_modules/readable-stream/README.md +0 -58
- data/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md +0 -60
- data/node_modules/readable-stream/duplex-browser.js +0 -1
- data/node_modules/readable-stream/duplex.js +0 -1
- data/node_modules/readable-stream/lib/_stream_duplex.js +0 -131
- data/node_modules/readable-stream/lib/_stream_passthrough.js +0 -47
- data/node_modules/readable-stream/lib/_stream_readable.js +0 -1019
- data/node_modules/readable-stream/lib/_stream_transform.js +0 -214
- data/node_modules/readable-stream/lib/_stream_writable.js +0 -687
- data/node_modules/readable-stream/lib/internal/streams/BufferList.js +0 -79
- data/node_modules/readable-stream/lib/internal/streams/destroy.js +0 -74
- data/node_modules/readable-stream/lib/internal/streams/stream-browser.js +0 -1
- data/node_modules/readable-stream/lib/internal/streams/stream.js +0 -1
- data/node_modules/readable-stream/package.json +0 -52
- data/node_modules/readable-stream/passthrough.js +0 -1
- data/node_modules/readable-stream/readable-browser.js +0 -7
- data/node_modules/readable-stream/readable.js +0 -19
- data/node_modules/readable-stream/transform.js +0 -1
- data/node_modules/readable-stream/writable-browser.js +0 -1
- data/node_modules/readable-stream/writable.js +0 -8
- data/node_modules/rimraf/LICENSE +0 -15
- data/node_modules/rimraf/README.md +0 -101
- data/node_modules/rimraf/bin.js +0 -50
- data/node_modules/rimraf/package.json +0 -26
- data/node_modules/rimraf/rimraf.js +0 -364
- data/node_modules/safe-buffer/LICENSE +0 -21
- data/node_modules/safe-buffer/README.md +0 -584
- data/node_modules/safe-buffer/index.d.ts +0 -187
- data/node_modules/safe-buffer/index.js +0 -62
- data/node_modules/safe-buffer/package.json +0 -37
- data/node_modules/string_decoder/LICENSE +0 -48
- data/node_modules/string_decoder/README.md +0 -47
- data/node_modules/string_decoder/lib/string_decoder.js +0 -296
- data/node_modules/string_decoder/package.json +0 -31
- data/node_modules/typedarray/LICENSE +0 -35
- data/node_modules/typedarray/example/tarray.js +0 -4
- data/node_modules/typedarray/index.js +0 -630
- data/node_modules/typedarray/package.json +0 -55
- data/node_modules/typedarray/readme.markdown +0 -61
- data/node_modules/typedarray/test/server/undef_globals.js +0 -19
- data/node_modules/typedarray/test/tarray.js +0 -10
- data/node_modules/ultron/LICENSE +0 -22
- data/node_modules/ultron/README.md +0 -113
- data/node_modules/ultron/index.js +0 -136
- data/node_modules/ultron/package.json +0 -41
- data/node_modules/util-deprecate/History.md +0 -16
- data/node_modules/util-deprecate/LICENSE +0 -24
- data/node_modules/util-deprecate/README.md +0 -53
- data/node_modules/util-deprecate/browser.js +0 -67
- data/node_modules/util-deprecate/node.js +0 -6
- data/node_modules/util-deprecate/package.json +0 -27
- data/node_modules/wrappy/LICENSE +0 -15
- data/node_modules/wrappy/README.md +0 -36
- data/node_modules/wrappy/package.json +0 -29
- data/node_modules/wrappy/wrappy.js +0 -33
- data/node_modules/ws/LICENSE +0 -21
- data/node_modules/ws/README.md +0 -341
- data/node_modules/ws/index.js +0 -15
- data/node_modules/ws/lib/BufferUtil.js +0 -71
- data/node_modules/ws/lib/Constants.js +0 -10
- data/node_modules/ws/lib/ErrorCodes.js +0 -28
- data/node_modules/ws/lib/EventTarget.js +0 -151
- data/node_modules/ws/lib/Extensions.js +0 -203
- data/node_modules/ws/lib/PerMessageDeflate.js +0 -507
- data/node_modules/ws/lib/Receiver.js +0 -553
- data/node_modules/ws/lib/Sender.js +0 -412
- data/node_modules/ws/lib/Validation.js +0 -17
- data/node_modules/ws/lib/WebSocket.js +0 -717
- data/node_modules/ws/lib/WebSocketServer.js +0 -326
- data/node_modules/ws/package.json +0 -46
- data/node_modules/yauzl/LICENSE +0 -21
- data/node_modules/yauzl/README.md +0 -467
- data/node_modules/yauzl/index.js +0 -626
- data/node_modules/yauzl/package.json +0 -36
- data/package.json +0 -5
- data/yarn.lock +0 -240
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* ws: a node.js websocket client
|
|
3
|
-
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
|
4
|
-
* MIT Licensed
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
const safeBuffer = require('safe-buffer');
|
|
10
|
-
const crypto = require('crypto');
|
|
11
|
-
|
|
12
|
-
const PerMessageDeflate = require('./PerMessageDeflate');
|
|
13
|
-
const bufferUtil = require('./BufferUtil');
|
|
14
|
-
const ErrorCodes = require('./ErrorCodes');
|
|
15
|
-
const constants = require('./Constants');
|
|
16
|
-
|
|
17
|
-
const Buffer = safeBuffer.Buffer;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* HyBi Sender implementation.
|
|
21
|
-
*/
|
|
22
|
-
class Sender {
|
|
23
|
-
/**
|
|
24
|
-
* Creates a Sender instance.
|
|
25
|
-
*
|
|
26
|
-
* @param {net.Socket} socket The connection socket
|
|
27
|
-
* @param {Object} extensions An object containing the negotiated extensions
|
|
28
|
-
*/
|
|
29
|
-
constructor (socket, extensions) {
|
|
30
|
-
this._extensions = extensions || {};
|
|
31
|
-
this._socket = socket;
|
|
32
|
-
|
|
33
|
-
this._firstFragment = true;
|
|
34
|
-
this._compress = false;
|
|
35
|
-
|
|
36
|
-
this._bufferedBytes = 0;
|
|
37
|
-
this._deflating = false;
|
|
38
|
-
this._queue = [];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Frames a piece of data according to the HyBi WebSocket protocol.
|
|
43
|
-
*
|
|
44
|
-
* @param {Buffer} data The data to frame
|
|
45
|
-
* @param {Object} options Options object
|
|
46
|
-
* @param {Number} options.opcode The opcode
|
|
47
|
-
* @param {Boolean} options.readOnly Specifies whether `data` can be modified
|
|
48
|
-
* @param {Boolean} options.fin Specifies whether or not to set the FIN bit
|
|
49
|
-
* @param {Boolean} options.mask Specifies whether or not to mask `data`
|
|
50
|
-
* @param {Boolean} options.rsv1 Specifies whether or not to set the RSV1 bit
|
|
51
|
-
* @return {Buffer[]} The framed data as a list of `Buffer` instances
|
|
52
|
-
* @public
|
|
53
|
-
*/
|
|
54
|
-
static frame (data, options) {
|
|
55
|
-
const merge = data.length < 1024 || (options.mask && options.readOnly);
|
|
56
|
-
var offset = options.mask ? 6 : 2;
|
|
57
|
-
var payloadLength = data.length;
|
|
58
|
-
|
|
59
|
-
if (data.length >= 65536) {
|
|
60
|
-
offset += 8;
|
|
61
|
-
payloadLength = 127;
|
|
62
|
-
} else if (data.length > 125) {
|
|
63
|
-
offset += 2;
|
|
64
|
-
payloadLength = 126;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const target = Buffer.allocUnsafe(merge ? data.length + offset : offset);
|
|
68
|
-
|
|
69
|
-
target[0] = options.fin ? options.opcode | 0x80 : options.opcode;
|
|
70
|
-
if (options.rsv1) target[0] |= 0x40;
|
|
71
|
-
|
|
72
|
-
if (payloadLength === 126) {
|
|
73
|
-
target.writeUInt16BE(data.length, 2, true);
|
|
74
|
-
} else if (payloadLength === 127) {
|
|
75
|
-
target.writeUInt32BE(0, 2, true);
|
|
76
|
-
target.writeUInt32BE(data.length, 6, true);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (!options.mask) {
|
|
80
|
-
target[1] = payloadLength;
|
|
81
|
-
if (merge) {
|
|
82
|
-
data.copy(target, offset);
|
|
83
|
-
return [target];
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return [target, data];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const mask = crypto.randomBytes(4);
|
|
90
|
-
|
|
91
|
-
target[1] = payloadLength | 0x80;
|
|
92
|
-
target[offset - 4] = mask[0];
|
|
93
|
-
target[offset - 3] = mask[1];
|
|
94
|
-
target[offset - 2] = mask[2];
|
|
95
|
-
target[offset - 1] = mask[3];
|
|
96
|
-
|
|
97
|
-
if (merge) {
|
|
98
|
-
bufferUtil.mask(data, mask, target, offset, data.length);
|
|
99
|
-
return [target];
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
bufferUtil.mask(data, mask, data, 0, data.length);
|
|
103
|
-
return [target, data];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Sends a close message to the other peer.
|
|
108
|
-
*
|
|
109
|
-
* @param {(Number|undefined)} code The status code component of the body
|
|
110
|
-
* @param {String} data The message component of the body
|
|
111
|
-
* @param {Boolean} mask Specifies whether or not to mask the message
|
|
112
|
-
* @param {Function} cb Callback
|
|
113
|
-
* @public
|
|
114
|
-
*/
|
|
115
|
-
close (code, data, mask, cb) {
|
|
116
|
-
var buf;
|
|
117
|
-
|
|
118
|
-
if (code === undefined) {
|
|
119
|
-
code = 1000;
|
|
120
|
-
} else if (typeof code !== 'number' || !ErrorCodes.isValidErrorCode(code)) {
|
|
121
|
-
throw new Error('first argument must be a valid error code number');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (data === undefined || data === '') {
|
|
125
|
-
if (code === 1000) {
|
|
126
|
-
buf = constants.EMPTY_BUFFER;
|
|
127
|
-
} else {
|
|
128
|
-
buf = Buffer.allocUnsafe(2);
|
|
129
|
-
buf.writeUInt16BE(code, 0, true);
|
|
130
|
-
}
|
|
131
|
-
} else {
|
|
132
|
-
buf = Buffer.allocUnsafe(2 + Buffer.byteLength(data));
|
|
133
|
-
buf.writeUInt16BE(code, 0, true);
|
|
134
|
-
buf.write(data, 2);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (this._deflating) {
|
|
138
|
-
this.enqueue([this.doClose, buf, mask, cb]);
|
|
139
|
-
} else {
|
|
140
|
-
this.doClose(buf, mask, cb);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Frames and sends a close message.
|
|
146
|
-
*
|
|
147
|
-
* @param {Buffer} data The message to send
|
|
148
|
-
* @param {Boolean} mask Specifies whether or not to mask `data`
|
|
149
|
-
* @param {Function} cb Callback
|
|
150
|
-
* @private
|
|
151
|
-
*/
|
|
152
|
-
doClose (data, mask, cb) {
|
|
153
|
-
this.sendFrame(Sender.frame(data, {
|
|
154
|
-
fin: true,
|
|
155
|
-
rsv1: false,
|
|
156
|
-
opcode: 0x08,
|
|
157
|
-
mask,
|
|
158
|
-
readOnly: false
|
|
159
|
-
}), cb);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Sends a ping message to the other peer.
|
|
164
|
-
*
|
|
165
|
-
* @param {*} data The message to send
|
|
166
|
-
* @param {Boolean} mask Specifies whether or not to mask `data`
|
|
167
|
-
* @public
|
|
168
|
-
*/
|
|
169
|
-
ping (data, mask) {
|
|
170
|
-
var readOnly = true;
|
|
171
|
-
|
|
172
|
-
if (!Buffer.isBuffer(data)) {
|
|
173
|
-
if (data instanceof ArrayBuffer) {
|
|
174
|
-
data = Buffer.from(data);
|
|
175
|
-
} else if (ArrayBuffer.isView(data)) {
|
|
176
|
-
data = viewToBuffer(data);
|
|
177
|
-
} else {
|
|
178
|
-
data = Buffer.from(data);
|
|
179
|
-
readOnly = false;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (this._deflating) {
|
|
184
|
-
this.enqueue([this.doPing, data, mask, readOnly]);
|
|
185
|
-
} else {
|
|
186
|
-
this.doPing(data, mask, readOnly);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Frames and sends a ping message.
|
|
192
|
-
*
|
|
193
|
-
* @param {*} data The message to send
|
|
194
|
-
* @param {Boolean} mask Specifies whether or not to mask `data`
|
|
195
|
-
* @param {Boolean} readOnly Specifies whether `data` can be modified
|
|
196
|
-
* @private
|
|
197
|
-
*/
|
|
198
|
-
doPing (data, mask, readOnly) {
|
|
199
|
-
this.sendFrame(Sender.frame(data, {
|
|
200
|
-
fin: true,
|
|
201
|
-
rsv1: false,
|
|
202
|
-
opcode: 0x09,
|
|
203
|
-
mask,
|
|
204
|
-
readOnly
|
|
205
|
-
}));
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Sends a pong message to the other peer.
|
|
210
|
-
*
|
|
211
|
-
* @param {*} data The message to send
|
|
212
|
-
* @param {Boolean} mask Specifies whether or not to mask `data`
|
|
213
|
-
* @public
|
|
214
|
-
*/
|
|
215
|
-
pong (data, mask) {
|
|
216
|
-
var readOnly = true;
|
|
217
|
-
|
|
218
|
-
if (!Buffer.isBuffer(data)) {
|
|
219
|
-
if (data instanceof ArrayBuffer) {
|
|
220
|
-
data = Buffer.from(data);
|
|
221
|
-
} else if (ArrayBuffer.isView(data)) {
|
|
222
|
-
data = viewToBuffer(data);
|
|
223
|
-
} else {
|
|
224
|
-
data = Buffer.from(data);
|
|
225
|
-
readOnly = false;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (this._deflating) {
|
|
230
|
-
this.enqueue([this.doPong, data, mask, readOnly]);
|
|
231
|
-
} else {
|
|
232
|
-
this.doPong(data, mask, readOnly);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Frames and sends a pong message.
|
|
238
|
-
*
|
|
239
|
-
* @param {*} data The message to send
|
|
240
|
-
* @param {Boolean} mask Specifies whether or not to mask `data`
|
|
241
|
-
* @param {Boolean} readOnly Specifies whether `data` can be modified
|
|
242
|
-
* @private
|
|
243
|
-
*/
|
|
244
|
-
doPong (data, mask, readOnly) {
|
|
245
|
-
this.sendFrame(Sender.frame(data, {
|
|
246
|
-
fin: true,
|
|
247
|
-
rsv1: false,
|
|
248
|
-
opcode: 0x0a,
|
|
249
|
-
mask,
|
|
250
|
-
readOnly
|
|
251
|
-
}));
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Sends a data message to the other peer.
|
|
256
|
-
*
|
|
257
|
-
* @param {*} data The message to send
|
|
258
|
-
* @param {Object} options Options object
|
|
259
|
-
* @param {Boolean} options.compress Specifies whether or not to compress `data`
|
|
260
|
-
* @param {Boolean} options.binary Specifies whether `data` is binary or text
|
|
261
|
-
* @param {Boolean} options.fin Specifies whether the fragment is the last one
|
|
262
|
-
* @param {Boolean} options.mask Specifies whether or not to mask `data`
|
|
263
|
-
* @param {Function} cb Callback
|
|
264
|
-
* @public
|
|
265
|
-
*/
|
|
266
|
-
send (data, options, cb) {
|
|
267
|
-
var opcode = options.binary ? 2 : 1;
|
|
268
|
-
var rsv1 = options.compress;
|
|
269
|
-
var readOnly = true;
|
|
270
|
-
|
|
271
|
-
if (!Buffer.isBuffer(data)) {
|
|
272
|
-
if (data instanceof ArrayBuffer) {
|
|
273
|
-
data = Buffer.from(data);
|
|
274
|
-
} else if (ArrayBuffer.isView(data)) {
|
|
275
|
-
data = viewToBuffer(data);
|
|
276
|
-
} else {
|
|
277
|
-
data = Buffer.from(data);
|
|
278
|
-
readOnly = false;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
|
|
283
|
-
|
|
284
|
-
if (this._firstFragment) {
|
|
285
|
-
this._firstFragment = false;
|
|
286
|
-
if (rsv1 && perMessageDeflate) {
|
|
287
|
-
rsv1 = data.length >= perMessageDeflate._threshold;
|
|
288
|
-
}
|
|
289
|
-
this._compress = rsv1;
|
|
290
|
-
} else {
|
|
291
|
-
rsv1 = false;
|
|
292
|
-
opcode = 0;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (options.fin) this._firstFragment = true;
|
|
296
|
-
|
|
297
|
-
if (perMessageDeflate) {
|
|
298
|
-
const opts = {
|
|
299
|
-
fin: options.fin,
|
|
300
|
-
rsv1,
|
|
301
|
-
opcode,
|
|
302
|
-
mask: options.mask,
|
|
303
|
-
readOnly
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
if (this._deflating) {
|
|
307
|
-
this.enqueue([this.dispatch, data, this._compress, opts, cb]);
|
|
308
|
-
} else {
|
|
309
|
-
this.dispatch(data, this._compress, opts, cb);
|
|
310
|
-
}
|
|
311
|
-
} else {
|
|
312
|
-
this.sendFrame(Sender.frame(data, {
|
|
313
|
-
fin: options.fin,
|
|
314
|
-
rsv1: false,
|
|
315
|
-
opcode,
|
|
316
|
-
mask: options.mask,
|
|
317
|
-
readOnly
|
|
318
|
-
}), cb);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Dispatches a data message.
|
|
324
|
-
*
|
|
325
|
-
* @param {Buffer} data The message to send
|
|
326
|
-
* @param {Boolean} compress Specifies whether or not to compress `data`
|
|
327
|
-
* @param {Object} options Options object
|
|
328
|
-
* @param {Number} options.opcode The opcode
|
|
329
|
-
* @param {Boolean} options.readOnly Specifies whether `data` can be modified
|
|
330
|
-
* @param {Boolean} options.fin Specifies whether or not to set the FIN bit
|
|
331
|
-
* @param {Boolean} options.mask Specifies whether or not to mask `data`
|
|
332
|
-
* @param {Boolean} options.rsv1 Specifies whether or not to set the RSV1 bit
|
|
333
|
-
* @param {Function} cb Callback
|
|
334
|
-
* @private
|
|
335
|
-
*/
|
|
336
|
-
dispatch (data, compress, options, cb) {
|
|
337
|
-
if (!compress) {
|
|
338
|
-
this.sendFrame(Sender.frame(data, options), cb);
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
|
|
343
|
-
|
|
344
|
-
this._deflating = true;
|
|
345
|
-
perMessageDeflate.compress(data, options.fin, (_, buf) => {
|
|
346
|
-
options.readOnly = false;
|
|
347
|
-
this.sendFrame(Sender.frame(buf, options), cb);
|
|
348
|
-
this._deflating = false;
|
|
349
|
-
this.dequeue();
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Executes queued send operations.
|
|
355
|
-
*
|
|
356
|
-
* @private
|
|
357
|
-
*/
|
|
358
|
-
dequeue () {
|
|
359
|
-
while (!this._deflating && this._queue.length) {
|
|
360
|
-
const params = this._queue.shift();
|
|
361
|
-
|
|
362
|
-
this._bufferedBytes -= params[1].length;
|
|
363
|
-
params[0].apply(this, params.slice(1));
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
* Enqueues a send operation.
|
|
369
|
-
*
|
|
370
|
-
* @param {Array} params Send operation parameters.
|
|
371
|
-
* @private
|
|
372
|
-
*/
|
|
373
|
-
enqueue (params) {
|
|
374
|
-
this._bufferedBytes += params[1].length;
|
|
375
|
-
this._queue.push(params);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Sends a frame.
|
|
380
|
-
*
|
|
381
|
-
* @param {Buffer[]} list The frame to send
|
|
382
|
-
* @param {Function} cb Callback
|
|
383
|
-
* @private
|
|
384
|
-
*/
|
|
385
|
-
sendFrame (list, cb) {
|
|
386
|
-
if (list.length === 2) {
|
|
387
|
-
this._socket.write(list[0]);
|
|
388
|
-
this._socket.write(list[1], cb);
|
|
389
|
-
} else {
|
|
390
|
-
this._socket.write(list[0], cb);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
module.exports = Sender;
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Converts an `ArrayBuffer` view into a buffer.
|
|
399
|
-
*
|
|
400
|
-
* @param {(DataView|TypedArray)} view The view to convert
|
|
401
|
-
* @return {Buffer} Converted view
|
|
402
|
-
* @private
|
|
403
|
-
*/
|
|
404
|
-
function viewToBuffer (view) {
|
|
405
|
-
const buf = Buffer.from(view.buffer);
|
|
406
|
-
|
|
407
|
-
if (view.byteLength !== view.buffer.byteLength) {
|
|
408
|
-
return buf.slice(view.byteOffset, view.byteOffset + view.byteLength);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
return buf;
|
|
412
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* ws: a node.js websocket client
|
|
3
|
-
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
|
4
|
-
* MIT Licensed
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
try {
|
|
10
|
-
const isValidUTF8 = require('utf-8-validate');
|
|
11
|
-
|
|
12
|
-
module.exports = typeof isValidUTF8 === 'object'
|
|
13
|
-
? isValidUTF8.Validation.isValidUTF8 // utf-8-validate@<3.0.0
|
|
14
|
-
: isValidUTF8;
|
|
15
|
-
} catch (e) /* istanbul ignore next */ {
|
|
16
|
-
module.exports = () => true;
|
|
17
|
-
}
|
|
@@ -1,717 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* ws: a node.js websocket client
|
|
3
|
-
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
|
4
|
-
* MIT Licensed
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
const EventEmitter = require('events');
|
|
10
|
-
const crypto = require('crypto');
|
|
11
|
-
const Ultron = require('ultron');
|
|
12
|
-
const https = require('https');
|
|
13
|
-
const http = require('http');
|
|
14
|
-
const url = require('url');
|
|
15
|
-
|
|
16
|
-
const PerMessageDeflate = require('./PerMessageDeflate');
|
|
17
|
-
const EventTarget = require('./EventTarget');
|
|
18
|
-
const Extensions = require('./Extensions');
|
|
19
|
-
const constants = require('./Constants');
|
|
20
|
-
const Receiver = require('./Receiver');
|
|
21
|
-
const Sender = require('./Sender');
|
|
22
|
-
|
|
23
|
-
const protocolVersions = [8, 13];
|
|
24
|
-
const closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly.
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Class representing a WebSocket.
|
|
28
|
-
*
|
|
29
|
-
* @extends EventEmitter
|
|
30
|
-
*/
|
|
31
|
-
class WebSocket extends EventEmitter {
|
|
32
|
-
/**
|
|
33
|
-
* Create a new `WebSocket`.
|
|
34
|
-
*
|
|
35
|
-
* @param {String} address The URL to which to connect
|
|
36
|
-
* @param {(String|String[])} protocols The subprotocols
|
|
37
|
-
* @param {Object} options Connection options
|
|
38
|
-
*/
|
|
39
|
-
constructor (address, protocols, options) {
|
|
40
|
-
super();
|
|
41
|
-
|
|
42
|
-
if (!protocols) {
|
|
43
|
-
protocols = [];
|
|
44
|
-
} else if (typeof protocols === 'string') {
|
|
45
|
-
protocols = [protocols];
|
|
46
|
-
} else if (!Array.isArray(protocols)) {
|
|
47
|
-
options = protocols;
|
|
48
|
-
protocols = [];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
this.readyState = WebSocket.CONNECTING;
|
|
52
|
-
this.bytesReceived = 0;
|
|
53
|
-
this.extensions = {};
|
|
54
|
-
this.protocol = '';
|
|
55
|
-
|
|
56
|
-
this._binaryType = constants.BINARY_TYPES[0];
|
|
57
|
-
this._finalize = this.finalize.bind(this);
|
|
58
|
-
this._closeFrameReceived = false;
|
|
59
|
-
this._closeFrameSent = false;
|
|
60
|
-
this._closeMessage = '';
|
|
61
|
-
this._closeTimer = null;
|
|
62
|
-
this._finalized = false;
|
|
63
|
-
this._closeCode = 1006;
|
|
64
|
-
this._receiver = null;
|
|
65
|
-
this._sender = null;
|
|
66
|
-
this._socket = null;
|
|
67
|
-
this._ultron = null;
|
|
68
|
-
|
|
69
|
-
if (Array.isArray(address)) {
|
|
70
|
-
initAsServerClient.call(this, address[0], address[1], options);
|
|
71
|
-
} else {
|
|
72
|
-
initAsClient.call(this, address, protocols, options);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
get CONNECTING () { return WebSocket.CONNECTING; }
|
|
77
|
-
get CLOSING () { return WebSocket.CLOSING; }
|
|
78
|
-
get CLOSED () { return WebSocket.CLOSED; }
|
|
79
|
-
get OPEN () { return WebSocket.OPEN; }
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @type {Number}
|
|
83
|
-
*/
|
|
84
|
-
get bufferedAmount () {
|
|
85
|
-
var amount = 0;
|
|
86
|
-
|
|
87
|
-
if (this._socket) {
|
|
88
|
-
amount = this._socket.bufferSize + this._sender._bufferedBytes;
|
|
89
|
-
}
|
|
90
|
-
return amount;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* This deviates from the WHATWG interface since ws doesn't support the required
|
|
95
|
-
* default "blob" type (instead we define a custom "nodebuffer" type).
|
|
96
|
-
*
|
|
97
|
-
* @type {String}
|
|
98
|
-
*/
|
|
99
|
-
get binaryType () {
|
|
100
|
-
return this._binaryType;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
set binaryType (type) {
|
|
104
|
-
if (constants.BINARY_TYPES.indexOf(type) < 0) return;
|
|
105
|
-
|
|
106
|
-
this._binaryType = type;
|
|
107
|
-
|
|
108
|
-
//
|
|
109
|
-
// Allow to change `binaryType` on the fly.
|
|
110
|
-
//
|
|
111
|
-
if (this._receiver) this._receiver._binaryType = type;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Set up the socket and the internal resources.
|
|
116
|
-
*
|
|
117
|
-
* @param {net.Socket} socket The network socket between the server and client
|
|
118
|
-
* @param {Buffer} head The first packet of the upgraded stream
|
|
119
|
-
* @private
|
|
120
|
-
*/
|
|
121
|
-
setSocket (socket, head) {
|
|
122
|
-
socket.setTimeout(0);
|
|
123
|
-
socket.setNoDelay();
|
|
124
|
-
|
|
125
|
-
this._receiver = new Receiver(this.extensions, this._maxPayload, this.binaryType);
|
|
126
|
-
this._sender = new Sender(socket, this.extensions);
|
|
127
|
-
this._ultron = new Ultron(socket);
|
|
128
|
-
this._socket = socket;
|
|
129
|
-
|
|
130
|
-
this._ultron.on('close', this._finalize);
|
|
131
|
-
this._ultron.on('error', this._finalize);
|
|
132
|
-
this._ultron.on('end', this._finalize);
|
|
133
|
-
|
|
134
|
-
if (head.length > 0) socket.unshift(head);
|
|
135
|
-
|
|
136
|
-
this._ultron.on('data', (data) => {
|
|
137
|
-
this.bytesReceived += data.length;
|
|
138
|
-
this._receiver.add(data);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
this._receiver.onmessage = (data) => this.emit('message', data);
|
|
142
|
-
this._receiver.onping = (data) => {
|
|
143
|
-
this.pong(data, !this._isServer, true);
|
|
144
|
-
this.emit('ping', data);
|
|
145
|
-
};
|
|
146
|
-
this._receiver.onpong = (data) => this.emit('pong', data);
|
|
147
|
-
this._receiver.onclose = (code, reason) => {
|
|
148
|
-
this._closeFrameReceived = true;
|
|
149
|
-
this._closeMessage = reason;
|
|
150
|
-
this._closeCode = code;
|
|
151
|
-
if (!this._finalized) this.close(code, reason);
|
|
152
|
-
};
|
|
153
|
-
this._receiver.onerror = (error, code) => {
|
|
154
|
-
this._closeMessage = '';
|
|
155
|
-
this._closeCode = code;
|
|
156
|
-
|
|
157
|
-
//
|
|
158
|
-
// Ensure that the error is emitted even if `WebSocket#finalize()` has
|
|
159
|
-
// already been called.
|
|
160
|
-
//
|
|
161
|
-
this.readyState = WebSocket.CLOSING;
|
|
162
|
-
this.emit('error', error);
|
|
163
|
-
this.finalize(true);
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
this.readyState = WebSocket.OPEN;
|
|
167
|
-
this.emit('open');
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Clean up and release internal resources.
|
|
172
|
-
*
|
|
173
|
-
* @param {(Boolean|Error)} error Indicates whether or not an error occurred
|
|
174
|
-
* @private
|
|
175
|
-
*/
|
|
176
|
-
finalize (error) {
|
|
177
|
-
if (this._finalized) return;
|
|
178
|
-
|
|
179
|
-
this.readyState = WebSocket.CLOSING;
|
|
180
|
-
this._finalized = true;
|
|
181
|
-
|
|
182
|
-
if (typeof error === 'object') this.emit('error', error);
|
|
183
|
-
if (!this._socket) return this.emitClose();
|
|
184
|
-
|
|
185
|
-
clearTimeout(this._closeTimer);
|
|
186
|
-
this._closeTimer = null;
|
|
187
|
-
|
|
188
|
-
this._ultron.destroy();
|
|
189
|
-
this._ultron = null;
|
|
190
|
-
|
|
191
|
-
this._socket.on('error', constants.NOOP);
|
|
192
|
-
|
|
193
|
-
if (!error) this._socket.end();
|
|
194
|
-
else this._socket.destroy();
|
|
195
|
-
|
|
196
|
-
this._socket = null;
|
|
197
|
-
this._sender = null;
|
|
198
|
-
|
|
199
|
-
this._receiver.cleanup(() => this.emitClose());
|
|
200
|
-
this._receiver = null;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Emit the `close` event.
|
|
205
|
-
*
|
|
206
|
-
* @private
|
|
207
|
-
*/
|
|
208
|
-
emitClose () {
|
|
209
|
-
this.readyState = WebSocket.CLOSED;
|
|
210
|
-
|
|
211
|
-
this.emit('close', this._closeCode, this._closeMessage);
|
|
212
|
-
|
|
213
|
-
if (this.extensions[PerMessageDeflate.extensionName]) {
|
|
214
|
-
this.extensions[PerMessageDeflate.extensionName].cleanup();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
this.extensions = null;
|
|
218
|
-
|
|
219
|
-
this.removeAllListeners();
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Pause the socket stream.
|
|
224
|
-
*
|
|
225
|
-
* @public
|
|
226
|
-
*/
|
|
227
|
-
pause () {
|
|
228
|
-
if (this.readyState !== WebSocket.OPEN) throw new Error('not opened');
|
|
229
|
-
|
|
230
|
-
this._socket.pause();
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Resume the socket stream
|
|
235
|
-
*
|
|
236
|
-
* @public
|
|
237
|
-
*/
|
|
238
|
-
resume () {
|
|
239
|
-
if (this.readyState !== WebSocket.OPEN) throw new Error('not opened');
|
|
240
|
-
|
|
241
|
-
this._socket.resume();
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Start a closing handshake.
|
|
246
|
-
*
|
|
247
|
-
* +----------+ +-----------+ +----------+
|
|
248
|
-
* + - - -|ws.close()|---->|close frame|-->|ws.close()|- - - -
|
|
249
|
-
* +----------+ +-----------+ +----------+ |
|
|
250
|
-
* | +----------+ +-----------+ |
|
|
251
|
-
* |ws.close()|<----|close frame|<--------+ |
|
|
252
|
-
* +----------+ +-----------+ |
|
|
253
|
-
* CLOSING | +---+ | CLOSING
|
|
254
|
-
* | +---|fin|<------------+
|
|
255
|
-
* | | | +---+ |
|
|
256
|
-
* | | +---+ +-------------+
|
|
257
|
-
* | +----------+-->|fin|----->|ws.finalize()| - - +
|
|
258
|
-
* | +---+ +-------------+
|
|
259
|
-
* | +-------------+ |
|
|
260
|
-
* - - -|ws.finalize()|<--+
|
|
261
|
-
* +-------------+
|
|
262
|
-
*
|
|
263
|
-
* @param {Number} code Status code explaining why the connection is closing
|
|
264
|
-
* @param {String} data A string explaining why the connection is closing
|
|
265
|
-
* @public
|
|
266
|
-
*/
|
|
267
|
-
close (code, data) {
|
|
268
|
-
if (this.readyState === WebSocket.CLOSED) return;
|
|
269
|
-
if (this.readyState === WebSocket.CONNECTING) {
|
|
270
|
-
this._req.abort();
|
|
271
|
-
this.finalize(new Error('closed before the connection is established'));
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (this.readyState === WebSocket.CLOSING) {
|
|
276
|
-
if (this._closeFrameSent && this._closeFrameReceived) this._socket.end();
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
this.readyState = WebSocket.CLOSING;
|
|
281
|
-
this._sender.close(code, data, !this._isServer, (err) => {
|
|
282
|
-
//
|
|
283
|
-
// This error is handled by the `'error'` listener on the socket. We only
|
|
284
|
-
// want to know if the close frame has been sent here.
|
|
285
|
-
//
|
|
286
|
-
if (err) return;
|
|
287
|
-
|
|
288
|
-
this._closeFrameSent = true;
|
|
289
|
-
|
|
290
|
-
if (!this._finalized) {
|
|
291
|
-
if (this._closeFrameReceived) this._socket.end();
|
|
292
|
-
|
|
293
|
-
//
|
|
294
|
-
// Ensure that the connection is cleaned up even when the closing
|
|
295
|
-
// handshake fails.
|
|
296
|
-
//
|
|
297
|
-
this._closeTimer = setTimeout(this._finalize, closeTimeout, true);
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Send a ping message.
|
|
304
|
-
*
|
|
305
|
-
* @param {*} data The message to send
|
|
306
|
-
* @param {Boolean} mask Indicates whether or not to mask `data`
|
|
307
|
-
* @param {Boolean} failSilently Indicates whether or not to throw if `readyState` isn't `OPEN`
|
|
308
|
-
* @public
|
|
309
|
-
*/
|
|
310
|
-
ping (data, mask, failSilently) {
|
|
311
|
-
if (this.readyState !== WebSocket.OPEN) {
|
|
312
|
-
if (failSilently) return;
|
|
313
|
-
throw new Error('not opened');
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (typeof data === 'number') data = data.toString();
|
|
317
|
-
if (mask === undefined) mask = !this._isServer;
|
|
318
|
-
this._sender.ping(data || constants.EMPTY_BUFFER, mask);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Send a pong message.
|
|
323
|
-
*
|
|
324
|
-
* @param {*} data The message to send
|
|
325
|
-
* @param {Boolean} mask Indicates whether or not to mask `data`
|
|
326
|
-
* @param {Boolean} failSilently Indicates whether or not to throw if `readyState` isn't `OPEN`
|
|
327
|
-
* @public
|
|
328
|
-
*/
|
|
329
|
-
pong (data, mask, failSilently) {
|
|
330
|
-
if (this.readyState !== WebSocket.OPEN) {
|
|
331
|
-
if (failSilently) return;
|
|
332
|
-
throw new Error('not opened');
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if (typeof data === 'number') data = data.toString();
|
|
336
|
-
if (mask === undefined) mask = !this._isServer;
|
|
337
|
-
this._sender.pong(data || constants.EMPTY_BUFFER, mask);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Send a data message.
|
|
342
|
-
*
|
|
343
|
-
* @param {*} data The message to send
|
|
344
|
-
* @param {Object} options Options object
|
|
345
|
-
* @param {Boolean} options.compress Specifies whether or not to compress `data`
|
|
346
|
-
* @param {Boolean} options.binary Specifies whether `data` is binary or text
|
|
347
|
-
* @param {Boolean} options.fin Specifies whether the fragment is the last one
|
|
348
|
-
* @param {Boolean} options.mask Specifies whether or not to mask `data`
|
|
349
|
-
* @param {Function} cb Callback which is executed when data is written out
|
|
350
|
-
* @public
|
|
351
|
-
*/
|
|
352
|
-
send (data, options, cb) {
|
|
353
|
-
if (typeof options === 'function') {
|
|
354
|
-
cb = options;
|
|
355
|
-
options = {};
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (this.readyState !== WebSocket.OPEN) {
|
|
359
|
-
if (cb) cb(new Error('not opened'));
|
|
360
|
-
else throw new Error('not opened');
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (typeof data === 'number') data = data.toString();
|
|
365
|
-
|
|
366
|
-
const opts = Object.assign({
|
|
367
|
-
binary: typeof data !== 'string',
|
|
368
|
-
mask: !this._isServer,
|
|
369
|
-
compress: true,
|
|
370
|
-
fin: true
|
|
371
|
-
}, options);
|
|
372
|
-
|
|
373
|
-
if (!this.extensions[PerMessageDeflate.extensionName]) {
|
|
374
|
-
opts.compress = false;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
this._sender.send(data || constants.EMPTY_BUFFER, opts, cb);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Forcibly close the connection.
|
|
382
|
-
*
|
|
383
|
-
* @public
|
|
384
|
-
*/
|
|
385
|
-
terminate () {
|
|
386
|
-
if (this.readyState === WebSocket.CLOSED) return;
|
|
387
|
-
if (this.readyState === WebSocket.CONNECTING) {
|
|
388
|
-
this._req.abort();
|
|
389
|
-
this.finalize(new Error('closed before the connection is established'));
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
this.finalize(true);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
WebSocket.CONNECTING = 0;
|
|
398
|
-
WebSocket.OPEN = 1;
|
|
399
|
-
WebSocket.CLOSING = 2;
|
|
400
|
-
WebSocket.CLOSED = 3;
|
|
401
|
-
|
|
402
|
-
//
|
|
403
|
-
// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes.
|
|
404
|
-
// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface
|
|
405
|
-
//
|
|
406
|
-
['open', 'error', 'close', 'message'].forEach((method) => {
|
|
407
|
-
Object.defineProperty(WebSocket.prototype, `on${method}`, {
|
|
408
|
-
/**
|
|
409
|
-
* Return the listener of the event.
|
|
410
|
-
*
|
|
411
|
-
* @return {(Function|undefined)} The event listener or `undefined`
|
|
412
|
-
* @public
|
|
413
|
-
*/
|
|
414
|
-
get () {
|
|
415
|
-
const listeners = this.listeners(method);
|
|
416
|
-
for (var i = 0; i < listeners.length; i++) {
|
|
417
|
-
if (listeners[i]._listener) return listeners[i]._listener;
|
|
418
|
-
}
|
|
419
|
-
},
|
|
420
|
-
/**
|
|
421
|
-
* Add a listener for the event.
|
|
422
|
-
*
|
|
423
|
-
* @param {Function} listener The listener to add
|
|
424
|
-
* @public
|
|
425
|
-
*/
|
|
426
|
-
set (listener) {
|
|
427
|
-
const listeners = this.listeners(method);
|
|
428
|
-
for (var i = 0; i < listeners.length; i++) {
|
|
429
|
-
//
|
|
430
|
-
// Remove only the listeners added via `addEventListener`.
|
|
431
|
-
//
|
|
432
|
-
if (listeners[i]._listener) this.removeListener(method, listeners[i]);
|
|
433
|
-
}
|
|
434
|
-
this.addEventListener(method, listener);
|
|
435
|
-
}
|
|
436
|
-
});
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
WebSocket.prototype.addEventListener = EventTarget.addEventListener;
|
|
440
|
-
WebSocket.prototype.removeEventListener = EventTarget.removeEventListener;
|
|
441
|
-
|
|
442
|
-
module.exports = WebSocket;
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* Initialize a WebSocket server client.
|
|
446
|
-
*
|
|
447
|
-
* @param {http.IncomingMessage} req The request object
|
|
448
|
-
* @param {net.Socket} socket The network socket between the server and client
|
|
449
|
-
* @param {Buffer} head The first packet of the upgraded stream
|
|
450
|
-
* @param {Object} options WebSocket attributes
|
|
451
|
-
* @param {Number} options.protocolVersion The WebSocket protocol version
|
|
452
|
-
* @param {Object} options.extensions The negotiated extensions
|
|
453
|
-
* @param {Number} options.maxPayload The maximum allowed message size
|
|
454
|
-
* @param {String} options.protocol The chosen subprotocol
|
|
455
|
-
* @private
|
|
456
|
-
*/
|
|
457
|
-
function initAsServerClient (socket, head, options) {
|
|
458
|
-
this.protocolVersion = options.protocolVersion;
|
|
459
|
-
this._maxPayload = options.maxPayload;
|
|
460
|
-
this.extensions = options.extensions;
|
|
461
|
-
this.protocol = options.protocol;
|
|
462
|
-
|
|
463
|
-
this._isServer = true;
|
|
464
|
-
|
|
465
|
-
this.setSocket(socket, head);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Initialize a WebSocket client.
|
|
470
|
-
*
|
|
471
|
-
* @param {String} address The URL to which to connect
|
|
472
|
-
* @param {String[]} protocols The list of subprotocols
|
|
473
|
-
* @param {Object} options Connection options
|
|
474
|
-
* @param {String} options.protocol Value of the `Sec-WebSocket-Protocol` header
|
|
475
|
-
* @param {(Boolean|Object)} options.perMessageDeflate Enable/disable permessage-deflate
|
|
476
|
-
* @param {Number} options.handshakeTimeout Timeout in milliseconds for the handshake request
|
|
477
|
-
* @param {String} options.localAddress Local interface to bind for network connections
|
|
478
|
-
* @param {Number} options.protocolVersion Value of the `Sec-WebSocket-Version` header
|
|
479
|
-
* @param {Object} options.headers An object containing request headers
|
|
480
|
-
* @param {String} options.origin Value of the `Origin` or `Sec-WebSocket-Origin` header
|
|
481
|
-
* @param {http.Agent} options.agent Use the specified Agent
|
|
482
|
-
* @param {String} options.host Value of the `Host` header
|
|
483
|
-
* @param {Number} options.family IP address family to use during hostname lookup (4 or 6).
|
|
484
|
-
* @param {Function} options.checkServerIdentity A function to validate the server hostname
|
|
485
|
-
* @param {Boolean} options.rejectUnauthorized Verify or not the server certificate
|
|
486
|
-
* @param {String} options.passphrase The passphrase for the private key or pfx
|
|
487
|
-
* @param {String} options.ciphers The ciphers to use or exclude
|
|
488
|
-
* @param {String} options.ecdhCurve The curves for ECDH key agreement to use or exclude
|
|
489
|
-
* @param {(String|String[]|Buffer|Buffer[])} options.cert The certificate key
|
|
490
|
-
* @param {(String|String[]|Buffer|Buffer[])} options.key The private key
|
|
491
|
-
* @param {(String|Buffer)} options.pfx The private key, certificate, and CA certs
|
|
492
|
-
* @param {(String|String[]|Buffer|Buffer[])} options.ca Trusted certificates
|
|
493
|
-
* @private
|
|
494
|
-
*/
|
|
495
|
-
function initAsClient (address, protocols, options) {
|
|
496
|
-
options = Object.assign({
|
|
497
|
-
protocolVersion: protocolVersions[1],
|
|
498
|
-
protocol: protocols.join(','),
|
|
499
|
-
perMessageDeflate: true,
|
|
500
|
-
handshakeTimeout: null,
|
|
501
|
-
localAddress: null,
|
|
502
|
-
headers: null,
|
|
503
|
-
family: null,
|
|
504
|
-
origin: null,
|
|
505
|
-
agent: null,
|
|
506
|
-
host: null,
|
|
507
|
-
|
|
508
|
-
//
|
|
509
|
-
// SSL options.
|
|
510
|
-
//
|
|
511
|
-
checkServerIdentity: null,
|
|
512
|
-
rejectUnauthorized: null,
|
|
513
|
-
passphrase: null,
|
|
514
|
-
ciphers: null,
|
|
515
|
-
ecdhCurve: null,
|
|
516
|
-
cert: null,
|
|
517
|
-
key: null,
|
|
518
|
-
pfx: null,
|
|
519
|
-
ca: null
|
|
520
|
-
}, options);
|
|
521
|
-
|
|
522
|
-
if (protocolVersions.indexOf(options.protocolVersion) === -1) {
|
|
523
|
-
throw new Error(
|
|
524
|
-
`unsupported protocol version: ${options.protocolVersion} ` +
|
|
525
|
-
`(supported versions: ${protocolVersions.join(', ')})`
|
|
526
|
-
);
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
this.protocolVersion = options.protocolVersion;
|
|
530
|
-
this._isServer = false;
|
|
531
|
-
this.url = address;
|
|
532
|
-
|
|
533
|
-
const serverUrl = url.parse(address);
|
|
534
|
-
const isUnixSocket = serverUrl.protocol === 'ws+unix:';
|
|
535
|
-
|
|
536
|
-
if (!serverUrl.host && (!isUnixSocket || !serverUrl.path)) {
|
|
537
|
-
throw new Error('invalid url');
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
const isSecure = serverUrl.protocol === 'wss:' || serverUrl.protocol === 'https:';
|
|
541
|
-
const key = crypto.randomBytes(16).toString('base64');
|
|
542
|
-
const httpObj = isSecure ? https : http;
|
|
543
|
-
var perMessageDeflate;
|
|
544
|
-
|
|
545
|
-
const requestOptions = {
|
|
546
|
-
port: serverUrl.port || (isSecure ? 443 : 80),
|
|
547
|
-
host: serverUrl.hostname,
|
|
548
|
-
path: '/',
|
|
549
|
-
headers: {
|
|
550
|
-
'Sec-WebSocket-Version': options.protocolVersion,
|
|
551
|
-
'Sec-WebSocket-Key': key,
|
|
552
|
-
'Connection': 'Upgrade',
|
|
553
|
-
'Upgrade': 'websocket'
|
|
554
|
-
}
|
|
555
|
-
};
|
|
556
|
-
|
|
557
|
-
if (options.headers) Object.assign(requestOptions.headers, options.headers);
|
|
558
|
-
if (options.perMessageDeflate) {
|
|
559
|
-
perMessageDeflate = new PerMessageDeflate(
|
|
560
|
-
options.perMessageDeflate !== true ? options.perMessageDeflate : {},
|
|
561
|
-
false
|
|
562
|
-
);
|
|
563
|
-
requestOptions.headers['Sec-WebSocket-Extensions'] = Extensions.format({
|
|
564
|
-
[PerMessageDeflate.extensionName]: perMessageDeflate.offer()
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
if (options.protocol) {
|
|
568
|
-
requestOptions.headers['Sec-WebSocket-Protocol'] = options.protocol;
|
|
569
|
-
}
|
|
570
|
-
if (options.origin) {
|
|
571
|
-
if (options.protocolVersion < 13) {
|
|
572
|
-
requestOptions.headers['Sec-WebSocket-Origin'] = options.origin;
|
|
573
|
-
} else {
|
|
574
|
-
requestOptions.headers.Origin = options.origin;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
if (options.host) requestOptions.headers.Host = options.host;
|
|
578
|
-
if (serverUrl.auth) requestOptions.auth = serverUrl.auth;
|
|
579
|
-
|
|
580
|
-
if (options.localAddress) requestOptions.localAddress = options.localAddress;
|
|
581
|
-
if (options.family) requestOptions.family = options.family;
|
|
582
|
-
|
|
583
|
-
if (isUnixSocket) {
|
|
584
|
-
const parts = serverUrl.path.split(':');
|
|
585
|
-
|
|
586
|
-
requestOptions.socketPath = parts[0];
|
|
587
|
-
requestOptions.path = parts[1];
|
|
588
|
-
} else if (serverUrl.path) {
|
|
589
|
-
//
|
|
590
|
-
// Make sure that path starts with `/`.
|
|
591
|
-
//
|
|
592
|
-
if (serverUrl.path.charAt(0) !== '/') {
|
|
593
|
-
requestOptions.path = `/${serverUrl.path}`;
|
|
594
|
-
} else {
|
|
595
|
-
requestOptions.path = serverUrl.path;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
var agent = options.agent;
|
|
600
|
-
|
|
601
|
-
//
|
|
602
|
-
// A custom agent is required for these options.
|
|
603
|
-
//
|
|
604
|
-
if (
|
|
605
|
-
options.rejectUnauthorized != null ||
|
|
606
|
-
options.checkServerIdentity ||
|
|
607
|
-
options.passphrase ||
|
|
608
|
-
options.ciphers ||
|
|
609
|
-
options.ecdhCurve ||
|
|
610
|
-
options.cert ||
|
|
611
|
-
options.key ||
|
|
612
|
-
options.pfx ||
|
|
613
|
-
options.ca
|
|
614
|
-
) {
|
|
615
|
-
if (options.passphrase) requestOptions.passphrase = options.passphrase;
|
|
616
|
-
if (options.ciphers) requestOptions.ciphers = options.ciphers;
|
|
617
|
-
if (options.ecdhCurve) requestOptions.ecdhCurve = options.ecdhCurve;
|
|
618
|
-
if (options.cert) requestOptions.cert = options.cert;
|
|
619
|
-
if (options.key) requestOptions.key = options.key;
|
|
620
|
-
if (options.pfx) requestOptions.pfx = options.pfx;
|
|
621
|
-
if (options.ca) requestOptions.ca = options.ca;
|
|
622
|
-
if (options.checkServerIdentity) {
|
|
623
|
-
requestOptions.checkServerIdentity = options.checkServerIdentity;
|
|
624
|
-
}
|
|
625
|
-
if (options.rejectUnauthorized != null) {
|
|
626
|
-
requestOptions.rejectUnauthorized = options.rejectUnauthorized;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
if (!agent) agent = new httpObj.Agent(requestOptions);
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
if (agent) requestOptions.agent = agent;
|
|
633
|
-
|
|
634
|
-
this._req = httpObj.get(requestOptions);
|
|
635
|
-
|
|
636
|
-
if (options.handshakeTimeout) {
|
|
637
|
-
this._req.setTimeout(options.handshakeTimeout, () => {
|
|
638
|
-
this._req.abort();
|
|
639
|
-
this.finalize(new Error('opening handshake has timed out'));
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
this._req.on('error', (error) => {
|
|
644
|
-
if (this._req.aborted) return;
|
|
645
|
-
|
|
646
|
-
this._req = null;
|
|
647
|
-
this.finalize(error);
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
this._req.on('response', (res) => {
|
|
651
|
-
if (!this.emit('unexpected-response', this._req, res)) {
|
|
652
|
-
this._req.abort();
|
|
653
|
-
this.finalize(new Error(`unexpected server response (${res.statusCode})`));
|
|
654
|
-
}
|
|
655
|
-
});
|
|
656
|
-
|
|
657
|
-
this._req.on('upgrade', (res, socket, head) => {
|
|
658
|
-
this.emit('headers', res.headers, res);
|
|
659
|
-
|
|
660
|
-
//
|
|
661
|
-
// The user may have closed the connection from a listener of the `headers`
|
|
662
|
-
// event.
|
|
663
|
-
//
|
|
664
|
-
if (this.readyState !== WebSocket.CONNECTING) return;
|
|
665
|
-
|
|
666
|
-
this._req = null;
|
|
667
|
-
|
|
668
|
-
const digest = crypto.createHash('sha1')
|
|
669
|
-
.update(key + constants.GUID, 'binary')
|
|
670
|
-
.digest('base64');
|
|
671
|
-
|
|
672
|
-
if (res.headers['sec-websocket-accept'] !== digest) {
|
|
673
|
-
socket.destroy();
|
|
674
|
-
return this.finalize(new Error('invalid server key'));
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
const serverProt = res.headers['sec-websocket-protocol'];
|
|
678
|
-
const protList = (options.protocol || '').split(/, */);
|
|
679
|
-
var protError;
|
|
680
|
-
|
|
681
|
-
if (!options.protocol && serverProt) {
|
|
682
|
-
protError = 'server sent a subprotocol even though none requested';
|
|
683
|
-
} else if (options.protocol && !serverProt) {
|
|
684
|
-
protError = 'server sent no subprotocol even though requested';
|
|
685
|
-
} else if (serverProt && protList.indexOf(serverProt) === -1) {
|
|
686
|
-
protError = 'server responded with an invalid protocol';
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
if (protError) {
|
|
690
|
-
socket.destroy();
|
|
691
|
-
return this.finalize(new Error(protError));
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
if (serverProt) this.protocol = serverProt;
|
|
695
|
-
|
|
696
|
-
if (perMessageDeflate) {
|
|
697
|
-
try {
|
|
698
|
-
const serverExtensions = Extensions.parse(
|
|
699
|
-
res.headers['sec-websocket-extensions']
|
|
700
|
-
);
|
|
701
|
-
|
|
702
|
-
if (serverExtensions[PerMessageDeflate.extensionName]) {
|
|
703
|
-
perMessageDeflate.accept(
|
|
704
|
-
serverExtensions[PerMessageDeflate.extensionName]
|
|
705
|
-
);
|
|
706
|
-
this.extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
|
|
707
|
-
}
|
|
708
|
-
} catch (err) {
|
|
709
|
-
socket.destroy();
|
|
710
|
-
this.finalize(new Error('invalid Sec-WebSocket-Extensions header'));
|
|
711
|
-
return;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
this.setSocket(socket, head);
|
|
716
|
-
});
|
|
717
|
-
}
|