[
  {
    "path": ".gitattributes",
    "content": "example/wsgi/static/engine.io.js linguist-vendored\nexample/aiohttp/static/engine.io.js linguist-vendored\n\ntests/common/index.html binary\ntests/common/files/index.html binary\ntests/common/files/file.txt binary\ntests/async/index.html binary\ntests/async/files/index.html binary\ntests/async/files/file.txt binary\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**IMPORTANT**: If you have a question, or you are not sure if you have found a bug in this package, then you are in the wrong place. Hit back in your web browser, and then open a GitHub Discussion instead. Likewise, if you are unable to provide the information requested below, open a discussion to troubleshoot your issue.\n\n**Describe the bug**\nA clear and concise description of what the bug is. If you are getting errors, please include the complete error message, including the stack trace.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Logs**\nPlease provide relevant logs from the server and the client. On the Python server and client, add the `logger=True` and `engineio_logger=True` arguments to your `Server()` or `Client()` objects to get logs dumped on your terminal. If you are using the JavaScript client, see [here](https://socket.io/docs/v4/logging-and-debugging/) for how to enable logs.\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: GitHub Discussions\n    url: https://github.com/miguelgrinberg/python-engineio/discussions\n    about: Ask questions here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Logs**\nPlease provide relevant logs from the server and the client. On the Python server and client, add the `logger=True` and `engineio_logger=True` arguments to your `Server()` or `Client()` objects to get logs dumped on your terminal. If you are using the JavaScript client, see [here](https://socket.io/docs/v4/logging-and-debugging/) for how to enable logs.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/workflows/tests.yml",
    "content": "name: build\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\njobs:\n  lint:\n    name: lint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-python@v3\n      - run: python -m pip install --upgrade pip wheel\n      - run: pip install tox tox-gh-actions\n      - run: tox -eflake8\n      - run: tox -edocs\n  tests:\n    name: tests\n    strategy:\n      matrix:\n        os: [ubuntu-latest, macos-latest, windows-latest]\n        python: ['3.10', '3.11', '3.12', '3.13', '3.14', 'pypy-3.11']\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-python@v3\n        with:\n          python-version: ${{ matrix.python }}\n      - run: python -m pip install --upgrade pip wheel\n      - run: pip install tox tox-gh-actions\n      - run: tox\n  coverage:\n    name: coverage\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-python@v3\n      - run: python -m pip install --upgrade pip wheel\n      - run: pip install tox tox-gh-actions\n      - run: tox\n      - uses: codecov/codecov-action@v3\n        with:\n          files: ./coverage.xml\n          fail_ci_if_error: true\n          token: ${{ secrets.CODECOV_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "*.py[cod]\n\n# C extensions\n*.so\n\n# Packages\n*.egg\n*.egg-info\ndist\nbuild\neggs\nparts\nvar\nsdist\ndevelop-eggs\n.installed.cfg\nlib\nlib64\n__pycache__\n\n# Installer logs\npip-log.txt\n\n# Unit test / coverage reports\n.coverage\n.tox\nnosetests.xml\n\n# Translations\n*.mo\n\n# Mr Developer\n.mr.developer.cfg\n.project\n.pydevproject\n\ndocs/_build\nvenv*\n.eggs\n.ropeproject\ntags\n.idea\n.vscode\nhtmlcov\n*.swp\nnode_modules\n.python-version\n"
  },
  {
    "path": ".readthedocs.yaml",
    "content": "version: 2\n\nbuild:\n  os: ubuntu-22.04\n  tools:\n    python: \"3.11\"\n\nsphinx:\n  configuration: docs/conf.py\n\npython:\n  install:\n    - method: pip\n      path: .\n      extra_requirements:\n        - docs\n"
  },
  {
    "path": "CHANGES.md",
    "content": "# python-engineio change log\n\n**Release 4.13.1** - 2026-02-06\n\n- Document that a process can have only one custom JSON module ([commit](https://github.com/miguelgrinberg/python-engineio/commit/119ec1ee1f486035e837625161eea10183b9c52b))\n- Switch to Furo documentation template ([commit](https://github.com/miguelgrinberg/python-engineio/commit/15e59899fe6387eb0fbe14160dbf298c01c115d5))\n\n**Release 4.13.0** - 2025-12-24\n\n- Apply escaping rules when parsing cookie values ([commit](https://github.com/miguelgrinberg/python-engineio/commit/04e7c4dd4792d1f551b71930ec771fbb96cdaaf2))\n- Several minor improvements to the aiohttp integration [#419](https://github.com/miguelgrinberg/python-engineio/issues/419) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f7cb71c9d7ef961e839f0eb1e570d76b4ce481da)) (thanks **PaulWasTaken**!)\n- Clarify logging behavior in documentation [#421](https://github.com/miguelgrinberg/python-engineio/issues/421) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7fe1771e7463960f6ef08f9bcc22b42c8df1012b)) (thanks **ZipFile**!)\n- Address deprecation warnings [#422](https://github.com/miguelgrinberg/python-engineio/issues/422) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b90cbf2b981c301968611b495dd548c4b0153223))\n- Add 3.14 and pypy-3.11 CI builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/df3d9741495d93f4ad0f2ec9f7b3a1d795f2234c))\n- Drop Python 3.8 and 3.9 from CI builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/697b50f5bbc68b2416778d537ed88fefc8b004f0))\n\n**Release 4.12.3** - 2025-09-28\n\n- Reset client queue upon disconnection [#414](https://github.com/miguelgrinberg/python-engineio/issues/414) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/af57bf235b824f7f179a68ef61a03d76a2c56655))\n- Support `['*']` in addition to `'*'` in the `cors_allowed_origins` option [#410](https://github.com/miguelgrinberg/python-engineio/issues/410) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d59658c22207a8ca9f8c9c28312887da8fd9ee29)) (thanks **Wu Clan**!)\n\n**Release 4.12.2** - 2025-06-04\n\n- Support new monkey-patched gevent `Queue` class in the client [#403](https://github.com/miguelgrinberg/python-engineio/issues/403) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/dcde006b62e004c8a1d29d3478c95fbffbb11122))\n- Better support of the ASGI spec when interpreting WebSocket events [#405](https://github.com/miguelgrinberg/python-engineio/issues/405) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/86cb4d22be1735f0346f35ecb912818479b74f05)) (thanks **Eric Zhang**!)\n\n**Release 4.12.1** - 2025-05-11\n\n- Accept empty binary values in the async server [#404](https://github.com/miguelgrinberg/python-engineio/issues/404) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/83691dd46336f10de8f288b3aa23b60e211307e1))\n- Add SPDX license identifier [#401](https://github.com/miguelgrinberg/python-engineio/issues/401) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b7f1e680f7d012294402c7e2a50d7dbcd9b2e40f)) (thanks **Marc Mueller**!)\n\n**Release 4.12.0** - 2025-04-12\n\n- Optimize packet parsing to avoid unnecessary calls to JSON parser [#399](https://github.com/miguelgrinberg/python-engineio/issues/399) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2dda203103d93bc751ab0967719f18318cffc8da))\n- Pass `environ` as a second argument to callable option `cors_allowed_origins` [#398](https://github.com/miguelgrinberg/python-engineio/issues/398) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5cb561101dfcaed06bc9d73486515da93ead1752)) (thanks **wft-swas**!)\n\n**Release 4.11.2** - 2024-12-29\n\n- Fix incorrect disconnection reason reported when browser page is closed ([commit](https://github.com/miguelgrinberg/python-engineio/commit/132fbd9b2728c342fb989d559fa8c24b324c3cf3))\n\n**Release 4.11.1** - 2024-12-17\n\n- Remove debugging prints :blush: ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ded35d682690bf8a74d6df1325ec5b7e28d6eed6))\n\n**Release 4.11.0** - 2024-12-17\n\n- Pass a `reason` argument to the disconnect handler [#393](https://github.com/miguelgrinberg/python-engineio/issues/393) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d782d9b9adc04fb691a490f29713239ad40de6c5))\n- Add `maxPayload` to connection response [#392](https://github.com/miguelgrinberg/python-engineio/issues/392) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/12e423fecd15c17ddecbef396844634431c45836)) (thanks **HeySMMReseller & HeySMMProvider**!)\n- Client option to disable timestamps in connection URLs [#386](https://github.com/miguelgrinberg/python-engineio/issues/386) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e8f9bbafc8c3ef8126dbe06343d0a30e32074627))\n- Return disconnected sessions as 400 errors [#391](https://github.com/miguelgrinberg/python-engineio/issues/391) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/55a9e46ff91aacfc04cb21683e12345e71fe2f98))\n- Handle unicode errors in ASGI driver [#389](https://github.com/miguelgrinberg/python-engineio/issues/389) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/44ce778c9a7e26d62254563e3de8c4a0c073bdc0))\n- Replaced deprecated `get_event_loop` with `get_running_loop` [#384](https://github.com/miguelgrinberg/python-engineio/issues/384) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a6e5d92ca98b41d2054737c6c49fc0511da0c3c6))\n- Remove constructs required by older, now unsupported Python versions ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2f257c3f83be91a464141ff4d8366cdcd7d9543b))\n- Switched to pyenv-asyncio for async unit tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/08ea5ad5127e3505120ddc8ac12657f3f70f9fef))\n- Adopted `unittest.mock.AsyncMock` in async unit tests instead of homegrown version ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0a25a1d404dd8aab968e2b8aef870ad52c858dfc))\n- Removed tests dependency on `unittest.TestCase` base class ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7de6d63f4034c4e8610e02c0c3478f8b97e1bc65))\n\n**Release 4.10.1** - 2024-10-15\n\n- Reject request with incorrect transport [#367](https://github.com/miguelgrinberg/python-engineio/issues/367) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7ad14481695df5adb070d52a377de49f43ddf399))\n\n**Release 4.10.0** - 2024-10-13\n\n- Reject requests with incorrect transport [#367](https://github.com/miguelgrinberg/python-engineio/issues/367) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4d614e5297ed2291ae97fcf30a3ee7223886440a))\n- Fixed runtime error when disconnecting all clients [#368](https://github.com/miguelgrinberg/python-engineio/issues/368) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b3339974c68dcf0e3f85c524450748c24c3a9223))\n- More flexible handling of the ASGI path [#359](https://github.com/miguelgrinberg/python-engineio/issues/359) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/972687b10c9a0fecb1c08fcd30dbd7b5a97c3a52))\n- Remove unused parameter in log message [#377](https://github.com/miguelgrinberg/python-engineio/issues/377) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f9a818d1444c9167457fc9f6fca3667ac7a46cf7))\n- Minor updates to the server and client documentation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/fe56a33fe37355dbdcd6a283f32e372f60115236))\n- Add Python 3.13 CI builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e0e577dfd1bc8f79c5f8b033aed61947d44a5ec6))\n- Run tests with mocked eventlet to avoid 3.13 failures ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5b5d67d1ffd98b31eb8fb30417152cb05af6fc97))\n\n**Release 4.9.1** - 2024-05-18\n\n- Fix inverted shutdown logic in async service task [#354](https://github.com/miguelgrinberg/python-engineio/issues/354) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8e688ba42de8aa9418f15943e0084f5626b092be))\n- More robust WebSocket close detection in the sync client [#346](https://github.com/miguelgrinberg/python-engineio/issues/346) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ec2df3f99fc02234c43ff01e2a75fb40c0df0409))\n- Option to disable routing in ASGIApp [#345](https://github.com/miguelgrinberg/python-engineio/issues/345) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1dbd57334499e839709ec951925b42ddfa70c57f)) (thanks **Rodja Trappe**!)\n\n**Release 4.9.0** - 2024-02-05\n\n- More robust handling of polling disconnects [#254](https://github.com/miguelgrinberg/python-engineio/issues/254) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e0bb263499525f5bd7eeb5195eea2dbf049d92b2))\n- Clearer client logs after disconnect [#342](https://github.com/miguelgrinberg/python-engineio/issues/342) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5b538a74061d893f255ac3544ffe1402ae97b58e))\n\n**Release 4.8.2** - 2024-01-06\n\n- Combine ssl_verify with other SSL options ([commit](https://github.com/miguelgrinberg/python-engineio/commit/cea2f92b7094dba8b1b0943bab9e833a5362affe)) (thanks **Simon Fonteneau**!)\n- Hold references to background tasks to avoid garbage collection ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0729554455d9ab1bdd36e6386272fb2d6b5607c6))\n- Clearer documentation for the `max_http_buffer_size` argument ([commit](https://github.com/miguelgrinberg/python-engineio/commit/88b19f93ffea7bc1e9527889b9c2b830d082ce6b))\n\n**Release 4.8.1** - 2023-12-28\n\n- Fix invalid WebSocket responses [#331](https://github.com/miguelgrinberg/python-engineio/issues/331) [#332](https://github.com/miguelgrinberg/python-engineio/issues/332) [#338](https://github.com/miguelgrinberg/python-engineio/issues/338) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ccc7a86886f507bd7aa6985e5d1b070f9505ac46))\n\n**Release 4.8.0** - 2023-10-14\n\n- Return consistent responses after Websocket connection ends ([commit](https://github.com/miguelgrinberg/python-engineio/commit/785c77c39d8c8fee37f969981f5a28ed2cc1b769))\n- Migrate Python package metadata to pyproject.toml ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f13b64d489ea99764f1a889987b1087f879967ea))\n- Remove Python 3.7 from builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f3717b244b6df09562760cc7e232d26a056bb1c2))\n- Internal code restructure (no functional changes) ([commit #1](https://github.com/miguelgrinberg/python-engineio/commit/e26163c8bbc2341e30f91b6acba06b9157247562)) ([commit #2](https://github.com/miguelgrinberg/python-engineio/commit/f15527bc48e2d3da1668e09ab801e594f85b20d5)) ([commit #3](https://github.com/miguelgrinberg/python-engineio/commit/5c996bec85d864526fe41569438a6e15e4a53123)) ([commit #4](https://github.com/miguelgrinberg/python-engineio/commit/ca9ca5bdd1467929be311d5ddcbfd18b5f4231ae))\n\n**Release 4.7.1** - 2023-09-12\n\n- Replace gevent-websocket with simple-websocket when using gevent ([commit](https://github.com/miguelgrinberg/python-engineio/commit/614f564275c635dc8b03d33dab44bf80d280cbcc))\n- Catch and log all errors that occur in event handlers ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2bef6d6fbbe684e5718f9202cd7af0ad19153495))\n- Use daemon threads for background tasks also in the threaded client ([commit](https://github.com/miguelgrinberg/python-engineio/commit/53578088046ca9f29b6119c182c7bed67d7a4ffb))\n- Silence exception on websocket exit when using uWSGI [#330](https://github.com/miguelgrinberg/python-engineio/issues/330) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9bc9e867e28e2495031bd1a552f4da0b1f0f575c))\n\n**Release 4.7.0** - 2023-09-03\n\n- Added `send_packet()` method ([commit](https://github.com/miguelgrinberg/python-engineio/commit/48451a3a18c40c58cc5d4127250e4776e5b7f8db))\n- Fixed race condition when lots of connections are ended at the same time [#328](https://github.com/miguelgrinberg/python-engineio/issues/328) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bb87ec652f55b41063400205971b0a667b78b162))\n- Workaround for strange memory leak in Eventlet's `Thread` class [#328](https://github.com/miguelgrinberg/python-engineio/issues/328) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d29aa9c44450c4ea729a0846091e3b105b8b7497))\n- Use daemon threads for background tasks in threading mode ([commit](https://github.com/miguelgrinberg/python-engineio/commit/541f172a4a61ebc16ee32fa38b0f410c4c711fbf))\n- Upgrade to pypy-3.9 in unit tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4581e53ada773fef8976110cc6d4ae40783b38d8))\n\n**Release 4.6.1** - 2023-08-23\n\n- Fix double close of websockets in ASGI adapter [#327](https://github.com/miguelgrinberg/python-engineio/issues/327) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e629eee17d7df7dc9736763b4220daed54a6dbdf))\n\n**Release 4.6.0** - 2023-08-21\n\n- Improvements in the connection rejected flow ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8051fc49f484585b786031a08617208efdc97f5a))\n- Better handling of Gunicorn threaded worker ([commit](https://github.com/miguelgrinberg/python-engineio/commit/29e4492cdf836a2197479c5946089b2363305379))\n- `shutdown()` method for the Engine.IO server ([commit](https://github.com/miguelgrinberg/python-engineio/commit/87f6003653b45fe2b230d8c33c8962e15e71e157))\n\n**Release 4.5.1** - 2023-07-06\n\n- Restore support for old versions of eventlet [#321](https://github.com/miguelgrinberg/python-engineio/issues/321) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/503c8651658e26276f3206655a819f79eb25739e))\n\n**Release 4.5.0** - 2023-07-05\n\n- Configure eventlet's websocket max frame length [#319](https://github.com/miguelgrinberg/python-engineio/issues/319) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1b04a562322a386ef806f1ada73e83d40fa1f0ce))\n- Remove old Python 2 syntax in `super()` calls ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b37ee7697418c9a982af570758044d0e728e2ce2))\n\n**Release 4.4.1** - 2023-04-19\n\n- Prevent crash when closing simple-websocket connection [#311](https://github.com/miguelgrinberg/python-engineio/issues/311) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/71e7d3688947779d2f086014e117ebb66606145e))\n- Fix server/client mixup in client docstrings [#312](https://github.com/miguelgrinberg/python-engineio/issues/312) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/911cf520034ee17bcc9311e244e616848cfff095)) (thanks **Sasja**!)\n\n**Release 4.4.0** - 2023-03-16\n\n- Allow configuring underlying websocket connection with custom options [#293](https://github.com/miguelgrinberg/python-engineio/issues/293) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/45e97b8cf885e998168857c46e29a7e257754f3e)) (thanks **Bruce Yu**!)\n- Cancel all running tasks in async SIGINT handler [#306](https://github.com/miguelgrinberg/python-engineio/issues/306) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0d263b0e40460c334a0b259804f2ff156bc3718c))\n- Handle unexpected WebSocket close frames sent by server [#292](https://github.com/miguelgrinberg/python-engineio/issues/292) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4f67c95f8631e624e44afe5bdfccfff924b232c9))\n- Close aiohttp session after a failed connection [#307](https://github.com/miguelgrinberg/python-engineio/issues/307) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/86ed2ae9f84578b9c6b7a6839c3b82304a65725f))\n- Catch IOErrors from uWSGI and explicitly close the driver [#301](https://github.com/miguelgrinberg/python-engineio/issues/301) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/678ae8b0efa6c12ae36d5c5b362e50aabc8dc8e9)) (thanks **June Oh**!)\n- Recommend ASGI integration for Sanic in Documentation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bf9d8eabe02c2aadce22e70b71375ccc2bd21e79))\n- Fix documentation for `max_http_buffer_size` [#310](https://github.com/miguelgrinberg/python-engineio/issues/310) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8182f783830b9fda9abc8e2410e7f397c0f62482)) (thanks **Lawrence Ong**!)\n- Add Python 3.11 to builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4a8a9a640fd4567d8c6001e1058e9980af3067ff))\n\n**Release 4.3.4** - 2022-08-03\n\n- Let companion ASGI app handle lifespan events [#287](https://github.com/miguelgrinberg/python-engineio/issues/287) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1c9001c537fd669a3b0e28d75f707216ec48befa))\n- Use configured request timeout when making a WebSocket connection [#286](https://github.com/miguelgrinberg/python-engineio/issues/286) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f6df30b841a86f96765c307efa99a7505dd9b4c1)) (thanks **jpfarias**!)\n\n**Release 4.3.3** - 2022-07-04\n\n- Handle ASGI lifespan when running with a secondary ASGI app [#284](https://github.com/miguelgrinberg/python-engineio/issues/284) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c4a021ee9c4d760bbe4066887ca816fc7c718f98)) (thanks **mozartilize**!)\n- Update deprecated usage of `asyncio.wait()` [#281](https://github.com/miguelgrinberg/python-engineio/issues/281) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d3a23c0936cda2ff3de8c5ae0c834ffef515e8cb)) (thanks **Ben Beasley**!)\n- Better handling of queued WebSocket messages in uWSGI [#256](https://github.com/miguelgrinberg/python-engineio/issues/256) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ec7b3da2e48060e177bf8ad6a9f5fae445207c82))\n- Gracefully fail to decode empty packets [#269](https://github.com/miguelgrinberg/python-engineio/issues/269) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9c657071f3d42a88fd1615b5edd245a89445ea1b))\n- Only attempt to set an async signal handler once [#276](https://github.com/miguelgrinberg/python-engineio/issues/276) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6869751aafb6db83d1a53fbd47d3fbfd2a8ae490))\n\n**Release 4.3.2** - 2022-04-24\n\n- Option to use a callable for `cors_allowed_origins` [#264](https://github.com/miguelgrinberg/python-engineio/issues/264) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/60e8e553e1fc64a5b0dbb846a86c5c0698101a9e))\n- Close aiohttp session when disconnecting [#272](https://github.com/miguelgrinberg/python-engineio/issues/272) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a9fb317c29d93b98a729df800f124b6b923fc82c))\n- Remove 3.6 and pypy-3.6 builds, add 3.10 and pypy-3.8 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/06480be268852ffc96793ef52213ad598b85fa69))\n\n**Release 4.3.1** - 2022-01-11\n\n- Fix support for Sanic v21.9.0 and up ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b0157d5a7e35ad83bc33f363b154402838fac83b)) (thanks **13g10n**!)\n- Include example code in flake8 pass ([commit](https://github.com/miguelgrinberg/python-engineio/commit/776bb86bb560bcd1912350bc24382fe6090c9c84))\n- Remove unused `__version__` constant [#262](https://github.com/miguelgrinberg/python-engineio/issues/262) ([commit 1](https://github.com/miguelgrinberg/python-engineio/commit/e882f5949bdd1618d97b0cade18a7e8af8670b41) [commit 2](https://github.com/miguelgrinberg/python-engineio/commit/ed4b1e2b8b18ac5adb2ee9a2ef126a4e5ffee128))\n\n**Release 4.3.0** - 2021-10-26\n\n- **Backward incompatible change**: Reject websocket messages larger than `max_http_buffer_size` [#260](https://github.com/miguelgrinberg/python-engineio/issues/260) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5f519a22b9543f585adc352e13f2a9b3cbfca727))\n- Enable or disable specific transports [#259](https://github.com/miguelgrinberg/python-engineio/issues/259) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8a0e4c3a406358065ef4eb878e60d2dc3b758bf4)) (thanks **Maciej Szeptuch**!)\n- Option to disable the `SIGINT` handler in the client ([commit](https://github.com/miguelgrinberg/python-engineio/commit/14ed9f1d8f19e87a13b427427a6597e72d51db57))\n- Support binary packets with zero length [#257](https://github.com/miguelgrinberg/python-engineio/issues/257) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bcd1a42f86aad12460b6eb836a5c317db55cba77))\n- Improve documentation on `start_background_task()` function ([commit](https://github.com/miguelgrinberg/python-engineio/commit/531d28ae2583e30c17ec7a0c911cde0343663244))\n- Remove unsanitized client input from error messages [#250](https://github.com/miguelgrinberg/python-engineio/issues/250) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/72b7136cffd67d4299cb3dab17d1632a30ef5207)) (thanks **André Carvalho**!)\n- Use plaintext Content-Type when using polling [#248](https://github.com/miguelgrinberg/python-engineio/issues/248) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c2603e9ddc7ff96a8fe7beced751aea1480ec5e6)) (thanks **Tobias**!)\n- Return better error messages for client connection errors [#243](https://github.com/miguelgrinberg/python-engineio/issues/243) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3daa02e198aca9657cb04ea91ba4e3234113bde9))\n- Reuse the aiohttp client session on reconnects [#226](https://github.com/miguelgrinberg/python-engineio/issues/226) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3c8fdfe05864e43ad8f35214fa2ad27bcb24965f))\n\n**Release 4.2.1** - 2021-08-02\n\n- Support setting `socketio_path` to the root URL [#242](https://github.com/miguelgrinberg/python-engineio/issues/242) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/47ada56b1ada2ed6eeb8c0fe172045bed321a037))\n- Use the gevent selector to avoid 1024 file handle limitation of select[#228](https://github.com/miguelgrinberg/python-engineio/issues/228) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6a4fd582e23d03d90b67b6825518a6c73431c6dd))\n- Pass reason when closing a WebSocket connection ([commit](https://github.com/miguelgrinberg/python-engineio/commit/583c7db1f9dfa62290481634b4f9ab4d39a8ec6b))\n- Improved project structure ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bf37732b38b6d798f86fdf5c3d26b8e306e34655))\n- Remove executable permissions from files that lack shebang lines [#240](https://github.com/miguelgrinberg/python-engineio/issues/240) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7a4e2780f9ea3466a8a14e3f1720561773faee7c)) (thanks **Ben Beasley**!)\n\n**Release 4.2.0** - 2021-05-15\n\n- WebSocket support for threading mode ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b84537af22e547211163521f7bc85995faab3625))\n- Fixed CORS handling of scheme proxy server header [#1501](https://github.com/miguelgrinberg/Flask-SocketIO/issues/1501) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/fb47df6949c10c35d6630daacb3d511d2086f1b3))\n- Correct handling of static files when secondary WSGI/ASGI app is set [#653](https://github.com/miguelgrinberg/python-socketio/issues/653) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bd2e59d0b37e86fd561f716f2d805081200f896e))\n- Remove outdated binary argument from example code ([commit](https://github.com/miguelgrinberg/python-engineio/commit/090454ffe66ebe7e830ecbd859f0416c7bc74eee))\n- Added Open Collective funding option ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9e3497a9749aebc87268250673cebba35c6922cf))\n\n**Release 4.1.0** - 2021-04-15\n\n- Change pingTimeout to 20 seconds to match JavaScript's Socket.IO 4.x releases ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1e29203b41ee5f1bbde17bf77a909183fc66033a))\n- Configure the JSON decoder for safer parsing ([commit](https://github.com/miguelgrinberg/python-engineio/commit/dd1db2ec6b75a95bfab5e73a8f71fdb69bd54534)) (thanks **Onno Kortmann**)\n- Remove obsolete 'mock' dependency [#218](https://github.com/miguelgrinberg/python-engineio/issues/218) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/845fc6201a783d14e02924c593028d3d06600d73)) (thanks **Michał Górny**!)\n\n**Release 4.0.1** - 2021-03-10\n\n- Support for client to verify server with custom CA bundle ([commit](https://github.com/miguelgrinberg/python-engineio/commit/792bdd040a460d0f77309ed1c7d9fea236542140)) (thanks **Brandon Hastings**!)\n- Report missing websocket client as an error in log [#557](https://github.com/miguelgrinberg/python-socketio/issues/557) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2f806acc927ac334541f77455b3a51a879649aeb))\n- Remove asyncio client delay before attempting reconnection [#622](https://github.com/miguelgrinberg/python-socketio/issues/622) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1d174b7bc47d4958a9829130321f8c87141007d7))\n- Fix error handling for ASGI WebSocket errors [#210](https://github.com/miguelgrinberg/python-engineio/issues/210) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e8e4ba5d1c832e14568e575ecdd173395493ea48))\n- Fix logging of missing sid [#1472](https://github.com/miguelgrinberg/Flask-SocketIO/issues/1472) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/cdfc1d88151a9f9f81082810db74fa3882d8adca))\n- Change deprecated `body_bytes` in sanic to `body` [#207](https://github.com/miguelgrinberg/python-engineio/issues/207) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e16bbcac1c76dbab61dd378768128af5dfeb8357)) (thanks **Alison Almeida**!)\n- Remove references to Python 3.5 in the documentation [#211](https://github.com/miguelgrinberg/python-engineio/issues/211) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/753656374ee74aedc8a70e92ea717d4ddb5c95dc))\n- Added performance testing scripts ([commit](https://github.com/miguelgrinberg/python-engineio/commit/28fe975daf239a2612e59843f06c52a72cfea84b))\n\n**Release 4.0.0** - 2020-12-07\n\n- Implementation of the Engine.IO v4 protocol revision\n    - v4 protocol: ping/ping reversal in the server ([commit](https://github.com/miguelgrinberg/python-engineio/commit/52774aaf019c1560ba2d46d7fb32668516fb9aff))\n    - v4 protocol: ping/ping reversal in the client ([commit](https://github.com/miguelgrinberg/python-engineio/commit/76a0615ec02818b1aba38ced38e5f6cefc40790d))\n    - v4 protocol: change max http buffer size to 1MB ([commit](https://github.com/miguelgrinberg/python-engineio/commit/38e20a3f31ffc566d521a80f0d13499a4de8e67e))\n    - v4 protocol: do not set the io cookie by default ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f17663608178d4ee5f0ab9f1d4523813b96f3e1f))\n    - v4 protocol: use EIO=4 in connection URL ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b474d70b413307be5b713d3f7e3b79dbd1b631a4))\n    - v4 protocol: new payload separator ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e895d6f5d0fa88566df61ffd316ce31d7cecfb90))\n    - v4 protocol: new binary encoding format ([commit](https://github.com/miguelgrinberg/python-engineio/commit/38beea5f7903af2e79ab3654b0c299aba2f226da))\n- Use a sid generator algorithm similar to JavaScript's version of Socket.IO ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0583c1e8b122e4c7620e04429bf4f901bad551bd))\n- Ignore case when comparing transport argument against 'HTTP_UPGRADE' header ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3d7ea22e8a9930544c711c5e124f75121b300ef3)) (thanks **Matthew Barry**!)\n- Remove dependency on the six package ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c181e8563edf1586eb3f2baacaf4f2c26b1a2593))\n\n**Release 3.14.2** - 2020-11-30\n\n- Log first occurrence of bad request errors at level ERROR for higher visibility ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3fc702f459554ccbdfaaad2673b6063d2ef4485e))\n\n**Release 3.14.1** - 2020-11-28\n\n- Catch more connection exceptions in the asyncio client [#561](https://github.com/miguelgrinberg/python-socketio/issues/561) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0d8d3a66292e2bc71b5af5b3e2162fde02c3f487))\n- Revert \"On Windows use SIGBREAK to break client\" since the fix was not effective ([commit](https://github.com/miguelgrinberg/python-engineio/commit/788cf86a0b6223546b085966e800466a25fe07e1))\n\n**Release 3.14.0** - 2020-11-28\n\n- Reject incorrect Engine.IO protocol versions ([commit](https://github.com/miguelgrinberg/python-engineio/commit/00330bbc4292f50e5a7726f28c028f6cd7c90aa5))\n- Accept an initialized requests or aiohttp session object ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f371ad17f3a261366cde124f926bf62dc191a9ea))\n- Handle ping interval and timeout given as strings [#201](https://github.com/miguelgrinberg/python-engineio/issues/201) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1751039070da3fee381568f2b017aa83bef36bf1)) (thanks **Akash Vibhute**!)\n- Handle websocket connections without upgrade header [#72](https://github.com/miguelgrinberg/python-engineio/issues/72) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/da4afaa6ed80f7cce6e102a51ff03390267b51a1))\n- Catch broken pipes and OS errors in websocket thread [#177](https://github.com/miguelgrinberg/python-engineio/issues/177) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0dde7d7ae19478a56610b3a06f76419013e60d62))\n- Expose ASGI scope in connect environ [#192](https://github.com/miguelgrinberg/python-engineio/issues/192) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3a58d406427a5ac99803c4b4d516b5478022b3c6)) (thanks **Korijn van Golen**!)\n- Emit ASGI lifespan shutdown event [#200](https://github.com/miguelgrinberg/python-engineio/issues/200) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2fb17746e72c74a2bce6a1169b6f841ac3473ea9))\n- Add option to set cookie SameSite and Secure settings. ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8f175760eb95b9c67548c5d9969765f710d40296)) (thanks **Billy Felton**!)\n- Stop event loop when client is interrupted with Ctrl-C [#197](https://github.com/miguelgrinberg/python-engineio/issues/197) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/402402f7c19760e84d0c32abc8e729baff51623d))\n- Do not try to install signal handler if unsupported [#199](https://github.com/miguelgrinberg/python-engineio/issues/199) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c0a1c2801cb35e6d192ddf542f79359c823655aa)) (thanks **Philippe**!)\n- On Windows use SIGBREAK to break client [#570](https://github.com/miguelgrinberg/python-socketio/issues/570) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f5fda518d8943be7846321275760a589a1e63bc0))\n- Client: handle error responses with invalid JSON [#553](https://github.com/miguelgrinberg/python-socketio/issues/553) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f543839512b960c904f73cf5ea2a647b058c8bf7))\n- Added troubleshooting section to the documentation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/32e0e2992f9d109dbad7124b615e97d6e8b3285d))\n- Move builds to GitHub actions ([commit](https://github.com/miguelgrinberg/python-engineio/commit/232f165a2d2b41b62f540ed6b77c8db722c6dc4f))\n\n**Release 3.13.2** - 2020-08-18\n\n- Improved signal handler for the async client [#523](https://github.com/miguelgrinberg/python-socketio/issues/523) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/eabfdaa9d1644d3346ec3ec7fae040c85029b75e))\n- Add SameSite attribute to Socket.IO cookie [#1344](https://github.com/miguelgrinberg/Flask-SocketIO/issues/1344) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2ec2bac6d7738b89ae0fe0645e30d50dd100cab1))\n- Handle GeneratorExit exception appropriately [#182](https://github.com/miguelgrinberg/python-engineio/issues/182) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c7ab55269e0cf94c7684675101d910d740f179cc)) (thanks **PaulWasTaken**!)\n- Simplify asserts in unit tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/638c1fa4d54a7cfa20711df5a1b3e8e1e3754c3d))\n- Use pytest as test runner ([commit](https://github.com/miguelgrinberg/python-engineio/commit/dcea3a09775cc054b4b937d6d8c1caff5af4f617))\n\n**Release 3.13.1** - 2020-07-02\n\n- Fix KeyError during WebSocket disconnection in AsyncServer [#179](https://github.com/miguelgrinberg/python-engineio/issues/179) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f43807b26ea1a185ff0b9f569dd586ca77b8da67))\n\n**Release 3.13.0** - 2020-05-23\n\n- Support direct WebSocket connections in ASGI server ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c0e2817bddf2c12e72cbfe7e2ca4bb3f41392af5))\n- ASGI startup and shutdown lifespan handlers [#169](https://github.com/miguelgrinberg/python-engineio/issues/169) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/38cc39f527e4913f3fee519a2f13f218056343a7)) (thanks **avi**!)\n- Improved handling of rejected connections ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0e0b26f89bea6b0662c1d1748c5ae1fde5668207))\n- Make client disconnects more robust [#417](https://github.com/miguelgrinberg/python-socketio/issues/417) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4297eb4a9033029cd0061e3ddd5d46974b8e4d9e))\n- End WebSocket connection gracefully when user is intentionally disconnected [#168](https://github.com/miguelgrinberg/python-engineio/issues/168) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e4d9c33216a851ca0261b0944d4c08afcc05ae1e)) (thanks **Mohammad Almoghrabi**!)\n- Enable locking in websocket-client package [#170](https://github.com/miguelgrinberg/python-engineio/issues/170) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f7bbd97a68022b25f7d70c044cbff4328c50e909))\n- Correctly parse cookies with a \"=\" in their values [#175](https://github.com/miguelgrinberg/python-engineio/issues/175) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8c1d98c056ac69b04d8a1412a70563909b19f7e6)) (thanks **Ignacio Pascual**!)\n- Removed references to Python 2.7 in the documentation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5b79e28d8a2c5349590f9ea23d9cb8142c165295))\n\n**Release 3.12.1** - 2020-03-17\n\n- Asyncio client: correctly update cookie jar [#166](https://github.com/miguelgrinberg/python-engineio/issues/166) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5f2c7f640cbe1620387b6843683b2150dc713d82))\n\n**Release 3.12.0** - 2020-03-14\n\n- Correct handling of cookies in the client [#162](https://github.com/miguelgrinberg/python-engineio/issues/162) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/59a0cd43f7fabc2c6b2546c59e72f8376b9f85cc))\n- Fixed infrequent race condition when upgrading from polling to WebSocket [#160](https://github.com/miguelgrinberg/python-engineio/issues/160) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f2cce2bccb7fca58bb6115630d5c221569e52ba4))\n- Only add signal handler when client is created in main thread [#163](https://github.com/miguelgrinberg/python-engineio/issues/163) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e1ed079a8dafe2b9ca596fa2fc2885a91d1b486d))\n- More robust handling of a closing connection [#164](https://github.com/miguelgrinberg/python-engineio/issues/164) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bdd584b3b3ca87f37f89921e54d5b27ec5fd7953))\n- More accurate logging documentation [#158](https://github.com/miguelgrinberg/python-engineio/issues/158) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5260f5c4d8e6091fb913be9b688d61e36c11fb26))\n\n**Release 3.11.2** - 2020-01-03\n\n- Last version to support Python 2\n- Detect unreported websocket closures in asyncio client [#401](https://github.com/miguelgrinberg/python-socketio/issues/401) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a67b3d76d80e665ec071292dc4aadffb50be6d3f))\n- Initialize aiohttp when client connects directly through websocket [#152](https://github.com/miguelgrinberg/python-engineio/issues/152) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9a3d6453bd35bc9581b5dd9226dc9e6bba3a18aa))\n- Initialize the client's SIGINT signal handler only if a client is created [#147](https://github.com/miguelgrinberg/python-engineio/issues/147) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6534d324f3dce2e1e4927932660d5e5e8bcab202))\n- Add better exception handling for errors thrown by the websocket-client package [#155](https://github.com/miguelgrinberg/python-engineio/issues/155) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/33c7cf1ba9ecc8dd24b0d850dfe334d425474612)) (thanks **Adam Grant**!)\n- Missing timeout when closing websocket client connection [#148](https://github.com/miguelgrinberg/python-engineio/issues/148) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/02a2c705b01f171edea106a7ee867b6112074853))\n\n**Release 3.11.1** - 2019-12-10\n\n- Reset event when it is reused after a reconnect [#153](https://github.com/miguelgrinberg/python-engineio/issues/153) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/179d0df931724f1c518d09417012e0adc90501fd))\n\n**Release 3.11.0** - 2019-12-07\n\n- Use aiohttp's WebSocket client [#324](https://github.com/miguelgrinberg/python-socketio/issues/324) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/280aa0f00c0ca3d099c2a693f6c2ce7919d2dc86))\n- Support user created loops on the asyncio client [#1065](https://github.com/miguelgrinberg/Flask-SocketIO/issues/1065) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e38daad301d4b855cabf6a289b7348a58a314273))\n- Fix occasional server disconnect crashes [#146](https://github.com/miguelgrinberg/python-engineio/issues/146) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9f96cd827c59776cb7da72614891be05681e5063)) (thanks **Dominik Winecki**!)\n- Use X-Forwarded headers if present to verify origin ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3c221aaec7173a046ca42f6aff9be0915cf92237))\n- Support async `make_response` function in ASGI driver [#145](https://github.com/miguelgrinberg/python-engineio/issues/145) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3f6391ca3229d26f081a16436cd4acd292ee69df))\n- Support not having a sigint handler [#143](https://github.com/miguelgrinberg/python-engineio/issues/143) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/fc984aaa5e5dc91f6632729e56b34628f2fd2563)) (thanks **Robin Christine Burr**!)\n- Fix websocket exception handling on python2.7 [#149](https://github.com/miguelgrinberg/python-engineio/issues/149) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b714f81a0ee27e30070a5ca702a1823236df9981)) (thanks **Payton Yao**!)\n\n**Release 3.10.0** - 2019-10-22\n\n- Added support for SSL connection to unverified host in the client. [#137](https://github.com/miguelgrinberg/python-engineio/issues/137) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/51da0bed3c93c41b980bb565560c7233da3501f5)) (thanks **sgaron-cse**!)\n- Performance improvements in parsing long-polling payloads ([commit](https://github.com/miguelgrinberg/python-engineio/commit/64a34fc1550458ded57014301d5f9e97534f0843))\n- Prevent heavy CPU usage when decoding payloads ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c8407ae97821bb00c33a91114f425b8454f5e50e))\n- Handle case where no original SIGINT handler existed and call signal.… [#140](https://github.com/miguelgrinberg/python-engineio/issues/140) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9b4a10fede2ef3a9e85f370f48b6720fe7a15f35)) (thanks **Robin Christine Burr**!)\n- Accept any 2xx response as valid in the client [#331](https://github.com/miguelgrinberg/python-socketio/issues/331) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9d4ab4bb519d898ef170815deb767b85aeefd141))\n- Avoid loop without yield when sockets are >60 [#138](https://github.com/miguelgrinberg/python-engineio/issues/138) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5c6fbeac0e9f0788d300cf06de74ce65f8994f05)) (thanks **Gawen Arab**!)\n- Configurable ping interval grace period [#134](https://github.com/miguelgrinberg/python-engineio/issues/134) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bb2401354c3b7c3cf6a5577db83cc51ae071836e))\n\n**Release 3.9.3** - 2019-08-05\n\n- Apply timeouts to all HTTP requests sent from the client [#127](https://github.com/miguelgrinberg/python-engineio/issues/127) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6666d6a092333aa60f48ccdc42b250be60e9f33c))\n- Shutdown non responding websocket connections in the client [#326](https://github.com/miguelgrinberg/python-socketio/issues/326) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/95731e9e2d66e8ee91faeb5538dcde84b88466bd))\n- Catch OSError exceptions from websockets package [#328](https://github.com/miguelgrinberg/python-socketio/issues/328) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0adc074e58dac1d81f769ed1a2edfcab5e0644d1))\n\n**Release 3.9.2** - 2019-08-03\n\n- Skip CORS headers when origin is not given by client [#131](https://github.com/miguelgrinberg/python-engineio/issues/131) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a349d4e3ce25ff771027f986c7594d840cc9e941))\n- Add `async_handler`s sub-package to setup.py ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e4163b64f3482d2d97dccf813a880cb6ad088533))\n\n**Release 3.9.1** - 2019-08-02\n\n- Restore CORS disable option [#329](https://github.com/miguelgrinberg/python-socketio/issues/329) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9f4cd8cf9e7be6baf4bc8c485e7ad204dd87be75))\n\n**Release 3.9.0** - 2019-07-29\n\n- Address potential websocket cross-origin attacks [#128](https://github.com/miguelgrinberg/python-engineio/issues/128) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7548f704a0a3000b7ac8a6c88796c4ae58aa9c37))\n- Documentation for the Same Origin security policy ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5b5879469348c529c283e1d81032a603c5e69b31))\n- Remove tests from built package [#124](https://github.com/miguelgrinberg/python-engineio/issues/124) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/399dc8acf2077856c4bd8edb22d0f254b47f0ca2)) (thanks **Pablo Escodebar**!)\n\n**Release 3.8.2** - 2019-06-29\n\n- Correctly autodetect asgi async mode [#122](https://github.com/miguelgrinberg/python-engineio/issues/122) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2690ea08b3d3beeaf34b5b4871ac1b567e048a9f))\n- Omit response when asyncio websocket ends [#120](https://github.com/miguelgrinberg/python-engineio/issues/120) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f13074670dcd95e578d17f00b91845139e4f25eb))\n- Improved ocumentation on user session behavior on disconnections ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6b8e667ad26c4e654f84b7f12b851c07d801211d))\n- Correct spelling mistakes in documentation [#119](https://github.com/miguelgrinberg/python-engineio/issues/119) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a4404989a1c48b3522c09a7f6335f2ad401805a2)) (thanks **Edward Betts**!)\n\n**Release 3.8.1** - 2019-06-08\n\n- Optimization to static file serving ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5b8701042678b3e092e2be365bdd31b425b714f6))\n- Do not reset connection when packet queue timeouts [#110](https://github.com/miguelgrinberg/python-engineio/issues/110) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e64e5a67b723400e20cb7c5a014413a4445d9184)) (thanks **Victor Moyano**!)\n\n**Release 3.8.0** - 2019-06-03\n\n- Much more flexible support for static files in the server ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b27cafb207589cc52b5ba1ffa60f9a2e1e553af9), [commit](https://github.com/miguelgrinberg/python-engineio/commit/a56aed103c39a25ff6afb316d171cfeca5bf9894))\n- Correctly handle rejected websocket connections in Tornado [#114](https://github.com/miguelgrinberg/python-engineio/issues/114) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/51f5ad28d5c3a17bfad7d9b55555b23223eff43b))\n\n**Release 3.7.0** - 2019-05-29\n\n- Add JSONP support in the server [#98](https://github.com/miguelgrinberg/python-engineio/issues/98) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/36a15987a677ba5a61675250f9b4a9e7c6cbaa74)) (thanks **StoneMoe**!)\n- Send binary packets as such in the sync client [#112](https://github.com/miguelgrinberg/python-engineio/issues/112) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/076232e86fa923c2f44472f8eb358b141c61783a))\n- Handle CLOSE packet in the client [#100](https://github.com/miguelgrinberg/python-engineio/issues/100) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/612815f793f4c749c9a9459ff08804ddd629da31))\n- Document how to access the sid for the connection ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3de448881989485e0f986441896a1871354ba36a))\n\n**Release 3.6.0** - 2019-05-25\n\n- Tornado 6 support ([commit](https://github.com/miguelgrinberg/python-engineio/commit/99359e43188f05e1844b68fef862f3af99919044)) (thanks **Michel Llorens**!)\n- added note on CORS support for sanic ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a3a4cb82059e2229d1b5e9ed9404dacc1b9afc34))\n- added python 3.7 build ([commit](https://github.com/miguelgrinberg/python-engineio/commit/805aa9fd7156425a2dce6b782b96f0e805ee4501))\n- auto-generate change log during release ([commit](https://github.com/miguelgrinberg/python-engineio/commit/be2c76e3e5b803284a6f2a9e4abed3314b9af7b6))\n- added change log ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f8b15d1c06439581ca6b0d697f67cd034fb5bbf5))\n- helper release script ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d36548cade90ddf8c6ab68178cb9747d5ac0d51f))\n\n**Release 3.5.2** - 2019-05-19\n\n- migrate to ASGI3 [#108](https://github.com/miguelgrinberg/python-engineio/issues/108) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5a7f9e719b6fb3bfc9da07b882c4b77b102aef0d)) (thanks **Florimond Manca**!)\n- updated asgi examples to latest uvicorn ([commit](https://github.com/miguelgrinberg/python-engineio/commit/261fd67103cb5d9a44369415748e66fdf62de6fb))\n- remove security alert in requirements ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1b044aaac9657ff947c6666638cf89315303bf6c))\n- removed unused arguments and methods ([commit](https://github.com/miguelgrinberg/python-engineio/commit/951b4c39af9ec22dbc06046d562866e0f32152cd))\n\n**Release 3.5.1** - 2019-04-07\n\n- Downgrade log levels in some areas [#103](https://github.com/miguelgrinberg/python-engineio/issues/103) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/57b81be14b1d2fd4701c1b1d3c07710661807983)) (thanks **Aaron Bach**!)\n- capture timeouts and other exceptions from requests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/45397f1d2f7a7ea7ae6fb87049579bccf6cb1b87))\n\n**Release 3.5.0** - 2019-03-16\n\n- not necessary to hold the packet queue when upgrading ([commit](https://github.com/miguelgrinberg/python-engineio/commit/330c6b9379afb4a098c24456f1a96fed8c314b10))\n- add link to stack overflow for questions ([commit](https://github.com/miguelgrinberg/python-engineio/commit/138fb60a9bb8a4aae86e08a5fd5485563733b9d1))\n- pep8 fixes for previous commit ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0c15cdc29ff130dba2887f5bfc2623f57b4fb45c))\n- Use the correct text type for upgrade probes in both Python 2 and 3 [#101](https://github.com/miguelgrinberg/python-engineio/issues/101) [#265](https://github.com/miguelgrinberg/python-engineio/issues/265). ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4f0b4ea83298701a2e192c1e42fc3e917f1ee989)) (thanks **Sam Brightman**!)\n\n**Release 3.4.4** - 2019-03-14\n\n- Pass cookies to websocket connection creation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c4c9178951aa2b9ede3ccec9af79324444e09314)) (thanks **Adrien Gavignet**!)\n- close the aiohttp client to prevent exit warnings ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9f6db446034a579415ae17dc0490ba23d92c723d))\n- readme fixes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d6a33d22cfd3ebe8b4d78cd5c27607de837d16e9))\n\n**Release 3.4.3** - 2019-02-20\n\n- exit service task if event loop is closed ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ee6e00d5d4131f1d120797528b94140c2006b848))\n- more tornado fixes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/68ca0c2f3ebe2d255449a1f3a8b1b11d2deb84ef))\n\n**Release 3.4.2** - 2019-02-19\n\n- added missing await in tornado driver ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4ac92d4642f248ae763493c1d26e9e5f2058ac93))\n\n**Release 3.4.1** - 2019-02-16\n\n- check for origin in Tornado's WebSocket handler ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c4b506a0eb91a67e68944c8048ca9a867407c182))\n\n**Release 3.4.0** - 2019-02-15\n\n- replace urllib3 with requests to get cookie support ([commit](https://github.com/miguelgrinberg/python-engineio/commit/41b8e29e49560170e852df1c5c070c6d311452d5))\n\n**Release 3.3.2** - 2019-02-12\n\n- reset sid after a disconnect ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9aa774270b41c7ef5f7e7c3bee6c2b8c40936951))\n- uniform service task cancellation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/82f6982b5f81f749600565266d9da9c108991eed))\n- Fix hang on KeyboardInterrupt when running with asyncio. [#95](https://github.com/miguelgrinberg/python-engineio/issues/95) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c60499e689fd8ea1ee4db269fcd3a7f2ab7fbb08)) (thanks **Ingmar Steen**!)\n\n**Release 3.3.1** - 2019-02-09\n\n- better error handling during websocket connection handshake ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f4c49c44a9b83a9fdc286bb38ff3be39b165118b))\n- more places where connection shouldn't be reset too quickly ([commit](https://github.com/miguelgrinberg/python-engineio/commit/693b51b2221d59863e2680acbf0f02170bb87a81))\n\n**Release 3.3.0** - 2019-01-23\n\n- do not reset connection when ping loop exits ([commit](https://github.com/miguelgrinberg/python-engineio/commit/dafbdb80ffb5eba0522adc14728bb47e13f0ac54))\n\n**Release 3.2.3** - 2019-01-12\n\n- never import invalid async drivers ([commit](https://github.com/miguelgrinberg/python-engineio/commit/61b04ea89cf2cc358a40f7854c31859aea8e30d6))\n\n**Release 3.2.2** - 2019-01-10\n\n- fixed unreliable unit test ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7e53442afa93d7155c49681050a7aacaaf7222e9))\n- Fixes [#236](https://github.com/miguelgrinberg/python-socketio/issues/236) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e6c285882ed023c17e319cf2bd9c3322a524125a))\n- fixed handling of queue empty exceptions [#88](https://github.com/miguelgrinberg/python-engineio/issues/88) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bc128c2e3f41a69d855acabdbdbad072f662df92))\n\n**Release 3.2.1** - 2019-01-09\n\n- add a grace period of 5 seconds to ping timeout ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b5f15e34ed9ef3a9f75d778c67e9bde4265618a7))\n- do not use six in setup.py ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c41bb5d0431c0a5d3c49a98392f530a93fd093c0))\n- minor refactor of clients for consistency with servers ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d9c278f326db52da1343c0f7fb4257ff7087e83c))\n- minor refactor of the async drivers ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0478110179f91f51c6a7a972b3e284b06c3db2ee))\n\n**Release 3.2.0** - 2019-01-03\n\n- unit test reorganization ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3786502ed57920d6b78283bf16150f1711721d38))\n- do not block upgrades with high packet traffic [#16](https://github.com/miguelgrinberg/python-engineio/issues/16) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/919d8ea639d5190d345b22168d6cbfbdebc421af))\n- user session documentation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/af3a0aa7d5b83f8c407f792cb688ef6f983b056b))\n- remove python 3.4 from builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8c9bbf4132f4cf4082c96d58a6e7270ad7eea0ff))\n- user sessions ([commit](https://github.com/miguelgrinberg/python-engineio/commit/561efad215661bfce3d00ffcb5c3290555de8f12))\n\n**Release 3.1.2** - 2018-12-22\n\n- fixed dependency ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8f8cbfd866086c3689a65bc049e0a9ce597e08c2))\n- small documentation updates ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d59648c663e2f54f96a824e947a86f62f45f637d))\n\n**Release 3.1.1** - 2018-12-20\n\n- bug fixes on handling of timeouts in the client ([commit](https://github.com/miguelgrinberg/python-engineio/commit/de1dbbd39f8516a89525282f4d24c7d854ecb321))\n- make ping loop task more responsive to cancellation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6a997b960c985b35f28b5f60f1dc8d9e99e05c08))\n- correct handling of disconnect event ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ccf1ddfa132a43fbe147c322608d913ede1d6c75))\n- make unit tests compatible with python 3.5 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/aeabccdd59f7d8939c6af47d5357e6545e9525d2))\n- do not drop extra packets included in first response ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0ffdb0a31b9b5be8d24d8208521fdd2121cb9a88))\n\n**Release 3.1.0** - 2018-12-14\n\n- initial Engine.IO client implementation\n- client examples ([commit](https://github.com/miguelgrinberg/python-engineio/commit/916bd7aa5f8df3a3caf7611133ff82cd2d0cdda7))\n- pass custom headers in client connection requests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6bacd03c9cf997af09f638cbcc9e1add441edc9b))\n- restructure async drivers into a subpackage ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4621ff8d6ce8bd2e6dd8381ee9764887970aa056))\n- documentation updates ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d014ca534e20ad37c75484ae151e3cec3809c200))\n\n**Release 3.0.0** - 2018-12-01\n\n- ASGI support\n- support serving static files in wsgi and asgi middlewares ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0c697591b44f6f849b45cec112e00331bbf537aa))\n- refactor wsgi and asgi middlewares ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1f7878536a62f9f5285e0a3ed8a83a9ec379d945))\n- minor documentation fixes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/00d713d8094233439e5bb888dd5c3b5ec363a5b1))\n- reorganized documentation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/84faa991890f33e8fbb5e5db884674d2dd32b1f3))\n\n**Release 2.3.2** - 2018-10-09\n\n- address potential lock of the service thread ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b702f6f98861e78f8c48f9aaee7b9f941de56d99))\n- graceful exit for service task ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2f5cd48f0f574c4cabd63f0b46dd652ff93ffc89))\n\n**Release 2.3.1** - 2018-09-30\n\n- updated requirements file ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2ab69b819bec6bea273b124c91cb2163b13266f3))\n- more fixes towards cleaning up abruptly disconnected clients ([commit](https://github.com/miguelgrinberg/python-engineio/commit/759dc5e8a3c4301f68ffe72ac8af8422a4099dad))\n\n**Release 2.3.0** - 2018-09-23\n\n- Actively monitor clients for disconnections ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3f583c88449f88200fa5f484954248bfad517aa8))\n- parse integer packets as strings [#75](https://github.com/miguelgrinberg/python-engineio/issues/75) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6735659d5cca69476e8a7e98a16a7529ab63a604))\n- missing unit test ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a51feef59da8fb491b50a05adb665e980dd9eaa9))\n- add Python 3.7 to build ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d9d617a5c62cab692fda4b9664750787303de411))\n- removed unused import ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ff3403f1216d838e1930d2322c66bcf609f790e8))\n- Tornado docs ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0ef4fbfeeb188a76095de2631cdef9ab4f01839d))\n\n**Release 2.2.0** - 2018-06-28\n\n- tornado unit tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/cb1fe75cea4573dfe3320e5b415c24aaad51d0a0))\n- Tornado 5 support ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e0dc7f16c562869d8b48d63f9ee049a413b2f1a2))\n\n**Release 2.1.1** - 2018-05-12\n\n- support OPTIONS request method in aiohttp and sanic [#70](https://github.com/miguelgrinberg/python-engineio/issues/70) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/27261c7d6563bc5c494e9ff345617a923e17452b))\n- More flexible specification of CORS allowed origins Suggested in https://github.com/miguelgrinberg/Flask-SocketIO/issues/697#issuecomment-385203087 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8f3d6ecff45d474da1a407d654d06fd3f8f882a8))\n\n**Release 2.1.0** - 2018-04-27\n\n- basic support for cors allowed headers ([commit](https://github.com/miguelgrinberg/python-engineio/commit/08e3766244b12f704ef20f266f10bdfc7381d43a))\n- add pypy3 target to travis builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d11b9dae19bf4a5b74b0f6636072e2527a5b8dfe))\n- respond to CORS preflight requests [#630](https://github.com/miguelgrinberg/Flask-SocketIO/issues/630) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/eac1e516589604a6831f47959047050af23ff01b))\n\n**Release 2.0.4** - 2018-03-13\n\n- suppress queue empty errors [#65](https://github.com/miguelgrinberg/python-engineio/issues/65) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/861dd52ca2c4fdd9ee1684f1a24bf7acd698039d))\n\n**Release 2.0.3** - 2018-03-06\n\n- more aiohttp unit test fixes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4fd45b8fb86d287c5ba47e7a74cdfb25fa4acb6a))\n- fix aiohttp unit test ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4b3ee9309e0250d428fb2faabbb2aa15d377db12))\n- support for aiohttp 3.x ([commit](https://github.com/miguelgrinberg/python-engineio/commit/810e759762dd24afa108c8b714fffdced49d3cc1))\n\n**Release 2.0.2** - 2018-01-04\n\n- fix documentation builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/107b751f16aafff5842894a6eff26eb6f784ea5c))\n- Suppress \"socket is closed\" stack trace from logs [#57](https://github.com/miguelgrinberg/python-engineio/issues/57) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7dfc60e91f076e4a70a771cf98f16ceaa3de077c))\n- Reraise exceptions in a Py2/Py3 compatible way [#58](https://github.com/miguelgrinberg/python-engineio/issues/58) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4a3320051aac532918b1e0448aad8cc8da615697))\n\n**Release 2.0.1** - 2017-11-21\n\n- Fixed poll() method to always empty the queue [#589](https://github.com/miguelgrinberg/Flask-SocketIO/issues/589) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e8e665b1737987a2b7c59cd6a96464842b864bad))\n\n**Release 2.0.0** - 2017-11-19\n\n- remove double-utf8 encoding hack this hack that made some incorrectly encoded packets sent by the JS socket.io 1.x clients does not always work, and is not needed anymore since the 2.x clients have been fixed. ([commit](https://github.com/miguelgrinberg/python-engineio/commit/83d2277de727e418b0abd1b1115a15307835d582))\n- Documented protocol defaults ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e6985ccfa9001aebfa31007dcae70989f2a4792f))\n\n**Release 1.7.0** - 2017-07-02\n\n- cleaner disconnecting of polling clients ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8d541fa2eb2f464b659baf0904de37567120f4bc))\n- Support async_handlers option for the asyncio server [#95](https://github.com/miguelgrinberg/python-socketio/issues/95) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6609416d2a0c7b8e750dcf1634f8a4218f5360e9))\n\n**Release 1.6.1** - 2017-06-27\n\n- Tolerate errors when cleaning up a task cancellation [#110](https://github.com/miguelgrinberg/python-engineio/issues/110) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a504e6b53fbb963c817755e57164ba07621aa253))\n\n**Release 1.6.0** - 2017-06-23\n\n- better error handling strategy [#49](https://github.com/miguelgrinberg/python-engineio/issues/49) (again and hopefully better) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8cc004a4a8014924dd822ca14ecabdad4e858c0d))\n- Reraise app exceptions with the correct traceback [#49](https://github.com/miguelgrinberg/python-engineio/issues/49) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/66b8f5d63d9583ea1cbd3bb0eb9b4db8f8047ce5))\n\n**Release 1.5.4** - 2017-05-30\n\n- Workaround to prevent the \"exception never retrieved\" asyncio bug [#48](https://github.com/miguelgrinberg/python-engineio/issues/48) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/dab2d2e9fd33896bbbb772b18323574ddc1b8ce5))\n\n**Release 1.5.3** - 2017-05-29\n\n- Handle buggy and correct encodings for engine.io unicode packets [#102](https://github.com/miguelgrinberg/python-socketio/issues/102) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/efc341ab321209007bddd75333c48d4e74527d53))\n\n**Release 1.5.2** - 2017-05-16\n\n- be a bit more forgiving with socket timeouts ([commit](https://github.com/miguelgrinberg/python-engineio/commit/05da51a41d4a1a7a08e5f19194a248923780fff8))\n\n**Release 1.5.1** - 2017-05-09\n\n- fixed typo ([commit](https://github.com/miguelgrinberg/python-engineio/commit/30445b239227daf88290a972349ba01cd31bd525))\n\n**Release 1.5.0** - 2017-05-09\n\n- another fix in the lost connection detection logic ([commit](https://github.com/miguelgrinberg/python-engineio/commit/73ac2ea7791b79a01974a1ebdb97104f99c1d7a7))\n- detect lost connections (asyncio) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9a96896bbda37613bd8b29ac658427366e5d49be))\n- detect lost connections (eventlet/gevent) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e9a3161fdcb7767d77a2370d003f4e74ef3ecd1d))\n\n**Release 1.4.0** - 2017-04-21\n\n- properly handle crashes in connect/disconnect handlers ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5b24410016f334e739690438345782fb5dcece02))\n- invoke disconnect handler when websocket handler crashes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f772cf62193e0dcc8be43814c1bfda7b987a2a15))\n- invoke disconnect handler when application handler crashes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/246edc3e84bce055284936745023ed4491897a5b))\n\n**Release 1.3.2** - 2017-04-09\n\n- Accept leading and trailing slashes in engineio_path [#83](https://github.com/miguelgrinberg/python-socketio/issues/83) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/924d3cb7a0416f7ccbc2364cc94dd07234f6f894))\n- Use custom exceptions for internal errors [#44](https://github.com/miguelgrinberg/python-engineio/issues/44) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/36814a48a58b6fdb996a0eed42e32e927711e182))\n- Fix sanic url parsing [#43](https://github.com/miguelgrinberg/python-engineio/issues/43) According to sanic docs, `request.url` already contains query string, so adding it results in data corruption. This fix worked for me. [#42](https://github.com/miguelgrinberg/python-engineio/issues/42) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7dda70cb46a0e782d42c0a175ec61d0b95ebced8)) (thanks **Семён Марьясин**!)\n- fixed aiohttp unit test ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2b629096cd26378c6755e4db83286a0f573be477))\n\n**Release 1.3.1** - 2017-03-22\n\n- Do not depends on SERVER_SOFTWARE constant from aiohttp [#86](https://github.com/miguelgrinberg/python-socketio/issues/86) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e1136aa4fda888f8f74135a94fadf8ac739cd6ad))\n- proper handling of closed sockets ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2144535e9dfe31a17ce6b9d40012d310b34a8c9a))\n- use Python 3.6 for docs build ([commit](https://github.com/miguelgrinberg/python-engineio/commit/52b37e50a816635cc363b4655fa984f4519f64e5))\n- release 1.3.0 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/51e620e3d49999c8bfff7afa68f712e1ee95bc44))\n- Better handling of close packets from the client [#41](https://github.com/miguelgrinberg/python-engineio/issues/41) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/db988f1c24db10db0a5969b0292834c4ac7b8882))\n- rename `async` to `_async` to avoid conflicts [#36](https://github.com/miguelgrinberg/python-engineio/issues/36) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6fcf926ec7ec28a3f97f94ffcc6b665ffbbd6bcc))\n- websocket support for sanic ([commit](https://github.com/miguelgrinberg/python-engineio/commit/317472459af6c04d26aa9255c0c8dc71ea81fa53))\n\n**Release 1.2.4** - 2017-03-02\n\n- Use non-blocking reads for uwsgi websocket handles [#417](https://github.com/miguelgrinberg/Flask-SocketIO/issues/417) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4148c9470b8d73fc2b35feeeb2d5048cc52b9250))\n- handle unexpected disconnects from uwsgi websocket ([commit](https://github.com/miguelgrinberg/python-engineio/commit/10ebccf6766a85da11fee4447a914ac338401d36))\n\n**Release 1.2.3** - 2017-02-22\n\n- Use correct key name for ACCEPT_ENCODING header [#39](https://github.com/miguelgrinberg/python-engineio/issues/39) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f1df2e4a3595207c9f0e91b67a5131af19c0528f))\n\n**Release 1.2.2** - 2017-02-15\n\n- updated examples readme ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ea9ab79e25a9fbba561782a55aeeb5e76d68137f))\n- Fix crash on invalid packet type. Add test [#37](https://github.com/miguelgrinberg/python-engineio/issues/37) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7eacdd98edfbf5ce7b1f0da0c3d2343cdf1cbffe)) (thanks **Dmitry Voronin**!)\n- minor updates to sanic examples ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c39a7751c72a90085d2bc88ab2487cb673724ee1))\n- sanic examples ([commit](https://github.com/miguelgrinberg/python-engineio/commit/251485dcea260f38136bf27bb7676430f458c4f0))\n- sanic support (long-polling only) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b2da2283451d558298cae888b9ef148186830a7e))\n- updated documentation logo ([commit](https://github.com/miguelgrinberg/python-engineio/commit/54e7115d35de20581e1328eded902c8d40788084))\n- ensure iscoroutinefunction works well for mocks ([commit](https://github.com/miguelgrinberg/python-engineio/commit/917df6f57a32e278ee38ef3c6201c90fdab6d061))\n- updated requirement files for examples ([commit](https://github.com/miguelgrinberg/python-engineio/commit/20db20f1764d25f50433e088d1d3486994b24139))\n\n**Release 1.2.1** - 2017-02-11\n\n- various minor improvements for asyncio support ([commit](https://github.com/miguelgrinberg/python-engineio/commit/24131a90d0ca5bfdafec0e02ee11ec433e81d44a))\n- Fixed asyncio example code [#35](https://github.com/miguelgrinberg/python-engineio/issues/35) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f86847beaff82054f677a4e18c08fb5056b61a78))\n\n**Release 1.2.0** - 2017-02-09\n\n- minor documentation updates ([commit](https://github.com/miguelgrinberg/python-engineio/commit/af2834dd7fb75c579b8e00d155649ce7c71528a1))\n- async socket unit tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c19c4477377fe0126a6dda8937414f669dc137f9))\n- more asyncio unit tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/039eb59b021ae59347be6a5614709756b915a5d0))\n- catch cancelled tasks due to client leaving ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3abadf1962ef433eb62c83d43522a8d636738fde))\n- some initial async server unit tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5796794ef2d12823f7306d3cf890fac1290da798))\n- asyncio documentation ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d1789caa27e509dcdc0cf76c665f5adab4ad1e41))\n- reorganized examples ([commit](https://github.com/miguelgrinberg/python-engineio/commit/824cdd541103f2d52e68848c8cacb2dc4df23c11))\n- Preliminary asyncio support! Yay! ([commit](https://github.com/miguelgrinberg/python-engineio/commit/cbeb025e808e9935fb979a042f5884c9ab1a4241))\n\n**Release 1.1.2** - 2017-01-30\n\n- Clean websocket exit for uWSGI [#377](https://github.com/miguelgrinberg/Flask-SocketIO/issues/377) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d15842383b1cd0fbaa741c5125b5ef26d1915a7a))\n\n**Release 1.1.1** - 2017-01-23\n\n- Use text/plain content type for base64 encoded responses [#33](https://github.com/miguelgrinberg/python-engineio/issues/33) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/297ff98e0d9f8f3b32ca5d2afe566a80bb16c6d8))\n- removed py33 from tests, added py36 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e0541bcfa069df0f54195a9031630baf7a46c069))\n- additional fix regarding bytearray support ([commit](https://github.com/miguelgrinberg/python-engineio/commit/268e3cba424391dd32950d0ba08d28a65c4ef14b))\n- Merge branch 'wwqgtxx-patch-1' ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4f25274a0e2e66b2a867b1cdcdf1e820c487e630))\n- allow binary packets to be given as bytearrays ([commit](https://github.com/miguelgrinberg/python-engineio/commit/eb8f357082369422464237f47a3c419fb7d14490)) (thanks **wwqgtxx**!)\n\n**Release 1.1.0** - 2016-11-27\n\n- Prevent recursive disconnect handlers [#329](https://github.com/miguelgrinberg/Flask-SocketIO/issues/329) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/84d5800c027fe093db0d7624cbc1e73e176ec221))\n\n**Release 1.0.4** - 2016-11-26\n\n- Use a statically allocated logger by default ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e6b3a6d8bce3d7f53fde7b56037fd9e9f7cbe492))\n- fix unit test to work on python 2.7 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/aab2182cea4f4fd3c64b512b443d6f0f3f35a5a9))\n\n**Release 1.0.3** - 2016-09-05\n\n- workaround double utf-8 encode bug in javascript client [#315](https://github.com/socketio/engine.io/issues/315) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/00d2459fcc7d89c7f35a2b3734b339c0fc148b1f))\n- upgrade to a more recent engineio.js for the examples ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d61c3ac9d6abd0e0af4518bd6486ec5c218f3ba9))\n- do not close a socket that is already closed [#312](https://github.com/miguelgrinberg/Flask-SocketIO/issues/312) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ef20ffcf9abc074493501b284ef2289cfaf6417d))\n\n**Release 1.0.2** - 2016-09-04\n\n- add __version__ to package ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8e1f4e0b3cbfda8d1ac1dcae7102e9f1b3046c88))\n\n**Release 1.0.1** - 2016-09-01\n\n- corrected logic that selects gevent_uwsgi as async mode [#28](https://github.com/miguelgrinberg/python-engineio/issues/28) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/db2fb14a252f0b142525d734bf60f665cb043367))\n- documentation fixes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/43fbe9a52e0a36c2cc73cf6e8064c55083c5ad61))\n\n**Release 1.0.0** - 2016-08-26\n\n- updated Server class docstring ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8b5304808bf62cd5215a4e75d1a3c97b07615ec9))\n- added async_handlers option to server ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c9133c2392baee13d7e3234d8aebfe550f106131))\n- documentation for new gevent_uwsgi async_mode ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3f0b4e3a5cb1f221702b4182c4dda7b91a1fdbd0))\n- add unit test for complete code coverage ([commit](https://github.com/miguelgrinberg/python-engineio/commit/36bb48c66b3b54635f55c77cf7b54c9bbc006b84))\n- Merge branch 'efficiosoft-uwsgi-gevent-support' ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ad64b54be24e5df17b4e08150693997eb404c0f1))\n- Added websocket support for uWSGI with gevent ([commit](https://github.com/miguelgrinberg/python-engineio/commit/8f92f4eba2f94d9388a98fadc38b95611a49056d)) (thanks **Robert Schindler**!)\n- minor updates to readme file ([commit](https://github.com/miguelgrinberg/python-engineio/commit/298310af53f1e8bc87468d1b3ed1f146167c090a))\n\n**Release 0.9.2** - 2016-06-28\n\n- minor comment additions to examples ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c85d06ebb3c5414c2b6b28a900e0e6d5f1916dd5))\n- async message events, sleep function, better client timeout Several improvements in this commit: 1. Message event handlers are invoked in a thread so that they are non-blocking. 2. Added a sleep function that is generic across async modes. 3. The timeout to declare a client gone has been extended to match the ping timeout setting. ([commit](https://github.com/miguelgrinberg/python-engineio/commit/6670627ea404679fc794b496c21ffce689fc6151))\n\n**Release 0.9.1** - 2016-05-15\n\n- do not crash if recipient of a message is gone ([commit](https://github.com/miguelgrinberg/python-engineio/commit/95c9a55457e9cbd36597b14ad840e31abdb2030e))\n\n**Release 0.9.0** - 2016-03-06\n\n- Correct generation of binary xhr2 packets ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5e5e0a34faa218de32b5bf7a2358d12a3fd6493d))\n- Do not write binary packets to the log ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d338ee8787738aab7b7b2fcac9b31127dcb2e9b1))\n- Hopefully addressed some tests that fail intermittently on travis ([commit](https://github.com/miguelgrinberg/python-engineio/commit/27bc79f91ad32a90f6f3ea8bd87cead8f4a14f41))\n\n**Release 0.8.8** - 2016-02-21\n\n- Dispose of disconnected sockets ([commit](https://github.com/miguelgrinberg/python-engineio/commit/08c518db6c6dd12d81890cd6239113cfd84e9eec))\n- disable imports warning in flake8 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e3badf30f89e4981ed419cf645ccec976370c376))\n\n**Release 0.8.7** - 2016-01-26\n\n\n**Release 0.8.6** - 2016-01-10\n\n- Graceful failure when websocket is request and the async mode does not support it ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2a5cdf289d2f1af97270f3bbf58669a507aecb9c))\n\n**Release 0.8.5** - 2016-01-02\n\n- additional eventlet unit test ([commit](https://github.com/miguelgrinberg/python-engineio/commit/abd54e58d274355d961ed9272d7b7fda9e3ef9fc))\n- Update tests to correspond with flake8 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d1969d6bc016b0e3dc66df7eeb30a9c76debc6b6)) (thanks **Artemiy Rodionov**!)\n- Fix eventlet wsgi websocket __call__ return [#12](https://github.com/miguelgrinberg/python-engineio/issues/12) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3f8ecccd40c3f05ef966a6f7e0e2953dc992dfa6)) (thanks **Artemiy Rodionov**!)\n\n**Release 0.8.4** - 2015-12-18\n\n- Revert \"_websocket_handler waits on writer even after the socket is closed\" [#11](https://github.com/miguelgrinberg/python-engineio/issues/11) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a4ffc8e916aabdc96b0cc7bb5262baf8bd39c661))\n\n**Release 0.8.3** - 2015-12-14\n\n- _websocket_handler waits on writer even after the socket is closed This patch wakes up the writer with a null message when the socket gets closed ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0c439be734b29b1006b7c6d43f1acc6d2260ed9c)) (thanks **Babu Shanmugam**!)\n\n**Release 0.8.2** - 2015-12-13\n\n- Runtime error when websocket is missing from environment ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2ba8a89df6558f088d2cccb541602893929954c0))\n\n**Release 0.8.1** - 2015-12-03\n\n- fix python 3.5 build ([commit](https://github.com/miguelgrinberg/python-engineio/commit/bba8f4bb39634b1523e6932f4b6378251dc0d401))\n- tolerate payloads in UPGRADE packet [#7](https://github.com/miguelgrinberg/python-engineio/issues/7) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/0193b5c9935f9dd56e48610499ea6b528cf09582))\n\n**Release 0.8.0** - 2015-11-21\n\n- expose start_background_thread() as a public method ([commit](https://github.com/miguelgrinberg/python-engineio/commit/16aa518d565b7af12c3de07d3416700da5bc99ec))\n- Added python 3.5 to the tox build ([commit](https://github.com/miguelgrinberg/python-engineio/commit/5be3c32d2688655891b203aef2d0a31b2b536d6a))\n\n**Release 0.7.2** - 2015-11-04\n\n- Correctly end eventlet's websocket connection See miguelgrinberg/flask-socketio[#167](https://github.com/miguelgrinberg/python-engineio/issues/167) for the problem this fixes. ([commit](https://github.com/miguelgrinberg/python-engineio/commit/fef4b4739d074cebc741d58e099d8b6459e96112))\n\n**Release 0.7.1** - 2015-10-19\n\n- More robust handling of the upgrade exchange ([commit](https://github.com/miguelgrinberg/python-engineio/commit/66b4bc14cb514230799e116a08410e4c3b1deb15))\n\n**Release 0.7.0** - 2015-10-17\n\n- Add kwargs to server constructor ([commit](https://github.com/miguelgrinberg/python-engineio/commit/933ef62fcfd7dedced4b5660084b172181fb4cc9))\n\n**Release 0.6.9** - 2015-10-16\n\n- Give eventlet access to the socket when running under gunicorn ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3c63157f14c2c7443aa2fa8f339bd9afdadb8fa4))\n\n**Release 0.6.8** - 2015-10-07\n\n- Raise a runtime error when gevent-websocket's custom server is not used ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e38cad9d1fb5924db48db4e6632fb756ef6f9767))\n\n**Release 0.6.7** - 2015-09-26\n\n- Better handling of connection state ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c3715e6e6e401d6bc217a99573a8d3b90cf025b1))\n- Small improvements to example apps ([commit](https://github.com/miguelgrinberg/python-engineio/commit/48d999d75e60ef2a11f5db6007385046702f50fa))\n- Correctly set state of socket connected directly with websocket transport ([commit](https://github.com/miguelgrinberg/python-engineio/commit/86ed25d19fe6f97d7906891172a44f7d0c5fe185))\n- Add wrapper to create threads compatible with the selected async mode ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d20c114e6b5bae6d23e756fe4dedb9293d63bdbc))\n\n**Release 0.6.6** - 2015-09-06\n\n- Accept direct websocket connections ([commit](https://github.com/miguelgrinberg/python-engineio/commit/448acfb367c5d9bae464bf7175e77205a970380b))\n- Fix executable bit, once again ([commit](https://github.com/miguelgrinberg/python-engineio/commit/fbc018f9a7592f166647ffa4dec3c534769705db))\n\n**Release 0.6.5** - 2015-09-02\n\n- Added transport() method ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f3aeeb51eed439dad82f7fc808a79e6a6718d261))\n\n**Release 0.6.4** - 2015-09-01\n\n- Preserve exception in case it is lost before it is re-reaised ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f0c2f5b444b57c7b80f262e90fcd608cd3af2deb))\n- Added a port of the \"latency\" example from the official Javascript client ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b976ff304e045aa375ec3f9f1f8f17483b2d1934))\n- Allow application to provide a custom JSON encoder/decoder. ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1e8fab676f83eab1b82778ab6dcd362609301d57))\n\n**Release 0.6.3** - 2015-08-30\n\n- added b64 unit tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c270acf1da2eb39e12049b86e58287aa9ce0dd71))\n- Added b64 checks and encoding during initial connect [#4](https://github.com/miguelgrinberg/python-engineio/issues/4) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/ac90ed68668f617f347c08d0ea4c37ea56ac12c3)) (thanks **Myles Ringle**!)\n\n**Release 0.6.2** - 2015-08-23\n\n- Improved handling of logging ([commit](https://github.com/miguelgrinberg/python-engineio/commit/142b9a66e1e29e5069696a8a2e9757bcb394b268))\n- Make gevent websocket optional in example app ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c6b1ae91e2e7c3ee8dfec3caf8a8dfa8c2800aa2))\n\n**Release 0.6.1** - 2015-08-20\n\n- Make gevent thread arguments optional ([commit](https://github.com/miguelgrinberg/python-engineio/commit/3c4f10f266e694380104234294b9ccf2730c1263))\n\n**Release 0.6.0** - 2015-08-20\n\n- Add WebSocket support for gevent (Idea derived from pull request [#1](https://github.com/miguelgrinberg/python-engineio/issues/1) by @drdaeman) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/96dc09b0119a816aada9ad787344ccc912608d55))\n- Made parsing of HTTP connection header more robust ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f1ce5e0f5b904e44d587d6dc5aab44800f73cf40))\n- Refactored the three async modes as separate modules for greater flexibility (Idea derived from pull request [#1](https://github.com/miguelgrinberg/python-engineio/issues/1) by @drdaeman) ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a85ac4c97e5a5e0d2ecdfd273673b479c0b6c7ff))\n- Fix executable bit on several files ([commit](https://github.com/miguelgrinberg/python-engineio/commit/47bc67efc86c3043f4b3c786eea9776a04222e04))\n\n**Release 0.5.1** - 2015-08-17\n\n- Correct handling of CORS origin header ([commit](https://github.com/miguelgrinberg/python-engineio/commit/394a87877e49424461a2c4053e9ce8c216c093b8))\n- minor improvements to the example application ([commit](https://github.com/miguelgrinberg/python-engineio/commit/c02a58795bb133f4eb80e7f4d0c64c3a9281c7c3))\n- documentation improvements ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f9eaa604d3025aa88a075ab13908ad27ca2b32f1))\n\n**Release 0.5.0** - 2015-08-04\n\n- Support for gevent and threading in addition to eventlet. Also improved example application. ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e72e4883a7301b8dc4bc1128597191d167776331))\n\n**Release 0.4.0** - 2015-08-03\n\n- ensure all HTTP response payloads are returned as bytes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/d38d57f6af139a02adeb5e73f8a3308542ffc3a7))\n- Added robustness when dealing with disconnected clients ([commit](https://github.com/miguelgrinberg/python-engineio/commit/7b39dbb6c547ed9dde19f4537e6b3f8e725a4fb6))\n- removed assert_called_once from tests ([commit](https://github.com/miguelgrinberg/python-engineio/commit/e6f1b8b7f6c5acb1f37f595cd9696bc5d855c987))\n- Added logging for websocket upgrade ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4b5cecab56f4891040f7da04ced523ea50cb8dca))\n- Fixed incorrect unit test ([commit](https://github.com/miguelgrinberg/python-engineio/commit/583736a3af266d15c31ee03546f11d018fb97e42))\n- rename close() to disconnect() for consistency ([commit](https://github.com/miguelgrinberg/python-engineio/commit/12cc2830374a4848127614f1a21fe8712574219b))\n\n**Release 0.3.1** - 2015-07-04\n\n- Switch README to rst format ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4fb16f8574004ad5b846d81eb9a9d958b448a7da))\n- minor documentation and code fixes ([commit](https://github.com/miguelgrinberg/python-engineio/commit/f0e6be6ce16e98f270327a516754ec4d18d7b2f1))\n\n**Release 0.3.0** - 2015-07-04\n\n- Better support for unicode in Python 2 ([commit](https://github.com/miguelgrinberg/python-engineio/commit/9fb200cbf81992cc6cc1cf8f1c9fc15471e5f0f9))\n- allow connect event handler to send data to client ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a0dbf69fec47db0bfdca6585267eed21bfc2da91))\n\n**Release 0.2.0** - 2015-06-29\n\n- Added non-decorator format for Server.on() ([commit](https://github.com/miguelgrinberg/python-engineio/commit/2d8d41c514f317e4c2e347030d82c351fbe0fb4e))\n- declared vendered js file ([commit](https://github.com/miguelgrinberg/python-engineio/commit/584aba250334fe10949cefbbb99afff89222f024))\n- Added pypy to travis builds ([commit](https://github.com/miguelgrinberg/python-engineio/commit/b982ed13d64ece4c76c6af323e2b29db4bdabfdf))\n- minor documentation updates ([commit](https://github.com/miguelgrinberg/python-engineio/commit/a25b639ea3e833a28725fd22b36de5b5f6973744))\n- Initial commit ([commit](https://github.com/miguelgrinberg/python-engineio/commit/4303b86e4f363e746957e6adecea303089e90f70))\n- initial version ([commit](https://github.com/miguelgrinberg/python-engineio/commit/1d53a103ffcc43d1482fecb489d748c1ffaadbe0))\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Miguel Grinberg\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include README.md LICENSE tox.ini tests/**/* docs/**/*\nexclude **/*.pyc\n"
  },
  {
    "path": "README.md",
    "content": "python-engineio\n===============\n\n[![Build status](https://github.com/miguelgrinberg/python-engineio/workflows/build/badge.svg)](https://github.com/miguelgrinberg/python-engineio/actions) [![codecov](https://codecov.io/gh/miguelgrinberg/python-engineio/branch/main/graph/badge.svg)](https://codecov.io/gh/miguelgrinberg/python-engineio)\n\nPython implementation of the `Engine.IO` realtime client and server.\n\nSponsors\n--------\n\nThe following organizations are funding this project:\n\n![Socket.IO](https://images.opencollective.com/socketio/050e5eb/logo/64.png)<br>[Socket.IO](https://socket.io)  | [Add your company here!](https://github.com/sponsors/miguelgrinberg)|\n-|-\n\nMany individual sponsors also support this project through small ongoing contributions. Why not [join them](https://github.com/sponsors/miguelgrinberg)?\n\nResources\n---------\n\n-  [Documentation](https://python-engineio.readthedocs.io/)\n-  [PyPI](https://pypi.python.org/pypi/python-engineio)\n-  [Change Log](https://github.com/miguelgrinberg/python-engineio/blob/main/CHANGES.md)\n-  Questions? See the [questions](https://stackoverflow.com/questions/tagged/python-socketio) others have asked on Stack Overflow, or [ask](https://stackoverflow.com/questions/ask?tags=python+python-socketio) your own question.\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Reporting a Vulnerability\n\nIf you think you've found a vulnerability on this project, please send me (Miguel Grinberg) an email at mailto:miguel.grinberg@gmail.com with a description of the problem. I will personally review the issue and respond to you with next steps.\n\nIf the issue is highly sensitive, you are welcome to encrypt your message. Here is my [PGP key](http://pgp.mit.edu/pks/lookup?search=miguel.grinberg%40gmail.com&op=index).\n\nPlease do not disclose vulnerabilities publicly before discussing how to proceed with me.\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nSOURCEDIR     = .\nBUILDDIR      = _build\n\n# Put it first so that \"make\" without argument is like \"make help\".\nhelp:\n\t@$(SPHINXBUILD) -M help \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n\n.PHONY: help Makefile\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%: Makefile\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)"
  },
  {
    "path": "docs/_static/README.md",
    "content": "Place static files used by the documentation here.\n"
  },
  {
    "path": "docs/api.rst",
    "content": "API Reference\n=============\n\n.. toctree::\n   :maxdepth: 2\n\n   api_client\n   api_async_client\n   api_server\n   api_async_server\n   api_wsgiapp\n   api_asgiapp\n   api_middleware\n\n"
  },
  {
    "path": "docs/api_asgiapp.rst",
    "content": ".. autoclass:: engineio.ASGIApp\n   :members:\n\n"
  },
  {
    "path": "docs/api_async_client.rst",
    "content": ".. autoclass:: engineio.AsyncClient\n   :members:\n   :inherited-members:\n\n"
  },
  {
    "path": "docs/api_async_server.rst",
    "content": ".. autoclass:: engineio.AsyncServer\n   :members:\n   :inherited-members:\n\n"
  },
  {
    "path": "docs/api_client.rst",
    "content": ".. autoclass:: engineio.Client\n   :members:\n   :inherited-members:\n\n"
  },
  {
    "path": "docs/api_middleware.rst",
    "content": ".. autoclass:: engineio.Middleware\n   :members:\n\n"
  },
  {
    "path": "docs/api_server.rst",
    "content": ".. autoclass:: engineio.Server\n   :members:\n   :inherited-members:\n\n"
  },
  {
    "path": "docs/api_wsgiapp.rst",
    "content": ".. autoclass:: engineio.WSGIApp\n   :members:\n\n"
  },
  {
    "path": "docs/client.rst",
    "content": "The Engine.IO Client\n====================\n\nThis package contains two Engine.IO clients:\n\n- The :func:`engineio.Client` class creates a client compatible with the\n  standard Python library.\n- The :func:`engineio.AsyncClient` class creates a client compatible with\n  the ``asyncio`` package.\n\nThe methods in the two clients are the same, with the only difference that in\nthe ``asyncio`` client most methods are implemented as coroutines.\n\nInstallation\n------------\n\nTo install the standard Python client along with its dependencies, use the\nfollowing command::\n\n    pip install \"python-engineio[client]\"\n\nIf instead you plan on using the ``asyncio`` client, then use this::\n\n    pip install \"python-engineio[asyncio_client]\"\n\nCreating a Client Instance\n--------------------------\n\nTo instantiate an Engine.IO client, simply create an instance of the\nappropriate client class::\n\n    import engineio\n\n    # standard Python\n    eio = engineio.Client()\n\n    # asyncio\n    eio = engineio.AsyncClient()\n\nDefining Event Handlers\n-----------------------\n\nTo responds to events triggered by the connection or the server, event Handler\nfunctions must be defined using the ``on`` decorator::\n\n    @eio.on('connect')\n    def on_connect():\n        print('I'm connected!')\n\n    @eio.on('message')\n    def on_message(data):\n        print('I received a message!')\n\n    @eio.on('disconnect')\n    def on_disconnect(reason):\n        print('I'm disconnected! reason:', reason)\n\nFor the ``asyncio`` server, event handlers can be regular functions as above,\nor can also be coroutines::\n\n    @eio.on('message')\n    async def on_message(data):\n        print('I received a message!')\n\nThe argument given to the ``on`` decorator is the event name. The events that\nare supported are ``connect``, ``message`` and ``disconnect``.\n\nThe ``data`` argument passed to the ``'message'`` event handler contains\napplication-specific data provided by the server with the event.\n\nThe ``disconnect`` handler is invoked for client initiated disconnects, server\ninitiated disconnects, or accidental disconnects, for example due to\nnetworking failures. The argument passed to this handler provides the\ndisconnect reason. Example::\n\n    @eio.on('disconnect')\n    def on_disconnect(reason):\n        if reason == eio.reason.CLIENT_DISCONNECT:\n            print('client disconnection')\n        elif reason == eio.reason.SERVER_DISCONNECT:\n            print('the server kicked me out')\n        else:\n            print(f'disconnect reason: {reason}')\n\nConnecting to a Server\n----------------------\n\nThe connection to a server is established by calling the ``connect()``\nmethod::\n\n    eio.connect('http://localhost:5000')\n\nIn the case of the ``asyncio`` client, the method is a coroutine::\n\n    await eio.connect('http://localhost:5000')\n\nUpon connection, the server assigns the client a unique session identifier.\nThe applicaction can find this identifier in the ``sid`` attribute::\n\n    print('my sid is', eio.sid)\n\nSending Messages\n----------------\n\nThe client can send a message to the server using the ``send()`` method::\n\n    eio.send({'foo': 'bar'})\n\nOr in the case of ``asyncio``, as a coroutine::\n\n    await eio.send({'foo': 'bar'})\n\nThe single argument provided to the method is the data that is passed on\nto the server. The data can be of type ``str``, ``bytes``, ``dict`` or\n``list``. The data included inside dictionaries and lists is also\nconstrained to these types.\n\nThe ``send()`` method can be invoked inside an event handler as a response\nto a server event, or in any other part of the application, including in\nbackground tasks.\n\nDisconnecting from the Server\n-----------------------------\n\nAt any time the client can request to be disconnected from the server by\ninvoking the ``disconnect()`` method::\n\n    eio.disconnect()\n\nFor the ``asyncio`` client this is a coroutine::\n\n    await eio.disconnect()\n\nManaging Background Tasks\n-------------------------\n\nWhen a client connection to the server is established, a few background\ntasks will be spawned to keep the connection alive and handle incoming\nevents. The application running on the main thread is free to do any\nwork, as this is not going to prevent the functioning of the Engine.IO\nclient.\n\nIf the application does not have anything to do in the main thread and\njust wants to wait until the connection ends, it can call the ``wait()``\nmethod::\n\n    eio.wait()\n\nOr in the ``asyncio`` version::\n\n    await eio.wait()\n\nFor the convenience of the application, a helper function is\nprovided to start a custom background task::\n\n    def my_background_task(my_argument)\n        # do some background work here!\n        pass\n\n    eio.start_background_task(my_background_task, 123)\n\nThe arguments passed to this method are the background function and any\npositional or keyword arguments to invoke the function with. \n\nHere is the ``asyncio`` version::\n\n    async def my_background_task(my_argument)\n        # do some background work here!\n        pass\n\n    eio.start_background_task(my_background_task, 123)\n\nNote that this function is not a coroutine, since it does not wait for the\nbackground function to end, but the background function is.\n\nThe ``sleep()`` method is a second convenience function that is provided for\nthe benefit of applications working with background tasks of their own::\n\n    eio.sleep(2)\n\nOr for ``asyncio``::\n\n    await eio.sleep(2)\n\nThe single argument passed to the method is the number of seconds to sleep\nfor.\n\nDebugging and Troubleshooting\n-----------------------------\n\nTo help you debug issues, the client can be configured to output logs to the\nterminal::\n\n    import engineio\n\n    # standard Python\n    eio = engineio.Client(logger=True)\n\n    # asyncio\n    eio = engineio.AsyncClient(logger=True)\n\nThe ``logger`` argument controls logging behavior:\n\n* ``True``: Enables log output to ``stderr`` at the ``INFO`` level.\n* ``False``: Enables log output to ``stderr`` at the ``ERROR`` level. This is\n  the default.\n* A ``logging.Logger`` instance: Uses the provided logger without additional\n  configuration.\n\nLogging can help identify the cause of connection problems, unexpected\ndisconnections and other issues.\n"
  },
  {
    "path": "docs/conf.py",
    "content": "#\n# Configuration file for the Sphinx documentation builder.\n#\n# This file does only contain a selection of the most common options. For a\n# full list see the documentation:\n# http://www.sphinx-doc.org/en/master/config\n\n# -- Path setup --------------------------------------------------------------\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\n# import os\n# import sys\n# sys.path.insert(0, os.path.abspath('.'))\n\n\n# -- Project information -----------------------------------------------------\n\nproject = 'python-engineio'\ncopyright = '2018, Miguel Grinberg'\nauthor = 'Miguel Grinberg'\n\n# The short X.Y version\nversion = ''\n# The full version, including alpha/beta/rc tags\nrelease = ''\n\n\n# -- General configuration ---------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n]\n\nautodoc_member_order = 'bysource'\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n#\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path.\nexclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']\n\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = 'furo'\nhtml_title = 'python-engineio'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#\nhtml_theme_options = {\n}\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n\n# Custom sidebar templates, must be a dictionary that maps document names\n# to template names.\n#\n# The default sidebars (for documents that don't match any pattern) are\n# defined by theme itself.  Builtin themes are using these templates by\n# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',\n# 'searchbox.html']``.\n#\n# html_sidebars = {}\n\n\n# -- Options for HTMLHelp output ---------------------------------------------\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'python-engineiodoc'\n\n\n# -- Options for LaTeX output ------------------------------------------------\n\nlatex_elements = {\n    # The paper size ('letterpaper' or 'a4paper').\n    #\n    # 'papersize': 'letterpaper',\n\n    # The font size ('10pt', '11pt' or '12pt').\n    #\n    # 'pointsize': '10pt',\n\n    # Additional stuff for the LaTeX preamble.\n    #\n    # 'preamble': '',\n\n    # Latex figure (float) alignment\n    #\n    # 'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n    (master_doc, 'python-engineio.tex', 'python-engineio Documentation',\n     'Miguel Grinberg', 'manual'),\n]\n\n\n# -- Options for manual page output ------------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'python-engineio', 'python-engineio Documentation',\n     [author], 1)\n]\n\n\n# -- Options for Texinfo output ----------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (master_doc, 'python-engineio', 'python-engineio Documentation',\n     author, 'python-engineio', 'One line description of project.',\n     'Miscellaneous'),\n]\n\n\n# -- Options for Epub output -------------------------------------------------\n\n# Bibliographic Dublin Core info.\nepub_title = project\n\n# The unique identifier of the text. This can be a ISBN number\n# or the project homepage.\n#\n# epub_identifier = ''\n\n# A unique identification for the text.\n#\n# epub_uid = ''\n\n# A list of files that should not be packed into the epub file.\nepub_exclude_files = ['search.html']\n\n\n# -- Extension configuration -------------------------------------------------\n"
  },
  {
    "path": "docs/index.rst",
    "content": ".. python-engineio documentation master file, created by\n   sphinx-quickstart on Sat Nov 24 09:42:25 2018.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\npython-engineio\n===============\n\nThis project implements Python based Engine.IO client and server that can run\nstandalone or integrated with a variety of Python web frameworks and\napplications.\n\n.. toctree::\n   :maxdepth: 2\n\n   intro\n   client\n   server\n   api\n\n* :ref:`genindex`\n* :ref:`modindex`\n* :ref:`search`\n"
  },
  {
    "path": "docs/intro.rst",
    "content": ".. engineio documentation master file, created by\n   sphinx-quickstart on Sat Jun 13 23:41:23 2015.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nGetting Started\n===============\n\nWhat is Engine.IO?\n------------------\n\nEngine.IO is a lightweight transport protocol that enables real-time\nbidirectional event-based communication between clients (typically, though\nnot always, web browsers) and a server. The official implementations of the\nclient and server components are written in JavaScript. This package provides\nPython implementations of both, each with standard and ``asyncio`` variants.\n\nThe Engine.IO protocol is extremely simple. Once a connection between a client\nand a server is established, either side can send \"messages\" to the other\nside. Event handlers provided by the applications on both ends are invoked\nwhen a message is received, or when a connection is established or dropped.\n\nClient Examples\n---------------\n\nThe example that follows shows a simple Python client::\n\n    import engineio\n\n    eio = engineio.Client()\n\n    @eio.on('connect')\n    def on_connect():\n        print('connection established')\n\n    @eio.on('message')\n    def on_message(data):\n        print('message received with ', data)\n        eio.send({'response': 'my response'})\n    \n    @eio.on('disconnect')\n    def on_disconnect():\n        print('disconnected from server')\n    \n    eio.connect('http://localhost:5000')\n    eio.wait()\n\nAnd here is a similar client written using the official Engine.IO Javascript\nclient::\n\n    <script src=\"/path/to/engine.io.js\"></script>\n    <script>\n        var socket = eio('http://localhost:5000');\n        socket.on('open', function() { console.log('connection established'); });\n        socket.on('message', function(data) {\n            console.log('message received with ' + data);\n            socket.send({response: 'my response'});\n        });\n        socket.on('close', function() { console.log('disconnected from server'); });\n    </script>\n\nClient Features\n---------------\n\n- Can connect to other Engine.IO complaint servers besides the one in this package.\n- Compatible with Python 3.6+.\n- Two versions of the client, one for standard Python and another for ``asyncio``.\n- Uses an event-based architecture implemented with decorators that hides the\n  details of the protocol.\n- Implements HTTP long-polling and WebSocket transports.\n\nServer Examples\n---------------\n\nThe following application is a basic example that uses the Eventlet\nasynchronous server::\n\n    import engineio\n    import eventlet\n\n    eio = engineio.Server()\n    app = engineio.WSGIApp(eio, static_files={\n        '/': {'content_type': 'text/html', 'filename': 'index.html'}\n    })\n\n    @eio.on('connect')\n    def connect(sid, environ):\n        print(\"connect \", sid)\n\n    @eio.on('message')\n    def message(sid, data):\n        print(\"message \", data)\n        eio.send(sid, 'reply')\n\n    @eio.on('disconnect')\n    def disconnect(sid):\n        print('disconnect ', sid)\n\n    if __name__ == '__main__':\n        eventlet.wsgi.server(eventlet.listen(('', 5000)), app)\n\nBelow is a similar application, coded for asyncio and the Uvicorn web server::\n\n    import engineio\n    import uvicorn\n\n    eio = engineio.AsyncServer()\n    app = engineio.ASGIApp(eio, static_files={\n        '/': {'content_type': 'text/html', 'filename': 'index.html'}\n    })\n\n    @eio.on('connect')\n    def connect(sid, environ):\n        print(\"connect \", sid)\n\n    @eio.on('message')\n    async def message(sid, data):\n        print(\"message \", data)\n        await eio.send(sid, 'reply')\n\n    @eio.on('disconnect')\n    def disconnect(sid):\n        print('disconnect ', sid)\n\n    if __name__ == '__main__':\n        uvicorn.run('127.0.0.1', 5000)\n\nServer Features\n---------------\n\n- Can accept clients running other complaint Engine.IO clients besides the one in this\n  package.\n- Compatible with Python 3.6+.\n- Two versions of the server, one for standard Python and another for ``asyncio``.\n- Supports large number of clients even on modest hardware due to being\n  asynchronous.\n- Can be hosted on any `WSGI <https://wsgi.readthedocs.io/en/latest/index.html>`_ and\n  `ASGI <https://asgi.readthedocs.io/en/latest/>`_ web servers includind\n  `Gunicorn <https://gunicorn.org/>`_, `Uvicorn <https://github.com/encode/uvicorn>`_,\n  `eventlet <http://eventlet.net/>`_ and `gevent <http://gevent.org>`_.\n- Can be integrated with WSGI applications written in frameworks such as Flask, Django,\n  etc.\n- Can be integrated with `aiohttp <http://aiohttp.readthedocs.io/>`_,\n  `sanic <http://sanic.readthedocs.io/>`_ and `tornado <http://www.tornadoweb.org/>`_\n  ``asyncio`` applications.\n- Uses an event-based architecture implemented with decorators that hides the\n  details of the protocol.\n- Implements HTTP long-polling and WebSocket transports.\n- Supports XHR2 and XHR browsers as clients.\n- Supports text and binary messages.\n- Supports gzip and deflate HTTP compression.\n- Configurable CORS responses to avoid cross-origin problems with browsers.\n"
  },
  {
    "path": "docs/make.bat",
    "content": "@ECHO OFF\r\n\r\npushd %~dp0\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sphinx-build\r\n)\r\nset SOURCEDIR=.\r\nset BUILDDIR=_build\r\n\r\nif \"%1\" == \"\" goto help\r\n\r\n%SPHINXBUILD% >NUL 2>NUL\r\nif errorlevel 9009 (\r\n\techo.\r\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r\n\techo.installed, then set the SPHINXBUILD environment variable to point\r\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\r\n\techo.may add the Sphinx directory to PATH.\r\n\techo.\r\n\techo.If you don't have Sphinx installed, grab it from\r\n\techo.http://sphinx-doc.org/\r\n\texit /b 1\r\n)\r\n\r\n%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%\r\ngoto end\r\n\r\n:help\r\n%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%\r\n\r\n:end\r\npopd\r\n"
  },
  {
    "path": "docs/server.rst",
    "content": "The Engine.IO Server\n====================\n\nThis package contains two Engine.IO servers:\n\n- The :func:`engineio.Server` class creates a server compatible with the\n  standard Python library.\n- The :func:`engineio.AsyncServer` class creates a server compatible with\n  the ``asyncio`` package.\n\nThe methods in the two servers are the same, with the only difference that in\nthe ``asyncio`` server most methods are implemented as coroutines.\n\nInstallation\n------------\n\nTo install the Python Engine.IO server use the following command::\n\n    pip install \"python-engineio\"\n\nIn addition to the server, you will need to select an asynchronous framework\nor server to use along with it. The list of supported packages is covered\nin the :ref:`deployment-strategies` section.\n\nCreating a Server Instance\n--------------------------\n\nAn Engine.IO server is an instance of class :class:`engineio.Server`. This\ninstance can be transformed into a standard WSGI application by wrapping it\nwith the :class:`engineio.WSGIApp` class::\n\n   import engineio\n\n   # create a Engine.IO server\n   eio = engineio.Server()\n\n   # wrap with a WSGI application\n   app = engineio.WSGIApp(eio)\n\nFor asyncio based servers, the :class:`engineio.AsyncServer` class provides\nthe same functionality, but in a coroutine friendly format. If desired, The\n:class:`engineio.ASGIApp` class can transform the server into a standard\nASGI application::\n\n    # create a Engine.IO server\n    eio = engineio.AsyncServer()\n\n    # wrap with ASGI application\n    app = engineio.ASGIApp(eio)\n\nThese two wrappers can also act as middlewares, forwarding any traffic that is\nnot intended to the Engine.IO server to another application. This allows\nEngine.IO servers to integrate easily into existing WSGI or ASGI applications::\n\n   from wsgi import app  # a Flask, Django, etc. application\n   app = engineio.WSGIApp(eio, app)\n\nServing Static Files\n--------------------\n\nThe Engine.IO server can be configured to serve static files to clients. This\nis particularly useful to deliver HTML, CSS and JavaScript files to clients\nwhen this package is used without a companion web framework.\n\nStatic files are configured with a Python dictionary in which each key/value\npair is a static file mapping rule. In its simplest form, this dictionary has\none or more static file URLs as keys, and the corresponding files in the server\nas values::\n\n    static_files = {\n        '/': 'latency.html',\n        '/static/engine.io.js': 'static/engine.io.js',\n        '/static/style.css': 'static/style.css',\n    }\n\nWith this example configuration, when the server receives a request for ``/``\n(the root URL) it will return the contents of the file ``latency.html`` in the\ncurrent directory, and will assign a content type based on the file extension,\nin this case ``text/html``.\n\nFiles with the ``.html``, ``.css``, ``.js``, ``.json``, ``.jpg``, ``.png``,\n``.gif`` and ``.txt`` file extensions are automatically recognized and\nassigned the correct content type. For files with other file extensions or\nwith no file extension, the ``application/octet-stream`` content type is used\nas a default.\n\nIf desired, an explicit content type for a static file can be given as follows::\n\n    static_files = {\n        '/': {'filename': 'latency.html', 'content_type': 'text/plain'},\n    }\n\nIt is also possible to configure an entire directory in a single rule, so that all\nthe files in it are served as static files::\n\n    static_files = {\n        '/static': './public',\n    }\n\nIn this example any files with URLs starting with ``/static`` will be served\ndirectly from the ``public`` folder in the current directory, so for example,\nthe URL ``/static/index.html`` will return local file ``./public/index.html``\nand the URL ``/static/css/styles.css`` will return local file\n``./public/css/styles.css``.\n\nIf a URL that ends in a ``/`` is requested, then a default filename of\n``index.html`` is appended to it. In the previous example, a request for the\n``/static/`` URL would return local file ``./public/index.html``. The default\nfilename to serve for slash-ending URLs can be set in the static files\ndictionary with an empty key::\n\n    static_files = {\n        '/static': './public',\n        '': 'image.gif',\n    }\n\nWith this configuration, a request for ``/static/`` would return\nlocal file ``./public/image.gif``. A non-standard content type can also be\nspecified if needed::\n\n    static_files = {\n        '/static': './public',\n        '': {'filename': 'image.gif', 'content_type': 'text/plain'},\n    }\n\nThe static file configuration dictionary is given as the ``static_files``\nargument to the ``engineio.WSGIApp`` or ``engineio.ASGIApp`` classes::\n\n    # for standard WSGI applications\n    eio = engineio.Server()\n    app = engineio.WSGIApp(eio, static_files=static_files)\n\n    # for asyncio-based ASGI applications\n    eio = engineio.AsyncServer()\n    app = engineio.ASGIApp(eio, static_files=static_files)\n\nThe routing precedence in these two classes is as follows:\n\n- First, the path is checked against the Engine.IO path.\n- Next, the path is checked against the static file configuration, if present.\n- If the path did not match the Engine.IO path or any static file, control is\n  passed to the secondary application if configured, else a 404 error is\n  returned.\n\nNote: static file serving is intended for development use only, and as such\nit lacks important features such as caching. Do not use in a production\nenvironment.\n\nDefining Event Handlers\n-----------------------\n\nTo responds to events triggered by the connection or the client, event Handler\nfunctions must be defined using the ``on`` decorator::\n\n    @eio.on('connect')\n    def on_connect(sid):\n        print('A client connected!')\n\n    @eio.on('message')\n    def on_message(sid, data):\n        print('I received a message!')\n\n    @eio.on('disconnect')\n    def on_disconnect(sid, reason):\n        print('Client disconnected! reason:', reason)\n\nFor the ``asyncio`` server, event handlers can be regular functions as above,\nor can also be coroutines::\n\n    @eio.on('message')\n    async def on_message(sid, data):\n        print('I received a message!')\n\nThe argument given to the ``on`` decorator is the event name. The events that\nare supported are ``connect``, ``message`` and ``disconnect``.\n\nThe ``sid`` argument passed into all the event handlers is a connection\nidentifier for the client. All the events from a client will use the same\n``sid`` value.\n\nThe ``connect`` handler is the place where the server can perform\nauthentication. The value returned by this handler is used to determine if the\nconnection is accepted or rejected. When the handler does not return any value\n(which is the same as returning ``None``) or when it returns ``True`` the\nconnection is accepted. If the handler returns ``False`` or any JSON\ncompatible data type (string, integer, list or dictionary) the connection is\nrejected. A rejected connection triggers a response with a 401 status code.\n\nThe ``data`` argument passed to the ``'message'`` event handler contains\napplication-specific data provided by the client with the event.\n\nThe ``disconnect`` handler is invoked for client initiated disconnects,\nserver initiated disconnects, or accidental disconnects, for example due to\nnetworking failures. The second argument passed to this handler provides the\ndisconnect reason. Example::\n\n    @eio.on('disconnect')\n    def on_disconnect(sid, reason):\n        if reason == eio.reason.CLIENT_DISCONNECT:\n            print('the client went away')\n        elif reason == eio.reason.SERVER_DISCONNECT:\n            print('the client was kicked out')\n        else:\n            print(f'disconnect reason: {reason}')\n\nSending Messages\n----------------\n\nThe server can send a message to any client using the ``send()`` method::\n\n    eio.send(sid, {'foo': 'bar'})\n\nOr in the case of ``asyncio``, as a coroutine::\n\n    await eio.send(sid, {'foo': 'bar'})\n\nThe first argument provided to the method is the connection identifier for\nthe recipient client. The second argument is the data that is passed on\nto the server. The data can be of type ``str``, ``bytes``, ``dict`` or\n``list``. The data included inside dictionaries and lists is also\nconstrained to these types.\n\nThe ``send()`` method can be invoked inside an event handler as a response\nto a client event, or in any other part of the application, including in\nbackground tasks.\n\nUser Sessions\n-------------\n\nThe server can maintain application-specific information in a user session\ndedicated to each connected client. Applications can use the user session to\nwrite any details about the user that need to be preserved throughout the life\nof the connection, such as usernames or user ids.\n\nThe ``save_session()`` and ``get_session()`` methods are used to store and\nretrieve information in the user session::\n\n    @eio.on('connect')\n    def on_connect(sid, environ):\n        username = authenticate_user(environ)\n        eio.save_session(sid, {'username': username})\n\n    @eio.on('message')\n    def on_message(sid, data):\n        session = eio.get_session(sid)\n        print('message from ', session['username'])\n\nFor the ``asyncio`` server, these methods are coroutines::\n\n    @eio.on('connect')\n    async def on_connect(sid, environ):\n        username = authenticate_user(environ)\n        await eio.save_session(sid, {'username': username})\n\n    @eio.on('message')\n    async def on_message(sid, data):\n        session = await eio.get_session(sid)\n        print('message from ', session['username'])\n\nThe session can also be manipulated with the `session()` context manager::\n\n    @eio.on('connect')\n    def on_connect(sid, environ):\n        username = authenticate_user(environ)\n        with eio.session(sid) as session:\n            session['username'] = username\n\n    @eio.on('message')\n    def on_message(sid, data):\n        with eio.session(sid) as session:\n            print('message from ', session['username'])\n\nFor the ``asyncio`` server, an asynchronous context manager is used::\n\n    @eio.on('connect')\n    def on_connect(sid, environ):\n        username = authenticate_user(environ)\n        async with eio.session(sid) as session:\n            session['username'] = username\n\n    @eio.on('message')\n    def on_message(sid, data):\n        async with eio.session(sid) as session:\n            print('message from ', session['username'])\n\nNote: the contents of the user session are destroyed when the client\ndisconnects.\n\nDisconnecting a Client\n----------------------\n\nAt any time the server can disconnect a client from the server by invoking the\n``disconnect()`` method and passing the ``sid`` value assigned to the client::\n\n    eio.disconnect(sid)\n\nFor the ``asyncio`` client this is a coroutine::\n\n    await eio.disconnect(sid)\n\nManaging Background Tasks\n-------------------------\n\nFor the convenience of the application, a helper function is provided to\nstart a custom background task::\n\n    def my_background_task(my_argument)\n        # do some background work here!\n        pass\n\n    eio.start_background_task(my_background_task, 123)\n\nThe arguments passed to this method are the background function and any\npositional or keyword arguments to invoke the function with. \n\nHere is the ``asyncio`` version::\n\n    async def my_background_task(my_argument)\n        # do some background work here!\n        pass\n\n    eio.start_background_task(my_background_task, 123)\n\nNote that this function is not a coroutine, since it does not wait for the\nbackground function to end, but the background function is.\n\nThe ``sleep()`` method is a second convenience function that is provided for\nthe benefit of applications working with background tasks of their own::\n\n    eio.sleep(2)\n\nOr for ``asyncio``::\n\n    await eio.sleep(2)\n\nThe single argument passed to the method is the number of seconds to sleep\nfor.\n\nDebugging and Troubleshooting\n-----------------------------\n\nTo help you debug issues, the server can be configured to output logs to the\nterminal::\n\n    import engineio\n\n    # standard Python\n    eio = engineio.Server(logger=True)\n\n    # asyncio\n    eio = engineio.AsyncServer(logger=True)\n\nThe ``logger`` argument controls logging behavior:\n\n* ``True``: Enables log output to ``stderr`` at the ``INFO`` level.\n* ``False``: Enables log output to ``stderr`` at the ``ERROR`` level. This is\n  the default.\n* A ``logging.Logger`` instance: Uses the provided logger without additional\n  configuration.\n\nLogging can help identify the cause of connection problems, 400 responses,\nbad performance and other issues.\n\n.. _deployment-strategies:\n\nDeployment Strategies\n---------------------\n\nThe following sections describe a variety of deployment strategies for\nEngine.IO servers.\n\nUvicorn, Daphne, and other ASGI servers\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe ``engineio.ASGIApp`` class is an ASGI compatible application that can\nforward Engine.IO traffic to an ``engineio.AsyncServer`` instance::\n\n   eio = engineio.AsyncServer(async_mode='asgi')\n   app = engineio.ASGIApp(eio)\n\nIf desired, the ``engineio.ASGIApp`` class can forward any traffic that is not\nEngine.IO to another ASGI application, making it possible to deploy a standard\nASGI web application and the Engine.IO server as a bundle::\n\n   eio = engineio.AsyncServer(async_mode='asgi')\n   app = engineio.ASGIApp(eio, other_app)\n\nThe ``ASGIApp`` instance is a fully complaint ASGI instance that can be\ndeployed with an ASGI compatible web server.\n\nAiohttp\n~~~~~~~\n\n`aiohttp <http://aiohttp.readthedocs.io/>`_ provides a framework with support\nfor HTTP and WebSocket, based on asyncio.\n\nInstances of class ``engineio.AsyncServer`` will automatically use aiohttp\nfor asynchronous operations if the library is installed. To request its use\nexplicitly, the ``async_mode`` option can be given in the constructor::\n\n    eio = engineio.AsyncServer(async_mode='aiohttp')\n\nA server configured for aiohttp must be attached to an existing application::\n\n    app = web.Application()\n    eio.attach(app)\n\nThe aiohttp application can define regular routes that will coexist with the\nEngine.IO server. A typical pattern is to add routes that serve a client\napplication and any associated static files.\n\nThe aiohttp application is then executed in the usual manner::\n\n    if __name__ == '__main__':\n        web.run_app(app)\n\nTornado\n~~~~~~~\n\n`Tornado <http://www.tornadoweb.org//>`_ is a web framework with support\nfor HTTP and WebSocket. Only Tornado version 5 and newer are supported, thanks\nto its tight integration with asyncio.\n\nInstances of class ``engineio.AsyncServer`` will automatically use tornado\nfor asynchronous operations if the library is installed. To request its use\nexplicitly, the ``async_mode`` option can be given in the constructor::\n\n    eio = engineio.AsyncServer(async_mode='tornado')\n\nA server configured for tornado must include a request handler for\nEngine.IO::\n\n    app = tornado.web.Application(\n        [\n            (r\"/engine.io/\", engineio.get_tornado_handler(eio)),\n        ],\n        # ... other application options\n    )\n\nThe tornado application can define other routes that will coexist with the\nEngine.IO server. A typical pattern is to add routes that serve a client\napplication and any associated static files.\n\nThe tornado application is then executed in the usual manner::\n\n    app.listen(port)\n    tornado.ioloop.IOLoop.current().start()\n\nSanic\n~~~~~\n\nNote: Due to some backward incompatible changes introduced in recent versions\nof Sanic, it is currently recommended that a Sanic application is deployed with\nthe ASGI integration instead.\n\n`Sanic <http://sanic.readthedocs.io/>`_ is a very efficient asynchronous web\nserver for Python.\n\nInstances of class ``engineio.AsyncServer`` will automatically use Sanic for\nasynchronous operations if the framework is installed. To request its use\nexplicitly, the ``async_mode`` option can be given in the constructor::\n\n    eio = engineio.AsyncServer(async_mode='sanic')\n\nA server configured for Sanic must be attached to an existing application::\n\n    app = Sanic()\n    eio.attach(app)\n\nThe Sanic application can define regular routes that will coexist with the\nEngine.IO server. A typical pattern is to add routes that serve a client\napplication and any associated static files to this application.\n\nThe Sanic application is then executed in the usual manner::\n\n    if __name__ == '__main__':\n        app.run()\n\nIt has been reported that the CORS support provided by the Sanic extension\n`sanic-cors <https://github.com/ashleysommer/sanic-cors>`_ is incompatible with\nthis package's own support for this protocol. To disable CORS support in this\npackage and let Sanic take full control, initialize the server as follows::\n\n    eio = engineio.AsyncServer(async_mode='sanic', cors_allowed_origins=[])\n\nOn the Sanic side you will need to enable the `CORS_SUPPORTS_CREDENTIALS`\nsetting in addition to any other configuration that you use::\n\n    app.config['CORS_SUPPORTS_CREDENTIALS'] = True\n\nEventlet\n~~~~~~~~\n\n`Eventlet <http://eventlet.net/>`_ is a high performance concurrent networking\nlibrary for Python 2 and 3 that uses coroutines, enabling code to be written in\nthe same style used with the blocking standard library functions. An Engine.IO\nserver deployed with eventlet has access to the long-polling and WebSocket\ntransports.\n\nInstances of class ``engineio.Server`` will automatically use eventlet for\nasynchronous operations if the library is installed. To request its use\nexplicitly, the ``async_mode`` option can be given in the constructor::\n\n    eio = engineio.Server(async_mode='eventlet')\n\nA server configured for eventlet is deployed as a regular WSGI application\nusing the provided ``engineio.WSGIApp``::\n\n    app = engineio.WSGIApp(eio)\n    import eventlet\n    eventlet.wsgi.server(eventlet.listen(('', 8000)), app)\n\nEventlet with Gunicorn\n~~~~~~~~~~~~~~~~~~~~~~\n\nAn alternative to running the eventlet WSGI server as above is to use\n`gunicorn <gunicorn.org>`_, a fully featured pure Python web server. The\ncommand to launch the application under gunicorn is shown below::\n\n    $ gunicorn -k eventlet -w 1 module:app\n\nDue to limitations in its load balancing algorithm, gunicorn can only be used\nwith one worker process, so the ``-w 1`` option is required. Note that a\nsingle eventlet worker can handle a large number of concurrent clients.\n\nAnother limitation when using gunicorn is that the WebSocket transport is not\navailable, because this transport it requires extensions to the WSGI standard.\n\nNote: Eventlet provides a ``monkey_patch()`` function that replaces all the\nblocking functions in the standard library with equivalent asynchronous\nversions. While python-engineio does not require monkey patching, other\nlibraries such as database drivers are likely to require it.\n\nGevent\n~~~~~~\n\n`Gevent <http://gevent.org>`_ is another asynchronous framework based on\ncoroutines, very similar to eventlet. An Engine.IO server deployed with\ngevent has access to the long-polling and websocket transports.\n\nInstances of class ``engineio.Server`` will automatically use gevent for\nasynchronous operations if the library is installed and eventlet is not\ninstalled. To request gevent to be selected explicitly, the ``async_mode``\noption can be given in the constructor::\n\n    eio = engineio.Server(async_mode='gevent')\n\nA server configured for gevent is deployed as a regular WSGI application\nusing the provided ``engineio.WSGIApp``::\n\n    from gevent import pywsgi\n    app = engineio.WSGIApp(eio)\n    pywsgi.WSGIServer(('', 8000), app).serve_forever()\n\nGevent with Gunicorn\n~~~~~~~~~~~~~~~~~~~~\n\nAn alternative to running the gevent WSGI server as above is to use\n`gunicorn <gunicorn.org>`_, a fully featured pure Python web server. The\ncommand to launch the application under gunicorn is shown below::\n\n    $ gunicorn -k gevent -w 1 module:app\n\nSame as with eventlet, due to limitations in its load balancing algorithm,\ngunicorn can only be used with one worker process, so the ``-w 1`` option is\nrequired. Note that a single gevent worker can handle a large number of\nconcurrent clients.\n\nNote: Gevent provides a ``monkey_patch()`` function that replaces all the\nblocking functions in the standard library with equivalent asynchronous\nversions. While python-engineio does not require monkey patching, other\nlibraries such as database drivers are likely to require it.\n\nuWSGI\n~~~~~\n\nWhen using the uWSGI server in combination with gevent, the Engine.IO server\ncan take advantage of uWSGI's native WebSocket support.\n\nInstances of class ``engineio.Server`` will automatically use this option for\nasynchronous operations if both gevent and uWSGI are installed and eventlet is\nnot installed. To request this asynchoronous mode explicitly, the\n``async_mode`` option can be given in the constructor::\n\n    # gevent with uWSGI\n    eio = engineio.Server(async_mode='gevent_uwsgi')\n\nA complete explanation of the configuration and usage of the uWSGI server is\nbeyond the scope of this documentation. The uWSGI server is a fairly complex\npackage that provides a large and comprehensive set of options. It must be\ncompiled with WebSocket and SSL support for the WebSocket transport to be\navailable. As way of an introduction, the following command starts a uWSGI\nserver for the ``latency.py`` example on port 5000::\n\n    $ uwsgi --http :5000 --gevent 1000 --http-websockets --master --wsgi-file latency.py --callable app\n\nStandard Threads\n~~~~~~~~~~~~~~~~\n\nWhile not comparable to eventlet and gevent in terms of performance,\nthe Engine.IO server can also be configured to work with multi-threaded web\nservers that use standard Python threads. This is an ideal setup to use with\ndevelopment servers such as `Werkzeug <http://werkzeug.pocoo.org>`_.\n\nInstances of class ``engineio.Server`` will automatically use the threading\nmode if neither eventlet nor gevent are not installed. To request the\nthreading mode explicitly, the ``async_mode`` option can be given in the\nconstructor::\n\n    eio = engineio.Server(async_mode='threading')\n\nA server configured for threading is deployed as a regular web application,\nusing any WSGI complaint multi-threaded server. The example below deploys an\nEngine.IO application combined with a Flask web application, using Flask's\ndevelopment web server based on Werkzeug::\n\n    eio = engineio.Server(async_mode='threading')\n    app = Flask(__name__)\n    app.wsgi_app = engineio.WSGIApp(eio, app.wsgi_app)\n\n    # ... Engine.IO and Flask handler functions ...\n\n    if __name__ == '__main__':\n        app.run()\n\nThe example that follows shows how to start an Engine.IO application using\nGunicorn's threaded worker class::\n\n    $ gunicorn -w 1 --threads 100 module:app\n\nWith the above configuration the server will be able to handle up to 100\nconcurrent clients.\n\nWhen using standard threads, WebSocket is supported through the\n`simple-websocket <https://github.com/miguelgrinberg/simple-websocket>`_\npackage, which must be installed separately. This package provides a\nmulti-threaded WebSocket server that is compatible with Werkzeug and Gunicorn's\nthreaded worker. Other multi-threaded web servers are not supported and will\nnot enable the WebSocket transport.\n\nScalability Notes\n~~~~~~~~~~~~~~~~~\n\nEngine.IO is a stateful protocol, which makes horizontal scaling more\ndifficult. To deploy a cluster of Engine.IO processes hosted on one or\nmultiple servers the following conditions must be met:\n\n- Each Engine.IO server process must be able to handle multiple requests\n  concurrently. This is required because long-polling clients send two\n  requests in parallel. Worker processes that can only handle one request at a\n  time are not supported.\n- The load balancer must be configured to always forward requests from a client\n  to the same process. Load balancers call this *sticky sessions*, or\n  *session affinity*.\n\nCross-Origin Controls\n---------------------\n\nFor security reasons, this server enforces a same-origin policy by default. In\npractical terms, this means the following:\n\n- If an incoming HTTP or WebSocket request includes the ``Origin`` header,\n  this header must match the scheme and host of the connection URL. In case\n  of a mismatch, a 400 status code response is returned and the connection is\n  rejected.\n- No restrictions are imposed on incoming requests that do not include the\n  ``Origin`` header.\n\nIf necessary, the ``cors_allowed_origins`` option can be used to allow other\norigins. This argument can be set to a string to set a single allowed origin, or\nto a list to allow multiple origins. A special value of ``'*'`` can be used to\ninstruct the server to allow all origins, but this should be done with care, as\nthis could make the server vulnerable to Cross-Site Request Forgery (CSRF)\nattacks.\n"
  },
  {
    "path": "examples/README.rst",
    "content": "Engine.IO Examples\n==================\n\nThis directory contains several example Engine.IO applications. Look in the\n`server` directory for Engine.IO servers, and in the `client` directory for\nEngine.IO clients.\n"
  },
  {
    "path": "examples/client/README.rst",
    "content": "Engine.IO Client Examples\n=========================\n\nThis directory contains several example Engine.IO client applications,\norganized by directory:\n\nthreads\n-------\n\nExamples that use standard Python thread concurrency.\n\nasyncio\n-------\n\nExamples that use Python's `asyncio` package for concurrency.\n\njavascript\n----------\n\nExamples that use the JavaScript version of Engine.IO for compatibility testing.\n"
  },
  {
    "path": "examples/client/asyncio/README.rst",
    "content": "Engine.IO Asyncio Examples\n==========================\n\nThis directory contains example Engine.IO clients that work with the\n`asyncio` package of the Python standard library.\n\nsimple_client.py\n----------------\n\nA basic application in which the client sends messages to the server and the\nserver responds.\n\nlatency_client.py\n-----------------\n\nIn this application the client sends *ping* messages to the server, which are\nresponded by the server with a *pong*. The client measures the time it takes\nfor each of these exchanges.\n\nThis is an ideal application to measure the performance of the different\nasynchronous modes supported by the Engine.IO server.\n\nRunning the Examples\n--------------------\n\nThese examples work with the server examples of the same name. First run one\nof the `simple.py` or `latency.py` versions from the `examples/server`\ndirectory. On another terminal, then start the corresponding client with one\nof the following commands::\n\n    $ python simple_client.py\n\nor::\n\n    $ python latency_client.py\n"
  },
  {
    "path": "examples/client/asyncio/latency_client.py",
    "content": "import asyncio\nimport time\nimport engineio\n\neio = engineio.AsyncClient()\nstart_timer = None\n\n\nasync def send_ping():\n    global start_timer\n    start_timer = time.time()\n    await eio.send('ping')\n\n\n@eio.on('connect')\nasync def on_connect():\n    print('connected to server')\n    await send_ping()\n\n\n@eio.on('message')\nasync def on_message(data):\n    latency = time.time() - start_timer\n    print(f'latency is {latency * 1000:.2f} ms')\n    await eio.sleep(1)\n    await send_ping()\n\n\nasync def start_client():\n    await eio.connect('http://localhost:5000')\n    await eio.wait()\n\n\nif __name__ == '__main__':\n    asyncio.run(start_client())\n"
  },
  {
    "path": "examples/client/asyncio/simple_client.py",
    "content": "import asyncio\nimport signal\nimport engineio\n\neio = engineio.AsyncClient()\nexit_event = asyncio.Event()\noriginal_signal_handler = None\n\n\nasync def send_hello():\n    message = 'Hello from client side!'\n    while not exit_event.is_set():\n        print('sending: ' + 'Hello from client side!')\n        await eio.send(message)\n        try:\n            await asyncio.wait_for(exit_event.wait(), timeout=5)\n        except asyncio.TimeoutError:\n            pass\n    await eio.disconnect()\n\n\n@eio.on('connect')\ndef on_connect():\n    print('connected to server')\n    eio.start_background_task(send_hello)\n\n\n@eio.on('message')\ndef on_message(data):\n    print('received: ' + str(data))\n\n\n@eio.on('disconnect')\ndef on_disconnect(reason):\n    print('disconnected from server with reason: ', reason)\n\n\ndef signal_handler(sig, frame):\n    exit_event.set()\n    print('exiting')\n    if callable(original_signal_handler):\n        original_signal_handler(sig, frame)\n\n\nasync def start_client():\n    await eio.connect('http://localhost:5000')\n    await eio.wait()\n\n\nif __name__ == '__main__':\n    original_signal_handler = signal.signal(signal.SIGINT, signal_handler)\n    asyncio.run(start_client())\n"
  },
  {
    "path": "examples/client/javascript/README.md",
    "content": "# eio-latency\n\nThis is a JavaScript example intended to be used when testing interoperability with Python.\n\n## Running\n\nFirst, execute:\n\n```\n$ npm install\n```\n\nThen execute the client:\n\n```\n$ node latency_client\n```\n\nA connection will be made to `localhost:5000` (if PORT is set in your environment, then it will use that instead).\n"
  },
  {
    "path": "examples/client/javascript/latency_client.js",
    "content": "const io = require('engine.io-client')\nconst port = process.env.PORT || 5000;\n\nconst socket = io('http://localhost:' + port);\nlet last;\nfunction send () {\n  last = new Date();\n  socket.send('ping');\n}\n\nsocket.on('open', () => {\n  send();\n});\n\nsocket.on('close', () => {\n});\n\nsocket.on('message', () => {\n  const latency = new Date() - last;\n  console.log('latency is ' + latency + ' ms');\n  setTimeout(send, 1000);\n});\n"
  },
  {
    "path": "examples/client/javascript/package.json",
    "content": "{\n  \"name\": \"eio-latency\",\n  \"version\": \"0.1.0\",\n  \"dependencies\": {\n    \"enchilada\": \"0.13.0\",\n    \"engine.io\": \"^6.6.2\",\n    \"engine.io-client\": \"^6.6.0\",\n    \"express\": \"^4.22.1\",\n    \"smoothie\": \"1.19.0\"\n  }\n}\n"
  },
  {
    "path": "examples/client/threads/README.rst",
    "content": "Engine.IO Threading Examples\n============================\n\nThis directory contains example Engine.IO clients that work with the\n`threading` package of the Python standard library.\n\nsimple_client.py\n----------------\n\nA basic application in which the client sends messages to the server and the\nserver responds.\n\nlatency_client.py\n-----------------\n\nIn this application the client sends *ping* messages to the server, which are\nresponded by the server with a *pong*. The client measures the time it takes\nfor each of these exchanges.\n\nThis is an ideal application to measure the performance of the different\nasynchronous modes supported by the Engine.IO server.\n\nRunning the Examples\n--------------------\n\nThese examples work with the server examples of the same name. First run one\nof the `simple.py` or `latency.py` versions from the `examples/server`\ndirectory. On another terminal, then start the corresponding client with one\nof the following commands::\n\n    $ python simple_client.py\n\nor::\n\n    $ python latency_client.py\n"
  },
  {
    "path": "examples/client/threads/latency_client.py",
    "content": "import time\nimport engineio\n\neio = engineio.Client()\nstart_timer = None\n\n\ndef send_ping():\n    global start_timer\n    start_timer = time.time()\n    eio.send('ping')\n\n\n@eio.on('connect')\ndef on_connect():\n    print('connected to server')\n    send_ping()\n\n\n@eio.on('message')\ndef on_message(data):\n    latency = time.time() - start_timer\n    print(f'latency is {latency * 1000:.2f} ms')\n    eio.sleep(1)\n    send_ping()\n\n\nif __name__ == '__main__':\n    eio.connect('http://localhost:5000')\n    eio.wait()\n"
  },
  {
    "path": "examples/client/threads/simple_client.py",
    "content": "import signal\nimport threading\nimport engineio\n\neio = engineio.Client()\nexit_event = threading.Event()\noriginal_signal_handler = None\n\n\ndef send_hello():\n    message = 'Hello from client side!'\n    while not exit_event.is_set():\n        print('sending: ' + 'Hello from client side!')\n        eio.send(message)\n        exit_event.wait(5)\n    eio.disconnect()\n\n\n@eio.on('connect')\ndef on_connect():\n    print('connected to server')\n    eio.start_background_task(send_hello)\n\n\n@eio.on('message')\ndef on_message(data):\n    print('received: ' + str(data))\n\n\n@eio.on('disconnect')\ndef on_disconnect(reason):\n    print('disconnected from server with reason: ', reason)\n\n\ndef signal_handler(sig, frame):\n    exit_event.set()\n    print('exiting')\n    if callable(original_signal_handler):\n        original_signal_handler(sig, frame)\n\n\nif __name__ == '__main__':\n    original_signal_handler = signal.signal(signal.SIGINT, signal_handler)\n    eio.connect('http://localhost:5000')\n    eio.wait()\n"
  },
  {
    "path": "examples/server/README.rst",
    "content": "Engine.IO Server Examples\n=========================\n\nThis directory contains several example Engine.IO server applications,\norganized by directory:\n\nwsgi\n----\n\nExamples that are compatible with the WSGI specification.\n\nasgi\n----\n\nExamples that are compatible with the ASGI specification.\n\naiohttp\n-------\n\nExamples that are compatible with the aiohttp framework for asyncio.\n\nsanic\n-----\n\nExamples that are compatible with the sanic framework for asyncio.\n\n\ntornado\n-------\n\nExamples that are compatible with the Tornado framework.\n\njavascript\n----------\n\nExamples that use the JavaScript version of Engine.IO for compatiblity testing.\n"
  },
  {
    "path": "examples/server/aiohttp/README.rst",
    "content": "Engine.IO Examples\n==================\n\nThis directory contains example Engine.IO applications that are compatible\nwith asyncio and the aiohttp framework. These applications require Python 3.5\nor later.\n\nsimple.py\n---------\n\nA basic application in which the client sends messages to the server and the\nserver responds.\n\nlatency.py\n----------\n\nA port of the latency application included in the official Engine.IO\nJavascript server. In this application the client sends *ping* messages to\nthe server, which are responded by the server with a *pong*. The client\nmeasures the time it takes for each of these exchanges and plots these in real\ntime to the page.\n\nThis is an ideal application to measure the performance of the different\nasynchronous modes supported by the Engine.IO server.\n\nRunning the Examples\n--------------------\n\nTo run these examples, create a virtual environment, install the requirements\nand then run::\n\n    $ python simple.py\n\nor::\n\n    $ python latency.py\n\nYou can then access the application from your web browser at\n``http://localhost:8080``."
  },
  {
    "path": "examples/server/aiohttp/latency.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>EIO Latency</title>\n    <link rel=\"stylesheet\" href=\"/static/style.css\" />\n  </head>\n  <body>\n    <h1>EIO Latency <span id=\"latency\"></span></h1>\n    <h2 id=\"transport\">(connecting)</h2>\n    <canvas id=\"chart\" height=\"200\"></canvas>\n\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/smoothie/1.27.0/smoothie.js\"></script>\n    <script src=\"/static/engine.io.js\"></script>\n    <script>\n      // socket\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      var char = $('chart').get(0);\n      socket.on('open', function() {\n          if (chart.getContext) {\n              render();\n              window.onresize = render;\n          }\n          send();\n      });\n      socket.on('message', function(data) {\n          var latency = new Date - last;\n          $('#latency').text(latency + 'ms');\n          if (time)\n              time.append(+new Date, latency);\n          setTimeout(send, 100);\n      });\n      socket.on('close', function() {\n          if (smoothie)\n              smoothie.stop();\n          $('#transport').text('(disconnected)');\n      });\n\n      var last;\n      function send() {\n          last = new Date;\n          socket.send('ping');\n          $('#transport').text(socket.transport.name);\n      }\n\n      // chart\n      var smoothie;\n      var time;\n      function render() {\n          if (smoothie)\n              smoothie.stop();\n          chart.width = document.body.clientWidth;\n          smoothie = new SmoothieChart();\n          smoothie.streamTo(chart, 1000);\n          time = new TimeSeries();\n          smoothie.addTimeSeries(time, {\n              strokeStyle: 'rgb(255, 0, 0)',\n              fillStyle: 'rgba(255, 0, 0, 0.4)',\n              lineWidth: 2\n          });\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/server/aiohttp/latency.py",
    "content": "from aiohttp import web\n\nimport engineio\n\neio = engineio.AsyncServer(async_mode='aiohttp')\napp = web.Application()\neio.attach(app)\n\n\nasync def index(request):\n    with open('latency.html') as f:\n        return web.Response(text=f.read(), content_type='text/html')\n\n\n@eio.on('message')\nasync def message(sid, data):\n    await eio.send(sid, 'pong')\n\n\napp.router.add_static('/static', 'static')\napp.router.add_get('/', index)\n\n\nif __name__ == '__main__':\n    web.run_app(app)\n"
  },
  {
    "path": "examples/server/aiohttp/requirements.txt",
    "content": "aiohttp==3.13.4\nasync-timeout==1.1.0\nchardet==2.3.0\nmultidict==2.1.4\npython-engineio\nsix==1.10.0\nyarl==0.8.1\n"
  },
  {
    "path": "examples/server/aiohttp/simple.html",
    "content": "<html>\n<head>\n<script src=\"/static/engine.io.js\"></script>\n<script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n<script>\n  $(document).ready(function() {\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      socket.on('open', function() {\n          $('#log').append(\"Connected to server.<br>\");\n      });\n      socket.on('message', function(data) {\n          $('#log').append(\"Server says: \" + data + \"<br>\");\n      });\n      socket.on('close', function() {\n          $('#log').append(\"Server closed the connection.<br>\");\n      });\n      window.setInterval(function() {\n          $('#log').append(\"Sending message to server...<br>\");\n          socket.send('hello from client side!');\n      }, 5000);\n  });\n</script>\n</head>\n<body>\n<h1>python-engineio example application</h1>\n<p id=\"log\"></p>\n</body>\n</html>\n"
  },
  {
    "path": "examples/server/aiohttp/simple.py",
    "content": "from aiohttp import web\n\nimport engineio\n\neio = engineio.AsyncServer(async_mode='aiohttp')\napp = web.Application()\neio.attach(app)\n\n\nasync def index(request):\n    with open('simple.html') as f:\n        return web.Response(text=f.read(), content_type='text/html')\n\n\n@eio.on('connect')\ndef connect(sid, environ):\n    print(\"connect \", sid)\n\n\n@eio.on('message')\nasync def message(sid, data):\n    print('message from', sid, data)\n    await eio.send(sid, 'Thank you for your message!')\n\n\n@eio.on('disconnect')\ndef disconnect(sid, reason):\n    print('disconnect ', sid, reason)\n\n\napp.router.add_static('/static', 'static')\napp.router.add_get('/', index)\n\n\nif __name__ == '__main__':\n    web.run_app(app)\n"
  },
  {
    "path": "examples/server/aiohttp/static/engine.io.js",
    "content": "/*!\n * Engine.IO v4.0.4\n * (c) 2014-2020 Guillermo Rauch\n * Released under the MIT License.\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"eio\"] = factory();\n\telse\n\t\troot[\"eio\"] = factory();\n})((() => {\n      if (typeof self !== 'undefined') {\n          return self;\n      } else if (typeof window !== 'undefined') {\n          return window;\n      } else if (typeof global !== 'undefined') {\n          return global;\n      } else {\n          return Function('return this')();\n      }\n    })(), function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./lib/index.js\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./lib/globalThis.browser.js\":\n/*!***********************************!*\\\n  !*** ./lib/globalThis.browser.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports = function () {\\n  if (typeof self !== \\\"undefined\\\") {\\n    return self;\\n  } else if (typeof window !== \\\"undefined\\\") {\\n    return window;\\n  } else {\\n    return Function(\\\"return this\\\")();\\n  }\\n}();\\n\\n//# sourceURL=webpack://eio/./lib/globalThis.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/index.js\":\n/*!**********************!*\\\n  !*** ./lib/index.js ***!\n  \\**********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var Socket = __webpack_require__(/*! ./socket */ \\\"./lib/socket.js\\\");\\n\\nmodule.exports = function (uri, opts) {\\n  return new Socket(uri, opts);\\n};\\n/**\\n * Expose deps for legacy compatibility\\n * and standalone browser access.\\n */\\n\\n\\nmodule.exports.Socket = Socket;\\nmodule.exports.protocol = Socket.protocol; // this is an int\\n\\nmodule.exports.Transport = __webpack_require__(/*! ./transport */ \\\"./lib/transport.js\\\");\\nmodule.exports.transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\nmodule.exports.parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\n//# sourceURL=webpack://eio/./lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/socket.js\":\n/*!***********************!*\\\n  !*** ./lib/socket.js ***!\n  \\***********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:socket\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseuri = __webpack_require__(/*! parseuri */ \\\"./node_modules/parseuri/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar Socket =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Socket, _Emitter);\\n\\n  /**\\n   * Socket constructor.\\n   *\\n   * @param {String|Object} uri or options\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Socket(uri) {\\n    var _this;\\n\\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\\n\\n    _classCallCheck(this, Socket);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Socket).call(this));\\n\\n    if (uri && \\\"object\\\" === _typeof(uri)) {\\n      opts = uri;\\n      uri = null;\\n    }\\n\\n    if (uri) {\\n      uri = parseuri(uri);\\n      opts.hostname = uri.host;\\n      opts.secure = uri.protocol === \\\"https\\\" || uri.protocol === \\\"wss\\\";\\n      opts.port = uri.port;\\n      if (uri.query) opts.query = uri.query;\\n    } else if (opts.host) {\\n      opts.hostname = parseuri(opts.host).host;\\n    }\\n\\n    _this.secure = null != opts.secure ? opts.secure : typeof location !== \\\"undefined\\\" && \\\"https:\\\" === location.protocol;\\n\\n    if (opts.hostname && !opts.port) {\\n      // if no port is specified manually, use the protocol default\\n      opts.port = _this.secure ? \\\"443\\\" : \\\"80\\\";\\n    }\\n\\n    _this.hostname = opts.hostname || (typeof location !== \\\"undefined\\\" ? location.hostname : \\\"localhost\\\");\\n    _this.port = opts.port || (typeof location !== \\\"undefined\\\" && location.port ? location.port : _this.secure ? 443 : 80);\\n    _this.transports = opts.transports || [\\\"polling\\\", \\\"websocket\\\"];\\n    _this.readyState = \\\"\\\";\\n    _this.writeBuffer = [];\\n    _this.prevBufferLen = 0;\\n    _this.opts = _extends({\\n      path: \\\"/engine.io\\\",\\n      agent: false,\\n      withCredentials: false,\\n      upgrade: true,\\n      jsonp: true,\\n      timestampParam: \\\"t\\\",\\n      policyPort: 843,\\n      rememberUpgrade: false,\\n      rejectUnauthorized: true,\\n      perMessageDeflate: {\\n        threshold: 1024\\n      },\\n      transportOptions: {}\\n    }, opts);\\n    _this.opts.path = _this.opts.path.replace(/\\\\/$/, \\\"\\\") + \\\"/\\\";\\n\\n    if (typeof _this.opts.query === \\\"string\\\") {\\n      _this.opts.query = parseqs.decode(_this.opts.query);\\n    } // set on handshake\\n\\n\\n    _this.id = null;\\n    _this.upgrades = null;\\n    _this.pingInterval = null;\\n    _this.pingTimeout = null; // set on heartbeat\\n\\n    _this.pingTimeoutTimer = null;\\n\\n    _this.open();\\n\\n    return _this;\\n  }\\n  /**\\n   * Creates transport of the given type.\\n   *\\n   * @param {String} transport name\\n   * @return {Transport}\\n   * @api private\\n   */\\n\\n\\n  _createClass(Socket, [{\\n    key: \\\"createTransport\\\",\\n    value: function createTransport(name) {\\n      debug('creating transport \\\"%s\\\"', name);\\n      var query = clone(this.opts.query); // append engine.io protocol identifier\\n\\n      query.EIO = parser.protocol; // transport name\\n\\n      query.transport = name; // session id if we already have one\\n\\n      if (this.id) query.sid = this.id;\\n\\n      var opts = _extends({}, this.opts.transportOptions[name], this.opts, {\\n        query: query,\\n        socket: this,\\n        hostname: this.hostname,\\n        secure: this.secure,\\n        port: this.port\\n      });\\n\\n      debug(\\\"options: %j\\\", opts);\\n      return new transports[name](opts);\\n    }\\n    /**\\n     * Initializes transport to use and starts probe.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      var transport;\\n\\n      if (this.opts.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf(\\\"websocket\\\") !== -1) {\\n        transport = \\\"websocket\\\";\\n      } else if (0 === this.transports.length) {\\n        // Emit error on next tick so it can be listened to\\n        var self = this;\\n        setTimeout(function () {\\n          self.emit(\\\"error\\\", \\\"No transports available\\\");\\n        }, 0);\\n        return;\\n      } else {\\n        transport = this.transports[0];\\n      }\\n\\n      this.readyState = \\\"opening\\\"; // Retry with the next transport if the transport is disabled (jsonp: false)\\n\\n      try {\\n        transport = this.createTransport(transport);\\n      } catch (e) {\\n        debug(\\\"error while creating transport: %s\\\", e);\\n        this.transports.shift();\\n        this.open();\\n        return;\\n      }\\n\\n      transport.open();\\n      this.setTransport(transport);\\n    }\\n    /**\\n     * Sets the current transport. Disables the existing one (if any).\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"setTransport\\\",\\n    value: function setTransport(transport) {\\n      debug(\\\"setting transport %s\\\", transport.name);\\n      var self = this;\\n\\n      if (this.transport) {\\n        debug(\\\"clearing existing transport %s\\\", this.transport.name);\\n        this.transport.removeAllListeners();\\n      } // set up transport\\n\\n\\n      this.transport = transport; // set up transport listeners\\n\\n      transport.on(\\\"drain\\\", function () {\\n        self.onDrain();\\n      }).on(\\\"packet\\\", function (packet) {\\n        self.onPacket(packet);\\n      }).on(\\\"error\\\", function (e) {\\n        self.onError(e);\\n      }).on(\\\"close\\\", function () {\\n        self.onClose(\\\"transport close\\\");\\n      });\\n    }\\n    /**\\n     * Probes a transport.\\n     *\\n     * @param {String} transport name\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"probe\\\",\\n    value: function probe(name) {\\n      debug('probing transport \\\"%s\\\"', name);\\n      var transport = this.createTransport(name, {\\n        probe: 1\\n      });\\n      var failed = false;\\n      var self = this;\\n      Socket.priorWebsocketSuccess = false;\\n\\n      function onTransportOpen() {\\n        if (self.onlyBinaryUpgrades) {\\n          var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;\\n          failed = failed || upgradeLosesBinary;\\n        }\\n\\n        if (failed) return;\\n        debug('probe transport \\\"%s\\\" opened', name);\\n        transport.send([{\\n          type: \\\"ping\\\",\\n          data: \\\"probe\\\"\\n        }]);\\n        transport.once(\\\"packet\\\", function (msg) {\\n          if (failed) return;\\n\\n          if (\\\"pong\\\" === msg.type && \\\"probe\\\" === msg.data) {\\n            debug('probe transport \\\"%s\\\" pong', name);\\n            self.upgrading = true;\\n            self.emit(\\\"upgrading\\\", transport);\\n            if (!transport) return;\\n            Socket.priorWebsocketSuccess = \\\"websocket\\\" === transport.name;\\n            debug('pausing current transport \\\"%s\\\"', self.transport.name);\\n            self.transport.pause(function () {\\n              if (failed) return;\\n              if (\\\"closed\\\" === self.readyState) return;\\n              debug(\\\"changing transport and sending upgrade packet\\\");\\n              cleanup();\\n              self.setTransport(transport);\\n              transport.send([{\\n                type: \\\"upgrade\\\"\\n              }]);\\n              self.emit(\\\"upgrade\\\", transport);\\n              transport = null;\\n              self.upgrading = false;\\n              self.flush();\\n            });\\n          } else {\\n            debug('probe transport \\\"%s\\\" failed', name);\\n            var err = new Error(\\\"probe error\\\");\\n            err.transport = transport.name;\\n            self.emit(\\\"upgradeError\\\", err);\\n          }\\n        });\\n      }\\n\\n      function freezeTransport() {\\n        if (failed) return; // Any callback called by transport should be ignored since now\\n\\n        failed = true;\\n        cleanup();\\n        transport.close();\\n        transport = null;\\n      } // Handle any error that happens while probing\\n\\n\\n      function onerror(err) {\\n        var error = new Error(\\\"probe error: \\\" + err);\\n        error.transport = transport.name;\\n        freezeTransport();\\n        debug('probe transport \\\"%s\\\" failed because of error: %s', name, err);\\n        self.emit(\\\"upgradeError\\\", error);\\n      }\\n\\n      function onTransportClose() {\\n        onerror(\\\"transport closed\\\");\\n      } // When the socket is closed while we're probing\\n\\n\\n      function onclose() {\\n        onerror(\\\"socket closed\\\");\\n      } // When the socket is upgraded while we're probing\\n\\n\\n      function onupgrade(to) {\\n        if (transport && to.name !== transport.name) {\\n          debug('\\\"%s\\\" works - aborting \\\"%s\\\"', to.name, transport.name);\\n          freezeTransport();\\n        }\\n      } // Remove all listeners on the transport and on self\\n\\n\\n      function cleanup() {\\n        transport.removeListener(\\\"open\\\", onTransportOpen);\\n        transport.removeListener(\\\"error\\\", onerror);\\n        transport.removeListener(\\\"close\\\", onTransportClose);\\n        self.removeListener(\\\"close\\\", onclose);\\n        self.removeListener(\\\"upgrading\\\", onupgrade);\\n      }\\n\\n      transport.once(\\\"open\\\", onTransportOpen);\\n      transport.once(\\\"error\\\", onerror);\\n      transport.once(\\\"close\\\", onTransportClose);\\n      this.once(\\\"close\\\", onclose);\\n      this.once(\\\"upgrading\\\", onupgrade);\\n      transport.open();\\n    }\\n    /**\\n     * Called when connection is deemed open.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      debug(\\\"socket open\\\");\\n      this.readyState = \\\"open\\\";\\n      Socket.priorWebsocketSuccess = \\\"websocket\\\" === this.transport.name;\\n      this.emit(\\\"open\\\");\\n      this.flush(); // we check for `readyState` in case an `open`\\n      // listener already closed the socket\\n\\n      if (\\\"open\\\" === this.readyState && this.opts.upgrade && this.transport.pause) {\\n        debug(\\\"starting upgrade probes\\\");\\n        var i = 0;\\n        var l = this.upgrades.length;\\n\\n        for (; i < l; i++) {\\n          this.probe(this.upgrades[i]);\\n        }\\n      }\\n    }\\n    /**\\n     * Handles a packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket receive: type \\\"%s\\\", data \\\"%s\\\"', packet.type, packet.data);\\n        this.emit(\\\"packet\\\", packet); // Socket is live - any packet counts\\n\\n        this.emit(\\\"heartbeat\\\");\\n\\n        switch (packet.type) {\\n          case \\\"open\\\":\\n            this.onHandshake(JSON.parse(packet.data));\\n            break;\\n\\n          case \\\"ping\\\":\\n            this.resetPingTimeout();\\n            this.sendPacket(\\\"pong\\\");\\n            this.emit(\\\"pong\\\");\\n            break;\\n\\n          case \\\"error\\\":\\n            var err = new Error(\\\"server error\\\");\\n            err.code = packet.data;\\n            this.onError(err);\\n            break;\\n\\n          case \\\"message\\\":\\n            this.emit(\\\"data\\\", packet.data);\\n            this.emit(\\\"message\\\", packet.data);\\n            break;\\n        }\\n      } else {\\n        debug('packet received with socket readyState \\\"%s\\\"', this.readyState);\\n      }\\n    }\\n    /**\\n     * Called upon handshake completion.\\n     *\\n     * @param {Object} handshake obj\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onHandshake\\\",\\n    value: function onHandshake(data) {\\n      this.emit(\\\"handshake\\\", data);\\n      this.id = data.sid;\\n      this.transport.query.sid = data.sid;\\n      this.upgrades = this.filterUpgrades(data.upgrades);\\n      this.pingInterval = data.pingInterval;\\n      this.pingTimeout = data.pingTimeout;\\n      this.onOpen(); // In case open handler closes socket\\n\\n      if (\\\"closed\\\" === this.readyState) return;\\n      this.resetPingTimeout();\\n    }\\n    /**\\n     * Sets and resets ping timeout timer based on server pings.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"resetPingTimeout\\\",\\n    value: function resetPingTimeout() {\\n      var _this2 = this;\\n\\n      clearTimeout(this.pingTimeoutTimer);\\n      this.pingTimeoutTimer = setTimeout(function () {\\n        _this2.onClose(\\\"ping timeout\\\");\\n      }, this.pingInterval + this.pingTimeout);\\n    }\\n    /**\\n     * Called on `drain` event\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onDrain\\\",\\n    value: function onDrain() {\\n      this.writeBuffer.splice(0, this.prevBufferLen); // setting prevBufferLen = 0 is very important\\n      // for example, when upgrading, upgrade packet is sent over,\\n      // and a nonzero prevBufferLen could cause problems on `drain`\\n\\n      this.prevBufferLen = 0;\\n\\n      if (0 === this.writeBuffer.length) {\\n        this.emit(\\\"drain\\\");\\n      } else {\\n        this.flush();\\n      }\\n    }\\n    /**\\n     * Flush write buffers.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"flush\\\",\\n    value: function flush() {\\n      if (\\\"closed\\\" !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) {\\n        debug(\\\"flushing %d packets in socket\\\", this.writeBuffer.length);\\n        this.transport.send(this.writeBuffer); // keep track of current length of writeBuffer\\n        // splice writeBuffer and callbackBuffer on `drain`\\n\\n        this.prevBufferLen = this.writeBuffer.length;\\n        this.emit(\\\"flush\\\");\\n      }\\n    }\\n    /**\\n     * Sends a message.\\n     *\\n     * @param {String} message.\\n     * @param {Function} callback function.\\n     * @param {Object} options.\\n     * @return {Socket} for chaining.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n    /**\\n     * Sends a packet.\\n     *\\n     * @param {String} packet type.\\n     * @param {String} data.\\n     * @param {Object} options.\\n     * @param {Function} callback function.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"sendPacket\\\",\\n    value: function sendPacket(type, data, options, fn) {\\n      if (\\\"function\\\" === typeof data) {\\n        fn = data;\\n        data = undefined;\\n      }\\n\\n      if (\\\"function\\\" === typeof options) {\\n        fn = options;\\n        options = null;\\n      }\\n\\n      if (\\\"closing\\\" === this.readyState || \\\"closed\\\" === this.readyState) {\\n        return;\\n      }\\n\\n      options = options || {};\\n      options.compress = false !== options.compress;\\n      var packet = {\\n        type: type,\\n        data: data,\\n        options: options\\n      };\\n      this.emit(\\\"packetCreate\\\", packet);\\n      this.writeBuffer.push(packet);\\n      if (fn) this.once(\\\"flush\\\", fn);\\n      this.flush();\\n    }\\n    /**\\n     * Closes the connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      var self = this;\\n\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.readyState = \\\"closing\\\";\\n\\n        if (this.writeBuffer.length) {\\n          this.once(\\\"drain\\\", function () {\\n            if (this.upgrading) {\\n              waitForUpgrade();\\n            } else {\\n              close();\\n            }\\n          });\\n        } else if (this.upgrading) {\\n          waitForUpgrade();\\n        } else {\\n          close();\\n        }\\n      }\\n\\n      function close() {\\n        self.onClose(\\\"forced close\\\");\\n        debug(\\\"socket closing - telling transport to close\\\");\\n        self.transport.close();\\n      }\\n\\n      function cleanupAndClose() {\\n        self.removeListener(\\\"upgrade\\\", cleanupAndClose);\\n        self.removeListener(\\\"upgradeError\\\", cleanupAndClose);\\n        close();\\n      }\\n\\n      function waitForUpgrade() {\\n        // wait for upgrade to finish since we can't send packets while pausing a transport\\n        self.once(\\\"upgrade\\\", cleanupAndClose);\\n        self.once(\\\"upgradeError\\\", cleanupAndClose);\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Called upon transport error\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      debug(\\\"socket error %j\\\", err);\\n      Socket.priorWebsocketSuccess = false;\\n      this.emit(\\\"error\\\", err);\\n      this.onClose(\\\"transport error\\\", err);\\n    }\\n    /**\\n     * Called upon transport close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose(reason, desc) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket close with reason: \\\"%s\\\"', reason);\\n        var self = this; // clear timers\\n\\n        clearTimeout(this.pingIntervalTimer);\\n        clearTimeout(this.pingTimeoutTimer); // stop event from firing again for transport\\n\\n        this.transport.removeAllListeners(\\\"close\\\"); // ensure transport won't stay open\\n\\n        this.transport.close(); // ignore further transport communication\\n\\n        this.transport.removeAllListeners(); // set ready state\\n\\n        this.readyState = \\\"closed\\\"; // clear session id\\n\\n        this.id = null; // emit close event\\n\\n        this.emit(\\\"close\\\", reason, desc); // clean buffers after, so users can still\\n        // grab the buffers on `close` event\\n\\n        self.writeBuffer = [];\\n        self.prevBufferLen = 0;\\n      }\\n    }\\n    /**\\n     * Filters upgrades, returning only those matching client transports.\\n     *\\n     * @param {Array} server upgrades\\n     * @api private\\n     *\\n     */\\n\\n  }, {\\n    key: \\\"filterUpgrades\\\",\\n    value: function filterUpgrades(upgrades) {\\n      var filteredUpgrades = [];\\n      var i = 0;\\n      var j = upgrades.length;\\n\\n      for (; i < j; i++) {\\n        if (~this.transports.indexOf(upgrades[i])) filteredUpgrades.push(upgrades[i]);\\n      }\\n\\n      return filteredUpgrades;\\n    }\\n  }]);\\n\\n  return Socket;\\n}(Emitter);\\n\\nSocket.priorWebsocketSuccess = false;\\n/**\\n * Protocol version.\\n *\\n * @api public\\n */\\n\\nSocket.protocol = parser.protocol; // this is an int\\n\\nfunction clone(obj) {\\n  var o = {};\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      o[i] = obj[i];\\n    }\\n  }\\n\\n  return o;\\n}\\n\\nmodule.exports = Socket;\\n\\n//# sourceURL=webpack://eio/./lib/socket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transport.js\":\n/*!**************************!*\\\n  !*** ./lib/transport.js ***!\n  \\**************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar Transport =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Transport, _Emitter);\\n\\n  /**\\n   * Transport abstract constructor.\\n   *\\n   * @param {Object} options.\\n   * @api private\\n   */\\n  function Transport(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, Transport);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Transport).call(this));\\n    _this.opts = opts;\\n    _this.query = opts.query;\\n    _this.readyState = \\\"\\\";\\n    _this.socket = opts.socket;\\n    return _this;\\n  }\\n  /**\\n   * Emits an error.\\n   *\\n   * @param {String} str\\n   * @return {Transport} for chaining\\n   * @api public\\n   */\\n\\n\\n  _createClass(Transport, [{\\n    key: \\\"onError\\\",\\n    value: function onError(msg, desc) {\\n      var err = new Error(msg);\\n      err.type = \\\"TransportError\\\";\\n      err.description = desc;\\n      this.emit(\\\"error\\\", err);\\n      return this;\\n    }\\n    /**\\n     * Opens the transport.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      if (\\\"closed\\\" === this.readyState || \\\"\\\" === this.readyState) {\\n        this.readyState = \\\"opening\\\";\\n        this.doOpen();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Closes the transport.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.doClose();\\n        this.onClose();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Sends multiple packets.\\n     *\\n     * @param {Array} packets\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(packets) {\\n      if (\\\"open\\\" === this.readyState) {\\n        this.write(packets);\\n      } else {\\n        throw new Error(\\\"Transport not open\\\");\\n      }\\n    }\\n    /**\\n     * Called upon open\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      this.readyState = \\\"open\\\";\\n      this.writable = true;\\n      this.emit(\\\"open\\\");\\n    }\\n    /**\\n     * Called with data.\\n     *\\n     * @param {String} data\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var packet = parser.decodePacket(data, this.socket.binaryType);\\n      this.onPacket(packet);\\n    }\\n    /**\\n     * Called with a decoded packet.\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      this.emit(\\\"packet\\\", packet);\\n    }\\n    /**\\n     * Called upon close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      this.readyState = \\\"closed\\\";\\n      this.emit(\\\"close\\\");\\n    }\\n  }]);\\n\\n  return Transport;\\n}(Emitter);\\n\\nmodule.exports = Transport;\\n\\n//# sourceURL=webpack://eio/./lib/transport.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/index.js\":\n/*!*********************************!*\\\n  !*** ./lib/transports/index.js ***!\n  \\*********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar XHR = __webpack_require__(/*! ./polling-xhr */ \\\"./lib/transports/polling-xhr.js\\\");\\n\\nvar JSONP = __webpack_require__(/*! ./polling-jsonp */ \\\"./lib/transports/polling-jsonp.js\\\");\\n\\nvar websocket = __webpack_require__(/*! ./websocket */ \\\"./lib/transports/websocket.js\\\");\\n\\nexports.polling = polling;\\nexports.websocket = websocket;\\n/**\\n * Polling transport polymorphic constructor.\\n * Decides on xhr vs jsonp based on feature detection.\\n *\\n * @api private\\n */\\n\\nfunction polling(opts) {\\n  var xhr;\\n  var xd = false;\\n  var xs = false;\\n  var jsonp = false !== opts.jsonp;\\n\\n  if (typeof location !== \\\"undefined\\\") {\\n    var isSSL = \\\"https:\\\" === location.protocol;\\n    var port = location.port; // some user agents have empty `location.port`\\n\\n    if (!port) {\\n      port = isSSL ? 443 : 80;\\n    }\\n\\n    xd = opts.hostname !== location.hostname || port !== opts.port;\\n    xs = opts.secure !== isSSL;\\n  }\\n\\n  opts.xdomain = xd;\\n  opts.xscheme = xs;\\n  xhr = new XMLHttpRequest(opts);\\n\\n  if (\\\"open\\\" in xhr && !opts.forceJSONP) {\\n    return new XHR(opts);\\n  } else {\\n    if (!jsonp) throw new Error(\\\"JSONP disabled\\\");\\n    return new JSONP(opts);\\n  }\\n}\\n\\n//# sourceURL=webpack://eio/./lib/transports/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-jsonp.js\":\n/*!*****************************************!*\\\n  !*** ./lib/transports/polling-jsonp.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _get(target, property, receiver) { if (typeof Reflect !== \\\"undefined\\\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\\n\\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar rNewline = /\\\\n/g;\\nvar rEscapedNewline = /\\\\\\\\n/g;\\n/**\\n * Global JSONP callbacks.\\n */\\n\\nvar callbacks;\\n/**\\n * Noop.\\n */\\n\\nfunction empty() {}\\n\\nvar JSONPPolling =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(JSONPPolling, _Polling);\\n\\n  /**\\n   * JSONP Polling constructor.\\n   *\\n   * @param {Object} opts.\\n   * @api public\\n   */\\n  function JSONPPolling(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, JSONPPolling);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(JSONPPolling).call(this, opts));\\n    _this.query = _this.query || {}; // define global callbacks array if not present\\n    // we do this here (lazily) to avoid unneeded global pollution\\n\\n    if (!callbacks) {\\n      // we need to consider multiple engines in the same page\\n      callbacks = globalThis.___eio = globalThis.___eio || [];\\n    } // callback identifier\\n\\n\\n    _this.index = callbacks.length; // add callback to jsonp global\\n\\n    var self = _assertThisInitialized(_this);\\n\\n    callbacks.push(function (msg) {\\n      self.onData(msg);\\n    }); // append to query string\\n\\n    _this.query.j = _this.index; // prevent spurious errors from being emitted when the window is unloaded\\n\\n    if (typeof addEventListener === \\\"function\\\") {\\n      addEventListener(\\\"beforeunload\\\", function () {\\n        if (self.script) self.script.onerror = empty;\\n      }, false);\\n    }\\n\\n    return _this;\\n  }\\n  /**\\n   * JSONP only supports binary as base64 encoded strings\\n   */\\n\\n\\n  _createClass(JSONPPolling, [{\\n    key: \\\"doClose\\\",\\n\\n    /**\\n     * Closes the socket.\\n     *\\n     * @api private\\n     */\\n    value: function doClose() {\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      if (this.form) {\\n        this.form.parentNode.removeChild(this.form);\\n        this.form = null;\\n        this.iframe = null;\\n      }\\n\\n      _get(_getPrototypeOf(JSONPPolling.prototype), \\\"doClose\\\", this).call(this);\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      var self = this;\\n      var script = document.createElement(\\\"script\\\");\\n\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      script.async = true;\\n      script.src = this.uri();\\n\\n      script.onerror = function (e) {\\n        self.onError(\\\"jsonp poll error\\\", e);\\n      };\\n\\n      var insertAt = document.getElementsByTagName(\\\"script\\\")[0];\\n\\n      if (insertAt) {\\n        insertAt.parentNode.insertBefore(script, insertAt);\\n      } else {\\n        (document.head || document.body).appendChild(script);\\n      }\\n\\n      this.script = script;\\n      var isUAgecko = \\\"undefined\\\" !== typeof navigator && /gecko/i.test(navigator.userAgent);\\n\\n      if (isUAgecko) {\\n        setTimeout(function () {\\n          var iframe = document.createElement(\\\"iframe\\\");\\n          document.body.appendChild(iframe);\\n          document.body.removeChild(iframe);\\n        }, 100);\\n      }\\n    }\\n    /**\\n     * Writes with a hidden iframe.\\n     *\\n     * @param {String} data to send\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var self = this;\\n      var iframe;\\n\\n      if (!this.form) {\\n        var form = document.createElement(\\\"form\\\");\\n        var area = document.createElement(\\\"textarea\\\");\\n        var id = this.iframeId = \\\"eio_iframe_\\\" + this.index;\\n        form.className = \\\"socketio\\\";\\n        form.style.position = \\\"absolute\\\";\\n        form.style.top = \\\"-1000px\\\";\\n        form.style.left = \\\"-1000px\\\";\\n        form.target = id;\\n        form.method = \\\"POST\\\";\\n        form.setAttribute(\\\"accept-charset\\\", \\\"utf-8\\\");\\n        area.name = \\\"d\\\";\\n        form.appendChild(area);\\n        document.body.appendChild(form);\\n        this.form = form;\\n        this.area = area;\\n      }\\n\\n      this.form.action = this.uri();\\n\\n      function complete() {\\n        initIframe();\\n        fn();\\n      }\\n\\n      function initIframe() {\\n        if (self.iframe) {\\n          try {\\n            self.form.removeChild(self.iframe);\\n          } catch (e) {\\n            self.onError(\\\"jsonp polling iframe removal error\\\", e);\\n          }\\n        }\\n\\n        try {\\n          // ie6 dynamic iframes with target=\\\"\\\" support (thanks Chris Lambacher)\\n          var html = '<iframe src=\\\"javascript:0\\\" name=\\\"' + self.iframeId + '\\\">';\\n          iframe = document.createElement(html);\\n        } catch (e) {\\n          iframe = document.createElement(\\\"iframe\\\");\\n          iframe.name = self.iframeId;\\n          iframe.src = \\\"javascript:0\\\";\\n        }\\n\\n        iframe.id = self.iframeId;\\n        self.form.appendChild(iframe);\\n        self.iframe = iframe;\\n      }\\n\\n      initIframe(); // escape \\\\n to prevent it from being converted into \\\\r\\\\n by some UAs\\n      // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side\\n\\n      data = data.replace(rEscapedNewline, \\\"\\\\\\\\\\\\n\\\");\\n      this.area.value = data.replace(rNewline, \\\"\\\\\\\\n\\\");\\n\\n      try {\\n        this.form.submit();\\n      } catch (e) {}\\n\\n      if (this.iframe.attachEvent) {\\n        this.iframe.onreadystatechange = function () {\\n          if (self.iframe.readyState === \\\"complete\\\") {\\n            complete();\\n          }\\n        };\\n      } else {\\n        this.iframe.onload = complete;\\n      }\\n    }\\n  }, {\\n    key: \\\"supportsBinary\\\",\\n    get: function get() {\\n      return false;\\n    }\\n  }]);\\n\\n  return JSONPPolling;\\n}(Polling);\\n\\nmodule.exports = JSONPPolling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-jsonp.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-xhr.js\":\n/*!***************************************!*\\\n  !*** ./lib/transports/polling-xhr.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\n/* global attachEvent */\\nvar XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling-xhr\\\");\\n/**\\n * Empty function\\n */\\n\\n\\nfunction empty() {}\\n\\nvar hasXHR2 = function () {\\n  var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\n  var xhr = new XMLHttpRequest({\\n    xdomain: false\\n  });\\n  return null != xhr.responseType;\\n}();\\n\\nvar XHR =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(XHR, _Polling);\\n\\n  /**\\n   * XHR Polling constructor.\\n   *\\n   * @param {Object} opts\\n   * @api public\\n   */\\n  function XHR(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, XHR);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(XHR).call(this, opts));\\n\\n    if (typeof location !== \\\"undefined\\\") {\\n      var isSSL = \\\"https:\\\" === location.protocol;\\n      var port = location.port; // some user agents have empty `location.port`\\n\\n      if (!port) {\\n        port = isSSL ? 443 : 80;\\n      }\\n\\n      _this.xd = typeof location !== \\\"undefined\\\" && opts.hostname !== location.hostname || port !== opts.port;\\n      _this.xs = opts.secure !== isSSL;\\n    }\\n    /**\\n     * XHR supports binary\\n     */\\n\\n\\n    var forceBase64 = opts && opts.forceBase64;\\n    _this.supportsBinary = hasXHR2 && !forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Creates a request.\\n   *\\n   * @param {String} method\\n   * @api private\\n   */\\n\\n\\n  _createClass(XHR, [{\\n    key: \\\"request\\\",\\n    value: function request() {\\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\\n\\n      _extends(opts, {\\n        xd: this.xd,\\n        xs: this.xs\\n      }, this.opts);\\n\\n      return new Request(this.uri(), opts);\\n    }\\n    /**\\n     * Sends data.\\n     *\\n     * @param {String} data to send.\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var req = this.request({\\n        method: \\\"POST\\\",\\n        data: data\\n      });\\n      var self = this;\\n      req.on(\\\"success\\\", fn);\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr post error\\\", err);\\n      });\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      debug(\\\"xhr poll\\\");\\n      var req = this.request();\\n      var self = this;\\n      req.on(\\\"data\\\", function (data) {\\n        self.onData(data);\\n      });\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr poll error\\\", err);\\n      });\\n      this.pollXhr = req;\\n    }\\n  }]);\\n\\n  return XHR;\\n}(Polling);\\n\\nvar Request =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Request, _Emitter);\\n\\n  /**\\n   * Request constructor\\n   *\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Request(uri, opts) {\\n    var _this2;\\n\\n    _classCallCheck(this, Request);\\n\\n    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Request).call(this));\\n    _this2.opts = opts;\\n    _this2.method = opts.method || \\\"GET\\\";\\n    _this2.uri = uri;\\n    _this2.async = false !== opts.async;\\n    _this2.data = undefined !== opts.data ? opts.data : null;\\n\\n    _this2.create();\\n\\n    return _this2;\\n  }\\n  /**\\n   * Creates the XHR object and sends the request.\\n   *\\n   * @api private\\n   */\\n\\n\\n  _createClass(Request, [{\\n    key: \\\"create\\\",\\n    value: function create() {\\n      var opts = pick(this.opts, \\\"agent\\\", \\\"enablesXDR\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\");\\n      opts.xdomain = !!this.opts.xd;\\n      opts.xscheme = !!this.opts.xs;\\n      var xhr = this.xhr = new XMLHttpRequest(opts);\\n      var self = this;\\n\\n      try {\\n        debug(\\\"xhr open %s: %s\\\", this.method, this.uri);\\n        xhr.open(this.method, this.uri, this.async);\\n\\n        try {\\n          if (this.opts.extraHeaders) {\\n            xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);\\n\\n            for (var i in this.opts.extraHeaders) {\\n              if (this.opts.extraHeaders.hasOwnProperty(i)) {\\n                xhr.setRequestHeader(i, this.opts.extraHeaders[i]);\\n              }\\n            }\\n          }\\n        } catch (e) {}\\n\\n        if (\\\"POST\\\" === this.method) {\\n          try {\\n            xhr.setRequestHeader(\\\"Content-type\\\", \\\"text/plain;charset=UTF-8\\\");\\n          } catch (e) {}\\n        }\\n\\n        try {\\n          xhr.setRequestHeader(\\\"Accept\\\", \\\"*/*\\\");\\n        } catch (e) {} // ie6 check\\n\\n\\n        if (\\\"withCredentials\\\" in xhr) {\\n          xhr.withCredentials = this.opts.withCredentials;\\n        }\\n\\n        if (this.opts.requestTimeout) {\\n          xhr.timeout = this.opts.requestTimeout;\\n        }\\n\\n        if (this.hasXDR()) {\\n          xhr.onload = function () {\\n            self.onLoad();\\n          };\\n\\n          xhr.onerror = function () {\\n            self.onError(xhr.responseText);\\n          };\\n        } else {\\n          xhr.onreadystatechange = function () {\\n            if (4 !== xhr.readyState) return;\\n\\n            if (200 === xhr.status || 1223 === xhr.status) {\\n              self.onLoad();\\n            } else {\\n              // make sure the `error` event handler that's user-set\\n              // does not throw in the same tick and gets caught here\\n              setTimeout(function () {\\n                self.onError(typeof xhr.status === \\\"number\\\" ? xhr.status : 0);\\n              }, 0);\\n            }\\n          };\\n        }\\n\\n        debug(\\\"xhr data %s\\\", this.data);\\n        xhr.send(this.data);\\n      } catch (e) {\\n        // Need to defer since .create() is called directly from the constructor\\n        // and thus the 'error' event can only be only bound *after* this exception\\n        // occurs.  Therefore, also, we cannot throw here at all.\\n        setTimeout(function () {\\n          self.onError(e);\\n        }, 0);\\n        return;\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        this.index = Request.requestsCount++;\\n        Request.requests[this.index] = this;\\n      }\\n    }\\n    /**\\n     * Called upon successful response.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onSuccess\\\",\\n    value: function onSuccess() {\\n      this.emit(\\\"success\\\");\\n      this.cleanup();\\n    }\\n    /**\\n     * Called if we have data.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      this.emit(\\\"data\\\", data);\\n      this.onSuccess();\\n    }\\n    /**\\n     * Called upon error.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      this.emit(\\\"error\\\", err);\\n      this.cleanup(true);\\n    }\\n    /**\\n     * Cleans up house.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"cleanup\\\",\\n    value: function cleanup(fromError) {\\n      if (\\\"undefined\\\" === typeof this.xhr || null === this.xhr) {\\n        return;\\n      } // xmlhttprequest\\n\\n\\n      if (this.hasXDR()) {\\n        this.xhr.onload = this.xhr.onerror = empty;\\n      } else {\\n        this.xhr.onreadystatechange = empty;\\n      }\\n\\n      if (fromError) {\\n        try {\\n          this.xhr.abort();\\n        } catch (e) {}\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        delete Request.requests[this.index];\\n      }\\n\\n      this.xhr = null;\\n    }\\n    /**\\n     * Called upon load.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onLoad\\\",\\n    value: function onLoad() {\\n      var data = this.xhr.responseText;\\n\\n      if (data !== null) {\\n        this.onData(data);\\n      }\\n    }\\n    /**\\n     * Check if it has XDomainRequest.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"hasXDR\\\",\\n    value: function hasXDR() {\\n      return typeof XDomainRequest !== \\\"undefined\\\" && !this.xs && this.enablesXDR;\\n    }\\n    /**\\n     * Aborts the request.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"abort\\\",\\n    value: function abort() {\\n      this.cleanup();\\n    }\\n  }]);\\n\\n  return Request;\\n}(Emitter);\\n/**\\n * Aborts pending requests when unloading the window. This is needed to prevent\\n * memory leaks (e.g. when using IE) and to ensure that no spurious error is\\n * emitted.\\n */\\n\\n\\nRequest.requestsCount = 0;\\nRequest.requests = {};\\n\\nif (typeof document !== \\\"undefined\\\") {\\n  if (typeof attachEvent === \\\"function\\\") {\\n    attachEvent(\\\"onunload\\\", unloadHandler);\\n  } else if (typeof addEventListener === \\\"function\\\") {\\n    var terminationEvent = \\\"onpagehide\\\" in globalThis ? \\\"pagehide\\\" : \\\"unload\\\";\\n    addEventListener(terminationEvent, unloadHandler, false);\\n  }\\n}\\n\\nfunction unloadHandler() {\\n  for (var i in Request.requests) {\\n    if (Request.requests.hasOwnProperty(i)) {\\n      Request.requests[i].abort();\\n    }\\n  }\\n}\\n\\nmodule.exports = XHR;\\nmodule.exports.Request = Request;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-xhr.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling.js\":\n/*!***********************************!*\\\n  !*** ./lib/transports/polling.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling\\\");\\n\\nvar Polling =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(Polling, _Transport);\\n\\n  function Polling() {\\n    _classCallCheck(this, Polling);\\n\\n    return _possibleConstructorReturn(this, _getPrototypeOf(Polling).apply(this, arguments));\\n  }\\n\\n  _createClass(Polling, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens the socket (triggers polling). We write a PING message to determine\\n     * when the transport is open.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      this.poll();\\n    }\\n    /**\\n     * Pauses polling.\\n     *\\n     * @param {Function} callback upon buffers are flushed and transport is paused\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"pause\\\",\\n    value: function pause(onPause) {\\n      var self = this;\\n      this.readyState = \\\"pausing\\\";\\n\\n      function pause() {\\n        debug(\\\"paused\\\");\\n        self.readyState = \\\"paused\\\";\\n        onPause();\\n      }\\n\\n      if (this.polling || !this.writable) {\\n        var total = 0;\\n\\n        if (this.polling) {\\n          debug(\\\"we are currently polling - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"pollComplete\\\", function () {\\n            debug(\\\"pre-pause polling complete\\\");\\n            --total || pause();\\n          });\\n        }\\n\\n        if (!this.writable) {\\n          debug(\\\"we are currently writing - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"drain\\\", function () {\\n            debug(\\\"pre-pause writing complete\\\");\\n            --total || pause();\\n          });\\n        }\\n      } else {\\n        pause();\\n      }\\n    }\\n    /**\\n     * Starts polling cycle.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"poll\\\",\\n    value: function poll() {\\n      debug(\\\"polling\\\");\\n      this.polling = true;\\n      this.doPoll();\\n      this.emit(\\\"poll\\\");\\n    }\\n    /**\\n     * Overloads onData to detect payloads.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var self = this;\\n      debug(\\\"polling got data %s\\\", data);\\n\\n      var callback = function callback(packet, index, total) {\\n        // if its the first message we consider the transport open\\n        if (\\\"opening\\\" === self.readyState && packet.type === \\\"open\\\") {\\n          self.onOpen();\\n        } // if its a close packet, we close the ongoing requests\\n\\n\\n        if (\\\"close\\\" === packet.type) {\\n          self.onClose();\\n          return false;\\n        } // otherwise bypass onData and handle the message\\n\\n\\n        self.onPacket(packet);\\n      }; // decode payload\\n\\n\\n      parser.decodePayload(data, this.socket.binaryType).forEach(callback); // if an event did not trigger closing\\n\\n      if (\\\"closed\\\" !== this.readyState) {\\n        // if we got data we're not polling\\n        this.polling = false;\\n        this.emit(\\\"pollComplete\\\");\\n\\n        if (\\\"open\\\" === this.readyState) {\\n          this.poll();\\n        } else {\\n          debug('ignoring poll - transport state \\\"%s\\\"', this.readyState);\\n        }\\n      }\\n    }\\n    /**\\n     * For polling, send a close packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      var self = this;\\n\\n      function close() {\\n        debug(\\\"writing close packet\\\");\\n        self.write([{\\n          type: \\\"close\\\"\\n        }]);\\n      }\\n\\n      if (\\\"open\\\" === this.readyState) {\\n        debug(\\\"transport open - closing\\\");\\n        close();\\n      } else {\\n        // in case we're trying to close while\\n        // handshaking is in progress (GH-164)\\n        debug(\\\"transport not open - deferring close\\\");\\n        this.once(\\\"open\\\", close);\\n      }\\n    }\\n    /**\\n     * Writes a packets payload.\\n     *\\n     * @param {Array} data packets\\n     * @param {Function} drain callback\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var _this = this;\\n\\n      this.writable = false;\\n      parser.encodePayload(packets, function (data) {\\n        _this.doWrite(data, function () {\\n          _this.writable = true;\\n\\n          _this.emit(\\\"drain\\\");\\n        });\\n      });\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"https\\\" : \\\"http\\\";\\n      var port = \\\"\\\"; // cache busting is forced\\n\\n      if (false !== this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      }\\n\\n      if (!this.supportsBinary && !query.sid) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"https\\\" === schema && Number(this.opts.port) !== 443 || \\\"http\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // prepend ? to query\\n\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n\\n    /**\\n     * Transport name.\\n     */\\n    get: function get() {\\n      return \\\"polling\\\";\\n    }\\n  }]);\\n\\n  return Polling;\\n}(Transport);\\n\\nmodule.exports = Polling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket-constructor.browser.js\":\n/*!*********************************************************!*\\\n  !*** ./lib/transports/websocket-constructor.browser.js ***!\n  \\*********************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = {\\n  WebSocket: globalThis.WebSocket || globalThis.MozWebSocket,\\n  usingBrowserWebSocket: true,\\n  defaultBinaryType: \\\"arraybuffer\\\"\\n};\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket-constructor.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket.js\":\n/*!*************************************!*\\\n  !*** ./lib/transports/websocket.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar _require2 = __webpack_require__(/*! ./websocket-constructor */ \\\"./lib/transports/websocket-constructor.browser.js\\\"),\\n    WebSocket = _require2.WebSocket,\\n    usingBrowserWebSocket = _require2.usingBrowserWebSocket,\\n    defaultBinaryType = _require2.defaultBinaryType;\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:websocket\\\"); // detect ReactNative environment\\n\\n\\nvar isReactNative = typeof navigator !== \\\"undefined\\\" && typeof navigator.product === \\\"string\\\" && navigator.product.toLowerCase() === \\\"reactnative\\\";\\n\\nvar WS =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(WS, _Transport);\\n\\n  /**\\n   * WebSocket transport constructor.\\n   *\\n   * @api {Object} connection options\\n   * @api public\\n   */\\n  function WS(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, WS);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(WS).call(this, opts));\\n    _this.supportsBinary = !opts.forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Transport name.\\n   *\\n   * @api public\\n   */\\n\\n\\n  _createClass(WS, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens socket.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      if (!this.check()) {\\n        // let probe timeout\\n        return;\\n      }\\n\\n      var uri = this.uri();\\n      var protocols = this.opts.protocols; // React Native only supports the 'headers' option, and will print a warning if anything else is passed\\n\\n      var opts = isReactNative ? {} : pick(this.opts, \\\"agent\\\", \\\"perMessageDeflate\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\", \\\"localAddress\\\");\\n\\n      if (this.opts.extraHeaders) {\\n        opts.headers = this.opts.extraHeaders;\\n      }\\n\\n      try {\\n        this.ws = usingBrowserWebSocket && !isReactNative ? protocols ? new WebSocket(uri, protocols) : new WebSocket(uri) : new WebSocket(uri, protocols, opts);\\n      } catch (err) {\\n        return this.emit(\\\"error\\\", err);\\n      }\\n\\n      this.ws.binaryType = this.socket.binaryType || defaultBinaryType;\\n      this.addEventListeners();\\n    }\\n    /**\\n     * Adds event listeners to the socket\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"addEventListeners\\\",\\n    value: function addEventListeners() {\\n      var self = this;\\n\\n      this.ws.onopen = function () {\\n        self.onOpen();\\n      };\\n\\n      this.ws.onclose = function () {\\n        self.onClose();\\n      };\\n\\n      this.ws.onmessage = function (ev) {\\n        self.onData(ev.data);\\n      };\\n\\n      this.ws.onerror = function (e) {\\n        self.onError(\\\"websocket error\\\", e);\\n      };\\n    }\\n    /**\\n     * Writes data to socket.\\n     *\\n     * @param {Array} array of packets.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var self = this;\\n      this.writable = false; // encodePacket efficient as it uses WS framing\\n      // no need for encodePayload\\n\\n      var total = packets.length;\\n      var i = 0;\\n      var l = total;\\n\\n      for (; i < l; i++) {\\n        (function (packet) {\\n          parser.encodePacket(packet, self.supportsBinary, function (data) {\\n            // always create a new object (GH-437)\\n            var opts = {};\\n\\n            if (!usingBrowserWebSocket) {\\n              if (packet.options) {\\n                opts.compress = packet.options.compress;\\n              }\\n\\n              if (self.opts.perMessageDeflate) {\\n                var len = \\\"string\\\" === typeof data ? Buffer.byteLength(data) : data.length;\\n\\n                if (len < self.opts.perMessageDeflate.threshold) {\\n                  opts.compress = false;\\n                }\\n              }\\n            } // Sometimes the websocket has already been closed but the browser didn't\\n            // have a chance of informing us about it yet, in that case send will\\n            // throw an error\\n\\n\\n            try {\\n              if (usingBrowserWebSocket) {\\n                // TypeError is thrown when passing the second argument on Safari\\n                self.ws.send(data);\\n              } else {\\n                self.ws.send(data, opts);\\n              }\\n            } catch (e) {\\n              debug(\\\"websocket closed before onclose event\\\");\\n            }\\n\\n            --total || done();\\n          });\\n        })(packets[i]);\\n      }\\n\\n      function done() {\\n        self.emit(\\\"flush\\\"); // fake drain\\n        // defer to next tick to allow Socket to clear writeBuffer\\n\\n        setTimeout(function () {\\n          self.writable = true;\\n          self.emit(\\\"drain\\\");\\n        }, 0);\\n      }\\n    }\\n    /**\\n     * Called upon close\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      Transport.prototype.onClose.call(this);\\n    }\\n    /**\\n     * Closes socket.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      if (typeof this.ws !== \\\"undefined\\\") {\\n        this.ws.close();\\n      }\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"wss\\\" : \\\"ws\\\";\\n      var port = \\\"\\\"; // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"wss\\\" === schema && Number(this.opts.port) !== 443 || \\\"ws\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // append timestamp to URI\\n\\n\\n      if (this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      } // communicate binary support capabilities\\n\\n\\n      if (!this.supportsBinary) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // prepend ? to query\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n    /**\\n     * Feature detection for WebSocket.\\n     *\\n     * @return {Boolean} whether this transport is available.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"check\\\",\\n    value: function check() {\\n      return !!WebSocket && !(\\\"__initialize\\\" in WebSocket && this.name === WS.prototype.name);\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n    get: function get() {\\n      return \\\"websocket\\\";\\n    }\\n  }]);\\n\\n  return WS;\\n}(Transport);\\n\\nmodule.exports = WS;\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/util.js\":\n/*!*********************!*\\\n  !*** ./lib/util.js ***!\n  \\*********************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports.pick = function (obj) {\\n  for (var _len = arguments.length, attr = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\\n    attr[_key - 1] = arguments[_key];\\n  }\\n\\n  return attr.reduce(function (acc, k) {\\n    acc[k] = obj[k];\\n    return acc;\\n  }, {});\\n};\\n\\n//# sourceURL=webpack://eio/./lib/util.js?\");\n\n/***/ }),\n\n/***/ \"./lib/xmlhttprequest.js\":\n/*!*******************************!*\\\n  !*** ./lib/xmlhttprequest.js ***!\n  \\*******************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"// browser shim for xmlhttprequest module\\nvar hasCORS = __webpack_require__(/*! has-cors */ \\\"./node_modules/has-cors/index.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ./globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = function (opts) {\\n  var xdomain = opts.xdomain; // scheme must be same when usign XDomainRequest\\n  // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx\\n\\n  var xscheme = opts.xscheme; // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.\\n  // https://github.com/Automattic/engine.io-client/pull/217\\n\\n  var enablesXDR = opts.enablesXDR; // XMLHttpRequest can be disabled on IE\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {\\n      return new XMLHttpRequest();\\n    }\\n  } catch (e) {} // Use XDomainRequest for IE8 if enablesXDR is true\\n  // because loading bar keeps flashing when using jsonp-polling\\n  // https://github.com/yujiosaka/socke.io-ie8-loading-example\\n\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XDomainRequest && !xscheme && enablesXDR) {\\n      return new XDomainRequest();\\n    }\\n  } catch (e) {}\\n\\n  if (!xdomain) {\\n    try {\\n      return new globalThis[[\\\"Active\\\"].concat(\\\"Object\\\").join(\\\"X\\\")](\\\"Microsoft.XMLHTTP\\\");\\n    } catch (e) {}\\n  }\\n};\\n\\n//# sourceURL=webpack://eio/./lib/xmlhttprequest.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/*\\n * base64-arraybuffer\\n * https://github.com/niklasvh/base64-arraybuffer\\n *\\n * Copyright (c) 2012 Niklas von Hertzen\\n * Licensed under the MIT license.\\n */\\n(function (chars) {\\n  \\\"use strict\\\";\\n\\n  exports.encode = function (arraybuffer) {\\n    var bytes = new Uint8Array(arraybuffer),\\n        i,\\n        len = bytes.length,\\n        base64 = \\\"\\\";\\n\\n    for (i = 0; i < len; i += 3) {\\n      base64 += chars[bytes[i] >> 2];\\n      base64 += chars[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];\\n      base64 += chars[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];\\n      base64 += chars[bytes[i + 2] & 63];\\n    }\\n\\n    if (len % 3 === 2) {\\n      base64 = base64.substring(0, base64.length - 1) + \\\"=\\\";\\n    } else if (len % 3 === 1) {\\n      base64 = base64.substring(0, base64.length - 2) + \\\"==\\\";\\n    }\\n\\n    return base64;\\n  };\\n\\n  exports.decode = function (base64) {\\n    var bufferLength = base64.length * 0.75,\\n        len = base64.length,\\n        i,\\n        p = 0,\\n        encoded1,\\n        encoded2,\\n        encoded3,\\n        encoded4;\\n\\n    if (base64[base64.length - 1] === \\\"=\\\") {\\n      bufferLength--;\\n\\n      if (base64[base64.length - 2] === \\\"=\\\") {\\n        bufferLength--;\\n      }\\n    }\\n\\n    var arraybuffer = new ArrayBuffer(bufferLength),\\n        bytes = new Uint8Array(arraybuffer);\\n\\n    for (i = 0; i < len; i += 4) {\\n      encoded1 = chars.indexOf(base64[i]);\\n      encoded2 = chars.indexOf(base64[i + 1]);\\n      encoded3 = chars.indexOf(base64[i + 2]);\\n      encoded4 = chars.indexOf(base64[i + 3]);\\n      bytes[p++] = encoded1 << 2 | encoded2 >> 4;\\n      bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;\\n      bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;\\n    }\\n\\n    return arraybuffer;\\n  };\\n})(\\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\");\\n\\n//# sourceURL=webpack://eio/./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/component-emitter/index.js\":\n/*!*************************************************!*\\\n  !*** ./node_modules/component-emitter/index.js ***!\n  \\*************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/**\\r\\n * Expose `Emitter`.\\r\\n */\\nif (true) {\\n  module.exports = Emitter;\\n}\\n/**\\r\\n * Initialize a new `Emitter`.\\r\\n *\\r\\n * @api public\\r\\n */\\n\\n\\nfunction Emitter(obj) {\\n  if (obj) return mixin(obj);\\n}\\n\\n;\\n/**\\r\\n * Mixin the emitter properties.\\r\\n *\\r\\n * @param {Object} obj\\r\\n * @return {Object}\\r\\n * @api private\\r\\n */\\n\\nfunction mixin(obj) {\\n  for (var key in Emitter.prototype) {\\n    obj[key] = Emitter.prototype[key];\\n  }\\n\\n  return obj;\\n}\\n/**\\r\\n * Listen on the given `event` with `fn`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {};\\n  (this._callbacks['$' + event] = this._callbacks['$' + event] || []).push(fn);\\n  return this;\\n};\\n/**\\r\\n * Adds an `event` listener that will be invoked a single\\r\\n * time then automatically removed.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.once = function (event, fn) {\\n  function on() {\\n    this.off(event, on);\\n    fn.apply(this, arguments);\\n  }\\n\\n  on.fn = fn;\\n  this.on(event, on);\\n  return this;\\n};\\n/**\\r\\n * Remove the given callback for `event` or all\\r\\n * registered callbacks.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {}; // all\\n\\n  if (0 == arguments.length) {\\n    this._callbacks = {};\\n    return this;\\n  } // specific event\\n\\n\\n  var callbacks = this._callbacks['$' + event];\\n  if (!callbacks) return this; // remove all handlers\\n\\n  if (1 == arguments.length) {\\n    delete this._callbacks['$' + event];\\n    return this;\\n  } // remove specific handler\\n\\n\\n  var cb;\\n\\n  for (var i = 0; i < callbacks.length; i++) {\\n    cb = callbacks[i];\\n\\n    if (cb === fn || cb.fn === fn) {\\n      callbacks.splice(i, 1);\\n      break;\\n    }\\n  } // Remove event specific arrays for event types that no\\n  // one is subscribed for to avoid memory leak.\\n\\n\\n  if (callbacks.length === 0) {\\n    delete this._callbacks['$' + event];\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Emit `event` with the given args.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Mixed} ...\\r\\n * @return {Emitter}\\r\\n */\\n\\n\\nEmitter.prototype.emit = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  var args = new Array(arguments.length - 1),\\n      callbacks = this._callbacks['$' + event];\\n\\n  for (var i = 1; i < arguments.length; i++) {\\n    args[i - 1] = arguments[i];\\n  }\\n\\n  if (callbacks) {\\n    callbacks = callbacks.slice(0);\\n\\n    for (var i = 0, len = callbacks.length; i < len; ++i) {\\n      callbacks[i].apply(this, args);\\n    }\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Return array of callbacks for `event`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Array}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.listeners = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  return this._callbacks['$' + event] || [];\\n};\\n/**\\r\\n * Check if this emitter has `event` handlers.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Boolean}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.hasListeners = function (event) {\\n  return !!this.listeners(event).length;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/component-emitter/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/browser.js\":\n/*!*******************************************!*\\\n  !*** ./node_modules/debug/src/browser.js ***!\n  \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/* WEBPACK VAR INJECTION */(function(process) {function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/* eslint-env browser */\\n\\n/**\\n * This is the web browser implementation of `debug()`.\\n */\\nexports.log = log;\\nexports.formatArgs = formatArgs;\\nexports.save = save;\\nexports.load = load;\\nexports.useColors = useColors;\\nexports.storage = localstorage();\\n/**\\n * Colors.\\n */\\n\\nexports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];\\n/**\\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\\n * and the Firebug extension (any Firefox version) are known\\n * to support \\\"%c\\\" CSS customizations.\\n *\\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\\n */\\n// eslint-disable-next-line complexity\\n\\nfunction useColors() {\\n  // NB: In an Electron preload script, document will be defined but not fully\\n  // initialized. Since we know we're in Chrome, we'll just detect this case\\n  // explicitly\\n  if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {\\n    return true;\\n  } // Internet Explorer and Edge do not support colors.\\n\\n\\n  if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\\\\/(\\\\d+)/)) {\\n    return false;\\n  } // Is webkit? http://stackoverflow.com/a/16459606/376773\\n  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\\n\\n\\n  return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773\\n  typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?\\n  // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\\\\/(\\\\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\\\/(\\\\d+)/);\\n}\\n/**\\n * Colorize log arguments if enabled.\\n *\\n * @api public\\n */\\n\\n\\nfunction formatArgs(args) {\\n  args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);\\n\\n  if (!this.useColors) {\\n    return;\\n  }\\n\\n  var c = 'color: ' + this.color;\\n  args.splice(1, 0, c, 'color: inherit'); // The final \\\"%c\\\" is somewhat tricky, because there could be other\\n  // arguments passed either before or after the %c, so we need to\\n  // figure out the correct index to insert the CSS into\\n\\n  var index = 0;\\n  var lastC = 0;\\n  args[0].replace(/%[a-zA-Z%]/g, function (match) {\\n    if (match === '%%') {\\n      return;\\n    }\\n\\n    index++;\\n\\n    if (match === '%c') {\\n      // We only are interested in the *last* %c\\n      // (the user may have provided their own)\\n      lastC = index;\\n    }\\n  });\\n  args.splice(lastC, 0, c);\\n}\\n/**\\n * Invokes `console.log()` when available.\\n * No-op when `console.log` is not a \\\"function\\\".\\n *\\n * @api public\\n */\\n\\n\\nfunction log() {\\n  var _console;\\n\\n  // This hackery is required for IE8/9, where\\n  // the `console.log` function doesn't have 'apply'\\n  return (typeof console === \\\"undefined\\\" ? \\\"undefined\\\" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments);\\n}\\n/**\\n * Save `namespaces`.\\n *\\n * @param {String} namespaces\\n * @api private\\n */\\n\\n\\nfunction save(namespaces) {\\n  try {\\n    if (namespaces) {\\n      exports.storage.setItem('debug', namespaces);\\n    } else {\\n      exports.storage.removeItem('debug');\\n    }\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n/**\\n * Load `namespaces`.\\n *\\n * @return {String} returns the previously persisted debug modes\\n * @api private\\n */\\n\\n\\nfunction load() {\\n  var r;\\n\\n  try {\\n    r = exports.storage.getItem('debug');\\n  } catch (error) {} // Swallow\\n  // XXX (@Qix-) should we be logging these?\\n  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\\n\\n\\n  if (!r && typeof process !== 'undefined' && 'env' in process) {\\n    r = process.env.DEBUG;\\n  }\\n\\n  return r;\\n}\\n/**\\n * Localstorage attempts to return the localstorage.\\n *\\n * This is necessary because safari throws\\n * when a user disables cookies/localstorage\\n * and you attempt to access it.\\n *\\n * @return {LocalStorage}\\n * @api private\\n */\\n\\n\\nfunction localstorage() {\\n  try {\\n    // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\\n    // The Browser also has localStorage in the global context.\\n    return localStorage;\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n\\nmodule.exports = __webpack_require__(/*! ./common */ \\\"./node_modules/debug/src/common.js\\\")(exports);\\nvar formatters = module.exports.formatters;\\n/**\\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\\n */\\n\\nformatters.j = function (v) {\\n  try {\\n    return JSON.stringify(v);\\n  } catch (error) {\\n    return '[UnexpectedJSONParseError]: ' + error.message;\\n  }\\n};\\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../process/browser.js */ \\\"./node_modules/process/browser.js\\\")))\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/common.js\":\n/*!******************************************!*\\\n  !*** ./node_modules/debug/src/common.js ***!\n  \\******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\\n\\nfunction _nonIterableSpread() { throw new TypeError(\\\"Invalid attempt to spread non-iterable instance\\\"); }\\n\\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \\\"[object Arguments]\\\") return Array.from(iter); }\\n\\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\\n\\n/**\\n * This is the common logic for both the Node.js and web browser\\n * implementations of `debug()`.\\n */\\nfunction setup(env) {\\n  createDebug.debug = createDebug;\\n  createDebug[\\\"default\\\"] = createDebug;\\n  createDebug.coerce = coerce;\\n  createDebug.disable = disable;\\n  createDebug.enable = enable;\\n  createDebug.enabled = enabled;\\n  createDebug.humanize = __webpack_require__(/*! ms */ \\\"./node_modules/ms/index.js\\\");\\n  Object.keys(env).forEach(function (key) {\\n    createDebug[key] = env[key];\\n  });\\n  /**\\n  * Active `debug` instances.\\n  */\\n\\n  createDebug.instances = [];\\n  /**\\n  * The currently active debug mode names, and names to skip.\\n  */\\n\\n  createDebug.names = [];\\n  createDebug.skips = [];\\n  /**\\n  * Map of special \\\"%n\\\" handling functions, for the debug \\\"format\\\" argument.\\n  *\\n  * Valid key names are a single, lower or upper-case letter, i.e. \\\"n\\\" and \\\"N\\\".\\n  */\\n\\n  createDebug.formatters = {};\\n  /**\\n  * Selects a color for a debug namespace\\n  * @param {String} namespace The namespace string for the for the debug instance to be colored\\n  * @return {Number|String} An ANSI color code for the given namespace\\n  * @api private\\n  */\\n\\n  function selectColor(namespace) {\\n    var hash = 0;\\n\\n    for (var i = 0; i < namespace.length; i++) {\\n      hash = (hash << 5) - hash + namespace.charCodeAt(i);\\n      hash |= 0; // Convert to 32bit integer\\n    }\\n\\n    return createDebug.colors[Math.abs(hash) % createDebug.colors.length];\\n  }\\n\\n  createDebug.selectColor = selectColor;\\n  /**\\n  * Create a debugger with the given `namespace`.\\n  *\\n  * @param {String} namespace\\n  * @return {Function}\\n  * @api public\\n  */\\n\\n  function createDebug(namespace) {\\n    var prevTime;\\n\\n    function debug() {\\n      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\\n        args[_key] = arguments[_key];\\n      }\\n\\n      // Disabled?\\n      if (!debug.enabled) {\\n        return;\\n      }\\n\\n      var self = debug; // Set `diff` timestamp\\n\\n      var curr = Number(new Date());\\n      var ms = curr - (prevTime || curr);\\n      self.diff = ms;\\n      self.prev = prevTime;\\n      self.curr = curr;\\n      prevTime = curr;\\n      args[0] = createDebug.coerce(args[0]);\\n\\n      if (typeof args[0] !== 'string') {\\n        // Anything else let's inspect with %O\\n        args.unshift('%O');\\n      } // Apply any `formatters` transformations\\n\\n\\n      var index = 0;\\n      args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {\\n        // If we encounter an escaped % then don't increase the array index\\n        if (match === '%%') {\\n          return match;\\n        }\\n\\n        index++;\\n        var formatter = createDebug.formatters[format];\\n\\n        if (typeof formatter === 'function') {\\n          var val = args[index];\\n          match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`\\n\\n          args.splice(index, 1);\\n          index--;\\n        }\\n\\n        return match;\\n      }); // Apply env-specific formatting (colors, etc.)\\n\\n      createDebug.formatArgs.call(self, args);\\n      var logFn = self.log || createDebug.log;\\n      logFn.apply(self, args);\\n    }\\n\\n    debug.namespace = namespace;\\n    debug.enabled = createDebug.enabled(namespace);\\n    debug.useColors = createDebug.useColors();\\n    debug.color = selectColor(namespace);\\n    debug.destroy = destroy;\\n    debug.extend = extend; // Debug.formatArgs = formatArgs;\\n    // debug.rawLog = rawLog;\\n    // env-specific initialization logic for debug instances\\n\\n    if (typeof createDebug.init === 'function') {\\n      createDebug.init(debug);\\n    }\\n\\n    createDebug.instances.push(debug);\\n    return debug;\\n  }\\n\\n  function destroy() {\\n    var index = createDebug.instances.indexOf(this);\\n\\n    if (index !== -1) {\\n      createDebug.instances.splice(index, 1);\\n      return true;\\n    }\\n\\n    return false;\\n  }\\n\\n  function extend(namespace, delimiter) {\\n    var newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);\\n    newDebug.log = this.log;\\n    return newDebug;\\n  }\\n  /**\\n  * Enables a debug mode by namespaces. This can include modes\\n  * separated by a colon and wildcards.\\n  *\\n  * @param {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function enable(namespaces) {\\n    createDebug.save(namespaces);\\n    createDebug.names = [];\\n    createDebug.skips = [];\\n    var i;\\n    var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\\\\s,]+/);\\n    var len = split.length;\\n\\n    for (i = 0; i < len; i++) {\\n      if (!split[i]) {\\n        // ignore empty strings\\n        continue;\\n      }\\n\\n      namespaces = split[i].replace(/\\\\*/g, '.*?');\\n\\n      if (namespaces[0] === '-') {\\n        createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));\\n      } else {\\n        createDebug.names.push(new RegExp('^' + namespaces + '$'));\\n      }\\n    }\\n\\n    for (i = 0; i < createDebug.instances.length; i++) {\\n      var instance = createDebug.instances[i];\\n      instance.enabled = createDebug.enabled(instance.namespace);\\n    }\\n  }\\n  /**\\n  * Disable debug output.\\n  *\\n  * @return {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function disable() {\\n    var namespaces = [].concat(_toConsumableArray(createDebug.names.map(toNamespace)), _toConsumableArray(createDebug.skips.map(toNamespace).map(function (namespace) {\\n      return '-' + namespace;\\n    }))).join(',');\\n    createDebug.enable('');\\n    return namespaces;\\n  }\\n  /**\\n  * Returns true if the given mode name is enabled, false otherwise.\\n  *\\n  * @param {String} name\\n  * @return {Boolean}\\n  * @api public\\n  */\\n\\n\\n  function enabled(name) {\\n    if (name[name.length - 1] === '*') {\\n      return true;\\n    }\\n\\n    var i;\\n    var len;\\n\\n    for (i = 0, len = createDebug.skips.length; i < len; i++) {\\n      if (createDebug.skips[i].test(name)) {\\n        return false;\\n      }\\n    }\\n\\n    for (i = 0, len = createDebug.names.length; i < len; i++) {\\n      if (createDebug.names[i].test(name)) {\\n        return true;\\n      }\\n    }\\n\\n    return false;\\n  }\\n  /**\\n  * Convert regexp to namespace\\n  *\\n  * @param {RegExp} regxep\\n  * @return {String} namespace\\n  * @api private\\n  */\\n\\n\\n  function toNamespace(regexp) {\\n    return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\\\\.\\\\*\\\\?$/, '*');\\n  }\\n  /**\\n  * Coerce `val`.\\n  *\\n  * @param {Mixed} val\\n  * @return {Mixed}\\n  * @api private\\n  */\\n\\n\\n  function coerce(val) {\\n    if (val instanceof Error) {\\n      return val.stack || val.message;\\n    }\\n\\n    return val;\\n  }\\n\\n  createDebug.enable(createDebug.load());\\n  return createDebug;\\n}\\n\\nmodule.exports = setup;\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/common.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/commons.js\":\n/*!******************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/commons.js ***!\n  \\******************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"var PACKET_TYPES = Object.create(null); // no Map = no polyfill\\n\\nPACKET_TYPES[\\\"open\\\"] = \\\"0\\\";\\nPACKET_TYPES[\\\"close\\\"] = \\\"1\\\";\\nPACKET_TYPES[\\\"ping\\\"] = \\\"2\\\";\\nPACKET_TYPES[\\\"pong\\\"] = \\\"3\\\";\\nPACKET_TYPES[\\\"message\\\"] = \\\"4\\\";\\nPACKET_TYPES[\\\"upgrade\\\"] = \\\"5\\\";\\nPACKET_TYPES[\\\"noop\\\"] = \\\"6\\\";\\nvar PACKET_TYPES_REVERSE = Object.create(null);\\nObject.keys(PACKET_TYPES).forEach(function (key) {\\n  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;\\n});\\nvar ERROR_PACKET = {\\n  type: \\\"error\\\",\\n  data: \\\"parser error\\\"\\n};\\nmodule.exports = {\\n  PACKET_TYPES: PACKET_TYPES,\\n  PACKET_TYPES_REVERSE: PACKET_TYPES_REVERSE,\\n  ERROR_PACKET: ERROR_PACKET\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/commons.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/decodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/decodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES_REVERSE = _require.PACKET_TYPES_REVERSE,\\n    ERROR_PACKET = _require.ERROR_PACKET;\\n\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\";\\nvar base64decoder;\\n\\nif (withNativeArrayBuffer) {\\n  base64decoder = __webpack_require__(/*! base64-arraybuffer */ \\\"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\\\");\\n}\\n\\nvar decodePacket = function decodePacket(encodedPacket, binaryType) {\\n  if (typeof encodedPacket !== \\\"string\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: mapBinary(encodedPacket, binaryType)\\n    };\\n  }\\n\\n  var type = encodedPacket.charAt(0);\\n\\n  if (type === \\\"b\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: decodeBase64Packet(encodedPacket.substring(1), binaryType)\\n    };\\n  }\\n\\n  var packetType = PACKET_TYPES_REVERSE[type];\\n\\n  if (!packetType) {\\n    return ERROR_PACKET;\\n  }\\n\\n  return encodedPacket.length > 1 ? {\\n    type: PACKET_TYPES_REVERSE[type],\\n    data: encodedPacket.substring(1)\\n  } : {\\n    type: PACKET_TYPES_REVERSE[type]\\n  };\\n};\\n\\nvar decodeBase64Packet = function decodeBase64Packet(data, binaryType) {\\n  if (base64decoder) {\\n    var decoded = base64decoder.decode(data);\\n    return mapBinary(decoded, binaryType);\\n  } else {\\n    return {\\n      base64: true,\\n      data: data\\n    }; // fallback for old browsers\\n  }\\n};\\n\\nvar mapBinary = function mapBinary(data, binaryType) {\\n  switch (binaryType) {\\n    case \\\"blob\\\":\\n      return data instanceof ArrayBuffer ? new Blob([data]) : data;\\n\\n    case \\\"arraybuffer\\\":\\n    default:\\n      return data;\\n    // assuming the data is already an ArrayBuffer\\n  }\\n};\\n\\nmodule.exports = decodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/decodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/encodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/encodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES = _require.PACKET_TYPES;\\n\\nvar withNativeBlob = typeof Blob === \\\"function\\\" || typeof Blob !== \\\"undefined\\\" && Object.prototype.toString.call(Blob) === \\\"[object BlobConstructor]\\\";\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\"; // ArrayBuffer.isView method is not defined in IE10\\n\\nvar isView = function isView(obj) {\\n  return typeof ArrayBuffer.isView === \\\"function\\\" ? ArrayBuffer.isView(obj) : obj && obj.buffer instanceof ArrayBuffer;\\n};\\n\\nvar encodePacket = function encodePacket(_ref, supportsBinary, callback) {\\n  var type = _ref.type,\\n      data = _ref.data;\\n\\n  if (withNativeBlob && data instanceof Blob) {\\n    if (supportsBinary) {\\n      return callback(data);\\n    } else {\\n      return encodeBlobAsBase64(data, callback);\\n    }\\n  } else if (withNativeArrayBuffer && (data instanceof ArrayBuffer || isView(data))) {\\n    if (supportsBinary) {\\n      return callback(data instanceof ArrayBuffer ? data : data.buffer);\\n    } else {\\n      return encodeBlobAsBase64(new Blob([data]), callback);\\n    }\\n  } // plain string\\n\\n\\n  return callback(PACKET_TYPES[type] + (data || \\\"\\\"));\\n};\\n\\nvar encodeBlobAsBase64 = function encodeBlobAsBase64(data, callback) {\\n  var fileReader = new FileReader();\\n\\n  fileReader.onload = function () {\\n    var content = fileReader.result.split(\\\",\\\")[1];\\n    callback(\\\"b\\\" + content);\\n  };\\n\\n  return fileReader.readAsDataURL(data);\\n};\\n\\nmodule.exports = encodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/encodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/index.js\":\n/*!****************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/index.js ***!\n  \\****************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var encodePacket = __webpack_require__(/*! ./encodePacket */ \\\"./node_modules/engine.io-parser/lib/encodePacket.browser.js\\\");\\n\\nvar decodePacket = __webpack_require__(/*! ./decodePacket */ \\\"./node_modules/engine.io-parser/lib/decodePacket.browser.js\\\");\\n\\nvar SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text\\n\\nvar encodePayload = function encodePayload(packets, callback) {\\n  // some packets may be added to the array while encoding, so the initial length must be saved\\n  var length = packets.length;\\n  var encodedPackets = new Array(length);\\n  var count = 0;\\n  packets.forEach(function (packet, i) {\\n    // force base64 encoding for binary packets\\n    encodePacket(packet, false, function (encodedPacket) {\\n      encodedPackets[i] = encodedPacket;\\n\\n      if (++count === length) {\\n        callback(encodedPackets.join(SEPARATOR));\\n      }\\n    });\\n  });\\n};\\n\\nvar decodePayload = function decodePayload(encodedPayload, binaryType) {\\n  var encodedPackets = encodedPayload.split(SEPARATOR);\\n  var packets = [];\\n\\n  for (var i = 0; i < encodedPackets.length; i++) {\\n    var decodedPacket = decodePacket(encodedPackets[i], binaryType);\\n    packets.push(decodedPacket);\\n\\n    if (decodedPacket.type === \\\"error\\\") {\\n      break;\\n    }\\n  }\\n\\n  return packets;\\n};\\n\\nmodule.exports = {\\n  protocol: 4,\\n  encodePacket: encodePacket,\\n  encodePayload: encodePayload,\\n  decodePacket: decodePacket,\\n  decodePayload: decodePayload\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/has-cors/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/has-cors/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Module exports.\\n *\\n * Logic borrowed from Modernizr:\\n *\\n *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js\\n */\\ntry {\\n  module.exports = typeof XMLHttpRequest !== 'undefined' && 'withCredentials' in new XMLHttpRequest();\\n} catch (err) {\\n  // if XMLHttp support is disabled in IE then it will throw\\n  // when trying to create\\n  module.exports = false;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/has-cors/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/ms/index.js\":\n/*!**********************************!*\\\n  !*** ./node_modules/ms/index.js ***!\n  \\**********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/**\\n * Helpers.\\n */\\nvar s = 1000;\\nvar m = s * 60;\\nvar h = m * 60;\\nvar d = h * 24;\\nvar w = d * 7;\\nvar y = d * 365.25;\\n/**\\n * Parse or format the given `val`.\\n *\\n * Options:\\n *\\n *  - `long` verbose formatting [false]\\n *\\n * @param {String|Number} val\\n * @param {Object} [options]\\n * @throws {Error} throw an error if val is not a non-empty string or a number\\n * @return {String|Number}\\n * @api public\\n */\\n\\nmodule.exports = function (val, options) {\\n  options = options || {};\\n\\n  var type = _typeof(val);\\n\\n  if (type === 'string' && val.length > 0) {\\n    return parse(val);\\n  } else if (type === 'number' && isFinite(val)) {\\n    return options[\\\"long\\\"] ? fmtLong(val) : fmtShort(val);\\n  }\\n\\n  throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val));\\n};\\n/**\\n * Parse the given `str` and return milliseconds.\\n *\\n * @param {String} str\\n * @return {Number}\\n * @api private\\n */\\n\\n\\nfunction parse(str) {\\n  str = String(str);\\n\\n  if (str.length > 100) {\\n    return;\\n  }\\n\\n  var match = /^(-?(?:\\\\d+)?\\\\.?\\\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);\\n\\n  if (!match) {\\n    return;\\n  }\\n\\n  var n = parseFloat(match[1]);\\n  var type = (match[2] || 'ms').toLowerCase();\\n\\n  switch (type) {\\n    case 'years':\\n    case 'year':\\n    case 'yrs':\\n    case 'yr':\\n    case 'y':\\n      return n * y;\\n\\n    case 'weeks':\\n    case 'week':\\n    case 'w':\\n      return n * w;\\n\\n    case 'days':\\n    case 'day':\\n    case 'd':\\n      return n * d;\\n\\n    case 'hours':\\n    case 'hour':\\n    case 'hrs':\\n    case 'hr':\\n    case 'h':\\n      return n * h;\\n\\n    case 'minutes':\\n    case 'minute':\\n    case 'mins':\\n    case 'min':\\n    case 'm':\\n      return n * m;\\n\\n    case 'seconds':\\n    case 'second':\\n    case 'secs':\\n    case 'sec':\\n    case 's':\\n      return n * s;\\n\\n    case 'milliseconds':\\n    case 'millisecond':\\n    case 'msecs':\\n    case 'msec':\\n    case 'ms':\\n      return n;\\n\\n    default:\\n      return undefined;\\n  }\\n}\\n/**\\n * Short format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtShort(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return Math.round(ms / d) + 'd';\\n  }\\n\\n  if (msAbs >= h) {\\n    return Math.round(ms / h) + 'h';\\n  }\\n\\n  if (msAbs >= m) {\\n    return Math.round(ms / m) + 'm';\\n  }\\n\\n  if (msAbs >= s) {\\n    return Math.round(ms / s) + 's';\\n  }\\n\\n  return ms + 'ms';\\n}\\n/**\\n * Long format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtLong(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return plural(ms, msAbs, d, 'day');\\n  }\\n\\n  if (msAbs >= h) {\\n    return plural(ms, msAbs, h, 'hour');\\n  }\\n\\n  if (msAbs >= m) {\\n    return plural(ms, msAbs, m, 'minute');\\n  }\\n\\n  if (msAbs >= s) {\\n    return plural(ms, msAbs, s, 'second');\\n  }\\n\\n  return ms + ' ms';\\n}\\n/**\\n * Pluralization helper.\\n */\\n\\n\\nfunction plural(ms, msAbs, n, name) {\\n  var isPlural = msAbs >= n * 1.5;\\n  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/ms/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseqs/index.js\":\n/*!***************************************!*\\\n  !*** ./node_modules/parseqs/index.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Compiles a querystring\\n * Returns string representation of the object\\n *\\n * @param {Object}\\n * @api private\\n */\\nexports.encode = function (obj) {\\n  var str = '';\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      if (str.length) str += '&';\\n      str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);\\n    }\\n  }\\n\\n  return str;\\n};\\n/**\\n * Parses a simple querystring into an object\\n *\\n * @param {String} qs\\n * @api private\\n */\\n\\n\\nexports.decode = function (qs) {\\n  var qry = {};\\n  var pairs = qs.split('&');\\n\\n  for (var i = 0, l = pairs.length; i < l; i++) {\\n    var pair = pairs[i].split('=');\\n    qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);\\n  }\\n\\n  return qry;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/parseqs/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseuri/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/parseuri/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Parses an URI\\n *\\n * @author Steven Levithan <stevenlevithan.com> (MIT license)\\n * @api private\\n */\\nvar re = /^(?:(?![^:@]+:[^:@\\\\/]*@)(http|https|ws|wss):\\\\/\\\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\\\/?#]*)(?::(\\\\d*))?)(((\\\\/(?:[^?#](?![^?#\\\\/]*\\\\.[^?#\\\\/.]+(?:[?#]|$)))*\\\\/?)?([^?#\\\\/]*))(?:\\\\?([^#]*))?(?:#(.*))?)/;\\nvar parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'];\\n\\nmodule.exports = function parseuri(str) {\\n  var src = str,\\n      b = str.indexOf('['),\\n      e = str.indexOf(']');\\n\\n  if (b != -1 && e != -1) {\\n    str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);\\n  }\\n\\n  var m = re.exec(str || ''),\\n      uri = {},\\n      i = 14;\\n\\n  while (i--) {\\n    uri[parts[i]] = m[i] || '';\\n  }\\n\\n  if (b != -1 && e != -1) {\\n    uri.source = src;\\n    uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');\\n    uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');\\n    uri.ipv6uri = true;\\n  }\\n\\n  uri.pathNames = pathNames(uri, uri['path']);\\n  uri.queryKey = queryKey(uri, uri['query']);\\n  return uri;\\n};\\n\\nfunction pathNames(obj, path) {\\n  var regx = /\\\\/{2,9}/g,\\n      names = path.replace(regx, \\\"/\\\").split(\\\"/\\\");\\n\\n  if (path.substr(0, 1) == '/' || path.length === 0) {\\n    names.splice(0, 1);\\n  }\\n\\n  if (path.substr(path.length - 1, 1) == '/') {\\n    names.splice(names.length - 1, 1);\\n  }\\n\\n  return names;\\n}\\n\\nfunction queryKey(uri, query) {\\n  var data = {};\\n  query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {\\n    if ($1) {\\n      data[$1] = $2;\\n    }\\n  });\\n  return data;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/parseuri/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/process/browser.js\":\n/*!*****************************************!*\\\n  !*** ./node_modules/process/browser.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"// shim for using process in browser\\nvar process = module.exports = {}; // cached from whatever global is present so that test runners that stub it\\n// don't break things.  But we need to wrap it in a try catch in case it is\\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\\n// function because try/catches deoptimize in certain engines.\\n\\nvar cachedSetTimeout;\\nvar cachedClearTimeout;\\n\\nfunction defaultSetTimout() {\\n  throw new Error('setTimeout has not been defined');\\n}\\n\\nfunction defaultClearTimeout() {\\n  throw new Error('clearTimeout has not been defined');\\n}\\n\\n(function () {\\n  try {\\n    if (typeof setTimeout === 'function') {\\n      cachedSetTimeout = setTimeout;\\n    } else {\\n      cachedSetTimeout = defaultSetTimout;\\n    }\\n  } catch (e) {\\n    cachedSetTimeout = defaultSetTimout;\\n  }\\n\\n  try {\\n    if (typeof clearTimeout === 'function') {\\n      cachedClearTimeout = clearTimeout;\\n    } else {\\n      cachedClearTimeout = defaultClearTimeout;\\n    }\\n  } catch (e) {\\n    cachedClearTimeout = defaultClearTimeout;\\n  }\\n})();\\n\\nfunction runTimeout(fun) {\\n  if (cachedSetTimeout === setTimeout) {\\n    //normal enviroments in sane situations\\n    return setTimeout(fun, 0);\\n  } // if setTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\\n    cachedSetTimeout = setTimeout;\\n    return setTimeout(fun, 0);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedSetTimeout(fun, 0);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\\n      return cachedSetTimeout.call(null, fun, 0);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\\n      return cachedSetTimeout.call(this, fun, 0);\\n    }\\n  }\\n}\\n\\nfunction runClearTimeout(marker) {\\n  if (cachedClearTimeout === clearTimeout) {\\n    //normal enviroments in sane situations\\n    return clearTimeout(marker);\\n  } // if clearTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\\n    cachedClearTimeout = clearTimeout;\\n    return clearTimeout(marker);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedClearTimeout(marker);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\\n      return cachedClearTimeout.call(null, marker);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\\n      // Some versions of I.E. have different rules for clearTimeout vs setTimeout\\n      return cachedClearTimeout.call(this, marker);\\n    }\\n  }\\n}\\n\\nvar queue = [];\\nvar draining = false;\\nvar currentQueue;\\nvar queueIndex = -1;\\n\\nfunction cleanUpNextTick() {\\n  if (!draining || !currentQueue) {\\n    return;\\n  }\\n\\n  draining = false;\\n\\n  if (currentQueue.length) {\\n    queue = currentQueue.concat(queue);\\n  } else {\\n    queueIndex = -1;\\n  }\\n\\n  if (queue.length) {\\n    drainQueue();\\n  }\\n}\\n\\nfunction drainQueue() {\\n  if (draining) {\\n    return;\\n  }\\n\\n  var timeout = runTimeout(cleanUpNextTick);\\n  draining = true;\\n  var len = queue.length;\\n\\n  while (len) {\\n    currentQueue = queue;\\n    queue = [];\\n\\n    while (++queueIndex < len) {\\n      if (currentQueue) {\\n        currentQueue[queueIndex].run();\\n      }\\n    }\\n\\n    queueIndex = -1;\\n    len = queue.length;\\n  }\\n\\n  currentQueue = null;\\n  draining = false;\\n  runClearTimeout(timeout);\\n}\\n\\nprocess.nextTick = function (fun) {\\n  var args = new Array(arguments.length - 1);\\n\\n  if (arguments.length > 1) {\\n    for (var i = 1; i < arguments.length; i++) {\\n      args[i - 1] = arguments[i];\\n    }\\n  }\\n\\n  queue.push(new Item(fun, args));\\n\\n  if (queue.length === 1 && !draining) {\\n    runTimeout(drainQueue);\\n  }\\n}; // v8 likes predictible objects\\n\\n\\nfunction Item(fun, array) {\\n  this.fun = fun;\\n  this.array = array;\\n}\\n\\nItem.prototype.run = function () {\\n  this.fun.apply(null, this.array);\\n};\\n\\nprocess.title = 'browser';\\nprocess.browser = true;\\nprocess.env = {};\\nprocess.argv = [];\\nprocess.version = ''; // empty string to avoid regexp issues\\n\\nprocess.versions = {};\\n\\nfunction noop() {}\\n\\nprocess.on = noop;\\nprocess.addListener = noop;\\nprocess.once = noop;\\nprocess.off = noop;\\nprocess.removeListener = noop;\\nprocess.removeAllListeners = noop;\\nprocess.emit = noop;\\nprocess.prependListener = noop;\\nprocess.prependOnceListener = noop;\\n\\nprocess.listeners = function (name) {\\n  return [];\\n};\\n\\nprocess.binding = function (name) {\\n  throw new Error('process.binding is not supported');\\n};\\n\\nprocess.cwd = function () {\\n  return '/';\\n};\\n\\nprocess.chdir = function (dir) {\\n  throw new Error('process.chdir is not supported');\\n};\\n\\nprocess.umask = function () {\\n  return 0;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/process/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/yeast/index.js\":\n/*!*************************************!*\\\n  !*** ./node_modules/yeast/index.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\neval(\"\\n\\nvar alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''),\\n    length = 64,\\n    map = {},\\n    seed = 0,\\n    i = 0,\\n    prev;\\n/**\\n * Return a string representing the specified number.\\n *\\n * @param {Number} num The number to convert.\\n * @returns {String} The string representation of the number.\\n * @api public\\n */\\n\\nfunction encode(num) {\\n  var encoded = '';\\n\\n  do {\\n    encoded = alphabet[num % length] + encoded;\\n    num = Math.floor(num / length);\\n  } while (num > 0);\\n\\n  return encoded;\\n}\\n/**\\n * Return the integer value specified by the given string.\\n *\\n * @param {String} str The string to convert.\\n * @returns {Number} The integer value represented by the string.\\n * @api public\\n */\\n\\n\\nfunction decode(str) {\\n  var decoded = 0;\\n\\n  for (i = 0; i < str.length; i++) {\\n    decoded = decoded * length + map[str.charAt(i)];\\n  }\\n\\n  return decoded;\\n}\\n/**\\n * Yeast: A tiny growing id generator.\\n *\\n * @returns {String} A unique id.\\n * @api public\\n */\\n\\n\\nfunction yeast() {\\n  var now = encode(+new Date());\\n  if (now !== prev) return seed = 0, prev = now;\\n  return now + '.' + encode(seed++);\\n} //\\n// Map each character to its index.\\n//\\n\\n\\nfor (; i < length; i++) {\\n  map[alphabet[i]] = i;\\n} //\\n// Expose the `yeast`, `encode` and `decode` functions.\\n//\\n\\n\\nyeast.encode = encode;\\nyeast.decode = decode;\\nmodule.exports = yeast;\\n\\n//# sourceURL=webpack://eio/./node_modules/yeast/index.js?\");\n\n/***/ })\n\n/******/ });\n});"
  },
  {
    "path": "examples/server/aiohttp/static/style.css",
    "content": "body { margin: 0; padding: 0; font-family: Helvetica Neue; }\nh1 { margin: 100px 100px 10px; }\nh2 { color: #999; margin: 0 100px 30px; font-weight: normal; }\n#latency { color: red; }\n"
  },
  {
    "path": "examples/server/asgi/README.rst",
    "content": "Engine.IO Examples\n==================\n\nThis directory contains example Engine.IO applications that are compatible\nwith asyncio and the ASGI specification\n\nsimple.py\n---------\n\nA basic application in which the client sends messages to the server and the\nserver responds.\n\nlatency.py\n----------\n\nA port of the latency application included in the official Engine.IO\nJavascript server. In this application the client sends *ping* messages to\nthe server, which are responded by the server with a *pong*. The client\nmeasures the time it takes for each of these exchanges and plots these in real\ntime to the page.\n\nThis is an ideal application to measure the performance of the different\nasynchronous modes supported by the Engine.IO server.\n\nRunning the Examples\n--------------------\n\nTo run these examples, create a virtual environment, install the requirements\nand then run::\n\n    $ python simple.py\n\nor::\n\n    $ python latency.py\n\nYou can then access the applications from your web browser at\n``http://localhost:5000``.\n"
  },
  {
    "path": "examples/server/asgi/latency.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>EIO Latency</title>\n    <link rel=\"stylesheet\" href=\"/static/style.css\" />\n  </head>\n  <body>\n    <h1>EIO Latency <span id=\"latency\"></span></h1>\n    <h2 id=\"transport\">(connecting)</h2>\n    <canvas id=\"chart\" height=\"200\"></canvas>\n\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/smoothie/1.27.0/smoothie.js\"></script>\n    <script src=\"/static/engine.io.js\"></script>\n    <script>\n      // socket\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      var char = $('chart').get(0);\n      socket.on('open', function() {\n          if (chart.getContext) {\n              render();\n              window.onresize = render;\n          }\n          send();\n      });\n      socket.on('message', function(data) {\n          var latency = new Date - last;\n          $('#latency').text(latency + 'ms');\n          if (time)\n              time.append(+new Date, latency);\n          setTimeout(send, 100);\n      });\n      socket.on('close', function() {\n          if (smoothie)\n              smoothie.stop();\n          $('#transport').text('(disconnected)');\n      });\n\n      var last;\n      function send() {\n          last = new Date;\n          socket.send('ping');\n          $('#transport').text(socket.transport.name);\n      }\n\n      // chart\n      var smoothie;\n      var time;\n      function render() {\n          if (smoothie)\n              smoothie.stop();\n          chart.width = document.body.clientWidth;\n          smoothie = new SmoothieChart();\n          smoothie.streamTo(chart, 1000);\n          time = new TimeSeries();\n          smoothie.addTimeSeries(time, {\n              strokeStyle: 'rgb(255, 0, 0)',\n              fillStyle: 'rgba(255, 0, 0, 0.4)',\n              lineWidth: 2\n          });\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/server/asgi/latency.py",
    "content": "import uvicorn\n\nimport engineio\n\neio = engineio.AsyncServer(async_mode='asgi')\napp = engineio.ASGIApp(eio, static_files={\n    '/': 'latency.html',\n    '/static': 'static',\n})\n\n\n@eio.on('message')\nasync def message(sid, data):\n    await eio.send(sid, 'pong')\n\n\nif __name__ == '__main__':\n    uvicorn.run(app, host='127.0.0.1', port=5000)\n"
  },
  {
    "path": "examples/server/asgi/requirements.txt",
    "content": "Click==7.0\nh11==0.16.0\nhttptools==0.0.13\npython_engineio\nsix==1.11.0\nuvicorn==0.11.7\nuvloop==0.12.2\nwebsockets==7.0\n"
  },
  {
    "path": "examples/server/asgi/simple.html",
    "content": "<html>\n<head>\n<script src=\"/static/engine.io.js\"></script>\n<script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n<script>\n  $(document).ready(function() {\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      socket.on('open', function() {\n          $('#log').append(\"Connected to server.<br>\");\n      });\n      socket.on('message', function(data) {\n          $('#log').append(\"Server says: \" + data + \"<br>\");\n      });\n      socket.on('close', function() {\n          $('#log').append(\"Server closed the connection.<br>\");\n      });\n      window.setInterval(function() {\n          $('#log').append(\"Sending message to server...<br>\");\n          socket.send('hello from client side!');\n      }, 5000);\n  });\n</script>\n</head>\n<body>\n<h1>python-engineio example application</h1>\n<p id=\"log\"></p>\n</body>\n</html>\n"
  },
  {
    "path": "examples/server/asgi/simple.py",
    "content": "import uvicorn\n\nimport engineio\n\neio = engineio.AsyncServer(async_mode='asgi')\napp = engineio.ASGIApp(eio, static_files={\n    '/': 'simple.html',\n    '/static': 'static',\n})\n\n\n@eio.on('connect')\ndef connect(sid, environ):\n    print(\"connect \", sid)\n\n\n@eio.on('message')\nasync def message(sid, data):\n    print('message from', sid, data)\n    await eio.send(sid, 'Thank you for your message!')\n\n\n@eio.on('disconnect')\ndef disconnect(sid, reason):\n    print('disconnect ', sid, reason)\n\n\nif __name__ == '__main__':\n    uvicorn.run(app, host='127.0.0.1', port=5000)\n"
  },
  {
    "path": "examples/server/asgi/static/engine.io.js",
    "content": "/*!\n * Engine.IO v4.0.4\n * (c) 2014-2020 Guillermo Rauch\n * Released under the MIT License.\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"eio\"] = factory();\n\telse\n\t\troot[\"eio\"] = factory();\n})((() => {\n      if (typeof self !== 'undefined') {\n          return self;\n      } else if (typeof window !== 'undefined') {\n          return window;\n      } else if (typeof global !== 'undefined') {\n          return global;\n      } else {\n          return Function('return this')();\n      }\n    })(), function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./lib/index.js\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./lib/globalThis.browser.js\":\n/*!***********************************!*\\\n  !*** ./lib/globalThis.browser.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports = function () {\\n  if (typeof self !== \\\"undefined\\\") {\\n    return self;\\n  } else if (typeof window !== \\\"undefined\\\") {\\n    return window;\\n  } else {\\n    return Function(\\\"return this\\\")();\\n  }\\n}();\\n\\n//# sourceURL=webpack://eio/./lib/globalThis.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/index.js\":\n/*!**********************!*\\\n  !*** ./lib/index.js ***!\n  \\**********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var Socket = __webpack_require__(/*! ./socket */ \\\"./lib/socket.js\\\");\\n\\nmodule.exports = function (uri, opts) {\\n  return new Socket(uri, opts);\\n};\\n/**\\n * Expose deps for legacy compatibility\\n * and standalone browser access.\\n */\\n\\n\\nmodule.exports.Socket = Socket;\\nmodule.exports.protocol = Socket.protocol; // this is an int\\n\\nmodule.exports.Transport = __webpack_require__(/*! ./transport */ \\\"./lib/transport.js\\\");\\nmodule.exports.transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\nmodule.exports.parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\n//# sourceURL=webpack://eio/./lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/socket.js\":\n/*!***********************!*\\\n  !*** ./lib/socket.js ***!\n  \\***********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:socket\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseuri = __webpack_require__(/*! parseuri */ \\\"./node_modules/parseuri/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar Socket =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Socket, _Emitter);\\n\\n  /**\\n   * Socket constructor.\\n   *\\n   * @param {String|Object} uri or options\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Socket(uri) {\\n    var _this;\\n\\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\\n\\n    _classCallCheck(this, Socket);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Socket).call(this));\\n\\n    if (uri && \\\"object\\\" === _typeof(uri)) {\\n      opts = uri;\\n      uri = null;\\n    }\\n\\n    if (uri) {\\n      uri = parseuri(uri);\\n      opts.hostname = uri.host;\\n      opts.secure = uri.protocol === \\\"https\\\" || uri.protocol === \\\"wss\\\";\\n      opts.port = uri.port;\\n      if (uri.query) opts.query = uri.query;\\n    } else if (opts.host) {\\n      opts.hostname = parseuri(opts.host).host;\\n    }\\n\\n    _this.secure = null != opts.secure ? opts.secure : typeof location !== \\\"undefined\\\" && \\\"https:\\\" === location.protocol;\\n\\n    if (opts.hostname && !opts.port) {\\n      // if no port is specified manually, use the protocol default\\n      opts.port = _this.secure ? \\\"443\\\" : \\\"80\\\";\\n    }\\n\\n    _this.hostname = opts.hostname || (typeof location !== \\\"undefined\\\" ? location.hostname : \\\"localhost\\\");\\n    _this.port = opts.port || (typeof location !== \\\"undefined\\\" && location.port ? location.port : _this.secure ? 443 : 80);\\n    _this.transports = opts.transports || [\\\"polling\\\", \\\"websocket\\\"];\\n    _this.readyState = \\\"\\\";\\n    _this.writeBuffer = [];\\n    _this.prevBufferLen = 0;\\n    _this.opts = _extends({\\n      path: \\\"/engine.io\\\",\\n      agent: false,\\n      withCredentials: false,\\n      upgrade: true,\\n      jsonp: true,\\n      timestampParam: \\\"t\\\",\\n      policyPort: 843,\\n      rememberUpgrade: false,\\n      rejectUnauthorized: true,\\n      perMessageDeflate: {\\n        threshold: 1024\\n      },\\n      transportOptions: {}\\n    }, opts);\\n    _this.opts.path = _this.opts.path.replace(/\\\\/$/, \\\"\\\") + \\\"/\\\";\\n\\n    if (typeof _this.opts.query === \\\"string\\\") {\\n      _this.opts.query = parseqs.decode(_this.opts.query);\\n    } // set on handshake\\n\\n\\n    _this.id = null;\\n    _this.upgrades = null;\\n    _this.pingInterval = null;\\n    _this.pingTimeout = null; // set on heartbeat\\n\\n    _this.pingTimeoutTimer = null;\\n\\n    _this.open();\\n\\n    return _this;\\n  }\\n  /**\\n   * Creates transport of the given type.\\n   *\\n   * @param {String} transport name\\n   * @return {Transport}\\n   * @api private\\n   */\\n\\n\\n  _createClass(Socket, [{\\n    key: \\\"createTransport\\\",\\n    value: function createTransport(name) {\\n      debug('creating transport \\\"%s\\\"', name);\\n      var query = clone(this.opts.query); // append engine.io protocol identifier\\n\\n      query.EIO = parser.protocol; // transport name\\n\\n      query.transport = name; // session id if we already have one\\n\\n      if (this.id) query.sid = this.id;\\n\\n      var opts = _extends({}, this.opts.transportOptions[name], this.opts, {\\n        query: query,\\n        socket: this,\\n        hostname: this.hostname,\\n        secure: this.secure,\\n        port: this.port\\n      });\\n\\n      debug(\\\"options: %j\\\", opts);\\n      return new transports[name](opts);\\n    }\\n    /**\\n     * Initializes transport to use and starts probe.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      var transport;\\n\\n      if (this.opts.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf(\\\"websocket\\\") !== -1) {\\n        transport = \\\"websocket\\\";\\n      } else if (0 === this.transports.length) {\\n        // Emit error on next tick so it can be listened to\\n        var self = this;\\n        setTimeout(function () {\\n          self.emit(\\\"error\\\", \\\"No transports available\\\");\\n        }, 0);\\n        return;\\n      } else {\\n        transport = this.transports[0];\\n      }\\n\\n      this.readyState = \\\"opening\\\"; // Retry with the next transport if the transport is disabled (jsonp: false)\\n\\n      try {\\n        transport = this.createTransport(transport);\\n      } catch (e) {\\n        debug(\\\"error while creating transport: %s\\\", e);\\n        this.transports.shift();\\n        this.open();\\n        return;\\n      }\\n\\n      transport.open();\\n      this.setTransport(transport);\\n    }\\n    /**\\n     * Sets the current transport. Disables the existing one (if any).\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"setTransport\\\",\\n    value: function setTransport(transport) {\\n      debug(\\\"setting transport %s\\\", transport.name);\\n      var self = this;\\n\\n      if (this.transport) {\\n        debug(\\\"clearing existing transport %s\\\", this.transport.name);\\n        this.transport.removeAllListeners();\\n      } // set up transport\\n\\n\\n      this.transport = transport; // set up transport listeners\\n\\n      transport.on(\\\"drain\\\", function () {\\n        self.onDrain();\\n      }).on(\\\"packet\\\", function (packet) {\\n        self.onPacket(packet);\\n      }).on(\\\"error\\\", function (e) {\\n        self.onError(e);\\n      }).on(\\\"close\\\", function () {\\n        self.onClose(\\\"transport close\\\");\\n      });\\n    }\\n    /**\\n     * Probes a transport.\\n     *\\n     * @param {String} transport name\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"probe\\\",\\n    value: function probe(name) {\\n      debug('probing transport \\\"%s\\\"', name);\\n      var transport = this.createTransport(name, {\\n        probe: 1\\n      });\\n      var failed = false;\\n      var self = this;\\n      Socket.priorWebsocketSuccess = false;\\n\\n      function onTransportOpen() {\\n        if (self.onlyBinaryUpgrades) {\\n          var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;\\n          failed = failed || upgradeLosesBinary;\\n        }\\n\\n        if (failed) return;\\n        debug('probe transport \\\"%s\\\" opened', name);\\n        transport.send([{\\n          type: \\\"ping\\\",\\n          data: \\\"probe\\\"\\n        }]);\\n        transport.once(\\\"packet\\\", function (msg) {\\n          if (failed) return;\\n\\n          if (\\\"pong\\\" === msg.type && \\\"probe\\\" === msg.data) {\\n            debug('probe transport \\\"%s\\\" pong', name);\\n            self.upgrading = true;\\n            self.emit(\\\"upgrading\\\", transport);\\n            if (!transport) return;\\n            Socket.priorWebsocketSuccess = \\\"websocket\\\" === transport.name;\\n            debug('pausing current transport \\\"%s\\\"', self.transport.name);\\n            self.transport.pause(function () {\\n              if (failed) return;\\n              if (\\\"closed\\\" === self.readyState) return;\\n              debug(\\\"changing transport and sending upgrade packet\\\");\\n              cleanup();\\n              self.setTransport(transport);\\n              transport.send([{\\n                type: \\\"upgrade\\\"\\n              }]);\\n              self.emit(\\\"upgrade\\\", transport);\\n              transport = null;\\n              self.upgrading = false;\\n              self.flush();\\n            });\\n          } else {\\n            debug('probe transport \\\"%s\\\" failed', name);\\n            var err = new Error(\\\"probe error\\\");\\n            err.transport = transport.name;\\n            self.emit(\\\"upgradeError\\\", err);\\n          }\\n        });\\n      }\\n\\n      function freezeTransport() {\\n        if (failed) return; // Any callback called by transport should be ignored since now\\n\\n        failed = true;\\n        cleanup();\\n        transport.close();\\n        transport = null;\\n      } // Handle any error that happens while probing\\n\\n\\n      function onerror(err) {\\n        var error = new Error(\\\"probe error: \\\" + err);\\n        error.transport = transport.name;\\n        freezeTransport();\\n        debug('probe transport \\\"%s\\\" failed because of error: %s', name, err);\\n        self.emit(\\\"upgradeError\\\", error);\\n      }\\n\\n      function onTransportClose() {\\n        onerror(\\\"transport closed\\\");\\n      } // When the socket is closed while we're probing\\n\\n\\n      function onclose() {\\n        onerror(\\\"socket closed\\\");\\n      } // When the socket is upgraded while we're probing\\n\\n\\n      function onupgrade(to) {\\n        if (transport && to.name !== transport.name) {\\n          debug('\\\"%s\\\" works - aborting \\\"%s\\\"', to.name, transport.name);\\n          freezeTransport();\\n        }\\n      } // Remove all listeners on the transport and on self\\n\\n\\n      function cleanup() {\\n        transport.removeListener(\\\"open\\\", onTransportOpen);\\n        transport.removeListener(\\\"error\\\", onerror);\\n        transport.removeListener(\\\"close\\\", onTransportClose);\\n        self.removeListener(\\\"close\\\", onclose);\\n        self.removeListener(\\\"upgrading\\\", onupgrade);\\n      }\\n\\n      transport.once(\\\"open\\\", onTransportOpen);\\n      transport.once(\\\"error\\\", onerror);\\n      transport.once(\\\"close\\\", onTransportClose);\\n      this.once(\\\"close\\\", onclose);\\n      this.once(\\\"upgrading\\\", onupgrade);\\n      transport.open();\\n    }\\n    /**\\n     * Called when connection is deemed open.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      debug(\\\"socket open\\\");\\n      this.readyState = \\\"open\\\";\\n      Socket.priorWebsocketSuccess = \\\"websocket\\\" === this.transport.name;\\n      this.emit(\\\"open\\\");\\n      this.flush(); // we check for `readyState` in case an `open`\\n      // listener already closed the socket\\n\\n      if (\\\"open\\\" === this.readyState && this.opts.upgrade && this.transport.pause) {\\n        debug(\\\"starting upgrade probes\\\");\\n        var i = 0;\\n        var l = this.upgrades.length;\\n\\n        for (; i < l; i++) {\\n          this.probe(this.upgrades[i]);\\n        }\\n      }\\n    }\\n    /**\\n     * Handles a packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket receive: type \\\"%s\\\", data \\\"%s\\\"', packet.type, packet.data);\\n        this.emit(\\\"packet\\\", packet); // Socket is live - any packet counts\\n\\n        this.emit(\\\"heartbeat\\\");\\n\\n        switch (packet.type) {\\n          case \\\"open\\\":\\n            this.onHandshake(JSON.parse(packet.data));\\n            break;\\n\\n          case \\\"ping\\\":\\n            this.resetPingTimeout();\\n            this.sendPacket(\\\"pong\\\");\\n            this.emit(\\\"pong\\\");\\n            break;\\n\\n          case \\\"error\\\":\\n            var err = new Error(\\\"server error\\\");\\n            err.code = packet.data;\\n            this.onError(err);\\n            break;\\n\\n          case \\\"message\\\":\\n            this.emit(\\\"data\\\", packet.data);\\n            this.emit(\\\"message\\\", packet.data);\\n            break;\\n        }\\n      } else {\\n        debug('packet received with socket readyState \\\"%s\\\"', this.readyState);\\n      }\\n    }\\n    /**\\n     * Called upon handshake completion.\\n     *\\n     * @param {Object} handshake obj\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onHandshake\\\",\\n    value: function onHandshake(data) {\\n      this.emit(\\\"handshake\\\", data);\\n      this.id = data.sid;\\n      this.transport.query.sid = data.sid;\\n      this.upgrades = this.filterUpgrades(data.upgrades);\\n      this.pingInterval = data.pingInterval;\\n      this.pingTimeout = data.pingTimeout;\\n      this.onOpen(); // In case open handler closes socket\\n\\n      if (\\\"closed\\\" === this.readyState) return;\\n      this.resetPingTimeout();\\n    }\\n    /**\\n     * Sets and resets ping timeout timer based on server pings.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"resetPingTimeout\\\",\\n    value: function resetPingTimeout() {\\n      var _this2 = this;\\n\\n      clearTimeout(this.pingTimeoutTimer);\\n      this.pingTimeoutTimer = setTimeout(function () {\\n        _this2.onClose(\\\"ping timeout\\\");\\n      }, this.pingInterval + this.pingTimeout);\\n    }\\n    /**\\n     * Called on `drain` event\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onDrain\\\",\\n    value: function onDrain() {\\n      this.writeBuffer.splice(0, this.prevBufferLen); // setting prevBufferLen = 0 is very important\\n      // for example, when upgrading, upgrade packet is sent over,\\n      // and a nonzero prevBufferLen could cause problems on `drain`\\n\\n      this.prevBufferLen = 0;\\n\\n      if (0 === this.writeBuffer.length) {\\n        this.emit(\\\"drain\\\");\\n      } else {\\n        this.flush();\\n      }\\n    }\\n    /**\\n     * Flush write buffers.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"flush\\\",\\n    value: function flush() {\\n      if (\\\"closed\\\" !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) {\\n        debug(\\\"flushing %d packets in socket\\\", this.writeBuffer.length);\\n        this.transport.send(this.writeBuffer); // keep track of current length of writeBuffer\\n        // splice writeBuffer and callbackBuffer on `drain`\\n\\n        this.prevBufferLen = this.writeBuffer.length;\\n        this.emit(\\\"flush\\\");\\n      }\\n    }\\n    /**\\n     * Sends a message.\\n     *\\n     * @param {String} message.\\n     * @param {Function} callback function.\\n     * @param {Object} options.\\n     * @return {Socket} for chaining.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n    /**\\n     * Sends a packet.\\n     *\\n     * @param {String} packet type.\\n     * @param {String} data.\\n     * @param {Object} options.\\n     * @param {Function} callback function.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"sendPacket\\\",\\n    value: function sendPacket(type, data, options, fn) {\\n      if (\\\"function\\\" === typeof data) {\\n        fn = data;\\n        data = undefined;\\n      }\\n\\n      if (\\\"function\\\" === typeof options) {\\n        fn = options;\\n        options = null;\\n      }\\n\\n      if (\\\"closing\\\" === this.readyState || \\\"closed\\\" === this.readyState) {\\n        return;\\n      }\\n\\n      options = options || {};\\n      options.compress = false !== options.compress;\\n      var packet = {\\n        type: type,\\n        data: data,\\n        options: options\\n      };\\n      this.emit(\\\"packetCreate\\\", packet);\\n      this.writeBuffer.push(packet);\\n      if (fn) this.once(\\\"flush\\\", fn);\\n      this.flush();\\n    }\\n    /**\\n     * Closes the connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      var self = this;\\n\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.readyState = \\\"closing\\\";\\n\\n        if (this.writeBuffer.length) {\\n          this.once(\\\"drain\\\", function () {\\n            if (this.upgrading) {\\n              waitForUpgrade();\\n            } else {\\n              close();\\n            }\\n          });\\n        } else if (this.upgrading) {\\n          waitForUpgrade();\\n        } else {\\n          close();\\n        }\\n      }\\n\\n      function close() {\\n        self.onClose(\\\"forced close\\\");\\n        debug(\\\"socket closing - telling transport to close\\\");\\n        self.transport.close();\\n      }\\n\\n      function cleanupAndClose() {\\n        self.removeListener(\\\"upgrade\\\", cleanupAndClose);\\n        self.removeListener(\\\"upgradeError\\\", cleanupAndClose);\\n        close();\\n      }\\n\\n      function waitForUpgrade() {\\n        // wait for upgrade to finish since we can't send packets while pausing a transport\\n        self.once(\\\"upgrade\\\", cleanupAndClose);\\n        self.once(\\\"upgradeError\\\", cleanupAndClose);\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Called upon transport error\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      debug(\\\"socket error %j\\\", err);\\n      Socket.priorWebsocketSuccess = false;\\n      this.emit(\\\"error\\\", err);\\n      this.onClose(\\\"transport error\\\", err);\\n    }\\n    /**\\n     * Called upon transport close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose(reason, desc) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket close with reason: \\\"%s\\\"', reason);\\n        var self = this; // clear timers\\n\\n        clearTimeout(this.pingIntervalTimer);\\n        clearTimeout(this.pingTimeoutTimer); // stop event from firing again for transport\\n\\n        this.transport.removeAllListeners(\\\"close\\\"); // ensure transport won't stay open\\n\\n        this.transport.close(); // ignore further transport communication\\n\\n        this.transport.removeAllListeners(); // set ready state\\n\\n        this.readyState = \\\"closed\\\"; // clear session id\\n\\n        this.id = null; // emit close event\\n\\n        this.emit(\\\"close\\\", reason, desc); // clean buffers after, so users can still\\n        // grab the buffers on `close` event\\n\\n        self.writeBuffer = [];\\n        self.prevBufferLen = 0;\\n      }\\n    }\\n    /**\\n     * Filters upgrades, returning only those matching client transports.\\n     *\\n     * @param {Array} server upgrades\\n     * @api private\\n     *\\n     */\\n\\n  }, {\\n    key: \\\"filterUpgrades\\\",\\n    value: function filterUpgrades(upgrades) {\\n      var filteredUpgrades = [];\\n      var i = 0;\\n      var j = upgrades.length;\\n\\n      for (; i < j; i++) {\\n        if (~this.transports.indexOf(upgrades[i])) filteredUpgrades.push(upgrades[i]);\\n      }\\n\\n      return filteredUpgrades;\\n    }\\n  }]);\\n\\n  return Socket;\\n}(Emitter);\\n\\nSocket.priorWebsocketSuccess = false;\\n/**\\n * Protocol version.\\n *\\n * @api public\\n */\\n\\nSocket.protocol = parser.protocol; // this is an int\\n\\nfunction clone(obj) {\\n  var o = {};\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      o[i] = obj[i];\\n    }\\n  }\\n\\n  return o;\\n}\\n\\nmodule.exports = Socket;\\n\\n//# sourceURL=webpack://eio/./lib/socket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transport.js\":\n/*!**************************!*\\\n  !*** ./lib/transport.js ***!\n  \\**************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar Transport =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Transport, _Emitter);\\n\\n  /**\\n   * Transport abstract constructor.\\n   *\\n   * @param {Object} options.\\n   * @api private\\n   */\\n  function Transport(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, Transport);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Transport).call(this));\\n    _this.opts = opts;\\n    _this.query = opts.query;\\n    _this.readyState = \\\"\\\";\\n    _this.socket = opts.socket;\\n    return _this;\\n  }\\n  /**\\n   * Emits an error.\\n   *\\n   * @param {String} str\\n   * @return {Transport} for chaining\\n   * @api public\\n   */\\n\\n\\n  _createClass(Transport, [{\\n    key: \\\"onError\\\",\\n    value: function onError(msg, desc) {\\n      var err = new Error(msg);\\n      err.type = \\\"TransportError\\\";\\n      err.description = desc;\\n      this.emit(\\\"error\\\", err);\\n      return this;\\n    }\\n    /**\\n     * Opens the transport.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      if (\\\"closed\\\" === this.readyState || \\\"\\\" === this.readyState) {\\n        this.readyState = \\\"opening\\\";\\n        this.doOpen();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Closes the transport.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.doClose();\\n        this.onClose();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Sends multiple packets.\\n     *\\n     * @param {Array} packets\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(packets) {\\n      if (\\\"open\\\" === this.readyState) {\\n        this.write(packets);\\n      } else {\\n        throw new Error(\\\"Transport not open\\\");\\n      }\\n    }\\n    /**\\n     * Called upon open\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      this.readyState = \\\"open\\\";\\n      this.writable = true;\\n      this.emit(\\\"open\\\");\\n    }\\n    /**\\n     * Called with data.\\n     *\\n     * @param {String} data\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var packet = parser.decodePacket(data, this.socket.binaryType);\\n      this.onPacket(packet);\\n    }\\n    /**\\n     * Called with a decoded packet.\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      this.emit(\\\"packet\\\", packet);\\n    }\\n    /**\\n     * Called upon close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      this.readyState = \\\"closed\\\";\\n      this.emit(\\\"close\\\");\\n    }\\n  }]);\\n\\n  return Transport;\\n}(Emitter);\\n\\nmodule.exports = Transport;\\n\\n//# sourceURL=webpack://eio/./lib/transport.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/index.js\":\n/*!*********************************!*\\\n  !*** ./lib/transports/index.js ***!\n  \\*********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar XHR = __webpack_require__(/*! ./polling-xhr */ \\\"./lib/transports/polling-xhr.js\\\");\\n\\nvar JSONP = __webpack_require__(/*! ./polling-jsonp */ \\\"./lib/transports/polling-jsonp.js\\\");\\n\\nvar websocket = __webpack_require__(/*! ./websocket */ \\\"./lib/transports/websocket.js\\\");\\n\\nexports.polling = polling;\\nexports.websocket = websocket;\\n/**\\n * Polling transport polymorphic constructor.\\n * Decides on xhr vs jsonp based on feature detection.\\n *\\n * @api private\\n */\\n\\nfunction polling(opts) {\\n  var xhr;\\n  var xd = false;\\n  var xs = false;\\n  var jsonp = false !== opts.jsonp;\\n\\n  if (typeof location !== \\\"undefined\\\") {\\n    var isSSL = \\\"https:\\\" === location.protocol;\\n    var port = location.port; // some user agents have empty `location.port`\\n\\n    if (!port) {\\n      port = isSSL ? 443 : 80;\\n    }\\n\\n    xd = opts.hostname !== location.hostname || port !== opts.port;\\n    xs = opts.secure !== isSSL;\\n  }\\n\\n  opts.xdomain = xd;\\n  opts.xscheme = xs;\\n  xhr = new XMLHttpRequest(opts);\\n\\n  if (\\\"open\\\" in xhr && !opts.forceJSONP) {\\n    return new XHR(opts);\\n  } else {\\n    if (!jsonp) throw new Error(\\\"JSONP disabled\\\");\\n    return new JSONP(opts);\\n  }\\n}\\n\\n//# sourceURL=webpack://eio/./lib/transports/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-jsonp.js\":\n/*!*****************************************!*\\\n  !*** ./lib/transports/polling-jsonp.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _get(target, property, receiver) { if (typeof Reflect !== \\\"undefined\\\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\\n\\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar rNewline = /\\\\n/g;\\nvar rEscapedNewline = /\\\\\\\\n/g;\\n/**\\n * Global JSONP callbacks.\\n */\\n\\nvar callbacks;\\n/**\\n * Noop.\\n */\\n\\nfunction empty() {}\\n\\nvar JSONPPolling =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(JSONPPolling, _Polling);\\n\\n  /**\\n   * JSONP Polling constructor.\\n   *\\n   * @param {Object} opts.\\n   * @api public\\n   */\\n  function JSONPPolling(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, JSONPPolling);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(JSONPPolling).call(this, opts));\\n    _this.query = _this.query || {}; // define global callbacks array if not present\\n    // we do this here (lazily) to avoid unneeded global pollution\\n\\n    if (!callbacks) {\\n      // we need to consider multiple engines in the same page\\n      callbacks = globalThis.___eio = globalThis.___eio || [];\\n    } // callback identifier\\n\\n\\n    _this.index = callbacks.length; // add callback to jsonp global\\n\\n    var self = _assertThisInitialized(_this);\\n\\n    callbacks.push(function (msg) {\\n      self.onData(msg);\\n    }); // append to query string\\n\\n    _this.query.j = _this.index; // prevent spurious errors from being emitted when the window is unloaded\\n\\n    if (typeof addEventListener === \\\"function\\\") {\\n      addEventListener(\\\"beforeunload\\\", function () {\\n        if (self.script) self.script.onerror = empty;\\n      }, false);\\n    }\\n\\n    return _this;\\n  }\\n  /**\\n   * JSONP only supports binary as base64 encoded strings\\n   */\\n\\n\\n  _createClass(JSONPPolling, [{\\n    key: \\\"doClose\\\",\\n\\n    /**\\n     * Closes the socket.\\n     *\\n     * @api private\\n     */\\n    value: function doClose() {\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      if (this.form) {\\n        this.form.parentNode.removeChild(this.form);\\n        this.form = null;\\n        this.iframe = null;\\n      }\\n\\n      _get(_getPrototypeOf(JSONPPolling.prototype), \\\"doClose\\\", this).call(this);\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      var self = this;\\n      var script = document.createElement(\\\"script\\\");\\n\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      script.async = true;\\n      script.src = this.uri();\\n\\n      script.onerror = function (e) {\\n        self.onError(\\\"jsonp poll error\\\", e);\\n      };\\n\\n      var insertAt = document.getElementsByTagName(\\\"script\\\")[0];\\n\\n      if (insertAt) {\\n        insertAt.parentNode.insertBefore(script, insertAt);\\n      } else {\\n        (document.head || document.body).appendChild(script);\\n      }\\n\\n      this.script = script;\\n      var isUAgecko = \\\"undefined\\\" !== typeof navigator && /gecko/i.test(navigator.userAgent);\\n\\n      if (isUAgecko) {\\n        setTimeout(function () {\\n          var iframe = document.createElement(\\\"iframe\\\");\\n          document.body.appendChild(iframe);\\n          document.body.removeChild(iframe);\\n        }, 100);\\n      }\\n    }\\n    /**\\n     * Writes with a hidden iframe.\\n     *\\n     * @param {String} data to send\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var self = this;\\n      var iframe;\\n\\n      if (!this.form) {\\n        var form = document.createElement(\\\"form\\\");\\n        var area = document.createElement(\\\"textarea\\\");\\n        var id = this.iframeId = \\\"eio_iframe_\\\" + this.index;\\n        form.className = \\\"socketio\\\";\\n        form.style.position = \\\"absolute\\\";\\n        form.style.top = \\\"-1000px\\\";\\n        form.style.left = \\\"-1000px\\\";\\n        form.target = id;\\n        form.method = \\\"POST\\\";\\n        form.setAttribute(\\\"accept-charset\\\", \\\"utf-8\\\");\\n        area.name = \\\"d\\\";\\n        form.appendChild(area);\\n        document.body.appendChild(form);\\n        this.form = form;\\n        this.area = area;\\n      }\\n\\n      this.form.action = this.uri();\\n\\n      function complete() {\\n        initIframe();\\n        fn();\\n      }\\n\\n      function initIframe() {\\n        if (self.iframe) {\\n          try {\\n            self.form.removeChild(self.iframe);\\n          } catch (e) {\\n            self.onError(\\\"jsonp polling iframe removal error\\\", e);\\n          }\\n        }\\n\\n        try {\\n          // ie6 dynamic iframes with target=\\\"\\\" support (thanks Chris Lambacher)\\n          var html = '<iframe src=\\\"javascript:0\\\" name=\\\"' + self.iframeId + '\\\">';\\n          iframe = document.createElement(html);\\n        } catch (e) {\\n          iframe = document.createElement(\\\"iframe\\\");\\n          iframe.name = self.iframeId;\\n          iframe.src = \\\"javascript:0\\\";\\n        }\\n\\n        iframe.id = self.iframeId;\\n        self.form.appendChild(iframe);\\n        self.iframe = iframe;\\n      }\\n\\n      initIframe(); // escape \\\\n to prevent it from being converted into \\\\r\\\\n by some UAs\\n      // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side\\n\\n      data = data.replace(rEscapedNewline, \\\"\\\\\\\\\\\\n\\\");\\n      this.area.value = data.replace(rNewline, \\\"\\\\\\\\n\\\");\\n\\n      try {\\n        this.form.submit();\\n      } catch (e) {}\\n\\n      if (this.iframe.attachEvent) {\\n        this.iframe.onreadystatechange = function () {\\n          if (self.iframe.readyState === \\\"complete\\\") {\\n            complete();\\n          }\\n        };\\n      } else {\\n        this.iframe.onload = complete;\\n      }\\n    }\\n  }, {\\n    key: \\\"supportsBinary\\\",\\n    get: function get() {\\n      return false;\\n    }\\n  }]);\\n\\n  return JSONPPolling;\\n}(Polling);\\n\\nmodule.exports = JSONPPolling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-jsonp.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-xhr.js\":\n/*!***************************************!*\\\n  !*** ./lib/transports/polling-xhr.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\n/* global attachEvent */\\nvar XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling-xhr\\\");\\n/**\\n * Empty function\\n */\\n\\n\\nfunction empty() {}\\n\\nvar hasXHR2 = function () {\\n  var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\n  var xhr = new XMLHttpRequest({\\n    xdomain: false\\n  });\\n  return null != xhr.responseType;\\n}();\\n\\nvar XHR =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(XHR, _Polling);\\n\\n  /**\\n   * XHR Polling constructor.\\n   *\\n   * @param {Object} opts\\n   * @api public\\n   */\\n  function XHR(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, XHR);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(XHR).call(this, opts));\\n\\n    if (typeof location !== \\\"undefined\\\") {\\n      var isSSL = \\\"https:\\\" === location.protocol;\\n      var port = location.port; // some user agents have empty `location.port`\\n\\n      if (!port) {\\n        port = isSSL ? 443 : 80;\\n      }\\n\\n      _this.xd = typeof location !== \\\"undefined\\\" && opts.hostname !== location.hostname || port !== opts.port;\\n      _this.xs = opts.secure !== isSSL;\\n    }\\n    /**\\n     * XHR supports binary\\n     */\\n\\n\\n    var forceBase64 = opts && opts.forceBase64;\\n    _this.supportsBinary = hasXHR2 && !forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Creates a request.\\n   *\\n   * @param {String} method\\n   * @api private\\n   */\\n\\n\\n  _createClass(XHR, [{\\n    key: \\\"request\\\",\\n    value: function request() {\\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\\n\\n      _extends(opts, {\\n        xd: this.xd,\\n        xs: this.xs\\n      }, this.opts);\\n\\n      return new Request(this.uri(), opts);\\n    }\\n    /**\\n     * Sends data.\\n     *\\n     * @param {String} data to send.\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var req = this.request({\\n        method: \\\"POST\\\",\\n        data: data\\n      });\\n      var self = this;\\n      req.on(\\\"success\\\", fn);\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr post error\\\", err);\\n      });\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      debug(\\\"xhr poll\\\");\\n      var req = this.request();\\n      var self = this;\\n      req.on(\\\"data\\\", function (data) {\\n        self.onData(data);\\n      });\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr poll error\\\", err);\\n      });\\n      this.pollXhr = req;\\n    }\\n  }]);\\n\\n  return XHR;\\n}(Polling);\\n\\nvar Request =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Request, _Emitter);\\n\\n  /**\\n   * Request constructor\\n   *\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Request(uri, opts) {\\n    var _this2;\\n\\n    _classCallCheck(this, Request);\\n\\n    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Request).call(this));\\n    _this2.opts = opts;\\n    _this2.method = opts.method || \\\"GET\\\";\\n    _this2.uri = uri;\\n    _this2.async = false !== opts.async;\\n    _this2.data = undefined !== opts.data ? opts.data : null;\\n\\n    _this2.create();\\n\\n    return _this2;\\n  }\\n  /**\\n   * Creates the XHR object and sends the request.\\n   *\\n   * @api private\\n   */\\n\\n\\n  _createClass(Request, [{\\n    key: \\\"create\\\",\\n    value: function create() {\\n      var opts = pick(this.opts, \\\"agent\\\", \\\"enablesXDR\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\");\\n      opts.xdomain = !!this.opts.xd;\\n      opts.xscheme = !!this.opts.xs;\\n      var xhr = this.xhr = new XMLHttpRequest(opts);\\n      var self = this;\\n\\n      try {\\n        debug(\\\"xhr open %s: %s\\\", this.method, this.uri);\\n        xhr.open(this.method, this.uri, this.async);\\n\\n        try {\\n          if (this.opts.extraHeaders) {\\n            xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);\\n\\n            for (var i in this.opts.extraHeaders) {\\n              if (this.opts.extraHeaders.hasOwnProperty(i)) {\\n                xhr.setRequestHeader(i, this.opts.extraHeaders[i]);\\n              }\\n            }\\n          }\\n        } catch (e) {}\\n\\n        if (\\\"POST\\\" === this.method) {\\n          try {\\n            xhr.setRequestHeader(\\\"Content-type\\\", \\\"text/plain;charset=UTF-8\\\");\\n          } catch (e) {}\\n        }\\n\\n        try {\\n          xhr.setRequestHeader(\\\"Accept\\\", \\\"*/*\\\");\\n        } catch (e) {} // ie6 check\\n\\n\\n        if (\\\"withCredentials\\\" in xhr) {\\n          xhr.withCredentials = this.opts.withCredentials;\\n        }\\n\\n        if (this.opts.requestTimeout) {\\n          xhr.timeout = this.opts.requestTimeout;\\n        }\\n\\n        if (this.hasXDR()) {\\n          xhr.onload = function () {\\n            self.onLoad();\\n          };\\n\\n          xhr.onerror = function () {\\n            self.onError(xhr.responseText);\\n          };\\n        } else {\\n          xhr.onreadystatechange = function () {\\n            if (4 !== xhr.readyState) return;\\n\\n            if (200 === xhr.status || 1223 === xhr.status) {\\n              self.onLoad();\\n            } else {\\n              // make sure the `error` event handler that's user-set\\n              // does not throw in the same tick and gets caught here\\n              setTimeout(function () {\\n                self.onError(typeof xhr.status === \\\"number\\\" ? xhr.status : 0);\\n              }, 0);\\n            }\\n          };\\n        }\\n\\n        debug(\\\"xhr data %s\\\", this.data);\\n        xhr.send(this.data);\\n      } catch (e) {\\n        // Need to defer since .create() is called directly from the constructor\\n        // and thus the 'error' event can only be only bound *after* this exception\\n        // occurs.  Therefore, also, we cannot throw here at all.\\n        setTimeout(function () {\\n          self.onError(e);\\n        }, 0);\\n        return;\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        this.index = Request.requestsCount++;\\n        Request.requests[this.index] = this;\\n      }\\n    }\\n    /**\\n     * Called upon successful response.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onSuccess\\\",\\n    value: function onSuccess() {\\n      this.emit(\\\"success\\\");\\n      this.cleanup();\\n    }\\n    /**\\n     * Called if we have data.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      this.emit(\\\"data\\\", data);\\n      this.onSuccess();\\n    }\\n    /**\\n     * Called upon error.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      this.emit(\\\"error\\\", err);\\n      this.cleanup(true);\\n    }\\n    /**\\n     * Cleans up house.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"cleanup\\\",\\n    value: function cleanup(fromError) {\\n      if (\\\"undefined\\\" === typeof this.xhr || null === this.xhr) {\\n        return;\\n      } // xmlhttprequest\\n\\n\\n      if (this.hasXDR()) {\\n        this.xhr.onload = this.xhr.onerror = empty;\\n      } else {\\n        this.xhr.onreadystatechange = empty;\\n      }\\n\\n      if (fromError) {\\n        try {\\n          this.xhr.abort();\\n        } catch (e) {}\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        delete Request.requests[this.index];\\n      }\\n\\n      this.xhr = null;\\n    }\\n    /**\\n     * Called upon load.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onLoad\\\",\\n    value: function onLoad() {\\n      var data = this.xhr.responseText;\\n\\n      if (data !== null) {\\n        this.onData(data);\\n      }\\n    }\\n    /**\\n     * Check if it has XDomainRequest.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"hasXDR\\\",\\n    value: function hasXDR() {\\n      return typeof XDomainRequest !== \\\"undefined\\\" && !this.xs && this.enablesXDR;\\n    }\\n    /**\\n     * Aborts the request.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"abort\\\",\\n    value: function abort() {\\n      this.cleanup();\\n    }\\n  }]);\\n\\n  return Request;\\n}(Emitter);\\n/**\\n * Aborts pending requests when unloading the window. This is needed to prevent\\n * memory leaks (e.g. when using IE) and to ensure that no spurious error is\\n * emitted.\\n */\\n\\n\\nRequest.requestsCount = 0;\\nRequest.requests = {};\\n\\nif (typeof document !== \\\"undefined\\\") {\\n  if (typeof attachEvent === \\\"function\\\") {\\n    attachEvent(\\\"onunload\\\", unloadHandler);\\n  } else if (typeof addEventListener === \\\"function\\\") {\\n    var terminationEvent = \\\"onpagehide\\\" in globalThis ? \\\"pagehide\\\" : \\\"unload\\\";\\n    addEventListener(terminationEvent, unloadHandler, false);\\n  }\\n}\\n\\nfunction unloadHandler() {\\n  for (var i in Request.requests) {\\n    if (Request.requests.hasOwnProperty(i)) {\\n      Request.requests[i].abort();\\n    }\\n  }\\n}\\n\\nmodule.exports = XHR;\\nmodule.exports.Request = Request;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-xhr.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling.js\":\n/*!***********************************!*\\\n  !*** ./lib/transports/polling.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling\\\");\\n\\nvar Polling =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(Polling, _Transport);\\n\\n  function Polling() {\\n    _classCallCheck(this, Polling);\\n\\n    return _possibleConstructorReturn(this, _getPrototypeOf(Polling).apply(this, arguments));\\n  }\\n\\n  _createClass(Polling, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens the socket (triggers polling). We write a PING message to determine\\n     * when the transport is open.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      this.poll();\\n    }\\n    /**\\n     * Pauses polling.\\n     *\\n     * @param {Function} callback upon buffers are flushed and transport is paused\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"pause\\\",\\n    value: function pause(onPause) {\\n      var self = this;\\n      this.readyState = \\\"pausing\\\";\\n\\n      function pause() {\\n        debug(\\\"paused\\\");\\n        self.readyState = \\\"paused\\\";\\n        onPause();\\n      }\\n\\n      if (this.polling || !this.writable) {\\n        var total = 0;\\n\\n        if (this.polling) {\\n          debug(\\\"we are currently polling - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"pollComplete\\\", function () {\\n            debug(\\\"pre-pause polling complete\\\");\\n            --total || pause();\\n          });\\n        }\\n\\n        if (!this.writable) {\\n          debug(\\\"we are currently writing - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"drain\\\", function () {\\n            debug(\\\"pre-pause writing complete\\\");\\n            --total || pause();\\n          });\\n        }\\n      } else {\\n        pause();\\n      }\\n    }\\n    /**\\n     * Starts polling cycle.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"poll\\\",\\n    value: function poll() {\\n      debug(\\\"polling\\\");\\n      this.polling = true;\\n      this.doPoll();\\n      this.emit(\\\"poll\\\");\\n    }\\n    /**\\n     * Overloads onData to detect payloads.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var self = this;\\n      debug(\\\"polling got data %s\\\", data);\\n\\n      var callback = function callback(packet, index, total) {\\n        // if its the first message we consider the transport open\\n        if (\\\"opening\\\" === self.readyState && packet.type === \\\"open\\\") {\\n          self.onOpen();\\n        } // if its a close packet, we close the ongoing requests\\n\\n\\n        if (\\\"close\\\" === packet.type) {\\n          self.onClose();\\n          return false;\\n        } // otherwise bypass onData and handle the message\\n\\n\\n        self.onPacket(packet);\\n      }; // decode payload\\n\\n\\n      parser.decodePayload(data, this.socket.binaryType).forEach(callback); // if an event did not trigger closing\\n\\n      if (\\\"closed\\\" !== this.readyState) {\\n        // if we got data we're not polling\\n        this.polling = false;\\n        this.emit(\\\"pollComplete\\\");\\n\\n        if (\\\"open\\\" === this.readyState) {\\n          this.poll();\\n        } else {\\n          debug('ignoring poll - transport state \\\"%s\\\"', this.readyState);\\n        }\\n      }\\n    }\\n    /**\\n     * For polling, send a close packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      var self = this;\\n\\n      function close() {\\n        debug(\\\"writing close packet\\\");\\n        self.write([{\\n          type: \\\"close\\\"\\n        }]);\\n      }\\n\\n      if (\\\"open\\\" === this.readyState) {\\n        debug(\\\"transport open - closing\\\");\\n        close();\\n      } else {\\n        // in case we're trying to close while\\n        // handshaking is in progress (GH-164)\\n        debug(\\\"transport not open - deferring close\\\");\\n        this.once(\\\"open\\\", close);\\n      }\\n    }\\n    /**\\n     * Writes a packets payload.\\n     *\\n     * @param {Array} data packets\\n     * @param {Function} drain callback\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var _this = this;\\n\\n      this.writable = false;\\n      parser.encodePayload(packets, function (data) {\\n        _this.doWrite(data, function () {\\n          _this.writable = true;\\n\\n          _this.emit(\\\"drain\\\");\\n        });\\n      });\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"https\\\" : \\\"http\\\";\\n      var port = \\\"\\\"; // cache busting is forced\\n\\n      if (false !== this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      }\\n\\n      if (!this.supportsBinary && !query.sid) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"https\\\" === schema && Number(this.opts.port) !== 443 || \\\"http\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // prepend ? to query\\n\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n\\n    /**\\n     * Transport name.\\n     */\\n    get: function get() {\\n      return \\\"polling\\\";\\n    }\\n  }]);\\n\\n  return Polling;\\n}(Transport);\\n\\nmodule.exports = Polling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket-constructor.browser.js\":\n/*!*********************************************************!*\\\n  !*** ./lib/transports/websocket-constructor.browser.js ***!\n  \\*********************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = {\\n  WebSocket: globalThis.WebSocket || globalThis.MozWebSocket,\\n  usingBrowserWebSocket: true,\\n  defaultBinaryType: \\\"arraybuffer\\\"\\n};\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket-constructor.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket.js\":\n/*!*************************************!*\\\n  !*** ./lib/transports/websocket.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar _require2 = __webpack_require__(/*! ./websocket-constructor */ \\\"./lib/transports/websocket-constructor.browser.js\\\"),\\n    WebSocket = _require2.WebSocket,\\n    usingBrowserWebSocket = _require2.usingBrowserWebSocket,\\n    defaultBinaryType = _require2.defaultBinaryType;\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:websocket\\\"); // detect ReactNative environment\\n\\n\\nvar isReactNative = typeof navigator !== \\\"undefined\\\" && typeof navigator.product === \\\"string\\\" && navigator.product.toLowerCase() === \\\"reactnative\\\";\\n\\nvar WS =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(WS, _Transport);\\n\\n  /**\\n   * WebSocket transport constructor.\\n   *\\n   * @api {Object} connection options\\n   * @api public\\n   */\\n  function WS(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, WS);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(WS).call(this, opts));\\n    _this.supportsBinary = !opts.forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Transport name.\\n   *\\n   * @api public\\n   */\\n\\n\\n  _createClass(WS, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens socket.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      if (!this.check()) {\\n        // let probe timeout\\n        return;\\n      }\\n\\n      var uri = this.uri();\\n      var protocols = this.opts.protocols; // React Native only supports the 'headers' option, and will print a warning if anything else is passed\\n\\n      var opts = isReactNative ? {} : pick(this.opts, \\\"agent\\\", \\\"perMessageDeflate\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\", \\\"localAddress\\\");\\n\\n      if (this.opts.extraHeaders) {\\n        opts.headers = this.opts.extraHeaders;\\n      }\\n\\n      try {\\n        this.ws = usingBrowserWebSocket && !isReactNative ? protocols ? new WebSocket(uri, protocols) : new WebSocket(uri) : new WebSocket(uri, protocols, opts);\\n      } catch (err) {\\n        return this.emit(\\\"error\\\", err);\\n      }\\n\\n      this.ws.binaryType = this.socket.binaryType || defaultBinaryType;\\n      this.addEventListeners();\\n    }\\n    /**\\n     * Adds event listeners to the socket\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"addEventListeners\\\",\\n    value: function addEventListeners() {\\n      var self = this;\\n\\n      this.ws.onopen = function () {\\n        self.onOpen();\\n      };\\n\\n      this.ws.onclose = function () {\\n        self.onClose();\\n      };\\n\\n      this.ws.onmessage = function (ev) {\\n        self.onData(ev.data);\\n      };\\n\\n      this.ws.onerror = function (e) {\\n        self.onError(\\\"websocket error\\\", e);\\n      };\\n    }\\n    /**\\n     * Writes data to socket.\\n     *\\n     * @param {Array} array of packets.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var self = this;\\n      this.writable = false; // encodePacket efficient as it uses WS framing\\n      // no need for encodePayload\\n\\n      var total = packets.length;\\n      var i = 0;\\n      var l = total;\\n\\n      for (; i < l; i++) {\\n        (function (packet) {\\n          parser.encodePacket(packet, self.supportsBinary, function (data) {\\n            // always create a new object (GH-437)\\n            var opts = {};\\n\\n            if (!usingBrowserWebSocket) {\\n              if (packet.options) {\\n                opts.compress = packet.options.compress;\\n              }\\n\\n              if (self.opts.perMessageDeflate) {\\n                var len = \\\"string\\\" === typeof data ? Buffer.byteLength(data) : data.length;\\n\\n                if (len < self.opts.perMessageDeflate.threshold) {\\n                  opts.compress = false;\\n                }\\n              }\\n            } // Sometimes the websocket has already been closed but the browser didn't\\n            // have a chance of informing us about it yet, in that case send will\\n            // throw an error\\n\\n\\n            try {\\n              if (usingBrowserWebSocket) {\\n                // TypeError is thrown when passing the second argument on Safari\\n                self.ws.send(data);\\n              } else {\\n                self.ws.send(data, opts);\\n              }\\n            } catch (e) {\\n              debug(\\\"websocket closed before onclose event\\\");\\n            }\\n\\n            --total || done();\\n          });\\n        })(packets[i]);\\n      }\\n\\n      function done() {\\n        self.emit(\\\"flush\\\"); // fake drain\\n        // defer to next tick to allow Socket to clear writeBuffer\\n\\n        setTimeout(function () {\\n          self.writable = true;\\n          self.emit(\\\"drain\\\");\\n        }, 0);\\n      }\\n    }\\n    /**\\n     * Called upon close\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      Transport.prototype.onClose.call(this);\\n    }\\n    /**\\n     * Closes socket.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      if (typeof this.ws !== \\\"undefined\\\") {\\n        this.ws.close();\\n      }\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"wss\\\" : \\\"ws\\\";\\n      var port = \\\"\\\"; // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"wss\\\" === schema && Number(this.opts.port) !== 443 || \\\"ws\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // append timestamp to URI\\n\\n\\n      if (this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      } // communicate binary support capabilities\\n\\n\\n      if (!this.supportsBinary) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // prepend ? to query\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n    /**\\n     * Feature detection for WebSocket.\\n     *\\n     * @return {Boolean} whether this transport is available.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"check\\\",\\n    value: function check() {\\n      return !!WebSocket && !(\\\"__initialize\\\" in WebSocket && this.name === WS.prototype.name);\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n    get: function get() {\\n      return \\\"websocket\\\";\\n    }\\n  }]);\\n\\n  return WS;\\n}(Transport);\\n\\nmodule.exports = WS;\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/util.js\":\n/*!*********************!*\\\n  !*** ./lib/util.js ***!\n  \\*********************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports.pick = function (obj) {\\n  for (var _len = arguments.length, attr = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\\n    attr[_key - 1] = arguments[_key];\\n  }\\n\\n  return attr.reduce(function (acc, k) {\\n    acc[k] = obj[k];\\n    return acc;\\n  }, {});\\n};\\n\\n//# sourceURL=webpack://eio/./lib/util.js?\");\n\n/***/ }),\n\n/***/ \"./lib/xmlhttprequest.js\":\n/*!*******************************!*\\\n  !*** ./lib/xmlhttprequest.js ***!\n  \\*******************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"// browser shim for xmlhttprequest module\\nvar hasCORS = __webpack_require__(/*! has-cors */ \\\"./node_modules/has-cors/index.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ./globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = function (opts) {\\n  var xdomain = opts.xdomain; // scheme must be same when usign XDomainRequest\\n  // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx\\n\\n  var xscheme = opts.xscheme; // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.\\n  // https://github.com/Automattic/engine.io-client/pull/217\\n\\n  var enablesXDR = opts.enablesXDR; // XMLHttpRequest can be disabled on IE\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {\\n      return new XMLHttpRequest();\\n    }\\n  } catch (e) {} // Use XDomainRequest for IE8 if enablesXDR is true\\n  // because loading bar keeps flashing when using jsonp-polling\\n  // https://github.com/yujiosaka/socke.io-ie8-loading-example\\n\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XDomainRequest && !xscheme && enablesXDR) {\\n      return new XDomainRequest();\\n    }\\n  } catch (e) {}\\n\\n  if (!xdomain) {\\n    try {\\n      return new globalThis[[\\\"Active\\\"].concat(\\\"Object\\\").join(\\\"X\\\")](\\\"Microsoft.XMLHTTP\\\");\\n    } catch (e) {}\\n  }\\n};\\n\\n//# sourceURL=webpack://eio/./lib/xmlhttprequest.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/*\\n * base64-arraybuffer\\n * https://github.com/niklasvh/base64-arraybuffer\\n *\\n * Copyright (c) 2012 Niklas von Hertzen\\n * Licensed under the MIT license.\\n */\\n(function (chars) {\\n  \\\"use strict\\\";\\n\\n  exports.encode = function (arraybuffer) {\\n    var bytes = new Uint8Array(arraybuffer),\\n        i,\\n        len = bytes.length,\\n        base64 = \\\"\\\";\\n\\n    for (i = 0; i < len; i += 3) {\\n      base64 += chars[bytes[i] >> 2];\\n      base64 += chars[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];\\n      base64 += chars[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];\\n      base64 += chars[bytes[i + 2] & 63];\\n    }\\n\\n    if (len % 3 === 2) {\\n      base64 = base64.substring(0, base64.length - 1) + \\\"=\\\";\\n    } else if (len % 3 === 1) {\\n      base64 = base64.substring(0, base64.length - 2) + \\\"==\\\";\\n    }\\n\\n    return base64;\\n  };\\n\\n  exports.decode = function (base64) {\\n    var bufferLength = base64.length * 0.75,\\n        len = base64.length,\\n        i,\\n        p = 0,\\n        encoded1,\\n        encoded2,\\n        encoded3,\\n        encoded4;\\n\\n    if (base64[base64.length - 1] === \\\"=\\\") {\\n      bufferLength--;\\n\\n      if (base64[base64.length - 2] === \\\"=\\\") {\\n        bufferLength--;\\n      }\\n    }\\n\\n    var arraybuffer = new ArrayBuffer(bufferLength),\\n        bytes = new Uint8Array(arraybuffer);\\n\\n    for (i = 0; i < len; i += 4) {\\n      encoded1 = chars.indexOf(base64[i]);\\n      encoded2 = chars.indexOf(base64[i + 1]);\\n      encoded3 = chars.indexOf(base64[i + 2]);\\n      encoded4 = chars.indexOf(base64[i + 3]);\\n      bytes[p++] = encoded1 << 2 | encoded2 >> 4;\\n      bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;\\n      bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;\\n    }\\n\\n    return arraybuffer;\\n  };\\n})(\\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\");\\n\\n//# sourceURL=webpack://eio/./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/component-emitter/index.js\":\n/*!*************************************************!*\\\n  !*** ./node_modules/component-emitter/index.js ***!\n  \\*************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/**\\r\\n * Expose `Emitter`.\\r\\n */\\nif (true) {\\n  module.exports = Emitter;\\n}\\n/**\\r\\n * Initialize a new `Emitter`.\\r\\n *\\r\\n * @api public\\r\\n */\\n\\n\\nfunction Emitter(obj) {\\n  if (obj) return mixin(obj);\\n}\\n\\n;\\n/**\\r\\n * Mixin the emitter properties.\\r\\n *\\r\\n * @param {Object} obj\\r\\n * @return {Object}\\r\\n * @api private\\r\\n */\\n\\nfunction mixin(obj) {\\n  for (var key in Emitter.prototype) {\\n    obj[key] = Emitter.prototype[key];\\n  }\\n\\n  return obj;\\n}\\n/**\\r\\n * Listen on the given `event` with `fn`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {};\\n  (this._callbacks['$' + event] = this._callbacks['$' + event] || []).push(fn);\\n  return this;\\n};\\n/**\\r\\n * Adds an `event` listener that will be invoked a single\\r\\n * time then automatically removed.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.once = function (event, fn) {\\n  function on() {\\n    this.off(event, on);\\n    fn.apply(this, arguments);\\n  }\\n\\n  on.fn = fn;\\n  this.on(event, on);\\n  return this;\\n};\\n/**\\r\\n * Remove the given callback for `event` or all\\r\\n * registered callbacks.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {}; // all\\n\\n  if (0 == arguments.length) {\\n    this._callbacks = {};\\n    return this;\\n  } // specific event\\n\\n\\n  var callbacks = this._callbacks['$' + event];\\n  if (!callbacks) return this; // remove all handlers\\n\\n  if (1 == arguments.length) {\\n    delete this._callbacks['$' + event];\\n    return this;\\n  } // remove specific handler\\n\\n\\n  var cb;\\n\\n  for (var i = 0; i < callbacks.length; i++) {\\n    cb = callbacks[i];\\n\\n    if (cb === fn || cb.fn === fn) {\\n      callbacks.splice(i, 1);\\n      break;\\n    }\\n  } // Remove event specific arrays for event types that no\\n  // one is subscribed for to avoid memory leak.\\n\\n\\n  if (callbacks.length === 0) {\\n    delete this._callbacks['$' + event];\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Emit `event` with the given args.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Mixed} ...\\r\\n * @return {Emitter}\\r\\n */\\n\\n\\nEmitter.prototype.emit = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  var args = new Array(arguments.length - 1),\\n      callbacks = this._callbacks['$' + event];\\n\\n  for (var i = 1; i < arguments.length; i++) {\\n    args[i - 1] = arguments[i];\\n  }\\n\\n  if (callbacks) {\\n    callbacks = callbacks.slice(0);\\n\\n    for (var i = 0, len = callbacks.length; i < len; ++i) {\\n      callbacks[i].apply(this, args);\\n    }\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Return array of callbacks for `event`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Array}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.listeners = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  return this._callbacks['$' + event] || [];\\n};\\n/**\\r\\n * Check if this emitter has `event` handlers.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Boolean}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.hasListeners = function (event) {\\n  return !!this.listeners(event).length;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/component-emitter/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/browser.js\":\n/*!*******************************************!*\\\n  !*** ./node_modules/debug/src/browser.js ***!\n  \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/* WEBPACK VAR INJECTION */(function(process) {function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/* eslint-env browser */\\n\\n/**\\n * This is the web browser implementation of `debug()`.\\n */\\nexports.log = log;\\nexports.formatArgs = formatArgs;\\nexports.save = save;\\nexports.load = load;\\nexports.useColors = useColors;\\nexports.storage = localstorage();\\n/**\\n * Colors.\\n */\\n\\nexports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];\\n/**\\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\\n * and the Firebug extension (any Firefox version) are known\\n * to support \\\"%c\\\" CSS customizations.\\n *\\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\\n */\\n// eslint-disable-next-line complexity\\n\\nfunction useColors() {\\n  // NB: In an Electron preload script, document will be defined but not fully\\n  // initialized. Since we know we're in Chrome, we'll just detect this case\\n  // explicitly\\n  if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {\\n    return true;\\n  } // Internet Explorer and Edge do not support colors.\\n\\n\\n  if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\\\\/(\\\\d+)/)) {\\n    return false;\\n  } // Is webkit? http://stackoverflow.com/a/16459606/376773\\n  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\\n\\n\\n  return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773\\n  typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?\\n  // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\\\\/(\\\\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\\\/(\\\\d+)/);\\n}\\n/**\\n * Colorize log arguments if enabled.\\n *\\n * @api public\\n */\\n\\n\\nfunction formatArgs(args) {\\n  args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);\\n\\n  if (!this.useColors) {\\n    return;\\n  }\\n\\n  var c = 'color: ' + this.color;\\n  args.splice(1, 0, c, 'color: inherit'); // The final \\\"%c\\\" is somewhat tricky, because there could be other\\n  // arguments passed either before or after the %c, so we need to\\n  // figure out the correct index to insert the CSS into\\n\\n  var index = 0;\\n  var lastC = 0;\\n  args[0].replace(/%[a-zA-Z%]/g, function (match) {\\n    if (match === '%%') {\\n      return;\\n    }\\n\\n    index++;\\n\\n    if (match === '%c') {\\n      // We only are interested in the *last* %c\\n      // (the user may have provided their own)\\n      lastC = index;\\n    }\\n  });\\n  args.splice(lastC, 0, c);\\n}\\n/**\\n * Invokes `console.log()` when available.\\n * No-op when `console.log` is not a \\\"function\\\".\\n *\\n * @api public\\n */\\n\\n\\nfunction log() {\\n  var _console;\\n\\n  // This hackery is required for IE8/9, where\\n  // the `console.log` function doesn't have 'apply'\\n  return (typeof console === \\\"undefined\\\" ? \\\"undefined\\\" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments);\\n}\\n/**\\n * Save `namespaces`.\\n *\\n * @param {String} namespaces\\n * @api private\\n */\\n\\n\\nfunction save(namespaces) {\\n  try {\\n    if (namespaces) {\\n      exports.storage.setItem('debug', namespaces);\\n    } else {\\n      exports.storage.removeItem('debug');\\n    }\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n/**\\n * Load `namespaces`.\\n *\\n * @return {String} returns the previously persisted debug modes\\n * @api private\\n */\\n\\n\\nfunction load() {\\n  var r;\\n\\n  try {\\n    r = exports.storage.getItem('debug');\\n  } catch (error) {} // Swallow\\n  // XXX (@Qix-) should we be logging these?\\n  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\\n\\n\\n  if (!r && typeof process !== 'undefined' && 'env' in process) {\\n    r = process.env.DEBUG;\\n  }\\n\\n  return r;\\n}\\n/**\\n * Localstorage attempts to return the localstorage.\\n *\\n * This is necessary because safari throws\\n * when a user disables cookies/localstorage\\n * and you attempt to access it.\\n *\\n * @return {LocalStorage}\\n * @api private\\n */\\n\\n\\nfunction localstorage() {\\n  try {\\n    // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\\n    // The Browser also has localStorage in the global context.\\n    return localStorage;\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n\\nmodule.exports = __webpack_require__(/*! ./common */ \\\"./node_modules/debug/src/common.js\\\")(exports);\\nvar formatters = module.exports.formatters;\\n/**\\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\\n */\\n\\nformatters.j = function (v) {\\n  try {\\n    return JSON.stringify(v);\\n  } catch (error) {\\n    return '[UnexpectedJSONParseError]: ' + error.message;\\n  }\\n};\\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../process/browser.js */ \\\"./node_modules/process/browser.js\\\")))\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/common.js\":\n/*!******************************************!*\\\n  !*** ./node_modules/debug/src/common.js ***!\n  \\******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\\n\\nfunction _nonIterableSpread() { throw new TypeError(\\\"Invalid attempt to spread non-iterable instance\\\"); }\\n\\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \\\"[object Arguments]\\\") return Array.from(iter); }\\n\\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\\n\\n/**\\n * This is the common logic for both the Node.js and web browser\\n * implementations of `debug()`.\\n */\\nfunction setup(env) {\\n  createDebug.debug = createDebug;\\n  createDebug[\\\"default\\\"] = createDebug;\\n  createDebug.coerce = coerce;\\n  createDebug.disable = disable;\\n  createDebug.enable = enable;\\n  createDebug.enabled = enabled;\\n  createDebug.humanize = __webpack_require__(/*! ms */ \\\"./node_modules/ms/index.js\\\");\\n  Object.keys(env).forEach(function (key) {\\n    createDebug[key] = env[key];\\n  });\\n  /**\\n  * Active `debug` instances.\\n  */\\n\\n  createDebug.instances = [];\\n  /**\\n  * The currently active debug mode names, and names to skip.\\n  */\\n\\n  createDebug.names = [];\\n  createDebug.skips = [];\\n  /**\\n  * Map of special \\\"%n\\\" handling functions, for the debug \\\"format\\\" argument.\\n  *\\n  * Valid key names are a single, lower or upper-case letter, i.e. \\\"n\\\" and \\\"N\\\".\\n  */\\n\\n  createDebug.formatters = {};\\n  /**\\n  * Selects a color for a debug namespace\\n  * @param {String} namespace The namespace string for the for the debug instance to be colored\\n  * @return {Number|String} An ANSI color code for the given namespace\\n  * @api private\\n  */\\n\\n  function selectColor(namespace) {\\n    var hash = 0;\\n\\n    for (var i = 0; i < namespace.length; i++) {\\n      hash = (hash << 5) - hash + namespace.charCodeAt(i);\\n      hash |= 0; // Convert to 32bit integer\\n    }\\n\\n    return createDebug.colors[Math.abs(hash) % createDebug.colors.length];\\n  }\\n\\n  createDebug.selectColor = selectColor;\\n  /**\\n  * Create a debugger with the given `namespace`.\\n  *\\n  * @param {String} namespace\\n  * @return {Function}\\n  * @api public\\n  */\\n\\n  function createDebug(namespace) {\\n    var prevTime;\\n\\n    function debug() {\\n      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\\n        args[_key] = arguments[_key];\\n      }\\n\\n      // Disabled?\\n      if (!debug.enabled) {\\n        return;\\n      }\\n\\n      var self = debug; // Set `diff` timestamp\\n\\n      var curr = Number(new Date());\\n      var ms = curr - (prevTime || curr);\\n      self.diff = ms;\\n      self.prev = prevTime;\\n      self.curr = curr;\\n      prevTime = curr;\\n      args[0] = createDebug.coerce(args[0]);\\n\\n      if (typeof args[0] !== 'string') {\\n        // Anything else let's inspect with %O\\n        args.unshift('%O');\\n      } // Apply any `formatters` transformations\\n\\n\\n      var index = 0;\\n      args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {\\n        // If we encounter an escaped % then don't increase the array index\\n        if (match === '%%') {\\n          return match;\\n        }\\n\\n        index++;\\n        var formatter = createDebug.formatters[format];\\n\\n        if (typeof formatter === 'function') {\\n          var val = args[index];\\n          match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`\\n\\n          args.splice(index, 1);\\n          index--;\\n        }\\n\\n        return match;\\n      }); // Apply env-specific formatting (colors, etc.)\\n\\n      createDebug.formatArgs.call(self, args);\\n      var logFn = self.log || createDebug.log;\\n      logFn.apply(self, args);\\n    }\\n\\n    debug.namespace = namespace;\\n    debug.enabled = createDebug.enabled(namespace);\\n    debug.useColors = createDebug.useColors();\\n    debug.color = selectColor(namespace);\\n    debug.destroy = destroy;\\n    debug.extend = extend; // Debug.formatArgs = formatArgs;\\n    // debug.rawLog = rawLog;\\n    // env-specific initialization logic for debug instances\\n\\n    if (typeof createDebug.init === 'function') {\\n      createDebug.init(debug);\\n    }\\n\\n    createDebug.instances.push(debug);\\n    return debug;\\n  }\\n\\n  function destroy() {\\n    var index = createDebug.instances.indexOf(this);\\n\\n    if (index !== -1) {\\n      createDebug.instances.splice(index, 1);\\n      return true;\\n    }\\n\\n    return false;\\n  }\\n\\n  function extend(namespace, delimiter) {\\n    var newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);\\n    newDebug.log = this.log;\\n    return newDebug;\\n  }\\n  /**\\n  * Enables a debug mode by namespaces. This can include modes\\n  * separated by a colon and wildcards.\\n  *\\n  * @param {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function enable(namespaces) {\\n    createDebug.save(namespaces);\\n    createDebug.names = [];\\n    createDebug.skips = [];\\n    var i;\\n    var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\\\\s,]+/);\\n    var len = split.length;\\n\\n    for (i = 0; i < len; i++) {\\n      if (!split[i]) {\\n        // ignore empty strings\\n        continue;\\n      }\\n\\n      namespaces = split[i].replace(/\\\\*/g, '.*?');\\n\\n      if (namespaces[0] === '-') {\\n        createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));\\n      } else {\\n        createDebug.names.push(new RegExp('^' + namespaces + '$'));\\n      }\\n    }\\n\\n    for (i = 0; i < createDebug.instances.length; i++) {\\n      var instance = createDebug.instances[i];\\n      instance.enabled = createDebug.enabled(instance.namespace);\\n    }\\n  }\\n  /**\\n  * Disable debug output.\\n  *\\n  * @return {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function disable() {\\n    var namespaces = [].concat(_toConsumableArray(createDebug.names.map(toNamespace)), _toConsumableArray(createDebug.skips.map(toNamespace).map(function (namespace) {\\n      return '-' + namespace;\\n    }))).join(',');\\n    createDebug.enable('');\\n    return namespaces;\\n  }\\n  /**\\n  * Returns true if the given mode name is enabled, false otherwise.\\n  *\\n  * @param {String} name\\n  * @return {Boolean}\\n  * @api public\\n  */\\n\\n\\n  function enabled(name) {\\n    if (name[name.length - 1] === '*') {\\n      return true;\\n    }\\n\\n    var i;\\n    var len;\\n\\n    for (i = 0, len = createDebug.skips.length; i < len; i++) {\\n      if (createDebug.skips[i].test(name)) {\\n        return false;\\n      }\\n    }\\n\\n    for (i = 0, len = createDebug.names.length; i < len; i++) {\\n      if (createDebug.names[i].test(name)) {\\n        return true;\\n      }\\n    }\\n\\n    return false;\\n  }\\n  /**\\n  * Convert regexp to namespace\\n  *\\n  * @param {RegExp} regxep\\n  * @return {String} namespace\\n  * @api private\\n  */\\n\\n\\n  function toNamespace(regexp) {\\n    return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\\\\.\\\\*\\\\?$/, '*');\\n  }\\n  /**\\n  * Coerce `val`.\\n  *\\n  * @param {Mixed} val\\n  * @return {Mixed}\\n  * @api private\\n  */\\n\\n\\n  function coerce(val) {\\n    if (val instanceof Error) {\\n      return val.stack || val.message;\\n    }\\n\\n    return val;\\n  }\\n\\n  createDebug.enable(createDebug.load());\\n  return createDebug;\\n}\\n\\nmodule.exports = setup;\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/common.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/commons.js\":\n/*!******************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/commons.js ***!\n  \\******************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"var PACKET_TYPES = Object.create(null); // no Map = no polyfill\\n\\nPACKET_TYPES[\\\"open\\\"] = \\\"0\\\";\\nPACKET_TYPES[\\\"close\\\"] = \\\"1\\\";\\nPACKET_TYPES[\\\"ping\\\"] = \\\"2\\\";\\nPACKET_TYPES[\\\"pong\\\"] = \\\"3\\\";\\nPACKET_TYPES[\\\"message\\\"] = \\\"4\\\";\\nPACKET_TYPES[\\\"upgrade\\\"] = \\\"5\\\";\\nPACKET_TYPES[\\\"noop\\\"] = \\\"6\\\";\\nvar PACKET_TYPES_REVERSE = Object.create(null);\\nObject.keys(PACKET_TYPES).forEach(function (key) {\\n  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;\\n});\\nvar ERROR_PACKET = {\\n  type: \\\"error\\\",\\n  data: \\\"parser error\\\"\\n};\\nmodule.exports = {\\n  PACKET_TYPES: PACKET_TYPES,\\n  PACKET_TYPES_REVERSE: PACKET_TYPES_REVERSE,\\n  ERROR_PACKET: ERROR_PACKET\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/commons.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/decodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/decodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES_REVERSE = _require.PACKET_TYPES_REVERSE,\\n    ERROR_PACKET = _require.ERROR_PACKET;\\n\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\";\\nvar base64decoder;\\n\\nif (withNativeArrayBuffer) {\\n  base64decoder = __webpack_require__(/*! base64-arraybuffer */ \\\"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\\\");\\n}\\n\\nvar decodePacket = function decodePacket(encodedPacket, binaryType) {\\n  if (typeof encodedPacket !== \\\"string\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: mapBinary(encodedPacket, binaryType)\\n    };\\n  }\\n\\n  var type = encodedPacket.charAt(0);\\n\\n  if (type === \\\"b\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: decodeBase64Packet(encodedPacket.substring(1), binaryType)\\n    };\\n  }\\n\\n  var packetType = PACKET_TYPES_REVERSE[type];\\n\\n  if (!packetType) {\\n    return ERROR_PACKET;\\n  }\\n\\n  return encodedPacket.length > 1 ? {\\n    type: PACKET_TYPES_REVERSE[type],\\n    data: encodedPacket.substring(1)\\n  } : {\\n    type: PACKET_TYPES_REVERSE[type]\\n  };\\n};\\n\\nvar decodeBase64Packet = function decodeBase64Packet(data, binaryType) {\\n  if (base64decoder) {\\n    var decoded = base64decoder.decode(data);\\n    return mapBinary(decoded, binaryType);\\n  } else {\\n    return {\\n      base64: true,\\n      data: data\\n    }; // fallback for old browsers\\n  }\\n};\\n\\nvar mapBinary = function mapBinary(data, binaryType) {\\n  switch (binaryType) {\\n    case \\\"blob\\\":\\n      return data instanceof ArrayBuffer ? new Blob([data]) : data;\\n\\n    case \\\"arraybuffer\\\":\\n    default:\\n      return data;\\n    // assuming the data is already an ArrayBuffer\\n  }\\n};\\n\\nmodule.exports = decodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/decodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/encodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/encodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES = _require.PACKET_TYPES;\\n\\nvar withNativeBlob = typeof Blob === \\\"function\\\" || typeof Blob !== \\\"undefined\\\" && Object.prototype.toString.call(Blob) === \\\"[object BlobConstructor]\\\";\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\"; // ArrayBuffer.isView method is not defined in IE10\\n\\nvar isView = function isView(obj) {\\n  return typeof ArrayBuffer.isView === \\\"function\\\" ? ArrayBuffer.isView(obj) : obj && obj.buffer instanceof ArrayBuffer;\\n};\\n\\nvar encodePacket = function encodePacket(_ref, supportsBinary, callback) {\\n  var type = _ref.type,\\n      data = _ref.data;\\n\\n  if (withNativeBlob && data instanceof Blob) {\\n    if (supportsBinary) {\\n      return callback(data);\\n    } else {\\n      return encodeBlobAsBase64(data, callback);\\n    }\\n  } else if (withNativeArrayBuffer && (data instanceof ArrayBuffer || isView(data))) {\\n    if (supportsBinary) {\\n      return callback(data instanceof ArrayBuffer ? data : data.buffer);\\n    } else {\\n      return encodeBlobAsBase64(new Blob([data]), callback);\\n    }\\n  } // plain string\\n\\n\\n  return callback(PACKET_TYPES[type] + (data || \\\"\\\"));\\n};\\n\\nvar encodeBlobAsBase64 = function encodeBlobAsBase64(data, callback) {\\n  var fileReader = new FileReader();\\n\\n  fileReader.onload = function () {\\n    var content = fileReader.result.split(\\\",\\\")[1];\\n    callback(\\\"b\\\" + content);\\n  };\\n\\n  return fileReader.readAsDataURL(data);\\n};\\n\\nmodule.exports = encodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/encodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/index.js\":\n/*!****************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/index.js ***!\n  \\****************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var encodePacket = __webpack_require__(/*! ./encodePacket */ \\\"./node_modules/engine.io-parser/lib/encodePacket.browser.js\\\");\\n\\nvar decodePacket = __webpack_require__(/*! ./decodePacket */ \\\"./node_modules/engine.io-parser/lib/decodePacket.browser.js\\\");\\n\\nvar SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text\\n\\nvar encodePayload = function encodePayload(packets, callback) {\\n  // some packets may be added to the array while encoding, so the initial length must be saved\\n  var length = packets.length;\\n  var encodedPackets = new Array(length);\\n  var count = 0;\\n  packets.forEach(function (packet, i) {\\n    // force base64 encoding for binary packets\\n    encodePacket(packet, false, function (encodedPacket) {\\n      encodedPackets[i] = encodedPacket;\\n\\n      if (++count === length) {\\n        callback(encodedPackets.join(SEPARATOR));\\n      }\\n    });\\n  });\\n};\\n\\nvar decodePayload = function decodePayload(encodedPayload, binaryType) {\\n  var encodedPackets = encodedPayload.split(SEPARATOR);\\n  var packets = [];\\n\\n  for (var i = 0; i < encodedPackets.length; i++) {\\n    var decodedPacket = decodePacket(encodedPackets[i], binaryType);\\n    packets.push(decodedPacket);\\n\\n    if (decodedPacket.type === \\\"error\\\") {\\n      break;\\n    }\\n  }\\n\\n  return packets;\\n};\\n\\nmodule.exports = {\\n  protocol: 4,\\n  encodePacket: encodePacket,\\n  encodePayload: encodePayload,\\n  decodePacket: decodePacket,\\n  decodePayload: decodePayload\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/has-cors/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/has-cors/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Module exports.\\n *\\n * Logic borrowed from Modernizr:\\n *\\n *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js\\n */\\ntry {\\n  module.exports = typeof XMLHttpRequest !== 'undefined' && 'withCredentials' in new XMLHttpRequest();\\n} catch (err) {\\n  // if XMLHttp support is disabled in IE then it will throw\\n  // when trying to create\\n  module.exports = false;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/has-cors/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/ms/index.js\":\n/*!**********************************!*\\\n  !*** ./node_modules/ms/index.js ***!\n  \\**********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/**\\n * Helpers.\\n */\\nvar s = 1000;\\nvar m = s * 60;\\nvar h = m * 60;\\nvar d = h * 24;\\nvar w = d * 7;\\nvar y = d * 365.25;\\n/**\\n * Parse or format the given `val`.\\n *\\n * Options:\\n *\\n *  - `long` verbose formatting [false]\\n *\\n * @param {String|Number} val\\n * @param {Object} [options]\\n * @throws {Error} throw an error if val is not a non-empty string or a number\\n * @return {String|Number}\\n * @api public\\n */\\n\\nmodule.exports = function (val, options) {\\n  options = options || {};\\n\\n  var type = _typeof(val);\\n\\n  if (type === 'string' && val.length > 0) {\\n    return parse(val);\\n  } else if (type === 'number' && isFinite(val)) {\\n    return options[\\\"long\\\"] ? fmtLong(val) : fmtShort(val);\\n  }\\n\\n  throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val));\\n};\\n/**\\n * Parse the given `str` and return milliseconds.\\n *\\n * @param {String} str\\n * @return {Number}\\n * @api private\\n */\\n\\n\\nfunction parse(str) {\\n  str = String(str);\\n\\n  if (str.length > 100) {\\n    return;\\n  }\\n\\n  var match = /^(-?(?:\\\\d+)?\\\\.?\\\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);\\n\\n  if (!match) {\\n    return;\\n  }\\n\\n  var n = parseFloat(match[1]);\\n  var type = (match[2] || 'ms').toLowerCase();\\n\\n  switch (type) {\\n    case 'years':\\n    case 'year':\\n    case 'yrs':\\n    case 'yr':\\n    case 'y':\\n      return n * y;\\n\\n    case 'weeks':\\n    case 'week':\\n    case 'w':\\n      return n * w;\\n\\n    case 'days':\\n    case 'day':\\n    case 'd':\\n      return n * d;\\n\\n    case 'hours':\\n    case 'hour':\\n    case 'hrs':\\n    case 'hr':\\n    case 'h':\\n      return n * h;\\n\\n    case 'minutes':\\n    case 'minute':\\n    case 'mins':\\n    case 'min':\\n    case 'm':\\n      return n * m;\\n\\n    case 'seconds':\\n    case 'second':\\n    case 'secs':\\n    case 'sec':\\n    case 's':\\n      return n * s;\\n\\n    case 'milliseconds':\\n    case 'millisecond':\\n    case 'msecs':\\n    case 'msec':\\n    case 'ms':\\n      return n;\\n\\n    default:\\n      return undefined;\\n  }\\n}\\n/**\\n * Short format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtShort(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return Math.round(ms / d) + 'd';\\n  }\\n\\n  if (msAbs >= h) {\\n    return Math.round(ms / h) + 'h';\\n  }\\n\\n  if (msAbs >= m) {\\n    return Math.round(ms / m) + 'm';\\n  }\\n\\n  if (msAbs >= s) {\\n    return Math.round(ms / s) + 's';\\n  }\\n\\n  return ms + 'ms';\\n}\\n/**\\n * Long format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtLong(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return plural(ms, msAbs, d, 'day');\\n  }\\n\\n  if (msAbs >= h) {\\n    return plural(ms, msAbs, h, 'hour');\\n  }\\n\\n  if (msAbs >= m) {\\n    return plural(ms, msAbs, m, 'minute');\\n  }\\n\\n  if (msAbs >= s) {\\n    return plural(ms, msAbs, s, 'second');\\n  }\\n\\n  return ms + ' ms';\\n}\\n/**\\n * Pluralization helper.\\n */\\n\\n\\nfunction plural(ms, msAbs, n, name) {\\n  var isPlural = msAbs >= n * 1.5;\\n  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/ms/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseqs/index.js\":\n/*!***************************************!*\\\n  !*** ./node_modules/parseqs/index.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Compiles a querystring\\n * Returns string representation of the object\\n *\\n * @param {Object}\\n * @api private\\n */\\nexports.encode = function (obj) {\\n  var str = '';\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      if (str.length) str += '&';\\n      str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);\\n    }\\n  }\\n\\n  return str;\\n};\\n/**\\n * Parses a simple querystring into an object\\n *\\n * @param {String} qs\\n * @api private\\n */\\n\\n\\nexports.decode = function (qs) {\\n  var qry = {};\\n  var pairs = qs.split('&');\\n\\n  for (var i = 0, l = pairs.length; i < l; i++) {\\n    var pair = pairs[i].split('=');\\n    qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);\\n  }\\n\\n  return qry;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/parseqs/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseuri/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/parseuri/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Parses an URI\\n *\\n * @author Steven Levithan <stevenlevithan.com> (MIT license)\\n * @api private\\n */\\nvar re = /^(?:(?![^:@]+:[^:@\\\\/]*@)(http|https|ws|wss):\\\\/\\\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\\\/?#]*)(?::(\\\\d*))?)(((\\\\/(?:[^?#](?![^?#\\\\/]*\\\\.[^?#\\\\/.]+(?:[?#]|$)))*\\\\/?)?([^?#\\\\/]*))(?:\\\\?([^#]*))?(?:#(.*))?)/;\\nvar parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'];\\n\\nmodule.exports = function parseuri(str) {\\n  var src = str,\\n      b = str.indexOf('['),\\n      e = str.indexOf(']');\\n\\n  if (b != -1 && e != -1) {\\n    str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);\\n  }\\n\\n  var m = re.exec(str || ''),\\n      uri = {},\\n      i = 14;\\n\\n  while (i--) {\\n    uri[parts[i]] = m[i] || '';\\n  }\\n\\n  if (b != -1 && e != -1) {\\n    uri.source = src;\\n    uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');\\n    uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');\\n    uri.ipv6uri = true;\\n  }\\n\\n  uri.pathNames = pathNames(uri, uri['path']);\\n  uri.queryKey = queryKey(uri, uri['query']);\\n  return uri;\\n};\\n\\nfunction pathNames(obj, path) {\\n  var regx = /\\\\/{2,9}/g,\\n      names = path.replace(regx, \\\"/\\\").split(\\\"/\\\");\\n\\n  if (path.substr(0, 1) == '/' || path.length === 0) {\\n    names.splice(0, 1);\\n  }\\n\\n  if (path.substr(path.length - 1, 1) == '/') {\\n    names.splice(names.length - 1, 1);\\n  }\\n\\n  return names;\\n}\\n\\nfunction queryKey(uri, query) {\\n  var data = {};\\n  query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {\\n    if ($1) {\\n      data[$1] = $2;\\n    }\\n  });\\n  return data;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/parseuri/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/process/browser.js\":\n/*!*****************************************!*\\\n  !*** ./node_modules/process/browser.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"// shim for using process in browser\\nvar process = module.exports = {}; // cached from whatever global is present so that test runners that stub it\\n// don't break things.  But we need to wrap it in a try catch in case it is\\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\\n// function because try/catches deoptimize in certain engines.\\n\\nvar cachedSetTimeout;\\nvar cachedClearTimeout;\\n\\nfunction defaultSetTimout() {\\n  throw new Error('setTimeout has not been defined');\\n}\\n\\nfunction defaultClearTimeout() {\\n  throw new Error('clearTimeout has not been defined');\\n}\\n\\n(function () {\\n  try {\\n    if (typeof setTimeout === 'function') {\\n      cachedSetTimeout = setTimeout;\\n    } else {\\n      cachedSetTimeout = defaultSetTimout;\\n    }\\n  } catch (e) {\\n    cachedSetTimeout = defaultSetTimout;\\n  }\\n\\n  try {\\n    if (typeof clearTimeout === 'function') {\\n      cachedClearTimeout = clearTimeout;\\n    } else {\\n      cachedClearTimeout = defaultClearTimeout;\\n    }\\n  } catch (e) {\\n    cachedClearTimeout = defaultClearTimeout;\\n  }\\n})();\\n\\nfunction runTimeout(fun) {\\n  if (cachedSetTimeout === setTimeout) {\\n    //normal enviroments in sane situations\\n    return setTimeout(fun, 0);\\n  } // if setTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\\n    cachedSetTimeout = setTimeout;\\n    return setTimeout(fun, 0);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedSetTimeout(fun, 0);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\\n      return cachedSetTimeout.call(null, fun, 0);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\\n      return cachedSetTimeout.call(this, fun, 0);\\n    }\\n  }\\n}\\n\\nfunction runClearTimeout(marker) {\\n  if (cachedClearTimeout === clearTimeout) {\\n    //normal enviroments in sane situations\\n    return clearTimeout(marker);\\n  } // if clearTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\\n    cachedClearTimeout = clearTimeout;\\n    return clearTimeout(marker);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedClearTimeout(marker);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\\n      return cachedClearTimeout.call(null, marker);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\\n      // Some versions of I.E. have different rules for clearTimeout vs setTimeout\\n      return cachedClearTimeout.call(this, marker);\\n    }\\n  }\\n}\\n\\nvar queue = [];\\nvar draining = false;\\nvar currentQueue;\\nvar queueIndex = -1;\\n\\nfunction cleanUpNextTick() {\\n  if (!draining || !currentQueue) {\\n    return;\\n  }\\n\\n  draining = false;\\n\\n  if (currentQueue.length) {\\n    queue = currentQueue.concat(queue);\\n  } else {\\n    queueIndex = -1;\\n  }\\n\\n  if (queue.length) {\\n    drainQueue();\\n  }\\n}\\n\\nfunction drainQueue() {\\n  if (draining) {\\n    return;\\n  }\\n\\n  var timeout = runTimeout(cleanUpNextTick);\\n  draining = true;\\n  var len = queue.length;\\n\\n  while (len) {\\n    currentQueue = queue;\\n    queue = [];\\n\\n    while (++queueIndex < len) {\\n      if (currentQueue) {\\n        currentQueue[queueIndex].run();\\n      }\\n    }\\n\\n    queueIndex = -1;\\n    len = queue.length;\\n  }\\n\\n  currentQueue = null;\\n  draining = false;\\n  runClearTimeout(timeout);\\n}\\n\\nprocess.nextTick = function (fun) {\\n  var args = new Array(arguments.length - 1);\\n\\n  if (arguments.length > 1) {\\n    for (var i = 1; i < arguments.length; i++) {\\n      args[i - 1] = arguments[i];\\n    }\\n  }\\n\\n  queue.push(new Item(fun, args));\\n\\n  if (queue.length === 1 && !draining) {\\n    runTimeout(drainQueue);\\n  }\\n}; // v8 likes predictible objects\\n\\n\\nfunction Item(fun, array) {\\n  this.fun = fun;\\n  this.array = array;\\n}\\n\\nItem.prototype.run = function () {\\n  this.fun.apply(null, this.array);\\n};\\n\\nprocess.title = 'browser';\\nprocess.browser = true;\\nprocess.env = {};\\nprocess.argv = [];\\nprocess.version = ''; // empty string to avoid regexp issues\\n\\nprocess.versions = {};\\n\\nfunction noop() {}\\n\\nprocess.on = noop;\\nprocess.addListener = noop;\\nprocess.once = noop;\\nprocess.off = noop;\\nprocess.removeListener = noop;\\nprocess.removeAllListeners = noop;\\nprocess.emit = noop;\\nprocess.prependListener = noop;\\nprocess.prependOnceListener = noop;\\n\\nprocess.listeners = function (name) {\\n  return [];\\n};\\n\\nprocess.binding = function (name) {\\n  throw new Error('process.binding is not supported');\\n};\\n\\nprocess.cwd = function () {\\n  return '/';\\n};\\n\\nprocess.chdir = function (dir) {\\n  throw new Error('process.chdir is not supported');\\n};\\n\\nprocess.umask = function () {\\n  return 0;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/process/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/yeast/index.js\":\n/*!*************************************!*\\\n  !*** ./node_modules/yeast/index.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\neval(\"\\n\\nvar alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''),\\n    length = 64,\\n    map = {},\\n    seed = 0,\\n    i = 0,\\n    prev;\\n/**\\n * Return a string representing the specified number.\\n *\\n * @param {Number} num The number to convert.\\n * @returns {String} The string representation of the number.\\n * @api public\\n */\\n\\nfunction encode(num) {\\n  var encoded = '';\\n\\n  do {\\n    encoded = alphabet[num % length] + encoded;\\n    num = Math.floor(num / length);\\n  } while (num > 0);\\n\\n  return encoded;\\n}\\n/**\\n * Return the integer value specified by the given string.\\n *\\n * @param {String} str The string to convert.\\n * @returns {Number} The integer value represented by the string.\\n * @api public\\n */\\n\\n\\nfunction decode(str) {\\n  var decoded = 0;\\n\\n  for (i = 0; i < str.length; i++) {\\n    decoded = decoded * length + map[str.charAt(i)];\\n  }\\n\\n  return decoded;\\n}\\n/**\\n * Yeast: A tiny growing id generator.\\n *\\n * @returns {String} A unique id.\\n * @api public\\n */\\n\\n\\nfunction yeast() {\\n  var now = encode(+new Date());\\n  if (now !== prev) return seed = 0, prev = now;\\n  return now + '.' + encode(seed++);\\n} //\\n// Map each character to its index.\\n//\\n\\n\\nfor (; i < length; i++) {\\n  map[alphabet[i]] = i;\\n} //\\n// Expose the `yeast`, `encode` and `decode` functions.\\n//\\n\\n\\nyeast.encode = encode;\\nyeast.decode = decode;\\nmodule.exports = yeast;\\n\\n//# sourceURL=webpack://eio/./node_modules/yeast/index.js?\");\n\n/***/ })\n\n/******/ });\n});"
  },
  {
    "path": "examples/server/asgi/static/style.css",
    "content": "body { margin: 0; padding: 0; font-family: Helvetica Neue; }\nh1 { margin: 100px 100px 10px; }\nh2 { color: #999; margin: 0 100px 30px; font-weight: normal; }\n#latency { color: red; }\n"
  },
  {
    "path": "examples/server/javascript/README.md",
    "content": "# eio-latency\n\nThis is a JavaScript example intended to be used when testing interoperability with Python.\n\n## Running\n\nFirst, execute:\n\n```\n$ npm install\n```\n\nThen execute the server:\n\n```\n$ node index\n```\n\nAnd point your browser to `localhost:5000` (if PORT is set in your environment, then it will use that instead).\n"
  },
  {
    "path": "examples/server/javascript/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>EIO Latency</title>\n    <link rel=\"stylesheet\" href=\"/style.css\" />\n  </head>\n  <body>\n    <h1>EIO Latency <span id=\"latency\"></span></h1>\n    <h2 id=\"transport\">(connecting)</h2>\n    <canvas id=\"chart\" height=\"200\"></canvas>\n\n    <script src=\"/engine.io.min.js\"></script>\n    <script src=\"/index.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/server/javascript/index.js",
    "content": "/**\n * Module dependencies.\n */\n\nconst express = require('express');\nconst app = express();\nconst server = require('http').createServer(app);\nconst enchilada = require('enchilada');\nconst io = require('engine.io').attach(server);\n\napp.use(enchilada({\n  src: __dirname + '/public',\n  debug: true\n}));\napp.use(express.static(__dirname + '/public'));\napp.get('/', (req, res) => {\n  res.sendFile(__dirname + '/index.html');\n});\n\napp.get('/engine.io.min.js', (req, res) => {\n  res.sendFile(require.resolve('engine.io-client/dist/engine.io.min.js'));\n});\n\nio.on('connection', (socket) => {\n  socket.on('message', () => {\n    socket.send('pong');\n  });\n});\n\nconst port = process.env.PORT || 5000;\nserver.listen(port, () => {\n  console.log('\\x1B[96mlistening on localhost:' + port + ' \\x1B[39m');\n});\n"
  },
  {
    "path": "examples/server/javascript/package.json",
    "content": "{\n  \"name\": \"eio-latency\",\n  \"version\": \"0.1.0\",\n  \"dependencies\": {\n    \"enchilada\": \"0.13.0\",\n    \"engine.io\": \"^6.6.2\",\n    \"engine.io-client\": \"^6.6.0\",\n    \"express\": \"^4.22.1\",\n    \"smoothie\": \"1.19.0\"\n  }\n}\n"
  },
  {
    "path": "examples/server/javascript/public/index.js",
    "content": "/**\n * Module dependencies.\n */\n\nconst SmoothieChart = require('smoothie').SmoothieChart;\nconst TimeSeries = require('smoothie').TimeSeries;\n\n// helper\n\nfunction $ (id) { return document.getElementById(id); }\n\n// chart\n\nlet smoothie;\nlet time;\n\nfunction render () {\n  if (smoothie) smoothie.stop();\n  $('chart').width = document.body.clientWidth;\n  smoothie = new SmoothieChart();\n  smoothie.streamTo($('chart'), 1000);\n  time = new TimeSeries();\n  smoothie.addTimeSeries(time, {\n    strokeStyle: 'rgb(255, 0, 0)',\n    fillStyle: 'rgba(255, 0, 0, 0.4)',\n    lineWidth: 2\n  });\n}\n\n// socket\nconst socket = new eio.Socket();\nlet last;\nfunction send () {\n  last = new Date();\n  socket.send('ping');\n  $('transport').innerHTML = socket.transport.name;\n}\n\nsocket.on('open', () => {\n  if ($('chart').getContext) {\n    render();\n    window.onresize = render;\n  }\n  send();\n});\n\nsocket.on('close', () => {\n  if (smoothie) smoothie.stop();\n  $('transport').innerHTML = '(disconnected)';\n});\n\nsocket.on('message', () => {\n  const latency = new Date() - last;\n  $('latency').innerHTML = latency + 'ms';\n  if (time) time.append(+new Date(), latency);\n  setTimeout(send, 100);\n});\n"
  },
  {
    "path": "examples/server/javascript/public/style.css",
    "content": "body { margin: 0; padding: 0; font-family: Helvetica Neue; }\nh1 { margin: 100px 100px 10px; }\nh2 { color: #999; margin: 0 100px 30px; font-weight: normal; }\n#latency { color: red; }\n"
  },
  {
    "path": "examples/server/sanic/README.rst",
    "content": "Engine.IO Examples\n==================\n\nThis directory contains example Engine.IO applications that are compatible\nwith asyncio and the sanic framework. These applications require Python 3.5\nor later.\n\nsimple.py\n---------\n\nA basic application in which the client sends messages to the server and the\nserver responds.\n\nlatency.py\n----------\n\nA port of the latency application included in the official Engine.IO\nJavascript server. In this application the client sends *ping* messages to\nthe server, which are responded by the server with a *pong*. The client\nmeasures the time it takes for each of these exchanges and plots these in real\ntime to the page.\n\nThis is an ideal application to measure the performance of the different\nasynchronous modes supported by the Engine.IO server.\n\nRunning the Examples\n--------------------\n\nTo run these examples, create a virtual environment, install the requirements\nand then run::\n\n    $ python simple.py\n\nor::\n\n    $ python latency.py\n\nYou can then access the application from your web browser at\n``http://localhost:8000``.\n"
  },
  {
    "path": "examples/server/sanic/latency.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>EIO Latency</title>\n    <link rel=\"stylesheet\" href=\"/static/style.css\" />\n  </head>\n  <body>\n    <h1>EIO Latency <span id=\"latency\"></span></h1>\n    <h2 id=\"transport\">(connecting)</h2>\n    <canvas id=\"chart\" height=\"200\"></canvas>\n\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/smoothie/1.27.0/smoothie.js\"></script>\n    <script src=\"/static/engine.io.js\"></script>\n    <script>\n      // socket\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      var char = $('chart').get(0);\n      socket.on('open', function() {\n          if (chart.getContext) {\n              render();\n              window.onresize = render;\n          }\n          send();\n      });\n      socket.on('message', function(data) {\n          var latency = new Date - last;\n          $('#latency').text(latency + 'ms');\n          if (time)\n              time.append(+new Date, latency);\n          setTimeout(send, 100);\n      });\n      socket.on('close', function() {\n          if (smoothie)\n              smoothie.stop();\n          $('#transport').text('(disconnected)');\n      });\n\n      var last;\n      function send() {\n          last = new Date;\n          socket.send('ping');\n          $('#transport').text(socket.transport.name);\n      }\n\n      // chart\n      var smoothie;\n      var time;\n      function render() {\n          if (smoothie)\n              smoothie.stop();\n          chart.width = document.body.clientWidth;\n          smoothie = new SmoothieChart();\n          smoothie.streamTo(chart, 1000);\n          time = new TimeSeries();\n          smoothie.addTimeSeries(time, {\n              strokeStyle: 'rgb(255, 0, 0)',\n              fillStyle: 'rgba(255, 0, 0, 0.4)',\n              lineWidth: 2\n          });\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/server/sanic/latency.py",
    "content": "from sanic import Sanic\nfrom sanic.response import html\n\nimport engineio\n\neio = engineio.AsyncServer(async_mode='sanic')\napp = Sanic(name='latency')\neio.attach(app)\n\n\n@app.route('/')\nasync def index(request):\n    with open('latency.html') as f:\n        return html(f.read())\n\n\n@eio.on('message')\nasync def message(sid, data):\n    await eio.send(sid, 'pong')\n\n\napp.static('/static', './static')\n\n\nif __name__ == '__main__':\n    app.run()\n"
  },
  {
    "path": "examples/server/sanic/requirements.txt",
    "content": "aiofiles==0.8.0\nhttptools==0.3.0\nmultidict==5.2.0\nsanic==21.12.2\nsanic-routing==0.7.2\nujson==5.4.0\nuvloop==0.16.0\nwebsockets==10.1\n"
  },
  {
    "path": "examples/server/sanic/simple.html",
    "content": "<html>\n<head>\n<script src=\"/static/engine.io.js\"></script>\n<script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n<script>\n  $(document).ready(function() {\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      socket.on('open', function() {\n          $('#log').append(\"Connected to server.<br>\");\n      });\n      socket.on('message', function(data) {\n          $('#log').append(\"Server says: \" + data + \"<br>\");\n      });\n      socket.on('close', function() {\n          $('#log').append(\"Server closed the connection.<br>\");\n      });\n      window.setInterval(function() {\n          $('#log').append(\"Sending message to server...<br>\");\n          socket.send('hello from client side!');\n      }, 5000);\n  });\n</script>\n</head>\n<body>\n<h1>python-engineio example application</h1>\n<p id=\"log\"></p>\n</body>\n</html>\n"
  },
  {
    "path": "examples/server/sanic/simple.py",
    "content": "from sanic import Sanic\nfrom sanic.response import html\n\nimport engineio\n\neio = engineio.AsyncServer(async_mode='sanic')\napp = Sanic(name='simple')\neio.attach(app)\n\n\n@app.route('/')\nasync def index(request):\n    with open('simple.html') as f:\n        return html(f.read())\n\n\n@eio.on('connect')\ndef connect(sid, environ):\n    print(\"connect \", sid)\n\n\n@eio.on('message')\nasync def message(sid, data):\n    print('message from', sid, data)\n    await eio.send(sid, 'Thank you for your message!')\n\n\n@eio.on('disconnect')\ndef disconnect(sid, reason):\n    print('disconnect ', sid, reason)\n\n\napp.static('/static', './static')\n\n\nif __name__ == '__main__':\n    app.run()\n"
  },
  {
    "path": "examples/server/sanic/static/engine.io.js",
    "content": "/*!\n * Engine.IO v4.0.4\n * (c) 2014-2020 Guillermo Rauch\n * Released under the MIT License.\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"eio\"] = factory();\n\telse\n\t\troot[\"eio\"] = factory();\n})((() => {\n      if (typeof self !== 'undefined') {\n          return self;\n      } else if (typeof window !== 'undefined') {\n          return window;\n      } else if (typeof global !== 'undefined') {\n          return global;\n      } else {\n          return Function('return this')();\n      }\n    })(), function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./lib/index.js\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./lib/globalThis.browser.js\":\n/*!***********************************!*\\\n  !*** ./lib/globalThis.browser.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports = function () {\\n  if (typeof self !== \\\"undefined\\\") {\\n    return self;\\n  } else if (typeof window !== \\\"undefined\\\") {\\n    return window;\\n  } else {\\n    return Function(\\\"return this\\\")();\\n  }\\n}();\\n\\n//# sourceURL=webpack://eio/./lib/globalThis.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/index.js\":\n/*!**********************!*\\\n  !*** ./lib/index.js ***!\n  \\**********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var Socket = __webpack_require__(/*! ./socket */ \\\"./lib/socket.js\\\");\\n\\nmodule.exports = function (uri, opts) {\\n  return new Socket(uri, opts);\\n};\\n/**\\n * Expose deps for legacy compatibility\\n * and standalone browser access.\\n */\\n\\n\\nmodule.exports.Socket = Socket;\\nmodule.exports.protocol = Socket.protocol; // this is an int\\n\\nmodule.exports.Transport = __webpack_require__(/*! ./transport */ \\\"./lib/transport.js\\\");\\nmodule.exports.transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\nmodule.exports.parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\n//# sourceURL=webpack://eio/./lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/socket.js\":\n/*!***********************!*\\\n  !*** ./lib/socket.js ***!\n  \\***********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:socket\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseuri = __webpack_require__(/*! parseuri */ \\\"./node_modules/parseuri/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar Socket =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Socket, _Emitter);\\n\\n  /**\\n   * Socket constructor.\\n   *\\n   * @param {String|Object} uri or options\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Socket(uri) {\\n    var _this;\\n\\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\\n\\n    _classCallCheck(this, Socket);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Socket).call(this));\\n\\n    if (uri && \\\"object\\\" === _typeof(uri)) {\\n      opts = uri;\\n      uri = null;\\n    }\\n\\n    if (uri) {\\n      uri = parseuri(uri);\\n      opts.hostname = uri.host;\\n      opts.secure = uri.protocol === \\\"https\\\" || uri.protocol === \\\"wss\\\";\\n      opts.port = uri.port;\\n      if (uri.query) opts.query = uri.query;\\n    } else if (opts.host) {\\n      opts.hostname = parseuri(opts.host).host;\\n    }\\n\\n    _this.secure = null != opts.secure ? opts.secure : typeof location !== \\\"undefined\\\" && \\\"https:\\\" === location.protocol;\\n\\n    if (opts.hostname && !opts.port) {\\n      // if no port is specified manually, use the protocol default\\n      opts.port = _this.secure ? \\\"443\\\" : \\\"80\\\";\\n    }\\n\\n    _this.hostname = opts.hostname || (typeof location !== \\\"undefined\\\" ? location.hostname : \\\"localhost\\\");\\n    _this.port = opts.port || (typeof location !== \\\"undefined\\\" && location.port ? location.port : _this.secure ? 443 : 80);\\n    _this.transports = opts.transports || [\\\"polling\\\", \\\"websocket\\\"];\\n    _this.readyState = \\\"\\\";\\n    _this.writeBuffer = [];\\n    _this.prevBufferLen = 0;\\n    _this.opts = _extends({\\n      path: \\\"/engine.io\\\",\\n      agent: false,\\n      withCredentials: false,\\n      upgrade: true,\\n      jsonp: true,\\n      timestampParam: \\\"t\\\",\\n      policyPort: 843,\\n      rememberUpgrade: false,\\n      rejectUnauthorized: true,\\n      perMessageDeflate: {\\n        threshold: 1024\\n      },\\n      transportOptions: {}\\n    }, opts);\\n    _this.opts.path = _this.opts.path.replace(/\\\\/$/, \\\"\\\") + \\\"/\\\";\\n\\n    if (typeof _this.opts.query === \\\"string\\\") {\\n      _this.opts.query = parseqs.decode(_this.opts.query);\\n    } // set on handshake\\n\\n\\n    _this.id = null;\\n    _this.upgrades = null;\\n    _this.pingInterval = null;\\n    _this.pingTimeout = null; // set on heartbeat\\n\\n    _this.pingTimeoutTimer = null;\\n\\n    _this.open();\\n\\n    return _this;\\n  }\\n  /**\\n   * Creates transport of the given type.\\n   *\\n   * @param {String} transport name\\n   * @return {Transport}\\n   * @api private\\n   */\\n\\n\\n  _createClass(Socket, [{\\n    key: \\\"createTransport\\\",\\n    value: function createTransport(name) {\\n      debug('creating transport \\\"%s\\\"', name);\\n      var query = clone(this.opts.query); // append engine.io protocol identifier\\n\\n      query.EIO = parser.protocol; // transport name\\n\\n      query.transport = name; // session id if we already have one\\n\\n      if (this.id) query.sid = this.id;\\n\\n      var opts = _extends({}, this.opts.transportOptions[name], this.opts, {\\n        query: query,\\n        socket: this,\\n        hostname: this.hostname,\\n        secure: this.secure,\\n        port: this.port\\n      });\\n\\n      debug(\\\"options: %j\\\", opts);\\n      return new transports[name](opts);\\n    }\\n    /**\\n     * Initializes transport to use and starts probe.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      var transport;\\n\\n      if (this.opts.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf(\\\"websocket\\\") !== -1) {\\n        transport = \\\"websocket\\\";\\n      } else if (0 === this.transports.length) {\\n        // Emit error on next tick so it can be listened to\\n        var self = this;\\n        setTimeout(function () {\\n          self.emit(\\\"error\\\", \\\"No transports available\\\");\\n        }, 0);\\n        return;\\n      } else {\\n        transport = this.transports[0];\\n      }\\n\\n      this.readyState = \\\"opening\\\"; // Retry with the next transport if the transport is disabled (jsonp: false)\\n\\n      try {\\n        transport = this.createTransport(transport);\\n      } catch (e) {\\n        debug(\\\"error while creating transport: %s\\\", e);\\n        this.transports.shift();\\n        this.open();\\n        return;\\n      }\\n\\n      transport.open();\\n      this.setTransport(transport);\\n    }\\n    /**\\n     * Sets the current transport. Disables the existing one (if any).\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"setTransport\\\",\\n    value: function setTransport(transport) {\\n      debug(\\\"setting transport %s\\\", transport.name);\\n      var self = this;\\n\\n      if (this.transport) {\\n        debug(\\\"clearing existing transport %s\\\", this.transport.name);\\n        this.transport.removeAllListeners();\\n      } // set up transport\\n\\n\\n      this.transport = transport; // set up transport listeners\\n\\n      transport.on(\\\"drain\\\", function () {\\n        self.onDrain();\\n      }).on(\\\"packet\\\", function (packet) {\\n        self.onPacket(packet);\\n      }).on(\\\"error\\\", function (e) {\\n        self.onError(e);\\n      }).on(\\\"close\\\", function () {\\n        self.onClose(\\\"transport close\\\");\\n      });\\n    }\\n    /**\\n     * Probes a transport.\\n     *\\n     * @param {String} transport name\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"probe\\\",\\n    value: function probe(name) {\\n      debug('probing transport \\\"%s\\\"', name);\\n      var transport = this.createTransport(name, {\\n        probe: 1\\n      });\\n      var failed = false;\\n      var self = this;\\n      Socket.priorWebsocketSuccess = false;\\n\\n      function onTransportOpen() {\\n        if (self.onlyBinaryUpgrades) {\\n          var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;\\n          failed = failed || upgradeLosesBinary;\\n        }\\n\\n        if (failed) return;\\n        debug('probe transport \\\"%s\\\" opened', name);\\n        transport.send([{\\n          type: \\\"ping\\\",\\n          data: \\\"probe\\\"\\n        }]);\\n        transport.once(\\\"packet\\\", function (msg) {\\n          if (failed) return;\\n\\n          if (\\\"pong\\\" === msg.type && \\\"probe\\\" === msg.data) {\\n            debug('probe transport \\\"%s\\\" pong', name);\\n            self.upgrading = true;\\n            self.emit(\\\"upgrading\\\", transport);\\n            if (!transport) return;\\n            Socket.priorWebsocketSuccess = \\\"websocket\\\" === transport.name;\\n            debug('pausing current transport \\\"%s\\\"', self.transport.name);\\n            self.transport.pause(function () {\\n              if (failed) return;\\n              if (\\\"closed\\\" === self.readyState) return;\\n              debug(\\\"changing transport and sending upgrade packet\\\");\\n              cleanup();\\n              self.setTransport(transport);\\n              transport.send([{\\n                type: \\\"upgrade\\\"\\n              }]);\\n              self.emit(\\\"upgrade\\\", transport);\\n              transport = null;\\n              self.upgrading = false;\\n              self.flush();\\n            });\\n          } else {\\n            debug('probe transport \\\"%s\\\" failed', name);\\n            var err = new Error(\\\"probe error\\\");\\n            err.transport = transport.name;\\n            self.emit(\\\"upgradeError\\\", err);\\n          }\\n        });\\n      }\\n\\n      function freezeTransport() {\\n        if (failed) return; // Any callback called by transport should be ignored since now\\n\\n        failed = true;\\n        cleanup();\\n        transport.close();\\n        transport = null;\\n      } // Handle any error that happens while probing\\n\\n\\n      function onerror(err) {\\n        var error = new Error(\\\"probe error: \\\" + err);\\n        error.transport = transport.name;\\n        freezeTransport();\\n        debug('probe transport \\\"%s\\\" failed because of error: %s', name, err);\\n        self.emit(\\\"upgradeError\\\", error);\\n      }\\n\\n      function onTransportClose() {\\n        onerror(\\\"transport closed\\\");\\n      } // When the socket is closed while we're probing\\n\\n\\n      function onclose() {\\n        onerror(\\\"socket closed\\\");\\n      } // When the socket is upgraded while we're probing\\n\\n\\n      function onupgrade(to) {\\n        if (transport && to.name !== transport.name) {\\n          debug('\\\"%s\\\" works - aborting \\\"%s\\\"', to.name, transport.name);\\n          freezeTransport();\\n        }\\n      } // Remove all listeners on the transport and on self\\n\\n\\n      function cleanup() {\\n        transport.removeListener(\\\"open\\\", onTransportOpen);\\n        transport.removeListener(\\\"error\\\", onerror);\\n        transport.removeListener(\\\"close\\\", onTransportClose);\\n        self.removeListener(\\\"close\\\", onclose);\\n        self.removeListener(\\\"upgrading\\\", onupgrade);\\n      }\\n\\n      transport.once(\\\"open\\\", onTransportOpen);\\n      transport.once(\\\"error\\\", onerror);\\n      transport.once(\\\"close\\\", onTransportClose);\\n      this.once(\\\"close\\\", onclose);\\n      this.once(\\\"upgrading\\\", onupgrade);\\n      transport.open();\\n    }\\n    /**\\n     * Called when connection is deemed open.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      debug(\\\"socket open\\\");\\n      this.readyState = \\\"open\\\";\\n      Socket.priorWebsocketSuccess = \\\"websocket\\\" === this.transport.name;\\n      this.emit(\\\"open\\\");\\n      this.flush(); // we check for `readyState` in case an `open`\\n      // listener already closed the socket\\n\\n      if (\\\"open\\\" === this.readyState && this.opts.upgrade && this.transport.pause) {\\n        debug(\\\"starting upgrade probes\\\");\\n        var i = 0;\\n        var l = this.upgrades.length;\\n\\n        for (; i < l; i++) {\\n          this.probe(this.upgrades[i]);\\n        }\\n      }\\n    }\\n    /**\\n     * Handles a packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket receive: type \\\"%s\\\", data \\\"%s\\\"', packet.type, packet.data);\\n        this.emit(\\\"packet\\\", packet); // Socket is live - any packet counts\\n\\n        this.emit(\\\"heartbeat\\\");\\n\\n        switch (packet.type) {\\n          case \\\"open\\\":\\n            this.onHandshake(JSON.parse(packet.data));\\n            break;\\n\\n          case \\\"ping\\\":\\n            this.resetPingTimeout();\\n            this.sendPacket(\\\"pong\\\");\\n            this.emit(\\\"pong\\\");\\n            break;\\n\\n          case \\\"error\\\":\\n            var err = new Error(\\\"server error\\\");\\n            err.code = packet.data;\\n            this.onError(err);\\n            break;\\n\\n          case \\\"message\\\":\\n            this.emit(\\\"data\\\", packet.data);\\n            this.emit(\\\"message\\\", packet.data);\\n            break;\\n        }\\n      } else {\\n        debug('packet received with socket readyState \\\"%s\\\"', this.readyState);\\n      }\\n    }\\n    /**\\n     * Called upon handshake completion.\\n     *\\n     * @param {Object} handshake obj\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onHandshake\\\",\\n    value: function onHandshake(data) {\\n      this.emit(\\\"handshake\\\", data);\\n      this.id = data.sid;\\n      this.transport.query.sid = data.sid;\\n      this.upgrades = this.filterUpgrades(data.upgrades);\\n      this.pingInterval = data.pingInterval;\\n      this.pingTimeout = data.pingTimeout;\\n      this.onOpen(); // In case open handler closes socket\\n\\n      if (\\\"closed\\\" === this.readyState) return;\\n      this.resetPingTimeout();\\n    }\\n    /**\\n     * Sets and resets ping timeout timer based on server pings.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"resetPingTimeout\\\",\\n    value: function resetPingTimeout() {\\n      var _this2 = this;\\n\\n      clearTimeout(this.pingTimeoutTimer);\\n      this.pingTimeoutTimer = setTimeout(function () {\\n        _this2.onClose(\\\"ping timeout\\\");\\n      }, this.pingInterval + this.pingTimeout);\\n    }\\n    /**\\n     * Called on `drain` event\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onDrain\\\",\\n    value: function onDrain() {\\n      this.writeBuffer.splice(0, this.prevBufferLen); // setting prevBufferLen = 0 is very important\\n      // for example, when upgrading, upgrade packet is sent over,\\n      // and a nonzero prevBufferLen could cause problems on `drain`\\n\\n      this.prevBufferLen = 0;\\n\\n      if (0 === this.writeBuffer.length) {\\n        this.emit(\\\"drain\\\");\\n      } else {\\n        this.flush();\\n      }\\n    }\\n    /**\\n     * Flush write buffers.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"flush\\\",\\n    value: function flush() {\\n      if (\\\"closed\\\" !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) {\\n        debug(\\\"flushing %d packets in socket\\\", this.writeBuffer.length);\\n        this.transport.send(this.writeBuffer); // keep track of current length of writeBuffer\\n        // splice writeBuffer and callbackBuffer on `drain`\\n\\n        this.prevBufferLen = this.writeBuffer.length;\\n        this.emit(\\\"flush\\\");\\n      }\\n    }\\n    /**\\n     * Sends a message.\\n     *\\n     * @param {String} message.\\n     * @param {Function} callback function.\\n     * @param {Object} options.\\n     * @return {Socket} for chaining.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n    /**\\n     * Sends a packet.\\n     *\\n     * @param {String} packet type.\\n     * @param {String} data.\\n     * @param {Object} options.\\n     * @param {Function} callback function.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"sendPacket\\\",\\n    value: function sendPacket(type, data, options, fn) {\\n      if (\\\"function\\\" === typeof data) {\\n        fn = data;\\n        data = undefined;\\n      }\\n\\n      if (\\\"function\\\" === typeof options) {\\n        fn = options;\\n        options = null;\\n      }\\n\\n      if (\\\"closing\\\" === this.readyState || \\\"closed\\\" === this.readyState) {\\n        return;\\n      }\\n\\n      options = options || {};\\n      options.compress = false !== options.compress;\\n      var packet = {\\n        type: type,\\n        data: data,\\n        options: options\\n      };\\n      this.emit(\\\"packetCreate\\\", packet);\\n      this.writeBuffer.push(packet);\\n      if (fn) this.once(\\\"flush\\\", fn);\\n      this.flush();\\n    }\\n    /**\\n     * Closes the connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      var self = this;\\n\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.readyState = \\\"closing\\\";\\n\\n        if (this.writeBuffer.length) {\\n          this.once(\\\"drain\\\", function () {\\n            if (this.upgrading) {\\n              waitForUpgrade();\\n            } else {\\n              close();\\n            }\\n          });\\n        } else if (this.upgrading) {\\n          waitForUpgrade();\\n        } else {\\n          close();\\n        }\\n      }\\n\\n      function close() {\\n        self.onClose(\\\"forced close\\\");\\n        debug(\\\"socket closing - telling transport to close\\\");\\n        self.transport.close();\\n      }\\n\\n      function cleanupAndClose() {\\n        self.removeListener(\\\"upgrade\\\", cleanupAndClose);\\n        self.removeListener(\\\"upgradeError\\\", cleanupAndClose);\\n        close();\\n      }\\n\\n      function waitForUpgrade() {\\n        // wait for upgrade to finish since we can't send packets while pausing a transport\\n        self.once(\\\"upgrade\\\", cleanupAndClose);\\n        self.once(\\\"upgradeError\\\", cleanupAndClose);\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Called upon transport error\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      debug(\\\"socket error %j\\\", err);\\n      Socket.priorWebsocketSuccess = false;\\n      this.emit(\\\"error\\\", err);\\n      this.onClose(\\\"transport error\\\", err);\\n    }\\n    /**\\n     * Called upon transport close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose(reason, desc) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket close with reason: \\\"%s\\\"', reason);\\n        var self = this; // clear timers\\n\\n        clearTimeout(this.pingIntervalTimer);\\n        clearTimeout(this.pingTimeoutTimer); // stop event from firing again for transport\\n\\n        this.transport.removeAllListeners(\\\"close\\\"); // ensure transport won't stay open\\n\\n        this.transport.close(); // ignore further transport communication\\n\\n        this.transport.removeAllListeners(); // set ready state\\n\\n        this.readyState = \\\"closed\\\"; // clear session id\\n\\n        this.id = null; // emit close event\\n\\n        this.emit(\\\"close\\\", reason, desc); // clean buffers after, so users can still\\n        // grab the buffers on `close` event\\n\\n        self.writeBuffer = [];\\n        self.prevBufferLen = 0;\\n      }\\n    }\\n    /**\\n     * Filters upgrades, returning only those matching client transports.\\n     *\\n     * @param {Array} server upgrades\\n     * @api private\\n     *\\n     */\\n\\n  }, {\\n    key: \\\"filterUpgrades\\\",\\n    value: function filterUpgrades(upgrades) {\\n      var filteredUpgrades = [];\\n      var i = 0;\\n      var j = upgrades.length;\\n\\n      for (; i < j; i++) {\\n        if (~this.transports.indexOf(upgrades[i])) filteredUpgrades.push(upgrades[i]);\\n      }\\n\\n      return filteredUpgrades;\\n    }\\n  }]);\\n\\n  return Socket;\\n}(Emitter);\\n\\nSocket.priorWebsocketSuccess = false;\\n/**\\n * Protocol version.\\n *\\n * @api public\\n */\\n\\nSocket.protocol = parser.protocol; // this is an int\\n\\nfunction clone(obj) {\\n  var o = {};\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      o[i] = obj[i];\\n    }\\n  }\\n\\n  return o;\\n}\\n\\nmodule.exports = Socket;\\n\\n//# sourceURL=webpack://eio/./lib/socket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transport.js\":\n/*!**************************!*\\\n  !*** ./lib/transport.js ***!\n  \\**************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar Transport =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Transport, _Emitter);\\n\\n  /**\\n   * Transport abstract constructor.\\n   *\\n   * @param {Object} options.\\n   * @api private\\n   */\\n  function Transport(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, Transport);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Transport).call(this));\\n    _this.opts = opts;\\n    _this.query = opts.query;\\n    _this.readyState = \\\"\\\";\\n    _this.socket = opts.socket;\\n    return _this;\\n  }\\n  /**\\n   * Emits an error.\\n   *\\n   * @param {String} str\\n   * @return {Transport} for chaining\\n   * @api public\\n   */\\n\\n\\n  _createClass(Transport, [{\\n    key: \\\"onError\\\",\\n    value: function onError(msg, desc) {\\n      var err = new Error(msg);\\n      err.type = \\\"TransportError\\\";\\n      err.description = desc;\\n      this.emit(\\\"error\\\", err);\\n      return this;\\n    }\\n    /**\\n     * Opens the transport.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      if (\\\"closed\\\" === this.readyState || \\\"\\\" === this.readyState) {\\n        this.readyState = \\\"opening\\\";\\n        this.doOpen();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Closes the transport.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.doClose();\\n        this.onClose();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Sends multiple packets.\\n     *\\n     * @param {Array} packets\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(packets) {\\n      if (\\\"open\\\" === this.readyState) {\\n        this.write(packets);\\n      } else {\\n        throw new Error(\\\"Transport not open\\\");\\n      }\\n    }\\n    /**\\n     * Called upon open\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      this.readyState = \\\"open\\\";\\n      this.writable = true;\\n      this.emit(\\\"open\\\");\\n    }\\n    /**\\n     * Called with data.\\n     *\\n     * @param {String} data\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var packet = parser.decodePacket(data, this.socket.binaryType);\\n      this.onPacket(packet);\\n    }\\n    /**\\n     * Called with a decoded packet.\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      this.emit(\\\"packet\\\", packet);\\n    }\\n    /**\\n     * Called upon close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      this.readyState = \\\"closed\\\";\\n      this.emit(\\\"close\\\");\\n    }\\n  }]);\\n\\n  return Transport;\\n}(Emitter);\\n\\nmodule.exports = Transport;\\n\\n//# sourceURL=webpack://eio/./lib/transport.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/index.js\":\n/*!*********************************!*\\\n  !*** ./lib/transports/index.js ***!\n  \\*********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar XHR = __webpack_require__(/*! ./polling-xhr */ \\\"./lib/transports/polling-xhr.js\\\");\\n\\nvar JSONP = __webpack_require__(/*! ./polling-jsonp */ \\\"./lib/transports/polling-jsonp.js\\\");\\n\\nvar websocket = __webpack_require__(/*! ./websocket */ \\\"./lib/transports/websocket.js\\\");\\n\\nexports.polling = polling;\\nexports.websocket = websocket;\\n/**\\n * Polling transport polymorphic constructor.\\n * Decides on xhr vs jsonp based on feature detection.\\n *\\n * @api private\\n */\\n\\nfunction polling(opts) {\\n  var xhr;\\n  var xd = false;\\n  var xs = false;\\n  var jsonp = false !== opts.jsonp;\\n\\n  if (typeof location !== \\\"undefined\\\") {\\n    var isSSL = \\\"https:\\\" === location.protocol;\\n    var port = location.port; // some user agents have empty `location.port`\\n\\n    if (!port) {\\n      port = isSSL ? 443 : 80;\\n    }\\n\\n    xd = opts.hostname !== location.hostname || port !== opts.port;\\n    xs = opts.secure !== isSSL;\\n  }\\n\\n  opts.xdomain = xd;\\n  opts.xscheme = xs;\\n  xhr = new XMLHttpRequest(opts);\\n\\n  if (\\\"open\\\" in xhr && !opts.forceJSONP) {\\n    return new XHR(opts);\\n  } else {\\n    if (!jsonp) throw new Error(\\\"JSONP disabled\\\");\\n    return new JSONP(opts);\\n  }\\n}\\n\\n//# sourceURL=webpack://eio/./lib/transports/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-jsonp.js\":\n/*!*****************************************!*\\\n  !*** ./lib/transports/polling-jsonp.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _get(target, property, receiver) { if (typeof Reflect !== \\\"undefined\\\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\\n\\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar rNewline = /\\\\n/g;\\nvar rEscapedNewline = /\\\\\\\\n/g;\\n/**\\n * Global JSONP callbacks.\\n */\\n\\nvar callbacks;\\n/**\\n * Noop.\\n */\\n\\nfunction empty() {}\\n\\nvar JSONPPolling =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(JSONPPolling, _Polling);\\n\\n  /**\\n   * JSONP Polling constructor.\\n   *\\n   * @param {Object} opts.\\n   * @api public\\n   */\\n  function JSONPPolling(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, JSONPPolling);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(JSONPPolling).call(this, opts));\\n    _this.query = _this.query || {}; // define global callbacks array if not present\\n    // we do this here (lazily) to avoid unneeded global pollution\\n\\n    if (!callbacks) {\\n      // we need to consider multiple engines in the same page\\n      callbacks = globalThis.___eio = globalThis.___eio || [];\\n    } // callback identifier\\n\\n\\n    _this.index = callbacks.length; // add callback to jsonp global\\n\\n    var self = _assertThisInitialized(_this);\\n\\n    callbacks.push(function (msg) {\\n      self.onData(msg);\\n    }); // append to query string\\n\\n    _this.query.j = _this.index; // prevent spurious errors from being emitted when the window is unloaded\\n\\n    if (typeof addEventListener === \\\"function\\\") {\\n      addEventListener(\\\"beforeunload\\\", function () {\\n        if (self.script) self.script.onerror = empty;\\n      }, false);\\n    }\\n\\n    return _this;\\n  }\\n  /**\\n   * JSONP only supports binary as base64 encoded strings\\n   */\\n\\n\\n  _createClass(JSONPPolling, [{\\n    key: \\\"doClose\\\",\\n\\n    /**\\n     * Closes the socket.\\n     *\\n     * @api private\\n     */\\n    value: function doClose() {\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      if (this.form) {\\n        this.form.parentNode.removeChild(this.form);\\n        this.form = null;\\n        this.iframe = null;\\n      }\\n\\n      _get(_getPrototypeOf(JSONPPolling.prototype), \\\"doClose\\\", this).call(this);\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      var self = this;\\n      var script = document.createElement(\\\"script\\\");\\n\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      script.async = true;\\n      script.src = this.uri();\\n\\n      script.onerror = function (e) {\\n        self.onError(\\\"jsonp poll error\\\", e);\\n      };\\n\\n      var insertAt = document.getElementsByTagName(\\\"script\\\")[0];\\n\\n      if (insertAt) {\\n        insertAt.parentNode.insertBefore(script, insertAt);\\n      } else {\\n        (document.head || document.body).appendChild(script);\\n      }\\n\\n      this.script = script;\\n      var isUAgecko = \\\"undefined\\\" !== typeof navigator && /gecko/i.test(navigator.userAgent);\\n\\n      if (isUAgecko) {\\n        setTimeout(function () {\\n          var iframe = document.createElement(\\\"iframe\\\");\\n          document.body.appendChild(iframe);\\n          document.body.removeChild(iframe);\\n        }, 100);\\n      }\\n    }\\n    /**\\n     * Writes with a hidden iframe.\\n     *\\n     * @param {String} data to send\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var self = this;\\n      var iframe;\\n\\n      if (!this.form) {\\n        var form = document.createElement(\\\"form\\\");\\n        var area = document.createElement(\\\"textarea\\\");\\n        var id = this.iframeId = \\\"eio_iframe_\\\" + this.index;\\n        form.className = \\\"socketio\\\";\\n        form.style.position = \\\"absolute\\\";\\n        form.style.top = \\\"-1000px\\\";\\n        form.style.left = \\\"-1000px\\\";\\n        form.target = id;\\n        form.method = \\\"POST\\\";\\n        form.setAttribute(\\\"accept-charset\\\", \\\"utf-8\\\");\\n        area.name = \\\"d\\\";\\n        form.appendChild(area);\\n        document.body.appendChild(form);\\n        this.form = form;\\n        this.area = area;\\n      }\\n\\n      this.form.action = this.uri();\\n\\n      function complete() {\\n        initIframe();\\n        fn();\\n      }\\n\\n      function initIframe() {\\n        if (self.iframe) {\\n          try {\\n            self.form.removeChild(self.iframe);\\n          } catch (e) {\\n            self.onError(\\\"jsonp polling iframe removal error\\\", e);\\n          }\\n        }\\n\\n        try {\\n          // ie6 dynamic iframes with target=\\\"\\\" support (thanks Chris Lambacher)\\n          var html = '<iframe src=\\\"javascript:0\\\" name=\\\"' + self.iframeId + '\\\">';\\n          iframe = document.createElement(html);\\n        } catch (e) {\\n          iframe = document.createElement(\\\"iframe\\\");\\n          iframe.name = self.iframeId;\\n          iframe.src = \\\"javascript:0\\\";\\n        }\\n\\n        iframe.id = self.iframeId;\\n        self.form.appendChild(iframe);\\n        self.iframe = iframe;\\n      }\\n\\n      initIframe(); // escape \\\\n to prevent it from being converted into \\\\r\\\\n by some UAs\\n      // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side\\n\\n      data = data.replace(rEscapedNewline, \\\"\\\\\\\\\\\\n\\\");\\n      this.area.value = data.replace(rNewline, \\\"\\\\\\\\n\\\");\\n\\n      try {\\n        this.form.submit();\\n      } catch (e) {}\\n\\n      if (this.iframe.attachEvent) {\\n        this.iframe.onreadystatechange = function () {\\n          if (self.iframe.readyState === \\\"complete\\\") {\\n            complete();\\n          }\\n        };\\n      } else {\\n        this.iframe.onload = complete;\\n      }\\n    }\\n  }, {\\n    key: \\\"supportsBinary\\\",\\n    get: function get() {\\n      return false;\\n    }\\n  }]);\\n\\n  return JSONPPolling;\\n}(Polling);\\n\\nmodule.exports = JSONPPolling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-jsonp.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-xhr.js\":\n/*!***************************************!*\\\n  !*** ./lib/transports/polling-xhr.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\n/* global attachEvent */\\nvar XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling-xhr\\\");\\n/**\\n * Empty function\\n */\\n\\n\\nfunction empty() {}\\n\\nvar hasXHR2 = function () {\\n  var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\n  var xhr = new XMLHttpRequest({\\n    xdomain: false\\n  });\\n  return null != xhr.responseType;\\n}();\\n\\nvar XHR =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(XHR, _Polling);\\n\\n  /**\\n   * XHR Polling constructor.\\n   *\\n   * @param {Object} opts\\n   * @api public\\n   */\\n  function XHR(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, XHR);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(XHR).call(this, opts));\\n\\n    if (typeof location !== \\\"undefined\\\") {\\n      var isSSL = \\\"https:\\\" === location.protocol;\\n      var port = location.port; // some user agents have empty `location.port`\\n\\n      if (!port) {\\n        port = isSSL ? 443 : 80;\\n      }\\n\\n      _this.xd = typeof location !== \\\"undefined\\\" && opts.hostname !== location.hostname || port !== opts.port;\\n      _this.xs = opts.secure !== isSSL;\\n    }\\n    /**\\n     * XHR supports binary\\n     */\\n\\n\\n    var forceBase64 = opts && opts.forceBase64;\\n    _this.supportsBinary = hasXHR2 && !forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Creates a request.\\n   *\\n   * @param {String} method\\n   * @api private\\n   */\\n\\n\\n  _createClass(XHR, [{\\n    key: \\\"request\\\",\\n    value: function request() {\\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\\n\\n      _extends(opts, {\\n        xd: this.xd,\\n        xs: this.xs\\n      }, this.opts);\\n\\n      return new Request(this.uri(), opts);\\n    }\\n    /**\\n     * Sends data.\\n     *\\n     * @param {String} data to send.\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var req = this.request({\\n        method: \\\"POST\\\",\\n        data: data\\n      });\\n      var self = this;\\n      req.on(\\\"success\\\", fn);\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr post error\\\", err);\\n      });\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      debug(\\\"xhr poll\\\");\\n      var req = this.request();\\n      var self = this;\\n      req.on(\\\"data\\\", function (data) {\\n        self.onData(data);\\n      });\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr poll error\\\", err);\\n      });\\n      this.pollXhr = req;\\n    }\\n  }]);\\n\\n  return XHR;\\n}(Polling);\\n\\nvar Request =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Request, _Emitter);\\n\\n  /**\\n   * Request constructor\\n   *\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Request(uri, opts) {\\n    var _this2;\\n\\n    _classCallCheck(this, Request);\\n\\n    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Request).call(this));\\n    _this2.opts = opts;\\n    _this2.method = opts.method || \\\"GET\\\";\\n    _this2.uri = uri;\\n    _this2.async = false !== opts.async;\\n    _this2.data = undefined !== opts.data ? opts.data : null;\\n\\n    _this2.create();\\n\\n    return _this2;\\n  }\\n  /**\\n   * Creates the XHR object and sends the request.\\n   *\\n   * @api private\\n   */\\n\\n\\n  _createClass(Request, [{\\n    key: \\\"create\\\",\\n    value: function create() {\\n      var opts = pick(this.opts, \\\"agent\\\", \\\"enablesXDR\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\");\\n      opts.xdomain = !!this.opts.xd;\\n      opts.xscheme = !!this.opts.xs;\\n      var xhr = this.xhr = new XMLHttpRequest(opts);\\n      var self = this;\\n\\n      try {\\n        debug(\\\"xhr open %s: %s\\\", this.method, this.uri);\\n        xhr.open(this.method, this.uri, this.async);\\n\\n        try {\\n          if (this.opts.extraHeaders) {\\n            xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);\\n\\n            for (var i in this.opts.extraHeaders) {\\n              if (this.opts.extraHeaders.hasOwnProperty(i)) {\\n                xhr.setRequestHeader(i, this.opts.extraHeaders[i]);\\n              }\\n            }\\n          }\\n        } catch (e) {}\\n\\n        if (\\\"POST\\\" === this.method) {\\n          try {\\n            xhr.setRequestHeader(\\\"Content-type\\\", \\\"text/plain;charset=UTF-8\\\");\\n          } catch (e) {}\\n        }\\n\\n        try {\\n          xhr.setRequestHeader(\\\"Accept\\\", \\\"*/*\\\");\\n        } catch (e) {} // ie6 check\\n\\n\\n        if (\\\"withCredentials\\\" in xhr) {\\n          xhr.withCredentials = this.opts.withCredentials;\\n        }\\n\\n        if (this.opts.requestTimeout) {\\n          xhr.timeout = this.opts.requestTimeout;\\n        }\\n\\n        if (this.hasXDR()) {\\n          xhr.onload = function () {\\n            self.onLoad();\\n          };\\n\\n          xhr.onerror = function () {\\n            self.onError(xhr.responseText);\\n          };\\n        } else {\\n          xhr.onreadystatechange = function () {\\n            if (4 !== xhr.readyState) return;\\n\\n            if (200 === xhr.status || 1223 === xhr.status) {\\n              self.onLoad();\\n            } else {\\n              // make sure the `error` event handler that's user-set\\n              // does not throw in the same tick and gets caught here\\n              setTimeout(function () {\\n                self.onError(typeof xhr.status === \\\"number\\\" ? xhr.status : 0);\\n              }, 0);\\n            }\\n          };\\n        }\\n\\n        debug(\\\"xhr data %s\\\", this.data);\\n        xhr.send(this.data);\\n      } catch (e) {\\n        // Need to defer since .create() is called directly from the constructor\\n        // and thus the 'error' event can only be only bound *after* this exception\\n        // occurs.  Therefore, also, we cannot throw here at all.\\n        setTimeout(function () {\\n          self.onError(e);\\n        }, 0);\\n        return;\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        this.index = Request.requestsCount++;\\n        Request.requests[this.index] = this;\\n      }\\n    }\\n    /**\\n     * Called upon successful response.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onSuccess\\\",\\n    value: function onSuccess() {\\n      this.emit(\\\"success\\\");\\n      this.cleanup();\\n    }\\n    /**\\n     * Called if we have data.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      this.emit(\\\"data\\\", data);\\n      this.onSuccess();\\n    }\\n    /**\\n     * Called upon error.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      this.emit(\\\"error\\\", err);\\n      this.cleanup(true);\\n    }\\n    /**\\n     * Cleans up house.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"cleanup\\\",\\n    value: function cleanup(fromError) {\\n      if (\\\"undefined\\\" === typeof this.xhr || null === this.xhr) {\\n        return;\\n      } // xmlhttprequest\\n\\n\\n      if (this.hasXDR()) {\\n        this.xhr.onload = this.xhr.onerror = empty;\\n      } else {\\n        this.xhr.onreadystatechange = empty;\\n      }\\n\\n      if (fromError) {\\n        try {\\n          this.xhr.abort();\\n        } catch (e) {}\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        delete Request.requests[this.index];\\n      }\\n\\n      this.xhr = null;\\n    }\\n    /**\\n     * Called upon load.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onLoad\\\",\\n    value: function onLoad() {\\n      var data = this.xhr.responseText;\\n\\n      if (data !== null) {\\n        this.onData(data);\\n      }\\n    }\\n    /**\\n     * Check if it has XDomainRequest.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"hasXDR\\\",\\n    value: function hasXDR() {\\n      return typeof XDomainRequest !== \\\"undefined\\\" && !this.xs && this.enablesXDR;\\n    }\\n    /**\\n     * Aborts the request.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"abort\\\",\\n    value: function abort() {\\n      this.cleanup();\\n    }\\n  }]);\\n\\n  return Request;\\n}(Emitter);\\n/**\\n * Aborts pending requests when unloading the window. This is needed to prevent\\n * memory leaks (e.g. when using IE) and to ensure that no spurious error is\\n * emitted.\\n */\\n\\n\\nRequest.requestsCount = 0;\\nRequest.requests = {};\\n\\nif (typeof document !== \\\"undefined\\\") {\\n  if (typeof attachEvent === \\\"function\\\") {\\n    attachEvent(\\\"onunload\\\", unloadHandler);\\n  } else if (typeof addEventListener === \\\"function\\\") {\\n    var terminationEvent = \\\"onpagehide\\\" in globalThis ? \\\"pagehide\\\" : \\\"unload\\\";\\n    addEventListener(terminationEvent, unloadHandler, false);\\n  }\\n}\\n\\nfunction unloadHandler() {\\n  for (var i in Request.requests) {\\n    if (Request.requests.hasOwnProperty(i)) {\\n      Request.requests[i].abort();\\n    }\\n  }\\n}\\n\\nmodule.exports = XHR;\\nmodule.exports.Request = Request;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-xhr.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling.js\":\n/*!***********************************!*\\\n  !*** ./lib/transports/polling.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling\\\");\\n\\nvar Polling =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(Polling, _Transport);\\n\\n  function Polling() {\\n    _classCallCheck(this, Polling);\\n\\n    return _possibleConstructorReturn(this, _getPrototypeOf(Polling).apply(this, arguments));\\n  }\\n\\n  _createClass(Polling, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens the socket (triggers polling). We write a PING message to determine\\n     * when the transport is open.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      this.poll();\\n    }\\n    /**\\n     * Pauses polling.\\n     *\\n     * @param {Function} callback upon buffers are flushed and transport is paused\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"pause\\\",\\n    value: function pause(onPause) {\\n      var self = this;\\n      this.readyState = \\\"pausing\\\";\\n\\n      function pause() {\\n        debug(\\\"paused\\\");\\n        self.readyState = \\\"paused\\\";\\n        onPause();\\n      }\\n\\n      if (this.polling || !this.writable) {\\n        var total = 0;\\n\\n        if (this.polling) {\\n          debug(\\\"we are currently polling - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"pollComplete\\\", function () {\\n            debug(\\\"pre-pause polling complete\\\");\\n            --total || pause();\\n          });\\n        }\\n\\n        if (!this.writable) {\\n          debug(\\\"we are currently writing - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"drain\\\", function () {\\n            debug(\\\"pre-pause writing complete\\\");\\n            --total || pause();\\n          });\\n        }\\n      } else {\\n        pause();\\n      }\\n    }\\n    /**\\n     * Starts polling cycle.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"poll\\\",\\n    value: function poll() {\\n      debug(\\\"polling\\\");\\n      this.polling = true;\\n      this.doPoll();\\n      this.emit(\\\"poll\\\");\\n    }\\n    /**\\n     * Overloads onData to detect payloads.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var self = this;\\n      debug(\\\"polling got data %s\\\", data);\\n\\n      var callback = function callback(packet, index, total) {\\n        // if its the first message we consider the transport open\\n        if (\\\"opening\\\" === self.readyState && packet.type === \\\"open\\\") {\\n          self.onOpen();\\n        } // if its a close packet, we close the ongoing requests\\n\\n\\n        if (\\\"close\\\" === packet.type) {\\n          self.onClose();\\n          return false;\\n        } // otherwise bypass onData and handle the message\\n\\n\\n        self.onPacket(packet);\\n      }; // decode payload\\n\\n\\n      parser.decodePayload(data, this.socket.binaryType).forEach(callback); // if an event did not trigger closing\\n\\n      if (\\\"closed\\\" !== this.readyState) {\\n        // if we got data we're not polling\\n        this.polling = false;\\n        this.emit(\\\"pollComplete\\\");\\n\\n        if (\\\"open\\\" === this.readyState) {\\n          this.poll();\\n        } else {\\n          debug('ignoring poll - transport state \\\"%s\\\"', this.readyState);\\n        }\\n      }\\n    }\\n    /**\\n     * For polling, send a close packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      var self = this;\\n\\n      function close() {\\n        debug(\\\"writing close packet\\\");\\n        self.write([{\\n          type: \\\"close\\\"\\n        }]);\\n      }\\n\\n      if (\\\"open\\\" === this.readyState) {\\n        debug(\\\"transport open - closing\\\");\\n        close();\\n      } else {\\n        // in case we're trying to close while\\n        // handshaking is in progress (GH-164)\\n        debug(\\\"transport not open - deferring close\\\");\\n        this.once(\\\"open\\\", close);\\n      }\\n    }\\n    /**\\n     * Writes a packets payload.\\n     *\\n     * @param {Array} data packets\\n     * @param {Function} drain callback\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var _this = this;\\n\\n      this.writable = false;\\n      parser.encodePayload(packets, function (data) {\\n        _this.doWrite(data, function () {\\n          _this.writable = true;\\n\\n          _this.emit(\\\"drain\\\");\\n        });\\n      });\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"https\\\" : \\\"http\\\";\\n      var port = \\\"\\\"; // cache busting is forced\\n\\n      if (false !== this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      }\\n\\n      if (!this.supportsBinary && !query.sid) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"https\\\" === schema && Number(this.opts.port) !== 443 || \\\"http\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // prepend ? to query\\n\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n\\n    /**\\n     * Transport name.\\n     */\\n    get: function get() {\\n      return \\\"polling\\\";\\n    }\\n  }]);\\n\\n  return Polling;\\n}(Transport);\\n\\nmodule.exports = Polling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket-constructor.browser.js\":\n/*!*********************************************************!*\\\n  !*** ./lib/transports/websocket-constructor.browser.js ***!\n  \\*********************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = {\\n  WebSocket: globalThis.WebSocket || globalThis.MozWebSocket,\\n  usingBrowserWebSocket: true,\\n  defaultBinaryType: \\\"arraybuffer\\\"\\n};\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket-constructor.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket.js\":\n/*!*************************************!*\\\n  !*** ./lib/transports/websocket.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar _require2 = __webpack_require__(/*! ./websocket-constructor */ \\\"./lib/transports/websocket-constructor.browser.js\\\"),\\n    WebSocket = _require2.WebSocket,\\n    usingBrowserWebSocket = _require2.usingBrowserWebSocket,\\n    defaultBinaryType = _require2.defaultBinaryType;\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:websocket\\\"); // detect ReactNative environment\\n\\n\\nvar isReactNative = typeof navigator !== \\\"undefined\\\" && typeof navigator.product === \\\"string\\\" && navigator.product.toLowerCase() === \\\"reactnative\\\";\\n\\nvar WS =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(WS, _Transport);\\n\\n  /**\\n   * WebSocket transport constructor.\\n   *\\n   * @api {Object} connection options\\n   * @api public\\n   */\\n  function WS(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, WS);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(WS).call(this, opts));\\n    _this.supportsBinary = !opts.forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Transport name.\\n   *\\n   * @api public\\n   */\\n\\n\\n  _createClass(WS, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens socket.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      if (!this.check()) {\\n        // let probe timeout\\n        return;\\n      }\\n\\n      var uri = this.uri();\\n      var protocols = this.opts.protocols; // React Native only supports the 'headers' option, and will print a warning if anything else is passed\\n\\n      var opts = isReactNative ? {} : pick(this.opts, \\\"agent\\\", \\\"perMessageDeflate\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\", \\\"localAddress\\\");\\n\\n      if (this.opts.extraHeaders) {\\n        opts.headers = this.opts.extraHeaders;\\n      }\\n\\n      try {\\n        this.ws = usingBrowserWebSocket && !isReactNative ? protocols ? new WebSocket(uri, protocols) : new WebSocket(uri) : new WebSocket(uri, protocols, opts);\\n      } catch (err) {\\n        return this.emit(\\\"error\\\", err);\\n      }\\n\\n      this.ws.binaryType = this.socket.binaryType || defaultBinaryType;\\n      this.addEventListeners();\\n    }\\n    /**\\n     * Adds event listeners to the socket\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"addEventListeners\\\",\\n    value: function addEventListeners() {\\n      var self = this;\\n\\n      this.ws.onopen = function () {\\n        self.onOpen();\\n      };\\n\\n      this.ws.onclose = function () {\\n        self.onClose();\\n      };\\n\\n      this.ws.onmessage = function (ev) {\\n        self.onData(ev.data);\\n      };\\n\\n      this.ws.onerror = function (e) {\\n        self.onError(\\\"websocket error\\\", e);\\n      };\\n    }\\n    /**\\n     * Writes data to socket.\\n     *\\n     * @param {Array} array of packets.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var self = this;\\n      this.writable = false; // encodePacket efficient as it uses WS framing\\n      // no need for encodePayload\\n\\n      var total = packets.length;\\n      var i = 0;\\n      var l = total;\\n\\n      for (; i < l; i++) {\\n        (function (packet) {\\n          parser.encodePacket(packet, self.supportsBinary, function (data) {\\n            // always create a new object (GH-437)\\n            var opts = {};\\n\\n            if (!usingBrowserWebSocket) {\\n              if (packet.options) {\\n                opts.compress = packet.options.compress;\\n              }\\n\\n              if (self.opts.perMessageDeflate) {\\n                var len = \\\"string\\\" === typeof data ? Buffer.byteLength(data) : data.length;\\n\\n                if (len < self.opts.perMessageDeflate.threshold) {\\n                  opts.compress = false;\\n                }\\n              }\\n            } // Sometimes the websocket has already been closed but the browser didn't\\n            // have a chance of informing us about it yet, in that case send will\\n            // throw an error\\n\\n\\n            try {\\n              if (usingBrowserWebSocket) {\\n                // TypeError is thrown when passing the second argument on Safari\\n                self.ws.send(data);\\n              } else {\\n                self.ws.send(data, opts);\\n              }\\n            } catch (e) {\\n              debug(\\\"websocket closed before onclose event\\\");\\n            }\\n\\n            --total || done();\\n          });\\n        })(packets[i]);\\n      }\\n\\n      function done() {\\n        self.emit(\\\"flush\\\"); // fake drain\\n        // defer to next tick to allow Socket to clear writeBuffer\\n\\n        setTimeout(function () {\\n          self.writable = true;\\n          self.emit(\\\"drain\\\");\\n        }, 0);\\n      }\\n    }\\n    /**\\n     * Called upon close\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      Transport.prototype.onClose.call(this);\\n    }\\n    /**\\n     * Closes socket.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      if (typeof this.ws !== \\\"undefined\\\") {\\n        this.ws.close();\\n      }\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"wss\\\" : \\\"ws\\\";\\n      var port = \\\"\\\"; // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"wss\\\" === schema && Number(this.opts.port) !== 443 || \\\"ws\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // append timestamp to URI\\n\\n\\n      if (this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      } // communicate binary support capabilities\\n\\n\\n      if (!this.supportsBinary) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // prepend ? to query\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n    /**\\n     * Feature detection for WebSocket.\\n     *\\n     * @return {Boolean} whether this transport is available.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"check\\\",\\n    value: function check() {\\n      return !!WebSocket && !(\\\"__initialize\\\" in WebSocket && this.name === WS.prototype.name);\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n    get: function get() {\\n      return \\\"websocket\\\";\\n    }\\n  }]);\\n\\n  return WS;\\n}(Transport);\\n\\nmodule.exports = WS;\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/util.js\":\n/*!*********************!*\\\n  !*** ./lib/util.js ***!\n  \\*********************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports.pick = function (obj) {\\n  for (var _len = arguments.length, attr = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\\n    attr[_key - 1] = arguments[_key];\\n  }\\n\\n  return attr.reduce(function (acc, k) {\\n    acc[k] = obj[k];\\n    return acc;\\n  }, {});\\n};\\n\\n//# sourceURL=webpack://eio/./lib/util.js?\");\n\n/***/ }),\n\n/***/ \"./lib/xmlhttprequest.js\":\n/*!*******************************!*\\\n  !*** ./lib/xmlhttprequest.js ***!\n  \\*******************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"// browser shim for xmlhttprequest module\\nvar hasCORS = __webpack_require__(/*! has-cors */ \\\"./node_modules/has-cors/index.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ./globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = function (opts) {\\n  var xdomain = opts.xdomain; // scheme must be same when usign XDomainRequest\\n  // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx\\n\\n  var xscheme = opts.xscheme; // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.\\n  // https://github.com/Automattic/engine.io-client/pull/217\\n\\n  var enablesXDR = opts.enablesXDR; // XMLHttpRequest can be disabled on IE\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {\\n      return new XMLHttpRequest();\\n    }\\n  } catch (e) {} // Use XDomainRequest for IE8 if enablesXDR is true\\n  // because loading bar keeps flashing when using jsonp-polling\\n  // https://github.com/yujiosaka/socke.io-ie8-loading-example\\n\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XDomainRequest && !xscheme && enablesXDR) {\\n      return new XDomainRequest();\\n    }\\n  } catch (e) {}\\n\\n  if (!xdomain) {\\n    try {\\n      return new globalThis[[\\\"Active\\\"].concat(\\\"Object\\\").join(\\\"X\\\")](\\\"Microsoft.XMLHTTP\\\");\\n    } catch (e) {}\\n  }\\n};\\n\\n//# sourceURL=webpack://eio/./lib/xmlhttprequest.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/*\\n * base64-arraybuffer\\n * https://github.com/niklasvh/base64-arraybuffer\\n *\\n * Copyright (c) 2012 Niklas von Hertzen\\n * Licensed under the MIT license.\\n */\\n(function (chars) {\\n  \\\"use strict\\\";\\n\\n  exports.encode = function (arraybuffer) {\\n    var bytes = new Uint8Array(arraybuffer),\\n        i,\\n        len = bytes.length,\\n        base64 = \\\"\\\";\\n\\n    for (i = 0; i < len; i += 3) {\\n      base64 += chars[bytes[i] >> 2];\\n      base64 += chars[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];\\n      base64 += chars[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];\\n      base64 += chars[bytes[i + 2] & 63];\\n    }\\n\\n    if (len % 3 === 2) {\\n      base64 = base64.substring(0, base64.length - 1) + \\\"=\\\";\\n    } else if (len % 3 === 1) {\\n      base64 = base64.substring(0, base64.length - 2) + \\\"==\\\";\\n    }\\n\\n    return base64;\\n  };\\n\\n  exports.decode = function (base64) {\\n    var bufferLength = base64.length * 0.75,\\n        len = base64.length,\\n        i,\\n        p = 0,\\n        encoded1,\\n        encoded2,\\n        encoded3,\\n        encoded4;\\n\\n    if (base64[base64.length - 1] === \\\"=\\\") {\\n      bufferLength--;\\n\\n      if (base64[base64.length - 2] === \\\"=\\\") {\\n        bufferLength--;\\n      }\\n    }\\n\\n    var arraybuffer = new ArrayBuffer(bufferLength),\\n        bytes = new Uint8Array(arraybuffer);\\n\\n    for (i = 0; i < len; i += 4) {\\n      encoded1 = chars.indexOf(base64[i]);\\n      encoded2 = chars.indexOf(base64[i + 1]);\\n      encoded3 = chars.indexOf(base64[i + 2]);\\n      encoded4 = chars.indexOf(base64[i + 3]);\\n      bytes[p++] = encoded1 << 2 | encoded2 >> 4;\\n      bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;\\n      bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;\\n    }\\n\\n    return arraybuffer;\\n  };\\n})(\\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\");\\n\\n//# sourceURL=webpack://eio/./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/component-emitter/index.js\":\n/*!*************************************************!*\\\n  !*** ./node_modules/component-emitter/index.js ***!\n  \\*************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/**\\r\\n * Expose `Emitter`.\\r\\n */\\nif (true) {\\n  module.exports = Emitter;\\n}\\n/**\\r\\n * Initialize a new `Emitter`.\\r\\n *\\r\\n * @api public\\r\\n */\\n\\n\\nfunction Emitter(obj) {\\n  if (obj) return mixin(obj);\\n}\\n\\n;\\n/**\\r\\n * Mixin the emitter properties.\\r\\n *\\r\\n * @param {Object} obj\\r\\n * @return {Object}\\r\\n * @api private\\r\\n */\\n\\nfunction mixin(obj) {\\n  for (var key in Emitter.prototype) {\\n    obj[key] = Emitter.prototype[key];\\n  }\\n\\n  return obj;\\n}\\n/**\\r\\n * Listen on the given `event` with `fn`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {};\\n  (this._callbacks['$' + event] = this._callbacks['$' + event] || []).push(fn);\\n  return this;\\n};\\n/**\\r\\n * Adds an `event` listener that will be invoked a single\\r\\n * time then automatically removed.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.once = function (event, fn) {\\n  function on() {\\n    this.off(event, on);\\n    fn.apply(this, arguments);\\n  }\\n\\n  on.fn = fn;\\n  this.on(event, on);\\n  return this;\\n};\\n/**\\r\\n * Remove the given callback for `event` or all\\r\\n * registered callbacks.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {}; // all\\n\\n  if (0 == arguments.length) {\\n    this._callbacks = {};\\n    return this;\\n  } // specific event\\n\\n\\n  var callbacks = this._callbacks['$' + event];\\n  if (!callbacks) return this; // remove all handlers\\n\\n  if (1 == arguments.length) {\\n    delete this._callbacks['$' + event];\\n    return this;\\n  } // remove specific handler\\n\\n\\n  var cb;\\n\\n  for (var i = 0; i < callbacks.length; i++) {\\n    cb = callbacks[i];\\n\\n    if (cb === fn || cb.fn === fn) {\\n      callbacks.splice(i, 1);\\n      break;\\n    }\\n  } // Remove event specific arrays for event types that no\\n  // one is subscribed for to avoid memory leak.\\n\\n\\n  if (callbacks.length === 0) {\\n    delete this._callbacks['$' + event];\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Emit `event` with the given args.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Mixed} ...\\r\\n * @return {Emitter}\\r\\n */\\n\\n\\nEmitter.prototype.emit = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  var args = new Array(arguments.length - 1),\\n      callbacks = this._callbacks['$' + event];\\n\\n  for (var i = 1; i < arguments.length; i++) {\\n    args[i - 1] = arguments[i];\\n  }\\n\\n  if (callbacks) {\\n    callbacks = callbacks.slice(0);\\n\\n    for (var i = 0, len = callbacks.length; i < len; ++i) {\\n      callbacks[i].apply(this, args);\\n    }\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Return array of callbacks for `event`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Array}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.listeners = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  return this._callbacks['$' + event] || [];\\n};\\n/**\\r\\n * Check if this emitter has `event` handlers.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Boolean}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.hasListeners = function (event) {\\n  return !!this.listeners(event).length;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/component-emitter/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/browser.js\":\n/*!*******************************************!*\\\n  !*** ./node_modules/debug/src/browser.js ***!\n  \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/* WEBPACK VAR INJECTION */(function(process) {function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/* eslint-env browser */\\n\\n/**\\n * This is the web browser implementation of `debug()`.\\n */\\nexports.log = log;\\nexports.formatArgs = formatArgs;\\nexports.save = save;\\nexports.load = load;\\nexports.useColors = useColors;\\nexports.storage = localstorage();\\n/**\\n * Colors.\\n */\\n\\nexports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];\\n/**\\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\\n * and the Firebug extension (any Firefox version) are known\\n * to support \\\"%c\\\" CSS customizations.\\n *\\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\\n */\\n// eslint-disable-next-line complexity\\n\\nfunction useColors() {\\n  // NB: In an Electron preload script, document will be defined but not fully\\n  // initialized. Since we know we're in Chrome, we'll just detect this case\\n  // explicitly\\n  if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {\\n    return true;\\n  } // Internet Explorer and Edge do not support colors.\\n\\n\\n  if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\\\\/(\\\\d+)/)) {\\n    return false;\\n  } // Is webkit? http://stackoverflow.com/a/16459606/376773\\n  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\\n\\n\\n  return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773\\n  typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?\\n  // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\\\\/(\\\\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\\\/(\\\\d+)/);\\n}\\n/**\\n * Colorize log arguments if enabled.\\n *\\n * @api public\\n */\\n\\n\\nfunction formatArgs(args) {\\n  args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);\\n\\n  if (!this.useColors) {\\n    return;\\n  }\\n\\n  var c = 'color: ' + this.color;\\n  args.splice(1, 0, c, 'color: inherit'); // The final \\\"%c\\\" is somewhat tricky, because there could be other\\n  // arguments passed either before or after the %c, so we need to\\n  // figure out the correct index to insert the CSS into\\n\\n  var index = 0;\\n  var lastC = 0;\\n  args[0].replace(/%[a-zA-Z%]/g, function (match) {\\n    if (match === '%%') {\\n      return;\\n    }\\n\\n    index++;\\n\\n    if (match === '%c') {\\n      // We only are interested in the *last* %c\\n      // (the user may have provided their own)\\n      lastC = index;\\n    }\\n  });\\n  args.splice(lastC, 0, c);\\n}\\n/**\\n * Invokes `console.log()` when available.\\n * No-op when `console.log` is not a \\\"function\\\".\\n *\\n * @api public\\n */\\n\\n\\nfunction log() {\\n  var _console;\\n\\n  // This hackery is required for IE8/9, where\\n  // the `console.log` function doesn't have 'apply'\\n  return (typeof console === \\\"undefined\\\" ? \\\"undefined\\\" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments);\\n}\\n/**\\n * Save `namespaces`.\\n *\\n * @param {String} namespaces\\n * @api private\\n */\\n\\n\\nfunction save(namespaces) {\\n  try {\\n    if (namespaces) {\\n      exports.storage.setItem('debug', namespaces);\\n    } else {\\n      exports.storage.removeItem('debug');\\n    }\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n/**\\n * Load `namespaces`.\\n *\\n * @return {String} returns the previously persisted debug modes\\n * @api private\\n */\\n\\n\\nfunction load() {\\n  var r;\\n\\n  try {\\n    r = exports.storage.getItem('debug');\\n  } catch (error) {} // Swallow\\n  // XXX (@Qix-) should we be logging these?\\n  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\\n\\n\\n  if (!r && typeof process !== 'undefined' && 'env' in process) {\\n    r = process.env.DEBUG;\\n  }\\n\\n  return r;\\n}\\n/**\\n * Localstorage attempts to return the localstorage.\\n *\\n * This is necessary because safari throws\\n * when a user disables cookies/localstorage\\n * and you attempt to access it.\\n *\\n * @return {LocalStorage}\\n * @api private\\n */\\n\\n\\nfunction localstorage() {\\n  try {\\n    // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\\n    // The Browser also has localStorage in the global context.\\n    return localStorage;\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n\\nmodule.exports = __webpack_require__(/*! ./common */ \\\"./node_modules/debug/src/common.js\\\")(exports);\\nvar formatters = module.exports.formatters;\\n/**\\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\\n */\\n\\nformatters.j = function (v) {\\n  try {\\n    return JSON.stringify(v);\\n  } catch (error) {\\n    return '[UnexpectedJSONParseError]: ' + error.message;\\n  }\\n};\\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../process/browser.js */ \\\"./node_modules/process/browser.js\\\")))\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/common.js\":\n/*!******************************************!*\\\n  !*** ./node_modules/debug/src/common.js ***!\n  \\******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\\n\\nfunction _nonIterableSpread() { throw new TypeError(\\\"Invalid attempt to spread non-iterable instance\\\"); }\\n\\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \\\"[object Arguments]\\\") return Array.from(iter); }\\n\\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\\n\\n/**\\n * This is the common logic for both the Node.js and web browser\\n * implementations of `debug()`.\\n */\\nfunction setup(env) {\\n  createDebug.debug = createDebug;\\n  createDebug[\\\"default\\\"] = createDebug;\\n  createDebug.coerce = coerce;\\n  createDebug.disable = disable;\\n  createDebug.enable = enable;\\n  createDebug.enabled = enabled;\\n  createDebug.humanize = __webpack_require__(/*! ms */ \\\"./node_modules/ms/index.js\\\");\\n  Object.keys(env).forEach(function (key) {\\n    createDebug[key] = env[key];\\n  });\\n  /**\\n  * Active `debug` instances.\\n  */\\n\\n  createDebug.instances = [];\\n  /**\\n  * The currently active debug mode names, and names to skip.\\n  */\\n\\n  createDebug.names = [];\\n  createDebug.skips = [];\\n  /**\\n  * Map of special \\\"%n\\\" handling functions, for the debug \\\"format\\\" argument.\\n  *\\n  * Valid key names are a single, lower or upper-case letter, i.e. \\\"n\\\" and \\\"N\\\".\\n  */\\n\\n  createDebug.formatters = {};\\n  /**\\n  * Selects a color for a debug namespace\\n  * @param {String} namespace The namespace string for the for the debug instance to be colored\\n  * @return {Number|String} An ANSI color code for the given namespace\\n  * @api private\\n  */\\n\\n  function selectColor(namespace) {\\n    var hash = 0;\\n\\n    for (var i = 0; i < namespace.length; i++) {\\n      hash = (hash << 5) - hash + namespace.charCodeAt(i);\\n      hash |= 0; // Convert to 32bit integer\\n    }\\n\\n    return createDebug.colors[Math.abs(hash) % createDebug.colors.length];\\n  }\\n\\n  createDebug.selectColor = selectColor;\\n  /**\\n  * Create a debugger with the given `namespace`.\\n  *\\n  * @param {String} namespace\\n  * @return {Function}\\n  * @api public\\n  */\\n\\n  function createDebug(namespace) {\\n    var prevTime;\\n\\n    function debug() {\\n      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\\n        args[_key] = arguments[_key];\\n      }\\n\\n      // Disabled?\\n      if (!debug.enabled) {\\n        return;\\n      }\\n\\n      var self = debug; // Set `diff` timestamp\\n\\n      var curr = Number(new Date());\\n      var ms = curr - (prevTime || curr);\\n      self.diff = ms;\\n      self.prev = prevTime;\\n      self.curr = curr;\\n      prevTime = curr;\\n      args[0] = createDebug.coerce(args[0]);\\n\\n      if (typeof args[0] !== 'string') {\\n        // Anything else let's inspect with %O\\n        args.unshift('%O');\\n      } // Apply any `formatters` transformations\\n\\n\\n      var index = 0;\\n      args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {\\n        // If we encounter an escaped % then don't increase the array index\\n        if (match === '%%') {\\n          return match;\\n        }\\n\\n        index++;\\n        var formatter = createDebug.formatters[format];\\n\\n        if (typeof formatter === 'function') {\\n          var val = args[index];\\n          match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`\\n\\n          args.splice(index, 1);\\n          index--;\\n        }\\n\\n        return match;\\n      }); // Apply env-specific formatting (colors, etc.)\\n\\n      createDebug.formatArgs.call(self, args);\\n      var logFn = self.log || createDebug.log;\\n      logFn.apply(self, args);\\n    }\\n\\n    debug.namespace = namespace;\\n    debug.enabled = createDebug.enabled(namespace);\\n    debug.useColors = createDebug.useColors();\\n    debug.color = selectColor(namespace);\\n    debug.destroy = destroy;\\n    debug.extend = extend; // Debug.formatArgs = formatArgs;\\n    // debug.rawLog = rawLog;\\n    // env-specific initialization logic for debug instances\\n\\n    if (typeof createDebug.init === 'function') {\\n      createDebug.init(debug);\\n    }\\n\\n    createDebug.instances.push(debug);\\n    return debug;\\n  }\\n\\n  function destroy() {\\n    var index = createDebug.instances.indexOf(this);\\n\\n    if (index !== -1) {\\n      createDebug.instances.splice(index, 1);\\n      return true;\\n    }\\n\\n    return false;\\n  }\\n\\n  function extend(namespace, delimiter) {\\n    var newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);\\n    newDebug.log = this.log;\\n    return newDebug;\\n  }\\n  /**\\n  * Enables a debug mode by namespaces. This can include modes\\n  * separated by a colon and wildcards.\\n  *\\n  * @param {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function enable(namespaces) {\\n    createDebug.save(namespaces);\\n    createDebug.names = [];\\n    createDebug.skips = [];\\n    var i;\\n    var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\\\\s,]+/);\\n    var len = split.length;\\n\\n    for (i = 0; i < len; i++) {\\n      if (!split[i]) {\\n        // ignore empty strings\\n        continue;\\n      }\\n\\n      namespaces = split[i].replace(/\\\\*/g, '.*?');\\n\\n      if (namespaces[0] === '-') {\\n        createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));\\n      } else {\\n        createDebug.names.push(new RegExp('^' + namespaces + '$'));\\n      }\\n    }\\n\\n    for (i = 0; i < createDebug.instances.length; i++) {\\n      var instance = createDebug.instances[i];\\n      instance.enabled = createDebug.enabled(instance.namespace);\\n    }\\n  }\\n  /**\\n  * Disable debug output.\\n  *\\n  * @return {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function disable() {\\n    var namespaces = [].concat(_toConsumableArray(createDebug.names.map(toNamespace)), _toConsumableArray(createDebug.skips.map(toNamespace).map(function (namespace) {\\n      return '-' + namespace;\\n    }))).join(',');\\n    createDebug.enable('');\\n    return namespaces;\\n  }\\n  /**\\n  * Returns true if the given mode name is enabled, false otherwise.\\n  *\\n  * @param {String} name\\n  * @return {Boolean}\\n  * @api public\\n  */\\n\\n\\n  function enabled(name) {\\n    if (name[name.length - 1] === '*') {\\n      return true;\\n    }\\n\\n    var i;\\n    var len;\\n\\n    for (i = 0, len = createDebug.skips.length; i < len; i++) {\\n      if (createDebug.skips[i].test(name)) {\\n        return false;\\n      }\\n    }\\n\\n    for (i = 0, len = createDebug.names.length; i < len; i++) {\\n      if (createDebug.names[i].test(name)) {\\n        return true;\\n      }\\n    }\\n\\n    return false;\\n  }\\n  /**\\n  * Convert regexp to namespace\\n  *\\n  * @param {RegExp} regxep\\n  * @return {String} namespace\\n  * @api private\\n  */\\n\\n\\n  function toNamespace(regexp) {\\n    return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\\\\.\\\\*\\\\?$/, '*');\\n  }\\n  /**\\n  * Coerce `val`.\\n  *\\n  * @param {Mixed} val\\n  * @return {Mixed}\\n  * @api private\\n  */\\n\\n\\n  function coerce(val) {\\n    if (val instanceof Error) {\\n      return val.stack || val.message;\\n    }\\n\\n    return val;\\n  }\\n\\n  createDebug.enable(createDebug.load());\\n  return createDebug;\\n}\\n\\nmodule.exports = setup;\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/common.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/commons.js\":\n/*!******************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/commons.js ***!\n  \\******************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"var PACKET_TYPES = Object.create(null); // no Map = no polyfill\\n\\nPACKET_TYPES[\\\"open\\\"] = \\\"0\\\";\\nPACKET_TYPES[\\\"close\\\"] = \\\"1\\\";\\nPACKET_TYPES[\\\"ping\\\"] = \\\"2\\\";\\nPACKET_TYPES[\\\"pong\\\"] = \\\"3\\\";\\nPACKET_TYPES[\\\"message\\\"] = \\\"4\\\";\\nPACKET_TYPES[\\\"upgrade\\\"] = \\\"5\\\";\\nPACKET_TYPES[\\\"noop\\\"] = \\\"6\\\";\\nvar PACKET_TYPES_REVERSE = Object.create(null);\\nObject.keys(PACKET_TYPES).forEach(function (key) {\\n  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;\\n});\\nvar ERROR_PACKET = {\\n  type: \\\"error\\\",\\n  data: \\\"parser error\\\"\\n};\\nmodule.exports = {\\n  PACKET_TYPES: PACKET_TYPES,\\n  PACKET_TYPES_REVERSE: PACKET_TYPES_REVERSE,\\n  ERROR_PACKET: ERROR_PACKET\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/commons.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/decodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/decodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES_REVERSE = _require.PACKET_TYPES_REVERSE,\\n    ERROR_PACKET = _require.ERROR_PACKET;\\n\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\";\\nvar base64decoder;\\n\\nif (withNativeArrayBuffer) {\\n  base64decoder = __webpack_require__(/*! base64-arraybuffer */ \\\"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\\\");\\n}\\n\\nvar decodePacket = function decodePacket(encodedPacket, binaryType) {\\n  if (typeof encodedPacket !== \\\"string\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: mapBinary(encodedPacket, binaryType)\\n    };\\n  }\\n\\n  var type = encodedPacket.charAt(0);\\n\\n  if (type === \\\"b\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: decodeBase64Packet(encodedPacket.substring(1), binaryType)\\n    };\\n  }\\n\\n  var packetType = PACKET_TYPES_REVERSE[type];\\n\\n  if (!packetType) {\\n    return ERROR_PACKET;\\n  }\\n\\n  return encodedPacket.length > 1 ? {\\n    type: PACKET_TYPES_REVERSE[type],\\n    data: encodedPacket.substring(1)\\n  } : {\\n    type: PACKET_TYPES_REVERSE[type]\\n  };\\n};\\n\\nvar decodeBase64Packet = function decodeBase64Packet(data, binaryType) {\\n  if (base64decoder) {\\n    var decoded = base64decoder.decode(data);\\n    return mapBinary(decoded, binaryType);\\n  } else {\\n    return {\\n      base64: true,\\n      data: data\\n    }; // fallback for old browsers\\n  }\\n};\\n\\nvar mapBinary = function mapBinary(data, binaryType) {\\n  switch (binaryType) {\\n    case \\\"blob\\\":\\n      return data instanceof ArrayBuffer ? new Blob([data]) : data;\\n\\n    case \\\"arraybuffer\\\":\\n    default:\\n      return data;\\n    // assuming the data is already an ArrayBuffer\\n  }\\n};\\n\\nmodule.exports = decodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/decodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/encodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/encodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES = _require.PACKET_TYPES;\\n\\nvar withNativeBlob = typeof Blob === \\\"function\\\" || typeof Blob !== \\\"undefined\\\" && Object.prototype.toString.call(Blob) === \\\"[object BlobConstructor]\\\";\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\"; // ArrayBuffer.isView method is not defined in IE10\\n\\nvar isView = function isView(obj) {\\n  return typeof ArrayBuffer.isView === \\\"function\\\" ? ArrayBuffer.isView(obj) : obj && obj.buffer instanceof ArrayBuffer;\\n};\\n\\nvar encodePacket = function encodePacket(_ref, supportsBinary, callback) {\\n  var type = _ref.type,\\n      data = _ref.data;\\n\\n  if (withNativeBlob && data instanceof Blob) {\\n    if (supportsBinary) {\\n      return callback(data);\\n    } else {\\n      return encodeBlobAsBase64(data, callback);\\n    }\\n  } else if (withNativeArrayBuffer && (data instanceof ArrayBuffer || isView(data))) {\\n    if (supportsBinary) {\\n      return callback(data instanceof ArrayBuffer ? data : data.buffer);\\n    } else {\\n      return encodeBlobAsBase64(new Blob([data]), callback);\\n    }\\n  } // plain string\\n\\n\\n  return callback(PACKET_TYPES[type] + (data || \\\"\\\"));\\n};\\n\\nvar encodeBlobAsBase64 = function encodeBlobAsBase64(data, callback) {\\n  var fileReader = new FileReader();\\n\\n  fileReader.onload = function () {\\n    var content = fileReader.result.split(\\\",\\\")[1];\\n    callback(\\\"b\\\" + content);\\n  };\\n\\n  return fileReader.readAsDataURL(data);\\n};\\n\\nmodule.exports = encodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/encodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/index.js\":\n/*!****************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/index.js ***!\n  \\****************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var encodePacket = __webpack_require__(/*! ./encodePacket */ \\\"./node_modules/engine.io-parser/lib/encodePacket.browser.js\\\");\\n\\nvar decodePacket = __webpack_require__(/*! ./decodePacket */ \\\"./node_modules/engine.io-parser/lib/decodePacket.browser.js\\\");\\n\\nvar SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text\\n\\nvar encodePayload = function encodePayload(packets, callback) {\\n  // some packets may be added to the array while encoding, so the initial length must be saved\\n  var length = packets.length;\\n  var encodedPackets = new Array(length);\\n  var count = 0;\\n  packets.forEach(function (packet, i) {\\n    // force base64 encoding for binary packets\\n    encodePacket(packet, false, function (encodedPacket) {\\n      encodedPackets[i] = encodedPacket;\\n\\n      if (++count === length) {\\n        callback(encodedPackets.join(SEPARATOR));\\n      }\\n    });\\n  });\\n};\\n\\nvar decodePayload = function decodePayload(encodedPayload, binaryType) {\\n  var encodedPackets = encodedPayload.split(SEPARATOR);\\n  var packets = [];\\n\\n  for (var i = 0; i < encodedPackets.length; i++) {\\n    var decodedPacket = decodePacket(encodedPackets[i], binaryType);\\n    packets.push(decodedPacket);\\n\\n    if (decodedPacket.type === \\\"error\\\") {\\n      break;\\n    }\\n  }\\n\\n  return packets;\\n};\\n\\nmodule.exports = {\\n  protocol: 4,\\n  encodePacket: encodePacket,\\n  encodePayload: encodePayload,\\n  decodePacket: decodePacket,\\n  decodePayload: decodePayload\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/has-cors/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/has-cors/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Module exports.\\n *\\n * Logic borrowed from Modernizr:\\n *\\n *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js\\n */\\ntry {\\n  module.exports = typeof XMLHttpRequest !== 'undefined' && 'withCredentials' in new XMLHttpRequest();\\n} catch (err) {\\n  // if XMLHttp support is disabled in IE then it will throw\\n  // when trying to create\\n  module.exports = false;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/has-cors/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/ms/index.js\":\n/*!**********************************!*\\\n  !*** ./node_modules/ms/index.js ***!\n  \\**********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/**\\n * Helpers.\\n */\\nvar s = 1000;\\nvar m = s * 60;\\nvar h = m * 60;\\nvar d = h * 24;\\nvar w = d * 7;\\nvar y = d * 365.25;\\n/**\\n * Parse or format the given `val`.\\n *\\n * Options:\\n *\\n *  - `long` verbose formatting [false]\\n *\\n * @param {String|Number} val\\n * @param {Object} [options]\\n * @throws {Error} throw an error if val is not a non-empty string or a number\\n * @return {String|Number}\\n * @api public\\n */\\n\\nmodule.exports = function (val, options) {\\n  options = options || {};\\n\\n  var type = _typeof(val);\\n\\n  if (type === 'string' && val.length > 0) {\\n    return parse(val);\\n  } else if (type === 'number' && isFinite(val)) {\\n    return options[\\\"long\\\"] ? fmtLong(val) : fmtShort(val);\\n  }\\n\\n  throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val));\\n};\\n/**\\n * Parse the given `str` and return milliseconds.\\n *\\n * @param {String} str\\n * @return {Number}\\n * @api private\\n */\\n\\n\\nfunction parse(str) {\\n  str = String(str);\\n\\n  if (str.length > 100) {\\n    return;\\n  }\\n\\n  var match = /^(-?(?:\\\\d+)?\\\\.?\\\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);\\n\\n  if (!match) {\\n    return;\\n  }\\n\\n  var n = parseFloat(match[1]);\\n  var type = (match[2] || 'ms').toLowerCase();\\n\\n  switch (type) {\\n    case 'years':\\n    case 'year':\\n    case 'yrs':\\n    case 'yr':\\n    case 'y':\\n      return n * y;\\n\\n    case 'weeks':\\n    case 'week':\\n    case 'w':\\n      return n * w;\\n\\n    case 'days':\\n    case 'day':\\n    case 'd':\\n      return n * d;\\n\\n    case 'hours':\\n    case 'hour':\\n    case 'hrs':\\n    case 'hr':\\n    case 'h':\\n      return n * h;\\n\\n    case 'minutes':\\n    case 'minute':\\n    case 'mins':\\n    case 'min':\\n    case 'm':\\n      return n * m;\\n\\n    case 'seconds':\\n    case 'second':\\n    case 'secs':\\n    case 'sec':\\n    case 's':\\n      return n * s;\\n\\n    case 'milliseconds':\\n    case 'millisecond':\\n    case 'msecs':\\n    case 'msec':\\n    case 'ms':\\n      return n;\\n\\n    default:\\n      return undefined;\\n  }\\n}\\n/**\\n * Short format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtShort(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return Math.round(ms / d) + 'd';\\n  }\\n\\n  if (msAbs >= h) {\\n    return Math.round(ms / h) + 'h';\\n  }\\n\\n  if (msAbs >= m) {\\n    return Math.round(ms / m) + 'm';\\n  }\\n\\n  if (msAbs >= s) {\\n    return Math.round(ms / s) + 's';\\n  }\\n\\n  return ms + 'ms';\\n}\\n/**\\n * Long format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtLong(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return plural(ms, msAbs, d, 'day');\\n  }\\n\\n  if (msAbs >= h) {\\n    return plural(ms, msAbs, h, 'hour');\\n  }\\n\\n  if (msAbs >= m) {\\n    return plural(ms, msAbs, m, 'minute');\\n  }\\n\\n  if (msAbs >= s) {\\n    return plural(ms, msAbs, s, 'second');\\n  }\\n\\n  return ms + ' ms';\\n}\\n/**\\n * Pluralization helper.\\n */\\n\\n\\nfunction plural(ms, msAbs, n, name) {\\n  var isPlural = msAbs >= n * 1.5;\\n  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/ms/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseqs/index.js\":\n/*!***************************************!*\\\n  !*** ./node_modules/parseqs/index.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Compiles a querystring\\n * Returns string representation of the object\\n *\\n * @param {Object}\\n * @api private\\n */\\nexports.encode = function (obj) {\\n  var str = '';\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      if (str.length) str += '&';\\n      str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);\\n    }\\n  }\\n\\n  return str;\\n};\\n/**\\n * Parses a simple querystring into an object\\n *\\n * @param {String} qs\\n * @api private\\n */\\n\\n\\nexports.decode = function (qs) {\\n  var qry = {};\\n  var pairs = qs.split('&');\\n\\n  for (var i = 0, l = pairs.length; i < l; i++) {\\n    var pair = pairs[i].split('=');\\n    qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);\\n  }\\n\\n  return qry;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/parseqs/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseuri/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/parseuri/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Parses an URI\\n *\\n * @author Steven Levithan <stevenlevithan.com> (MIT license)\\n * @api private\\n */\\nvar re = /^(?:(?![^:@]+:[^:@\\\\/]*@)(http|https|ws|wss):\\\\/\\\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\\\/?#]*)(?::(\\\\d*))?)(((\\\\/(?:[^?#](?![^?#\\\\/]*\\\\.[^?#\\\\/.]+(?:[?#]|$)))*\\\\/?)?([^?#\\\\/]*))(?:\\\\?([^#]*))?(?:#(.*))?)/;\\nvar parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'];\\n\\nmodule.exports = function parseuri(str) {\\n  var src = str,\\n      b = str.indexOf('['),\\n      e = str.indexOf(']');\\n\\n  if (b != -1 && e != -1) {\\n    str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);\\n  }\\n\\n  var m = re.exec(str || ''),\\n      uri = {},\\n      i = 14;\\n\\n  while (i--) {\\n    uri[parts[i]] = m[i] || '';\\n  }\\n\\n  if (b != -1 && e != -1) {\\n    uri.source = src;\\n    uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');\\n    uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');\\n    uri.ipv6uri = true;\\n  }\\n\\n  uri.pathNames = pathNames(uri, uri['path']);\\n  uri.queryKey = queryKey(uri, uri['query']);\\n  return uri;\\n};\\n\\nfunction pathNames(obj, path) {\\n  var regx = /\\\\/{2,9}/g,\\n      names = path.replace(regx, \\\"/\\\").split(\\\"/\\\");\\n\\n  if (path.substr(0, 1) == '/' || path.length === 0) {\\n    names.splice(0, 1);\\n  }\\n\\n  if (path.substr(path.length - 1, 1) == '/') {\\n    names.splice(names.length - 1, 1);\\n  }\\n\\n  return names;\\n}\\n\\nfunction queryKey(uri, query) {\\n  var data = {};\\n  query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {\\n    if ($1) {\\n      data[$1] = $2;\\n    }\\n  });\\n  return data;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/parseuri/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/process/browser.js\":\n/*!*****************************************!*\\\n  !*** ./node_modules/process/browser.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"// shim for using process in browser\\nvar process = module.exports = {}; // cached from whatever global is present so that test runners that stub it\\n// don't break things.  But we need to wrap it in a try catch in case it is\\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\\n// function because try/catches deoptimize in certain engines.\\n\\nvar cachedSetTimeout;\\nvar cachedClearTimeout;\\n\\nfunction defaultSetTimout() {\\n  throw new Error('setTimeout has not been defined');\\n}\\n\\nfunction defaultClearTimeout() {\\n  throw new Error('clearTimeout has not been defined');\\n}\\n\\n(function () {\\n  try {\\n    if (typeof setTimeout === 'function') {\\n      cachedSetTimeout = setTimeout;\\n    } else {\\n      cachedSetTimeout = defaultSetTimout;\\n    }\\n  } catch (e) {\\n    cachedSetTimeout = defaultSetTimout;\\n  }\\n\\n  try {\\n    if (typeof clearTimeout === 'function') {\\n      cachedClearTimeout = clearTimeout;\\n    } else {\\n      cachedClearTimeout = defaultClearTimeout;\\n    }\\n  } catch (e) {\\n    cachedClearTimeout = defaultClearTimeout;\\n  }\\n})();\\n\\nfunction runTimeout(fun) {\\n  if (cachedSetTimeout === setTimeout) {\\n    //normal enviroments in sane situations\\n    return setTimeout(fun, 0);\\n  } // if setTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\\n    cachedSetTimeout = setTimeout;\\n    return setTimeout(fun, 0);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedSetTimeout(fun, 0);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\\n      return cachedSetTimeout.call(null, fun, 0);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\\n      return cachedSetTimeout.call(this, fun, 0);\\n    }\\n  }\\n}\\n\\nfunction runClearTimeout(marker) {\\n  if (cachedClearTimeout === clearTimeout) {\\n    //normal enviroments in sane situations\\n    return clearTimeout(marker);\\n  } // if clearTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\\n    cachedClearTimeout = clearTimeout;\\n    return clearTimeout(marker);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedClearTimeout(marker);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\\n      return cachedClearTimeout.call(null, marker);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\\n      // Some versions of I.E. have different rules for clearTimeout vs setTimeout\\n      return cachedClearTimeout.call(this, marker);\\n    }\\n  }\\n}\\n\\nvar queue = [];\\nvar draining = false;\\nvar currentQueue;\\nvar queueIndex = -1;\\n\\nfunction cleanUpNextTick() {\\n  if (!draining || !currentQueue) {\\n    return;\\n  }\\n\\n  draining = false;\\n\\n  if (currentQueue.length) {\\n    queue = currentQueue.concat(queue);\\n  } else {\\n    queueIndex = -1;\\n  }\\n\\n  if (queue.length) {\\n    drainQueue();\\n  }\\n}\\n\\nfunction drainQueue() {\\n  if (draining) {\\n    return;\\n  }\\n\\n  var timeout = runTimeout(cleanUpNextTick);\\n  draining = true;\\n  var len = queue.length;\\n\\n  while (len) {\\n    currentQueue = queue;\\n    queue = [];\\n\\n    while (++queueIndex < len) {\\n      if (currentQueue) {\\n        currentQueue[queueIndex].run();\\n      }\\n    }\\n\\n    queueIndex = -1;\\n    len = queue.length;\\n  }\\n\\n  currentQueue = null;\\n  draining = false;\\n  runClearTimeout(timeout);\\n}\\n\\nprocess.nextTick = function (fun) {\\n  var args = new Array(arguments.length - 1);\\n\\n  if (arguments.length > 1) {\\n    for (var i = 1; i < arguments.length; i++) {\\n      args[i - 1] = arguments[i];\\n    }\\n  }\\n\\n  queue.push(new Item(fun, args));\\n\\n  if (queue.length === 1 && !draining) {\\n    runTimeout(drainQueue);\\n  }\\n}; // v8 likes predictible objects\\n\\n\\nfunction Item(fun, array) {\\n  this.fun = fun;\\n  this.array = array;\\n}\\n\\nItem.prototype.run = function () {\\n  this.fun.apply(null, this.array);\\n};\\n\\nprocess.title = 'browser';\\nprocess.browser = true;\\nprocess.env = {};\\nprocess.argv = [];\\nprocess.version = ''; // empty string to avoid regexp issues\\n\\nprocess.versions = {};\\n\\nfunction noop() {}\\n\\nprocess.on = noop;\\nprocess.addListener = noop;\\nprocess.once = noop;\\nprocess.off = noop;\\nprocess.removeListener = noop;\\nprocess.removeAllListeners = noop;\\nprocess.emit = noop;\\nprocess.prependListener = noop;\\nprocess.prependOnceListener = noop;\\n\\nprocess.listeners = function (name) {\\n  return [];\\n};\\n\\nprocess.binding = function (name) {\\n  throw new Error('process.binding is not supported');\\n};\\n\\nprocess.cwd = function () {\\n  return '/';\\n};\\n\\nprocess.chdir = function (dir) {\\n  throw new Error('process.chdir is not supported');\\n};\\n\\nprocess.umask = function () {\\n  return 0;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/process/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/yeast/index.js\":\n/*!*************************************!*\\\n  !*** ./node_modules/yeast/index.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\neval(\"\\n\\nvar alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''),\\n    length = 64,\\n    map = {},\\n    seed = 0,\\n    i = 0,\\n    prev;\\n/**\\n * Return a string representing the specified number.\\n *\\n * @param {Number} num The number to convert.\\n * @returns {String} The string representation of the number.\\n * @api public\\n */\\n\\nfunction encode(num) {\\n  var encoded = '';\\n\\n  do {\\n    encoded = alphabet[num % length] + encoded;\\n    num = Math.floor(num / length);\\n  } while (num > 0);\\n\\n  return encoded;\\n}\\n/**\\n * Return the integer value specified by the given string.\\n *\\n * @param {String} str The string to convert.\\n * @returns {Number} The integer value represented by the string.\\n * @api public\\n */\\n\\n\\nfunction decode(str) {\\n  var decoded = 0;\\n\\n  for (i = 0; i < str.length; i++) {\\n    decoded = decoded * length + map[str.charAt(i)];\\n  }\\n\\n  return decoded;\\n}\\n/**\\n * Yeast: A tiny growing id generator.\\n *\\n * @returns {String} A unique id.\\n * @api public\\n */\\n\\n\\nfunction yeast() {\\n  var now = encode(+new Date());\\n  if (now !== prev) return seed = 0, prev = now;\\n  return now + '.' + encode(seed++);\\n} //\\n// Map each character to its index.\\n//\\n\\n\\nfor (; i < length; i++) {\\n  map[alphabet[i]] = i;\\n} //\\n// Expose the `yeast`, `encode` and `decode` functions.\\n//\\n\\n\\nyeast.encode = encode;\\nyeast.decode = decode;\\nmodule.exports = yeast;\\n\\n//# sourceURL=webpack://eio/./node_modules/yeast/index.js?\");\n\n/***/ })\n\n/******/ });\n});"
  },
  {
    "path": "examples/server/sanic/static/style.css",
    "content": "body { margin: 0; padding: 0; font-family: Helvetica Neue; }\nh1 { margin: 100px 100px 10px; }\nh2 { color: #999; margin: 0 100px 30px; font-weight: normal; }\n#latency { color: red; }\n"
  },
  {
    "path": "examples/server/tornado/README.rst",
    "content": "Engine.IO Examples\n==================\n\nThis directory contains example Engine.IO applications that are compatible\nwith the Tornado framework. These applications require Tornado 5 and Python\n3.5 or later.\n\nsimple.py\n---------\n\nA basic application in which the client sends messages to the server and the\nserver responds.\n\nlatency.py\n----------\n\nA port of the latency application included in the official Engine.IO\nJavascript server. In this application the client sends *ping* messages to\nthe server, which are responded by the server with a *pong*. The client\nmeasures the time it takes for each of these exchanges and plots these in real\ntime to the page.\n\nThis is an ideal application to measure the performance of the different\nasynchronous modes supported by the Engine.IO server.\n\nRunning the Examples\n--------------------\n\nTo run these examples, create a virtual environment, install the requirements\nand then run::\n\n    $ python simple.py\n\nor::\n\n    $ python latency.py\n\nYou can then access the application from your web browser at\n``http://localhost:8888``."
  },
  {
    "path": "examples/server/tornado/latency.py",
    "content": "import os\n\nimport tornado.ioloop\nfrom tornado.options import define, options, parse_command_line\nimport tornado.web\n\nimport engineio\n\ndefine(\"port\", default=8888, help=\"run on the given port\", type=int)\ndefine(\"debug\", default=False, help=\"run in debug mode\")\n\neio = engineio.AsyncServer(async_mode='tornado')\n\n\nclass MainHandler(tornado.web.RequestHandler):\n    def get(self):\n        self.render(\"latency.html\")\n\n\n@eio.on('message')\nasync def message(sid, data):\n    await eio.send(sid, 'pong')\n\n\ndef main():\n    parse_command_line()\n    app = tornado.web.Application(\n        [\n            (r\"/\", MainHandler),\n            (r\"/engine.io/\", engineio.get_tornado_handler(eio)),\n        ],\n        template_path=os.path.join(os.path.dirname(__file__), \"templates\"),\n        static_path=os.path.join(os.path.dirname(__file__), \"static\"),\n        debug=options.debug,\n    )\n    app.listen(options.port)\n    tornado.ioloop.IOLoop.current().start()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/server/tornado/requirements.txt",
    "content": "tornado==6.5.5\npython-engineio\nsix==1.10.0\n"
  },
  {
    "path": "examples/server/tornado/simple.py",
    "content": "import os\n\nimport tornado.ioloop\nfrom tornado.options import define, options, parse_command_line\nimport tornado.web\n\nimport engineio\n\ndefine(\"port\", default=8888, help=\"run on the given port\", type=int)\ndefine(\"debug\", default=False, help=\"run in debug mode\")\n\neio = engineio.AsyncServer(async_mode='tornado')\n\n\nclass MainHandler(tornado.web.RequestHandler):\n    def get(self):\n        self.render(\"simple.html\")\n\n\n@eio.on('connect')\ndef connect(sid, environ):\n    print(\"connect \", sid)\n\n\n@eio.on('message')\nasync def message(sid, data):\n    print('message from', sid, data)\n    await eio.send(sid, 'Thank you for your message!')\n\n\n@eio.on('disconnect')\ndef disconnect(sid, reason):\n    print('disconnect ', sid, reason)\n\n\ndef main():\n    parse_command_line()\n    app = tornado.web.Application(\n        [\n            (r\"/\", MainHandler),\n            (r\"/engine.io/\", engineio.get_tornado_handler(eio)),\n        ],\n        template_path=os.path.join(os.path.dirname(__file__), \"templates\"),\n        static_path=os.path.join(os.path.dirname(__file__), \"static\"),\n        debug=options.debug,\n    )\n    app.listen(options.port)\n    tornado.ioloop.IOLoop.current().start()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/server/tornado/static/engine.io.js",
    "content": "/*!\n * Engine.IO v4.0.4\n * (c) 2014-2020 Guillermo Rauch\n * Released under the MIT License.\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"eio\"] = factory();\n\telse\n\t\troot[\"eio\"] = factory();\n})((() => {\n      if (typeof self !== 'undefined') {\n          return self;\n      } else if (typeof window !== 'undefined') {\n          return window;\n      } else if (typeof global !== 'undefined') {\n          return global;\n      } else {\n          return Function('return this')();\n      }\n    })(), function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./lib/index.js\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./lib/globalThis.browser.js\":\n/*!***********************************!*\\\n  !*** ./lib/globalThis.browser.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports = function () {\\n  if (typeof self !== \\\"undefined\\\") {\\n    return self;\\n  } else if (typeof window !== \\\"undefined\\\") {\\n    return window;\\n  } else {\\n    return Function(\\\"return this\\\")();\\n  }\\n}();\\n\\n//# sourceURL=webpack://eio/./lib/globalThis.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/index.js\":\n/*!**********************!*\\\n  !*** ./lib/index.js ***!\n  \\**********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var Socket = __webpack_require__(/*! ./socket */ \\\"./lib/socket.js\\\");\\n\\nmodule.exports = function (uri, opts) {\\n  return new Socket(uri, opts);\\n};\\n/**\\n * Expose deps for legacy compatibility\\n * and standalone browser access.\\n */\\n\\n\\nmodule.exports.Socket = Socket;\\nmodule.exports.protocol = Socket.protocol; // this is an int\\n\\nmodule.exports.Transport = __webpack_require__(/*! ./transport */ \\\"./lib/transport.js\\\");\\nmodule.exports.transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\nmodule.exports.parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\n//# sourceURL=webpack://eio/./lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/socket.js\":\n/*!***********************!*\\\n  !*** ./lib/socket.js ***!\n  \\***********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:socket\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseuri = __webpack_require__(/*! parseuri */ \\\"./node_modules/parseuri/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar Socket =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Socket, _Emitter);\\n\\n  /**\\n   * Socket constructor.\\n   *\\n   * @param {String|Object} uri or options\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Socket(uri) {\\n    var _this;\\n\\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\\n\\n    _classCallCheck(this, Socket);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Socket).call(this));\\n\\n    if (uri && \\\"object\\\" === _typeof(uri)) {\\n      opts = uri;\\n      uri = null;\\n    }\\n\\n    if (uri) {\\n      uri = parseuri(uri);\\n      opts.hostname = uri.host;\\n      opts.secure = uri.protocol === \\\"https\\\" || uri.protocol === \\\"wss\\\";\\n      opts.port = uri.port;\\n      if (uri.query) opts.query = uri.query;\\n    } else if (opts.host) {\\n      opts.hostname = parseuri(opts.host).host;\\n    }\\n\\n    _this.secure = null != opts.secure ? opts.secure : typeof location !== \\\"undefined\\\" && \\\"https:\\\" === location.protocol;\\n\\n    if (opts.hostname && !opts.port) {\\n      // if no port is specified manually, use the protocol default\\n      opts.port = _this.secure ? \\\"443\\\" : \\\"80\\\";\\n    }\\n\\n    _this.hostname = opts.hostname || (typeof location !== \\\"undefined\\\" ? location.hostname : \\\"localhost\\\");\\n    _this.port = opts.port || (typeof location !== \\\"undefined\\\" && location.port ? location.port : _this.secure ? 443 : 80);\\n    _this.transports = opts.transports || [\\\"polling\\\", \\\"websocket\\\"];\\n    _this.readyState = \\\"\\\";\\n    _this.writeBuffer = [];\\n    _this.prevBufferLen = 0;\\n    _this.opts = _extends({\\n      path: \\\"/engine.io\\\",\\n      agent: false,\\n      withCredentials: false,\\n      upgrade: true,\\n      jsonp: true,\\n      timestampParam: \\\"t\\\",\\n      policyPort: 843,\\n      rememberUpgrade: false,\\n      rejectUnauthorized: true,\\n      perMessageDeflate: {\\n        threshold: 1024\\n      },\\n      transportOptions: {}\\n    }, opts);\\n    _this.opts.path = _this.opts.path.replace(/\\\\/$/, \\\"\\\") + \\\"/\\\";\\n\\n    if (typeof _this.opts.query === \\\"string\\\") {\\n      _this.opts.query = parseqs.decode(_this.opts.query);\\n    } // set on handshake\\n\\n\\n    _this.id = null;\\n    _this.upgrades = null;\\n    _this.pingInterval = null;\\n    _this.pingTimeout = null; // set on heartbeat\\n\\n    _this.pingTimeoutTimer = null;\\n\\n    _this.open();\\n\\n    return _this;\\n  }\\n  /**\\n   * Creates transport of the given type.\\n   *\\n   * @param {String} transport name\\n   * @return {Transport}\\n   * @api private\\n   */\\n\\n\\n  _createClass(Socket, [{\\n    key: \\\"createTransport\\\",\\n    value: function createTransport(name) {\\n      debug('creating transport \\\"%s\\\"', name);\\n      var query = clone(this.opts.query); // append engine.io protocol identifier\\n\\n      query.EIO = parser.protocol; // transport name\\n\\n      query.transport = name; // session id if we already have one\\n\\n      if (this.id) query.sid = this.id;\\n\\n      var opts = _extends({}, this.opts.transportOptions[name], this.opts, {\\n        query: query,\\n        socket: this,\\n        hostname: this.hostname,\\n        secure: this.secure,\\n        port: this.port\\n      });\\n\\n      debug(\\\"options: %j\\\", opts);\\n      return new transports[name](opts);\\n    }\\n    /**\\n     * Initializes transport to use and starts probe.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      var transport;\\n\\n      if (this.opts.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf(\\\"websocket\\\") !== -1) {\\n        transport = \\\"websocket\\\";\\n      } else if (0 === this.transports.length) {\\n        // Emit error on next tick so it can be listened to\\n        var self = this;\\n        setTimeout(function () {\\n          self.emit(\\\"error\\\", \\\"No transports available\\\");\\n        }, 0);\\n        return;\\n      } else {\\n        transport = this.transports[0];\\n      }\\n\\n      this.readyState = \\\"opening\\\"; // Retry with the next transport if the transport is disabled (jsonp: false)\\n\\n      try {\\n        transport = this.createTransport(transport);\\n      } catch (e) {\\n        debug(\\\"error while creating transport: %s\\\", e);\\n        this.transports.shift();\\n        this.open();\\n        return;\\n      }\\n\\n      transport.open();\\n      this.setTransport(transport);\\n    }\\n    /**\\n     * Sets the current transport. Disables the existing one (if any).\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"setTransport\\\",\\n    value: function setTransport(transport) {\\n      debug(\\\"setting transport %s\\\", transport.name);\\n      var self = this;\\n\\n      if (this.transport) {\\n        debug(\\\"clearing existing transport %s\\\", this.transport.name);\\n        this.transport.removeAllListeners();\\n      } // set up transport\\n\\n\\n      this.transport = transport; // set up transport listeners\\n\\n      transport.on(\\\"drain\\\", function () {\\n        self.onDrain();\\n      }).on(\\\"packet\\\", function (packet) {\\n        self.onPacket(packet);\\n      }).on(\\\"error\\\", function (e) {\\n        self.onError(e);\\n      }).on(\\\"close\\\", function () {\\n        self.onClose(\\\"transport close\\\");\\n      });\\n    }\\n    /**\\n     * Probes a transport.\\n     *\\n     * @param {String} transport name\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"probe\\\",\\n    value: function probe(name) {\\n      debug('probing transport \\\"%s\\\"', name);\\n      var transport = this.createTransport(name, {\\n        probe: 1\\n      });\\n      var failed = false;\\n      var self = this;\\n      Socket.priorWebsocketSuccess = false;\\n\\n      function onTransportOpen() {\\n        if (self.onlyBinaryUpgrades) {\\n          var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;\\n          failed = failed || upgradeLosesBinary;\\n        }\\n\\n        if (failed) return;\\n        debug('probe transport \\\"%s\\\" opened', name);\\n        transport.send([{\\n          type: \\\"ping\\\",\\n          data: \\\"probe\\\"\\n        }]);\\n        transport.once(\\\"packet\\\", function (msg) {\\n          if (failed) return;\\n\\n          if (\\\"pong\\\" === msg.type && \\\"probe\\\" === msg.data) {\\n            debug('probe transport \\\"%s\\\" pong', name);\\n            self.upgrading = true;\\n            self.emit(\\\"upgrading\\\", transport);\\n            if (!transport) return;\\n            Socket.priorWebsocketSuccess = \\\"websocket\\\" === transport.name;\\n            debug('pausing current transport \\\"%s\\\"', self.transport.name);\\n            self.transport.pause(function () {\\n              if (failed) return;\\n              if (\\\"closed\\\" === self.readyState) return;\\n              debug(\\\"changing transport and sending upgrade packet\\\");\\n              cleanup();\\n              self.setTransport(transport);\\n              transport.send([{\\n                type: \\\"upgrade\\\"\\n              }]);\\n              self.emit(\\\"upgrade\\\", transport);\\n              transport = null;\\n              self.upgrading = false;\\n              self.flush();\\n            });\\n          } else {\\n            debug('probe transport \\\"%s\\\" failed', name);\\n            var err = new Error(\\\"probe error\\\");\\n            err.transport = transport.name;\\n            self.emit(\\\"upgradeError\\\", err);\\n          }\\n        });\\n      }\\n\\n      function freezeTransport() {\\n        if (failed) return; // Any callback called by transport should be ignored since now\\n\\n        failed = true;\\n        cleanup();\\n        transport.close();\\n        transport = null;\\n      } // Handle any error that happens while probing\\n\\n\\n      function onerror(err) {\\n        var error = new Error(\\\"probe error: \\\" + err);\\n        error.transport = transport.name;\\n        freezeTransport();\\n        debug('probe transport \\\"%s\\\" failed because of error: %s', name, err);\\n        self.emit(\\\"upgradeError\\\", error);\\n      }\\n\\n      function onTransportClose() {\\n        onerror(\\\"transport closed\\\");\\n      } // When the socket is closed while we're probing\\n\\n\\n      function onclose() {\\n        onerror(\\\"socket closed\\\");\\n      } // When the socket is upgraded while we're probing\\n\\n\\n      function onupgrade(to) {\\n        if (transport && to.name !== transport.name) {\\n          debug('\\\"%s\\\" works - aborting \\\"%s\\\"', to.name, transport.name);\\n          freezeTransport();\\n        }\\n      } // Remove all listeners on the transport and on self\\n\\n\\n      function cleanup() {\\n        transport.removeListener(\\\"open\\\", onTransportOpen);\\n        transport.removeListener(\\\"error\\\", onerror);\\n        transport.removeListener(\\\"close\\\", onTransportClose);\\n        self.removeListener(\\\"close\\\", onclose);\\n        self.removeListener(\\\"upgrading\\\", onupgrade);\\n      }\\n\\n      transport.once(\\\"open\\\", onTransportOpen);\\n      transport.once(\\\"error\\\", onerror);\\n      transport.once(\\\"close\\\", onTransportClose);\\n      this.once(\\\"close\\\", onclose);\\n      this.once(\\\"upgrading\\\", onupgrade);\\n      transport.open();\\n    }\\n    /**\\n     * Called when connection is deemed open.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      debug(\\\"socket open\\\");\\n      this.readyState = \\\"open\\\";\\n      Socket.priorWebsocketSuccess = \\\"websocket\\\" === this.transport.name;\\n      this.emit(\\\"open\\\");\\n      this.flush(); // we check for `readyState` in case an `open`\\n      // listener already closed the socket\\n\\n      if (\\\"open\\\" === this.readyState && this.opts.upgrade && this.transport.pause) {\\n        debug(\\\"starting upgrade probes\\\");\\n        var i = 0;\\n        var l = this.upgrades.length;\\n\\n        for (; i < l; i++) {\\n          this.probe(this.upgrades[i]);\\n        }\\n      }\\n    }\\n    /**\\n     * Handles a packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket receive: type \\\"%s\\\", data \\\"%s\\\"', packet.type, packet.data);\\n        this.emit(\\\"packet\\\", packet); // Socket is live - any packet counts\\n\\n        this.emit(\\\"heartbeat\\\");\\n\\n        switch (packet.type) {\\n          case \\\"open\\\":\\n            this.onHandshake(JSON.parse(packet.data));\\n            break;\\n\\n          case \\\"ping\\\":\\n            this.resetPingTimeout();\\n            this.sendPacket(\\\"pong\\\");\\n            this.emit(\\\"pong\\\");\\n            break;\\n\\n          case \\\"error\\\":\\n            var err = new Error(\\\"server error\\\");\\n            err.code = packet.data;\\n            this.onError(err);\\n            break;\\n\\n          case \\\"message\\\":\\n            this.emit(\\\"data\\\", packet.data);\\n            this.emit(\\\"message\\\", packet.data);\\n            break;\\n        }\\n      } else {\\n        debug('packet received with socket readyState \\\"%s\\\"', this.readyState);\\n      }\\n    }\\n    /**\\n     * Called upon handshake completion.\\n     *\\n     * @param {Object} handshake obj\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onHandshake\\\",\\n    value: function onHandshake(data) {\\n      this.emit(\\\"handshake\\\", data);\\n      this.id = data.sid;\\n      this.transport.query.sid = data.sid;\\n      this.upgrades = this.filterUpgrades(data.upgrades);\\n      this.pingInterval = data.pingInterval;\\n      this.pingTimeout = data.pingTimeout;\\n      this.onOpen(); // In case open handler closes socket\\n\\n      if (\\\"closed\\\" === this.readyState) return;\\n      this.resetPingTimeout();\\n    }\\n    /**\\n     * Sets and resets ping timeout timer based on server pings.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"resetPingTimeout\\\",\\n    value: function resetPingTimeout() {\\n      var _this2 = this;\\n\\n      clearTimeout(this.pingTimeoutTimer);\\n      this.pingTimeoutTimer = setTimeout(function () {\\n        _this2.onClose(\\\"ping timeout\\\");\\n      }, this.pingInterval + this.pingTimeout);\\n    }\\n    /**\\n     * Called on `drain` event\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onDrain\\\",\\n    value: function onDrain() {\\n      this.writeBuffer.splice(0, this.prevBufferLen); // setting prevBufferLen = 0 is very important\\n      // for example, when upgrading, upgrade packet is sent over,\\n      // and a nonzero prevBufferLen could cause problems on `drain`\\n\\n      this.prevBufferLen = 0;\\n\\n      if (0 === this.writeBuffer.length) {\\n        this.emit(\\\"drain\\\");\\n      } else {\\n        this.flush();\\n      }\\n    }\\n    /**\\n     * Flush write buffers.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"flush\\\",\\n    value: function flush() {\\n      if (\\\"closed\\\" !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) {\\n        debug(\\\"flushing %d packets in socket\\\", this.writeBuffer.length);\\n        this.transport.send(this.writeBuffer); // keep track of current length of writeBuffer\\n        // splice writeBuffer and callbackBuffer on `drain`\\n\\n        this.prevBufferLen = this.writeBuffer.length;\\n        this.emit(\\\"flush\\\");\\n      }\\n    }\\n    /**\\n     * Sends a message.\\n     *\\n     * @param {String} message.\\n     * @param {Function} callback function.\\n     * @param {Object} options.\\n     * @return {Socket} for chaining.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n    /**\\n     * Sends a packet.\\n     *\\n     * @param {String} packet type.\\n     * @param {String} data.\\n     * @param {Object} options.\\n     * @param {Function} callback function.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"sendPacket\\\",\\n    value: function sendPacket(type, data, options, fn) {\\n      if (\\\"function\\\" === typeof data) {\\n        fn = data;\\n        data = undefined;\\n      }\\n\\n      if (\\\"function\\\" === typeof options) {\\n        fn = options;\\n        options = null;\\n      }\\n\\n      if (\\\"closing\\\" === this.readyState || \\\"closed\\\" === this.readyState) {\\n        return;\\n      }\\n\\n      options = options || {};\\n      options.compress = false !== options.compress;\\n      var packet = {\\n        type: type,\\n        data: data,\\n        options: options\\n      };\\n      this.emit(\\\"packetCreate\\\", packet);\\n      this.writeBuffer.push(packet);\\n      if (fn) this.once(\\\"flush\\\", fn);\\n      this.flush();\\n    }\\n    /**\\n     * Closes the connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      var self = this;\\n\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.readyState = \\\"closing\\\";\\n\\n        if (this.writeBuffer.length) {\\n          this.once(\\\"drain\\\", function () {\\n            if (this.upgrading) {\\n              waitForUpgrade();\\n            } else {\\n              close();\\n            }\\n          });\\n        } else if (this.upgrading) {\\n          waitForUpgrade();\\n        } else {\\n          close();\\n        }\\n      }\\n\\n      function close() {\\n        self.onClose(\\\"forced close\\\");\\n        debug(\\\"socket closing - telling transport to close\\\");\\n        self.transport.close();\\n      }\\n\\n      function cleanupAndClose() {\\n        self.removeListener(\\\"upgrade\\\", cleanupAndClose);\\n        self.removeListener(\\\"upgradeError\\\", cleanupAndClose);\\n        close();\\n      }\\n\\n      function waitForUpgrade() {\\n        // wait for upgrade to finish since we can't send packets while pausing a transport\\n        self.once(\\\"upgrade\\\", cleanupAndClose);\\n        self.once(\\\"upgradeError\\\", cleanupAndClose);\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Called upon transport error\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      debug(\\\"socket error %j\\\", err);\\n      Socket.priorWebsocketSuccess = false;\\n      this.emit(\\\"error\\\", err);\\n      this.onClose(\\\"transport error\\\", err);\\n    }\\n    /**\\n     * Called upon transport close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose(reason, desc) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket close with reason: \\\"%s\\\"', reason);\\n        var self = this; // clear timers\\n\\n        clearTimeout(this.pingIntervalTimer);\\n        clearTimeout(this.pingTimeoutTimer); // stop event from firing again for transport\\n\\n        this.transport.removeAllListeners(\\\"close\\\"); // ensure transport won't stay open\\n\\n        this.transport.close(); // ignore further transport communication\\n\\n        this.transport.removeAllListeners(); // set ready state\\n\\n        this.readyState = \\\"closed\\\"; // clear session id\\n\\n        this.id = null; // emit close event\\n\\n        this.emit(\\\"close\\\", reason, desc); // clean buffers after, so users can still\\n        // grab the buffers on `close` event\\n\\n        self.writeBuffer = [];\\n        self.prevBufferLen = 0;\\n      }\\n    }\\n    /**\\n     * Filters upgrades, returning only those matching client transports.\\n     *\\n     * @param {Array} server upgrades\\n     * @api private\\n     *\\n     */\\n\\n  }, {\\n    key: \\\"filterUpgrades\\\",\\n    value: function filterUpgrades(upgrades) {\\n      var filteredUpgrades = [];\\n      var i = 0;\\n      var j = upgrades.length;\\n\\n      for (; i < j; i++) {\\n        if (~this.transports.indexOf(upgrades[i])) filteredUpgrades.push(upgrades[i]);\\n      }\\n\\n      return filteredUpgrades;\\n    }\\n  }]);\\n\\n  return Socket;\\n}(Emitter);\\n\\nSocket.priorWebsocketSuccess = false;\\n/**\\n * Protocol version.\\n *\\n * @api public\\n */\\n\\nSocket.protocol = parser.protocol; // this is an int\\n\\nfunction clone(obj) {\\n  var o = {};\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      o[i] = obj[i];\\n    }\\n  }\\n\\n  return o;\\n}\\n\\nmodule.exports = Socket;\\n\\n//# sourceURL=webpack://eio/./lib/socket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transport.js\":\n/*!**************************!*\\\n  !*** ./lib/transport.js ***!\n  \\**************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar Transport =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Transport, _Emitter);\\n\\n  /**\\n   * Transport abstract constructor.\\n   *\\n   * @param {Object} options.\\n   * @api private\\n   */\\n  function Transport(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, Transport);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Transport).call(this));\\n    _this.opts = opts;\\n    _this.query = opts.query;\\n    _this.readyState = \\\"\\\";\\n    _this.socket = opts.socket;\\n    return _this;\\n  }\\n  /**\\n   * Emits an error.\\n   *\\n   * @param {String} str\\n   * @return {Transport} for chaining\\n   * @api public\\n   */\\n\\n\\n  _createClass(Transport, [{\\n    key: \\\"onError\\\",\\n    value: function onError(msg, desc) {\\n      var err = new Error(msg);\\n      err.type = \\\"TransportError\\\";\\n      err.description = desc;\\n      this.emit(\\\"error\\\", err);\\n      return this;\\n    }\\n    /**\\n     * Opens the transport.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      if (\\\"closed\\\" === this.readyState || \\\"\\\" === this.readyState) {\\n        this.readyState = \\\"opening\\\";\\n        this.doOpen();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Closes the transport.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.doClose();\\n        this.onClose();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Sends multiple packets.\\n     *\\n     * @param {Array} packets\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(packets) {\\n      if (\\\"open\\\" === this.readyState) {\\n        this.write(packets);\\n      } else {\\n        throw new Error(\\\"Transport not open\\\");\\n      }\\n    }\\n    /**\\n     * Called upon open\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      this.readyState = \\\"open\\\";\\n      this.writable = true;\\n      this.emit(\\\"open\\\");\\n    }\\n    /**\\n     * Called with data.\\n     *\\n     * @param {String} data\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var packet = parser.decodePacket(data, this.socket.binaryType);\\n      this.onPacket(packet);\\n    }\\n    /**\\n     * Called with a decoded packet.\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      this.emit(\\\"packet\\\", packet);\\n    }\\n    /**\\n     * Called upon close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      this.readyState = \\\"closed\\\";\\n      this.emit(\\\"close\\\");\\n    }\\n  }]);\\n\\n  return Transport;\\n}(Emitter);\\n\\nmodule.exports = Transport;\\n\\n//# sourceURL=webpack://eio/./lib/transport.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/index.js\":\n/*!*********************************!*\\\n  !*** ./lib/transports/index.js ***!\n  \\*********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar XHR = __webpack_require__(/*! ./polling-xhr */ \\\"./lib/transports/polling-xhr.js\\\");\\n\\nvar JSONP = __webpack_require__(/*! ./polling-jsonp */ \\\"./lib/transports/polling-jsonp.js\\\");\\n\\nvar websocket = __webpack_require__(/*! ./websocket */ \\\"./lib/transports/websocket.js\\\");\\n\\nexports.polling = polling;\\nexports.websocket = websocket;\\n/**\\n * Polling transport polymorphic constructor.\\n * Decides on xhr vs jsonp based on feature detection.\\n *\\n * @api private\\n */\\n\\nfunction polling(opts) {\\n  var xhr;\\n  var xd = false;\\n  var xs = false;\\n  var jsonp = false !== opts.jsonp;\\n\\n  if (typeof location !== \\\"undefined\\\") {\\n    var isSSL = \\\"https:\\\" === location.protocol;\\n    var port = location.port; // some user agents have empty `location.port`\\n\\n    if (!port) {\\n      port = isSSL ? 443 : 80;\\n    }\\n\\n    xd = opts.hostname !== location.hostname || port !== opts.port;\\n    xs = opts.secure !== isSSL;\\n  }\\n\\n  opts.xdomain = xd;\\n  opts.xscheme = xs;\\n  xhr = new XMLHttpRequest(opts);\\n\\n  if (\\\"open\\\" in xhr && !opts.forceJSONP) {\\n    return new XHR(opts);\\n  } else {\\n    if (!jsonp) throw new Error(\\\"JSONP disabled\\\");\\n    return new JSONP(opts);\\n  }\\n}\\n\\n//# sourceURL=webpack://eio/./lib/transports/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-jsonp.js\":\n/*!*****************************************!*\\\n  !*** ./lib/transports/polling-jsonp.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _get(target, property, receiver) { if (typeof Reflect !== \\\"undefined\\\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\\n\\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar rNewline = /\\\\n/g;\\nvar rEscapedNewline = /\\\\\\\\n/g;\\n/**\\n * Global JSONP callbacks.\\n */\\n\\nvar callbacks;\\n/**\\n * Noop.\\n */\\n\\nfunction empty() {}\\n\\nvar JSONPPolling =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(JSONPPolling, _Polling);\\n\\n  /**\\n   * JSONP Polling constructor.\\n   *\\n   * @param {Object} opts.\\n   * @api public\\n   */\\n  function JSONPPolling(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, JSONPPolling);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(JSONPPolling).call(this, opts));\\n    _this.query = _this.query || {}; // define global callbacks array if not present\\n    // we do this here (lazily) to avoid unneeded global pollution\\n\\n    if (!callbacks) {\\n      // we need to consider multiple engines in the same page\\n      callbacks = globalThis.___eio = globalThis.___eio || [];\\n    } // callback identifier\\n\\n\\n    _this.index = callbacks.length; // add callback to jsonp global\\n\\n    var self = _assertThisInitialized(_this);\\n\\n    callbacks.push(function (msg) {\\n      self.onData(msg);\\n    }); // append to query string\\n\\n    _this.query.j = _this.index; // prevent spurious errors from being emitted when the window is unloaded\\n\\n    if (typeof addEventListener === \\\"function\\\") {\\n      addEventListener(\\\"beforeunload\\\", function () {\\n        if (self.script) self.script.onerror = empty;\\n      }, false);\\n    }\\n\\n    return _this;\\n  }\\n  /**\\n   * JSONP only supports binary as base64 encoded strings\\n   */\\n\\n\\n  _createClass(JSONPPolling, [{\\n    key: \\\"doClose\\\",\\n\\n    /**\\n     * Closes the socket.\\n     *\\n     * @api private\\n     */\\n    value: function doClose() {\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      if (this.form) {\\n        this.form.parentNode.removeChild(this.form);\\n        this.form = null;\\n        this.iframe = null;\\n      }\\n\\n      _get(_getPrototypeOf(JSONPPolling.prototype), \\\"doClose\\\", this).call(this);\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      var self = this;\\n      var script = document.createElement(\\\"script\\\");\\n\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      script.async = true;\\n      script.src = this.uri();\\n\\n      script.onerror = function (e) {\\n        self.onError(\\\"jsonp poll error\\\", e);\\n      };\\n\\n      var insertAt = document.getElementsByTagName(\\\"script\\\")[0];\\n\\n      if (insertAt) {\\n        insertAt.parentNode.insertBefore(script, insertAt);\\n      } else {\\n        (document.head || document.body).appendChild(script);\\n      }\\n\\n      this.script = script;\\n      var isUAgecko = \\\"undefined\\\" !== typeof navigator && /gecko/i.test(navigator.userAgent);\\n\\n      if (isUAgecko) {\\n        setTimeout(function () {\\n          var iframe = document.createElement(\\\"iframe\\\");\\n          document.body.appendChild(iframe);\\n          document.body.removeChild(iframe);\\n        }, 100);\\n      }\\n    }\\n    /**\\n     * Writes with a hidden iframe.\\n     *\\n     * @param {String} data to send\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var self = this;\\n      var iframe;\\n\\n      if (!this.form) {\\n        var form = document.createElement(\\\"form\\\");\\n        var area = document.createElement(\\\"textarea\\\");\\n        var id = this.iframeId = \\\"eio_iframe_\\\" + this.index;\\n        form.className = \\\"socketio\\\";\\n        form.style.position = \\\"absolute\\\";\\n        form.style.top = \\\"-1000px\\\";\\n        form.style.left = \\\"-1000px\\\";\\n        form.target = id;\\n        form.method = \\\"POST\\\";\\n        form.setAttribute(\\\"accept-charset\\\", \\\"utf-8\\\");\\n        area.name = \\\"d\\\";\\n        form.appendChild(area);\\n        document.body.appendChild(form);\\n        this.form = form;\\n        this.area = area;\\n      }\\n\\n      this.form.action = this.uri();\\n\\n      function complete() {\\n        initIframe();\\n        fn();\\n      }\\n\\n      function initIframe() {\\n        if (self.iframe) {\\n          try {\\n            self.form.removeChild(self.iframe);\\n          } catch (e) {\\n            self.onError(\\\"jsonp polling iframe removal error\\\", e);\\n          }\\n        }\\n\\n        try {\\n          // ie6 dynamic iframes with target=\\\"\\\" support (thanks Chris Lambacher)\\n          var html = '<iframe src=\\\"javascript:0\\\" name=\\\"' + self.iframeId + '\\\">';\\n          iframe = document.createElement(html);\\n        } catch (e) {\\n          iframe = document.createElement(\\\"iframe\\\");\\n          iframe.name = self.iframeId;\\n          iframe.src = \\\"javascript:0\\\";\\n        }\\n\\n        iframe.id = self.iframeId;\\n        self.form.appendChild(iframe);\\n        self.iframe = iframe;\\n      }\\n\\n      initIframe(); // escape \\\\n to prevent it from being converted into \\\\r\\\\n by some UAs\\n      // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side\\n\\n      data = data.replace(rEscapedNewline, \\\"\\\\\\\\\\\\n\\\");\\n      this.area.value = data.replace(rNewline, \\\"\\\\\\\\n\\\");\\n\\n      try {\\n        this.form.submit();\\n      } catch (e) {}\\n\\n      if (this.iframe.attachEvent) {\\n        this.iframe.onreadystatechange = function () {\\n          if (self.iframe.readyState === \\\"complete\\\") {\\n            complete();\\n          }\\n        };\\n      } else {\\n        this.iframe.onload = complete;\\n      }\\n    }\\n  }, {\\n    key: \\\"supportsBinary\\\",\\n    get: function get() {\\n      return false;\\n    }\\n  }]);\\n\\n  return JSONPPolling;\\n}(Polling);\\n\\nmodule.exports = JSONPPolling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-jsonp.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-xhr.js\":\n/*!***************************************!*\\\n  !*** ./lib/transports/polling-xhr.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\n/* global attachEvent */\\nvar XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling-xhr\\\");\\n/**\\n * Empty function\\n */\\n\\n\\nfunction empty() {}\\n\\nvar hasXHR2 = function () {\\n  var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\n  var xhr = new XMLHttpRequest({\\n    xdomain: false\\n  });\\n  return null != xhr.responseType;\\n}();\\n\\nvar XHR =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(XHR, _Polling);\\n\\n  /**\\n   * XHR Polling constructor.\\n   *\\n   * @param {Object} opts\\n   * @api public\\n   */\\n  function XHR(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, XHR);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(XHR).call(this, opts));\\n\\n    if (typeof location !== \\\"undefined\\\") {\\n      var isSSL = \\\"https:\\\" === location.protocol;\\n      var port = location.port; // some user agents have empty `location.port`\\n\\n      if (!port) {\\n        port = isSSL ? 443 : 80;\\n      }\\n\\n      _this.xd = typeof location !== \\\"undefined\\\" && opts.hostname !== location.hostname || port !== opts.port;\\n      _this.xs = opts.secure !== isSSL;\\n    }\\n    /**\\n     * XHR supports binary\\n     */\\n\\n\\n    var forceBase64 = opts && opts.forceBase64;\\n    _this.supportsBinary = hasXHR2 && !forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Creates a request.\\n   *\\n   * @param {String} method\\n   * @api private\\n   */\\n\\n\\n  _createClass(XHR, [{\\n    key: \\\"request\\\",\\n    value: function request() {\\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\\n\\n      _extends(opts, {\\n        xd: this.xd,\\n        xs: this.xs\\n      }, this.opts);\\n\\n      return new Request(this.uri(), opts);\\n    }\\n    /**\\n     * Sends data.\\n     *\\n     * @param {String} data to send.\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var req = this.request({\\n        method: \\\"POST\\\",\\n        data: data\\n      });\\n      var self = this;\\n      req.on(\\\"success\\\", fn);\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr post error\\\", err);\\n      });\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      debug(\\\"xhr poll\\\");\\n      var req = this.request();\\n      var self = this;\\n      req.on(\\\"data\\\", function (data) {\\n        self.onData(data);\\n      });\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr poll error\\\", err);\\n      });\\n      this.pollXhr = req;\\n    }\\n  }]);\\n\\n  return XHR;\\n}(Polling);\\n\\nvar Request =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Request, _Emitter);\\n\\n  /**\\n   * Request constructor\\n   *\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Request(uri, opts) {\\n    var _this2;\\n\\n    _classCallCheck(this, Request);\\n\\n    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Request).call(this));\\n    _this2.opts = opts;\\n    _this2.method = opts.method || \\\"GET\\\";\\n    _this2.uri = uri;\\n    _this2.async = false !== opts.async;\\n    _this2.data = undefined !== opts.data ? opts.data : null;\\n\\n    _this2.create();\\n\\n    return _this2;\\n  }\\n  /**\\n   * Creates the XHR object and sends the request.\\n   *\\n   * @api private\\n   */\\n\\n\\n  _createClass(Request, [{\\n    key: \\\"create\\\",\\n    value: function create() {\\n      var opts = pick(this.opts, \\\"agent\\\", \\\"enablesXDR\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\");\\n      opts.xdomain = !!this.opts.xd;\\n      opts.xscheme = !!this.opts.xs;\\n      var xhr = this.xhr = new XMLHttpRequest(opts);\\n      var self = this;\\n\\n      try {\\n        debug(\\\"xhr open %s: %s\\\", this.method, this.uri);\\n        xhr.open(this.method, this.uri, this.async);\\n\\n        try {\\n          if (this.opts.extraHeaders) {\\n            xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);\\n\\n            for (var i in this.opts.extraHeaders) {\\n              if (this.opts.extraHeaders.hasOwnProperty(i)) {\\n                xhr.setRequestHeader(i, this.opts.extraHeaders[i]);\\n              }\\n            }\\n          }\\n        } catch (e) {}\\n\\n        if (\\\"POST\\\" === this.method) {\\n          try {\\n            xhr.setRequestHeader(\\\"Content-type\\\", \\\"text/plain;charset=UTF-8\\\");\\n          } catch (e) {}\\n        }\\n\\n        try {\\n          xhr.setRequestHeader(\\\"Accept\\\", \\\"*/*\\\");\\n        } catch (e) {} // ie6 check\\n\\n\\n        if (\\\"withCredentials\\\" in xhr) {\\n          xhr.withCredentials = this.opts.withCredentials;\\n        }\\n\\n        if (this.opts.requestTimeout) {\\n          xhr.timeout = this.opts.requestTimeout;\\n        }\\n\\n        if (this.hasXDR()) {\\n          xhr.onload = function () {\\n            self.onLoad();\\n          };\\n\\n          xhr.onerror = function () {\\n            self.onError(xhr.responseText);\\n          };\\n        } else {\\n          xhr.onreadystatechange = function () {\\n            if (4 !== xhr.readyState) return;\\n\\n            if (200 === xhr.status || 1223 === xhr.status) {\\n              self.onLoad();\\n            } else {\\n              // make sure the `error` event handler that's user-set\\n              // does not throw in the same tick and gets caught here\\n              setTimeout(function () {\\n                self.onError(typeof xhr.status === \\\"number\\\" ? xhr.status : 0);\\n              }, 0);\\n            }\\n          };\\n        }\\n\\n        debug(\\\"xhr data %s\\\", this.data);\\n        xhr.send(this.data);\\n      } catch (e) {\\n        // Need to defer since .create() is called directly from the constructor\\n        // and thus the 'error' event can only be only bound *after* this exception\\n        // occurs.  Therefore, also, we cannot throw here at all.\\n        setTimeout(function () {\\n          self.onError(e);\\n        }, 0);\\n        return;\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        this.index = Request.requestsCount++;\\n        Request.requests[this.index] = this;\\n      }\\n    }\\n    /**\\n     * Called upon successful response.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onSuccess\\\",\\n    value: function onSuccess() {\\n      this.emit(\\\"success\\\");\\n      this.cleanup();\\n    }\\n    /**\\n     * Called if we have data.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      this.emit(\\\"data\\\", data);\\n      this.onSuccess();\\n    }\\n    /**\\n     * Called upon error.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      this.emit(\\\"error\\\", err);\\n      this.cleanup(true);\\n    }\\n    /**\\n     * Cleans up house.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"cleanup\\\",\\n    value: function cleanup(fromError) {\\n      if (\\\"undefined\\\" === typeof this.xhr || null === this.xhr) {\\n        return;\\n      } // xmlhttprequest\\n\\n\\n      if (this.hasXDR()) {\\n        this.xhr.onload = this.xhr.onerror = empty;\\n      } else {\\n        this.xhr.onreadystatechange = empty;\\n      }\\n\\n      if (fromError) {\\n        try {\\n          this.xhr.abort();\\n        } catch (e) {}\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        delete Request.requests[this.index];\\n      }\\n\\n      this.xhr = null;\\n    }\\n    /**\\n     * Called upon load.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onLoad\\\",\\n    value: function onLoad() {\\n      var data = this.xhr.responseText;\\n\\n      if (data !== null) {\\n        this.onData(data);\\n      }\\n    }\\n    /**\\n     * Check if it has XDomainRequest.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"hasXDR\\\",\\n    value: function hasXDR() {\\n      return typeof XDomainRequest !== \\\"undefined\\\" && !this.xs && this.enablesXDR;\\n    }\\n    /**\\n     * Aborts the request.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"abort\\\",\\n    value: function abort() {\\n      this.cleanup();\\n    }\\n  }]);\\n\\n  return Request;\\n}(Emitter);\\n/**\\n * Aborts pending requests when unloading the window. This is needed to prevent\\n * memory leaks (e.g. when using IE) and to ensure that no spurious error is\\n * emitted.\\n */\\n\\n\\nRequest.requestsCount = 0;\\nRequest.requests = {};\\n\\nif (typeof document !== \\\"undefined\\\") {\\n  if (typeof attachEvent === \\\"function\\\") {\\n    attachEvent(\\\"onunload\\\", unloadHandler);\\n  } else if (typeof addEventListener === \\\"function\\\") {\\n    var terminationEvent = \\\"onpagehide\\\" in globalThis ? \\\"pagehide\\\" : \\\"unload\\\";\\n    addEventListener(terminationEvent, unloadHandler, false);\\n  }\\n}\\n\\nfunction unloadHandler() {\\n  for (var i in Request.requests) {\\n    if (Request.requests.hasOwnProperty(i)) {\\n      Request.requests[i].abort();\\n    }\\n  }\\n}\\n\\nmodule.exports = XHR;\\nmodule.exports.Request = Request;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-xhr.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling.js\":\n/*!***********************************!*\\\n  !*** ./lib/transports/polling.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling\\\");\\n\\nvar Polling =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(Polling, _Transport);\\n\\n  function Polling() {\\n    _classCallCheck(this, Polling);\\n\\n    return _possibleConstructorReturn(this, _getPrototypeOf(Polling).apply(this, arguments));\\n  }\\n\\n  _createClass(Polling, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens the socket (triggers polling). We write a PING message to determine\\n     * when the transport is open.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      this.poll();\\n    }\\n    /**\\n     * Pauses polling.\\n     *\\n     * @param {Function} callback upon buffers are flushed and transport is paused\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"pause\\\",\\n    value: function pause(onPause) {\\n      var self = this;\\n      this.readyState = \\\"pausing\\\";\\n\\n      function pause() {\\n        debug(\\\"paused\\\");\\n        self.readyState = \\\"paused\\\";\\n        onPause();\\n      }\\n\\n      if (this.polling || !this.writable) {\\n        var total = 0;\\n\\n        if (this.polling) {\\n          debug(\\\"we are currently polling - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"pollComplete\\\", function () {\\n            debug(\\\"pre-pause polling complete\\\");\\n            --total || pause();\\n          });\\n        }\\n\\n        if (!this.writable) {\\n          debug(\\\"we are currently writing - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"drain\\\", function () {\\n            debug(\\\"pre-pause writing complete\\\");\\n            --total || pause();\\n          });\\n        }\\n      } else {\\n        pause();\\n      }\\n    }\\n    /**\\n     * Starts polling cycle.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"poll\\\",\\n    value: function poll() {\\n      debug(\\\"polling\\\");\\n      this.polling = true;\\n      this.doPoll();\\n      this.emit(\\\"poll\\\");\\n    }\\n    /**\\n     * Overloads onData to detect payloads.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var self = this;\\n      debug(\\\"polling got data %s\\\", data);\\n\\n      var callback = function callback(packet, index, total) {\\n        // if its the first message we consider the transport open\\n        if (\\\"opening\\\" === self.readyState && packet.type === \\\"open\\\") {\\n          self.onOpen();\\n        } // if its a close packet, we close the ongoing requests\\n\\n\\n        if (\\\"close\\\" === packet.type) {\\n          self.onClose();\\n          return false;\\n        } // otherwise bypass onData and handle the message\\n\\n\\n        self.onPacket(packet);\\n      }; // decode payload\\n\\n\\n      parser.decodePayload(data, this.socket.binaryType).forEach(callback); // if an event did not trigger closing\\n\\n      if (\\\"closed\\\" !== this.readyState) {\\n        // if we got data we're not polling\\n        this.polling = false;\\n        this.emit(\\\"pollComplete\\\");\\n\\n        if (\\\"open\\\" === this.readyState) {\\n          this.poll();\\n        } else {\\n          debug('ignoring poll - transport state \\\"%s\\\"', this.readyState);\\n        }\\n      }\\n    }\\n    /**\\n     * For polling, send a close packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      var self = this;\\n\\n      function close() {\\n        debug(\\\"writing close packet\\\");\\n        self.write([{\\n          type: \\\"close\\\"\\n        }]);\\n      }\\n\\n      if (\\\"open\\\" === this.readyState) {\\n        debug(\\\"transport open - closing\\\");\\n        close();\\n      } else {\\n        // in case we're trying to close while\\n        // handshaking is in progress (GH-164)\\n        debug(\\\"transport not open - deferring close\\\");\\n        this.once(\\\"open\\\", close);\\n      }\\n    }\\n    /**\\n     * Writes a packets payload.\\n     *\\n     * @param {Array} data packets\\n     * @param {Function} drain callback\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var _this = this;\\n\\n      this.writable = false;\\n      parser.encodePayload(packets, function (data) {\\n        _this.doWrite(data, function () {\\n          _this.writable = true;\\n\\n          _this.emit(\\\"drain\\\");\\n        });\\n      });\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"https\\\" : \\\"http\\\";\\n      var port = \\\"\\\"; // cache busting is forced\\n\\n      if (false !== this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      }\\n\\n      if (!this.supportsBinary && !query.sid) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"https\\\" === schema && Number(this.opts.port) !== 443 || \\\"http\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // prepend ? to query\\n\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n\\n    /**\\n     * Transport name.\\n     */\\n    get: function get() {\\n      return \\\"polling\\\";\\n    }\\n  }]);\\n\\n  return Polling;\\n}(Transport);\\n\\nmodule.exports = Polling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket-constructor.browser.js\":\n/*!*********************************************************!*\\\n  !*** ./lib/transports/websocket-constructor.browser.js ***!\n  \\*********************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = {\\n  WebSocket: globalThis.WebSocket || globalThis.MozWebSocket,\\n  usingBrowserWebSocket: true,\\n  defaultBinaryType: \\\"arraybuffer\\\"\\n};\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket-constructor.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket.js\":\n/*!*************************************!*\\\n  !*** ./lib/transports/websocket.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar _require2 = __webpack_require__(/*! ./websocket-constructor */ \\\"./lib/transports/websocket-constructor.browser.js\\\"),\\n    WebSocket = _require2.WebSocket,\\n    usingBrowserWebSocket = _require2.usingBrowserWebSocket,\\n    defaultBinaryType = _require2.defaultBinaryType;\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:websocket\\\"); // detect ReactNative environment\\n\\n\\nvar isReactNative = typeof navigator !== \\\"undefined\\\" && typeof navigator.product === \\\"string\\\" && navigator.product.toLowerCase() === \\\"reactnative\\\";\\n\\nvar WS =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(WS, _Transport);\\n\\n  /**\\n   * WebSocket transport constructor.\\n   *\\n   * @api {Object} connection options\\n   * @api public\\n   */\\n  function WS(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, WS);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(WS).call(this, opts));\\n    _this.supportsBinary = !opts.forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Transport name.\\n   *\\n   * @api public\\n   */\\n\\n\\n  _createClass(WS, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens socket.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      if (!this.check()) {\\n        // let probe timeout\\n        return;\\n      }\\n\\n      var uri = this.uri();\\n      var protocols = this.opts.protocols; // React Native only supports the 'headers' option, and will print a warning if anything else is passed\\n\\n      var opts = isReactNative ? {} : pick(this.opts, \\\"agent\\\", \\\"perMessageDeflate\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\", \\\"localAddress\\\");\\n\\n      if (this.opts.extraHeaders) {\\n        opts.headers = this.opts.extraHeaders;\\n      }\\n\\n      try {\\n        this.ws = usingBrowserWebSocket && !isReactNative ? protocols ? new WebSocket(uri, protocols) : new WebSocket(uri) : new WebSocket(uri, protocols, opts);\\n      } catch (err) {\\n        return this.emit(\\\"error\\\", err);\\n      }\\n\\n      this.ws.binaryType = this.socket.binaryType || defaultBinaryType;\\n      this.addEventListeners();\\n    }\\n    /**\\n     * Adds event listeners to the socket\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"addEventListeners\\\",\\n    value: function addEventListeners() {\\n      var self = this;\\n\\n      this.ws.onopen = function () {\\n        self.onOpen();\\n      };\\n\\n      this.ws.onclose = function () {\\n        self.onClose();\\n      };\\n\\n      this.ws.onmessage = function (ev) {\\n        self.onData(ev.data);\\n      };\\n\\n      this.ws.onerror = function (e) {\\n        self.onError(\\\"websocket error\\\", e);\\n      };\\n    }\\n    /**\\n     * Writes data to socket.\\n     *\\n     * @param {Array} array of packets.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var self = this;\\n      this.writable = false; // encodePacket efficient as it uses WS framing\\n      // no need for encodePayload\\n\\n      var total = packets.length;\\n      var i = 0;\\n      var l = total;\\n\\n      for (; i < l; i++) {\\n        (function (packet) {\\n          parser.encodePacket(packet, self.supportsBinary, function (data) {\\n            // always create a new object (GH-437)\\n            var opts = {};\\n\\n            if (!usingBrowserWebSocket) {\\n              if (packet.options) {\\n                opts.compress = packet.options.compress;\\n              }\\n\\n              if (self.opts.perMessageDeflate) {\\n                var len = \\\"string\\\" === typeof data ? Buffer.byteLength(data) : data.length;\\n\\n                if (len < self.opts.perMessageDeflate.threshold) {\\n                  opts.compress = false;\\n                }\\n              }\\n            } // Sometimes the websocket has already been closed but the browser didn't\\n            // have a chance of informing us about it yet, in that case send will\\n            // throw an error\\n\\n\\n            try {\\n              if (usingBrowserWebSocket) {\\n                // TypeError is thrown when passing the second argument on Safari\\n                self.ws.send(data);\\n              } else {\\n                self.ws.send(data, opts);\\n              }\\n            } catch (e) {\\n              debug(\\\"websocket closed before onclose event\\\");\\n            }\\n\\n            --total || done();\\n          });\\n        })(packets[i]);\\n      }\\n\\n      function done() {\\n        self.emit(\\\"flush\\\"); // fake drain\\n        // defer to next tick to allow Socket to clear writeBuffer\\n\\n        setTimeout(function () {\\n          self.writable = true;\\n          self.emit(\\\"drain\\\");\\n        }, 0);\\n      }\\n    }\\n    /**\\n     * Called upon close\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      Transport.prototype.onClose.call(this);\\n    }\\n    /**\\n     * Closes socket.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      if (typeof this.ws !== \\\"undefined\\\") {\\n        this.ws.close();\\n      }\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"wss\\\" : \\\"ws\\\";\\n      var port = \\\"\\\"; // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"wss\\\" === schema && Number(this.opts.port) !== 443 || \\\"ws\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // append timestamp to URI\\n\\n\\n      if (this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      } // communicate binary support capabilities\\n\\n\\n      if (!this.supportsBinary) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // prepend ? to query\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n    /**\\n     * Feature detection for WebSocket.\\n     *\\n     * @return {Boolean} whether this transport is available.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"check\\\",\\n    value: function check() {\\n      return !!WebSocket && !(\\\"__initialize\\\" in WebSocket && this.name === WS.prototype.name);\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n    get: function get() {\\n      return \\\"websocket\\\";\\n    }\\n  }]);\\n\\n  return WS;\\n}(Transport);\\n\\nmodule.exports = WS;\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/util.js\":\n/*!*********************!*\\\n  !*** ./lib/util.js ***!\n  \\*********************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports.pick = function (obj) {\\n  for (var _len = arguments.length, attr = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\\n    attr[_key - 1] = arguments[_key];\\n  }\\n\\n  return attr.reduce(function (acc, k) {\\n    acc[k] = obj[k];\\n    return acc;\\n  }, {});\\n};\\n\\n//# sourceURL=webpack://eio/./lib/util.js?\");\n\n/***/ }),\n\n/***/ \"./lib/xmlhttprequest.js\":\n/*!*******************************!*\\\n  !*** ./lib/xmlhttprequest.js ***!\n  \\*******************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"// browser shim for xmlhttprequest module\\nvar hasCORS = __webpack_require__(/*! has-cors */ \\\"./node_modules/has-cors/index.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ./globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = function (opts) {\\n  var xdomain = opts.xdomain; // scheme must be same when usign XDomainRequest\\n  // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx\\n\\n  var xscheme = opts.xscheme; // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.\\n  // https://github.com/Automattic/engine.io-client/pull/217\\n\\n  var enablesXDR = opts.enablesXDR; // XMLHttpRequest can be disabled on IE\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {\\n      return new XMLHttpRequest();\\n    }\\n  } catch (e) {} // Use XDomainRequest for IE8 if enablesXDR is true\\n  // because loading bar keeps flashing when using jsonp-polling\\n  // https://github.com/yujiosaka/socke.io-ie8-loading-example\\n\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XDomainRequest && !xscheme && enablesXDR) {\\n      return new XDomainRequest();\\n    }\\n  } catch (e) {}\\n\\n  if (!xdomain) {\\n    try {\\n      return new globalThis[[\\\"Active\\\"].concat(\\\"Object\\\").join(\\\"X\\\")](\\\"Microsoft.XMLHTTP\\\");\\n    } catch (e) {}\\n  }\\n};\\n\\n//# sourceURL=webpack://eio/./lib/xmlhttprequest.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/*\\n * base64-arraybuffer\\n * https://github.com/niklasvh/base64-arraybuffer\\n *\\n * Copyright (c) 2012 Niklas von Hertzen\\n * Licensed under the MIT license.\\n */\\n(function (chars) {\\n  \\\"use strict\\\";\\n\\n  exports.encode = function (arraybuffer) {\\n    var bytes = new Uint8Array(arraybuffer),\\n        i,\\n        len = bytes.length,\\n        base64 = \\\"\\\";\\n\\n    for (i = 0; i < len; i += 3) {\\n      base64 += chars[bytes[i] >> 2];\\n      base64 += chars[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];\\n      base64 += chars[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];\\n      base64 += chars[bytes[i + 2] & 63];\\n    }\\n\\n    if (len % 3 === 2) {\\n      base64 = base64.substring(0, base64.length - 1) + \\\"=\\\";\\n    } else if (len % 3 === 1) {\\n      base64 = base64.substring(0, base64.length - 2) + \\\"==\\\";\\n    }\\n\\n    return base64;\\n  };\\n\\n  exports.decode = function (base64) {\\n    var bufferLength = base64.length * 0.75,\\n        len = base64.length,\\n        i,\\n        p = 0,\\n        encoded1,\\n        encoded2,\\n        encoded3,\\n        encoded4;\\n\\n    if (base64[base64.length - 1] === \\\"=\\\") {\\n      bufferLength--;\\n\\n      if (base64[base64.length - 2] === \\\"=\\\") {\\n        bufferLength--;\\n      }\\n    }\\n\\n    var arraybuffer = new ArrayBuffer(bufferLength),\\n        bytes = new Uint8Array(arraybuffer);\\n\\n    for (i = 0; i < len; i += 4) {\\n      encoded1 = chars.indexOf(base64[i]);\\n      encoded2 = chars.indexOf(base64[i + 1]);\\n      encoded3 = chars.indexOf(base64[i + 2]);\\n      encoded4 = chars.indexOf(base64[i + 3]);\\n      bytes[p++] = encoded1 << 2 | encoded2 >> 4;\\n      bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;\\n      bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;\\n    }\\n\\n    return arraybuffer;\\n  };\\n})(\\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\");\\n\\n//# sourceURL=webpack://eio/./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/component-emitter/index.js\":\n/*!*************************************************!*\\\n  !*** ./node_modules/component-emitter/index.js ***!\n  \\*************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/**\\r\\n * Expose `Emitter`.\\r\\n */\\nif (true) {\\n  module.exports = Emitter;\\n}\\n/**\\r\\n * Initialize a new `Emitter`.\\r\\n *\\r\\n * @api public\\r\\n */\\n\\n\\nfunction Emitter(obj) {\\n  if (obj) return mixin(obj);\\n}\\n\\n;\\n/**\\r\\n * Mixin the emitter properties.\\r\\n *\\r\\n * @param {Object} obj\\r\\n * @return {Object}\\r\\n * @api private\\r\\n */\\n\\nfunction mixin(obj) {\\n  for (var key in Emitter.prototype) {\\n    obj[key] = Emitter.prototype[key];\\n  }\\n\\n  return obj;\\n}\\n/**\\r\\n * Listen on the given `event` with `fn`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {};\\n  (this._callbacks['$' + event] = this._callbacks['$' + event] || []).push(fn);\\n  return this;\\n};\\n/**\\r\\n * Adds an `event` listener that will be invoked a single\\r\\n * time then automatically removed.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.once = function (event, fn) {\\n  function on() {\\n    this.off(event, on);\\n    fn.apply(this, arguments);\\n  }\\n\\n  on.fn = fn;\\n  this.on(event, on);\\n  return this;\\n};\\n/**\\r\\n * Remove the given callback for `event` or all\\r\\n * registered callbacks.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {}; // all\\n\\n  if (0 == arguments.length) {\\n    this._callbacks = {};\\n    return this;\\n  } // specific event\\n\\n\\n  var callbacks = this._callbacks['$' + event];\\n  if (!callbacks) return this; // remove all handlers\\n\\n  if (1 == arguments.length) {\\n    delete this._callbacks['$' + event];\\n    return this;\\n  } // remove specific handler\\n\\n\\n  var cb;\\n\\n  for (var i = 0; i < callbacks.length; i++) {\\n    cb = callbacks[i];\\n\\n    if (cb === fn || cb.fn === fn) {\\n      callbacks.splice(i, 1);\\n      break;\\n    }\\n  } // Remove event specific arrays for event types that no\\n  // one is subscribed for to avoid memory leak.\\n\\n\\n  if (callbacks.length === 0) {\\n    delete this._callbacks['$' + event];\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Emit `event` with the given args.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Mixed} ...\\r\\n * @return {Emitter}\\r\\n */\\n\\n\\nEmitter.prototype.emit = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  var args = new Array(arguments.length - 1),\\n      callbacks = this._callbacks['$' + event];\\n\\n  for (var i = 1; i < arguments.length; i++) {\\n    args[i - 1] = arguments[i];\\n  }\\n\\n  if (callbacks) {\\n    callbacks = callbacks.slice(0);\\n\\n    for (var i = 0, len = callbacks.length; i < len; ++i) {\\n      callbacks[i].apply(this, args);\\n    }\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Return array of callbacks for `event`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Array}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.listeners = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  return this._callbacks['$' + event] || [];\\n};\\n/**\\r\\n * Check if this emitter has `event` handlers.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Boolean}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.hasListeners = function (event) {\\n  return !!this.listeners(event).length;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/component-emitter/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/browser.js\":\n/*!*******************************************!*\\\n  !*** ./node_modules/debug/src/browser.js ***!\n  \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/* WEBPACK VAR INJECTION */(function(process) {function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/* eslint-env browser */\\n\\n/**\\n * This is the web browser implementation of `debug()`.\\n */\\nexports.log = log;\\nexports.formatArgs = formatArgs;\\nexports.save = save;\\nexports.load = load;\\nexports.useColors = useColors;\\nexports.storage = localstorage();\\n/**\\n * Colors.\\n */\\n\\nexports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];\\n/**\\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\\n * and the Firebug extension (any Firefox version) are known\\n * to support \\\"%c\\\" CSS customizations.\\n *\\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\\n */\\n// eslint-disable-next-line complexity\\n\\nfunction useColors() {\\n  // NB: In an Electron preload script, document will be defined but not fully\\n  // initialized. Since we know we're in Chrome, we'll just detect this case\\n  // explicitly\\n  if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {\\n    return true;\\n  } // Internet Explorer and Edge do not support colors.\\n\\n\\n  if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\\\\/(\\\\d+)/)) {\\n    return false;\\n  } // Is webkit? http://stackoverflow.com/a/16459606/376773\\n  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\\n\\n\\n  return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773\\n  typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?\\n  // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\\\\/(\\\\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\\\/(\\\\d+)/);\\n}\\n/**\\n * Colorize log arguments if enabled.\\n *\\n * @api public\\n */\\n\\n\\nfunction formatArgs(args) {\\n  args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);\\n\\n  if (!this.useColors) {\\n    return;\\n  }\\n\\n  var c = 'color: ' + this.color;\\n  args.splice(1, 0, c, 'color: inherit'); // The final \\\"%c\\\" is somewhat tricky, because there could be other\\n  // arguments passed either before or after the %c, so we need to\\n  // figure out the correct index to insert the CSS into\\n\\n  var index = 0;\\n  var lastC = 0;\\n  args[0].replace(/%[a-zA-Z%]/g, function (match) {\\n    if (match === '%%') {\\n      return;\\n    }\\n\\n    index++;\\n\\n    if (match === '%c') {\\n      // We only are interested in the *last* %c\\n      // (the user may have provided their own)\\n      lastC = index;\\n    }\\n  });\\n  args.splice(lastC, 0, c);\\n}\\n/**\\n * Invokes `console.log()` when available.\\n * No-op when `console.log` is not a \\\"function\\\".\\n *\\n * @api public\\n */\\n\\n\\nfunction log() {\\n  var _console;\\n\\n  // This hackery is required for IE8/9, where\\n  // the `console.log` function doesn't have 'apply'\\n  return (typeof console === \\\"undefined\\\" ? \\\"undefined\\\" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments);\\n}\\n/**\\n * Save `namespaces`.\\n *\\n * @param {String} namespaces\\n * @api private\\n */\\n\\n\\nfunction save(namespaces) {\\n  try {\\n    if (namespaces) {\\n      exports.storage.setItem('debug', namespaces);\\n    } else {\\n      exports.storage.removeItem('debug');\\n    }\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n/**\\n * Load `namespaces`.\\n *\\n * @return {String} returns the previously persisted debug modes\\n * @api private\\n */\\n\\n\\nfunction load() {\\n  var r;\\n\\n  try {\\n    r = exports.storage.getItem('debug');\\n  } catch (error) {} // Swallow\\n  // XXX (@Qix-) should we be logging these?\\n  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\\n\\n\\n  if (!r && typeof process !== 'undefined' && 'env' in process) {\\n    r = process.env.DEBUG;\\n  }\\n\\n  return r;\\n}\\n/**\\n * Localstorage attempts to return the localstorage.\\n *\\n * This is necessary because safari throws\\n * when a user disables cookies/localstorage\\n * and you attempt to access it.\\n *\\n * @return {LocalStorage}\\n * @api private\\n */\\n\\n\\nfunction localstorage() {\\n  try {\\n    // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\\n    // The Browser also has localStorage in the global context.\\n    return localStorage;\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n\\nmodule.exports = __webpack_require__(/*! ./common */ \\\"./node_modules/debug/src/common.js\\\")(exports);\\nvar formatters = module.exports.formatters;\\n/**\\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\\n */\\n\\nformatters.j = function (v) {\\n  try {\\n    return JSON.stringify(v);\\n  } catch (error) {\\n    return '[UnexpectedJSONParseError]: ' + error.message;\\n  }\\n};\\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../process/browser.js */ \\\"./node_modules/process/browser.js\\\")))\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/common.js\":\n/*!******************************************!*\\\n  !*** ./node_modules/debug/src/common.js ***!\n  \\******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\\n\\nfunction _nonIterableSpread() { throw new TypeError(\\\"Invalid attempt to spread non-iterable instance\\\"); }\\n\\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \\\"[object Arguments]\\\") return Array.from(iter); }\\n\\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\\n\\n/**\\n * This is the common logic for both the Node.js and web browser\\n * implementations of `debug()`.\\n */\\nfunction setup(env) {\\n  createDebug.debug = createDebug;\\n  createDebug[\\\"default\\\"] = createDebug;\\n  createDebug.coerce = coerce;\\n  createDebug.disable = disable;\\n  createDebug.enable = enable;\\n  createDebug.enabled = enabled;\\n  createDebug.humanize = __webpack_require__(/*! ms */ \\\"./node_modules/ms/index.js\\\");\\n  Object.keys(env).forEach(function (key) {\\n    createDebug[key] = env[key];\\n  });\\n  /**\\n  * Active `debug` instances.\\n  */\\n\\n  createDebug.instances = [];\\n  /**\\n  * The currently active debug mode names, and names to skip.\\n  */\\n\\n  createDebug.names = [];\\n  createDebug.skips = [];\\n  /**\\n  * Map of special \\\"%n\\\" handling functions, for the debug \\\"format\\\" argument.\\n  *\\n  * Valid key names are a single, lower or upper-case letter, i.e. \\\"n\\\" and \\\"N\\\".\\n  */\\n\\n  createDebug.formatters = {};\\n  /**\\n  * Selects a color for a debug namespace\\n  * @param {String} namespace The namespace string for the for the debug instance to be colored\\n  * @return {Number|String} An ANSI color code for the given namespace\\n  * @api private\\n  */\\n\\n  function selectColor(namespace) {\\n    var hash = 0;\\n\\n    for (var i = 0; i < namespace.length; i++) {\\n      hash = (hash << 5) - hash + namespace.charCodeAt(i);\\n      hash |= 0; // Convert to 32bit integer\\n    }\\n\\n    return createDebug.colors[Math.abs(hash) % createDebug.colors.length];\\n  }\\n\\n  createDebug.selectColor = selectColor;\\n  /**\\n  * Create a debugger with the given `namespace`.\\n  *\\n  * @param {String} namespace\\n  * @return {Function}\\n  * @api public\\n  */\\n\\n  function createDebug(namespace) {\\n    var prevTime;\\n\\n    function debug() {\\n      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\\n        args[_key] = arguments[_key];\\n      }\\n\\n      // Disabled?\\n      if (!debug.enabled) {\\n        return;\\n      }\\n\\n      var self = debug; // Set `diff` timestamp\\n\\n      var curr = Number(new Date());\\n      var ms = curr - (prevTime || curr);\\n      self.diff = ms;\\n      self.prev = prevTime;\\n      self.curr = curr;\\n      prevTime = curr;\\n      args[0] = createDebug.coerce(args[0]);\\n\\n      if (typeof args[0] !== 'string') {\\n        // Anything else let's inspect with %O\\n        args.unshift('%O');\\n      } // Apply any `formatters` transformations\\n\\n\\n      var index = 0;\\n      args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {\\n        // If we encounter an escaped % then don't increase the array index\\n        if (match === '%%') {\\n          return match;\\n        }\\n\\n        index++;\\n        var formatter = createDebug.formatters[format];\\n\\n        if (typeof formatter === 'function') {\\n          var val = args[index];\\n          match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`\\n\\n          args.splice(index, 1);\\n          index--;\\n        }\\n\\n        return match;\\n      }); // Apply env-specific formatting (colors, etc.)\\n\\n      createDebug.formatArgs.call(self, args);\\n      var logFn = self.log || createDebug.log;\\n      logFn.apply(self, args);\\n    }\\n\\n    debug.namespace = namespace;\\n    debug.enabled = createDebug.enabled(namespace);\\n    debug.useColors = createDebug.useColors();\\n    debug.color = selectColor(namespace);\\n    debug.destroy = destroy;\\n    debug.extend = extend; // Debug.formatArgs = formatArgs;\\n    // debug.rawLog = rawLog;\\n    // env-specific initialization logic for debug instances\\n\\n    if (typeof createDebug.init === 'function') {\\n      createDebug.init(debug);\\n    }\\n\\n    createDebug.instances.push(debug);\\n    return debug;\\n  }\\n\\n  function destroy() {\\n    var index = createDebug.instances.indexOf(this);\\n\\n    if (index !== -1) {\\n      createDebug.instances.splice(index, 1);\\n      return true;\\n    }\\n\\n    return false;\\n  }\\n\\n  function extend(namespace, delimiter) {\\n    var newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);\\n    newDebug.log = this.log;\\n    return newDebug;\\n  }\\n  /**\\n  * Enables a debug mode by namespaces. This can include modes\\n  * separated by a colon and wildcards.\\n  *\\n  * @param {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function enable(namespaces) {\\n    createDebug.save(namespaces);\\n    createDebug.names = [];\\n    createDebug.skips = [];\\n    var i;\\n    var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\\\\s,]+/);\\n    var len = split.length;\\n\\n    for (i = 0; i < len; i++) {\\n      if (!split[i]) {\\n        // ignore empty strings\\n        continue;\\n      }\\n\\n      namespaces = split[i].replace(/\\\\*/g, '.*?');\\n\\n      if (namespaces[0] === '-') {\\n        createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));\\n      } else {\\n        createDebug.names.push(new RegExp('^' + namespaces + '$'));\\n      }\\n    }\\n\\n    for (i = 0; i < createDebug.instances.length; i++) {\\n      var instance = createDebug.instances[i];\\n      instance.enabled = createDebug.enabled(instance.namespace);\\n    }\\n  }\\n  /**\\n  * Disable debug output.\\n  *\\n  * @return {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function disable() {\\n    var namespaces = [].concat(_toConsumableArray(createDebug.names.map(toNamespace)), _toConsumableArray(createDebug.skips.map(toNamespace).map(function (namespace) {\\n      return '-' + namespace;\\n    }))).join(',');\\n    createDebug.enable('');\\n    return namespaces;\\n  }\\n  /**\\n  * Returns true if the given mode name is enabled, false otherwise.\\n  *\\n  * @param {String} name\\n  * @return {Boolean}\\n  * @api public\\n  */\\n\\n\\n  function enabled(name) {\\n    if (name[name.length - 1] === '*') {\\n      return true;\\n    }\\n\\n    var i;\\n    var len;\\n\\n    for (i = 0, len = createDebug.skips.length; i < len; i++) {\\n      if (createDebug.skips[i].test(name)) {\\n        return false;\\n      }\\n    }\\n\\n    for (i = 0, len = createDebug.names.length; i < len; i++) {\\n      if (createDebug.names[i].test(name)) {\\n        return true;\\n      }\\n    }\\n\\n    return false;\\n  }\\n  /**\\n  * Convert regexp to namespace\\n  *\\n  * @param {RegExp} regxep\\n  * @return {String} namespace\\n  * @api private\\n  */\\n\\n\\n  function toNamespace(regexp) {\\n    return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\\\\.\\\\*\\\\?$/, '*');\\n  }\\n  /**\\n  * Coerce `val`.\\n  *\\n  * @param {Mixed} val\\n  * @return {Mixed}\\n  * @api private\\n  */\\n\\n\\n  function coerce(val) {\\n    if (val instanceof Error) {\\n      return val.stack || val.message;\\n    }\\n\\n    return val;\\n  }\\n\\n  createDebug.enable(createDebug.load());\\n  return createDebug;\\n}\\n\\nmodule.exports = setup;\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/common.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/commons.js\":\n/*!******************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/commons.js ***!\n  \\******************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"var PACKET_TYPES = Object.create(null); // no Map = no polyfill\\n\\nPACKET_TYPES[\\\"open\\\"] = \\\"0\\\";\\nPACKET_TYPES[\\\"close\\\"] = \\\"1\\\";\\nPACKET_TYPES[\\\"ping\\\"] = \\\"2\\\";\\nPACKET_TYPES[\\\"pong\\\"] = \\\"3\\\";\\nPACKET_TYPES[\\\"message\\\"] = \\\"4\\\";\\nPACKET_TYPES[\\\"upgrade\\\"] = \\\"5\\\";\\nPACKET_TYPES[\\\"noop\\\"] = \\\"6\\\";\\nvar PACKET_TYPES_REVERSE = Object.create(null);\\nObject.keys(PACKET_TYPES).forEach(function (key) {\\n  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;\\n});\\nvar ERROR_PACKET = {\\n  type: \\\"error\\\",\\n  data: \\\"parser error\\\"\\n};\\nmodule.exports = {\\n  PACKET_TYPES: PACKET_TYPES,\\n  PACKET_TYPES_REVERSE: PACKET_TYPES_REVERSE,\\n  ERROR_PACKET: ERROR_PACKET\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/commons.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/decodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/decodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES_REVERSE = _require.PACKET_TYPES_REVERSE,\\n    ERROR_PACKET = _require.ERROR_PACKET;\\n\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\";\\nvar base64decoder;\\n\\nif (withNativeArrayBuffer) {\\n  base64decoder = __webpack_require__(/*! base64-arraybuffer */ \\\"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\\\");\\n}\\n\\nvar decodePacket = function decodePacket(encodedPacket, binaryType) {\\n  if (typeof encodedPacket !== \\\"string\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: mapBinary(encodedPacket, binaryType)\\n    };\\n  }\\n\\n  var type = encodedPacket.charAt(0);\\n\\n  if (type === \\\"b\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: decodeBase64Packet(encodedPacket.substring(1), binaryType)\\n    };\\n  }\\n\\n  var packetType = PACKET_TYPES_REVERSE[type];\\n\\n  if (!packetType) {\\n    return ERROR_PACKET;\\n  }\\n\\n  return encodedPacket.length > 1 ? {\\n    type: PACKET_TYPES_REVERSE[type],\\n    data: encodedPacket.substring(1)\\n  } : {\\n    type: PACKET_TYPES_REVERSE[type]\\n  };\\n};\\n\\nvar decodeBase64Packet = function decodeBase64Packet(data, binaryType) {\\n  if (base64decoder) {\\n    var decoded = base64decoder.decode(data);\\n    return mapBinary(decoded, binaryType);\\n  } else {\\n    return {\\n      base64: true,\\n      data: data\\n    }; // fallback for old browsers\\n  }\\n};\\n\\nvar mapBinary = function mapBinary(data, binaryType) {\\n  switch (binaryType) {\\n    case \\\"blob\\\":\\n      return data instanceof ArrayBuffer ? new Blob([data]) : data;\\n\\n    case \\\"arraybuffer\\\":\\n    default:\\n      return data;\\n    // assuming the data is already an ArrayBuffer\\n  }\\n};\\n\\nmodule.exports = decodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/decodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/encodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/encodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES = _require.PACKET_TYPES;\\n\\nvar withNativeBlob = typeof Blob === \\\"function\\\" || typeof Blob !== \\\"undefined\\\" && Object.prototype.toString.call(Blob) === \\\"[object BlobConstructor]\\\";\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\"; // ArrayBuffer.isView method is not defined in IE10\\n\\nvar isView = function isView(obj) {\\n  return typeof ArrayBuffer.isView === \\\"function\\\" ? ArrayBuffer.isView(obj) : obj && obj.buffer instanceof ArrayBuffer;\\n};\\n\\nvar encodePacket = function encodePacket(_ref, supportsBinary, callback) {\\n  var type = _ref.type,\\n      data = _ref.data;\\n\\n  if (withNativeBlob && data instanceof Blob) {\\n    if (supportsBinary) {\\n      return callback(data);\\n    } else {\\n      return encodeBlobAsBase64(data, callback);\\n    }\\n  } else if (withNativeArrayBuffer && (data instanceof ArrayBuffer || isView(data))) {\\n    if (supportsBinary) {\\n      return callback(data instanceof ArrayBuffer ? data : data.buffer);\\n    } else {\\n      return encodeBlobAsBase64(new Blob([data]), callback);\\n    }\\n  } // plain string\\n\\n\\n  return callback(PACKET_TYPES[type] + (data || \\\"\\\"));\\n};\\n\\nvar encodeBlobAsBase64 = function encodeBlobAsBase64(data, callback) {\\n  var fileReader = new FileReader();\\n\\n  fileReader.onload = function () {\\n    var content = fileReader.result.split(\\\",\\\")[1];\\n    callback(\\\"b\\\" + content);\\n  };\\n\\n  return fileReader.readAsDataURL(data);\\n};\\n\\nmodule.exports = encodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/encodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/index.js\":\n/*!****************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/index.js ***!\n  \\****************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var encodePacket = __webpack_require__(/*! ./encodePacket */ \\\"./node_modules/engine.io-parser/lib/encodePacket.browser.js\\\");\\n\\nvar decodePacket = __webpack_require__(/*! ./decodePacket */ \\\"./node_modules/engine.io-parser/lib/decodePacket.browser.js\\\");\\n\\nvar SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text\\n\\nvar encodePayload = function encodePayload(packets, callback) {\\n  // some packets may be added to the array while encoding, so the initial length must be saved\\n  var length = packets.length;\\n  var encodedPackets = new Array(length);\\n  var count = 0;\\n  packets.forEach(function (packet, i) {\\n    // force base64 encoding for binary packets\\n    encodePacket(packet, false, function (encodedPacket) {\\n      encodedPackets[i] = encodedPacket;\\n\\n      if (++count === length) {\\n        callback(encodedPackets.join(SEPARATOR));\\n      }\\n    });\\n  });\\n};\\n\\nvar decodePayload = function decodePayload(encodedPayload, binaryType) {\\n  var encodedPackets = encodedPayload.split(SEPARATOR);\\n  var packets = [];\\n\\n  for (var i = 0; i < encodedPackets.length; i++) {\\n    var decodedPacket = decodePacket(encodedPackets[i], binaryType);\\n    packets.push(decodedPacket);\\n\\n    if (decodedPacket.type === \\\"error\\\") {\\n      break;\\n    }\\n  }\\n\\n  return packets;\\n};\\n\\nmodule.exports = {\\n  protocol: 4,\\n  encodePacket: encodePacket,\\n  encodePayload: encodePayload,\\n  decodePacket: decodePacket,\\n  decodePayload: decodePayload\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/has-cors/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/has-cors/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Module exports.\\n *\\n * Logic borrowed from Modernizr:\\n *\\n *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js\\n */\\ntry {\\n  module.exports = typeof XMLHttpRequest !== 'undefined' && 'withCredentials' in new XMLHttpRequest();\\n} catch (err) {\\n  // if XMLHttp support is disabled in IE then it will throw\\n  // when trying to create\\n  module.exports = false;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/has-cors/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/ms/index.js\":\n/*!**********************************!*\\\n  !*** ./node_modules/ms/index.js ***!\n  \\**********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/**\\n * Helpers.\\n */\\nvar s = 1000;\\nvar m = s * 60;\\nvar h = m * 60;\\nvar d = h * 24;\\nvar w = d * 7;\\nvar y = d * 365.25;\\n/**\\n * Parse or format the given `val`.\\n *\\n * Options:\\n *\\n *  - `long` verbose formatting [false]\\n *\\n * @param {String|Number} val\\n * @param {Object} [options]\\n * @throws {Error} throw an error if val is not a non-empty string or a number\\n * @return {String|Number}\\n * @api public\\n */\\n\\nmodule.exports = function (val, options) {\\n  options = options || {};\\n\\n  var type = _typeof(val);\\n\\n  if (type === 'string' && val.length > 0) {\\n    return parse(val);\\n  } else if (type === 'number' && isFinite(val)) {\\n    return options[\\\"long\\\"] ? fmtLong(val) : fmtShort(val);\\n  }\\n\\n  throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val));\\n};\\n/**\\n * Parse the given `str` and return milliseconds.\\n *\\n * @param {String} str\\n * @return {Number}\\n * @api private\\n */\\n\\n\\nfunction parse(str) {\\n  str = String(str);\\n\\n  if (str.length > 100) {\\n    return;\\n  }\\n\\n  var match = /^(-?(?:\\\\d+)?\\\\.?\\\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);\\n\\n  if (!match) {\\n    return;\\n  }\\n\\n  var n = parseFloat(match[1]);\\n  var type = (match[2] || 'ms').toLowerCase();\\n\\n  switch (type) {\\n    case 'years':\\n    case 'year':\\n    case 'yrs':\\n    case 'yr':\\n    case 'y':\\n      return n * y;\\n\\n    case 'weeks':\\n    case 'week':\\n    case 'w':\\n      return n * w;\\n\\n    case 'days':\\n    case 'day':\\n    case 'd':\\n      return n * d;\\n\\n    case 'hours':\\n    case 'hour':\\n    case 'hrs':\\n    case 'hr':\\n    case 'h':\\n      return n * h;\\n\\n    case 'minutes':\\n    case 'minute':\\n    case 'mins':\\n    case 'min':\\n    case 'm':\\n      return n * m;\\n\\n    case 'seconds':\\n    case 'second':\\n    case 'secs':\\n    case 'sec':\\n    case 's':\\n      return n * s;\\n\\n    case 'milliseconds':\\n    case 'millisecond':\\n    case 'msecs':\\n    case 'msec':\\n    case 'ms':\\n      return n;\\n\\n    default:\\n      return undefined;\\n  }\\n}\\n/**\\n * Short format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtShort(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return Math.round(ms / d) + 'd';\\n  }\\n\\n  if (msAbs >= h) {\\n    return Math.round(ms / h) + 'h';\\n  }\\n\\n  if (msAbs >= m) {\\n    return Math.round(ms / m) + 'm';\\n  }\\n\\n  if (msAbs >= s) {\\n    return Math.round(ms / s) + 's';\\n  }\\n\\n  return ms + 'ms';\\n}\\n/**\\n * Long format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtLong(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return plural(ms, msAbs, d, 'day');\\n  }\\n\\n  if (msAbs >= h) {\\n    return plural(ms, msAbs, h, 'hour');\\n  }\\n\\n  if (msAbs >= m) {\\n    return plural(ms, msAbs, m, 'minute');\\n  }\\n\\n  if (msAbs >= s) {\\n    return plural(ms, msAbs, s, 'second');\\n  }\\n\\n  return ms + ' ms';\\n}\\n/**\\n * Pluralization helper.\\n */\\n\\n\\nfunction plural(ms, msAbs, n, name) {\\n  var isPlural = msAbs >= n * 1.5;\\n  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/ms/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseqs/index.js\":\n/*!***************************************!*\\\n  !*** ./node_modules/parseqs/index.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Compiles a querystring\\n * Returns string representation of the object\\n *\\n * @param {Object}\\n * @api private\\n */\\nexports.encode = function (obj) {\\n  var str = '';\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      if (str.length) str += '&';\\n      str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);\\n    }\\n  }\\n\\n  return str;\\n};\\n/**\\n * Parses a simple querystring into an object\\n *\\n * @param {String} qs\\n * @api private\\n */\\n\\n\\nexports.decode = function (qs) {\\n  var qry = {};\\n  var pairs = qs.split('&');\\n\\n  for (var i = 0, l = pairs.length; i < l; i++) {\\n    var pair = pairs[i].split('=');\\n    qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);\\n  }\\n\\n  return qry;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/parseqs/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseuri/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/parseuri/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Parses an URI\\n *\\n * @author Steven Levithan <stevenlevithan.com> (MIT license)\\n * @api private\\n */\\nvar re = /^(?:(?![^:@]+:[^:@\\\\/]*@)(http|https|ws|wss):\\\\/\\\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\\\/?#]*)(?::(\\\\d*))?)(((\\\\/(?:[^?#](?![^?#\\\\/]*\\\\.[^?#\\\\/.]+(?:[?#]|$)))*\\\\/?)?([^?#\\\\/]*))(?:\\\\?([^#]*))?(?:#(.*))?)/;\\nvar parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'];\\n\\nmodule.exports = function parseuri(str) {\\n  var src = str,\\n      b = str.indexOf('['),\\n      e = str.indexOf(']');\\n\\n  if (b != -1 && e != -1) {\\n    str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);\\n  }\\n\\n  var m = re.exec(str || ''),\\n      uri = {},\\n      i = 14;\\n\\n  while (i--) {\\n    uri[parts[i]] = m[i] || '';\\n  }\\n\\n  if (b != -1 && e != -1) {\\n    uri.source = src;\\n    uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');\\n    uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');\\n    uri.ipv6uri = true;\\n  }\\n\\n  uri.pathNames = pathNames(uri, uri['path']);\\n  uri.queryKey = queryKey(uri, uri['query']);\\n  return uri;\\n};\\n\\nfunction pathNames(obj, path) {\\n  var regx = /\\\\/{2,9}/g,\\n      names = path.replace(regx, \\\"/\\\").split(\\\"/\\\");\\n\\n  if (path.substr(0, 1) == '/' || path.length === 0) {\\n    names.splice(0, 1);\\n  }\\n\\n  if (path.substr(path.length - 1, 1) == '/') {\\n    names.splice(names.length - 1, 1);\\n  }\\n\\n  return names;\\n}\\n\\nfunction queryKey(uri, query) {\\n  var data = {};\\n  query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {\\n    if ($1) {\\n      data[$1] = $2;\\n    }\\n  });\\n  return data;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/parseuri/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/process/browser.js\":\n/*!*****************************************!*\\\n  !*** ./node_modules/process/browser.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"// shim for using process in browser\\nvar process = module.exports = {}; // cached from whatever global is present so that test runners that stub it\\n// don't break things.  But we need to wrap it in a try catch in case it is\\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\\n// function because try/catches deoptimize in certain engines.\\n\\nvar cachedSetTimeout;\\nvar cachedClearTimeout;\\n\\nfunction defaultSetTimout() {\\n  throw new Error('setTimeout has not been defined');\\n}\\n\\nfunction defaultClearTimeout() {\\n  throw new Error('clearTimeout has not been defined');\\n}\\n\\n(function () {\\n  try {\\n    if (typeof setTimeout === 'function') {\\n      cachedSetTimeout = setTimeout;\\n    } else {\\n      cachedSetTimeout = defaultSetTimout;\\n    }\\n  } catch (e) {\\n    cachedSetTimeout = defaultSetTimout;\\n  }\\n\\n  try {\\n    if (typeof clearTimeout === 'function') {\\n      cachedClearTimeout = clearTimeout;\\n    } else {\\n      cachedClearTimeout = defaultClearTimeout;\\n    }\\n  } catch (e) {\\n    cachedClearTimeout = defaultClearTimeout;\\n  }\\n})();\\n\\nfunction runTimeout(fun) {\\n  if (cachedSetTimeout === setTimeout) {\\n    //normal enviroments in sane situations\\n    return setTimeout(fun, 0);\\n  } // if setTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\\n    cachedSetTimeout = setTimeout;\\n    return setTimeout(fun, 0);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedSetTimeout(fun, 0);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\\n      return cachedSetTimeout.call(null, fun, 0);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\\n      return cachedSetTimeout.call(this, fun, 0);\\n    }\\n  }\\n}\\n\\nfunction runClearTimeout(marker) {\\n  if (cachedClearTimeout === clearTimeout) {\\n    //normal enviroments in sane situations\\n    return clearTimeout(marker);\\n  } // if clearTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\\n    cachedClearTimeout = clearTimeout;\\n    return clearTimeout(marker);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedClearTimeout(marker);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\\n      return cachedClearTimeout.call(null, marker);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\\n      // Some versions of I.E. have different rules for clearTimeout vs setTimeout\\n      return cachedClearTimeout.call(this, marker);\\n    }\\n  }\\n}\\n\\nvar queue = [];\\nvar draining = false;\\nvar currentQueue;\\nvar queueIndex = -1;\\n\\nfunction cleanUpNextTick() {\\n  if (!draining || !currentQueue) {\\n    return;\\n  }\\n\\n  draining = false;\\n\\n  if (currentQueue.length) {\\n    queue = currentQueue.concat(queue);\\n  } else {\\n    queueIndex = -1;\\n  }\\n\\n  if (queue.length) {\\n    drainQueue();\\n  }\\n}\\n\\nfunction drainQueue() {\\n  if (draining) {\\n    return;\\n  }\\n\\n  var timeout = runTimeout(cleanUpNextTick);\\n  draining = true;\\n  var len = queue.length;\\n\\n  while (len) {\\n    currentQueue = queue;\\n    queue = [];\\n\\n    while (++queueIndex < len) {\\n      if (currentQueue) {\\n        currentQueue[queueIndex].run();\\n      }\\n    }\\n\\n    queueIndex = -1;\\n    len = queue.length;\\n  }\\n\\n  currentQueue = null;\\n  draining = false;\\n  runClearTimeout(timeout);\\n}\\n\\nprocess.nextTick = function (fun) {\\n  var args = new Array(arguments.length - 1);\\n\\n  if (arguments.length > 1) {\\n    for (var i = 1; i < arguments.length; i++) {\\n      args[i - 1] = arguments[i];\\n    }\\n  }\\n\\n  queue.push(new Item(fun, args));\\n\\n  if (queue.length === 1 && !draining) {\\n    runTimeout(drainQueue);\\n  }\\n}; // v8 likes predictible objects\\n\\n\\nfunction Item(fun, array) {\\n  this.fun = fun;\\n  this.array = array;\\n}\\n\\nItem.prototype.run = function () {\\n  this.fun.apply(null, this.array);\\n};\\n\\nprocess.title = 'browser';\\nprocess.browser = true;\\nprocess.env = {};\\nprocess.argv = [];\\nprocess.version = ''; // empty string to avoid regexp issues\\n\\nprocess.versions = {};\\n\\nfunction noop() {}\\n\\nprocess.on = noop;\\nprocess.addListener = noop;\\nprocess.once = noop;\\nprocess.off = noop;\\nprocess.removeListener = noop;\\nprocess.removeAllListeners = noop;\\nprocess.emit = noop;\\nprocess.prependListener = noop;\\nprocess.prependOnceListener = noop;\\n\\nprocess.listeners = function (name) {\\n  return [];\\n};\\n\\nprocess.binding = function (name) {\\n  throw new Error('process.binding is not supported');\\n};\\n\\nprocess.cwd = function () {\\n  return '/';\\n};\\n\\nprocess.chdir = function (dir) {\\n  throw new Error('process.chdir is not supported');\\n};\\n\\nprocess.umask = function () {\\n  return 0;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/process/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/yeast/index.js\":\n/*!*************************************!*\\\n  !*** ./node_modules/yeast/index.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\neval(\"\\n\\nvar alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''),\\n    length = 64,\\n    map = {},\\n    seed = 0,\\n    i = 0,\\n    prev;\\n/**\\n * Return a string representing the specified number.\\n *\\n * @param {Number} num The number to convert.\\n * @returns {String} The string representation of the number.\\n * @api public\\n */\\n\\nfunction encode(num) {\\n  var encoded = '';\\n\\n  do {\\n    encoded = alphabet[num % length] + encoded;\\n    num = Math.floor(num / length);\\n  } while (num > 0);\\n\\n  return encoded;\\n}\\n/**\\n * Return the integer value specified by the given string.\\n *\\n * @param {String} str The string to convert.\\n * @returns {Number} The integer value represented by the string.\\n * @api public\\n */\\n\\n\\nfunction decode(str) {\\n  var decoded = 0;\\n\\n  for (i = 0; i < str.length; i++) {\\n    decoded = decoded * length + map[str.charAt(i)];\\n  }\\n\\n  return decoded;\\n}\\n/**\\n * Yeast: A tiny growing id generator.\\n *\\n * @returns {String} A unique id.\\n * @api public\\n */\\n\\n\\nfunction yeast() {\\n  var now = encode(+new Date());\\n  if (now !== prev) return seed = 0, prev = now;\\n  return now + '.' + encode(seed++);\\n} //\\n// Map each character to its index.\\n//\\n\\n\\nfor (; i < length; i++) {\\n  map[alphabet[i]] = i;\\n} //\\n// Expose the `yeast`, `encode` and `decode` functions.\\n//\\n\\n\\nyeast.encode = encode;\\nyeast.decode = decode;\\nmodule.exports = yeast;\\n\\n//# sourceURL=webpack://eio/./node_modules/yeast/index.js?\");\n\n/***/ })\n\n/******/ });\n});"
  },
  {
    "path": "examples/server/tornado/static/style.css",
    "content": "body { margin: 0; padding: 0; font-family: Helvetica Neue; }\nh1 { margin: 100px 100px 10px; }\nh2 { color: #999; margin: 0 100px 30px; font-weight: normal; }\n#latency { color: red; }\n"
  },
  {
    "path": "examples/server/tornado/templates/latency.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>EIO Latency</title>\n    <link rel=\"stylesheet\" href=\"/static/style.css\" />\n  </head>\n  <body>\n    <h1>EIO Latency <span id=\"latency\"></span></h1>\n    <h2 id=\"transport\">(connecting)</h2>\n    <canvas id=\"chart\" height=\"200\"></canvas>\n\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/smoothie/1.27.0/smoothie.js\"></script>\n    <script src=\"/static/engine.io.js\"></script>\n    <script>\n      // socket\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      var char = $('chart').get(0);\n      socket.on('open', function() {\n          if (chart.getContext) {\n              render();\n              window.onresize = render;\n          }\n          send();\n      });\n      socket.on('message', function(data) {\n          var latency = new Date - last;\n          $('#latency').text(latency + 'ms');\n          if (time)\n              time.append(+new Date, latency);\n          setTimeout(send, 100);\n      });\n      socket.on('close', function() {\n          if (smoothie)\n              smoothie.stop();\n          $('#transport').text('(disconnected)');\n      });\n\n      var last;\n      function send() {\n          last = new Date;\n          socket.send('ping');\n          $('#transport').text(socket.transport.name);\n      }\n\n      // chart\n      var smoothie;\n      var time;\n      function render() {\n          if (smoothie)\n              smoothie.stop();\n          chart.width = document.body.clientWidth;\n          smoothie = new SmoothieChart();\n          smoothie.streamTo(chart, 1000);\n          time = new TimeSeries();\n          smoothie.addTimeSeries(time, {\n              strokeStyle: 'rgb(255, 0, 0)',\n              fillStyle: 'rgba(255, 0, 0, 0.4)',\n              lineWidth: 2\n          });\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/server/tornado/templates/simple.html",
    "content": "<html>\n<head>\n<script src=\"/static/engine.io.js\"></script>\n<script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n<script>\n  $(document).ready(function() {\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      socket.on('open', function() {\n          $('#log').append(\"Connected to server.<br>\");\n      });\n      socket.on('message', function(data) {\n          $('#log').append(\"Server says: \" + data + \"<br>\");\n      });\n      socket.on('close', function() {\n          $('#log').append(\"Server closed the connection.<br>\");\n      });\n      window.setInterval(function() {\n          $('#log').append(\"Sending message to server...<br>\");\n          socket.send('hello from client side!');\n      }, 5000);\n  });\n</script>\n</head>\n<body>\n<h1>python-engineio example application</h1>\n<p id=\"log\"></p>\n</body>\n</html>\n"
  },
  {
    "path": "examples/server/wsgi/README.rst",
    "content": "Engine.IO WSGI Examples\n=======================\n\nThis directory contains example Engine.IO applications that work together with\nWSGI frameworks. These examples all use Flask to serve the client application\nto the web browser, but they should be easily adapted to use other WSGI\ncompliant frameworks.\n\nsimple.py\n---------\n\nA basic application in which the client sends messages to the server and the\nserver responds.\n\nlatency.py\n----------\n\nA port of the latency application included in the official Engine.IO\nJavascript server. In this application the client sends *ping* messages to\nthe server, which are responded by the server with a *pong*. The client\nmeasures the time it takes for each of these exchanges and plots these in real\ntime to the page.\n\nThis is an ideal application to measure the performance of the different\nasynchronous modes supported by the Engine.IO server.\n\nRunning the Examples\n--------------------\n\nTo run these examples, create a virtual environment, install the requirements\nand then run::\n\n    $ python simple.py\n\nor::\n\n    $ python latency.py\n\nYou can then access the application from your web browser at\n``http://localhost:5000``.\n\nNear the top of the ``simple.py`` and ``latency.py`` source files there is a\n``async_mode`` variable that can be edited to switch to the other asynchronous\nmodes that perform much better than the threading mode. Accepted values for\n``async_mode`` are ``'threading'``, ``'eventlet'`` and ``'gevent'``.\n\nNote 1: when using the ``'eventlet'`` mode, the eventlet package must be\ninstalled in the virtual environment::\n\n    $ pip install eventlet\n\nNote 2: when using the ``'gevent'`` mode, the gevent and gevent-websocket\npackages must be installed in the virtual environment::\n\n    $ pip install gevent gevent-websocket\n"
  },
  {
    "path": "examples/server/wsgi/latency.py",
    "content": "from flask import Flask, render_template\n\nimport engineio\n\n# set async_mode to 'threading', 'eventlet' or 'gevent' to force a mode\n# else, the best mode is selected automatically from what's installed\nasync_mode = None\n\neio = engineio.Server(async_mode=async_mode)\napp = Flask(__name__)\napp.wsgi_app = engineio.WSGIApp(eio, app.wsgi_app)\n\n\n@app.route('/')\ndef index():\n    return render_template('latency.html')\n\n\n@eio.on('message')\ndef message(sid, data):\n    eio.send(sid, 'pong')\n\n\nif __name__ == '__main__':\n    if eio.async_mode == 'threading':\n        # deploy with Werkzeug\n        app.run(threaded=True)\n    elif eio.async_mode == 'eventlet':\n        # deploy with eventlet\n        import eventlet\n        from eventlet import wsgi\n        wsgi.server(eventlet.listen(('', 5000)), app)\n    elif eio.async_mode == 'gevent':\n        # deploy with gevent\n        from gevent import pywsgi\n        try:\n            from geventwebsocket.handler import WebSocketHandler\n            websocket = True\n        except ImportError:\n            websocket = False\n        if websocket:\n            pywsgi.WSGIServer(('', 5000), app,\n                              handler_class=WebSocketHandler).serve_forever()\n        else:\n            pywsgi.WSGIServer(('', 5000), app).serve_forever()\n    else:\n        print('Unknown async_mode: ' + async_mode)\n"
  },
  {
    "path": "examples/server/wsgi/requirements.txt",
    "content": "appdirs==1.4.0\nclick==6.7\nenum-compat==0.0.2\nenum34==1.1.6\neventlet==0.40.3\nFlask==1.0.2\ngreenlet==0.4.12\nitsdangerous==0.24\nJinja2==3.1.6\nMarkupSafe==0.23\npackaging==16.8\npyparsing==2.1.10\npython-engineio\nsix==1.10.0\nWerkzeug==2.3.8\n"
  },
  {
    "path": "examples/server/wsgi/simple.py",
    "content": "from flask import Flask, render_template\n\nimport engineio\n\n# set async_mode to 'threading', 'eventlet' or 'gevent' to force a mode\n# else, the best mode is selected automatically from what's installed\nasync_mode = None\n\neio = engineio.Server(async_mode=async_mode)\napp = Flask(__name__)\napp.wsgi_app = engineio.WSGIApp(eio, app.wsgi_app)\n\n\n@app.route('/')\ndef index():\n    return render_template('simple.html')\n\n\n@eio.on('connect')\ndef connect(sid, environ):\n    print(\"connect \", sid)\n\n\n@eio.on('message')\ndef message(sid, data):\n    print('message from', sid, data)\n    eio.send(sid, 'Thank you for your message!')\n\n\n@eio.on('disconnect')\ndef disconnect(sid, reason):\n    print('disconnect ', sid, reason)\n\n\nif __name__ == '__main__':\n    if eio.async_mode == 'threading':\n        # deploy with Werkzeug\n        app.run(threaded=True)\n    elif eio.async_mode == 'eventlet':\n        # deploy with eventlet\n        import eventlet\n        from eventlet import wsgi\n        wsgi.server(eventlet.listen(('', 5000)), app)\n    elif eio.async_mode == 'gevent':\n        # deploy with gevent\n        from gevent import pywsgi\n        try:\n            from geventwebsocket.handler import WebSocketHandler\n            websocket = True\n        except ImportError:\n            websocket = False\n        if websocket:\n            pywsgi.WSGIServer(('', 5000), app,\n                              handler_class=WebSocketHandler).serve_forever()\n        else:\n            pywsgi.WSGIServer(('', 5000), app).serve_forever()\n    else:\n        print('Unknown async_mode: ' + eio.async_mode)\n"
  },
  {
    "path": "examples/server/wsgi/static/engine.io.js",
    "content": "/*!\n * Engine.IO v4.0.4\n * (c) 2014-2020 Guillermo Rauch\n * Released under the MIT License.\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"eio\"] = factory();\n\telse\n\t\troot[\"eio\"] = factory();\n})((() => {\n      if (typeof self !== 'undefined') {\n          return self;\n      } else if (typeof window !== 'undefined') {\n          return window;\n      } else if (typeof global !== 'undefined') {\n          return global;\n      } else {\n          return Function('return this')();\n      }\n    })(), function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./lib/index.js\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./lib/globalThis.browser.js\":\n/*!***********************************!*\\\n  !*** ./lib/globalThis.browser.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports = function () {\\n  if (typeof self !== \\\"undefined\\\") {\\n    return self;\\n  } else if (typeof window !== \\\"undefined\\\") {\\n    return window;\\n  } else {\\n    return Function(\\\"return this\\\")();\\n  }\\n}();\\n\\n//# sourceURL=webpack://eio/./lib/globalThis.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/index.js\":\n/*!**********************!*\\\n  !*** ./lib/index.js ***!\n  \\**********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var Socket = __webpack_require__(/*! ./socket */ \\\"./lib/socket.js\\\");\\n\\nmodule.exports = function (uri, opts) {\\n  return new Socket(uri, opts);\\n};\\n/**\\n * Expose deps for legacy compatibility\\n * and standalone browser access.\\n */\\n\\n\\nmodule.exports.Socket = Socket;\\nmodule.exports.protocol = Socket.protocol; // this is an int\\n\\nmodule.exports.Transport = __webpack_require__(/*! ./transport */ \\\"./lib/transport.js\\\");\\nmodule.exports.transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\nmodule.exports.parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\n//# sourceURL=webpack://eio/./lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/socket.js\":\n/*!***********************!*\\\n  !*** ./lib/socket.js ***!\n  \\***********************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar transports = __webpack_require__(/*! ./transports/index */ \\\"./lib/transports/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:socket\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseuri = __webpack_require__(/*! parseuri */ \\\"./node_modules/parseuri/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar Socket =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Socket, _Emitter);\\n\\n  /**\\n   * Socket constructor.\\n   *\\n   * @param {String|Object} uri or options\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Socket(uri) {\\n    var _this;\\n\\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\\n\\n    _classCallCheck(this, Socket);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Socket).call(this));\\n\\n    if (uri && \\\"object\\\" === _typeof(uri)) {\\n      opts = uri;\\n      uri = null;\\n    }\\n\\n    if (uri) {\\n      uri = parseuri(uri);\\n      opts.hostname = uri.host;\\n      opts.secure = uri.protocol === \\\"https\\\" || uri.protocol === \\\"wss\\\";\\n      opts.port = uri.port;\\n      if (uri.query) opts.query = uri.query;\\n    } else if (opts.host) {\\n      opts.hostname = parseuri(opts.host).host;\\n    }\\n\\n    _this.secure = null != opts.secure ? opts.secure : typeof location !== \\\"undefined\\\" && \\\"https:\\\" === location.protocol;\\n\\n    if (opts.hostname && !opts.port) {\\n      // if no port is specified manually, use the protocol default\\n      opts.port = _this.secure ? \\\"443\\\" : \\\"80\\\";\\n    }\\n\\n    _this.hostname = opts.hostname || (typeof location !== \\\"undefined\\\" ? location.hostname : \\\"localhost\\\");\\n    _this.port = opts.port || (typeof location !== \\\"undefined\\\" && location.port ? location.port : _this.secure ? 443 : 80);\\n    _this.transports = opts.transports || [\\\"polling\\\", \\\"websocket\\\"];\\n    _this.readyState = \\\"\\\";\\n    _this.writeBuffer = [];\\n    _this.prevBufferLen = 0;\\n    _this.opts = _extends({\\n      path: \\\"/engine.io\\\",\\n      agent: false,\\n      withCredentials: false,\\n      upgrade: true,\\n      jsonp: true,\\n      timestampParam: \\\"t\\\",\\n      policyPort: 843,\\n      rememberUpgrade: false,\\n      rejectUnauthorized: true,\\n      perMessageDeflate: {\\n        threshold: 1024\\n      },\\n      transportOptions: {}\\n    }, opts);\\n    _this.opts.path = _this.opts.path.replace(/\\\\/$/, \\\"\\\") + \\\"/\\\";\\n\\n    if (typeof _this.opts.query === \\\"string\\\") {\\n      _this.opts.query = parseqs.decode(_this.opts.query);\\n    } // set on handshake\\n\\n\\n    _this.id = null;\\n    _this.upgrades = null;\\n    _this.pingInterval = null;\\n    _this.pingTimeout = null; // set on heartbeat\\n\\n    _this.pingTimeoutTimer = null;\\n\\n    _this.open();\\n\\n    return _this;\\n  }\\n  /**\\n   * Creates transport of the given type.\\n   *\\n   * @param {String} transport name\\n   * @return {Transport}\\n   * @api private\\n   */\\n\\n\\n  _createClass(Socket, [{\\n    key: \\\"createTransport\\\",\\n    value: function createTransport(name) {\\n      debug('creating transport \\\"%s\\\"', name);\\n      var query = clone(this.opts.query); // append engine.io protocol identifier\\n\\n      query.EIO = parser.protocol; // transport name\\n\\n      query.transport = name; // session id if we already have one\\n\\n      if (this.id) query.sid = this.id;\\n\\n      var opts = _extends({}, this.opts.transportOptions[name], this.opts, {\\n        query: query,\\n        socket: this,\\n        hostname: this.hostname,\\n        secure: this.secure,\\n        port: this.port\\n      });\\n\\n      debug(\\\"options: %j\\\", opts);\\n      return new transports[name](opts);\\n    }\\n    /**\\n     * Initializes transport to use and starts probe.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      var transport;\\n\\n      if (this.opts.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf(\\\"websocket\\\") !== -1) {\\n        transport = \\\"websocket\\\";\\n      } else if (0 === this.transports.length) {\\n        // Emit error on next tick so it can be listened to\\n        var self = this;\\n        setTimeout(function () {\\n          self.emit(\\\"error\\\", \\\"No transports available\\\");\\n        }, 0);\\n        return;\\n      } else {\\n        transport = this.transports[0];\\n      }\\n\\n      this.readyState = \\\"opening\\\"; // Retry with the next transport if the transport is disabled (jsonp: false)\\n\\n      try {\\n        transport = this.createTransport(transport);\\n      } catch (e) {\\n        debug(\\\"error while creating transport: %s\\\", e);\\n        this.transports.shift();\\n        this.open();\\n        return;\\n      }\\n\\n      transport.open();\\n      this.setTransport(transport);\\n    }\\n    /**\\n     * Sets the current transport. Disables the existing one (if any).\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"setTransport\\\",\\n    value: function setTransport(transport) {\\n      debug(\\\"setting transport %s\\\", transport.name);\\n      var self = this;\\n\\n      if (this.transport) {\\n        debug(\\\"clearing existing transport %s\\\", this.transport.name);\\n        this.transport.removeAllListeners();\\n      } // set up transport\\n\\n\\n      this.transport = transport; // set up transport listeners\\n\\n      transport.on(\\\"drain\\\", function () {\\n        self.onDrain();\\n      }).on(\\\"packet\\\", function (packet) {\\n        self.onPacket(packet);\\n      }).on(\\\"error\\\", function (e) {\\n        self.onError(e);\\n      }).on(\\\"close\\\", function () {\\n        self.onClose(\\\"transport close\\\");\\n      });\\n    }\\n    /**\\n     * Probes a transport.\\n     *\\n     * @param {String} transport name\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"probe\\\",\\n    value: function probe(name) {\\n      debug('probing transport \\\"%s\\\"', name);\\n      var transport = this.createTransport(name, {\\n        probe: 1\\n      });\\n      var failed = false;\\n      var self = this;\\n      Socket.priorWebsocketSuccess = false;\\n\\n      function onTransportOpen() {\\n        if (self.onlyBinaryUpgrades) {\\n          var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;\\n          failed = failed || upgradeLosesBinary;\\n        }\\n\\n        if (failed) return;\\n        debug('probe transport \\\"%s\\\" opened', name);\\n        transport.send([{\\n          type: \\\"ping\\\",\\n          data: \\\"probe\\\"\\n        }]);\\n        transport.once(\\\"packet\\\", function (msg) {\\n          if (failed) return;\\n\\n          if (\\\"pong\\\" === msg.type && \\\"probe\\\" === msg.data) {\\n            debug('probe transport \\\"%s\\\" pong', name);\\n            self.upgrading = true;\\n            self.emit(\\\"upgrading\\\", transport);\\n            if (!transport) return;\\n            Socket.priorWebsocketSuccess = \\\"websocket\\\" === transport.name;\\n            debug('pausing current transport \\\"%s\\\"', self.transport.name);\\n            self.transport.pause(function () {\\n              if (failed) return;\\n              if (\\\"closed\\\" === self.readyState) return;\\n              debug(\\\"changing transport and sending upgrade packet\\\");\\n              cleanup();\\n              self.setTransport(transport);\\n              transport.send([{\\n                type: \\\"upgrade\\\"\\n              }]);\\n              self.emit(\\\"upgrade\\\", transport);\\n              transport = null;\\n              self.upgrading = false;\\n              self.flush();\\n            });\\n          } else {\\n            debug('probe transport \\\"%s\\\" failed', name);\\n            var err = new Error(\\\"probe error\\\");\\n            err.transport = transport.name;\\n            self.emit(\\\"upgradeError\\\", err);\\n          }\\n        });\\n      }\\n\\n      function freezeTransport() {\\n        if (failed) return; // Any callback called by transport should be ignored since now\\n\\n        failed = true;\\n        cleanup();\\n        transport.close();\\n        transport = null;\\n      } // Handle any error that happens while probing\\n\\n\\n      function onerror(err) {\\n        var error = new Error(\\\"probe error: \\\" + err);\\n        error.transport = transport.name;\\n        freezeTransport();\\n        debug('probe transport \\\"%s\\\" failed because of error: %s', name, err);\\n        self.emit(\\\"upgradeError\\\", error);\\n      }\\n\\n      function onTransportClose() {\\n        onerror(\\\"transport closed\\\");\\n      } // When the socket is closed while we're probing\\n\\n\\n      function onclose() {\\n        onerror(\\\"socket closed\\\");\\n      } // When the socket is upgraded while we're probing\\n\\n\\n      function onupgrade(to) {\\n        if (transport && to.name !== transport.name) {\\n          debug('\\\"%s\\\" works - aborting \\\"%s\\\"', to.name, transport.name);\\n          freezeTransport();\\n        }\\n      } // Remove all listeners on the transport and on self\\n\\n\\n      function cleanup() {\\n        transport.removeListener(\\\"open\\\", onTransportOpen);\\n        transport.removeListener(\\\"error\\\", onerror);\\n        transport.removeListener(\\\"close\\\", onTransportClose);\\n        self.removeListener(\\\"close\\\", onclose);\\n        self.removeListener(\\\"upgrading\\\", onupgrade);\\n      }\\n\\n      transport.once(\\\"open\\\", onTransportOpen);\\n      transport.once(\\\"error\\\", onerror);\\n      transport.once(\\\"close\\\", onTransportClose);\\n      this.once(\\\"close\\\", onclose);\\n      this.once(\\\"upgrading\\\", onupgrade);\\n      transport.open();\\n    }\\n    /**\\n     * Called when connection is deemed open.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      debug(\\\"socket open\\\");\\n      this.readyState = \\\"open\\\";\\n      Socket.priorWebsocketSuccess = \\\"websocket\\\" === this.transport.name;\\n      this.emit(\\\"open\\\");\\n      this.flush(); // we check for `readyState` in case an `open`\\n      // listener already closed the socket\\n\\n      if (\\\"open\\\" === this.readyState && this.opts.upgrade && this.transport.pause) {\\n        debug(\\\"starting upgrade probes\\\");\\n        var i = 0;\\n        var l = this.upgrades.length;\\n\\n        for (; i < l; i++) {\\n          this.probe(this.upgrades[i]);\\n        }\\n      }\\n    }\\n    /**\\n     * Handles a packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket receive: type \\\"%s\\\", data \\\"%s\\\"', packet.type, packet.data);\\n        this.emit(\\\"packet\\\", packet); // Socket is live - any packet counts\\n\\n        this.emit(\\\"heartbeat\\\");\\n\\n        switch (packet.type) {\\n          case \\\"open\\\":\\n            this.onHandshake(JSON.parse(packet.data));\\n            break;\\n\\n          case \\\"ping\\\":\\n            this.resetPingTimeout();\\n            this.sendPacket(\\\"pong\\\");\\n            this.emit(\\\"pong\\\");\\n            break;\\n\\n          case \\\"error\\\":\\n            var err = new Error(\\\"server error\\\");\\n            err.code = packet.data;\\n            this.onError(err);\\n            break;\\n\\n          case \\\"message\\\":\\n            this.emit(\\\"data\\\", packet.data);\\n            this.emit(\\\"message\\\", packet.data);\\n            break;\\n        }\\n      } else {\\n        debug('packet received with socket readyState \\\"%s\\\"', this.readyState);\\n      }\\n    }\\n    /**\\n     * Called upon handshake completion.\\n     *\\n     * @param {Object} handshake obj\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onHandshake\\\",\\n    value: function onHandshake(data) {\\n      this.emit(\\\"handshake\\\", data);\\n      this.id = data.sid;\\n      this.transport.query.sid = data.sid;\\n      this.upgrades = this.filterUpgrades(data.upgrades);\\n      this.pingInterval = data.pingInterval;\\n      this.pingTimeout = data.pingTimeout;\\n      this.onOpen(); // In case open handler closes socket\\n\\n      if (\\\"closed\\\" === this.readyState) return;\\n      this.resetPingTimeout();\\n    }\\n    /**\\n     * Sets and resets ping timeout timer based on server pings.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"resetPingTimeout\\\",\\n    value: function resetPingTimeout() {\\n      var _this2 = this;\\n\\n      clearTimeout(this.pingTimeoutTimer);\\n      this.pingTimeoutTimer = setTimeout(function () {\\n        _this2.onClose(\\\"ping timeout\\\");\\n      }, this.pingInterval + this.pingTimeout);\\n    }\\n    /**\\n     * Called on `drain` event\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onDrain\\\",\\n    value: function onDrain() {\\n      this.writeBuffer.splice(0, this.prevBufferLen); // setting prevBufferLen = 0 is very important\\n      // for example, when upgrading, upgrade packet is sent over,\\n      // and a nonzero prevBufferLen could cause problems on `drain`\\n\\n      this.prevBufferLen = 0;\\n\\n      if (0 === this.writeBuffer.length) {\\n        this.emit(\\\"drain\\\");\\n      } else {\\n        this.flush();\\n      }\\n    }\\n    /**\\n     * Flush write buffers.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"flush\\\",\\n    value: function flush() {\\n      if (\\\"closed\\\" !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) {\\n        debug(\\\"flushing %d packets in socket\\\", this.writeBuffer.length);\\n        this.transport.send(this.writeBuffer); // keep track of current length of writeBuffer\\n        // splice writeBuffer and callbackBuffer on `drain`\\n\\n        this.prevBufferLen = this.writeBuffer.length;\\n        this.emit(\\\"flush\\\");\\n      }\\n    }\\n    /**\\n     * Sends a message.\\n     *\\n     * @param {String} message.\\n     * @param {Function} callback function.\\n     * @param {Object} options.\\n     * @return {Socket} for chaining.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(msg, options, fn) {\\n      this.sendPacket(\\\"message\\\", msg, options, fn);\\n      return this;\\n    }\\n    /**\\n     * Sends a packet.\\n     *\\n     * @param {String} packet type.\\n     * @param {String} data.\\n     * @param {Object} options.\\n     * @param {Function} callback function.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"sendPacket\\\",\\n    value: function sendPacket(type, data, options, fn) {\\n      if (\\\"function\\\" === typeof data) {\\n        fn = data;\\n        data = undefined;\\n      }\\n\\n      if (\\\"function\\\" === typeof options) {\\n        fn = options;\\n        options = null;\\n      }\\n\\n      if (\\\"closing\\\" === this.readyState || \\\"closed\\\" === this.readyState) {\\n        return;\\n      }\\n\\n      options = options || {};\\n      options.compress = false !== options.compress;\\n      var packet = {\\n        type: type,\\n        data: data,\\n        options: options\\n      };\\n      this.emit(\\\"packetCreate\\\", packet);\\n      this.writeBuffer.push(packet);\\n      if (fn) this.once(\\\"flush\\\", fn);\\n      this.flush();\\n    }\\n    /**\\n     * Closes the connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      var self = this;\\n\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.readyState = \\\"closing\\\";\\n\\n        if (this.writeBuffer.length) {\\n          this.once(\\\"drain\\\", function () {\\n            if (this.upgrading) {\\n              waitForUpgrade();\\n            } else {\\n              close();\\n            }\\n          });\\n        } else if (this.upgrading) {\\n          waitForUpgrade();\\n        } else {\\n          close();\\n        }\\n      }\\n\\n      function close() {\\n        self.onClose(\\\"forced close\\\");\\n        debug(\\\"socket closing - telling transport to close\\\");\\n        self.transport.close();\\n      }\\n\\n      function cleanupAndClose() {\\n        self.removeListener(\\\"upgrade\\\", cleanupAndClose);\\n        self.removeListener(\\\"upgradeError\\\", cleanupAndClose);\\n        close();\\n      }\\n\\n      function waitForUpgrade() {\\n        // wait for upgrade to finish since we can't send packets while pausing a transport\\n        self.once(\\\"upgrade\\\", cleanupAndClose);\\n        self.once(\\\"upgradeError\\\", cleanupAndClose);\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Called upon transport error\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      debug(\\\"socket error %j\\\", err);\\n      Socket.priorWebsocketSuccess = false;\\n      this.emit(\\\"error\\\", err);\\n      this.onClose(\\\"transport error\\\", err);\\n    }\\n    /**\\n     * Called upon transport close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose(reason, desc) {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState || \\\"closing\\\" === this.readyState) {\\n        debug('socket close with reason: \\\"%s\\\"', reason);\\n        var self = this; // clear timers\\n\\n        clearTimeout(this.pingIntervalTimer);\\n        clearTimeout(this.pingTimeoutTimer); // stop event from firing again for transport\\n\\n        this.transport.removeAllListeners(\\\"close\\\"); // ensure transport won't stay open\\n\\n        this.transport.close(); // ignore further transport communication\\n\\n        this.transport.removeAllListeners(); // set ready state\\n\\n        this.readyState = \\\"closed\\\"; // clear session id\\n\\n        this.id = null; // emit close event\\n\\n        this.emit(\\\"close\\\", reason, desc); // clean buffers after, so users can still\\n        // grab the buffers on `close` event\\n\\n        self.writeBuffer = [];\\n        self.prevBufferLen = 0;\\n      }\\n    }\\n    /**\\n     * Filters upgrades, returning only those matching client transports.\\n     *\\n     * @param {Array} server upgrades\\n     * @api private\\n     *\\n     */\\n\\n  }, {\\n    key: \\\"filterUpgrades\\\",\\n    value: function filterUpgrades(upgrades) {\\n      var filteredUpgrades = [];\\n      var i = 0;\\n      var j = upgrades.length;\\n\\n      for (; i < j; i++) {\\n        if (~this.transports.indexOf(upgrades[i])) filteredUpgrades.push(upgrades[i]);\\n      }\\n\\n      return filteredUpgrades;\\n    }\\n  }]);\\n\\n  return Socket;\\n}(Emitter);\\n\\nSocket.priorWebsocketSuccess = false;\\n/**\\n * Protocol version.\\n *\\n * @api public\\n */\\n\\nSocket.protocol = parser.protocol; // this is an int\\n\\nfunction clone(obj) {\\n  var o = {};\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      o[i] = obj[i];\\n    }\\n  }\\n\\n  return o;\\n}\\n\\nmodule.exports = Socket;\\n\\n//# sourceURL=webpack://eio/./lib/socket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transport.js\":\n/*!**************************!*\\\n  !*** ./lib/transport.js ***!\n  \\**************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar Transport =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Transport, _Emitter);\\n\\n  /**\\n   * Transport abstract constructor.\\n   *\\n   * @param {Object} options.\\n   * @api private\\n   */\\n  function Transport(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, Transport);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(Transport).call(this));\\n    _this.opts = opts;\\n    _this.query = opts.query;\\n    _this.readyState = \\\"\\\";\\n    _this.socket = opts.socket;\\n    return _this;\\n  }\\n  /**\\n   * Emits an error.\\n   *\\n   * @param {String} str\\n   * @return {Transport} for chaining\\n   * @api public\\n   */\\n\\n\\n  _createClass(Transport, [{\\n    key: \\\"onError\\\",\\n    value: function onError(msg, desc) {\\n      var err = new Error(msg);\\n      err.type = \\\"TransportError\\\";\\n      err.description = desc;\\n      this.emit(\\\"error\\\", err);\\n      return this;\\n    }\\n    /**\\n     * Opens the transport.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"open\\\",\\n    value: function open() {\\n      if (\\\"closed\\\" === this.readyState || \\\"\\\" === this.readyState) {\\n        this.readyState = \\\"opening\\\";\\n        this.doOpen();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Closes the transport.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"close\\\",\\n    value: function close() {\\n      if (\\\"opening\\\" === this.readyState || \\\"open\\\" === this.readyState) {\\n        this.doClose();\\n        this.onClose();\\n      }\\n\\n      return this;\\n    }\\n    /**\\n     * Sends multiple packets.\\n     *\\n     * @param {Array} packets\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"send\\\",\\n    value: function send(packets) {\\n      if (\\\"open\\\" === this.readyState) {\\n        this.write(packets);\\n      } else {\\n        throw new Error(\\\"Transport not open\\\");\\n      }\\n    }\\n    /**\\n     * Called upon open\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onOpen\\\",\\n    value: function onOpen() {\\n      this.readyState = \\\"open\\\";\\n      this.writable = true;\\n      this.emit(\\\"open\\\");\\n    }\\n    /**\\n     * Called with data.\\n     *\\n     * @param {String} data\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var packet = parser.decodePacket(data, this.socket.binaryType);\\n      this.onPacket(packet);\\n    }\\n    /**\\n     * Called with a decoded packet.\\n     */\\n\\n  }, {\\n    key: \\\"onPacket\\\",\\n    value: function onPacket(packet) {\\n      this.emit(\\\"packet\\\", packet);\\n    }\\n    /**\\n     * Called upon close.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      this.readyState = \\\"closed\\\";\\n      this.emit(\\\"close\\\");\\n    }\\n  }]);\\n\\n  return Transport;\\n}(Emitter);\\n\\nmodule.exports = Transport;\\n\\n//# sourceURL=webpack://eio/./lib/transport.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/index.js\":\n/*!*********************************!*\\\n  !*** ./lib/transports/index.js ***!\n  \\*********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar XHR = __webpack_require__(/*! ./polling-xhr */ \\\"./lib/transports/polling-xhr.js\\\");\\n\\nvar JSONP = __webpack_require__(/*! ./polling-jsonp */ \\\"./lib/transports/polling-jsonp.js\\\");\\n\\nvar websocket = __webpack_require__(/*! ./websocket */ \\\"./lib/transports/websocket.js\\\");\\n\\nexports.polling = polling;\\nexports.websocket = websocket;\\n/**\\n * Polling transport polymorphic constructor.\\n * Decides on xhr vs jsonp based on feature detection.\\n *\\n * @api private\\n */\\n\\nfunction polling(opts) {\\n  var xhr;\\n  var xd = false;\\n  var xs = false;\\n  var jsonp = false !== opts.jsonp;\\n\\n  if (typeof location !== \\\"undefined\\\") {\\n    var isSSL = \\\"https:\\\" === location.protocol;\\n    var port = location.port; // some user agents have empty `location.port`\\n\\n    if (!port) {\\n      port = isSSL ? 443 : 80;\\n    }\\n\\n    xd = opts.hostname !== location.hostname || port !== opts.port;\\n    xs = opts.secure !== isSSL;\\n  }\\n\\n  opts.xdomain = xd;\\n  opts.xscheme = xs;\\n  xhr = new XMLHttpRequest(opts);\\n\\n  if (\\\"open\\\" in xhr && !opts.forceJSONP) {\\n    return new XHR(opts);\\n  } else {\\n    if (!jsonp) throw new Error(\\\"JSONP disabled\\\");\\n    return new JSONP(opts);\\n  }\\n}\\n\\n//# sourceURL=webpack://eio/./lib/transports/index.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-jsonp.js\":\n/*!*****************************************!*\\\n  !*** ./lib/transports/polling-jsonp.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _get(target, property, receiver) { if (typeof Reflect !== \\\"undefined\\\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\\n\\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar rNewline = /\\\\n/g;\\nvar rEscapedNewline = /\\\\\\\\n/g;\\n/**\\n * Global JSONP callbacks.\\n */\\n\\nvar callbacks;\\n/**\\n * Noop.\\n */\\n\\nfunction empty() {}\\n\\nvar JSONPPolling =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(JSONPPolling, _Polling);\\n\\n  /**\\n   * JSONP Polling constructor.\\n   *\\n   * @param {Object} opts.\\n   * @api public\\n   */\\n  function JSONPPolling(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, JSONPPolling);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(JSONPPolling).call(this, opts));\\n    _this.query = _this.query || {}; // define global callbacks array if not present\\n    // we do this here (lazily) to avoid unneeded global pollution\\n\\n    if (!callbacks) {\\n      // we need to consider multiple engines in the same page\\n      callbacks = globalThis.___eio = globalThis.___eio || [];\\n    } // callback identifier\\n\\n\\n    _this.index = callbacks.length; // add callback to jsonp global\\n\\n    var self = _assertThisInitialized(_this);\\n\\n    callbacks.push(function (msg) {\\n      self.onData(msg);\\n    }); // append to query string\\n\\n    _this.query.j = _this.index; // prevent spurious errors from being emitted when the window is unloaded\\n\\n    if (typeof addEventListener === \\\"function\\\") {\\n      addEventListener(\\\"beforeunload\\\", function () {\\n        if (self.script) self.script.onerror = empty;\\n      }, false);\\n    }\\n\\n    return _this;\\n  }\\n  /**\\n   * JSONP only supports binary as base64 encoded strings\\n   */\\n\\n\\n  _createClass(JSONPPolling, [{\\n    key: \\\"doClose\\\",\\n\\n    /**\\n     * Closes the socket.\\n     *\\n     * @api private\\n     */\\n    value: function doClose() {\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      if (this.form) {\\n        this.form.parentNode.removeChild(this.form);\\n        this.form = null;\\n        this.iframe = null;\\n      }\\n\\n      _get(_getPrototypeOf(JSONPPolling.prototype), \\\"doClose\\\", this).call(this);\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      var self = this;\\n      var script = document.createElement(\\\"script\\\");\\n\\n      if (this.script) {\\n        this.script.parentNode.removeChild(this.script);\\n        this.script = null;\\n      }\\n\\n      script.async = true;\\n      script.src = this.uri();\\n\\n      script.onerror = function (e) {\\n        self.onError(\\\"jsonp poll error\\\", e);\\n      };\\n\\n      var insertAt = document.getElementsByTagName(\\\"script\\\")[0];\\n\\n      if (insertAt) {\\n        insertAt.parentNode.insertBefore(script, insertAt);\\n      } else {\\n        (document.head || document.body).appendChild(script);\\n      }\\n\\n      this.script = script;\\n      var isUAgecko = \\\"undefined\\\" !== typeof navigator && /gecko/i.test(navigator.userAgent);\\n\\n      if (isUAgecko) {\\n        setTimeout(function () {\\n          var iframe = document.createElement(\\\"iframe\\\");\\n          document.body.appendChild(iframe);\\n          document.body.removeChild(iframe);\\n        }, 100);\\n      }\\n    }\\n    /**\\n     * Writes with a hidden iframe.\\n     *\\n     * @param {String} data to send\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var self = this;\\n      var iframe;\\n\\n      if (!this.form) {\\n        var form = document.createElement(\\\"form\\\");\\n        var area = document.createElement(\\\"textarea\\\");\\n        var id = this.iframeId = \\\"eio_iframe_\\\" + this.index;\\n        form.className = \\\"socketio\\\";\\n        form.style.position = \\\"absolute\\\";\\n        form.style.top = \\\"-1000px\\\";\\n        form.style.left = \\\"-1000px\\\";\\n        form.target = id;\\n        form.method = \\\"POST\\\";\\n        form.setAttribute(\\\"accept-charset\\\", \\\"utf-8\\\");\\n        area.name = \\\"d\\\";\\n        form.appendChild(area);\\n        document.body.appendChild(form);\\n        this.form = form;\\n        this.area = area;\\n      }\\n\\n      this.form.action = this.uri();\\n\\n      function complete() {\\n        initIframe();\\n        fn();\\n      }\\n\\n      function initIframe() {\\n        if (self.iframe) {\\n          try {\\n            self.form.removeChild(self.iframe);\\n          } catch (e) {\\n            self.onError(\\\"jsonp polling iframe removal error\\\", e);\\n          }\\n        }\\n\\n        try {\\n          // ie6 dynamic iframes with target=\\\"\\\" support (thanks Chris Lambacher)\\n          var html = '<iframe src=\\\"javascript:0\\\" name=\\\"' + self.iframeId + '\\\">';\\n          iframe = document.createElement(html);\\n        } catch (e) {\\n          iframe = document.createElement(\\\"iframe\\\");\\n          iframe.name = self.iframeId;\\n          iframe.src = \\\"javascript:0\\\";\\n        }\\n\\n        iframe.id = self.iframeId;\\n        self.form.appendChild(iframe);\\n        self.iframe = iframe;\\n      }\\n\\n      initIframe(); // escape \\\\n to prevent it from being converted into \\\\r\\\\n by some UAs\\n      // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side\\n\\n      data = data.replace(rEscapedNewline, \\\"\\\\\\\\\\\\n\\\");\\n      this.area.value = data.replace(rNewline, \\\"\\\\\\\\n\\\");\\n\\n      try {\\n        this.form.submit();\\n      } catch (e) {}\\n\\n      if (this.iframe.attachEvent) {\\n        this.iframe.onreadystatechange = function () {\\n          if (self.iframe.readyState === \\\"complete\\\") {\\n            complete();\\n          }\\n        };\\n      } else {\\n        this.iframe.onload = complete;\\n      }\\n    }\\n  }, {\\n    key: \\\"supportsBinary\\\",\\n    get: function get() {\\n      return false;\\n    }\\n  }]);\\n\\n  return JSONPPolling;\\n}(Polling);\\n\\nmodule.exports = JSONPPolling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-jsonp.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling-xhr.js\":\n/*!***************************************!*\\\n  !*** ./lib/transports/polling-xhr.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\n/* global attachEvent */\\nvar XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\nvar Polling = __webpack_require__(/*! ./polling */ \\\"./lib/transports/polling.js\\\");\\n\\nvar Emitter = __webpack_require__(/*! component-emitter */ \\\"./node_modules/component-emitter/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling-xhr\\\");\\n/**\\n * Empty function\\n */\\n\\n\\nfunction empty() {}\\n\\nvar hasXHR2 = function () {\\n  var XMLHttpRequest = __webpack_require__(/*! xmlhttprequest-ssl */ \\\"./lib/xmlhttprequest.js\\\");\\n\\n  var xhr = new XMLHttpRequest({\\n    xdomain: false\\n  });\\n  return null != xhr.responseType;\\n}();\\n\\nvar XHR =\\n/*#__PURE__*/\\nfunction (_Polling) {\\n  _inherits(XHR, _Polling);\\n\\n  /**\\n   * XHR Polling constructor.\\n   *\\n   * @param {Object} opts\\n   * @api public\\n   */\\n  function XHR(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, XHR);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(XHR).call(this, opts));\\n\\n    if (typeof location !== \\\"undefined\\\") {\\n      var isSSL = \\\"https:\\\" === location.protocol;\\n      var port = location.port; // some user agents have empty `location.port`\\n\\n      if (!port) {\\n        port = isSSL ? 443 : 80;\\n      }\\n\\n      _this.xd = typeof location !== \\\"undefined\\\" && opts.hostname !== location.hostname || port !== opts.port;\\n      _this.xs = opts.secure !== isSSL;\\n    }\\n    /**\\n     * XHR supports binary\\n     */\\n\\n\\n    var forceBase64 = opts && opts.forceBase64;\\n    _this.supportsBinary = hasXHR2 && !forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Creates a request.\\n   *\\n   * @param {String} method\\n   * @api private\\n   */\\n\\n\\n  _createClass(XHR, [{\\n    key: \\\"request\\\",\\n    value: function request() {\\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\\n\\n      _extends(opts, {\\n        xd: this.xd,\\n        xs: this.xs\\n      }, this.opts);\\n\\n      return new Request(this.uri(), opts);\\n    }\\n    /**\\n     * Sends data.\\n     *\\n     * @param {String} data to send.\\n     * @param {Function} called upon flush.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doWrite\\\",\\n    value: function doWrite(data, fn) {\\n      var req = this.request({\\n        method: \\\"POST\\\",\\n        data: data\\n      });\\n      var self = this;\\n      req.on(\\\"success\\\", fn);\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr post error\\\", err);\\n      });\\n    }\\n    /**\\n     * Starts a poll cycle.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doPoll\\\",\\n    value: function doPoll() {\\n      debug(\\\"xhr poll\\\");\\n      var req = this.request();\\n      var self = this;\\n      req.on(\\\"data\\\", function (data) {\\n        self.onData(data);\\n      });\\n      req.on(\\\"error\\\", function (err) {\\n        self.onError(\\\"xhr poll error\\\", err);\\n      });\\n      this.pollXhr = req;\\n    }\\n  }]);\\n\\n  return XHR;\\n}(Polling);\\n\\nvar Request =\\n/*#__PURE__*/\\nfunction (_Emitter) {\\n  _inherits(Request, _Emitter);\\n\\n  /**\\n   * Request constructor\\n   *\\n   * @param {Object} options\\n   * @api public\\n   */\\n  function Request(uri, opts) {\\n    var _this2;\\n\\n    _classCallCheck(this, Request);\\n\\n    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Request).call(this));\\n    _this2.opts = opts;\\n    _this2.method = opts.method || \\\"GET\\\";\\n    _this2.uri = uri;\\n    _this2.async = false !== opts.async;\\n    _this2.data = undefined !== opts.data ? opts.data : null;\\n\\n    _this2.create();\\n\\n    return _this2;\\n  }\\n  /**\\n   * Creates the XHR object and sends the request.\\n   *\\n   * @api private\\n   */\\n\\n\\n  _createClass(Request, [{\\n    key: \\\"create\\\",\\n    value: function create() {\\n      var opts = pick(this.opts, \\\"agent\\\", \\\"enablesXDR\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\");\\n      opts.xdomain = !!this.opts.xd;\\n      opts.xscheme = !!this.opts.xs;\\n      var xhr = this.xhr = new XMLHttpRequest(opts);\\n      var self = this;\\n\\n      try {\\n        debug(\\\"xhr open %s: %s\\\", this.method, this.uri);\\n        xhr.open(this.method, this.uri, this.async);\\n\\n        try {\\n          if (this.opts.extraHeaders) {\\n            xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);\\n\\n            for (var i in this.opts.extraHeaders) {\\n              if (this.opts.extraHeaders.hasOwnProperty(i)) {\\n                xhr.setRequestHeader(i, this.opts.extraHeaders[i]);\\n              }\\n            }\\n          }\\n        } catch (e) {}\\n\\n        if (\\\"POST\\\" === this.method) {\\n          try {\\n            xhr.setRequestHeader(\\\"Content-type\\\", \\\"text/plain;charset=UTF-8\\\");\\n          } catch (e) {}\\n        }\\n\\n        try {\\n          xhr.setRequestHeader(\\\"Accept\\\", \\\"*/*\\\");\\n        } catch (e) {} // ie6 check\\n\\n\\n        if (\\\"withCredentials\\\" in xhr) {\\n          xhr.withCredentials = this.opts.withCredentials;\\n        }\\n\\n        if (this.opts.requestTimeout) {\\n          xhr.timeout = this.opts.requestTimeout;\\n        }\\n\\n        if (this.hasXDR()) {\\n          xhr.onload = function () {\\n            self.onLoad();\\n          };\\n\\n          xhr.onerror = function () {\\n            self.onError(xhr.responseText);\\n          };\\n        } else {\\n          xhr.onreadystatechange = function () {\\n            if (4 !== xhr.readyState) return;\\n\\n            if (200 === xhr.status || 1223 === xhr.status) {\\n              self.onLoad();\\n            } else {\\n              // make sure the `error` event handler that's user-set\\n              // does not throw in the same tick and gets caught here\\n              setTimeout(function () {\\n                self.onError(typeof xhr.status === \\\"number\\\" ? xhr.status : 0);\\n              }, 0);\\n            }\\n          };\\n        }\\n\\n        debug(\\\"xhr data %s\\\", this.data);\\n        xhr.send(this.data);\\n      } catch (e) {\\n        // Need to defer since .create() is called directly from the constructor\\n        // and thus the 'error' event can only be only bound *after* this exception\\n        // occurs.  Therefore, also, we cannot throw here at all.\\n        setTimeout(function () {\\n          self.onError(e);\\n        }, 0);\\n        return;\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        this.index = Request.requestsCount++;\\n        Request.requests[this.index] = this;\\n      }\\n    }\\n    /**\\n     * Called upon successful response.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onSuccess\\\",\\n    value: function onSuccess() {\\n      this.emit(\\\"success\\\");\\n      this.cleanup();\\n    }\\n    /**\\n     * Called if we have data.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      this.emit(\\\"data\\\", data);\\n      this.onSuccess();\\n    }\\n    /**\\n     * Called upon error.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onError\\\",\\n    value: function onError(err) {\\n      this.emit(\\\"error\\\", err);\\n      this.cleanup(true);\\n    }\\n    /**\\n     * Cleans up house.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"cleanup\\\",\\n    value: function cleanup(fromError) {\\n      if (\\\"undefined\\\" === typeof this.xhr || null === this.xhr) {\\n        return;\\n      } // xmlhttprequest\\n\\n\\n      if (this.hasXDR()) {\\n        this.xhr.onload = this.xhr.onerror = empty;\\n      } else {\\n        this.xhr.onreadystatechange = empty;\\n      }\\n\\n      if (fromError) {\\n        try {\\n          this.xhr.abort();\\n        } catch (e) {}\\n      }\\n\\n      if (typeof document !== \\\"undefined\\\") {\\n        delete Request.requests[this.index];\\n      }\\n\\n      this.xhr = null;\\n    }\\n    /**\\n     * Called upon load.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onLoad\\\",\\n    value: function onLoad() {\\n      var data = this.xhr.responseText;\\n\\n      if (data !== null) {\\n        this.onData(data);\\n      }\\n    }\\n    /**\\n     * Check if it has XDomainRequest.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"hasXDR\\\",\\n    value: function hasXDR() {\\n      return typeof XDomainRequest !== \\\"undefined\\\" && !this.xs && this.enablesXDR;\\n    }\\n    /**\\n     * Aborts the request.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"abort\\\",\\n    value: function abort() {\\n      this.cleanup();\\n    }\\n  }]);\\n\\n  return Request;\\n}(Emitter);\\n/**\\n * Aborts pending requests when unloading the window. This is needed to prevent\\n * memory leaks (e.g. when using IE) and to ensure that no spurious error is\\n * emitted.\\n */\\n\\n\\nRequest.requestsCount = 0;\\nRequest.requests = {};\\n\\nif (typeof document !== \\\"undefined\\\") {\\n  if (typeof attachEvent === \\\"function\\\") {\\n    attachEvent(\\\"onunload\\\", unloadHandler);\\n  } else if (typeof addEventListener === \\\"function\\\") {\\n    var terminationEvent = \\\"onpagehide\\\" in globalThis ? \\\"pagehide\\\" : \\\"unload\\\";\\n    addEventListener(terminationEvent, unloadHandler, false);\\n  }\\n}\\n\\nfunction unloadHandler() {\\n  for (var i in Request.requests) {\\n    if (Request.requests.hasOwnProperty(i)) {\\n      Request.requests[i].abort();\\n    }\\n  }\\n}\\n\\nmodule.exports = XHR;\\nmodule.exports.Request = Request;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling-xhr.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/polling.js\":\n/*!***********************************!*\\\n  !*** ./lib/transports/polling.js ***!\n  \\***********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:polling\\\");\\n\\nvar Polling =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(Polling, _Transport);\\n\\n  function Polling() {\\n    _classCallCheck(this, Polling);\\n\\n    return _possibleConstructorReturn(this, _getPrototypeOf(Polling).apply(this, arguments));\\n  }\\n\\n  _createClass(Polling, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens the socket (triggers polling). We write a PING message to determine\\n     * when the transport is open.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      this.poll();\\n    }\\n    /**\\n     * Pauses polling.\\n     *\\n     * @param {Function} callback upon buffers are flushed and transport is paused\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"pause\\\",\\n    value: function pause(onPause) {\\n      var self = this;\\n      this.readyState = \\\"pausing\\\";\\n\\n      function pause() {\\n        debug(\\\"paused\\\");\\n        self.readyState = \\\"paused\\\";\\n        onPause();\\n      }\\n\\n      if (this.polling || !this.writable) {\\n        var total = 0;\\n\\n        if (this.polling) {\\n          debug(\\\"we are currently polling - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"pollComplete\\\", function () {\\n            debug(\\\"pre-pause polling complete\\\");\\n            --total || pause();\\n          });\\n        }\\n\\n        if (!this.writable) {\\n          debug(\\\"we are currently writing - waiting to pause\\\");\\n          total++;\\n          this.once(\\\"drain\\\", function () {\\n            debug(\\\"pre-pause writing complete\\\");\\n            --total || pause();\\n          });\\n        }\\n      } else {\\n        pause();\\n      }\\n    }\\n    /**\\n     * Starts polling cycle.\\n     *\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"poll\\\",\\n    value: function poll() {\\n      debug(\\\"polling\\\");\\n      this.polling = true;\\n      this.doPoll();\\n      this.emit(\\\"poll\\\");\\n    }\\n    /**\\n     * Overloads onData to detect payloads.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onData\\\",\\n    value: function onData(data) {\\n      var self = this;\\n      debug(\\\"polling got data %s\\\", data);\\n\\n      var callback = function callback(packet, index, total) {\\n        // if its the first message we consider the transport open\\n        if (\\\"opening\\\" === self.readyState && packet.type === \\\"open\\\") {\\n          self.onOpen();\\n        } // if its a close packet, we close the ongoing requests\\n\\n\\n        if (\\\"close\\\" === packet.type) {\\n          self.onClose();\\n          return false;\\n        } // otherwise bypass onData and handle the message\\n\\n\\n        self.onPacket(packet);\\n      }; // decode payload\\n\\n\\n      parser.decodePayload(data, this.socket.binaryType).forEach(callback); // if an event did not trigger closing\\n\\n      if (\\\"closed\\\" !== this.readyState) {\\n        // if we got data we're not polling\\n        this.polling = false;\\n        this.emit(\\\"pollComplete\\\");\\n\\n        if (\\\"open\\\" === this.readyState) {\\n          this.poll();\\n        } else {\\n          debug('ignoring poll - transport state \\\"%s\\\"', this.readyState);\\n        }\\n      }\\n    }\\n    /**\\n     * For polling, send a close packet.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      var self = this;\\n\\n      function close() {\\n        debug(\\\"writing close packet\\\");\\n        self.write([{\\n          type: \\\"close\\\"\\n        }]);\\n      }\\n\\n      if (\\\"open\\\" === this.readyState) {\\n        debug(\\\"transport open - closing\\\");\\n        close();\\n      } else {\\n        // in case we're trying to close while\\n        // handshaking is in progress (GH-164)\\n        debug(\\\"transport not open - deferring close\\\");\\n        this.once(\\\"open\\\", close);\\n      }\\n    }\\n    /**\\n     * Writes a packets payload.\\n     *\\n     * @param {Array} data packets\\n     * @param {Function} drain callback\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var _this = this;\\n\\n      this.writable = false;\\n      parser.encodePayload(packets, function (data) {\\n        _this.doWrite(data, function () {\\n          _this.writable = true;\\n\\n          _this.emit(\\\"drain\\\");\\n        });\\n      });\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"https\\\" : \\\"http\\\";\\n      var port = \\\"\\\"; // cache busting is forced\\n\\n      if (false !== this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      }\\n\\n      if (!this.supportsBinary && !query.sid) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"https\\\" === schema && Number(this.opts.port) !== 443 || \\\"http\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // prepend ? to query\\n\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n\\n    /**\\n     * Transport name.\\n     */\\n    get: function get() {\\n      return \\\"polling\\\";\\n    }\\n  }]);\\n\\n  return Polling;\\n}(Transport);\\n\\nmodule.exports = Polling;\\n\\n//# sourceURL=webpack://eio/./lib/transports/polling.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket-constructor.browser.js\":\n/*!*********************************************************!*\\\n  !*** ./lib/transports/websocket-constructor.browser.js ***!\n  \\*********************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var globalThis = __webpack_require__(/*! ../globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = {\\n  WebSocket: globalThis.WebSocket || globalThis.MozWebSocket,\\n  usingBrowserWebSocket: true,\\n  defaultBinaryType: \\\"arraybuffer\\\"\\n};\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket-constructor.browser.js?\");\n\n/***/ }),\n\n/***/ \"./lib/transports/websocket.js\":\n/*!*************************************!*\\\n  !*** ./lib/transports/websocket.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nvar Transport = __webpack_require__(/*! ../transport */ \\\"./lib/transport.js\\\");\\n\\nvar parser = __webpack_require__(/*! engine.io-parser */ \\\"./node_modules/engine.io-parser/lib/index.js\\\");\\n\\nvar parseqs = __webpack_require__(/*! parseqs */ \\\"./node_modules/parseqs/index.js\\\");\\n\\nvar yeast = __webpack_require__(/*! yeast */ \\\"./node_modules/yeast/index.js\\\");\\n\\nvar _require = __webpack_require__(/*! ../util */ \\\"./lib/util.js\\\"),\\n    pick = _require.pick;\\n\\nvar _require2 = __webpack_require__(/*! ./websocket-constructor */ \\\"./lib/transports/websocket-constructor.browser.js\\\"),\\n    WebSocket = _require2.WebSocket,\\n    usingBrowserWebSocket = _require2.usingBrowserWebSocket,\\n    defaultBinaryType = _require2.defaultBinaryType;\\n\\nvar debug = __webpack_require__(/*! debug */ \\\"./node_modules/debug/src/browser.js\\\")(\\\"engine.io-client:websocket\\\"); // detect ReactNative environment\\n\\n\\nvar isReactNative = typeof navigator !== \\\"undefined\\\" && typeof navigator.product === \\\"string\\\" && navigator.product.toLowerCase() === \\\"reactnative\\\";\\n\\nvar WS =\\n/*#__PURE__*/\\nfunction (_Transport) {\\n  _inherits(WS, _Transport);\\n\\n  /**\\n   * WebSocket transport constructor.\\n   *\\n   * @api {Object} connection options\\n   * @api public\\n   */\\n  function WS(opts) {\\n    var _this;\\n\\n    _classCallCheck(this, WS);\\n\\n    _this = _possibleConstructorReturn(this, _getPrototypeOf(WS).call(this, opts));\\n    _this.supportsBinary = !opts.forceBase64;\\n    return _this;\\n  }\\n  /**\\n   * Transport name.\\n   *\\n   * @api public\\n   */\\n\\n\\n  _createClass(WS, [{\\n    key: \\\"doOpen\\\",\\n\\n    /**\\n     * Opens socket.\\n     *\\n     * @api private\\n     */\\n    value: function doOpen() {\\n      if (!this.check()) {\\n        // let probe timeout\\n        return;\\n      }\\n\\n      var uri = this.uri();\\n      var protocols = this.opts.protocols; // React Native only supports the 'headers' option, and will print a warning if anything else is passed\\n\\n      var opts = isReactNative ? {} : pick(this.opts, \\\"agent\\\", \\\"perMessageDeflate\\\", \\\"pfx\\\", \\\"key\\\", \\\"passphrase\\\", \\\"cert\\\", \\\"ca\\\", \\\"ciphers\\\", \\\"rejectUnauthorized\\\", \\\"localAddress\\\");\\n\\n      if (this.opts.extraHeaders) {\\n        opts.headers = this.opts.extraHeaders;\\n      }\\n\\n      try {\\n        this.ws = usingBrowserWebSocket && !isReactNative ? protocols ? new WebSocket(uri, protocols) : new WebSocket(uri) : new WebSocket(uri, protocols, opts);\\n      } catch (err) {\\n        return this.emit(\\\"error\\\", err);\\n      }\\n\\n      this.ws.binaryType = this.socket.binaryType || defaultBinaryType;\\n      this.addEventListeners();\\n    }\\n    /**\\n     * Adds event listeners to the socket\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"addEventListeners\\\",\\n    value: function addEventListeners() {\\n      var self = this;\\n\\n      this.ws.onopen = function () {\\n        self.onOpen();\\n      };\\n\\n      this.ws.onclose = function () {\\n        self.onClose();\\n      };\\n\\n      this.ws.onmessage = function (ev) {\\n        self.onData(ev.data);\\n      };\\n\\n      this.ws.onerror = function (e) {\\n        self.onError(\\\"websocket error\\\", e);\\n      };\\n    }\\n    /**\\n     * Writes data to socket.\\n     *\\n     * @param {Array} array of packets.\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"write\\\",\\n    value: function write(packets) {\\n      var self = this;\\n      this.writable = false; // encodePacket efficient as it uses WS framing\\n      // no need for encodePayload\\n\\n      var total = packets.length;\\n      var i = 0;\\n      var l = total;\\n\\n      for (; i < l; i++) {\\n        (function (packet) {\\n          parser.encodePacket(packet, self.supportsBinary, function (data) {\\n            // always create a new object (GH-437)\\n            var opts = {};\\n\\n            if (!usingBrowserWebSocket) {\\n              if (packet.options) {\\n                opts.compress = packet.options.compress;\\n              }\\n\\n              if (self.opts.perMessageDeflate) {\\n                var len = \\\"string\\\" === typeof data ? Buffer.byteLength(data) : data.length;\\n\\n                if (len < self.opts.perMessageDeflate.threshold) {\\n                  opts.compress = false;\\n                }\\n              }\\n            } // Sometimes the websocket has already been closed but the browser didn't\\n            // have a chance of informing us about it yet, in that case send will\\n            // throw an error\\n\\n\\n            try {\\n              if (usingBrowserWebSocket) {\\n                // TypeError is thrown when passing the second argument on Safari\\n                self.ws.send(data);\\n              } else {\\n                self.ws.send(data, opts);\\n              }\\n            } catch (e) {\\n              debug(\\\"websocket closed before onclose event\\\");\\n            }\\n\\n            --total || done();\\n          });\\n        })(packets[i]);\\n      }\\n\\n      function done() {\\n        self.emit(\\\"flush\\\"); // fake drain\\n        // defer to next tick to allow Socket to clear writeBuffer\\n\\n        setTimeout(function () {\\n          self.writable = true;\\n          self.emit(\\\"drain\\\");\\n        }, 0);\\n      }\\n    }\\n    /**\\n     * Called upon close\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"onClose\\\",\\n    value: function onClose() {\\n      Transport.prototype.onClose.call(this);\\n    }\\n    /**\\n     * Closes socket.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"doClose\\\",\\n    value: function doClose() {\\n      if (typeof this.ws !== \\\"undefined\\\") {\\n        this.ws.close();\\n      }\\n    }\\n    /**\\n     * Generates uri for connection.\\n     *\\n     * @api private\\n     */\\n\\n  }, {\\n    key: \\\"uri\\\",\\n    value: function uri() {\\n      var query = this.query || {};\\n      var schema = this.opts.secure ? \\\"wss\\\" : \\\"ws\\\";\\n      var port = \\\"\\\"; // avoid port if default for schema\\n\\n      if (this.opts.port && (\\\"wss\\\" === schema && Number(this.opts.port) !== 443 || \\\"ws\\\" === schema && Number(this.opts.port) !== 80)) {\\n        port = \\\":\\\" + this.opts.port;\\n      } // append timestamp to URI\\n\\n\\n      if (this.opts.timestampRequests) {\\n        query[this.opts.timestampParam] = yeast();\\n      } // communicate binary support capabilities\\n\\n\\n      if (!this.supportsBinary) {\\n        query.b64 = 1;\\n      }\\n\\n      query = parseqs.encode(query); // prepend ? to query\\n\\n      if (query.length) {\\n        query = \\\"?\\\" + query;\\n      }\\n\\n      var ipv6 = this.opts.hostname.indexOf(\\\":\\\") !== -1;\\n      return schema + \\\"://\\\" + (ipv6 ? \\\"[\\\" + this.opts.hostname + \\\"]\\\" : this.opts.hostname) + port + this.opts.path + query;\\n    }\\n    /**\\n     * Feature detection for WebSocket.\\n     *\\n     * @return {Boolean} whether this transport is available.\\n     * @api public\\n     */\\n\\n  }, {\\n    key: \\\"check\\\",\\n    value: function check() {\\n      return !!WebSocket && !(\\\"__initialize\\\" in WebSocket && this.name === WS.prototype.name);\\n    }\\n  }, {\\n    key: \\\"name\\\",\\n    get: function get() {\\n      return \\\"websocket\\\";\\n    }\\n  }]);\\n\\n  return WS;\\n}(Transport);\\n\\nmodule.exports = WS;\\n\\n//# sourceURL=webpack://eio/./lib/transports/websocket.js?\");\n\n/***/ }),\n\n/***/ \"./lib/util.js\":\n/*!*********************!*\\\n  !*** ./lib/util.js ***!\n  \\*********************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"module.exports.pick = function (obj) {\\n  for (var _len = arguments.length, attr = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\\n    attr[_key - 1] = arguments[_key];\\n  }\\n\\n  return attr.reduce(function (acc, k) {\\n    acc[k] = obj[k];\\n    return acc;\\n  }, {});\\n};\\n\\n//# sourceURL=webpack://eio/./lib/util.js?\");\n\n/***/ }),\n\n/***/ \"./lib/xmlhttprequest.js\":\n/*!*******************************!*\\\n  !*** ./lib/xmlhttprequest.js ***!\n  \\*******************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"// browser shim for xmlhttprequest module\\nvar hasCORS = __webpack_require__(/*! has-cors */ \\\"./node_modules/has-cors/index.js\\\");\\n\\nvar globalThis = __webpack_require__(/*! ./globalThis */ \\\"./lib/globalThis.browser.js\\\");\\n\\nmodule.exports = function (opts) {\\n  var xdomain = opts.xdomain; // scheme must be same when usign XDomainRequest\\n  // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx\\n\\n  var xscheme = opts.xscheme; // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.\\n  // https://github.com/Automattic/engine.io-client/pull/217\\n\\n  var enablesXDR = opts.enablesXDR; // XMLHttpRequest can be disabled on IE\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {\\n      return new XMLHttpRequest();\\n    }\\n  } catch (e) {} // Use XDomainRequest for IE8 if enablesXDR is true\\n  // because loading bar keeps flashing when using jsonp-polling\\n  // https://github.com/yujiosaka/socke.io-ie8-loading-example\\n\\n\\n  try {\\n    if (\\\"undefined\\\" !== typeof XDomainRequest && !xscheme && enablesXDR) {\\n      return new XDomainRequest();\\n    }\\n  } catch (e) {}\\n\\n  if (!xdomain) {\\n    try {\\n      return new globalThis[[\\\"Active\\\"].concat(\\\"Object\\\").join(\\\"X\\\")](\\\"Microsoft.XMLHTTP\\\");\\n    } catch (e) {}\\n  }\\n};\\n\\n//# sourceURL=webpack://eio/./lib/xmlhttprequest.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/*\\n * base64-arraybuffer\\n * https://github.com/niklasvh/base64-arraybuffer\\n *\\n * Copyright (c) 2012 Niklas von Hertzen\\n * Licensed under the MIT license.\\n */\\n(function (chars) {\\n  \\\"use strict\\\";\\n\\n  exports.encode = function (arraybuffer) {\\n    var bytes = new Uint8Array(arraybuffer),\\n        i,\\n        len = bytes.length,\\n        base64 = \\\"\\\";\\n\\n    for (i = 0; i < len; i += 3) {\\n      base64 += chars[bytes[i] >> 2];\\n      base64 += chars[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];\\n      base64 += chars[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];\\n      base64 += chars[bytes[i + 2] & 63];\\n    }\\n\\n    if (len % 3 === 2) {\\n      base64 = base64.substring(0, base64.length - 1) + \\\"=\\\";\\n    } else if (len % 3 === 1) {\\n      base64 = base64.substring(0, base64.length - 2) + \\\"==\\\";\\n    }\\n\\n    return base64;\\n  };\\n\\n  exports.decode = function (base64) {\\n    var bufferLength = base64.length * 0.75,\\n        len = base64.length,\\n        i,\\n        p = 0,\\n        encoded1,\\n        encoded2,\\n        encoded3,\\n        encoded4;\\n\\n    if (base64[base64.length - 1] === \\\"=\\\") {\\n      bufferLength--;\\n\\n      if (base64[base64.length - 2] === \\\"=\\\") {\\n        bufferLength--;\\n      }\\n    }\\n\\n    var arraybuffer = new ArrayBuffer(bufferLength),\\n        bytes = new Uint8Array(arraybuffer);\\n\\n    for (i = 0; i < len; i += 4) {\\n      encoded1 = chars.indexOf(base64[i]);\\n      encoded2 = chars.indexOf(base64[i + 1]);\\n      encoded3 = chars.indexOf(base64[i + 2]);\\n      encoded4 = chars.indexOf(base64[i + 3]);\\n      bytes[p++] = encoded1 << 2 | encoded2 >> 4;\\n      bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;\\n      bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;\\n    }\\n\\n    return arraybuffer;\\n  };\\n})(\\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\");\\n\\n//# sourceURL=webpack://eio/./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/component-emitter/index.js\":\n/*!*************************************************!*\\\n  !*** ./node_modules/component-emitter/index.js ***!\n  \\*************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/**\\r\\n * Expose `Emitter`.\\r\\n */\\nif (true) {\\n  module.exports = Emitter;\\n}\\n/**\\r\\n * Initialize a new `Emitter`.\\r\\n *\\r\\n * @api public\\r\\n */\\n\\n\\nfunction Emitter(obj) {\\n  if (obj) return mixin(obj);\\n}\\n\\n;\\n/**\\r\\n * Mixin the emitter properties.\\r\\n *\\r\\n * @param {Object} obj\\r\\n * @return {Object}\\r\\n * @api private\\r\\n */\\n\\nfunction mixin(obj) {\\n  for (var key in Emitter.prototype) {\\n    obj[key] = Emitter.prototype[key];\\n  }\\n\\n  return obj;\\n}\\n/**\\r\\n * Listen on the given `event` with `fn`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {};\\n  (this._callbacks['$' + event] = this._callbacks['$' + event] || []).push(fn);\\n  return this;\\n};\\n/**\\r\\n * Adds an `event` listener that will be invoked a single\\r\\n * time then automatically removed.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.once = function (event, fn) {\\n  function on() {\\n    this.off(event, on);\\n    fn.apply(this, arguments);\\n  }\\n\\n  on.fn = fn;\\n  this.on(event, on);\\n  return this;\\n};\\n/**\\r\\n * Remove the given callback for `event` or all\\r\\n * registered callbacks.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Function} fn\\r\\n * @return {Emitter}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) {\\n  this._callbacks = this._callbacks || {}; // all\\n\\n  if (0 == arguments.length) {\\n    this._callbacks = {};\\n    return this;\\n  } // specific event\\n\\n\\n  var callbacks = this._callbacks['$' + event];\\n  if (!callbacks) return this; // remove all handlers\\n\\n  if (1 == arguments.length) {\\n    delete this._callbacks['$' + event];\\n    return this;\\n  } // remove specific handler\\n\\n\\n  var cb;\\n\\n  for (var i = 0; i < callbacks.length; i++) {\\n    cb = callbacks[i];\\n\\n    if (cb === fn || cb.fn === fn) {\\n      callbacks.splice(i, 1);\\n      break;\\n    }\\n  } // Remove event specific arrays for event types that no\\n  // one is subscribed for to avoid memory leak.\\n\\n\\n  if (callbacks.length === 0) {\\n    delete this._callbacks['$' + event];\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Emit `event` with the given args.\\r\\n *\\r\\n * @param {String} event\\r\\n * @param {Mixed} ...\\r\\n * @return {Emitter}\\r\\n */\\n\\n\\nEmitter.prototype.emit = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  var args = new Array(arguments.length - 1),\\n      callbacks = this._callbacks['$' + event];\\n\\n  for (var i = 1; i < arguments.length; i++) {\\n    args[i - 1] = arguments[i];\\n  }\\n\\n  if (callbacks) {\\n    callbacks = callbacks.slice(0);\\n\\n    for (var i = 0, len = callbacks.length; i < len; ++i) {\\n      callbacks[i].apply(this, args);\\n    }\\n  }\\n\\n  return this;\\n};\\n/**\\r\\n * Return array of callbacks for `event`.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Array}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.listeners = function (event) {\\n  this._callbacks = this._callbacks || {};\\n  return this._callbacks['$' + event] || [];\\n};\\n/**\\r\\n * Check if this emitter has `event` handlers.\\r\\n *\\r\\n * @param {String} event\\r\\n * @return {Boolean}\\r\\n * @api public\\r\\n */\\n\\n\\nEmitter.prototype.hasListeners = function (event) {\\n  return !!this.listeners(event).length;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/component-emitter/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/browser.js\":\n/*!*******************************************!*\\\n  !*** ./node_modules/debug/src/browser.js ***!\n  \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"/* WEBPACK VAR INJECTION */(function(process) {function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/* eslint-env browser */\\n\\n/**\\n * This is the web browser implementation of `debug()`.\\n */\\nexports.log = log;\\nexports.formatArgs = formatArgs;\\nexports.save = save;\\nexports.load = load;\\nexports.useColors = useColors;\\nexports.storage = localstorage();\\n/**\\n * Colors.\\n */\\n\\nexports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];\\n/**\\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\\n * and the Firebug extension (any Firefox version) are known\\n * to support \\\"%c\\\" CSS customizations.\\n *\\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\\n */\\n// eslint-disable-next-line complexity\\n\\nfunction useColors() {\\n  // NB: In an Electron preload script, document will be defined but not fully\\n  // initialized. Since we know we're in Chrome, we'll just detect this case\\n  // explicitly\\n  if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {\\n    return true;\\n  } // Internet Explorer and Edge do not support colors.\\n\\n\\n  if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\\\\/(\\\\d+)/)) {\\n    return false;\\n  } // Is webkit? http://stackoverflow.com/a/16459606/376773\\n  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\\n\\n\\n  return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773\\n  typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?\\n  // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\\\\/(\\\\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker\\n  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\\\/(\\\\d+)/);\\n}\\n/**\\n * Colorize log arguments if enabled.\\n *\\n * @api public\\n */\\n\\n\\nfunction formatArgs(args) {\\n  args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);\\n\\n  if (!this.useColors) {\\n    return;\\n  }\\n\\n  var c = 'color: ' + this.color;\\n  args.splice(1, 0, c, 'color: inherit'); // The final \\\"%c\\\" is somewhat tricky, because there could be other\\n  // arguments passed either before or after the %c, so we need to\\n  // figure out the correct index to insert the CSS into\\n\\n  var index = 0;\\n  var lastC = 0;\\n  args[0].replace(/%[a-zA-Z%]/g, function (match) {\\n    if (match === '%%') {\\n      return;\\n    }\\n\\n    index++;\\n\\n    if (match === '%c') {\\n      // We only are interested in the *last* %c\\n      // (the user may have provided their own)\\n      lastC = index;\\n    }\\n  });\\n  args.splice(lastC, 0, c);\\n}\\n/**\\n * Invokes `console.log()` when available.\\n * No-op when `console.log` is not a \\\"function\\\".\\n *\\n * @api public\\n */\\n\\n\\nfunction log() {\\n  var _console;\\n\\n  // This hackery is required for IE8/9, where\\n  // the `console.log` function doesn't have 'apply'\\n  return (typeof console === \\\"undefined\\\" ? \\\"undefined\\\" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments);\\n}\\n/**\\n * Save `namespaces`.\\n *\\n * @param {String} namespaces\\n * @api private\\n */\\n\\n\\nfunction save(namespaces) {\\n  try {\\n    if (namespaces) {\\n      exports.storage.setItem('debug', namespaces);\\n    } else {\\n      exports.storage.removeItem('debug');\\n    }\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n/**\\n * Load `namespaces`.\\n *\\n * @return {String} returns the previously persisted debug modes\\n * @api private\\n */\\n\\n\\nfunction load() {\\n  var r;\\n\\n  try {\\n    r = exports.storage.getItem('debug');\\n  } catch (error) {} // Swallow\\n  // XXX (@Qix-) should we be logging these?\\n  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\\n\\n\\n  if (!r && typeof process !== 'undefined' && 'env' in process) {\\n    r = process.env.DEBUG;\\n  }\\n\\n  return r;\\n}\\n/**\\n * Localstorage attempts to return the localstorage.\\n *\\n * This is necessary because safari throws\\n * when a user disables cookies/localstorage\\n * and you attempt to access it.\\n *\\n * @return {LocalStorage}\\n * @api private\\n */\\n\\n\\nfunction localstorage() {\\n  try {\\n    // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\\n    // The Browser also has localStorage in the global context.\\n    return localStorage;\\n  } catch (error) {// Swallow\\n    // XXX (@Qix-) should we be logging these?\\n  }\\n}\\n\\nmodule.exports = __webpack_require__(/*! ./common */ \\\"./node_modules/debug/src/common.js\\\")(exports);\\nvar formatters = module.exports.formatters;\\n/**\\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\\n */\\n\\nformatters.j = function (v) {\\n  try {\\n    return JSON.stringify(v);\\n  } catch (error) {\\n    return '[UnexpectedJSONParseError]: ' + error.message;\\n  }\\n};\\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../process/browser.js */ \\\"./node_modules/process/browser.js\\\")))\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/debug/src/common.js\":\n/*!******************************************!*\\\n  !*** ./node_modules/debug/src/common.js ***!\n  \\******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\\n\\nfunction _nonIterableSpread() { throw new TypeError(\\\"Invalid attempt to spread non-iterable instance\\\"); }\\n\\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \\\"[object Arguments]\\\") return Array.from(iter); }\\n\\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\\n\\n/**\\n * This is the common logic for both the Node.js and web browser\\n * implementations of `debug()`.\\n */\\nfunction setup(env) {\\n  createDebug.debug = createDebug;\\n  createDebug[\\\"default\\\"] = createDebug;\\n  createDebug.coerce = coerce;\\n  createDebug.disable = disable;\\n  createDebug.enable = enable;\\n  createDebug.enabled = enabled;\\n  createDebug.humanize = __webpack_require__(/*! ms */ \\\"./node_modules/ms/index.js\\\");\\n  Object.keys(env).forEach(function (key) {\\n    createDebug[key] = env[key];\\n  });\\n  /**\\n  * Active `debug` instances.\\n  */\\n\\n  createDebug.instances = [];\\n  /**\\n  * The currently active debug mode names, and names to skip.\\n  */\\n\\n  createDebug.names = [];\\n  createDebug.skips = [];\\n  /**\\n  * Map of special \\\"%n\\\" handling functions, for the debug \\\"format\\\" argument.\\n  *\\n  * Valid key names are a single, lower or upper-case letter, i.e. \\\"n\\\" and \\\"N\\\".\\n  */\\n\\n  createDebug.formatters = {};\\n  /**\\n  * Selects a color for a debug namespace\\n  * @param {String} namespace The namespace string for the for the debug instance to be colored\\n  * @return {Number|String} An ANSI color code for the given namespace\\n  * @api private\\n  */\\n\\n  function selectColor(namespace) {\\n    var hash = 0;\\n\\n    for (var i = 0; i < namespace.length; i++) {\\n      hash = (hash << 5) - hash + namespace.charCodeAt(i);\\n      hash |= 0; // Convert to 32bit integer\\n    }\\n\\n    return createDebug.colors[Math.abs(hash) % createDebug.colors.length];\\n  }\\n\\n  createDebug.selectColor = selectColor;\\n  /**\\n  * Create a debugger with the given `namespace`.\\n  *\\n  * @param {String} namespace\\n  * @return {Function}\\n  * @api public\\n  */\\n\\n  function createDebug(namespace) {\\n    var prevTime;\\n\\n    function debug() {\\n      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\\n        args[_key] = arguments[_key];\\n      }\\n\\n      // Disabled?\\n      if (!debug.enabled) {\\n        return;\\n      }\\n\\n      var self = debug; // Set `diff` timestamp\\n\\n      var curr = Number(new Date());\\n      var ms = curr - (prevTime || curr);\\n      self.diff = ms;\\n      self.prev = prevTime;\\n      self.curr = curr;\\n      prevTime = curr;\\n      args[0] = createDebug.coerce(args[0]);\\n\\n      if (typeof args[0] !== 'string') {\\n        // Anything else let's inspect with %O\\n        args.unshift('%O');\\n      } // Apply any `formatters` transformations\\n\\n\\n      var index = 0;\\n      args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {\\n        // If we encounter an escaped % then don't increase the array index\\n        if (match === '%%') {\\n          return match;\\n        }\\n\\n        index++;\\n        var formatter = createDebug.formatters[format];\\n\\n        if (typeof formatter === 'function') {\\n          var val = args[index];\\n          match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`\\n\\n          args.splice(index, 1);\\n          index--;\\n        }\\n\\n        return match;\\n      }); // Apply env-specific formatting (colors, etc.)\\n\\n      createDebug.formatArgs.call(self, args);\\n      var logFn = self.log || createDebug.log;\\n      logFn.apply(self, args);\\n    }\\n\\n    debug.namespace = namespace;\\n    debug.enabled = createDebug.enabled(namespace);\\n    debug.useColors = createDebug.useColors();\\n    debug.color = selectColor(namespace);\\n    debug.destroy = destroy;\\n    debug.extend = extend; // Debug.formatArgs = formatArgs;\\n    // debug.rawLog = rawLog;\\n    // env-specific initialization logic for debug instances\\n\\n    if (typeof createDebug.init === 'function') {\\n      createDebug.init(debug);\\n    }\\n\\n    createDebug.instances.push(debug);\\n    return debug;\\n  }\\n\\n  function destroy() {\\n    var index = createDebug.instances.indexOf(this);\\n\\n    if (index !== -1) {\\n      createDebug.instances.splice(index, 1);\\n      return true;\\n    }\\n\\n    return false;\\n  }\\n\\n  function extend(namespace, delimiter) {\\n    var newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);\\n    newDebug.log = this.log;\\n    return newDebug;\\n  }\\n  /**\\n  * Enables a debug mode by namespaces. This can include modes\\n  * separated by a colon and wildcards.\\n  *\\n  * @param {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function enable(namespaces) {\\n    createDebug.save(namespaces);\\n    createDebug.names = [];\\n    createDebug.skips = [];\\n    var i;\\n    var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\\\\s,]+/);\\n    var len = split.length;\\n\\n    for (i = 0; i < len; i++) {\\n      if (!split[i]) {\\n        // ignore empty strings\\n        continue;\\n      }\\n\\n      namespaces = split[i].replace(/\\\\*/g, '.*?');\\n\\n      if (namespaces[0] === '-') {\\n        createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));\\n      } else {\\n        createDebug.names.push(new RegExp('^' + namespaces + '$'));\\n      }\\n    }\\n\\n    for (i = 0; i < createDebug.instances.length; i++) {\\n      var instance = createDebug.instances[i];\\n      instance.enabled = createDebug.enabled(instance.namespace);\\n    }\\n  }\\n  /**\\n  * Disable debug output.\\n  *\\n  * @return {String} namespaces\\n  * @api public\\n  */\\n\\n\\n  function disable() {\\n    var namespaces = [].concat(_toConsumableArray(createDebug.names.map(toNamespace)), _toConsumableArray(createDebug.skips.map(toNamespace).map(function (namespace) {\\n      return '-' + namespace;\\n    }))).join(',');\\n    createDebug.enable('');\\n    return namespaces;\\n  }\\n  /**\\n  * Returns true if the given mode name is enabled, false otherwise.\\n  *\\n  * @param {String} name\\n  * @return {Boolean}\\n  * @api public\\n  */\\n\\n\\n  function enabled(name) {\\n    if (name[name.length - 1] === '*') {\\n      return true;\\n    }\\n\\n    var i;\\n    var len;\\n\\n    for (i = 0, len = createDebug.skips.length; i < len; i++) {\\n      if (createDebug.skips[i].test(name)) {\\n        return false;\\n      }\\n    }\\n\\n    for (i = 0, len = createDebug.names.length; i < len; i++) {\\n      if (createDebug.names[i].test(name)) {\\n        return true;\\n      }\\n    }\\n\\n    return false;\\n  }\\n  /**\\n  * Convert regexp to namespace\\n  *\\n  * @param {RegExp} regxep\\n  * @return {String} namespace\\n  * @api private\\n  */\\n\\n\\n  function toNamespace(regexp) {\\n    return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\\\\.\\\\*\\\\?$/, '*');\\n  }\\n  /**\\n  * Coerce `val`.\\n  *\\n  * @param {Mixed} val\\n  * @return {Mixed}\\n  * @api private\\n  */\\n\\n\\n  function coerce(val) {\\n    if (val instanceof Error) {\\n      return val.stack || val.message;\\n    }\\n\\n    return val;\\n  }\\n\\n  createDebug.enable(createDebug.load());\\n  return createDebug;\\n}\\n\\nmodule.exports = setup;\\n\\n//# sourceURL=webpack://eio/./node_modules/debug/src/common.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/commons.js\":\n/*!******************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/commons.js ***!\n  \\******************************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"var PACKET_TYPES = Object.create(null); // no Map = no polyfill\\n\\nPACKET_TYPES[\\\"open\\\"] = \\\"0\\\";\\nPACKET_TYPES[\\\"close\\\"] = \\\"1\\\";\\nPACKET_TYPES[\\\"ping\\\"] = \\\"2\\\";\\nPACKET_TYPES[\\\"pong\\\"] = \\\"3\\\";\\nPACKET_TYPES[\\\"message\\\"] = \\\"4\\\";\\nPACKET_TYPES[\\\"upgrade\\\"] = \\\"5\\\";\\nPACKET_TYPES[\\\"noop\\\"] = \\\"6\\\";\\nvar PACKET_TYPES_REVERSE = Object.create(null);\\nObject.keys(PACKET_TYPES).forEach(function (key) {\\n  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;\\n});\\nvar ERROR_PACKET = {\\n  type: \\\"error\\\",\\n  data: \\\"parser error\\\"\\n};\\nmodule.exports = {\\n  PACKET_TYPES: PACKET_TYPES,\\n  PACKET_TYPES_REVERSE: PACKET_TYPES_REVERSE,\\n  ERROR_PACKET: ERROR_PACKET\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/commons.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/decodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/decodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES_REVERSE = _require.PACKET_TYPES_REVERSE,\\n    ERROR_PACKET = _require.ERROR_PACKET;\\n\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\";\\nvar base64decoder;\\n\\nif (withNativeArrayBuffer) {\\n  base64decoder = __webpack_require__(/*! base64-arraybuffer */ \\\"./node_modules/base64-arraybuffer/lib/base64-arraybuffer.js\\\");\\n}\\n\\nvar decodePacket = function decodePacket(encodedPacket, binaryType) {\\n  if (typeof encodedPacket !== \\\"string\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: mapBinary(encodedPacket, binaryType)\\n    };\\n  }\\n\\n  var type = encodedPacket.charAt(0);\\n\\n  if (type === \\\"b\\\") {\\n    return {\\n      type: \\\"message\\\",\\n      data: decodeBase64Packet(encodedPacket.substring(1), binaryType)\\n    };\\n  }\\n\\n  var packetType = PACKET_TYPES_REVERSE[type];\\n\\n  if (!packetType) {\\n    return ERROR_PACKET;\\n  }\\n\\n  return encodedPacket.length > 1 ? {\\n    type: PACKET_TYPES_REVERSE[type],\\n    data: encodedPacket.substring(1)\\n  } : {\\n    type: PACKET_TYPES_REVERSE[type]\\n  };\\n};\\n\\nvar decodeBase64Packet = function decodeBase64Packet(data, binaryType) {\\n  if (base64decoder) {\\n    var decoded = base64decoder.decode(data);\\n    return mapBinary(decoded, binaryType);\\n  } else {\\n    return {\\n      base64: true,\\n      data: data\\n    }; // fallback for old browsers\\n  }\\n};\\n\\nvar mapBinary = function mapBinary(data, binaryType) {\\n  switch (binaryType) {\\n    case \\\"blob\\\":\\n      return data instanceof ArrayBuffer ? new Blob([data]) : data;\\n\\n    case \\\"arraybuffer\\\":\\n    default:\\n      return data;\\n    // assuming the data is already an ArrayBuffer\\n  }\\n};\\n\\nmodule.exports = decodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/decodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/encodePacket.browser.js\":\n/*!*******************************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/encodePacket.browser.js ***!\n  \\*******************************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var _require = __webpack_require__(/*! ./commons */ \\\"./node_modules/engine.io-parser/lib/commons.js\\\"),\\n    PACKET_TYPES = _require.PACKET_TYPES;\\n\\nvar withNativeBlob = typeof Blob === \\\"function\\\" || typeof Blob !== \\\"undefined\\\" && Object.prototype.toString.call(Blob) === \\\"[object BlobConstructor]\\\";\\nvar withNativeArrayBuffer = typeof ArrayBuffer === \\\"function\\\"; // ArrayBuffer.isView method is not defined in IE10\\n\\nvar isView = function isView(obj) {\\n  return typeof ArrayBuffer.isView === \\\"function\\\" ? ArrayBuffer.isView(obj) : obj && obj.buffer instanceof ArrayBuffer;\\n};\\n\\nvar encodePacket = function encodePacket(_ref, supportsBinary, callback) {\\n  var type = _ref.type,\\n      data = _ref.data;\\n\\n  if (withNativeBlob && data instanceof Blob) {\\n    if (supportsBinary) {\\n      return callback(data);\\n    } else {\\n      return encodeBlobAsBase64(data, callback);\\n    }\\n  } else if (withNativeArrayBuffer && (data instanceof ArrayBuffer || isView(data))) {\\n    if (supportsBinary) {\\n      return callback(data instanceof ArrayBuffer ? data : data.buffer);\\n    } else {\\n      return encodeBlobAsBase64(new Blob([data]), callback);\\n    }\\n  } // plain string\\n\\n\\n  return callback(PACKET_TYPES[type] + (data || \\\"\\\"));\\n};\\n\\nvar encodeBlobAsBase64 = function encodeBlobAsBase64(data, callback) {\\n  var fileReader = new FileReader();\\n\\n  fileReader.onload = function () {\\n    var content = fileReader.result.split(\\\",\\\")[1];\\n    callback(\\\"b\\\" + content);\\n  };\\n\\n  return fileReader.readAsDataURL(data);\\n};\\n\\nmodule.exports = encodePacket;\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/encodePacket.browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/engine.io-parser/lib/index.js\":\n/*!****************************************************!*\\\n  !*** ./node_modules/engine.io-parser/lib/index.js ***!\n  \\****************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\neval(\"var encodePacket = __webpack_require__(/*! ./encodePacket */ \\\"./node_modules/engine.io-parser/lib/encodePacket.browser.js\\\");\\n\\nvar decodePacket = __webpack_require__(/*! ./decodePacket */ \\\"./node_modules/engine.io-parser/lib/decodePacket.browser.js\\\");\\n\\nvar SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text\\n\\nvar encodePayload = function encodePayload(packets, callback) {\\n  // some packets may be added to the array while encoding, so the initial length must be saved\\n  var length = packets.length;\\n  var encodedPackets = new Array(length);\\n  var count = 0;\\n  packets.forEach(function (packet, i) {\\n    // force base64 encoding for binary packets\\n    encodePacket(packet, false, function (encodedPacket) {\\n      encodedPackets[i] = encodedPacket;\\n\\n      if (++count === length) {\\n        callback(encodedPackets.join(SEPARATOR));\\n      }\\n    });\\n  });\\n};\\n\\nvar decodePayload = function decodePayload(encodedPayload, binaryType) {\\n  var encodedPackets = encodedPayload.split(SEPARATOR);\\n  var packets = [];\\n\\n  for (var i = 0; i < encodedPackets.length; i++) {\\n    var decodedPacket = decodePacket(encodedPackets[i], binaryType);\\n    packets.push(decodedPacket);\\n\\n    if (decodedPacket.type === \\\"error\\\") {\\n      break;\\n    }\\n  }\\n\\n  return packets;\\n};\\n\\nmodule.exports = {\\n  protocol: 4,\\n  encodePacket: encodePacket,\\n  encodePayload: encodePayload,\\n  decodePacket: decodePacket,\\n  decodePayload: decodePayload\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/engine.io-parser/lib/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/has-cors/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/has-cors/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Module exports.\\n *\\n * Logic borrowed from Modernizr:\\n *\\n *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js\\n */\\ntry {\\n  module.exports = typeof XMLHttpRequest !== 'undefined' && 'withCredentials' in new XMLHttpRequest();\\n} catch (err) {\\n  // if XMLHttp support is disabled in IE then it will throw\\n  // when trying to create\\n  module.exports = false;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/has-cors/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/ms/index.js\":\n/*!**********************************!*\\\n  !*** ./node_modules/ms/index.js ***!\n  \\**********************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\n/**\\n * Helpers.\\n */\\nvar s = 1000;\\nvar m = s * 60;\\nvar h = m * 60;\\nvar d = h * 24;\\nvar w = d * 7;\\nvar y = d * 365.25;\\n/**\\n * Parse or format the given `val`.\\n *\\n * Options:\\n *\\n *  - `long` verbose formatting [false]\\n *\\n * @param {String|Number} val\\n * @param {Object} [options]\\n * @throws {Error} throw an error if val is not a non-empty string or a number\\n * @return {String|Number}\\n * @api public\\n */\\n\\nmodule.exports = function (val, options) {\\n  options = options || {};\\n\\n  var type = _typeof(val);\\n\\n  if (type === 'string' && val.length > 0) {\\n    return parse(val);\\n  } else if (type === 'number' && isFinite(val)) {\\n    return options[\\\"long\\\"] ? fmtLong(val) : fmtShort(val);\\n  }\\n\\n  throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val));\\n};\\n/**\\n * Parse the given `str` and return milliseconds.\\n *\\n * @param {String} str\\n * @return {Number}\\n * @api private\\n */\\n\\n\\nfunction parse(str) {\\n  str = String(str);\\n\\n  if (str.length > 100) {\\n    return;\\n  }\\n\\n  var match = /^(-?(?:\\\\d+)?\\\\.?\\\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);\\n\\n  if (!match) {\\n    return;\\n  }\\n\\n  var n = parseFloat(match[1]);\\n  var type = (match[2] || 'ms').toLowerCase();\\n\\n  switch (type) {\\n    case 'years':\\n    case 'year':\\n    case 'yrs':\\n    case 'yr':\\n    case 'y':\\n      return n * y;\\n\\n    case 'weeks':\\n    case 'week':\\n    case 'w':\\n      return n * w;\\n\\n    case 'days':\\n    case 'day':\\n    case 'd':\\n      return n * d;\\n\\n    case 'hours':\\n    case 'hour':\\n    case 'hrs':\\n    case 'hr':\\n    case 'h':\\n      return n * h;\\n\\n    case 'minutes':\\n    case 'minute':\\n    case 'mins':\\n    case 'min':\\n    case 'm':\\n      return n * m;\\n\\n    case 'seconds':\\n    case 'second':\\n    case 'secs':\\n    case 'sec':\\n    case 's':\\n      return n * s;\\n\\n    case 'milliseconds':\\n    case 'millisecond':\\n    case 'msecs':\\n    case 'msec':\\n    case 'ms':\\n      return n;\\n\\n    default:\\n      return undefined;\\n  }\\n}\\n/**\\n * Short format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtShort(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return Math.round(ms / d) + 'd';\\n  }\\n\\n  if (msAbs >= h) {\\n    return Math.round(ms / h) + 'h';\\n  }\\n\\n  if (msAbs >= m) {\\n    return Math.round(ms / m) + 'm';\\n  }\\n\\n  if (msAbs >= s) {\\n    return Math.round(ms / s) + 's';\\n  }\\n\\n  return ms + 'ms';\\n}\\n/**\\n * Long format for `ms`.\\n *\\n * @param {Number} ms\\n * @return {String}\\n * @api private\\n */\\n\\n\\nfunction fmtLong(ms) {\\n  var msAbs = Math.abs(ms);\\n\\n  if (msAbs >= d) {\\n    return plural(ms, msAbs, d, 'day');\\n  }\\n\\n  if (msAbs >= h) {\\n    return plural(ms, msAbs, h, 'hour');\\n  }\\n\\n  if (msAbs >= m) {\\n    return plural(ms, msAbs, m, 'minute');\\n  }\\n\\n  if (msAbs >= s) {\\n    return plural(ms, msAbs, s, 'second');\\n  }\\n\\n  return ms + ' ms';\\n}\\n/**\\n * Pluralization helper.\\n */\\n\\n\\nfunction plural(ms, msAbs, n, name) {\\n  var isPlural = msAbs >= n * 1.5;\\n  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/ms/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseqs/index.js\":\n/*!***************************************!*\\\n  !*** ./node_modules/parseqs/index.js ***!\n  \\***************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Compiles a querystring\\n * Returns string representation of the object\\n *\\n * @param {Object}\\n * @api private\\n */\\nexports.encode = function (obj) {\\n  var str = '';\\n\\n  for (var i in obj) {\\n    if (obj.hasOwnProperty(i)) {\\n      if (str.length) str += '&';\\n      str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);\\n    }\\n  }\\n\\n  return str;\\n};\\n/**\\n * Parses a simple querystring into an object\\n *\\n * @param {String} qs\\n * @api private\\n */\\n\\n\\nexports.decode = function (qs) {\\n  var qry = {};\\n  var pairs = qs.split('&');\\n\\n  for (var i = 0, l = pairs.length; i < l; i++) {\\n    var pair = pairs[i].split('=');\\n    qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);\\n  }\\n\\n  return qry;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/parseqs/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/parseuri/index.js\":\n/*!****************************************!*\\\n  !*** ./node_modules/parseuri/index.js ***!\n  \\****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"/**\\n * Parses an URI\\n *\\n * @author Steven Levithan <stevenlevithan.com> (MIT license)\\n * @api private\\n */\\nvar re = /^(?:(?![^:@]+:[^:@\\\\/]*@)(http|https|ws|wss):\\\\/\\\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\\\/?#]*)(?::(\\\\d*))?)(((\\\\/(?:[^?#](?![^?#\\\\/]*\\\\.[^?#\\\\/.]+(?:[?#]|$)))*\\\\/?)?([^?#\\\\/]*))(?:\\\\?([^#]*))?(?:#(.*))?)/;\\nvar parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'];\\n\\nmodule.exports = function parseuri(str) {\\n  var src = str,\\n      b = str.indexOf('['),\\n      e = str.indexOf(']');\\n\\n  if (b != -1 && e != -1) {\\n    str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);\\n  }\\n\\n  var m = re.exec(str || ''),\\n      uri = {},\\n      i = 14;\\n\\n  while (i--) {\\n    uri[parts[i]] = m[i] || '';\\n  }\\n\\n  if (b != -1 && e != -1) {\\n    uri.source = src;\\n    uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');\\n    uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');\\n    uri.ipv6uri = true;\\n  }\\n\\n  uri.pathNames = pathNames(uri, uri['path']);\\n  uri.queryKey = queryKey(uri, uri['query']);\\n  return uri;\\n};\\n\\nfunction pathNames(obj, path) {\\n  var regx = /\\\\/{2,9}/g,\\n      names = path.replace(regx, \\\"/\\\").split(\\\"/\\\");\\n\\n  if (path.substr(0, 1) == '/' || path.length === 0) {\\n    names.splice(0, 1);\\n  }\\n\\n  if (path.substr(path.length - 1, 1) == '/') {\\n    names.splice(names.length - 1, 1);\\n  }\\n\\n  return names;\\n}\\n\\nfunction queryKey(uri, query) {\\n  var data = {};\\n  query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {\\n    if ($1) {\\n      data[$1] = $2;\\n    }\\n  });\\n  return data;\\n}\\n\\n//# sourceURL=webpack://eio/./node_modules/parseuri/index.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/process/browser.js\":\n/*!*****************************************!*\\\n  !*** ./node_modules/process/browser.js ***!\n  \\*****************************************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"// shim for using process in browser\\nvar process = module.exports = {}; // cached from whatever global is present so that test runners that stub it\\n// don't break things.  But we need to wrap it in a try catch in case it is\\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\\n// function because try/catches deoptimize in certain engines.\\n\\nvar cachedSetTimeout;\\nvar cachedClearTimeout;\\n\\nfunction defaultSetTimout() {\\n  throw new Error('setTimeout has not been defined');\\n}\\n\\nfunction defaultClearTimeout() {\\n  throw new Error('clearTimeout has not been defined');\\n}\\n\\n(function () {\\n  try {\\n    if (typeof setTimeout === 'function') {\\n      cachedSetTimeout = setTimeout;\\n    } else {\\n      cachedSetTimeout = defaultSetTimout;\\n    }\\n  } catch (e) {\\n    cachedSetTimeout = defaultSetTimout;\\n  }\\n\\n  try {\\n    if (typeof clearTimeout === 'function') {\\n      cachedClearTimeout = clearTimeout;\\n    } else {\\n      cachedClearTimeout = defaultClearTimeout;\\n    }\\n  } catch (e) {\\n    cachedClearTimeout = defaultClearTimeout;\\n  }\\n})();\\n\\nfunction runTimeout(fun) {\\n  if (cachedSetTimeout === setTimeout) {\\n    //normal enviroments in sane situations\\n    return setTimeout(fun, 0);\\n  } // if setTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\\n    cachedSetTimeout = setTimeout;\\n    return setTimeout(fun, 0);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedSetTimeout(fun, 0);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\\n      return cachedSetTimeout.call(null, fun, 0);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\\n      return cachedSetTimeout.call(this, fun, 0);\\n    }\\n  }\\n}\\n\\nfunction runClearTimeout(marker) {\\n  if (cachedClearTimeout === clearTimeout) {\\n    //normal enviroments in sane situations\\n    return clearTimeout(marker);\\n  } // if clearTimeout wasn't available but was latter defined\\n\\n\\n  if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\\n    cachedClearTimeout = clearTimeout;\\n    return clearTimeout(marker);\\n  }\\n\\n  try {\\n    // when when somebody has screwed with setTimeout but no I.E. maddness\\n    return cachedClearTimeout(marker);\\n  } catch (e) {\\n    try {\\n      // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\\n      return cachedClearTimeout.call(null, marker);\\n    } catch (e) {\\n      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\\n      // Some versions of I.E. have different rules for clearTimeout vs setTimeout\\n      return cachedClearTimeout.call(this, marker);\\n    }\\n  }\\n}\\n\\nvar queue = [];\\nvar draining = false;\\nvar currentQueue;\\nvar queueIndex = -1;\\n\\nfunction cleanUpNextTick() {\\n  if (!draining || !currentQueue) {\\n    return;\\n  }\\n\\n  draining = false;\\n\\n  if (currentQueue.length) {\\n    queue = currentQueue.concat(queue);\\n  } else {\\n    queueIndex = -1;\\n  }\\n\\n  if (queue.length) {\\n    drainQueue();\\n  }\\n}\\n\\nfunction drainQueue() {\\n  if (draining) {\\n    return;\\n  }\\n\\n  var timeout = runTimeout(cleanUpNextTick);\\n  draining = true;\\n  var len = queue.length;\\n\\n  while (len) {\\n    currentQueue = queue;\\n    queue = [];\\n\\n    while (++queueIndex < len) {\\n      if (currentQueue) {\\n        currentQueue[queueIndex].run();\\n      }\\n    }\\n\\n    queueIndex = -1;\\n    len = queue.length;\\n  }\\n\\n  currentQueue = null;\\n  draining = false;\\n  runClearTimeout(timeout);\\n}\\n\\nprocess.nextTick = function (fun) {\\n  var args = new Array(arguments.length - 1);\\n\\n  if (arguments.length > 1) {\\n    for (var i = 1; i < arguments.length; i++) {\\n      args[i - 1] = arguments[i];\\n    }\\n  }\\n\\n  queue.push(new Item(fun, args));\\n\\n  if (queue.length === 1 && !draining) {\\n    runTimeout(drainQueue);\\n  }\\n}; // v8 likes predictible objects\\n\\n\\nfunction Item(fun, array) {\\n  this.fun = fun;\\n  this.array = array;\\n}\\n\\nItem.prototype.run = function () {\\n  this.fun.apply(null, this.array);\\n};\\n\\nprocess.title = 'browser';\\nprocess.browser = true;\\nprocess.env = {};\\nprocess.argv = [];\\nprocess.version = ''; // empty string to avoid regexp issues\\n\\nprocess.versions = {};\\n\\nfunction noop() {}\\n\\nprocess.on = noop;\\nprocess.addListener = noop;\\nprocess.once = noop;\\nprocess.off = noop;\\nprocess.removeListener = noop;\\nprocess.removeAllListeners = noop;\\nprocess.emit = noop;\\nprocess.prependListener = noop;\\nprocess.prependOnceListener = noop;\\n\\nprocess.listeners = function (name) {\\n  return [];\\n};\\n\\nprocess.binding = function (name) {\\n  throw new Error('process.binding is not supported');\\n};\\n\\nprocess.cwd = function () {\\n  return '/';\\n};\\n\\nprocess.chdir = function (dir) {\\n  throw new Error('process.chdir is not supported');\\n};\\n\\nprocess.umask = function () {\\n  return 0;\\n};\\n\\n//# sourceURL=webpack://eio/./node_modules/process/browser.js?\");\n\n/***/ }),\n\n/***/ \"./node_modules/yeast/index.js\":\n/*!*************************************!*\\\n  !*** ./node_modules/yeast/index.js ***!\n  \\*************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\neval(\"\\n\\nvar alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''),\\n    length = 64,\\n    map = {},\\n    seed = 0,\\n    i = 0,\\n    prev;\\n/**\\n * Return a string representing the specified number.\\n *\\n * @param {Number} num The number to convert.\\n * @returns {String} The string representation of the number.\\n * @api public\\n */\\n\\nfunction encode(num) {\\n  var encoded = '';\\n\\n  do {\\n    encoded = alphabet[num % length] + encoded;\\n    num = Math.floor(num / length);\\n  } while (num > 0);\\n\\n  return encoded;\\n}\\n/**\\n * Return the integer value specified by the given string.\\n *\\n * @param {String} str The string to convert.\\n * @returns {Number} The integer value represented by the string.\\n * @api public\\n */\\n\\n\\nfunction decode(str) {\\n  var decoded = 0;\\n\\n  for (i = 0; i < str.length; i++) {\\n    decoded = decoded * length + map[str.charAt(i)];\\n  }\\n\\n  return decoded;\\n}\\n/**\\n * Yeast: A tiny growing id generator.\\n *\\n * @returns {String} A unique id.\\n * @api public\\n */\\n\\n\\nfunction yeast() {\\n  var now = encode(+new Date());\\n  if (now !== prev) return seed = 0, prev = now;\\n  return now + '.' + encode(seed++);\\n} //\\n// Map each character to its index.\\n//\\n\\n\\nfor (; i < length; i++) {\\n  map[alphabet[i]] = i;\\n} //\\n// Expose the `yeast`, `encode` and `decode` functions.\\n//\\n\\n\\nyeast.encode = encode;\\nyeast.decode = decode;\\nmodule.exports = yeast;\\n\\n//# sourceURL=webpack://eio/./node_modules/yeast/index.js?\");\n\n/***/ })\n\n/******/ });\n});"
  },
  {
    "path": "examples/server/wsgi/static/style.css",
    "content": "body { margin: 0; padding: 0; font-family: Helvetica Neue; }\nh1 { margin: 100px 100px 10px; }\nh2 { color: #999; margin: 0 100px 30px; font-weight: normal; }\n#latency { color: red; }\n"
  },
  {
    "path": "examples/server/wsgi/templates/latency.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>EIO Latency</title>\n    <link rel=\"stylesheet\" href=\"{{ url_for('static', filename='style.css') }}\" />\n  </head>\n  <body>\n    <h1>EIO Latency <span id=\"latency\"></span></h1>\n    <h2 id=\"transport\">(connecting)</h2>\n    <canvas id=\"chart\" height=\"200\"></canvas>\n\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/smoothie/1.27.0/smoothie.js\"></script>\n    <script src=\"{{ url_for('static', filename='engine.io.js') }}\"></script>\n    <script>\n      // socket\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      var char = $('chart').get(0);\n      socket.on('open', function() {\n          if (chart.getContext) {\n              render();\n              window.onresize = render;\n          }\n          send();\n      });\n      socket.on('message', function(data) {\n          var latency = new Date - last;\n          $('#latency').text(latency + 'ms');\n          if (time)\n              time.append(+new Date, latency);\n          setTimeout(send, 100);\n      });\n      socket.on('close', function() {\n          if (smoothie)\n              smoothie.stop();\n          $('#transport').text('(disconnected)');\n      });\n\n      var last;\n      function send() {\n          last = new Date;\n          socket.send('ping');\n          $('#transport').text(socket.transport.name);\n      }\n\n      // chart\n      var smoothie;\n      var time;\n      function render() {\n          if (smoothie)\n              smoothie.stop();\n          chart.width = document.body.clientWidth;\n          smoothie = new SmoothieChart();\n          smoothie.streamTo(chart, 1000);\n          time = new TimeSeries();\n          smoothie.addTimeSeries(time, {\n              strokeStyle: 'rgb(255, 0, 0)',\n              fillStyle: 'rgba(255, 0, 0, 0.4)',\n              lineWidth: 2\n          });\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/server/wsgi/templates/simple.html",
    "content": "<html>\n<head>\n<script src=\"{{ url_for('static', filename='engine.io.js') }}\"></script>\n<script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js\"></script>\n<script>\n  $(document).ready(function() {\n      var socket = eio('http://' + document.domain + ':' + location.port);\n      socket.on('open', function() {\n          $('#log').append(\"Connected to server.<br>\");\n      });\n      socket.on('message', function(data) {\n          $('#log').append(\"Server says: \" + data + \"<br>\");\n      });\n      socket.on('close', function() {\n          $('#log').append(\"Server closed the connection.<br>\");\n      });\n      window.setInterval(function() {\n          $('#log').append(\"Sending message to server...<br>\");\n          socket.send('hello from client side!');\n      }, 5000);\n  });\n</script>\n</head>\n<body>\n<h1>python-engineio example application</h1>\n<p id=\"log\"></p>\n</body>\n</html>\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[project]\nname = \"python-engineio\"\nversion = \"4.13.2.dev0\"\nlicense = {text = \"MIT\"}\nauthors = [{name = \"Miguel Grinberg\", email = \"miguel.grinberg@gmail.com\"}]\ndescription = \"Engine.IO server and client for Python\"\nclassifiers = [\n    \"Environment :: Web Environment\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python :: 3\",\n    \"Operating System :: OS Independent\",\n]\nrequires-python = \">=3.8\"\ndependencies = [\"simple-websocket >= 0.10.0\"]\n\n[project.readme]\nfile = \"README.md\"\ncontent-type = \"text/markdown\"\n\n[project.urls]\nHomepage = \"https://github.com/miguelgrinberg/python-engineio\"\n\"Bug Tracker\" = \"https://github.com/miguelgrinberg/python-engineio/issues\"\n\n[project.optional-dependencies]\nclient = [\n    \"requests >= 2.21.0\",\n    \"websocket-client >= 0.54.0\",\n]\nasyncio_client = [\n    \"aiohttp >= 3.11\"\n]\ndev = [\n    \"tox\",\n]\ndocs = [\n    \"sphinx\",\n    \"furo\",\n]\n\n[tool.setuptools]\nzip-safe = false\ninclude-package-data = true\npackage-dir = {\"\" = \"src\"}\n\n[tool.setuptools.packages.find]\nwhere = [\"src\"]\nnamespaces = false\n\n[build-system]\nrequires = [\"setuptools>=61.2\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[tool.pytest.ini_options]\nasyncio_mode = \"auto\"\nasyncio_default_fixture_loop_scope = \"session\"\n"
  },
  {
    "path": "src/engineio/__init__.py",
    "content": "from .client import Client\nfrom .middleware import WSGIApp, Middleware\nfrom .server import Server\nfrom .async_server import AsyncServer\nfrom .async_client import AsyncClient\nfrom .async_drivers.asgi import ASGIApp\ntry:\n    from .async_drivers.tornado import get_tornado_handler\nexcept ImportError:  # pragma: no cover\n    get_tornado_handler = None\n\n__all__ = ['Server', 'WSGIApp', 'Middleware', 'Client',\n           'AsyncServer', 'ASGIApp', 'get_tornado_handler', 'AsyncClient']\n"
  },
  {
    "path": "src/engineio/async_client.py",
    "content": "import asyncio\nfrom http.cookies import SimpleCookie\nimport inspect\nimport signal\nimport ssl\nimport threading\n\ntry:\n    import aiohttp\nexcept ImportError:  # pragma: no cover\n    aiohttp = None\n\nfrom . import base_client\nfrom . import exceptions\nfrom . import packet\nfrom . import payload\n\nasync_signal_handler_set = False\n\n# this set is used to keep references to background tasks to prevent them from\n# being garbage collected mid-execution. Solution taken from\n# https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task\ntask_reference_holder = set()\n\n\ndef async_signal_handler():\n    \"\"\"SIGINT handler.\n\n    Disconnect all active async clients.\n    \"\"\"\n    async def _handler():  # pragma: no cover\n        for c in base_client.connected_clients[:]:\n            if c.is_asyncio_based():\n                await c.disconnect()\n\n        # cancel all running tasks\n        tasks = [task for task in asyncio.all_tasks() if task is not\n                 asyncio.current_task()]\n        for task in tasks:\n            task.cancel()\n        await asyncio.gather(*tasks, return_exceptions=True)\n        asyncio.get_running_loop().stop()\n\n    asyncio.ensure_future(_handler())\n\n\nclass AsyncClient(base_client.BaseClient):\n    \"\"\"An Engine.IO client for asyncio.\n\n    This class implements a fully compliant Engine.IO web client with support\n    for websocket and long-polling transports, compatible with the asyncio\n    framework on Python 3.5 or newer.\n\n    :param logger: To enable logging set to ``True`` or pass a logger object to\n                   use. To disable logging set to ``False``. The default is\n                   ``False``. Note that fatal errors are logged even when\n                   ``logger`` is ``False``.\n    :param json: An alternative JSON module to use for encoding and decoding\n                 packets. Custom json modules must have ``dumps`` and ``loads``\n                 functions that are compatible with the standard library\n                 versions. This is a process-wide setting, all instantiated\n                 servers and clients must use the same JSON module.\n    :param request_timeout: A timeout in seconds for requests. The default is\n                            5 seconds.\n    :param http_session: an initialized ``aiohttp.ClientSession`` object to be\n                         used when sending requests to the server. Use it if\n                         you need to add special client options such as proxy\n                         servers, SSL certificates, custom CA bundle, etc.\n    :param ssl_verify: ``True`` to verify SSL certificates, or ``False`` to\n                       skip SSL certificate verification, allowing\n                       connections to servers with self signed certificates.\n                       The default is ``True``.\n    :param handle_sigint: Set to ``True`` to automatically handle disconnection\n                          when the process is interrupted, or to ``False`` to\n                          leave interrupt handling to the calling application.\n                          Interrupt handling can only be enabled when the\n                          client instance is created in the main thread.\n    :param websocket_extra_options: Dictionary containing additional keyword\n                                    arguments passed to\n                                    ``aiohttp.ws_connect()``.\n    :param timestamp_requests: If ``True`` a timestamp is added to the query\n                               string of Socket.IO requests as a cache-busting\n                               measure. Set to ``False`` to disable.\n    \"\"\"\n    def is_asyncio_based(self):\n        return True\n\n    async def connect(self, url, headers=None, transports=None,\n                      engineio_path='engine.io'):\n        \"\"\"Connect to an Engine.IO server.\n\n        :param url: The URL of the Engine.IO server. It can include custom\n                    query string parameters if required by the server.\n        :param headers: A dictionary with custom headers to send with the\n                        connection request.\n        :param transports: The list of allowed transports. Valid transports\n                           are ``'polling'`` and ``'websocket'``. If not\n                           given, the polling transport is connected first,\n                           then an upgrade to websocket is attempted.\n        :param engineio_path: The endpoint where the Engine.IO server is\n                              installed. The default value is appropriate for\n                              most cases.\n\n        Note: this method is a coroutine.\n\n        Example usage::\n\n            eio = engineio.Client()\n            await eio.connect('http://localhost:5000')\n        \"\"\"\n        global async_signal_handler_set\n        if self.handle_sigint and not async_signal_handler_set and \\\n                threading.current_thread() == threading.main_thread():\n            try:\n                asyncio.get_running_loop().add_signal_handler(\n                    signal.SIGINT, async_signal_handler)\n            except NotImplementedError:  # pragma: no cover\n                self.logger.warning('Signal handler is unsupported')\n        async_signal_handler_set = True\n\n        if self.state != 'disconnected':\n            raise ValueError('Client is not in a disconnected state')\n        valid_transports = ['polling', 'websocket']\n        if transports is not None:\n            if isinstance(transports, str):\n                transports = [transports]\n            transports = [transport for transport in transports\n                          if transport in valid_transports]\n            if not transports:\n                raise ValueError('No valid transports provided')\n        self.transports = transports or valid_transports\n        return await getattr(self, '_connect_' + self.transports[0])(\n            url, headers or {}, engineio_path)\n\n    async def wait(self):\n        \"\"\"Wait until the connection with the server ends.\n\n        Client applications can use this function to block the main thread\n        during the life of the connection.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        if self.read_loop_task:\n            await self.read_loop_task\n\n    async def send(self, data):\n        \"\"\"Send a message to the server.\n\n        :param data: The data to send to the server. Data can be of type\n                     ``str``, ``bytes``, ``list`` or ``dict``. If a ``list``\n                     or ``dict``, the data will be serialized as JSON.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        await self._send_packet(packet.Packet(packet.MESSAGE, data=data))\n\n    async def disconnect(self, abort=False, reason=None):\n        \"\"\"Disconnect from the server.\n\n        :param abort: If set to ``True``, do not wait for background tasks\n                      associated with the connection to end.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        if self.state == 'connected':\n            await self._send_packet(packet.Packet(packet.CLOSE))\n            await self.queue.put(None)\n            self.state = 'disconnecting'\n            await self._trigger_event('disconnect',\n                                      reason or self.reason.CLIENT_DISCONNECT,\n                                      run_async=False)\n            if self.current_transport == 'websocket':\n                await self.ws.close()\n            if not abort:\n                await self.read_loop_task\n            self.state = 'disconnected'\n            try:\n                base_client.connected_clients.remove(self)\n            except ValueError:  # pragma: no cover\n                pass\n        await self._reset()\n\n    def start_background_task(self, target, *args, **kwargs):\n        \"\"\"Start a background task.\n\n        This is a utility function that applications can use to start a\n        background task.\n\n        :param target: the target function to execute.\n        :param args: arguments to pass to the function.\n        :param kwargs: keyword arguments to pass to the function.\n\n        The return value is a ``asyncio.Task`` object.\n        \"\"\"\n        return asyncio.ensure_future(target(*args, **kwargs))\n\n    async def sleep(self, seconds=0):\n        \"\"\"Sleep for the requested amount of time.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        return await asyncio.sleep(seconds)\n\n    def create_queue(self, *args, **kwargs):\n        \"\"\"Create a queue object.\"\"\"\n        return asyncio.Queue(*args, **kwargs)\n\n    def get_queue_empty_exception(self):\n        \"\"\"Return the queue empty exception raised by queues created by the\n        ``create_queue()`` method.\n        \"\"\"\n        return asyncio.QueueEmpty\n\n    def create_event(self):\n        \"\"\"Create an event object.\"\"\"\n        return asyncio.Event()\n\n    async def _reset(self):\n        super()._reset()\n        while True:  # pragma: no cover\n            try:\n                self.queue.get_nowait()\n                self.queue.task_done()\n            except self.queue_empty:\n                break\n        if not self.external_http:  # pragma: no cover\n            if self.http and not self.http.closed:\n                await self.http.close()\n\n    def __del__(self):  # pragma: no cover\n        # try to close the aiohttp session if it is still open\n        if self.http and not self.http.closed:\n            try:\n                loop = asyncio.get_event_loop()\n                if loop.is_running():\n                    loop.ensure_future(self.http.close())\n                else:\n                    loop.run_until_complete(self.http.close())\n            except:\n                pass\n\n    async def _connect_polling(self, url, headers, engineio_path):\n        \"\"\"Establish a long-polling connection to the Engine.IO server.\"\"\"\n        if aiohttp is None:  # pragma: no cover\n            self.logger.error('aiohttp not installed -- cannot make HTTP '\n                              'requests!')\n            return\n        self.base_url = self._get_engineio_url(url, engineio_path, 'polling')\n        self.logger.info('Attempting polling connection to ' + self.base_url)\n        r = await self._send_request(\n            'GET', self.base_url + self._get_url_timestamp(), headers=headers,\n            timeout=self.request_timeout)\n        if r is None or isinstance(r, str):\n            await self._reset()\n            raise exceptions.ConnectionError(\n                r or 'Connection refused by the server')\n        if r.status < 200 or r.status >= 300:\n            await self._reset()\n            try:\n                arg = await r.json()\n            except aiohttp.ClientError:\n                arg = None\n            raise exceptions.ConnectionError(\n                'Unexpected status code {} in server response'.format(\n                    r.status), arg)\n        try:\n            p = payload.Payload(encoded_payload=(await r.read()).decode(\n                'utf-8'))\n        except ValueError:\n            raise exceptions.ConnectionError(\n                'Unexpected response from server') from None\n        open_packet = p.packets[0]\n        if open_packet.packet_type != packet.OPEN:\n            raise exceptions.ConnectionError(\n                'OPEN packet not returned by server')\n        self.logger.info(\n            'Polling connection accepted with ' + str(open_packet.data))\n        self.sid = open_packet.data['sid']\n        self.upgrades = open_packet.data['upgrades']\n        self.ping_interval = int(open_packet.data['pingInterval']) / 1000.0\n        self.ping_timeout = int(open_packet.data['pingTimeout']) / 1000.0\n        self.current_transport = 'polling'\n        self.base_url += '&sid=' + self.sid\n\n        self.state = 'connected'\n        base_client.connected_clients.append(self)\n        await self._trigger_event('connect', run_async=False)\n\n        for pkt in p.packets[1:]:\n            await self._receive_packet(pkt)\n\n        if 'websocket' in self.upgrades and 'websocket' in self.transports:\n            # attempt to upgrade to websocket\n            if await self._connect_websocket(url, headers, engineio_path):\n                # upgrade to websocket succeeded, we're done here\n                return\n\n        self.write_loop_task = self.start_background_task(self._write_loop)\n        self.read_loop_task = self.start_background_task(\n            self._read_loop_polling)\n\n    async def _connect_websocket(self, url, headers, engineio_path):\n        \"\"\"Establish or upgrade to a WebSocket connection with the server.\"\"\"\n        if aiohttp is None:  # pragma: no cover\n            self.logger.error('aiohttp package not installed')\n            return False\n        websocket_url = self._get_engineio_url(url, engineio_path,\n                                               'websocket')\n        if self.sid:\n            self.logger.info(\n                'Attempting WebSocket upgrade to ' + websocket_url)\n            upgrade = True\n            websocket_url += '&sid=' + self.sid\n        else:\n            upgrade = False\n            self.base_url = websocket_url\n            self.logger.info(\n                'Attempting WebSocket connection to ' + websocket_url)\n\n        if self.http is None or self.http.closed:  # pragma: no cover\n            self.http = aiohttp.ClientSession()\n\n        # extract any new cookies passed in a header so that they can also be\n        # sent the the WebSocket route\n        for header, value in headers.items():\n            if header.lower() == 'cookie':\n                ck = SimpleCookie(headers[header])\n                self.http.cookie_jar.update_cookies(\n                    {k: m.value for k, m in ck.items()})\n                del headers[header]\n                break\n\n        extra_options = {\n            'timeout': aiohttp.ClientWSTimeout(ws_close=self.request_timeout)}\n        if not self.ssl_verify:\n            ssl_context = ssl.create_default_context()\n            ssl_context.check_hostname = False\n            ssl_context.verify_mode = ssl.CERT_NONE\n            extra_options['ssl'] = ssl_context\n\n        # combine internally generated options with the ones supplied by the\n        # caller. The caller's options take precedence.\n        headers.update(self.websocket_extra_options.pop('headers', {}))\n        extra_options['headers'] = headers\n        extra_options.update(self.websocket_extra_options)\n\n        try:\n            ws = await self.http.ws_connect(\n                websocket_url + self._get_url_timestamp(), **extra_options)\n        except (aiohttp.client_exceptions.WSServerHandshakeError,\n                aiohttp.client_exceptions.ServerConnectionError,\n                aiohttp.client_exceptions.ClientConnectionError):\n            if upgrade:\n                self.logger.warning(\n                    'WebSocket upgrade failed: connection error')\n                return False\n            else:\n                raise exceptions.ConnectionError('Connection error')\n        if upgrade:\n            p = packet.Packet(packet.PING, data='probe').encode()\n            try:\n                await ws.send_str(p)\n            except Exception as e:  # pragma: no cover\n                self.logger.warning(\n                    'WebSocket upgrade failed: unexpected send exception: %s',\n                    str(e))\n                return False\n            try:\n                p = (await ws.receive()).data\n            except Exception as e:  # pragma: no cover\n                self.logger.warning(\n                    'WebSocket upgrade failed: unexpected recv exception: %s',\n                    str(e))\n                return False\n            pkt = packet.Packet(encoded_packet=p)\n            if pkt.packet_type != packet.PONG or pkt.data != 'probe':\n                self.logger.warning(\n                    'WebSocket upgrade failed: no PONG packet')\n                return False\n            p = packet.Packet(packet.UPGRADE).encode()\n            try:\n                await ws.send_str(p)\n            except Exception as e:  # pragma: no cover\n                self.logger.warning(\n                    'WebSocket upgrade failed: unexpected send exception: %s',\n                    str(e))\n                return False\n            self.current_transport = 'websocket'\n            self.logger.info('WebSocket upgrade was successful')\n        else:\n            try:\n                p = (await ws.receive()).data\n            except Exception as e:  # pragma: no cover\n                raise exceptions.ConnectionError(\n                    'Unexpected recv exception: ' + str(e))\n            open_packet = packet.Packet(encoded_packet=p)\n            if open_packet.packet_type != packet.OPEN:\n                raise exceptions.ConnectionError('no OPEN packet')\n            self.logger.info(\n                'WebSocket connection accepted with ' + str(open_packet.data))\n            self.sid = open_packet.data['sid']\n            self.upgrades = open_packet.data['upgrades']\n            self.ping_interval = int(open_packet.data['pingInterval']) / 1000.0\n            self.ping_timeout = int(open_packet.data['pingTimeout']) / 1000.0\n            self.current_transport = 'websocket'\n\n            self.state = 'connected'\n            base_client.connected_clients.append(self)\n            await self._trigger_event('connect', run_async=False)\n\n        self.ws = ws\n        self.write_loop_task = self.start_background_task(self._write_loop)\n        self.read_loop_task = self.start_background_task(\n            self._read_loop_websocket)\n        return True\n\n    async def _receive_packet(self, pkt):\n        \"\"\"Handle incoming packets from the server.\"\"\"\n        packet_name = packet.packet_names[pkt.packet_type] \\\n            if pkt.packet_type < len(packet.packet_names) else 'UNKNOWN'\n        self.logger.info(\n            'Received packet %s data %s', packet_name,\n            pkt.data if not isinstance(pkt.data, bytes) else '<binary>')\n        if pkt.packet_type == packet.MESSAGE:\n            await self._trigger_event('message', pkt.data, run_async=True)\n        elif pkt.packet_type == packet.PING:\n            await self._send_packet(packet.Packet(packet.PONG, pkt.data))\n        elif pkt.packet_type == packet.CLOSE:\n            await self.disconnect(abort=True,\n                                  reason=self.reason.SERVER_DISCONNECT)\n        elif pkt.packet_type == packet.NOOP:\n            pass\n        else:\n            self.logger.error('Received unexpected packet of type %s',\n                              pkt.packet_type)\n\n    async def _send_packet(self, pkt):\n        \"\"\"Queue a packet to be sent to the server.\"\"\"\n        if self.state != 'connected':\n            return\n        await self.queue.put(pkt)\n        self.logger.info(\n            'Sending packet %s data %s',\n            packet.packet_names[pkt.packet_type],\n            pkt.data if not isinstance(pkt.data, bytes) else '<binary>')\n\n    async def _send_request(\n            self, method, url, headers=None, body=None,\n            timeout=None):  # pragma: no cover\n        if self.http is None or self.http.closed:\n            self.http = aiohttp.ClientSession()\n        http_method = getattr(self.http, method.lower())\n\n        try:\n            if not self.ssl_verify:\n                return await http_method(\n                    url, headers=headers, data=body,\n                    timeout=aiohttp.ClientTimeout(total=timeout), ssl=False)\n            else:\n                return await http_method(\n                    url, headers=headers, data=body,\n                    timeout=aiohttp.ClientTimeout(total=timeout))\n\n        except (aiohttp.ClientError, asyncio.TimeoutError) as exc:\n            self.logger.info('HTTP %s request to %s failed with error %s.',\n                             method, url, exc)\n            return str(exc)\n\n    async def _trigger_event(self, event, *args, **kwargs):\n        \"\"\"Invoke an event handler.\"\"\"\n        run_async = kwargs.pop('run_async', False)\n        ret = None\n        if event in self.handlers:\n            if inspect.iscoroutinefunction(self.handlers[event]) is True:\n                if run_async:\n                    task = self.start_background_task(self.handlers[event],\n                                                      *args)\n                    task_reference_holder.add(task)\n                    task.add_done_callback(task_reference_holder.discard)\n                    return task\n                else:\n                    try:\n                        try:\n                            ret = await self.handlers[event](*args)\n                        except TypeError:\n                            if event == 'disconnect' and \\\n                                    len(args) == 1:  # pragma: no branch\n                                # legacy disconnect events do not have a reason\n                                # argument\n                                return await self.handlers[event]()\n                            else:  # pragma: no cover\n                                raise\n                    except asyncio.CancelledError:  # pragma: no cover\n                        pass\n                    except:\n                        self.logger.exception(event + ' async handler error')\n                        if event == 'connect':\n                            # if connect handler raised error we reject the\n                            # connection\n                            return False\n            else:\n                if run_async:\n                    async def async_handler():\n                        return self.handlers[event](*args)\n\n                    task = self.start_background_task(async_handler)\n                    task_reference_holder.add(task)\n                    task.add_done_callback(task_reference_holder.discard)\n                    return task\n                else:\n                    try:\n                        try:\n                            ret = self.handlers[event](*args)\n                        except TypeError:\n                            if event == 'disconnect' and \\\n                                    len(args) == 1:  # pragma: no branch\n                                # legacy disconnect events do not have a reason\n                                # argument\n                                ret = self.handlers[event]()\n                            else:  # pragma: no cover\n                                raise\n                    except:\n                        self.logger.exception(event + ' handler error')\n                        if event == 'connect':\n                            # if connect handler raised error we reject the\n                            # connection\n                            return False\n        return ret\n\n    async def _read_loop_polling(self):\n        \"\"\"Read packets by polling the Engine.IO server.\"\"\"\n        while self.state == 'connected' and self.write_loop_task:\n            self.logger.info(\n                'Sending polling GET request to ' + self.base_url)\n            r = await self._send_request(\n                'GET', self.base_url + self._get_url_timestamp(),\n                timeout=max(self.ping_interval, self.ping_timeout) + 5)\n            if r is None or isinstance(r, str):\n                self.logger.warning(\n                    r or 'Connection refused by the server, aborting')\n                await self.queue.put(None)\n                break\n            if r.status < 200 or r.status >= 300:\n                self.logger.warning('Unexpected status code %s in server '\n                                    'response, aborting', r.status)\n                await self.queue.put(None)\n                break\n            try:\n                p = payload.Payload(encoded_payload=(await r.read()).decode(\n                    'utf-8'))\n            except ValueError:\n                self.logger.warning(\n                    'Unexpected packet from server, aborting')\n                await self.queue.put(None)\n                break\n            for pkt in p.packets:\n                await self._receive_packet(pkt)\n\n        if self.write_loop_task:  # pragma: no branch\n            self.logger.info('Waiting for write loop task to end')\n            await self.write_loop_task\n        if self.state == 'connected':\n            await self._trigger_event(\n                'disconnect', self.reason.TRANSPORT_ERROR, run_async=False)\n            try:\n                base_client.connected_clients.remove(self)\n            except ValueError:  # pragma: no cover\n                pass\n            await self._reset()\n        self.logger.info('Exiting read loop task')\n\n    async def _read_loop_websocket(self):\n        \"\"\"Read packets from the Engine.IO WebSocket connection.\"\"\"\n        while self.state == 'connected':\n            p = None\n            try:\n                p = await asyncio.wait_for(\n                    self.ws.receive(),\n                    timeout=self.ping_interval + self.ping_timeout)\n                if not isinstance(p.data, (str, bytes)):  # pragma: no cover\n                    self.logger.warning(\n                        'Server sent %s packet data %s, aborting',\n                        'close' if p.type in [aiohttp.WSMsgType.CLOSE,\n                                              aiohttp.WSMsgType.CLOSING]\n                        else str(p.type), str(p.data))\n                    await self.queue.put(None)\n                    break  # the connection is broken\n                p = p.data\n            except asyncio.TimeoutError:\n                self.logger.warning(\n                    'Server has stopped communicating, aborting')\n                await self.queue.put(None)\n                break\n            except aiohttp.client_exceptions.ServerDisconnectedError:\n                self.logger.info(\n                    'Read loop: WebSocket connection was closed, aborting')\n                await self.queue.put(None)\n                break\n            except Exception as e:\n                self.logger.info(\n                    'Unexpected error receiving packet: \"%s\", aborting',\n                    str(e))\n                await self.queue.put(None)\n                break\n            try:\n                pkt = packet.Packet(encoded_packet=p)\n            except Exception as e:  # pragma: no cover\n                self.logger.info(\n                    'Unexpected error decoding packet: \"%s\", aborting', str(e))\n                await self.queue.put(None)\n                break\n            await self._receive_packet(pkt)\n\n        if self.write_loop_task:  # pragma: no branch\n            self.logger.info('Waiting for write loop task to end')\n            await self.write_loop_task\n        if self.state == 'connected':\n            await self._trigger_event(\n                'disconnect', self.reason.TRANSPORT_ERROR, run_async=False)\n            try:\n                base_client.connected_clients.remove(self)\n            except ValueError:  # pragma: no cover\n                pass\n            await self._reset()\n        self.logger.info('Exiting read loop task')\n\n    async def _write_loop(self):\n        \"\"\"This background task sends packages to the server as they are\n        pushed to the send queue.\n        \"\"\"\n        while self.state == 'connected':\n            # to simplify the timeout handling, use the maximum of the\n            # ping interval and ping timeout as timeout, with an extra 5\n            # seconds grace period\n            timeout = max(self.ping_interval, self.ping_timeout) + 5\n            packets = None\n            try:\n                packets = [await asyncio.wait_for(self.queue.get(), timeout)]\n            except (self.queue_empty, asyncio.TimeoutError):\n                self.logger.error('packet queue is empty, aborting')\n                break\n            except asyncio.CancelledError:  # pragma: no cover\n                break\n            if packets == [None]:\n                self.queue.task_done()\n                packets = []\n            else:\n                while True:\n                    try:\n                        packets.append(self.queue.get_nowait())\n                    except self.queue_empty:\n                        break\n                    if packets[-1] is None:\n                        packets = packets[:-1]\n                        self.queue.task_done()\n                        break\n            if not packets:\n                # empty packet list returned -> connection closed\n                break\n            if self.current_transport == 'polling':\n                p = payload.Payload(packets=packets)\n                r = await self._send_request(\n                    'POST', self.base_url, body=p.encode(),\n                    headers={'Content-Type': 'text/plain'},\n                    timeout=self.request_timeout)\n                for pkt in packets:\n                    self.queue.task_done()\n                if r is None or isinstance(r, str):\n                    self.logger.warning(\n                        r or 'Connection refused by the server, aborting')\n                    break\n                if r.status < 200 or r.status >= 300:\n                    self.logger.warning('Unexpected status code %s in server '\n                                        'response, aborting', r.status)\n                    self.write_loop_task = None\n                    break\n            else:\n                # websocket\n                try:\n                    for pkt in packets:\n                        if pkt.binary:\n                            await self.ws.send_bytes(pkt.encode())\n                        else:\n                            await self.ws.send_str(pkt.encode())\n                        self.queue.task_done()\n                except (aiohttp.client_exceptions.ServerDisconnectedError,\n                        BrokenPipeError, OSError):\n                    self.logger.info(\n                        'Write loop: WebSocket connection was closed, '\n                        'aborting')\n                    break\n        self.logger.info('Exiting write loop task')\n"
  },
  {
    "path": "src/engineio/async_drivers/__init__.py",
    "content": ""
  },
  {
    "path": "src/engineio/async_drivers/_websocket_wsgi.py",
    "content": "import simple_websocket\n\n\nclass SimpleWebSocketWSGI:  # pragma: no cover\n    \"\"\"\n    This wrapper class provides a threading WebSocket interface that is\n    compatible with eventlet's implementation.\n    \"\"\"\n    def __init__(self, handler, server, **kwargs):\n        self.app = handler\n        self.server_args = kwargs\n\n    def __call__(self, environ, start_response):\n        self.ws = simple_websocket.Server(environ, **self.server_args)\n        ret = self.app(self)\n        if self.ws.mode == 'gunicorn':\n            raise StopIteration()\n        return ret\n\n    def close(self):\n        if self.ws.connected:\n            self.ws.close()\n\n    def send(self, message):\n        try:\n            return self.ws.send(message)\n        except simple_websocket.ConnectionClosed:\n            raise OSError()\n\n    def wait(self):\n        try:\n            return self.ws.receive()\n        except simple_websocket.ConnectionClosed:\n            return None\n"
  },
  {
    "path": "src/engineio/async_drivers/aiohttp.py",
    "content": "import inspect\nimport sys\n\nfrom aiohttp.web import Response, WebSocketResponse\n\n\ndef create_route(app, engineio_server, engineio_endpoint):\n    \"\"\"This function sets up the engine.io endpoint as a route for the\n    application.\n\n    Note that both GET and POST requests must be hooked up on the engine.io\n    endpoint.\n    \"\"\"\n    app.router.add_get(engineio_endpoint, engineio_server.handle_request)\n    app.router.add_post(engineio_endpoint, engineio_server.handle_request)\n    app.router.add_route('OPTIONS', engineio_endpoint,\n                         engineio_server.handle_request)\n\n\ndef translate_request(request):\n    \"\"\"This function takes the arguments passed to the request handler and\n    uses them to generate a WSGI compatible environ dictionary.\n    \"\"\"\n    environ = {\n        'wsgi.input': request.content,\n        'wsgi.errors': sys.stderr,\n        'wsgi.version': (1, 0),\n        'wsgi.async': True,\n        'wsgi.multithread': False,\n        'wsgi.multiprocess': False,\n        'wsgi.run_once': False,\n        'SERVER_SOFTWARE': 'aiohttp',\n        'REQUEST_METHOD': request.method,\n        'QUERY_STRING': request.query_string or '',\n        'RAW_URI': request.path_qs,\n        'SERVER_PROTOCOL': f'HTTP/{request.version[0]}.{request.version[1]}',\n        'REMOTE_ADDR': '127.0.0.1',\n        'REMOTE_PORT': '0',\n        'SERVER_NAME': 'aiohttp',\n        'SERVER_PORT': '0',\n        'aiohttp.request': request\n    }\n\n    for hdr_name, hdr_value in request.headers.items():\n        hdr_name = hdr_name.upper()\n        if hdr_name == 'CONTENT-TYPE':\n            environ['CONTENT_TYPE'] = hdr_value\n            continue\n        elif hdr_name == 'CONTENT-LENGTH':\n            environ['CONTENT_LENGTH'] = hdr_value\n            continue\n\n        key = 'HTTP_%s' % hdr_name.replace('-', '_')\n        if key in environ:\n            hdr_value = f'{environ[key]},{hdr_value}'\n\n        environ[key] = hdr_value\n\n    environ['wsgi.url_scheme'] = environ.get('HTTP_X_FORWARDED_PROTO', 'http')\n\n    environ['PATH_INFO'] = request.path\n    environ['SCRIPT_NAME'] = ''\n\n    return environ\n\n\ndef make_response(status, headers, payload, environ):\n    \"\"\"This function generates an appropriate response object for this async\n    mode.\n    \"\"\"\n    return Response(body=payload, status=int(status.split()[0]),\n                    headers=headers)\n\n\nclass WebSocket:  # pragma: no cover\n    \"\"\"\n    This wrapper class provides a aiohttp WebSocket interface that is\n    somewhat compatible with eventlet's implementation.\n    \"\"\"\n    def __init__(self, handler, server):\n        self.handler = handler\n        self._sock = None\n\n    async def __call__(self, environ):\n        request = environ['aiohttp.request']\n        self._sock = WebSocketResponse(max_msg_size=0)\n        await self._sock.prepare(request)\n\n        self.environ = environ\n        await self.handler(self)\n        return self._sock\n\n    async def close(self):\n        await self._sock.close()\n\n    async def send(self, message):\n        if isinstance(message, bytes):\n            f = self._sock.send_bytes\n        else:\n            f = self._sock.send_str\n        if inspect.iscoroutinefunction(f):\n            await f(message)\n        else:\n            f(message)\n\n    async def wait(self):\n        msg = await self._sock.receive()\n        if not isinstance(msg.data, bytes) and \\\n                not isinstance(msg.data, str):\n            raise OSError()\n        return msg.data\n\n\n_async = {\n    'asyncio': True,\n    'create_route': create_route,\n    'translate_request': translate_request,\n    'make_response': make_response,\n    'websocket': WebSocket,\n}\n"
  },
  {
    "path": "src/engineio/async_drivers/asgi.py",
    "content": "import inspect\nimport os\nimport sys\n\nfrom engineio.static_files import get_static_file\n\n\nclass ASGIApp:\n    \"\"\"ASGI application middleware for Engine.IO.\n\n    This middleware dispatches traffic to an Engine.IO application. It can\n    also serve a list of static files to the client, or forward unrelated\n    HTTP traffic to another ASGI application.\n\n    :param engineio_server: The Engine.IO server. Must be an instance of the\n                            ``engineio.AsyncServer`` class.\n    :param static_files: A dictionary with static file mapping rules. See the\n                         documentation for details on this argument.\n    :param other_asgi_app: A separate ASGI app that receives all other traffic.\n    :param engineio_path: The endpoint where the Engine.IO application should\n                          be installed. The default value is appropriate for\n                          most cases. With a value of ``None``, all incoming\n                          traffic is directed to the Engine.IO server, with the\n                          assumption that routing, if necessary, is handled by\n                          a different layer. When this option is set to\n                          ``None``, ``static_files`` and ``other_asgi_app`` are\n                          ignored.\n    :param on_startup: function to be called on application startup; can be\n                       coroutine\n    :param on_shutdown: function to be called on application shutdown; can be\n                        coroutine\n\n    Example usage::\n\n        import engineio\n        import uvicorn\n\n        eio = engineio.AsyncServer()\n        app = engineio.ASGIApp(eio, static_files={\n            '/': {'content_type': 'text/html', 'filename': 'index.html'},\n            '/index.html': {'content_type': 'text/html',\n                            'filename': 'index.html'},\n        })\n        uvicorn.run(app, '127.0.0.1', 5000)\n    \"\"\"\n    def __init__(self, engineio_server, other_asgi_app=None,\n                 static_files=None, engineio_path='engine.io',\n                 on_startup=None, on_shutdown=None):\n        self.engineio_server = engineio_server\n        self.other_asgi_app = other_asgi_app\n        self.engineio_path = engineio_path\n        if self.engineio_path is not None:\n            if not self.engineio_path.startswith('/'):\n                self.engineio_path = '/' + self.engineio_path\n            if not self.engineio_path.endswith('/'):\n                self.engineio_path += '/'\n        self.static_files = static_files or {}\n        self.on_startup = on_startup\n        self.on_shutdown = on_shutdown\n\n    async def __call__(self, scope, receive, send):\n        if scope['type'] == 'lifespan':\n            await self.lifespan(scope, receive, send)\n        elif scope['type'] in ['http', 'websocket'] and (\n                self.engineio_path is None\n                or self._ensure_trailing_slash(scope['path']).startswith(\n                    self.engineio_path)):\n            await self.engineio_server.handle_request(scope, receive, send)\n        else:\n            static_file = get_static_file(scope['path'], self.static_files) \\\n                if scope['type'] == 'http' and self.static_files else None\n            if static_file and os.path.exists(static_file['filename']):\n                await self.serve_static_file(static_file, receive, send)\n            elif self.other_asgi_app is not None:\n                await self.other_asgi_app(scope, receive, send)\n            else:\n                await self.not_found(receive, send)\n\n    async def serve_static_file(self, static_file, receive,\n                                send):  # pragma: no cover\n        event = await receive()\n        if event['type'] == 'http.request':\n            with open(static_file['filename'], 'rb') as f:\n                payload = f.read()\n            await send({'type': 'http.response.start',\n                        'status': 200,\n                        'headers': [(b'Content-Type', static_file[\n                            'content_type'].encode('utf-8'))]})\n            await send({'type': 'http.response.body',\n                        'body': payload})\n\n    async def lifespan(self, scope, receive, send):\n        if self.other_asgi_app is not None and self.on_startup is None and \\\n                self.on_shutdown is None:\n            # let the other ASGI app handle lifespan events\n            await self.other_asgi_app(scope, receive, send)\n            return\n\n        while True:\n            event = await receive()\n            if event['type'] == 'lifespan.startup':\n                if self.on_startup:\n                    try:\n                        await self.on_startup() \\\n                            if inspect.iscoroutinefunction(self.on_startup) \\\n                            else self.on_startup()\n                    except:\n                        await send({'type': 'lifespan.startup.failed'})\n                        return\n                await send({'type': 'lifespan.startup.complete'})\n            elif event['type'] == 'lifespan.shutdown':\n                if self.on_shutdown:\n                    try:\n                        await self.on_shutdown() \\\n                            if inspect.iscoroutinefunction(self.on_shutdown) \\\n                            else self.on_shutdown()\n                    except:\n                        await send({'type': 'lifespan.shutdown.failed'})\n                        return\n                await send({'type': 'lifespan.shutdown.complete'})\n                return\n\n    async def not_found(self, receive, send):\n        \"\"\"Return a 404 Not Found error to the client.\"\"\"\n        await send({'type': 'http.response.start',\n                    'status': 404,\n                    'headers': [(b'Content-Type', b'text/plain')]})\n        await send({'type': 'http.response.body',\n                    'body': b'Not Found'})\n\n    def _ensure_trailing_slash(self, path):\n        if not path.endswith('/'):\n            path += '/'\n        return path\n\n\nasync def translate_request(scope, receive, send):\n    class AwaitablePayload:  # pragma: no cover\n        def __init__(self, payload):\n            self.payload = payload or b''\n\n        async def read(self, length=None):\n            if length is None:\n                r = self.payload\n                self.payload = b''\n            else:\n                r = self.payload[:length]\n                self.payload = self.payload[length:]\n            return r\n\n    event = await receive()\n    payload = b''\n    if event['type'] == 'http.request':\n        payload += event.get('body') or b''\n        while event.get('more_body'):\n            event = await receive()\n            if event['type'] == 'http.request':\n                payload += event.get('body') or b''\n    elif event['type'] == 'websocket.connect':\n        pass\n    else:\n        return {}\n\n    raw_uri = scope['path']\n    query_string = ''\n    if 'query_string' in scope and scope['query_string']:\n        try:\n            query_string = scope['query_string'].decode('utf-8')\n        except UnicodeDecodeError:\n            pass\n        else:\n            raw_uri += '?' + query_string\n    environ = {\n        'wsgi.input': AwaitablePayload(payload),\n        'wsgi.errors': sys.stderr,\n        'wsgi.version': (1, 0),\n        'wsgi.async': True,\n        'wsgi.multithread': False,\n        'wsgi.multiprocess': False,\n        'wsgi.run_once': False,\n        'SERVER_SOFTWARE': 'asgi',\n        'REQUEST_METHOD': scope.get('method', 'GET'),\n        'PATH_INFO': scope['path'],\n        'QUERY_STRING': query_string,\n        'RAW_URI': raw_uri,\n        'SCRIPT_NAME': '',\n        'SERVER_PROTOCOL': 'HTTP/1.1',\n        'REMOTE_ADDR': '127.0.0.1',\n        'REMOTE_PORT': '0',\n        'SERVER_NAME': 'asgi',\n        'SERVER_PORT': '0',\n        'asgi.receive': receive,\n        'asgi.send': send,\n        'asgi.scope': scope,\n    }\n\n    for hdr_name, hdr_value in scope['headers']:\n        try:\n            hdr_name = hdr_name.upper().decode('utf-8')\n            hdr_value = hdr_value.decode('utf-8')\n        except UnicodeDecodeError:\n            # skip header if it cannot be decoded\n            continue\n        if hdr_name == 'CONTENT-TYPE':\n            environ['CONTENT_TYPE'] = hdr_value\n            continue\n        elif hdr_name == 'CONTENT-LENGTH':\n            environ['CONTENT_LENGTH'] = hdr_value\n            continue\n\n        key = 'HTTP_%s' % hdr_name.replace('-', '_')\n        if key in environ:\n            hdr_value = f'{environ[key]},{hdr_value}'\n\n        environ[key] = hdr_value\n\n    environ['wsgi.url_scheme'] = environ.get('HTTP_X_FORWARDED_PROTO', 'http')\n    return environ\n\n\nasync def make_response(status, headers, payload, environ):\n    headers = [(h[0].encode('utf-8'), h[1].encode('utf-8')) for h in headers]\n    if environ['asgi.scope']['type'] == 'websocket':\n        if status.startswith('200 '):\n            await environ['asgi.send']({'type': 'websocket.accept',\n                                        'headers': headers})\n        else:\n            if payload:\n                reason = payload.decode('utf-8') \\\n                    if isinstance(payload, bytes) else str(payload)\n                await environ['asgi.send']({'type': 'websocket.close',\n                                            'reason': reason})\n            else:\n                await environ['asgi.send']({'type': 'websocket.close'})\n        return\n\n    await environ['asgi.send']({'type': 'http.response.start',\n                                'status': int(status.split(' ')[0]),\n                                'headers': headers})\n    await environ['asgi.send']({'type': 'http.response.body',\n                                'body': payload})\n\n\nclass WebSocket:  # pragma: no cover\n    \"\"\"\n    This wrapper class provides an asgi WebSocket interface that is\n    somewhat compatible with eventlet's implementation.\n    \"\"\"\n    def __init__(self, handler, server):\n        self.handler = handler\n        self.asgi_receive = None\n        self.asgi_send = None\n\n    async def __call__(self, environ):\n        self.asgi_receive = environ['asgi.receive']\n        self.asgi_send = environ['asgi.send']\n        await self.asgi_send({'type': 'websocket.accept'})\n        await self.handler(self)\n        return ''  # send nothing as response\n\n    async def close(self):\n        try:\n            await self.asgi_send({'type': 'websocket.close'})\n        except Exception:\n            # if the socket is already close we don't care\n            pass\n\n    async def send(self, message):\n        msg_bytes = None\n        msg_text = None\n        if isinstance(message, bytes):\n            msg_bytes = message\n        else:\n            msg_text = message\n        await self.asgi_send({'type': 'websocket.send',\n                              'bytes': msg_bytes,\n                              'text': msg_text})\n\n    async def wait(self):\n        event = await self.asgi_receive()\n        if event['type'] != 'websocket.receive':\n            raise OSError()\n        if event.get('bytes', None) is not None:\n            return event['bytes']\n        elif event.get('text', None) is not None:\n            return event['text']\n        else:  # pragma: no cover\n            raise OSError()\n\n\n_async = {\n    'asyncio': True,\n    'translate_request': translate_request,\n    'make_response': make_response,\n    'websocket': WebSocket,\n}\n"
  },
  {
    "path": "src/engineio/async_drivers/eventlet.py",
    "content": "from eventlet.green.threading import Event\nfrom eventlet import queue, sleep, spawn\nfrom eventlet.websocket import WebSocketWSGI as _WebSocketWSGI\n\n\nclass EventletThread:  # pragma: no cover\n    \"\"\"Thread class that uses eventlet green threads.\n\n    Eventlet's own Thread class has a strange bug that causes _DummyThread\n    objects to be created and leaked, since they are never garbage collected.\n    \"\"\"\n    def __init__(self, target, args=None, kwargs=None):\n        self.target = target\n        self.args = args or ()\n        self.kwargs = kwargs or {}\n        self.g = None\n\n    def start(self):\n        self.g = spawn(self.target, *self.args, **self.kwargs)\n\n    def join(self):\n        if self.g:\n            return self.g.wait()\n\n\nclass WebSocketWSGI(_WebSocketWSGI):  # pragma: no cover\n    def __init__(self, handler, server):\n        try:\n            super().__init__(\n                handler, max_frame_length=int(server.max_http_buffer_size))\n        except TypeError:  # pragma: no cover\n            # older versions of eventlet do not support a max frame size\n            super().__init__(handler)\n        self._sock = None\n\n    def __call__(self, environ, start_response):\n        if 'eventlet.input' not in environ:\n            raise RuntimeError('You need to use the eventlet server. '\n                               'See the Deployment section of the '\n                               'documentation for more information.')\n        self._sock = environ['eventlet.input'].get_socket()\n        return super().__call__(environ, start_response)\n\n\n_async = {\n    'thread': EventletThread,\n    'queue': queue.Queue,\n    'queue_empty': queue.Empty,\n    'event': Event,\n    'websocket': WebSocketWSGI,\n    'sleep': sleep,\n}\n"
  },
  {
    "path": "src/engineio/async_drivers/gevent.py",
    "content": "import gevent\nfrom gevent import queue\nfrom gevent.event import Event\ntry:\n    # use gevent-websocket if installed\n    import geventwebsocket  # noqa\n    SimpleWebSocketWSGI = None\nexcept ImportError:  # pragma: no cover\n    # fallback to simple_websocket when gevent-websocket is not installed\n    from engineio.async_drivers._websocket_wsgi import SimpleWebSocketWSGI\n\n\nclass Thread(gevent.Greenlet):  # pragma: no cover\n    \"\"\"\n    This wrapper class provides gevent Greenlet interface that is compatible\n    with the standard library's Thread class.\n    \"\"\"\n    def __init__(self, target, args=[], kwargs={}):\n        super().__init__(target, *args, **kwargs)\n\n    def _run(self):\n        return self.run()\n\n\nif SimpleWebSocketWSGI is not None:\n    class WebSocketWSGI(SimpleWebSocketWSGI):  # pragma: no cover\n        \"\"\"\n        This wrapper class provides a gevent WebSocket interface that is\n        compatible with eventlet's implementation, using the simple-websocket\n        package.\n        \"\"\"\n        def __init__(self, handler, server):\n            # to avoid the requirement that the standard library is\n            # monkey-patched, here we pass the gevent versions of the\n            # concurrency and networking classes required by simple-websocket\n            import gevent.event\n            import gevent.selectors\n            super().__init__(handler, server,\n                             thread_class=Thread,\n                             event_class=gevent.event.Event,\n                             selector_class=gevent.selectors.DefaultSelector)\nelse:\n    class WebSocketWSGI:  # pragma: no cover\n        \"\"\"\n        This wrapper class provides a gevent WebSocket interface that is\n        compatible with eventlet's implementation, using the gevent-websocket\n        package.\n        \"\"\"\n        def __init__(self, handler, server):\n            self.app = handler\n\n        def __call__(self, environ, start_response):\n            if 'wsgi.websocket' not in environ:\n                raise RuntimeError('The gevent-websocket server is not '\n                                   'configured appropriately. '\n                                   'See the Deployment section of the '\n                                   'documentation for more information.')\n            self._sock = environ['wsgi.websocket']\n            self.environ = environ\n            self.version = self._sock.version\n            self.path = self._sock.path\n            self.origin = self._sock.origin\n            self.protocol = self._sock.protocol\n            return self.app(self)\n\n        def close(self):\n            return self._sock.close()\n\n        def send(self, message):\n            return self._sock.send(message)\n\n        def wait(self):\n            return self._sock.receive()\n\n\n_async = {\n    'thread': Thread,\n    'queue': queue.JoinableQueue,\n    'queue_empty': queue.Empty,\n    'event': Event,\n    'websocket': WebSocketWSGI,\n    'sleep': gevent.sleep,\n}\n"
  },
  {
    "path": "src/engineio/async_drivers/gevent_uwsgi.py",
    "content": "import gevent\nfrom gevent import queue\nfrom gevent.event import Event\nfrom gevent import selectors\nimport uwsgi\n_websocket_available = hasattr(uwsgi, 'websocket_handshake')\n\n\nclass Thread(gevent.Greenlet):  # pragma: no cover\n    \"\"\"\n    This wrapper class provides gevent Greenlet interface that is compatible\n    with the standard library's Thread class.\n    \"\"\"\n    def __init__(self, target, args=[], kwargs={}):\n        super().__init__(target, *args, **kwargs)\n\n    def _run(self):\n        return self.run()\n\n\nclass uWSGIWebSocket:  # pragma: no cover\n    \"\"\"\n    This wrapper class provides a uWSGI WebSocket interface that is\n    compatible with eventlet's implementation.\n    \"\"\"\n    def __init__(self, handler, server):\n        self.app = handler\n        self._sock = None\n        self.received_messages = []\n\n    def __call__(self, environ, start_response):\n        self._sock = uwsgi.connection_fd()\n        self.environ = environ\n\n        uwsgi.websocket_handshake()\n\n        self._req_ctx = None\n        if hasattr(uwsgi, 'request_context'):\n            # uWSGI >= 2.1.x with support for api access across-greenlets\n            self._req_ctx = uwsgi.request_context()\n        else:\n            # use event and queue for sending messages\n            self._event = Event()\n            self._send_queue = queue.Queue()\n\n            # spawn a select greenlet\n            def select_greenlet_runner(fd, event):\n                \"\"\"Sets event when data becomes available to read on fd.\"\"\"\n                sel = selectors.DefaultSelector()\n                sel.register(fd, selectors.EVENT_READ)\n                try:\n                    while True:\n                        sel.select()\n                        event.set()\n                except gevent.GreenletExit:\n                    sel.unregister(fd)\n            self._select_greenlet = gevent.spawn(\n                select_greenlet_runner,\n                self._sock,\n                self._event)\n\n        self.app(self)\n        uwsgi.disconnect()\n        return ''  # send nothing as response\n\n    def close(self):\n        \"\"\"Disconnects uWSGI from the client.\"\"\"\n        if self._req_ctx is None:\n            # better kill it here in case wait() is not called again\n            self._select_greenlet.kill()\n            self._event.set()\n\n    def _send(self, msg):\n        \"\"\"Transmits message either in binary or UTF-8 text mode,\n        depending on its type.\"\"\"\n        if isinstance(msg, bytes):\n            method = uwsgi.websocket_send_binary\n        else:\n            method = uwsgi.websocket_send\n        if self._req_ctx is not None:\n            method(msg, request_context=self._req_ctx)\n        else:\n            method(msg)\n\n    def _decode_received(self, msg):\n        \"\"\"Returns either bytes or str, depending on message type.\"\"\"\n        if not isinstance(msg, bytes):\n            # already decoded - do nothing\n            return msg\n        # only decode from utf-8 if message is not binary data\n        type = ord(msg[0:1])\n        if type >= 48:  # no binary\n            return msg.decode('utf-8')\n        # binary message, don't try to decode\n        return msg\n\n    def send(self, msg):\n        \"\"\"Queues a message for sending. Real transmission is done in\n        wait method.\n        Sends directly if uWSGI version is new enough.\"\"\"\n        if self._req_ctx is not None:\n            self._send(msg)\n        else:\n            self._send_queue.put(msg)\n            self._event.set()\n\n    def wait(self):\n        \"\"\"Waits and returns received messages.\n        If running in compatibility mode for older uWSGI versions,\n        it also sends messages that have been queued by send().\n        A return value of None means that connection was closed.\n        This must be called repeatedly. For uWSGI < 2.1.x it must\n        be called from the main greenlet.\"\"\"\n        while True:\n            if self._req_ctx is not None:\n                try:\n                    msg = uwsgi.websocket_recv(request_context=self._req_ctx)\n                except OSError:  # connection closed\n                    self.close()\n                    return None\n                return self._decode_received(msg)\n            else:\n                if self.received_messages:\n                    return self.received_messages.pop(0)\n\n                # we wake up at least every 3 seconds to let uWSGI\n                # do its ping/ponging\n                event_set = self._event.wait(timeout=3)\n                if event_set:\n                    self._event.clear()\n                    # maybe there is something to send\n                    msgs = []\n                    while True:\n                        try:\n                            msgs.append(self._send_queue.get(block=False))\n                        except gevent.queue.Empty:\n                            break\n                    for msg in msgs:\n                        try:\n                            self._send(msg)\n                        except OSError:\n                            self.close()\n                            return None\n                # maybe there is something to receive, if not, at least\n                # ensure uWSGI does its ping/ponging\n                while True:\n                    try:\n                        msg = uwsgi.websocket_recv_nb()\n                    except OSError:  # connection closed\n                        self.close()\n                        return None\n                    if msg:  # message available\n                        self.received_messages.append(\n                            self._decode_received(msg))\n                    else:\n                        break\n                if self.received_messages:\n                    return self.received_messages.pop(0)\n\n\n_async = {\n    'thread': Thread,\n    'queue': queue.JoinableQueue,\n    'queue_empty': queue.Empty,\n    'event': Event,\n    'websocket': uWSGIWebSocket if _websocket_available else None,\n    'sleep': gevent.sleep,\n}\n"
  },
  {
    "path": "src/engineio/async_drivers/sanic.py",
    "content": "import sys\nfrom urllib.parse import urlsplit\n\ntry:  # pragma: no cover\n    from sanic.response import HTTPResponse\n    try:\n        from sanic.server.protocols.websocket_protocol import WebSocketProtocol\n    except ImportError:\n        from sanic.websocket import WebSocketProtocol\nexcept ImportError:\n    HTTPResponse = None\n    WebSocketProtocol = None\n\n\ndef create_route(app, engineio_server, engineio_endpoint):  # pragma: no cover\n    \"\"\"This function sets up the engine.io endpoint as a route for the\n    application.\n\n    Note that both GET and POST requests must be hooked up on the engine.io\n    endpoint.\n    \"\"\"\n    app.add_route(engineio_server.handle_request, engineio_endpoint,\n                  methods=['GET', 'POST', 'OPTIONS'])\n    try:\n        app.enable_websocket()\n    except AttributeError:\n        # ignore, this version does not support websocket\n        pass\n\n\ndef translate_request(request):  # pragma: no cover\n    \"\"\"This function takes the arguments passed to the request handler and\n    uses them to generate a WSGI compatible environ dictionary.\n    \"\"\"\n    class AwaitablePayload:\n        def __init__(self, payload):\n            self.payload = payload or b''\n\n        async def read(self, length=None):\n            if length is None:\n                r = self.payload\n                self.payload = b''\n            else:\n                r = self.payload[:length]\n                self.payload = self.payload[length:]\n            return r\n\n    uri_parts = urlsplit(request.url)\n    environ = {\n        'wsgi.input': AwaitablePayload(request.body),\n        'wsgi.errors': sys.stderr,\n        'wsgi.version': (1, 0),\n        'wsgi.async': True,\n        'wsgi.multithread': False,\n        'wsgi.multiprocess': False,\n        'wsgi.run_once': False,\n        'SERVER_SOFTWARE': 'sanic',\n        'REQUEST_METHOD': request.method,\n        'QUERY_STRING': uri_parts.query or '',\n        'RAW_URI': request.url,\n        'SERVER_PROTOCOL': 'HTTP/' + request.version,\n        'REMOTE_ADDR': '127.0.0.1',\n        'REMOTE_PORT': '0',\n        'SERVER_NAME': 'sanic',\n        'SERVER_PORT': '0',\n        'sanic.request': request\n    }\n\n    for hdr_name, hdr_value in request.headers.items():\n        hdr_name = hdr_name.upper()\n        if hdr_name == 'CONTENT-TYPE':\n            environ['CONTENT_TYPE'] = hdr_value\n            continue\n        elif hdr_name == 'CONTENT-LENGTH':\n            environ['CONTENT_LENGTH'] = hdr_value\n            continue\n\n        key = 'HTTP_%s' % hdr_name.replace('-', '_')\n        if key in environ:\n            hdr_value = f'{environ[key]},{hdr_value}'\n\n        environ[key] = hdr_value\n\n    environ['wsgi.url_scheme'] = environ.get('HTTP_X_FORWARDED_PROTO', 'http')\n\n    path_info = uri_parts.path\n\n    environ['PATH_INFO'] = path_info\n    environ['SCRIPT_NAME'] = ''\n\n    return environ\n\n\ndef make_response(status, headers, payload, environ):  # pragma: no cover\n    \"\"\"This function generates an appropriate response object for this async\n    mode.\n    \"\"\"\n    headers_dict = {}\n    content_type = None\n    for h in headers:\n        if h[0].lower() == 'content-type':\n            content_type = h[1]\n        else:\n            headers_dict[h[0]] = h[1]\n    return HTTPResponse(body=payload, content_type=content_type,\n                        status=int(status.split()[0]), headers=headers_dict)\n\n\nclass WebSocket:  # pragma: no cover\n    \"\"\"\n    This wrapper class provides a sanic WebSocket interface that is\n    somewhat compatible with eventlet's implementation.\n    \"\"\"\n    def __init__(self, handler, server):\n        self.handler = handler\n        self.server = server\n        self._sock = None\n\n    async def __call__(self, environ):\n        request = environ['sanic.request']\n        protocol = request.transport.get_protocol()\n        self._sock = await protocol.websocket_handshake(request)\n\n        self.environ = environ\n        await self.handler(self)\n        return self.server._ok()\n\n    async def close(self):\n        await self._sock.close()\n\n    async def send(self, message):\n        await self._sock.send(message)\n\n    async def wait(self):\n        data = await self._sock.recv()\n        if not isinstance(data, bytes) and \\\n                not isinstance(data, str):\n            raise OSError()\n        return data\n\n\n_async = {\n    'asyncio': True,\n    'create_route': create_route,\n    'translate_request': translate_request,\n    'make_response': make_response,\n    'websocket': WebSocket if WebSocketProtocol else None,\n}\n"
  },
  {
    "path": "src/engineio/async_drivers/threading.py",
    "content": "import queue\nimport threading\nimport time\nfrom engineio.async_drivers._websocket_wsgi import SimpleWebSocketWSGI\n\n\nclass DaemonThread(threading.Thread):  # pragma: no cover\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs, daemon=True)\n\n\n_async = {\n    'thread': DaemonThread,\n    'queue': queue.Queue,\n    'queue_empty': queue.Empty,\n    'event': threading.Event,\n    'websocket': SimpleWebSocketWSGI,\n    'sleep': time.sleep,\n}\n"
  },
  {
    "path": "src/engineio/async_drivers/tornado.py",
    "content": "import asyncio\nimport inspect\nimport sys\nfrom urllib.parse import urlsplit\nfrom .. import exceptions\n\nimport tornado.web\nimport tornado.websocket\n\n\ndef get_tornado_handler(engineio_server):\n    class Handler(tornado.websocket.WebSocketHandler):  # pragma: no cover\n        def __init__(self, *args, **kwargs):\n            super().__init__(*args, **kwargs)\n            if isinstance(engineio_server.cors_allowed_origins, str):\n                if engineio_server.cors_allowed_origins == '*':\n                    self.allowed_origins = None\n                else:\n                    self.allowed_origins = [\n                        engineio_server.cors_allowed_origins]\n            else:\n                self.allowed_origins = engineio_server.cors_allowed_origins\n            self.receive_queue = asyncio.Queue()\n\n        async def get(self, *args, **kwargs):\n            if self.request.headers.get('Upgrade', '').lower() == 'websocket':\n                ret = super().get(*args, **kwargs)\n                if inspect.iscoroutine(ret):\n                    await ret\n            else:\n                await engineio_server.handle_request(self)\n\n        async def open(self, *args, **kwargs):\n            # this is the handler for the websocket request\n            asyncio.ensure_future(engineio_server.handle_request(self))\n\n        async def post(self, *args, **kwargs):\n            await engineio_server.handle_request(self)\n\n        async def options(self, *args, **kwargs):\n            await engineio_server.handle_request(self)\n\n        async def on_message(self, message):\n            await self.receive_queue.put(message)\n\n        async def get_next_message(self):\n            return await self.receive_queue.get()\n\n        def on_close(self):\n            self.receive_queue.put_nowait(None)\n\n        def check_origin(self, origin):\n            if self.allowed_origins is None or origin in self.allowed_origins:\n                return True\n            return super().check_origin(origin)\n\n        def get_compression_options(self):\n            # enable compression\n            return {}\n\n    return Handler\n\n\ndef translate_request(handler):\n    \"\"\"This function takes the arguments passed to the request handler and\n    uses them to generate a WSGI compatible environ dictionary.\n    \"\"\"\n    class AwaitablePayload:\n        def __init__(self, payload):\n            self.payload = payload or b''\n\n        async def read(self, length=None):\n            if length is None:\n                r = self.payload\n                self.payload = b''\n            else:\n                r = self.payload[:length]\n                self.payload = self.payload[length:]\n            return r\n\n    payload = handler.request.body\n\n    uri_parts = urlsplit(handler.request.path)\n    full_uri = handler.request.path\n    if handler.request.query:  # pragma: no cover\n        full_uri += '?' + handler.request.query\n    environ = {\n        'wsgi.input': AwaitablePayload(payload),\n        'wsgi.errors': sys.stderr,\n        'wsgi.version': (1, 0),\n        'wsgi.async': True,\n        'wsgi.multithread': False,\n        'wsgi.multiprocess': False,\n        'wsgi.run_once': False,\n        'SERVER_SOFTWARE': 'aiohttp',\n        'REQUEST_METHOD': handler.request.method,\n        'QUERY_STRING': handler.request.query or '',\n        'RAW_URI': full_uri,\n        'SERVER_PROTOCOL': 'HTTP/%s' % handler.request.version,\n        'REMOTE_ADDR': '127.0.0.1',\n        'REMOTE_PORT': '0',\n        'SERVER_NAME': 'aiohttp',\n        'SERVER_PORT': '0',\n        'tornado.handler': handler\n    }\n\n    for hdr_name, hdr_value in handler.request.headers.items():\n        hdr_name = hdr_name.upper()\n        if hdr_name == 'CONTENT-TYPE':\n            environ['CONTENT_TYPE'] = hdr_value\n            continue\n        elif hdr_name == 'CONTENT-LENGTH':\n            environ['CONTENT_LENGTH'] = hdr_value\n            continue\n\n        key = 'HTTP_%s' % hdr_name.replace('-', '_')\n        environ[key] = hdr_value\n\n    environ['wsgi.url_scheme'] = environ.get('HTTP_X_FORWARDED_PROTO', 'http')\n\n    path_info = uri_parts.path\n\n    environ['PATH_INFO'] = path_info\n    environ['SCRIPT_NAME'] = ''\n\n    return environ\n\n\ndef make_response(status, headers, payload, environ):\n    \"\"\"This function generates an appropriate response object for this async\n    mode.\n    \"\"\"\n    tornado_handler = environ['tornado.handler']\n    try:\n        tornado_handler.set_status(int(status.split()[0]))\n    except RuntimeError:  # pragma: no cover\n        # for websocket connections Tornado does not accept a response, since\n        # it already emitted the 101 status code\n        return\n    for header, value in headers:\n        tornado_handler.set_header(header, value)\n    tornado_handler.write(payload)\n    tornado_handler.finish()\n\n\nclass WebSocket:  # pragma: no cover\n    \"\"\"\n    This wrapper class provides a tornado WebSocket interface that is\n    somewhat compatible with eventlet's implementation.\n    \"\"\"\n    def __init__(self, handler, server):\n        self.handler = handler\n        self.tornado_handler = None\n\n    async def __call__(self, environ):\n        self.tornado_handler = environ['tornado.handler']\n        self.environ = environ\n        await self.handler(self)\n\n    async def close(self):\n        self.tornado_handler.close()\n\n    async def send(self, message):\n        try:\n            self.tornado_handler.write_message(\n                message, binary=isinstance(message, bytes))\n        except tornado.websocket.WebSocketClosedError:\n            raise exceptions.EngineIOError()\n\n    async def wait(self):\n        msg = await self.tornado_handler.get_next_message()\n        if not isinstance(msg, bytes) and \\\n                not isinstance(msg, str):\n            raise OSError()\n        return msg\n\n\n_async = {\n    'asyncio': True,\n    'translate_request': translate_request,\n    'make_response': make_response,\n    'websocket': WebSocket,\n}\n"
  },
  {
    "path": "src/engineio/async_server.py",
    "content": "import asyncio\nimport inspect\nimport urllib\n\nfrom . import base_server\nfrom . import exceptions\nfrom . import packet\nfrom . import async_socket\n\n# this set is used to keep references to background tasks to prevent them from\n# being garbage collected mid-execution. Solution taken from\n# https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task\ntask_reference_holder = set()\n\n\nclass AsyncServer(base_server.BaseServer):\n    \"\"\"An Engine.IO server for asyncio.\n\n    This class implements a fully compliant Engine.IO web server with support\n    for websocket and long-polling transports, compatible with the asyncio\n    framework on Python 3.5 or newer.\n\n    :param async_mode: The asynchronous model to use. See the Deployment\n                       section in the documentation for a description of the\n                       available options. Valid async modes are \"aiohttp\",\n                       \"sanic\", \"tornado\" and \"asgi\". If this argument is not\n                       given, \"aiohttp\" is tried first, followed by \"sanic\",\n                       \"tornado\", and finally \"asgi\". The first async mode that\n                       has all its dependencies installed is the one that is\n                       chosen.\n    :param ping_interval: The interval in seconds at which the server pings\n                          the client. The default is 25 seconds. For advanced\n                          control, a two element tuple can be given, where\n                          the first number is the ping interval and the second\n                          is a grace period added by the server.\n    :param ping_timeout: The time in seconds that the client waits for the\n                         server to respond before disconnecting. The default\n                         is 20 seconds.\n    :param max_http_buffer_size: The maximum size that is accepted for incoming\n                                 messages.  The default is 1,000,000 bytes. In\n                                 spite of its name, the value set in this\n                                 argument is enforced for HTTP long-polling and\n                                 WebSocket connections.\n    :param allow_upgrades: Whether to allow transport upgrades or not.\n    :param http_compression: Whether to compress packages when using the\n                             polling transport.\n    :param compression_threshold: Only compress messages when their byte size\n                                  is greater than this value.\n    :param cookie: If set to a string, it is the name of the HTTP cookie the\n                   server sends back tot he client containing the client\n                   session id. If set to a dictionary, the ``'name'`` key\n                   contains the cookie name and other keys define cookie\n                   attributes, where the value of each attribute can be a\n                   string, a callable with no arguments, or a boolean. If set\n                   to ``None`` (the default), a cookie is not sent to the\n                   client.\n    :param cors_allowed_origins: Origin or list of origins that are allowed to\n                                 connect to this server. Only the same origin\n                                 is allowed by default. Set this argument to\n                                 ``'*'`` or ``['*']`` to allow all origins, or\n                                 to ``[]`` to disable CORS handling.\n    :param cors_credentials: Whether credentials (cookies, authentication) are\n                             allowed in requests to this server.\n    :param logger: To enable logging set to ``True`` or pass a logger object to\n                   use. To disable logging set to ``False``. Note that fatal\n                   errors are logged even when ``logger`` is ``False``.\n    :param json: An alternative JSON module to use for encoding and decoding\n                 packets. Custom JSON modules must have ``dumps`` and ``loads``\n                 functions that are compatible with the standard library\n                 versions. This is a process-wide setting, all instantiated\n                 servers and clients must use the same JSON module.\n    :param async_handlers: If set to ``True``, run message event handlers in\n                           non-blocking threads. To run handlers synchronously,\n                           set to ``False``. The default is ``True``.\n    :param monitor_clients: If set to ``True``, a background task will ensure\n                            inactive clients are closed. Set to ``False`` to\n                            disable the monitoring task (not recommended). The\n                            default is ``True``.\n    :param transports: The list of allowed transports. Valid transports\n                       are ``'polling'`` and ``'websocket'``. Defaults to\n                       ``['polling', 'websocket']``.\n    :param kwargs: Reserved for future extensions, any additional parameters\n                   given as keyword arguments will be silently ignored.\n    \"\"\"\n    def is_asyncio_based(self):\n        return True\n\n    def async_modes(self):\n        return ['aiohttp', 'sanic', 'tornado', 'asgi']\n\n    def attach(self, app, engineio_path='engine.io'):\n        \"\"\"Attach the Engine.IO server to an application.\"\"\"\n        engineio_path = engineio_path.strip('/')\n        self._async['create_route'](app, self, f'/{engineio_path}/')\n\n    async def send(self, sid, data):\n        \"\"\"Send a message to a client.\n\n        :param sid: The session id of the recipient client.\n        :param data: The data to send to the client. Data can be of type\n                     ``str``, ``bytes``, ``list`` or ``dict``. If a ``list``\n                     or ``dict``, the data will be serialized as JSON.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        await self.send_packet(sid, packet.Packet(packet.MESSAGE, data=data))\n\n    async def send_packet(self, sid, pkt):\n        \"\"\"Send a raw packet to a client.\n\n        :param sid: The session id of the recipient client.\n        :param pkt: The packet to send to the client.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        try:\n            socket = self._get_socket(sid)\n        except KeyError:\n            # the socket is not available\n            self.logger.warning('Cannot send to sid %s', sid)\n            return\n        await socket.send(pkt)\n\n    async def get_session(self, sid):\n        \"\"\"Return the user session for a client.\n\n        :param sid: The session id of the client.\n\n        The return value is a dictionary. Modifications made to this\n        dictionary are not guaranteed to be preserved. If you want to modify\n        the user session, use the ``session`` context manager instead.\n        \"\"\"\n        socket = self._get_socket(sid)\n        return socket.session\n\n    async def save_session(self, sid, session):\n        \"\"\"Store the user session for a client.\n\n        :param sid: The session id of the client.\n        :param session: The session dictionary.\n        \"\"\"\n        socket = self._get_socket(sid)\n        socket.session = session\n\n    def session(self, sid):\n        \"\"\"Return the user session for a client with context manager syntax.\n\n        :param sid: The session id of the client.\n\n        This is a context manager that returns the user session dictionary for\n        the client. Any changes that are made to this dictionary inside the\n        context manager block are saved back to the session. Example usage::\n\n            @eio.on('connect')\n            def on_connect(sid, environ):\n                username = authenticate_user(environ)\n                if not username:\n                    return False\n                with eio.session(sid) as session:\n                    session['username'] = username\n\n            @eio.on('message')\n            def on_message(sid, msg):\n                async with eio.session(sid) as session:\n                    print('received message from ', session['username'])\n        \"\"\"\n        class _session_context_manager:\n            def __init__(self, server, sid):\n                self.server = server\n                self.sid = sid\n                self.session = None\n\n            async def __aenter__(self):\n                self.session = await self.server.get_session(sid)\n                return self.session\n\n            async def __aexit__(self, *args):\n                await self.server.save_session(sid, self.session)\n\n        return _session_context_manager(self, sid)\n\n    async def disconnect(self, sid=None):\n        \"\"\"Disconnect a client.\n\n        :param sid: The session id of the client to close. If this parameter\n                    is not given, then all clients are closed.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        if sid is not None:\n            try:\n                socket = self._get_socket(sid)\n            except KeyError:  # pragma: no cover\n                # the socket was already closed or gone\n                pass\n            else:\n                await socket.close(reason=self.reason.SERVER_DISCONNECT)\n                if sid in self.sockets:  # pragma: no cover\n                    del self.sockets[sid]\n        else:\n            await asyncio.wait([\n                asyncio.create_task(client.close(\n                    reason=self.reason.SERVER_DISCONNECT))\n                for client in self.sockets.values()\n            ])\n            self.sockets = {}\n\n    async def handle_request(self, *args, **kwargs):\n        \"\"\"Handle an HTTP request from the client.\n\n        This is the entry point of the Engine.IO application. This function\n        returns the HTTP response to deliver to the client.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        translate_request = self._async['translate_request']\n        if inspect.iscoroutinefunction(translate_request):\n            environ = await translate_request(*args, **kwargs)\n        else:\n            environ = translate_request(*args, **kwargs)\n\n        if self.cors_allowed_origins != []:\n            # Validate the origin header if present\n            # This is important for WebSocket more than for HTTP, since\n            # browsers only apply CORS controls to HTTP.\n            origin = environ.get('HTTP_ORIGIN')\n            if origin:\n                allowed_origins = self._cors_allowed_origins(environ)\n                if allowed_origins is not None and origin not in \\\n                        allowed_origins:\n                    self._log_error_once(\n                        origin + ' is not an accepted origin.', 'bad-origin')\n                    return await self._make_response(\n                        self._bad_request(\n                            origin + ' is not an accepted origin.'),\n                        environ)\n\n        method = environ['REQUEST_METHOD']\n        query = urllib.parse.parse_qs(environ.get('QUERY_STRING', ''))\n\n        sid = query['sid'][0] if 'sid' in query else None\n        jsonp = False\n        jsonp_index = None\n\n        # make sure the client uses an allowed transport\n        transport = query.get('transport', ['polling'])[0]\n        if transport not in self.transports:\n            self._log_error_once('Invalid transport', 'bad-transport')\n            return await self._make_response(\n                self._bad_request('Invalid transport'), environ)\n\n        # make sure the client speaks a compatible Engine.IO version\n        sid = query['sid'][0] if 'sid' in query else None\n        if sid is None and query.get('EIO') != ['4']:\n            self._log_error_once(\n                'The client is using an unsupported version of the Socket.IO '\n                'or Engine.IO protocols', 'bad-version'\n            )\n            return await self._make_response(self._bad_request(\n                'The client is using an unsupported version of the Socket.IO '\n                'or Engine.IO protocols'\n            ), environ)\n\n        if 'j' in query:\n            jsonp = True\n            try:\n                jsonp_index = int(query['j'][0])\n            except (ValueError, KeyError, IndexError):\n                # Invalid JSONP index number\n                pass\n\n        if jsonp and jsonp_index is None:\n            self._log_error_once('Invalid JSONP index number',\n                                 'bad-jsonp-index')\n            r = self._bad_request('Invalid JSONP index number')\n        elif method == 'GET':\n            upgrade_header = environ.get('HTTP_UPGRADE').lower() \\\n                if 'HTTP_UPGRADE' in environ else None\n            if sid is None:\n                # transport must be one of 'polling' or 'websocket'.\n                # if 'websocket', the HTTP_UPGRADE header must match.\n                if transport == 'polling' \\\n                        or transport == upgrade_header == 'websocket':\n                    r = await self._handle_connect(environ, transport,\n                                                   jsonp_index)\n                else:\n                    self._log_error_once('Invalid websocket upgrade',\n                                         'bad-upgrade')\n                    r = self._bad_request('Invalid websocket upgrade')\n            else:\n                if sid not in self.sockets:\n                    self._log_error_once(f'Invalid session {sid}', 'bad-sid')\n                    r = self._bad_request(f'Invalid session {sid}')\n                else:\n                    try:\n                        socket = self._get_socket(sid)\n                    except KeyError as e:  # pragma: no cover\n                        self._log_error_once(f'{e} {sid}', 'bad-sid')\n                        r = self._bad_request(f'{e} {sid}')\n                    else:\n                        if self.transport(sid) != transport and \\\n                                transport != upgrade_header:\n                            self._log_error_once(\n                                f'Invalid transport for session {sid}',\n                                'bad-transport')\n                            r = self._bad_request('Invalid transport')\n                        else:\n                            try:\n                                packets = await socket.handle_get_request(\n                                    environ)\n                                if isinstance(packets, list):\n                                    r = self._ok(packets,\n                                                 jsonp_index=jsonp_index)\n                                else:\n                                    r = packets\n                            except exceptions.EngineIOError:\n                                if sid in self.sockets:  # pragma: no cover\n                                    await self.disconnect(sid)\n                                r = self._bad_request()\n                            if sid in self.sockets and \\\n                                    self.sockets[sid].closed:\n                                del self.sockets[sid]\n        elif method == 'POST':\n            if sid is None or sid not in self.sockets:\n                self._log_error_once(f'Invalid session {sid}', 'bad-sid')\n                r = self._bad_request(f'Invalid session {sid}')\n            else:\n                socket = self._get_socket(sid)\n                try:\n                    await socket.handle_post_request(environ)\n                    r = self._ok(jsonp_index=jsonp_index)\n                except exceptions.EngineIOError:\n                    if sid in self.sockets:  # pragma: no cover\n                        await self.disconnect(sid)\n                    r = self._bad_request()\n                except:  # pragma: no cover\n                    # for any other unexpected errors, we log the error\n                    # and keep going\n                    self.logger.exception('post request handler error')\n                    r = self._ok(jsonp_index=jsonp_index)\n        elif method == 'OPTIONS':\n            r = self._ok()\n        else:\n            self.logger.warning('Method %s not supported', method)\n            r = self._method_not_found()\n        if not isinstance(r, dict):\n            return r\n        if self.http_compression and \\\n                len(r['response']) >= self.compression_threshold:\n            encodings = [e.split(';')[0].strip() for e in\n                         environ.get('HTTP_ACCEPT_ENCODING', '').split(',')]\n            for encoding in encodings:\n                if encoding in self.compression_methods:\n                    r['response'] = \\\n                        getattr(self, '_' + encoding)(r['response'])\n                    r['headers'] += [('Content-Encoding', encoding)]\n                    break\n        return await self._make_response(r, environ)\n\n    async def shutdown(self):\n        \"\"\"Stop Socket.IO background tasks.\n\n        This method stops background activity initiated by the Socket.IO\n        server. It must be called before shutting down the web server.\n        \"\"\"\n        self.logger.info('Socket.IO is shutting down')\n        if self.service_task_event:  # pragma: no cover\n            self.service_task_event.set()\n            await self.service_task_handle\n            self.service_task_handle = None\n\n    def start_background_task(self, target, *args, **kwargs):\n        \"\"\"Start a background task using the appropriate async model.\n\n        This is a utility function that applications can use to start a\n        background task using the method that is compatible with the\n        selected async mode.\n\n        :param target: the target function to execute.\n        :param args: arguments to pass to the function.\n        :param kwargs: keyword arguments to pass to the function.\n\n        The return value is a ``asyncio.Task`` object.\n        \"\"\"\n        return asyncio.ensure_future(target(*args, **kwargs))\n\n    async def sleep(self, seconds=0):\n        \"\"\"Sleep for the requested amount of time using the appropriate async\n        model.\n\n        This is a utility function that applications can use to put a task to\n        sleep without having to worry about using the correct call for the\n        selected async mode.\n\n        Note: this method is a coroutine.\n        \"\"\"\n        return await asyncio.sleep(seconds)\n\n    def create_queue(self, *args, **kwargs):\n        \"\"\"Create a queue object using the appropriate async model.\n\n        This is a utility function that applications can use to create a queue\n        without having to worry about using the correct call for the selected\n        async mode. For asyncio based async modes, this returns an instance of\n        ``asyncio.Queue``.\n        \"\"\"\n        return asyncio.Queue(*args, **kwargs)\n\n    def get_queue_empty_exception(self):\n        \"\"\"Return the queue empty exception for the appropriate async model.\n\n        This is a utility function that applications can use to work with a\n        queue without having to worry about using the correct call for the\n        selected async mode. For asyncio based async modes, this returns an\n        instance of ``asyncio.QueueEmpty``.\n        \"\"\"\n        return asyncio.QueueEmpty\n\n    def create_event(self, *args, **kwargs):\n        \"\"\"Create an event object using the appropriate async model.\n\n        This is a utility function that applications can use to create an\n        event without having to worry about using the correct call for the\n        selected async mode. For asyncio based async modes, this returns\n        an instance of ``asyncio.Event``.\n        \"\"\"\n        return asyncio.Event(*args, **kwargs)\n\n    async def _make_response(self, response_dict, environ):\n        cors_headers = self._cors_headers(environ)\n        make_response = self._async['make_response']\n        if inspect.iscoroutinefunction(make_response):\n            response = await make_response(\n                response_dict['status'],\n                response_dict['headers'] + cors_headers,\n                response_dict['response'], environ)\n        else:\n            response = make_response(\n                response_dict['status'],\n                response_dict['headers'] + cors_headers,\n                response_dict['response'], environ)\n        return response\n\n    async def _handle_connect(self, environ, transport, jsonp_index=None):\n        \"\"\"Handle a client connection request.\"\"\"\n        if self.start_service_task:\n            # start the service task to monitor connected clients\n            self.start_service_task = False\n            self.service_task_handle = self.start_background_task(\n                self._service_task)\n\n        sid = self.generate_id()\n        s = async_socket.AsyncSocket(self, sid)\n        self.sockets[sid] = s\n\n        pkt = packet.Packet(packet.OPEN, {\n            'sid': sid,\n            'upgrades': self._upgrades(sid, transport),\n            'pingTimeout': int(self.ping_timeout * 1000),\n            'pingInterval': int(\n                self.ping_interval + self.ping_interval_grace_period) * 1000,\n            'maxPayload': self.max_http_buffer_size,\n        })\n        await s.send(pkt)\n        s.schedule_ping()\n\n        ret = await self._trigger_event('connect', sid, environ,\n                                        run_async=False)\n        if ret is not None and ret is not True:\n            del self.sockets[sid]\n            self.logger.warning('Application rejected connection')\n            return self._unauthorized(ret or None)\n\n        if transport == 'websocket':\n            ret = await s.handle_get_request(environ)\n            if s.closed and sid in self.sockets:\n                # websocket connection ended, so we are done\n                del self.sockets[sid]\n            return ret\n        else:\n            s.connected = True\n            headers = None\n            if self.cookie:\n                if isinstance(self.cookie, dict):\n                    headers = [(\n                        'Set-Cookie',\n                        self._generate_sid_cookie(sid, self.cookie)\n                    )]\n                else:\n                    headers = [(\n                        'Set-Cookie',\n                        self._generate_sid_cookie(sid, {\n                            'name': self.cookie, 'path': '/', 'SameSite': 'Lax'\n                        })\n                    )]\n            try:\n                return self._ok(await s.poll(), headers=headers,\n                                jsonp_index=jsonp_index)\n            except exceptions.QueueEmpty:\n                return self._bad_request()\n\n    async def _trigger_event(self, event, *args, **kwargs):\n        \"\"\"Invoke an event handler.\"\"\"\n        run_async = kwargs.pop('run_async', False)\n        ret = None\n        if event in self.handlers:\n            if inspect.iscoroutinefunction(self.handlers[event]):\n                async def run_async_handler():\n                    try:\n                        try:\n                            return await self.handlers[event](*args)\n                        except TypeError:\n                            if event == 'disconnect' and \\\n                                    len(args) == 2:  # pragma: no branch\n                                # legacy disconnect events do not have a reason\n                                # argument\n                                return await self.handlers[event](args[0])\n                            else:  # pragma: no cover\n                                raise\n                    except asyncio.CancelledError:  # pragma: no cover\n                        pass\n                    except:\n                        self.logger.exception(event + ' async handler error')\n                        if event == 'connect':\n                            # if connect handler raised error we reject the\n                            # connection\n                            return False\n\n                if run_async:\n                    ret = self.start_background_task(run_async_handler)\n                    task_reference_holder.add(ret)\n                    ret.add_done_callback(task_reference_holder.discard)\n                else:\n                    ret = await run_async_handler()\n            else:\n                async def run_sync_handler():\n                    try:\n                        try:\n                            return self.handlers[event](*args)\n                        except TypeError:\n                            if event == 'disconnect' and \\\n                                    len(args) == 2:  # pragma: no branch\n                                # legacy disconnect events do not have a reason\n                                # argument\n                                return self.handlers[event](args[0])\n                            else:  # pragma: no cover\n                                raise\n                    except:\n                        self.logger.exception(event + ' handler error')\n                        if event == 'connect':\n                            # if connect handler raised error we reject the\n                            # connection\n                            return False\n\n                if run_async:\n                    ret = self.start_background_task(run_sync_handler)\n                    task_reference_holder.add(ret)\n                    ret.add_done_callback(task_reference_holder.discard)\n                else:\n                    ret = await run_sync_handler()\n        return ret\n\n    async def _service_task(self):  # pragma: no cover\n        \"\"\"Monitor connected clients and clean up those that time out.\"\"\"\n        loop = asyncio.get_running_loop()\n        self.service_task_event = self.create_event()\n        while not self.service_task_event.is_set():\n            if len(self.sockets) == 0:\n                # nothing to do\n                try:\n                    await asyncio.wait_for(self.service_task_event.wait(),\n                                           timeout=self.ping_timeout)\n                    break\n                except asyncio.TimeoutError:\n                    continue\n\n            # go through the entire client list in a ping interval cycle\n            sleep_interval = self.ping_timeout / len(self.sockets)\n\n            try:\n                # iterate over the current clients\n                for s in self.sockets.copy().values():\n                    if s.closed:\n                        try:\n                            del self.sockets[s.sid]\n                        except KeyError:\n                            # the socket could have also been removed by\n                            # the _get_socket() method from another thread\n                            pass\n                    elif not s.closing:\n                        await s.check_ping_timeout()\n                    try:\n                        await asyncio.wait_for(self.service_task_event.wait(),\n                                               timeout=sleep_interval)\n                        raise KeyboardInterrupt()\n                    except asyncio.TimeoutError:\n                        continue\n            except (\n                SystemExit,\n                KeyboardInterrupt,\n                asyncio.CancelledError,\n                GeneratorExit,\n            ):\n                self.logger.info('service task canceled')\n                break\n            except:\n                if loop.is_closed():\n                    self.logger.info('event loop is closed, exiting service '\n                                     'task')\n                    break\n\n                # an unexpected exception has occurred, log it and continue\n                self.logger.exception('service task exception')\n"
  },
  {
    "path": "src/engineio/async_socket.py",
    "content": "import asyncio\nimport sys\nimport time\n\nfrom . import base_socket\nfrom . import exceptions\nfrom . import packet\nfrom . import payload\n\n\nclass AsyncSocket(base_socket.BaseSocket):\n    async def poll(self):\n        \"\"\"Wait for packets to send to the client.\"\"\"\n        try:\n            packets = [await asyncio.wait_for(\n                self.queue.get(),\n                self.server.ping_interval + self.server.ping_timeout)]\n            self.queue.task_done()\n        except (asyncio.TimeoutError, asyncio.CancelledError):\n            raise exceptions.QueueEmpty()\n        if packets == [None]:\n            return []\n        while True:\n            try:\n                pkt = self.queue.get_nowait()\n                self.queue.task_done()\n                if pkt is None:\n                    self.queue.put_nowait(None)\n                    break\n                packets.append(pkt)\n            except asyncio.QueueEmpty:\n                break\n        return packets\n\n    async def receive(self, pkt):\n        \"\"\"Receive packet from the client.\"\"\"\n        self.server.logger.info('%s: Received packet %s data %s',\n                                self.sid, packet.packet_names[pkt.packet_type],\n                                pkt.data if not isinstance(pkt.data, bytes)\n                                else '<binary>')\n        if pkt.packet_type == packet.PONG:\n            self.schedule_ping()\n        elif pkt.packet_type == packet.MESSAGE:\n            await self.server._trigger_event(\n                'message', self.sid, pkt.data,\n                run_async=self.server.async_handlers)\n        elif pkt.packet_type == packet.UPGRADE:\n            await self.send(packet.Packet(packet.NOOP))\n        elif pkt.packet_type == packet.CLOSE:\n            await self.close(wait=False, abort=True,\n                             reason=self.server.reason.CLIENT_DISCONNECT)\n        else:\n            raise exceptions.UnknownPacketError()\n\n    async def check_ping_timeout(self):\n        \"\"\"Make sure the client is still sending pings.\"\"\"\n        if self.closed:\n            raise exceptions.SocketIsClosedError()\n        if self.last_ping and \\\n                time.time() - self.last_ping > self.server.ping_timeout:\n            self.server.logger.info('%s: Client is gone, closing socket',\n                                    self.sid)\n            # Passing abort=False here will cause close() to write a\n            # CLOSE packet. This has the effect of updating half-open sockets\n            # to their correct state of disconnected\n            await self.close(wait=False, abort=False,\n                             reason=self.server.reason.PING_TIMEOUT)\n            return False\n        return True\n\n    async def send(self, pkt):\n        \"\"\"Send a packet to the client.\"\"\"\n        if not await self.check_ping_timeout():\n            return\n        else:\n            await self.queue.put(pkt)\n        self.server.logger.info('%s: Sending packet %s data %s',\n                                self.sid, packet.packet_names[pkt.packet_type],\n                                pkt.data if not isinstance(pkt.data, bytes)\n                                else '<binary>')\n\n    async def handle_get_request(self, environ):\n        \"\"\"Handle a long-polling GET request from the client.\"\"\"\n        connections = [\n            s.strip()\n            for s in environ.get('HTTP_CONNECTION', '').lower().split(',')]\n        transport = environ.get('HTTP_UPGRADE', '').lower()\n        if 'upgrade' in connections and transport in self.upgrade_protocols:\n            self.server.logger.info('%s: Received request to upgrade to %s',\n                                    self.sid, transport)\n            return await getattr(self, '_upgrade_' + transport)(environ)\n        if self.upgrading or self.upgraded:\n            # we are upgrading to WebSocket, do not return any more packets\n            # through the polling endpoint\n            return [packet.Packet(packet.NOOP)]\n        try:\n            packets = await self.poll()\n        except exceptions.QueueEmpty:\n            exc = sys.exc_info()\n            await self.close(wait=False,\n                             reason=self.server.reason.TRANSPORT_ERROR)\n            raise exc[1].with_traceback(exc[2])\n        return packets\n\n    async def handle_post_request(self, environ):\n        \"\"\"Handle a long-polling POST request from the client.\"\"\"\n        length = int(environ.get('CONTENT_LENGTH', '0'))\n        if length > self.server.max_http_buffer_size:\n            raise exceptions.ContentTooLongError()\n        else:\n            body = (await environ['wsgi.input'].read(length)).decode('utf-8')\n            p = payload.Payload(encoded_payload=body)\n            for pkt in p.packets:\n                await self.receive(pkt)\n\n    async def close(self, wait=True, abort=False, reason=None):\n        \"\"\"Close the socket connection.\"\"\"\n        if not self.closed and not self.closing:\n            self.closing = True\n            await self.server._trigger_event(\n                'disconnect', self.sid,\n                reason or self.server.reason.SERVER_DISCONNECT,\n                run_async=False)\n            if not abort:\n                await self.send(packet.Packet(packet.CLOSE))\n            self.closed = True\n            if wait:\n                await self.queue.join()\n\n    def schedule_ping(self):\n        self.server.start_background_task(self._send_ping)\n\n    async def _send_ping(self):\n        self.last_ping = None\n        await asyncio.sleep(self.server.ping_interval)\n        if not self.closing and not self.closed:\n            self.last_ping = time.time()\n            await self.send(packet.Packet(packet.PING))\n\n    async def _upgrade_websocket(self, environ):\n        \"\"\"Upgrade the connection from polling to websocket.\"\"\"\n        if self.upgraded:\n            raise OSError('Socket has been upgraded already')\n        if self.server._async['websocket'] is None:\n            # the selected async mode does not support websocket\n            return self.server._bad_request()\n        ws = self.server._async['websocket'](\n            self._websocket_handler, self.server)\n        return await ws(environ)\n\n    async def _websocket_handler(self, ws):\n        \"\"\"Engine.IO handler for websocket transport.\"\"\"\n        async def websocket_wait():\n            data = await ws.wait()\n            if data and len(data) > self.server.max_http_buffer_size:\n                raise ValueError('packet is too large')\n            return data\n\n        if self.connected:\n            # the socket was already connected, so this is an upgrade\n            self.upgrading = True  # hold packet sends during the upgrade\n\n            try:\n                pkt = await websocket_wait()\n            except OSError:  # pragma: no cover\n                return\n            decoded_pkt = packet.Packet(encoded_packet=pkt)\n            if decoded_pkt.packet_type != packet.PING or \\\n                    decoded_pkt.data != 'probe':\n                self.server.logger.info(\n                    '%s: Failed websocket upgrade, no PING packet', self.sid)\n                self.upgrading = False\n                return\n            await ws.send(packet.Packet(packet.PONG, data='probe').encode())\n            await self.queue.put(packet.Packet(packet.NOOP))  # end poll\n\n            try:\n                pkt = await websocket_wait()\n            except OSError:  # pragma: no cover\n                self.upgrading = False\n                return\n            decoded_pkt = packet.Packet(encoded_packet=pkt)\n            if decoded_pkt.packet_type != packet.UPGRADE:\n                self.upgraded = False\n                self.server.logger.info(\n                    ('%s: Failed websocket upgrade, expected UPGRADE packet, '\n                     'received %s instead.'),\n                    self.sid, pkt)\n                self.upgrading = False\n                return\n            self.upgraded = True\n            self.upgrading = False\n        else:\n            self.connected = True\n            self.upgraded = True\n\n        # start separate writer thread\n        async def writer():\n            while True:\n                packets = None\n                try:\n                    packets = await self.poll()\n                except exceptions.QueueEmpty:\n                    break\n                if not packets:\n                    # empty packet list returned -> connection closed\n                    break\n                try:\n                    for pkt in packets:\n                        await ws.send(pkt.encode())\n                except:\n                    break\n            await ws.close()\n\n        writer_task = asyncio.ensure_future(writer())\n\n        self.server.logger.info(\n            '%s: Upgrade to websocket successful', self.sid)\n\n        while True:\n            p = None\n            wait_task = asyncio.ensure_future(websocket_wait())\n            try:\n                p = await asyncio.wait_for(\n                    wait_task,\n                    self.server.ping_interval + self.server.ping_timeout)\n            except asyncio.CancelledError:  # pragma: no cover\n                # there is a bug (https://bugs.python.org/issue30508) in\n                # asyncio that causes a \"Task exception never retrieved\" error\n                # to appear when wait_task raises an exception before it gets\n                # cancelled. Calling wait_task.exception() prevents the error\n                # from being issued in Python 3.6, but causes other errors in\n                # other versions, so we run it with all errors suppressed and\n                # hope for the best.\n                try:\n                    wait_task.exception()\n                except:\n                    pass\n                break\n            except:\n                break\n            if p is None:\n                # connection closed by client\n                break\n            pkt = packet.Packet(encoded_packet=p)\n            try:\n                await self.receive(pkt)\n            except exceptions.UnknownPacketError:  # pragma: no cover\n                pass\n            except exceptions.SocketIsClosedError:  # pragma: no cover\n                self.server.logger.info('Receive error -- socket is closed')\n                break\n            except:  # pragma: no cover\n                # if we get an unexpected exception we log the error and exit\n                # the connection properly\n                self.server.logger.exception('Unknown receive error')\n\n        await self.queue.put(None)  # unlock the writer task so it can exit\n        await asyncio.wait_for(writer_task, timeout=None)\n        await self.close(wait=False, abort=True,\n                         reason=self.server.reason.TRANSPORT_CLOSE)\n"
  },
  {
    "path": "src/engineio/base_client.py",
    "content": "import logging\nimport signal\nimport threading\nimport time\nimport urllib\nfrom . import packet\n\ndefault_logger = logging.getLogger('engineio.client')\nconnected_clients = []\n\n\ndef signal_handler(sig, frame):\n    \"\"\"SIGINT handler.\n\n    Disconnect all active clients and then invoke the original signal handler.\n    \"\"\"\n    for client in connected_clients[:]:\n        if not client.is_asyncio_based():\n            client.disconnect()\n    if callable(original_signal_handler):\n        return original_signal_handler(sig, frame)\n    else:  # pragma: no cover\n        # Handle case where no original SIGINT handler was present.\n        return signal.default_int_handler(sig, frame)\n\n\noriginal_signal_handler = None\n\n\nclass BaseClient:\n    event_names = ['connect', 'disconnect', 'message']\n\n    class reason:\n        \"\"\"Disconnection reasons.\"\"\"\n        #: Client-initiated disconnection.\n        CLIENT_DISCONNECT = 'client disconnect'\n        #: Server-initiated disconnection.\n        SERVER_DISCONNECT = 'server disconnect'\n        #: Transport error.\n        TRANSPORT_ERROR = 'transport error'\n\n    def __init__(self, logger=False, json=None, request_timeout=5,\n                 http_session=None, ssl_verify=True, handle_sigint=True,\n                 websocket_extra_options=None, timestamp_requests=True):\n        global original_signal_handler\n        if handle_sigint and original_signal_handler is None and \\\n                threading.current_thread() == threading.main_thread():\n            original_signal_handler = signal.signal(signal.SIGINT,\n                                                    signal_handler)\n        self.handlers = {}\n        self.base_url = None\n        self.transports = None\n        self.current_transport = None\n        self.sid = None\n        self.upgrades = None\n        self.ping_interval = None\n        self.ping_timeout = None\n        self.http = http_session\n        self.external_http = http_session is not None\n        self.handle_sigint = handle_sigint\n        self.ws = None\n        self.read_loop_task = None\n        self.write_loop_task = None\n        self.queue = self.create_queue()\n        self.queue_empty = self.get_queue_empty_exception()\n        self.state = 'disconnected'\n        self.ssl_verify = ssl_verify\n        self.websocket_extra_options = websocket_extra_options or {}\n        self.timestamp_requests = timestamp_requests\n\n        if json is not None:\n            packet.Packet.json = json\n        if not isinstance(logger, bool):\n            self.logger = logger\n        else:\n            self.logger = default_logger\n            if self.logger.level == logging.NOTSET:\n                if logger:\n                    self.logger.setLevel(logging.INFO)\n                else:\n                    self.logger.setLevel(logging.ERROR)\n                self.logger.addHandler(logging.StreamHandler())\n\n        self.request_timeout = request_timeout\n\n    def is_asyncio_based(self):\n        return False\n\n    def on(self, event, handler=None):\n        \"\"\"Register an event handler.\n\n        :param event: The event name. Can be ``'connect'``, ``'message'`` or\n                      ``'disconnect'``.\n        :param handler: The function that should be invoked to handle the\n                        event. When this parameter is not given, the method\n                        acts as a decorator for the handler function.\n\n        Example usage::\n\n            # as a decorator:\n            @eio.on('connect')\n            def connect_handler():\n                print('Connection request')\n\n            # as a method:\n            def message_handler(msg):\n                print('Received message: ', msg)\n                eio.send('response')\n            eio.on('message', message_handler)\n        \"\"\"\n        if event not in self.event_names:\n            raise ValueError('Invalid event')\n\n        def set_handler(handler):\n            self.handlers[event] = handler\n            return handler\n\n        if handler is None:\n            return set_handler\n        set_handler(handler)\n\n    def transport(self):\n        \"\"\"Return the name of the transport currently in use.\n\n        The possible values returned by this function are ``'polling'`` and\n        ``'websocket'``.\n        \"\"\"\n        return self.current_transport\n\n    def _reset(self):\n        self.state = 'disconnected'\n        self.sid = None\n\n    def _get_engineio_url(self, url, engineio_path, transport):\n        \"\"\"Generate the Engine.IO connection URL.\"\"\"\n        engineio_path = engineio_path.strip('/')\n        parsed_url = urllib.parse.urlparse(url)\n\n        if transport == 'polling':\n            scheme = 'http'\n        elif transport == 'websocket':\n            scheme = 'ws'\n        else:  # pragma: no cover\n            raise ValueError('invalid transport')\n        if parsed_url.scheme in ['https', 'wss']:\n            scheme += 's'\n\n        return ('{scheme}://{netloc}/{path}/?{query}'\n                '{sep}transport={transport}&EIO=4').format(\n                    scheme=scheme, netloc=parsed_url.netloc,\n                    path=engineio_path, query=parsed_url.query,\n                    sep='&' if parsed_url.query else '',\n                    transport=transport)\n\n    def _get_url_timestamp(self):\n        \"\"\"Generate the Engine.IO query string timestamp.\"\"\"\n        if not self.timestamp_requests:\n            return ''\n        return '&t=' + str(time.time())\n\n    def create_queue(self, *args, **kwargs):  # pragma: no cover\n        \"\"\"Create a queue object.\"\"\"\n        raise NotImplementedError('must be implemented in a subclass')\n\n    def get_queue_empty_exception(self):  # pragma: no cover\n        \"\"\"Return the queue empty exception raised by queues created by the\n        ``create_queue()`` method.\n        \"\"\"\n        raise NotImplementedError('must be implemented in a subclass')\n"
  },
  {
    "path": "src/engineio/base_server.py",
    "content": "import base64\nimport gzip\nimport importlib\nimport io\nimport logging\nimport secrets\nimport zlib\n\nfrom . import packet\nfrom . import payload\n\ndefault_logger = logging.getLogger('engineio.server')\n\n\nclass BaseServer:\n    compression_methods = ['gzip', 'deflate']\n    event_names = ['connect', 'disconnect', 'message']\n    valid_transports = ['polling', 'websocket']\n    _default_monitor_clients = True\n    sequence_number = 0\n\n    class reason:\n        \"\"\"Disconnection reasons.\"\"\"\n        #: Server-initiated disconnection.\n        SERVER_DISCONNECT = 'server disconnect'\n        #: Client-initiated disconnection.\n        CLIENT_DISCONNECT = 'client disconnect'\n        #: Ping timeout.\n        PING_TIMEOUT = 'ping timeout'\n        #: Transport close.\n        TRANSPORT_CLOSE = 'transport close'\n        #: Transport error.\n        TRANSPORT_ERROR = 'transport error'\n\n    def __init__(self, async_mode=None, ping_interval=25, ping_timeout=20,\n                 max_http_buffer_size=1000000, allow_upgrades=True,\n                 http_compression=True, compression_threshold=1024,\n                 cookie=None, cors_allowed_origins=None,\n                 cors_credentials=True, logger=False, json=None,\n                 async_handlers=True, monitor_clients=None, transports=None,\n                 **kwargs):\n        self.ping_timeout = ping_timeout\n        if isinstance(ping_interval, tuple):\n            self.ping_interval = ping_interval[0]\n            self.ping_interval_grace_period = ping_interval[1]\n        else:\n            self.ping_interval = ping_interval\n            self.ping_interval_grace_period = 0\n        self.max_http_buffer_size = max_http_buffer_size\n        self.allow_upgrades = allow_upgrades\n        self.http_compression = http_compression\n        self.compression_threshold = compression_threshold\n        self.cookie = cookie\n        self.cors_allowed_origins = cors_allowed_origins\n        self.cors_credentials = cors_credentials\n        self.async_handlers = async_handlers\n        self.sockets = {}\n        self.handlers = {}\n        self.log_message_keys = set()\n        self.start_service_task = monitor_clients \\\n            if monitor_clients is not None else self._default_monitor_clients\n        self.service_task_handle = None\n        self.service_task_event = None\n        if json is not None:\n            packet.Packet.json = json\n        if not isinstance(logger, bool):\n            self.logger = logger\n        else:\n            self.logger = default_logger\n            if self.logger.level == logging.NOTSET:\n                if logger:\n                    self.logger.setLevel(logging.INFO)\n                else:\n                    self.logger.setLevel(logging.ERROR)\n                self.logger.addHandler(logging.StreamHandler())\n        modes = self.async_modes()\n        if async_mode is not None:\n            modes = [async_mode] if async_mode in modes else []\n        self._async = None\n        self.async_mode = None\n        for mode in modes:\n            try:\n                self._async = importlib.import_module(\n                    'engineio.async_drivers.' + mode)._async\n                asyncio_based = self._async['asyncio'] \\\n                    if 'asyncio' in self._async else False\n                if asyncio_based != self.is_asyncio_based():\n                    continue  # pragma: no cover\n                self.async_mode = mode\n                break\n            except ImportError:\n                pass\n        if self.async_mode is None:\n            raise ValueError('Invalid async_mode specified')\n        if self.is_asyncio_based() and \\\n                ('asyncio' not in self._async or not\n                 self._async['asyncio']):  # pragma: no cover\n            raise ValueError('The selected async_mode is not asyncio '\n                             'compatible')\n        if not self.is_asyncio_based() and 'asyncio' in self._async and \\\n                self._async['asyncio']:  # pragma: no cover\n            raise ValueError('The selected async_mode requires asyncio and '\n                             'must use the AsyncServer class')\n        if transports is not None:\n            if isinstance(transports, str):\n                transports = [transports]\n            transports = [transport for transport in transports\n                          if transport in self.valid_transports]\n            if not transports:\n                raise ValueError('No valid transports provided')\n        self.transports = transports or self.valid_transports\n        self.logger.info('Server initialized for %s.', self.async_mode)\n\n    def is_asyncio_based(self):\n        return False\n\n    def async_modes(self):\n        return ['eventlet', 'gevent_uwsgi', 'gevent', 'threading']\n\n    def on(self, event, handler=None):\n        \"\"\"Register an event handler.\n\n        :param event: The event name. Can be ``'connect'``, ``'message'`` or\n                      ``'disconnect'``.\n        :param handler: The function that should be invoked to handle the\n                        event. When this parameter is not given, the method\n                        acts as a decorator for the handler function.\n\n        Example usage::\n\n            # as a decorator:\n            @eio.on('connect')\n            def connect_handler(sid, environ):\n                print('Connection request')\n                if environ['REMOTE_ADDR'] in blacklisted:\n                    return False  # reject\n\n            # as a method:\n            def message_handler(sid, msg):\n                print('Received message: ', msg)\n                eio.send(sid, 'response')\n            eio.on('message', message_handler)\n\n        The handler function receives the ``sid`` (session ID) for the\n        client as first argument. The ``'connect'`` event handler receives the\n        WSGI environment as a second argument, and can return ``False`` to\n        reject the connection. The ``'message'`` handler receives the message\n        payload as a second argument. The ``'disconnect'`` handler does not\n        take a second argument.\n        \"\"\"\n        if event not in self.event_names:\n            raise ValueError('Invalid event')\n\n        def set_handler(handler):\n            self.handlers[event] = handler\n            return handler\n\n        if handler is None:\n            return set_handler\n        set_handler(handler)\n\n    def transport(self, sid):\n        \"\"\"Return the name of the transport used by the client.\n\n        The two possible values returned by this function are ``'polling'``\n        and ``'websocket'``.\n\n        :param sid: The session of the client.\n        \"\"\"\n        return 'websocket' if self._get_socket(sid).upgraded else 'polling'\n\n    def create_queue(self, *args, **kwargs):\n        \"\"\"Create a queue object using the appropriate async model.\n\n        This is a utility function that applications can use to create a queue\n        without having to worry about using the correct call for the selected\n        async mode.\n        \"\"\"\n        return self._async['queue'](*args, **kwargs)\n\n    def get_queue_empty_exception(self):\n        \"\"\"Return the queue empty exception for the appropriate async model.\n\n        This is a utility function that applications can use to work with a\n        queue without having to worry about using the correct call for the\n        selected async mode.\n        \"\"\"\n        return self._async['queue_empty']\n\n    def create_event(self, *args, **kwargs):\n        \"\"\"Create an event object using the appropriate async model.\n\n        This is a utility function that applications can use to create an\n        event without having to worry about using the correct call for the\n        selected async mode.\n        \"\"\"\n        return self._async['event'](*args, **kwargs)\n\n    def generate_id(self):\n        \"\"\"Generate a unique session id.\"\"\"\n        id = base64.b64encode(\n            secrets.token_bytes(12) + self.sequence_number.to_bytes(3, 'big'))\n        self.sequence_number = (self.sequence_number + 1) & 0xffffff\n        return id.decode('utf-8').replace('/', '_').replace('+', '-')\n\n    def _generate_sid_cookie(self, sid, attributes):\n        \"\"\"Generate the sid cookie.\"\"\"\n        cookie = attributes.get('name', 'io') + '=' + sid\n        for attribute, value in attributes.items():\n            if attribute == 'name':\n                continue\n            if callable(value):\n                value = value()\n            if value is True:\n                cookie += '; ' + attribute\n            else:\n                cookie += '; ' + attribute + '=' + value\n        return cookie\n\n    def _upgrades(self, sid, transport):\n        \"\"\"Return the list of possible upgrades for a client connection.\"\"\"\n        if not self.allow_upgrades or self._get_socket(sid).upgraded or \\\n                transport == 'websocket':\n            return []\n        if self._async['websocket'] is None:  # pragma: no cover\n            self._log_error_once(\n                'The WebSocket transport is not available, you must install a '\n                'WebSocket server that is compatible with your async mode to '\n                'enable it. See the documentation for details.',\n                'no-websocket')\n            return []\n        return ['websocket']\n\n    def _get_socket(self, sid):\n        \"\"\"Return the socket object for a given session.\"\"\"\n        try:\n            s = self.sockets[sid]\n        except KeyError:\n            raise KeyError('Session not found')\n        if s.closed:\n            del self.sockets[sid]\n            raise KeyError('Session is disconnected')\n        return s\n\n    def _ok(self, packets=None, headers=None, jsonp_index=None):\n        \"\"\"Generate a successful HTTP response.\"\"\"\n        if packets is not None:\n            if headers is None:\n                headers = []\n            headers += [('Content-Type', 'text/plain; charset=UTF-8')]\n            return {'status': '200 OK',\n                    'headers': headers,\n                    'response': payload.Payload(packets=packets).encode(\n                        jsonp_index=jsonp_index).encode('utf-8')}\n        else:\n            return {'status': '200 OK',\n                    'headers': [('Content-Type', 'text/plain')],\n                    'response': b'OK'}\n\n    def _bad_request(self, message=None):\n        \"\"\"Generate a bad request HTTP error response.\"\"\"\n        if message is None:\n            message = 'Bad Request'\n        message = packet.Packet.json.dumps(message)\n        return {'status': '400 BAD REQUEST',\n                'headers': [('Content-Type', 'text/plain')],\n                'response': message.encode('utf-8')}\n\n    def _method_not_found(self):\n        \"\"\"Generate a method not found HTTP error response.\"\"\"\n        return {'status': '405 METHOD NOT FOUND',\n                'headers': [('Content-Type', 'text/plain')],\n                'response': b'Method Not Found'}\n\n    def _unauthorized(self, message=None):\n        \"\"\"Generate a unauthorized HTTP error response.\"\"\"\n        if message is None:\n            message = 'Unauthorized'\n        message = packet.Packet.json.dumps(message)\n        return {'status': '401 UNAUTHORIZED',\n                'headers': [('Content-Type', 'application/json')],\n                'response': message.encode('utf-8')}\n\n    def _cors_allowed_origins(self, environ):\n        if self.cors_allowed_origins is None:\n            allowed_origins = []\n            if 'wsgi.url_scheme' in environ and 'HTTP_HOST' in environ:\n                allowed_origins.append('{scheme}://{host}'.format(\n                    scheme=environ['wsgi.url_scheme'],\n                    host=environ['HTTP_HOST']))\n                if 'HTTP_X_FORWARDED_PROTO' in environ or \\\n                        'HTTP_X_FORWARDED_HOST' in environ:\n                    scheme = environ.get(\n                        'HTTP_X_FORWARDED_PROTO',\n                        environ['wsgi.url_scheme']).split(',')[0].strip()\n                    allowed_origins.append('{scheme}://{host}'.format(\n                        scheme=scheme, host=environ.get(\n                            'HTTP_X_FORWARDED_HOST',\n                            environ['HTTP_HOST']).split(\n                                ',')[0].strip()))\n        elif self.cors_allowed_origins == '*':\n            allowed_origins = None\n        elif isinstance(self.cors_allowed_origins, str):\n            allowed_origins = [self.cors_allowed_origins]\n        elif callable(self.cors_allowed_origins):\n            origin = environ.get('HTTP_ORIGIN')\n            try:\n                is_allowed = self.cors_allowed_origins(origin, environ)\n            except TypeError:\n                is_allowed = self.cors_allowed_origins(origin)\n            allowed_origins = [origin] if is_allowed else []\n        else:\n            if '*' in self.cors_allowed_origins:\n                allowed_origins = None\n            else:\n                allowed_origins = self.cors_allowed_origins\n        return allowed_origins\n\n    def _cors_headers(self, environ):\n        \"\"\"Return the cross-origin-resource-sharing headers.\"\"\"\n        if self.cors_allowed_origins == []:\n            # special case, CORS handling is completely disabled\n            return []\n        headers = []\n        allowed_origins = self._cors_allowed_origins(environ)\n        if 'HTTP_ORIGIN' in environ and \\\n                (allowed_origins is None or environ['HTTP_ORIGIN'] in\n                 allowed_origins):\n            headers = [('Access-Control-Allow-Origin', environ['HTTP_ORIGIN'])]\n        if environ['REQUEST_METHOD'] == 'OPTIONS':\n            headers += [('Access-Control-Allow-Methods', 'OPTIONS, GET, POST')]\n        if 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' in environ:\n            headers += [('Access-Control-Allow-Headers',\n                        environ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])]\n        if self.cors_credentials:\n            headers += [('Access-Control-Allow-Credentials', 'true')]\n        return headers\n\n    def _gzip(self, response):\n        \"\"\"Apply gzip compression to a response.\"\"\"\n        bytesio = io.BytesIO()\n        with gzip.GzipFile(fileobj=bytesio, mode='w') as gz:\n            gz.write(response)\n        return bytesio.getvalue()\n\n    def _deflate(self, response):\n        \"\"\"Apply deflate compression to a response.\"\"\"\n        return zlib.compress(response)\n\n    def _log_error_once(self, message, message_key):\n        \"\"\"Log message with logging.ERROR level the first time, then log\n        with given level.\"\"\"\n        if message_key not in self.log_message_keys:\n            self.logger.error(message + ' (further occurrences of this error '\n                              'will be logged with level INFO)')\n            self.log_message_keys.add(message_key)\n        else:\n            self.logger.info(message)\n"
  },
  {
    "path": "src/engineio/base_socket.py",
    "content": "class BaseSocket:\n    upgrade_protocols = ['websocket']\n\n    def __init__(self, server, sid):\n        self.server = server\n        self.sid = sid\n        self.queue = self.server.create_queue()\n        self.last_ping = None\n        self.connected = False\n        self.upgrading = False\n        self.upgraded = False\n        self.closing = False\n        self.closed = False\n        self.session = {}\n"
  },
  {
    "path": "src/engineio/client.py",
    "content": "from base64 import b64encode\nfrom http.cookies import SimpleCookie\nimport logging\nimport queue\nimport ssl\nimport threading\nimport time\nimport urllib\nfrom engineio.json import JSONDecodeError\n\ntry:\n    import requests\nexcept ImportError:  # pragma: no cover\n    requests = None\ntry:\n    import websocket\nexcept ImportError:  # pragma: no cover\n    websocket = None\nfrom . import base_client\nfrom . import exceptions\nfrom . import packet\nfrom . import payload\n\ndefault_logger = logging.getLogger('engineio.client')\n\n\nclass Client(base_client.BaseClient):\n    \"\"\"An Engine.IO client.\n\n    This class implements a fully compliant Engine.IO web client with support\n    for websocket and long-polling transports.\n\n    :param logger: To enable logging set to ``True`` or pass a logger object to\n                   use. To disable logging set to ``False``. The default is\n                   ``False``. Note that fatal errors are logged even when\n                   ``logger`` is ``False``.\n    :param json: An alternative JSON module to use for encoding and decoding\n                 packets. Custom json modules must have ``dumps`` and ``loads``\n                 functions that are compatible with the standard library\n                 versions. This is a process-wide setting, all instantiated\n                 servers and clients must use the same JSON module.\n    :param request_timeout: A timeout in seconds for requests. The default is\n                            5 seconds.\n    :param http_session: an initialized ``requests.Session`` object to be used\n                         when sending requests to the server. Use it if you\n                         need to add special client options such as proxy\n                         servers, SSL certificates, custom CA bundle, etc.\n    :param ssl_verify: ``True`` to verify SSL certificates, or ``False`` to\n                       skip SSL certificate verification, allowing\n                       connections to servers with self signed certificates.\n                       The default is ``True``.\n    :param handle_sigint: Set to ``True`` to automatically handle disconnection\n                          when the process is interrupted, or to ``False`` to\n                          leave interrupt handling to the calling application.\n                          Interrupt handling can only be enabled when the\n                          client instance is created in the main thread.\n    :param websocket_extra_options: Dictionary containing additional keyword\n                                    arguments passed to\n                                    ``websocket.create_connection()``.\n    :param timestamp_requests: If ``True`` a timestamp is added to the query\n                               string of Socket.IO requests as a cache-busting\n                               measure. Set to ``False`` to disable.\n    \"\"\"\n    def connect(self, url, headers=None, transports=None,\n                engineio_path='engine.io'):\n        \"\"\"Connect to an Engine.IO server.\n\n        :param url: The URL of the Engine.IO server. It can include custom\n                    query string parameters if required by the server.\n        :param headers: A dictionary with custom headers to send with the\n                        connection request.\n        :param transports: The list of allowed transports. Valid transports\n                           are ``'polling'`` and ``'websocket'``. If not\n                           given, the polling transport is connected first,\n                           then an upgrade to websocket is attempted.\n        :param engineio_path: The endpoint where the Engine.IO server is\n                              installed. The default value is appropriate for\n                              most cases.\n\n        Example usage::\n\n            eio = engineio.Client()\n            eio.connect('http://localhost:5000')\n        \"\"\"\n        if self.state != 'disconnected':\n            raise ValueError('Client is not in a disconnected state')\n        valid_transports = ['polling', 'websocket']\n        if transports is not None:\n            if isinstance(transports, str):\n                transports = [transports]\n            transports = [transport for transport in transports\n                          if transport in valid_transports]\n            if not transports:\n                raise ValueError('No valid transports provided')\n        self.transports = transports or valid_transports\n        return getattr(self, '_connect_' + self.transports[0])(\n            url, headers or {}, engineio_path)\n\n    def wait(self):\n        \"\"\"Wait until the connection with the server ends.\n\n        Client applications can use this function to block the main thread\n        during the life of the connection.\n        \"\"\"\n        if self.read_loop_task:\n            self.read_loop_task.join()\n\n    def send(self, data):\n        \"\"\"Send a message to the server.\n\n        :param data: The data to send to the server. Data can be of type\n                     ``str``, ``bytes``, ``list`` or ``dict``. If a ``list``\n                     or ``dict``, the data will be serialized as JSON.\n        \"\"\"\n        self._send_packet(packet.Packet(packet.MESSAGE, data=data))\n\n    def disconnect(self, abort=False, reason=None):\n        \"\"\"Disconnect from the server.\n\n        :param abort: If set to ``True``, do not wait for background tasks\n                      associated with the connection to end.\n        \"\"\"\n        if self.state == 'connected':\n            self._send_packet(packet.Packet(packet.CLOSE))\n            self.queue.put(None)\n            self.state = 'disconnecting'\n            self._trigger_event('disconnect',\n                                reason or self.reason.CLIENT_DISCONNECT,\n                                run_async=False)\n            if self.current_transport == 'websocket':\n                self.ws.close()\n            if not abort:\n                self.read_loop_task.join()\n            self.state = 'disconnected'\n            try:\n                base_client.connected_clients.remove(self)\n            except ValueError:  # pragma: no cover\n                pass\n        self._reset()\n\n    def start_background_task(self, target, *args, **kwargs):\n        \"\"\"Start a background task.\n\n        This is a utility function that applications can use to start a\n        background task.\n\n        :param target: the target function to execute.\n        :param args: arguments to pass to the function.\n        :param kwargs: keyword arguments to pass to the function.\n\n        This function returns an object that represents the background task,\n        on which the ``join()`` method can be invoked to wait for the task to\n        complete.\n        \"\"\"\n        th = threading.Thread(target=target, args=args, kwargs=kwargs,\n                              daemon=True)\n        th.start()\n        return th\n\n    def sleep(self, seconds=0):\n        \"\"\"Sleep for the requested amount of time.\"\"\"\n        return time.sleep(seconds)\n\n    def create_queue(self, *args, **kwargs):\n        \"\"\"Create a queue object.\"\"\"\n        return queue.Queue(*args, **kwargs)\n\n    def get_queue_empty_exception(self):\n        \"\"\"Return the queue empty exception raised by queues created by the\n        ``create_queue()`` method.\n        \"\"\"\n        return queue.Empty\n\n    def create_event(self, *args, **kwargs):\n        \"\"\"Create an event object.\"\"\"\n        return threading.Event(*args, **kwargs)\n\n    def _reset(self):\n        super()._reset()\n        while True:  # pragma: no cover\n            try:\n                self.queue.get_nowait()\n                self.queue.task_done()\n            except self.queue_empty:\n                break\n\n    def _connect_polling(self, url, headers, engineio_path):\n        \"\"\"Establish a long-polling connection to the Engine.IO server.\"\"\"\n        if requests is None:  # pragma: no cover\n            # not installed\n            self.logger.error('requests package is not installed -- cannot '\n                              'send HTTP requests!')\n            return\n        self.base_url = self._get_engineio_url(url, engineio_path, 'polling')\n        self.logger.info('Attempting polling connection to ' + self.base_url)\n        r = self._send_request(\n            'GET', self.base_url + self._get_url_timestamp(), headers=headers,\n            timeout=self.request_timeout)\n        if r is None or isinstance(r, str):\n            self._reset()\n            raise exceptions.ConnectionError(\n                r or 'Connection refused by the server')\n        if r.status_code < 200 or r.status_code >= 300:\n            self._reset()\n            try:\n                arg = r.json()\n            except JSONDecodeError:\n                arg = None\n            raise exceptions.ConnectionError(\n                'Unexpected status code {} in server response'.format(\n                    r.status_code), arg)\n        try:\n            p = payload.Payload(encoded_payload=r.content.decode('utf-8'))\n        except ValueError:\n            raise exceptions.ConnectionError(\n                'Unexpected response from server') from None\n        open_packet = p.packets[0]\n        if open_packet.packet_type != packet.OPEN:\n            raise exceptions.ConnectionError(\n                'OPEN packet not returned by server')\n        self.logger.info(\n            'Polling connection accepted with ' + str(open_packet.data))\n        self.sid = open_packet.data['sid']\n        self.upgrades = open_packet.data['upgrades']\n        self.ping_interval = int(open_packet.data['pingInterval']) / 1000.0\n        self.ping_timeout = int(open_packet.data['pingTimeout']) / 1000.0\n        self.current_transport = 'polling'\n        self.base_url += '&sid=' + self.sid\n\n        self.state = 'connected'\n        base_client.connected_clients.append(self)\n        self._trigger_event('connect', run_async=False)\n\n        for pkt in p.packets[1:]:\n            self._receive_packet(pkt)\n\n        if 'websocket' in self.upgrades and 'websocket' in self.transports:\n            # attempt to upgrade to websocket\n            if self._connect_websocket(url, headers, engineio_path):\n                # upgrade to websocket succeeded, we're done here\n                return\n\n        # start background tasks associated with this client\n        self.write_loop_task = self.start_background_task(self._write_loop)\n        self.read_loop_task = self.start_background_task(\n            self._read_loop_polling)\n\n    def _connect_websocket(self, url, headers, engineio_path):\n        \"\"\"Establish or upgrade to a WebSocket connection with the server.\"\"\"\n        if websocket is None:  # pragma: no cover\n            # not installed\n            self.logger.error('websocket-client package not installed, only '\n                              'polling transport is available')\n            return False\n        websocket_url = self._get_engineio_url(url, engineio_path, 'websocket')\n        if self.sid:\n            self.logger.info(\n                'Attempting WebSocket upgrade to ' + websocket_url)\n            upgrade = True\n            websocket_url += '&sid=' + self.sid\n        else:\n            upgrade = False\n            self.base_url = websocket_url\n            self.logger.info(\n                'Attempting WebSocket connection to ' + websocket_url)\n\n        # get cookies and other settings from the long-polling connection\n        # so that they are preserved when connecting to the WebSocket route\n        cookies = None\n        extra_options = {}\n        if self.http:\n            # cookies\n            ck = SimpleCookie()\n            for cookie in self.http.cookies:\n                ck[cookie.name] = cookie.value\n            cookies = ck.output(header='', sep=';').strip()\n            for header, value in headers.items():\n                if header.lower() == 'cookie':\n                    if cookies:\n                        cookies += '; '\n                    cookies += value\n                    del headers[header]\n                    break\n\n            # auth\n            if 'Authorization' not in headers and self.http.auth is not None:\n                if not isinstance(self.http.auth, tuple):  # pragma: no cover\n                    raise ValueError('Only basic authentication is supported')\n                basic_auth = '{}:{}'.format(\n                    self.http.auth[0], self.http.auth[1]).encode('utf-8')\n                basic_auth = b64encode(basic_auth).decode('utf-8')\n                headers['Authorization'] = 'Basic ' + basic_auth\n\n            # cert\n            # this can be given as ('certfile', 'keyfile') or just 'certfile'\n            if isinstance(self.http.cert, tuple):\n                extra_options['sslopt'] = {\n                    'certfile': self.http.cert[0],\n                    'keyfile': self.http.cert[1]}\n            elif self.http.cert:\n                extra_options['sslopt'] = {'certfile': self.http.cert}\n\n            # proxies\n            if self.http.proxies:\n                proxy_url = None\n                if websocket_url.startswith('ws://'):\n                    proxy_url = self.http.proxies.get(\n                        'ws', self.http.proxies.get('http'))\n                else:  # wss://\n                    proxy_url = self.http.proxies.get(\n                        'wss', self.http.proxies.get('https'))\n                if proxy_url:\n                    parsed_url = urllib.parse.urlparse(\n                        proxy_url if '://' in proxy_url\n                        else 'scheme://' + proxy_url)\n                    extra_options['http_proxy_host'] = parsed_url.hostname\n                    extra_options['http_proxy_port'] = parsed_url.port\n                    extra_options['http_proxy_auth'] = (\n                        (parsed_url.username, parsed_url.password)\n                        if parsed_url.username or parsed_url.password\n                        else None)\n\n            # verify\n            if isinstance(self.http.verify, str):\n                if 'sslopt' in extra_options:\n                    extra_options['sslopt']['ca_certs'] = self.http.verify\n                else:\n                    extra_options['sslopt'] = {'ca_certs': self.http.verify}\n            elif not self.http.verify:\n                self.ssl_verify = False\n\n        if not self.ssl_verify:\n            if 'sslopt' in extra_options:\n                extra_options['sslopt'].update({\"cert_reqs\": ssl.CERT_NONE})\n            else:\n                extra_options['sslopt'] = {\"cert_reqs\": ssl.CERT_NONE}\n\n        # combine internally generated options with the ones supplied by the\n        # caller. The caller's options take precedence.\n        headers.update(self.websocket_extra_options.pop('header', {}))\n        extra_options['header'] = headers\n        extra_options['cookie'] = cookies\n        extra_options['enable_multithread'] = True\n        extra_options['timeout'] = self.request_timeout\n        extra_options.update(self.websocket_extra_options)\n        try:\n            ws = websocket.create_connection(\n                websocket_url + self._get_url_timestamp(), **extra_options)\n        except (ConnectionError, OSError, websocket.WebSocketException):\n            if upgrade:\n                self.logger.warning(\n                    'WebSocket upgrade failed: connection error')\n                return False\n            else:\n                raise exceptions.ConnectionError('Connection error')\n        if upgrade:\n            p = packet.Packet(packet.PING, data='probe').encode()\n            try:\n                ws.send(p)\n            except Exception as e:  # pragma: no cover\n                self.logger.warning(\n                    'WebSocket upgrade failed: unexpected send exception: %s',\n                    str(e))\n                return False\n            try:\n                p = ws.recv()\n            except Exception as e:  # pragma: no cover\n                self.logger.warning(\n                    'WebSocket upgrade failed: unexpected recv exception: %s',\n                    str(e))\n                return False\n            pkt = packet.Packet(encoded_packet=p)\n            if pkt.packet_type != packet.PONG or pkt.data != 'probe':\n                self.logger.warning(\n                    'WebSocket upgrade failed: no PONG packet')\n                return False\n            p = packet.Packet(packet.UPGRADE).encode()\n            try:\n                ws.send(p)\n            except Exception as e:  # pragma: no cover\n                self.logger.warning(\n                    'WebSocket upgrade failed: unexpected send exception: %s',\n                    str(e))\n                return False\n            self.current_transport = 'websocket'\n            self.logger.info('WebSocket upgrade was successful')\n        else:\n            try:\n                p = ws.recv()\n            except Exception as e:  # pragma: no cover\n                raise exceptions.ConnectionError(\n                    'Unexpected recv exception: ' + str(e))\n            open_packet = packet.Packet(encoded_packet=p)\n            if open_packet.packet_type != packet.OPEN:\n                raise exceptions.ConnectionError('no OPEN packet')\n            self.logger.info(\n                'WebSocket connection accepted with ' + str(open_packet.data))\n            self.sid = open_packet.data['sid']\n            self.upgrades = open_packet.data['upgrades']\n            self.ping_interval = int(open_packet.data['pingInterval']) / 1000.0\n            self.ping_timeout = int(open_packet.data['pingTimeout']) / 1000.0\n            self.current_transport = 'websocket'\n\n            self.state = 'connected'\n            base_client.connected_clients.append(self)\n            self._trigger_event('connect', run_async=False)\n        self.ws = ws\n        self.ws.settimeout(self.ping_interval + self.ping_timeout)\n\n        # start background tasks associated with this client\n        self.write_loop_task = self.start_background_task(self._write_loop)\n        self.read_loop_task = self.start_background_task(\n            self._read_loop_websocket)\n        return True\n\n    def _receive_packet(self, pkt):\n        \"\"\"Handle incoming packets from the server.\"\"\"\n        packet_name = packet.packet_names[pkt.packet_type] \\\n            if pkt.packet_type < len(packet.packet_names) else 'UNKNOWN'\n        self.logger.info(\n            'Received packet %s data %s', packet_name,\n            pkt.data if not isinstance(pkt.data, bytes) else '<binary>')\n        if pkt.packet_type == packet.MESSAGE:\n            self._trigger_event('message', pkt.data, run_async=True)\n        elif pkt.packet_type == packet.PING:\n            self._send_packet(packet.Packet(packet.PONG, pkt.data))\n        elif pkt.packet_type == packet.CLOSE:\n            self.disconnect(abort=True, reason=self.reason.SERVER_DISCONNECT)\n        elif pkt.packet_type == packet.NOOP:\n            pass\n        else:\n            self.logger.error('Received unexpected packet of type %s',\n                              pkt.packet_type)\n\n    def _send_packet(self, pkt):\n        \"\"\"Queue a packet to be sent to the server.\"\"\"\n        if self.state != 'connected':\n            return\n        self.queue.put(pkt)\n        self.logger.info(\n            'Sending packet %s data %s',\n            packet.packet_names[pkt.packet_type],\n            pkt.data if not isinstance(pkt.data, bytes) else '<binary>')\n\n    def _send_request(\n            self, method, url, headers=None, body=None,\n            timeout=None):  # pragma: no cover\n        if self.http is None:\n            self.http = requests.Session()\n        if not self.ssl_verify:\n            self.http.verify = False\n        try:\n            return self.http.request(method, url, headers=headers, data=body,\n                                     timeout=timeout)\n        except requests.exceptions.RequestException as exc:\n            self.logger.info('HTTP %s request to %s failed with error %s.',\n                             method, url, exc)\n            return str(exc)\n\n    def _trigger_event(self, event, *args, **kwargs):\n        \"\"\"Invoke an event handler.\"\"\"\n        run_async = kwargs.pop('run_async', False)\n        if event in self.handlers:\n            if run_async:\n                return self.start_background_task(self.handlers[event], *args)\n            else:\n                try:\n                    try:\n                        return self.handlers[event](*args)\n                    except TypeError:\n                        if event == 'disconnect' and \\\n                                len(args) == 1:  # pragma: no branch\n                            # legacy disconnect events do  not have a reason\n                            # argument\n                            return self.handlers[event]()\n                        else:  # pragma: no cover\n                            raise\n                except:\n                    self.logger.exception(event + ' handler error')\n\n    def _read_loop_polling(self):\n        \"\"\"Read packets by polling the Engine.IO server.\"\"\"\n        while self.state == 'connected' and self.write_loop_task:\n            self.logger.info(\n                'Sending polling GET request to ' + self.base_url)\n            r = self._send_request(\n                'GET', self.base_url + self._get_url_timestamp(),\n                timeout=max(self.ping_interval, self.ping_timeout) + 5)\n            if r is None or isinstance(r, str):\n                self.logger.warning(\n                    r or 'Connection refused by the server, aborting')\n                self.queue.put(None)\n                break\n            if r.status_code < 200 or r.status_code >= 300:\n                self.logger.warning('Unexpected status code %s in server '\n                                    'response, aborting', r.status_code)\n                self.queue.put(None)\n                break\n            try:\n                p = payload.Payload(encoded_payload=r.content.decode('utf-8'))\n            except ValueError:\n                self.logger.warning(\n                    'Unexpected packet from server, aborting')\n                self.queue.put(None)\n                break\n            for pkt in p.packets:\n                self._receive_packet(pkt)\n\n        if self.write_loop_task:  # pragma: no branch\n            self.logger.info('Waiting for write loop task to end')\n            self.write_loop_task.join()\n        if self.state == 'connected':\n            self._trigger_event('disconnect', self.reason.TRANSPORT_ERROR,\n                                run_async=False)\n            try:\n                base_client.connected_clients.remove(self)\n            except ValueError:  # pragma: no cover\n                pass\n            self._reset()\n        self.logger.info('Exiting read loop task')\n\n    def _read_loop_websocket(self):\n        \"\"\"Read packets from the Engine.IO WebSocket connection.\"\"\"\n        while self.state == 'connected':\n            p = None\n            try:\n                p = self.ws.recv()\n                if len(p) == 0 and not self.ws.connected:  # pragma: no cover\n                    # websocket client can return an empty string after close\n                    raise websocket.WebSocketConnectionClosedException()\n            except websocket.WebSocketTimeoutException:\n                self.logger.warning(\n                    'Server has stopped communicating, aborting')\n                self.queue.put(None)\n                break\n            except websocket.WebSocketConnectionClosedException:\n                self.logger.warning(\n                    'WebSocket connection was closed, aborting')\n                self.queue.put(None)\n                break\n            except Exception as e:  # pragma: no cover\n                if type(e) is OSError and e.errno == 9:\n                    self.logger.info(\n                        'WebSocket connection is closing, aborting')\n                else:\n                    self.logger.info(\n                        'Unexpected error receiving packet: \"%s\", aborting',\n                        str(e))\n                self.queue.put(None)\n                break\n            try:\n                pkt = packet.Packet(encoded_packet=p)\n            except Exception as e:  # pragma: no cover\n                self.logger.info(\n                    'Unexpected error decoding packet: \"%s\", aborting', str(e))\n                self.queue.put(None)\n                break\n            self._receive_packet(pkt)\n\n        if self.write_loop_task:  # pragma: no branch\n            self.logger.info('Waiting for write loop task to end')\n            self.write_loop_task.join()\n        if self.state == 'connected':\n            self._trigger_event('disconnect', self.reason.TRANSPORT_ERROR,\n                                run_async=False)\n            try:\n                base_client.connected_clients.remove(self)\n            except ValueError:  # pragma: no cover\n                pass\n            self._reset()\n        self.logger.info('Exiting read loop task')\n\n    def _write_loop(self):\n        \"\"\"This background task sends packages to the server as they are\n        pushed to the send queue.\n        \"\"\"\n        while self.state == 'connected':\n            # to simplify the timeout handling, use the maximum of the\n            # ping interval and ping timeout as timeout, with an extra 5\n            # seconds grace period\n            timeout = max(self.ping_interval, self.ping_timeout) + 5\n            packets = None\n            try:\n                packets = [self.queue.get(timeout=timeout)]\n            except self.queue_empty:\n                self.logger.error('packet queue is empty, aborting')\n                break\n            if packets == [None]:\n                self.queue.task_done()\n                packets = []\n            else:\n                while True:\n                    try:\n                        packets.append(self.queue.get(block=False))\n                    except self.queue_empty:\n                        break\n                    if packets[-1] is None:\n                        packets = packets[:-1]\n                        self.queue.task_done()\n                        break\n            if not packets:\n                # empty packet list returned -> connection closed\n                break\n            if self.current_transport == 'polling':\n                p = payload.Payload(packets=packets)\n                r = self._send_request(\n                    'POST', self.base_url, body=p.encode(),\n                    headers={'Content-Type': 'text/plain'},\n                    timeout=self.request_timeout)\n                for pkt in packets:\n                    self.queue.task_done()\n                if r is None or isinstance(r, str):\n                    self.logger.warning(\n                        r or 'Connection refused by the server, aborting')\n                    break\n                if r.status_code < 200 or r.status_code >= 300:\n                    self.logger.warning('Unexpected status code %s in server '\n                                        'response, aborting', r.status_code)\n                    self.write_loop_task = None\n                    break\n            else:\n                # websocket\n                try:\n                    for pkt in packets:\n                        encoded_packet = pkt.encode()\n                        if pkt.binary:\n                            self.ws.send_binary(encoded_packet)\n                        else:\n                            self.ws.send(encoded_packet)\n                        self.queue.task_done()\n                except (websocket.WebSocketConnectionClosedException,\n                        BrokenPipeError, OSError):\n                    self.logger.warning(\n                        'WebSocket connection was closed, aborting')\n                    break\n        self.logger.info('Exiting write loop task')\n"
  },
  {
    "path": "src/engineio/exceptions.py",
    "content": "class EngineIOError(Exception):\n    pass\n\n\nclass ContentTooLongError(EngineIOError):\n    pass\n\n\nclass UnknownPacketError(EngineIOError):\n    pass\n\n\nclass QueueEmpty(EngineIOError):\n    pass\n\n\nclass SocketIsClosedError(EngineIOError):\n    pass\n\n\nclass ConnectionError(EngineIOError):\n    pass\n"
  },
  {
    "path": "src/engineio/json.py",
    "content": "\"\"\"JSON-compatible module with sane defaults.\"\"\"\n\nfrom json import *  # noqa: F401, F403\nfrom json import loads as original_loads\n\n\ndef _safe_int(s):\n    if len(s) > 100:\n        raise ValueError('Integer is too large')\n    return int(s)\n\n\ndef loads(*args, **kwargs):\n    if 'parse_int' not in kwargs:  # pragma: no cover\n        kwargs['parse_int'] = _safe_int\n    return original_loads(*args, **kwargs)\n"
  },
  {
    "path": "src/engineio/middleware.py",
    "content": "import os\nfrom engineio.static_files import get_static_file\n\n\nclass WSGIApp:\n    \"\"\"WSGI application middleware for Engine.IO.\n\n    This middleware dispatches traffic to an Engine.IO application. It can\n    also serve a list of static files to the client, or forward unrelated\n    HTTP traffic to another WSGI application.\n\n    :param engineio_app: The Engine.IO server. Must be an instance of the\n                         ``engineio.Server`` class.\n    :param wsgi_app: The WSGI app that receives all other traffic.\n    :param static_files: A dictionary with static file mapping rules. See the\n                         documentation for details on this argument.\n    :param engineio_path: The endpoint where the Engine.IO application should\n                          be installed. The default value is appropriate for\n                          most cases.\n\n    Example usage::\n\n        import engineio\n        import eventlet\n\n        eio = engineio.Server()\n        app = engineio.WSGIApp(eio, static_files={\n            '/': {'content_type': 'text/html', 'filename': 'index.html'},\n            '/index.html': {'content_type': 'text/html',\n                            'filename': 'index.html'},\n        })\n        eventlet.wsgi.server(eventlet.listen(('', 8000)), app)\n    \"\"\"\n    def __init__(self, engineio_app, wsgi_app=None, static_files=None,\n                 engineio_path='engine.io'):\n        self.engineio_app = engineio_app\n        self.wsgi_app = wsgi_app\n        self.engineio_path = engineio_path\n        if not self.engineio_path.startswith('/'):\n            self.engineio_path = '/' + self.engineio_path\n        if not self.engineio_path.endswith('/'):\n            self.engineio_path += '/'\n        self.static_files = static_files or {}\n\n    def __call__(self, environ, start_response):\n        if 'gunicorn.socket' in environ:\n            # gunicorn saves the socket under environ['gunicorn.socket'], while\n            # eventlet saves it under environ['eventlet.input']. Eventlet also\n            # stores the socket inside a wrapper class, while gunicon writes it\n            # directly into the environment. To give eventlet's WebSocket\n            # module access to this socket when running under gunicorn, here we\n            # copy the socket to the eventlet format.\n            class Input:\n                def __init__(self, socket):\n                    self.socket = socket\n\n                def get_socket(self):\n                    return self.socket\n\n            environ['eventlet.input'] = Input(environ['gunicorn.socket'])\n        path = environ['PATH_INFO']\n        if path is not None and path.startswith(self.engineio_path):\n            return self.engineio_app.handle_request(environ, start_response)\n        else:\n            static_file = get_static_file(path, self.static_files) \\\n                if self.static_files else None\n            if static_file and os.path.exists(static_file['filename']):\n                start_response(\n                    '200 OK',\n                    [('Content-Type', static_file['content_type'])])\n                with open(static_file['filename'], 'rb') as f:\n                    return [f.read()]\n            elif self.wsgi_app is not None:\n                return self.wsgi_app(environ, start_response)\n        return self.not_found(start_response)\n\n    def not_found(self, start_response):\n        start_response(\"404 Not Found\", [('Content-Type', 'text/plain')])\n        return [b'Not Found']\n\n\nclass Middleware(WSGIApp):\n    \"\"\"This class has been renamed to ``WSGIApp`` and is now deprecated.\"\"\"\n    def __init__(self, engineio_app, wsgi_app=None,\n                 engineio_path='engine.io'):\n        super().__init__(engineio_app, wsgi_app, engineio_path=engineio_path)\n"
  },
  {
    "path": "src/engineio/packet.py",
    "content": "import base64\nfrom engineio import json as _json\n\n(OPEN, CLOSE, PING, PONG, MESSAGE, UPGRADE, NOOP) = (0, 1, 2, 3, 4, 5, 6)\npacket_names = ['OPEN', 'CLOSE', 'PING', 'PONG', 'MESSAGE', 'UPGRADE', 'NOOP']\n\nbinary_types = (bytes, bytearray)\n\n\nclass Packet:\n    \"\"\"Engine.IO packet.\"\"\"\n\n    json = _json\n\n    def __init__(self, packet_type=NOOP, data=None, encoded_packet=None):\n        self.packet_type = packet_type\n        self.data = data\n        self.encode_cache = None\n        if isinstance(data, str):\n            self.binary = False\n        elif isinstance(data, binary_types):\n            self.binary = True\n        else:\n            self.binary = False\n        if self.binary and self.packet_type != MESSAGE:\n            raise ValueError('Binary packets can only be of type MESSAGE')\n        if encoded_packet is not None:\n            self.decode(encoded_packet)\n\n    def encode(self, b64=False):\n        \"\"\"Encode the packet for transmission.\n\n        Note: as a performance optimization, subsequent calls to this method\n        will return a cached encoded packet, even if the data has changed.\n        \"\"\"\n        if self.encode_cache:\n            return self.encode_cache\n        if self.binary:\n            if b64:\n                encoded_packet = 'b' + base64.b64encode(self.data).decode(\n                    'utf-8')\n            else:\n                encoded_packet = self.data\n        else:\n            encoded_packet = str(self.packet_type)\n            if isinstance(self.data, str):\n                encoded_packet += self.data\n            elif isinstance(self.data, dict) or isinstance(self.data, list):\n                encoded_packet += self.json.dumps(self.data,\n                                                  separators=(',', ':'))\n            elif self.data is not None:\n                encoded_packet += str(self.data)\n        self.encode_cache = encoded_packet\n        return encoded_packet\n\n    def decode(self, encoded_packet):\n        \"\"\"Decode a transmitted package.\"\"\"\n        self.binary = isinstance(encoded_packet, binary_types)\n        if not self.binary and len(encoded_packet) == 0:\n            raise ValueError('Invalid empty packet received')\n        b64 = not self.binary and encoded_packet[0] == 'b'\n        if b64:\n            self.binary = True\n            self.packet_type = MESSAGE\n            self.data = base64.b64decode(encoded_packet[1:])\n        else:\n            if self.binary and not isinstance(encoded_packet, bytes):\n                encoded_packet = bytes(encoded_packet)\n            if self.binary:\n                self.packet_type = MESSAGE\n                self.data = encoded_packet\n            else:\n                self.packet_type = int(encoded_packet[0])\n                try:\n                    if encoded_packet[1].isnumeric():\n                        # do not allow integer payloads, see\n                        # github.com/miguelgrinberg/python-engineio/issues/75\n                        # for background on this decision\n                        raise ValueError\n                    self.data = self.json.loads(encoded_packet[1:])\n                except (ValueError, IndexError):\n                    self.data = encoded_packet[1:]\n"
  },
  {
    "path": "src/engineio/payload.py",
    "content": "import urllib\n\nfrom . import packet\n\n\nclass Payload:\n    \"\"\"Engine.IO payload.\"\"\"\n    max_decode_packets = 16\n\n    def __init__(self, packets=None, encoded_payload=None):\n        self.packets = packets or []\n        if encoded_payload is not None:\n            self.decode(encoded_payload)\n\n    def encode(self, jsonp_index=None):\n        \"\"\"Encode the payload for transmission.\"\"\"\n        encoded_payload = ''\n        for pkt in self.packets:\n            if encoded_payload:\n                encoded_payload += '\\x1e'\n            encoded_payload += pkt.encode(b64=True)\n        if jsonp_index is not None:\n            encoded_payload = '___eio[' + \\\n                              str(jsonp_index) + \\\n                              '](\"' + \\\n                              encoded_payload.replace('\"', '\\\\\"') + \\\n                              '\");'\n        return encoded_payload\n\n    def decode(self, encoded_payload):\n        \"\"\"Decode a transmitted payload.\"\"\"\n        self.packets = []\n\n        if len(encoded_payload) == 0:\n            return\n\n        # JSONP POST payload starts with 'd='\n        if encoded_payload.startswith('d='):\n            encoded_payload = urllib.parse.parse_qs(\n                encoded_payload)['d'][0]\n\n        encoded_packets = encoded_payload.split('\\x1e')\n        if len(encoded_packets) > self.max_decode_packets:\n            raise ValueError('Too many packets in payload')\n        self.packets = [packet.Packet(encoded_packet=encoded_packet)\n                        for encoded_packet in encoded_packets]\n"
  },
  {
    "path": "src/engineio/server.py",
    "content": "import logging\nimport urllib\n\nfrom . import base_server\nfrom . import exceptions\nfrom . import packet\nfrom . import socket\n\ndefault_logger = logging.getLogger('engineio.server')\n\n\nclass Server(base_server.BaseServer):\n    \"\"\"An Engine.IO server.\n\n    This class implements a fully compliant Engine.IO web server with support\n    for websocket and long-polling transports.\n\n    :param async_mode: The asynchronous model to use. See the Deployment\n                       section in the documentation for a description of the\n                       available options. Valid async modes are \"threading\",\n                       \"eventlet\", \"gevent\" and \"gevent_uwsgi\". If this\n                       argument is not given, \"eventlet\" is tried first, then\n                       \"gevent_uwsgi\", then \"gevent\", and finally \"threading\".\n                       The first async mode that has all its dependencies\n                       installed is the one that is chosen.\n    :param ping_interval: The interval in seconds at which the server pings\n                          the client. The default is 25 seconds. For advanced\n                          control, a two element tuple can be given, where\n                          the first number is the ping interval and the second\n                          is a grace period added by the server.\n    :param ping_timeout: The time in seconds that the client waits for the\n                         server to respond before disconnecting. The default\n                         is 20 seconds.\n    :param max_http_buffer_size: The maximum size that is accepted for incoming\n                                 messages.  The default is 1,000,000 bytes. In\n                                 spite of its name, the value set in this\n                                 argument is enforced for HTTP long-polling and\n                                 WebSocket connections.\n    :param allow_upgrades: Whether to allow transport upgrades or not. The\n                           default is ``True``.\n    :param http_compression: Whether to compress packages when using the\n                             polling transport. The default is ``True``.\n    :param compression_threshold: Only compress messages when their byte size\n                                  is greater than this value. The default is\n                                  1024 bytes.\n    :param cookie: If set to a string, it is the name of the HTTP cookie the\n                   server sends back tot he client containing the client\n                   session id. If set to a dictionary, the ``'name'`` key\n                   contains the cookie name and other keys define cookie\n                   attributes, where the value of each attribute can be a\n                   string, a callable with no arguments, or a boolean. If set\n                   to ``None`` (the default), a cookie is not sent to the\n                   client.\n    :param cors_allowed_origins: Origin or list of origins that are allowed to\n                                 connect to this server. Only the same origin\n                                 is allowed by default. Set this argument to\n                                 ``'*'`` or ``['*']`` to allow all origins, or\n                                 to ``[]`` to disable CORS handling.\n    :param cors_credentials: Whether credentials (cookies, authentication) are\n                             allowed in requests to this server. The default\n                             is ``True``.\n    :param logger: To enable logging set to ``True`` or pass a logger object to\n                   use. To disable logging set to ``False``. The default is\n                   ``False``. Note that fatal errors are logged even when\n                   ``logger`` is ``False``.\n    :param json: An alternative JSON module to use for encoding and decoding\n                 packets. Custom JSON modules must have ``dumps`` and ``loads``\n                 functions that are compatible with the standard library\n                 versions. This is a process-wide setting, all instantiated\n                 servers and clients must use the same JSON module.\n    :param async_handlers: If set to ``True``, run message event handlers in\n                           non-blocking threads. To run handlers synchronously,\n                           set to ``False``. The default is ``True``.\n    :param monitor_clients: If set to ``True``, a background task will ensure\n                            inactive clients are closed. Set to ``False`` to\n                            disable the monitoring task (not recommended). The\n                            default is ``True``.\n    :param transports: The list of allowed transports. Valid transports\n                       are ``'polling'`` and ``'websocket'``. Defaults to\n                       ``['polling', 'websocket']``.\n    :param kwargs: Reserved for future extensions, any additional parameters\n                   given as keyword arguments will be silently ignored.\n    \"\"\"\n    def send(self, sid, data):\n        \"\"\"Send a message to a client.\n\n        :param sid: The session id of the recipient client.\n        :param data: The data to send to the client. Data can be of type\n                     ``str``, ``bytes``, ``list`` or ``dict``. If a ``list``\n                     or ``dict``, the data will be serialized as JSON.\n        \"\"\"\n        self.send_packet(sid, packet.Packet(packet.MESSAGE, data=data))\n\n    def send_packet(self, sid, pkt):\n        \"\"\"Send a raw packet to a client.\n\n        :param sid: The session id of the recipient client.\n        :param pkt: The packet to send to the client.\n        \"\"\"\n        try:\n            socket = self._get_socket(sid)\n        except KeyError:\n            # the socket is not available\n            self.logger.warning('Cannot send to sid %s', sid)\n            return\n        socket.send(pkt)\n\n    def get_session(self, sid):\n        \"\"\"Return the user session for a client.\n\n        :param sid: The session id of the client.\n\n        The return value is a dictionary. Modifications made to this\n        dictionary are not guaranteed to be preserved unless\n        ``save_session()`` is called, or when the ``session`` context manager\n        is used.\n        \"\"\"\n        socket = self._get_socket(sid)\n        return socket.session\n\n    def save_session(self, sid, session):\n        \"\"\"Store the user session for a client.\n\n        :param sid: The session id of the client.\n        :param session: The session dictionary.\n        \"\"\"\n        socket = self._get_socket(sid)\n        socket.session = session\n\n    def session(self, sid):\n        \"\"\"Return the user session for a client with context manager syntax.\n\n        :param sid: The session id of the client.\n\n        This is a context manager that returns the user session dictionary for\n        the client. Any changes that are made to this dictionary inside the\n        context manager block are saved back to the session. Example usage::\n\n            @eio.on('connect')\n            def on_connect(sid, environ):\n                username = authenticate_user(environ)\n                if not username:\n                    return False\n                with eio.session(sid) as session:\n                    session['username'] = username\n\n            @eio.on('message')\n            def on_message(sid, msg):\n                with eio.session(sid) as session:\n                    print('received message from ', session['username'])\n        \"\"\"\n        class _session_context_manager:\n            def __init__(self, server, sid):\n                self.server = server\n                self.sid = sid\n                self.session = None\n\n            def __enter__(self):\n                self.session = self.server.get_session(sid)\n                return self.session\n\n            def __exit__(self, *args):\n                self.server.save_session(sid, self.session)\n\n        return _session_context_manager(self, sid)\n\n    def disconnect(self, sid=None):\n        \"\"\"Disconnect a client.\n\n        :param sid: The session id of the client to close. If this parameter\n                    is not given, then all clients are closed.\n        \"\"\"\n        if sid is not None:\n            try:\n                socket = self._get_socket(sid)\n            except KeyError:  # pragma: no cover\n                # the socket was already closed or gone\n                pass\n            else:\n                socket.close(reason=self.reason.SERVER_DISCONNECT)\n                if sid in self.sockets:  # pragma: no cover\n                    del self.sockets[sid]\n        else:\n            for client in self.sockets.copy().values():\n                client.close(reason=self.reason.SERVER_DISCONNECT)\n            self.sockets = {}\n\n    def handle_request(self, environ, start_response):\n        \"\"\"Handle an HTTP request from the client.\n\n        This is the entry point of the Engine.IO application, using the same\n        interface as a WSGI application. For the typical usage, this function\n        is invoked by the :class:`Middleware` instance, but it can be invoked\n        directly when the middleware is not used.\n\n        :param environ: The WSGI environment.\n        :param start_response: The WSGI ``start_response`` function.\n\n        This function returns the HTTP response body to deliver to the client\n        as a byte sequence.\n        \"\"\"\n        if self.cors_allowed_origins != []:\n            # Validate the origin header if present\n            # This is important for WebSocket more than for HTTP, since\n            # browsers only apply CORS controls to HTTP.\n            origin = environ.get('HTTP_ORIGIN')\n            if origin:\n                allowed_origins = self._cors_allowed_origins(environ)\n                if allowed_origins is not None and origin not in \\\n                        allowed_origins:\n                    self._log_error_once(\n                        origin + ' is not an accepted origin.', 'bad-origin')\n                    r = self._bad_request('Not an accepted origin.')\n                    start_response(r['status'], r['headers'])\n                    return [r['response']]\n\n        method = environ['REQUEST_METHOD']\n        query = urllib.parse.parse_qs(environ.get('QUERY_STRING', ''))\n        jsonp = False\n        jsonp_index = None\n\n        # make sure the client uses an allowed transport\n        transport = query.get('transport', ['polling'])[0]\n        if transport not in self.transports:\n            self._log_error_once('Invalid transport', 'bad-transport')\n            r = self._bad_request('Invalid transport')\n            start_response(r['status'], r['headers'])\n            return [r['response']]\n\n        # make sure the client speaks a compatible Engine.IO version\n        sid = query['sid'][0] if 'sid' in query else None\n        if sid is None and query.get('EIO') != ['4']:\n            self._log_error_once(\n                'The client is using an unsupported version of the Socket.IO '\n                'or Engine.IO protocols', 'bad-version')\n            r = self._bad_request(\n                'The client is using an unsupported version of the Socket.IO '\n                'or Engine.IO protocols')\n            start_response(r['status'], r['headers'])\n            return [r['response']]\n\n        if 'j' in query:\n            jsonp = True\n            try:\n                jsonp_index = int(query['j'][0])\n            except (ValueError, KeyError, IndexError):\n                # Invalid JSONP index number\n                pass\n\n        if jsonp and jsonp_index is None:\n            self._log_error_once('Invalid JSONP index number',\n                                 'bad-jsonp-index')\n            r = self._bad_request('Invalid JSONP index number')\n        elif method == 'GET':\n            upgrade_header = environ.get('HTTP_UPGRADE').lower() \\\n                if 'HTTP_UPGRADE' in environ else None\n            if sid is None:\n                # transport must be one of 'polling' or 'websocket'.\n                # if 'websocket', the HTTP_UPGRADE header must match.\n                if transport == 'polling' \\\n                        or transport == upgrade_header == 'websocket':\n                    r = self._handle_connect(environ, start_response,\n                                             transport, jsonp_index)\n                else:\n                    self._log_error_once('Invalid websocket upgrade',\n                                         'bad-upgrade')\n                    r = self._bad_request('Invalid websocket upgrade')\n            else:\n                if sid not in self.sockets:\n                    self._log_error_once(f'Invalid session {sid}', 'bad-sid')\n                    r = self._bad_request(f'Invalid session {sid}')\n                else:\n                    try:\n                        socket = self._get_socket(sid)\n                    except KeyError as e:  # pragma: no cover\n                        self._log_error_once(f'{e} {sid}', 'bad-sid')\n                        r = self._bad_request(f'{e} {sid}')\n                    else:\n                        if self.transport(sid) != transport and \\\n                                transport != upgrade_header:\n                            self._log_error_once(\n                                f'Invalid transport for session {sid}',\n                                'bad-transport')\n                            r = self._bad_request('Invalid transport')\n                        else:\n                            try:\n                                packets = socket.handle_get_request(\n                                    environ, start_response)\n                                if isinstance(packets, list):\n                                    r = self._ok(packets,\n                                                 jsonp_index=jsonp_index)\n                                else:\n                                    r = packets\n                            except exceptions.EngineIOError:\n                                if sid in self.sockets:  # pragma: no cover\n                                    self.disconnect(sid)\n                                r = self._bad_request()\n                            if sid in self.sockets and \\\n                                    self.sockets[sid].closed:\n                                del self.sockets[sid]\n        elif method == 'POST':\n            if sid is None or sid not in self.sockets:\n                self._log_error_once(f'Invalid session {sid}', 'bad-sid')\n                r = self._bad_request(f'Invalid session {sid}')\n            else:\n                socket = self._get_socket(sid)\n                try:\n                    socket.handle_post_request(environ)\n                    r = self._ok(jsonp_index=jsonp_index)\n                except exceptions.EngineIOError:\n                    if sid in self.sockets:  # pragma: no cover\n                        self.disconnect(sid)\n                    r = self._bad_request()\n                except:  # pragma: no cover\n                    # for any other unexpected errors, we log the error\n                    # and keep going\n                    self.logger.exception('post request handler error')\n                    r = self._ok(jsonp_index=jsonp_index)\n        elif method == 'OPTIONS':\n            r = self._ok()\n        else:\n            self.logger.warning('Method %s not supported', method)\n            r = self._method_not_found()\n\n        if not isinstance(r, dict):\n            return r\n        if self.http_compression and \\\n                len(r['response']) >= self.compression_threshold:\n            encodings = [e.split(';')[0].strip() for e in\n                         environ.get('HTTP_ACCEPT_ENCODING', '').split(',')]\n            for encoding in encodings:\n                if encoding in self.compression_methods:\n                    r['response'] = \\\n                        getattr(self, '_' + encoding)(r['response'])\n                    r['headers'] += [('Content-Encoding', encoding)]\n                    break\n        cors_headers = self._cors_headers(environ)\n        start_response(r['status'], r['headers'] + cors_headers)\n        return [r['response']]\n\n    def shutdown(self):\n        \"\"\"Stop Socket.IO background tasks.\n\n        This method stops background activity initiated by the Socket.IO\n        server. It must be called before shutting down the web server.\n        \"\"\"\n        self.logger.info('Socket.IO is shutting down')\n        if self.service_task_event:  # pragma: no cover\n            self.service_task_event.set()\n            self.service_task_handle.join()\n            self.service_task_handle = None\n\n    def start_background_task(self, target, *args, **kwargs):\n        \"\"\"Start a background task using the appropriate async model.\n\n        This is a utility function that applications can use to start a\n        background task using the method that is compatible with the\n        selected async mode.\n\n        :param target: the target function to execute.\n        :param args: arguments to pass to the function.\n        :param kwargs: keyword arguments to pass to the function.\n\n        This function returns an object that represents the background task,\n        on which the ``join()`` methond can be invoked to wait for the task to\n        complete.\n        \"\"\"\n        th = self._async['thread'](target=target, args=args, kwargs=kwargs)\n        th.start()\n        return th  # pragma: no cover\n\n    def sleep(self, seconds=0):\n        \"\"\"Sleep for the requested amount of time using the appropriate async\n        model.\n\n        This is a utility function that applications can use to put a task to\n        sleep without having to worry about using the correct call for the\n        selected async mode.\n        \"\"\"\n        return self._async['sleep'](seconds)\n\n    def _handle_connect(self, environ, start_response, transport,\n                        jsonp_index=None):\n        \"\"\"Handle a client connection request.\"\"\"\n        if self.start_service_task:\n            # start the service task to monitor connected clients\n            self.start_service_task = False\n            self.service_task_handle = self.start_background_task(\n                self._service_task)\n\n        sid = self.generate_id()\n        s = socket.Socket(self, sid)\n        self.sockets[sid] = s\n\n        pkt = packet.Packet(packet.OPEN, {\n            'sid': sid,\n            'upgrades': self._upgrades(sid, transport),\n            'pingTimeout': int(self.ping_timeout * 1000),\n            'pingInterval': int(\n                self.ping_interval + self.ping_interval_grace_period) * 1000,\n            'maxPayload': self.max_http_buffer_size,\n        })\n        s.send(pkt)\n        s.schedule_ping()\n\n        # NOTE: some sections below are marked as \"no cover\" to workaround\n        # what seems to be a bug in the coverage package. All the lines below\n        # are covered by tests, but some are not reported as such for some\n        # reason\n        ret = self._trigger_event('connect', sid, environ, run_async=False)\n        if ret is not None and ret is not True:  # pragma: no cover\n            del self.sockets[sid]\n            self.logger.warning('Application rejected connection')\n            return self._unauthorized(ret or None)\n\n        if transport == 'websocket':  # pragma: no cover\n            ret = s.handle_get_request(environ, start_response)\n            if s.closed and sid in self.sockets:\n                # websocket connection ended, so we are done\n                del self.sockets[sid]\n            return ret\n        else:  # pragma: no cover\n            s.connected = True\n            headers = None\n            if self.cookie:\n                if isinstance(self.cookie, dict):\n                    headers = [(\n                        'Set-Cookie',\n                        self._generate_sid_cookie(sid, self.cookie)\n                    )]\n                else:\n                    headers = [(\n                        'Set-Cookie',\n                        self._generate_sid_cookie(sid, {\n                            'name': self.cookie, 'path': '/', 'SameSite': 'Lax'\n                        })\n                    )]\n            try:\n                return self._ok(s.poll(), headers=headers,\n                                jsonp_index=jsonp_index)\n            except exceptions.QueueEmpty:\n                return self._bad_request()\n\n    def _trigger_event(self, event, *args, **kwargs):\n        \"\"\"Invoke an event handler.\"\"\"\n        run_async = kwargs.pop('run_async', False)\n        if event in self.handlers:\n            def run_handler():\n                try:\n                    try:\n                        return self.handlers[event](*args)\n                    except TypeError:\n                        if event == 'disconnect' and \\\n                                len(args) == 2:  # pragma: no branch\n                            # legacy disconnect events do not have a reason\n                            # argument\n                            return self.handlers[event](args[0])\n                        else:  # pragma: no cover\n                            raise\n                except:\n                    self.logger.exception(event + ' handler error')\n                    if event == 'connect':\n                        # if connect handler raised error we reject the\n                        # connection\n                        return False\n\n            if run_async:\n                return self.start_background_task(run_handler)\n            else:\n                return run_handler()\n\n    def _service_task(self):  # pragma: no cover\n        \"\"\"Monitor connected clients and clean up those that time out.\"\"\"\n        self.service_task_event = self.create_event()\n        while not self.service_task_event.is_set():\n            if len(self.sockets) == 0:\n                # nothing to do\n                if self.service_task_event.wait(timeout=self.ping_timeout):\n                    break\n                continue\n\n            # go through the entire client list in a ping interval cycle\n            sleep_interval = float(self.ping_timeout) / len(self.sockets)\n\n            try:\n                # iterate over the current clients\n                for s in self.sockets.copy().values():\n                    if s.closed:\n                        try:\n                            del self.sockets[s.sid]\n                        except KeyError:\n                            # the socket could have also been removed by\n                            # the _get_socket() method from another thread\n                            pass\n                    elif not s.closing:\n                        s.check_ping_timeout()\n                    if self.service_task_event.wait(timeout=sleep_interval):\n                        raise KeyboardInterrupt()\n            except (SystemExit, KeyboardInterrupt):\n                self.logger.info('service task canceled')\n                break\n            except:\n                # an unexpected exception has occurred, log it and continue\n                self.logger.exception('service task exception')\n"
  },
  {
    "path": "src/engineio/socket.py",
    "content": "import sys\nimport time\n\nfrom . import base_socket\nfrom . import exceptions\nfrom . import packet\nfrom . import payload\n\n\nclass Socket(base_socket.BaseSocket):\n    \"\"\"An Engine.IO socket.\"\"\"\n    def poll(self):\n        \"\"\"Wait for packets to send to the client.\"\"\"\n        queue_empty = self.server.get_queue_empty_exception()\n        try:\n            packets = [self.queue.get(\n                timeout=self.server.ping_interval + self.server.ping_timeout)]\n            self.queue.task_done()\n        except queue_empty:\n            raise exceptions.QueueEmpty()\n        if packets == [None]:\n            return []\n        while True:\n            try:\n                pkt = self.queue.get(block=False)\n                self.queue.task_done()\n                if pkt is None:\n                    self.queue.put(None)\n                    break\n                packets.append(pkt)\n            except queue_empty:\n                break\n        return packets\n\n    def receive(self, pkt):\n        \"\"\"Receive packet from the client.\"\"\"\n        packet_name = packet.packet_names[pkt.packet_type] \\\n            if pkt.packet_type < len(packet.packet_names) else 'UNKNOWN'\n        self.server.logger.info('%s: Received packet %s data %s',\n                                self.sid, packet_name,\n                                pkt.data if not isinstance(pkt.data, bytes)\n                                else '<binary>')\n        if pkt.packet_type == packet.PONG:\n            self.schedule_ping()\n        elif pkt.packet_type == packet.MESSAGE:\n            self.server._trigger_event('message', self.sid, pkt.data,\n                                       run_async=self.server.async_handlers)\n        elif pkt.packet_type == packet.UPGRADE:\n            self.send(packet.Packet(packet.NOOP))\n        elif pkt.packet_type == packet.CLOSE:\n            self.close(wait=False, abort=True,\n                       reason=self.server.reason.CLIENT_DISCONNECT)\n        else:\n            raise exceptions.UnknownPacketError()\n\n    def check_ping_timeout(self):\n        \"\"\"Make sure the client is still responding to pings.\"\"\"\n        if self.closed:\n            raise exceptions.SocketIsClosedError()\n        if self.last_ping and \\\n                time.time() - self.last_ping > self.server.ping_timeout:\n            self.server.logger.info('%s: Client is gone, closing socket',\n                                    self.sid)\n            # Passing abort=False here will cause close() to write a\n            # CLOSE packet. This has the effect of updating half-open sockets\n            # to their correct state of disconnected\n            self.close(wait=False, abort=False,\n                       reason=self.server.reason.PING_TIMEOUT)\n            return False\n        return True\n\n    def send(self, pkt):\n        \"\"\"Send a packet to the client.\"\"\"\n        if not self.check_ping_timeout():\n            return\n        else:\n            self.queue.put(pkt)\n        self.server.logger.info('%s: Sending packet %s data %s',\n                                self.sid, packet.packet_names[pkt.packet_type],\n                                pkt.data if not isinstance(pkt.data, bytes)\n                                else '<binary>')\n\n    def handle_get_request(self, environ, start_response):\n        \"\"\"Handle a long-polling GET request from the client.\"\"\"\n        connections = [\n            s.strip()\n            for s in environ.get('HTTP_CONNECTION', '').lower().split(',')]\n        transport = environ.get('HTTP_UPGRADE', '').lower()\n        if 'upgrade' in connections and transport in self.upgrade_protocols:\n            self.server.logger.info('%s: Received request to upgrade to %s',\n                                    self.sid, transport)\n            return getattr(self, '_upgrade_' + transport)(environ,\n                                                          start_response)\n        if self.upgrading or self.upgraded:\n            # we are upgrading to WebSocket, do not return any more packets\n            # through the polling endpoint\n            return [packet.Packet(packet.NOOP)]\n        try:\n            packets = self.poll()\n        except exceptions.QueueEmpty:\n            exc = sys.exc_info()\n            self.close(wait=False, reason=self.server.reason.TRANSPORT_ERROR)\n            raise exc[1].with_traceback(exc[2])\n        return packets\n\n    def handle_post_request(self, environ):\n        \"\"\"Handle a long-polling POST request from the client.\"\"\"\n        length = int(environ.get('CONTENT_LENGTH', '0'))\n        if length > self.server.max_http_buffer_size:\n            raise exceptions.ContentTooLongError()\n        else:\n            body = environ['wsgi.input'].read(length).decode('utf-8')\n            p = payload.Payload(encoded_payload=body)\n            for pkt in p.packets:\n                self.receive(pkt)\n\n    def close(self, wait=True, abort=False, reason=None):\n        \"\"\"Close the socket connection.\"\"\"\n        if not self.closed and not self.closing:\n            self.closing = True\n            self.server._trigger_event(\n                'disconnect', self.sid,\n                reason or self.server.reason.SERVER_DISCONNECT,\n                run_async=False)\n            if not abort:\n                self.send(packet.Packet(packet.CLOSE))\n            self.closed = True\n            self.queue.put(None)\n            if wait:\n                self.queue.join()\n\n    def schedule_ping(self):\n        self.server.start_background_task(self._send_ping)\n\n    def _send_ping(self):\n        self.last_ping = None\n        self.server.sleep(self.server.ping_interval)\n        if not self.closing and not self.closed:\n            self.last_ping = time.time()\n            self.send(packet.Packet(packet.PING))\n\n    def _upgrade_websocket(self, environ, start_response):\n        \"\"\"Upgrade the connection from polling to websocket.\"\"\"\n        if self.upgraded:\n            raise OSError('Socket has been upgraded already')\n        if self.server._async['websocket'] is None:\n            # the selected async mode does not support websocket\n            return self.server._bad_request()\n        ws = self.server._async['websocket'](\n            self._websocket_handler, self.server)\n        return ws(environ, start_response)\n\n    def _websocket_handler(self, ws):\n        \"\"\"Engine.IO handler for websocket transport.\"\"\"\n        def websocket_wait():\n            data = ws.wait()\n            if data and len(data) > self.server.max_http_buffer_size:\n                raise ValueError('packet is too large')\n            return data\n\n        # try to set a socket timeout matching the configured ping interval\n        # and timeout\n        for attr in ['_sock', 'socket']:  # pragma: no cover\n            if hasattr(ws, attr) and hasattr(getattr(ws, attr), 'settimeout'):\n                getattr(ws, attr).settimeout(\n                    self.server.ping_interval + self.server.ping_timeout)\n\n        if self.connected:\n            # the socket was already connected, so this is an upgrade\n            self.upgrading = True  # hold packet sends during the upgrade\n\n            pkt = websocket_wait()\n            decoded_pkt = packet.Packet(encoded_packet=pkt)\n            if decoded_pkt.packet_type != packet.PING or \\\n                    decoded_pkt.data != 'probe':\n                self.server.logger.info(\n                    '%s: Failed websocket upgrade, no PING packet', self.sid)\n                self.upgrading = False\n                return []\n            ws.send(packet.Packet(packet.PONG, data='probe').encode())\n            self.queue.put(packet.Packet(packet.NOOP))  # end poll\n\n            pkt = websocket_wait()\n            decoded_pkt = packet.Packet(encoded_packet=pkt)\n            if decoded_pkt.packet_type != packet.UPGRADE:\n                self.upgraded = False\n                self.server.logger.info(\n                    ('%s: Failed websocket upgrade, expected UPGRADE packet, '\n                     'received %s instead.'),\n                    self.sid, pkt)\n                self.upgrading = False\n                return []\n            self.upgraded = True\n            self.upgrading = False\n        else:\n            self.connected = True\n            self.upgraded = True\n\n        # start separate writer thread\n        def writer():\n            while True:\n                packets = None\n                try:\n                    packets = self.poll()\n                except exceptions.QueueEmpty:\n                    break\n                if not packets:\n                    # empty packet list returned -> connection closed\n                    break\n                try:\n                    for pkt in packets:\n                        ws.send(pkt.encode())\n                except:\n                    break\n            ws.close()\n\n        writer_task = self.server.start_background_task(writer)\n\n        self.server.logger.info(\n            '%s: Upgrade to websocket successful', self.sid)\n\n        while True:\n            p = None\n            try:\n                p = websocket_wait()\n            except Exception as e:\n                # if the socket is already closed, we can assume this is a\n                # downstream error of that\n                if not self.closed:  # pragma: no cover\n                    self.server.logger.info(\n                        '%s: Unexpected error \"%s\", closing connection',\n                        self.sid, str(e))\n                break\n            if p is None:\n                # connection closed by client\n                break\n            pkt = packet.Packet(encoded_packet=p)\n            try:\n                self.receive(pkt)\n            except exceptions.UnknownPacketError:  # pragma: no cover\n                pass\n            except exceptions.SocketIsClosedError:  # pragma: no cover\n                self.server.logger.info('Receive error -- socket is closed')\n                break\n            except:  # pragma: no cover\n                # if we get an unexpected exception we log the error and exit\n                # the connection properly\n                self.server.logger.exception('Unknown receive error')\n                break\n\n        self.queue.put(None)  # unlock the writer task so that it can exit\n        writer_task.join()\n        self.close(wait=False, abort=True,\n                   reason=self.server.reason.TRANSPORT_CLOSE)\n\n        return []\n"
  },
  {
    "path": "src/engineio/static_files.py",
    "content": "content_types = {\n    'css': 'text/css',\n    'gif': 'image/gif',\n    'html': 'text/html',\n    'jpg': 'image/jpeg',\n    'js': 'application/javascript',\n    'json': 'application/json',\n    'png': 'image/png',\n    'txt': 'text/plain',\n}\n\n\ndef get_static_file(path, static_files):\n    \"\"\"Return the local filename and content type for the requested static\n    file URL.\n\n    :param path: the path portion of the requested URL.\n    :param static_files: a static file configuration dictionary.\n\n    This function returns a dictionary with two keys, \"filename\" and\n    \"content_type\". If the requested URL does not match any static file, the\n    return value is None.\n    \"\"\"\n    extra_path = ''\n    if path in static_files:\n        f = static_files[path]\n    else:\n        f = None\n        while path != '':\n            path, last = path.rsplit('/', 1)\n            extra_path = '/' + last + extra_path\n            if path in static_files:\n                f = static_files[path]\n                break\n            elif path + '/' in static_files:\n                f = static_files[path + '/']\n                break\n    if f:\n        if isinstance(f, str):\n            f = {'filename': f}\n        else:\n            f = f.copy()  # in case it is mutated below\n        if f['filename'].endswith('/') and extra_path.startswith('/'):\n            extra_path = extra_path[1:]\n        f['filename'] += extra_path\n        if f['filename'].endswith('/'):\n            if '' in static_files:\n                if isinstance(static_files[''], str):\n                    f['filename'] += static_files['']\n                else:\n                    f['filename'] += static_files['']['filename']\n                    if 'content_type' in static_files['']:\n                        f['content_type'] = static_files['']['content_type']\n            else:\n                f['filename'] += 'index.html'\n        if 'content_type' not in f:\n            ext = f['filename'].rsplit('.')[-1]\n            f['content_type'] = content_types.get(\n                ext, 'application/octet-stream')\n    return f\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/async/__init__.py",
    "content": ""
  },
  {
    "path": "tests/async/files/file.txt",
    "content": "file\n"
  },
  {
    "path": "tests/async/files/index.html",
    "content": "<html>file</html>\n"
  },
  {
    "path": "tests/async/index.html",
    "content": "<html></html>\n"
  },
  {
    "path": "tests/async/test_aiohttp.py",
    "content": "from unittest import mock\n\nimport yarl\nfrom aiohttp.web import Request\n\nfrom engineio.async_drivers import aiohttp as async_aiohttp\n\n\nclass TestAiohttp:\n    def test_create_route(self):\n        app = mock.MagicMock()\n        mock_server = mock.MagicMock()\n        async_aiohttp.create_route(app, mock_server, '/foo')\n        app.router.add_get.assert_any_call('/foo', mock_server.handle_request)\n        app.router.add_post.assert_any_call('/foo', mock_server.handle_request)\n\n    def test_translate_request(self):\n        message = mock.MagicMock()\n        message.url = yarl.URL('https://example.com/foo/bar?baz=1')\n        message.method = 'PUT'\n        message.path = '/foo/bar?baz=1'\n        message.version = (1, 1)\n        message.headers = {\n            'a': 'b',\n            'c-c': 'd',\n            'c_c': 'e',\n            'content-type': 'application/json',\n            'content-length': 123,\n        }\n\n        request = Request(\n            message,\n            payload=b'hello world',\n            protocol=mock.MagicMock(),\n            payload_writer=mock.MagicMock(),\n            task=mock.MagicMock(),\n            loop=mock.MagicMock(),\n        )\n\n        environ = async_aiohttp.translate_request(request)\n        expected_environ = {\n            'REQUEST_METHOD': 'PUT',\n            'PATH_INFO': '/foo/bar',\n            'QUERY_STRING': 'baz=1',\n            'CONTENT_TYPE': 'application/json',\n            'CONTENT_LENGTH': 123,\n            'HTTP_A': 'b',\n            # 'HTTP_C_C': 'd,e',\n            'RAW_URI': '/foo/bar?baz=1',\n            'SERVER_PROTOCOL': 'HTTP/1.1',\n            'wsgi.input': b'hello world',\n            'aiohttp.request': request,\n        }\n        for k, v in expected_environ.items():\n            assert v == environ[k]\n        assert environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d'\n\n    # @mock.patch('async_aiohttp.aiohttp.web.Response')\n    def test_make_response(self):\n        rv = async_aiohttp.make_response(\n            '202 ACCEPTED', {'foo': 'bar'}, b'payload', {}\n        )\n        assert rv.status == 202\n        assert rv.headers['foo'] == 'bar'\n        assert rv.body == b'payload'\n"
  },
  {
    "path": "tests/async/test_asgi.py",
    "content": "import os\nfrom unittest import mock\n\nfrom engineio.async_drivers import asgi as async_asgi\n\n\nclass TestAsgi:\n    async def test_create_app(self):\n        app = async_asgi.ASGIApp(\n            'eio',\n            'other_app',\n            static_files='static_files',\n            engineio_path='/foo/',\n        )\n        assert app.engineio_server == 'eio'\n        assert app.other_asgi_app == 'other_app'\n        assert app.static_files == 'static_files'\n        assert app.engineio_path == '/foo/'\n\n    async def test_engineio_routing(self):\n        mock_server = mock.MagicMock()\n        mock_server.handle_request = mock.AsyncMock()\n\n        app = async_asgi.ASGIApp(mock_server)\n        scope = {'type': 'http', 'path': '/engine.io/'}\n        await app(scope, 'receive', 'send')\n        mock_server.handle_request.assert_awaited_once_with(\n            scope, 'receive', 'send'\n        )\n        mock_server.handle_request.reset_mock()\n        scope = {'type': 'http', 'path': '/engine.io/'}\n        await app(scope, 'receive', 'send')\n        mock_server.handle_request.assert_awaited_once_with(\n            scope, 'receive', 'send'\n        )\n        mock_server.handle_request.reset_mock()\n        scope = {'type': 'http', 'path': '/engine.iofoo/'}\n        await app(scope, 'receive', mock.AsyncMock())\n        mock_server.handle_request.assert_not_awaited()\n\n        app = async_asgi.ASGIApp(mock_server, engineio_path=None)\n        mock_server.handle_request.reset_mock()\n        scope = {'type': 'http', 'path': '/foo'}\n        await app(scope, 'receive', 'send')\n        mock_server.handle_request.assert_awaited_once_with(\n            scope, 'receive', 'send'\n        )\n\n        app = async_asgi.ASGIApp(mock_server, engineio_path='mysocket.io')\n        mock_server.handle_request.reset_mock()\n        scope = {'type': 'http', 'path': '/mysocket.io'}\n        await app(scope, 'receive', 'send')\n        mock_server.handle_request.assert_awaited_once_with(\n            scope, 'receive', 'send'\n        )\n        mock_server.handle_request.reset_mock()\n        scope = {'type': 'http', 'path': '/mysocket.io/'}\n        await app(scope, 'receive', 'send')\n        mock_server.handle_request.assert_awaited_once_with(\n            scope, 'receive', 'send'\n        )\n        mock_server.handle_request.reset_mock()\n        scope = {'type': 'http', 'path': '/mysocket.io/foo'}\n        await app(scope, 'receive', 'send')\n        mock_server.handle_request.assert_awaited_once_with(\n            scope, 'receive', 'send'\n        )\n        mock_server.handle_request.reset_mock()\n        scope = {'type': 'http', 'path': '/mysocket.iofoo'}\n        await app(scope, 'receive', mock.AsyncMock())\n        mock_server.handle_request.assert_not_awaited()\n\n    async def test_other_app_routing(self):\n        other_app = mock.AsyncMock()\n        app = async_asgi.ASGIApp('eio', other_app)\n        scope = {'type': 'http', 'path': '/foo'}\n        await app(scope, 'receive', 'send')\n        other_app.assert_awaited_once_with(scope, 'receive', 'send')\n\n    async def test_other_app_lifespan_routing(self):\n        other_app = mock.AsyncMock()\n        app = async_asgi.ASGIApp('eio', other_app)\n        scope = {'type': 'lifespan'}\n        await app(scope, 'receive', 'send')\n        other_app.assert_awaited_once_with(scope, 'receive', 'send')\n\n    async def test_static_file_routing(self):\n        root_dir = os.path.dirname(__file__)\n        app = async_asgi.ASGIApp(\n            'eio',\n            static_files={\n                '/': root_dir + '/index.html',\n                '/foo': {\n                    'content_type': 'text/plain',\n                    'filename': root_dir + '/index.html',\n                },\n                '/static': root_dir,\n                '/static/test/': root_dir + '/',\n                '/static2/test/': {'filename': root_dir + '/',\n                                   'content_type': 'image/gif'},\n            },\n        )\n\n        async def check_path(path, status_code, content_type, body):\n            scope = {'type': 'http', 'path': path}\n            receive = mock.AsyncMock(return_value={'type': 'http.request'})\n            send = mock.AsyncMock()\n            await app(scope, receive, send)\n            send.assert_any_await(\n                {\n                    'type': 'http.response.start',\n                    'status': status_code,\n                    'headers': [\n                        (b'Content-Type', content_type.encode('utf-8'))\n                    ],\n                }\n            )\n            send.assert_any_await(\n                {'type': 'http.response.body', 'body': body.encode('utf-8')}\n            )\n\n        await check_path('/', 200, 'text/html', '<html></html>\\n')\n        await check_path('/foo', 200, 'text/plain', '<html></html>\\n')\n        await check_path('/foo/bar', 404, 'text/plain', 'Not Found')\n        await check_path('/static/index.html', 200, 'text/html',\n                         '<html></html>\\n')\n        await check_path('/static/foo.bar', 404, 'text/plain', 'Not Found')\n        await check_path(\n            '/static/test/index.html', 200, 'text/html', '<html></html>\\n'\n        )\n        await check_path('/static/test/index.html', 200, 'text/html',\n                         '<html></html>\\n')\n        await check_path('/static/test/files/', 200, 'text/html',\n                         '<html>file</html>\\n')\n        await check_path('/static/test/files/file.txt', 200, 'text/plain',\n                         'file\\n')\n        await check_path('/static/test/files/x.html', 404, 'text/plain',\n                         'Not Found')\n        await check_path('/static2/test/', 200, 'image/gif', '<html></html>\\n')\n        await check_path('/static2/test/index.html', 200, 'image/gif',\n                         '<html></html>\\n')\n        await check_path('/static2/test/files/', 200, 'image/gif',\n                         '<html>file</html>\\n')\n        await check_path('/static2/test/files/file.txt', 200, 'image/gif',\n                         'file\\n')\n        await check_path('/static2/test/files/x.html', 404, 'text/plain',\n                         'Not Found')\n        await check_path('/bar/foo', 404, 'text/plain', 'Not Found')\n        await check_path('', 404, 'text/plain', 'Not Found')\n\n        app.static_files[''] = 'index.html'\n        await check_path('/static/test/', 200, 'text/html', '<html></html>\\n')\n\n        app.static_files[''] = {'filename': 'index.html'}\n        await check_path('/static/test/', 200, 'text/html', '<html></html>\\n')\n\n        app.static_files[''] = {\n            'filename': 'index.html',\n            'content_type': 'image/gif',\n        }\n        await check_path('/static/test/', 200, 'image/gif', '<html></html>\\n')\n\n        app.static_files[''] = {'filename': 'test.gif'}\n        await check_path('/static/test/', 404, 'text/plain', 'Not Found')\n\n        app.static_files = {}\n        await check_path('/static/test/index.html', 404, 'text/plain',\n                         'Not Found')\n\n    async def test_lifespan_startup(self):\n        app = async_asgi.ASGIApp('eio')\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.startup'},\n                                              {'type': 'lifespan.shutdown'}])\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_any_await(\n            {'type': 'lifespan.startup.complete'}\n        )\n\n    async def test_lifespan_startup_sync_function(self):\n        up = False\n\n        def startup():\n            nonlocal up\n            up = True\n\n        app = async_asgi.ASGIApp('eio', on_startup=startup)\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.startup'},\n                                              {'type': 'lifespan.shutdown'}])\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_any_await(\n            {'type': 'lifespan.startup.complete'}\n        )\n        assert up\n\n    async def test_lifespan_startup_async_function(self):\n        up = False\n\n        async def startup():\n            nonlocal up\n            up = True\n\n        app = async_asgi.ASGIApp('eio', on_startup=startup)\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.startup'},\n                                              {'type': 'lifespan.shutdown'}])\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_any_await(\n            {'type': 'lifespan.startup.complete'}\n        )\n        assert up\n\n    async def test_lifespan_startup_function_exception(self):\n        up = False\n\n        def startup():\n            raise Exception\n\n        app = async_asgi.ASGIApp('eio', on_startup=startup)\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.startup'}])\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_awaited_once_with({'type': 'lifespan.startup.failed'})\n        assert not up\n\n    async def test_lifespan_shutdown(self):\n        app = async_asgi.ASGIApp('eio')\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(return_value={'type': 'lifespan.shutdown'})\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_awaited_once_with(\n            {'type': 'lifespan.shutdown.complete'}\n        )\n\n    async def test_lifespan_shutdown_sync_function(self):\n        down = False\n\n        def shutdown():\n            nonlocal down\n            down = True\n\n        app = async_asgi.ASGIApp('eio', on_shutdown=shutdown)\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(return_value={'type': 'lifespan.shutdown'})\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_awaited_once_with(\n            {'type': 'lifespan.shutdown.complete'}\n        )\n        assert down\n\n    async def test_lifespan_shutdown_async_function(self):\n        down = False\n\n        async def shutdown():\n            nonlocal down\n            down = True\n\n        app = async_asgi.ASGIApp('eio', on_shutdown=shutdown)\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(return_value={'type': 'lifespan.shutdown'})\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_awaited_once_with(\n            {'type': 'lifespan.shutdown.complete'}\n        )\n        assert down\n\n    async def test_lifespan_shutdown_function_exception(self):\n        down = False\n\n        def shutdown():\n            raise Exception\n\n        app = async_asgi.ASGIApp('eio', on_shutdown=shutdown)\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(return_value={'type': 'lifespan.shutdown'})\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_awaited_once_with({'type': 'lifespan.shutdown.failed'})\n        assert not down\n\n    async def test_lifespan_invalid(self):\n        app = async_asgi.ASGIApp('eio')\n        scope = {'type': 'lifespan'}\n        receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.foo'},\n                                              {'type': 'lifespan.shutdown'}])\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_awaited_once_with(\n            {'type': 'lifespan.shutdown.complete'}\n        )\n\n    async def test_not_found(self):\n        app = async_asgi.ASGIApp('eio')\n        scope = {'type': 'http', 'path': '/foo'}\n        receive = mock.AsyncMock(return_value={'type': 'http.request'})\n        send = mock.AsyncMock()\n        await app(scope, receive, send)\n        send.assert_any_await(\n            {\n                'type': 'http.response.start',\n                'status': 404,\n                'headers': [(b'Content-Type', b'text/plain')],\n            }\n        )\n        send.assert_any_await(\n            {'type': 'http.response.body', 'body': b'Not Found'}\n        )\n\n    async def test_translate_request(self):\n        receive = mock.AsyncMock(\n            return_value={'type': 'http.request', 'body': b'hello world'}\n        )\n        send = mock.AsyncMock()\n        environ = await async_asgi.translate_request(\n            {\n                'type': 'http',\n                'method': 'PUT',\n                'headers': [\n                    (b'a', b'b'),\n                    (b'c-c', b'd'),\n                    (b'c_c', b'e'),\n                    (b'content-type', b'application/json'),\n                    (b'content-length', b'123'),\n                ],\n                'path': '/foo/bar',\n                'query_string': b'baz=1',\n            },\n            receive,\n            send,\n        )\n        expected_environ = {\n            'REQUEST_METHOD': 'PUT',\n            'PATH_INFO': '/foo/bar',\n            'QUERY_STRING': 'baz=1',\n            'CONTENT_TYPE': 'application/json',\n            'CONTENT_LENGTH': '123',\n            'HTTP_A': 'b',\n            # 'HTTP_C_C': 'd,e',\n            'RAW_URI': '/foo/bar?baz=1',\n            'SERVER_PROTOCOL': 'HTTP/1.1',\n            'asgi.receive': receive,\n            'asgi.send': send,\n        }\n        for k, v in expected_environ.items():\n            assert v == environ[k]\n        assert environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d'\n        body = await environ['wsgi.input'].read()\n        assert body == b'hello world'\n\n    async def test_translate_request_no_query_string(self):\n        receive = mock.AsyncMock(\n            return_value={'type': 'http.request', 'body': b'hello world'}\n        )\n        send = mock.AsyncMock()\n        environ = await async_asgi.translate_request(\n            {\n                'type': 'http',\n                'method': 'PUT',\n                'headers': [\n                    (b'a', b'b'),\n                    (b'c-c', b'd'),\n                    (b'c_c', b'e'),\n                    (b'content-type', b'application/json'),\n                    (b'content-length', b'123'),\n                ],\n                'path': '/foo/bar',\n            },\n            receive,\n            send,\n        )\n        expected_environ = {\n            'REQUEST_METHOD': 'PUT',\n            'PATH_INFO': '/foo/bar',\n            'QUERY_STRING': '',\n            'CONTENT_TYPE': 'application/json',\n            'CONTENT_LENGTH': '123',\n            'HTTP_A': 'b',\n            # 'HTTP_C_C': 'd,e',\n            'RAW_URI': '/foo/bar',\n            'SERVER_PROTOCOL': 'HTTP/1.1',\n            'asgi.receive': receive,\n            'asgi.send': send,\n        }\n        for k, v in expected_environ.items():\n            assert v == environ[k]\n        assert environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d'\n        body = await environ['wsgi.input'].read()\n        assert body == b'hello world'\n\n    async def test_translate_request_with_large_body(self):\n        receive = mock.AsyncMock(\n            side_effect=[\n                {'type': 'http.request', 'body': b'hello ', 'more_body': True},\n                {'type': 'http.request', 'body': b'world', 'more_body': True},\n                {'type': 'foo.bar'},  # should stop parsing here\n                {'type': 'http.request', 'body': b'!!!'},\n            ]\n        )\n        send = mock.AsyncMock()\n        environ = await async_asgi.translate_request(\n            {\n                'type': 'http',\n                'method': 'PUT',\n                'headers': [\n                    (b'a', b'b'),\n                    (b'c-c', b'd'),\n                    (b'c_c', b'e'),\n                    (b'content-type', b'application/json'),\n                    (b'content-length', b'123'),\n                ],\n                'path': '/foo/bar',\n                'query_string': b'baz=1',\n            },\n            receive,\n            send,\n        )\n        expected_environ = {\n            'REQUEST_METHOD': 'PUT',\n            'PATH_INFO': '/foo/bar',\n            'QUERY_STRING': 'baz=1',\n            'CONTENT_TYPE': 'application/json',\n            'CONTENT_LENGTH': '123',\n            'HTTP_A': 'b',\n            # 'HTTP_C_C': 'd,e',\n            'RAW_URI': '/foo/bar?baz=1',\n            'SERVER_PROTOCOL': 'HTTP/1.1',\n            'asgi.receive': receive,\n            'asgi.send': send,\n        }\n        for k, v in expected_environ.items():\n            assert v == environ[k]\n        assert environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d'\n        body = await environ['wsgi.input'].read()\n        assert body == b'hello world'\n\n    async def test_translate_websocket_request(self):\n        receive = mock.AsyncMock(return_value={'type': 'websocket.connect'})\n        send = mock.AsyncMock()\n        await async_asgi.translate_request(\n            {\n                'type': 'websocket',\n                'headers': [\n                    (b'a', b'b'),\n                    (b'c-c', b'd'),\n                    (b'c_c', b'e'),\n                    (b'content-type', b'application/json'),\n                    (b'content-length', b'123'),\n                ],\n                'path': '/foo/bar',\n                'query_string': b'baz=1',\n            },\n            receive,\n            send,\n        )\n        send.assert_not_awaited()\n\n    async def test_translate_unknown_request(self):\n        receive = mock.AsyncMock(return_value={'type': 'http.foo'})\n        send = mock.AsyncMock()\n        environ = await async_asgi.translate_request(\n            {'type': 'http', 'path': '/foo/bar', 'query_string': b'baz=1'},\n            receive,\n            send,\n        )\n        assert environ == {}\n\n    async def test_translate_request_bad_unicode(self):\n        receive = mock.AsyncMock(return_value={'type': 'http.request',\n                                               'body': b'foo'})\n        send = mock.AsyncMock()\n        environ = await async_asgi.translate_request(\n            {\n                'type': 'http.request',\n                'headers': [\n                    (b'a', b'b'),\n                    (b'c', b'\\xa0'),\n                    (b'e', b'f'),\n                ],\n                'path': '/foo/bar',\n                'query_string': b'baz=1&bad=\\xa0',\n            },\n            receive,\n            send,\n        )\n        assert environ['HTTP_A'] == 'b'\n        assert environ['HTTP_E'] == 'f'\n        assert 'HTTP_C' not in environ\n        assert environ['QUERY_STRING'] == ''\n        assert environ['RAW_URI'] == '/foo/bar'\n\n    async def test_make_response(self):\n        environ = {'asgi.send': mock.AsyncMock(),\n                   'asgi.scope': {'type': 'http'}}\n        await async_asgi.make_response(\n            '202 ACCEPTED', [('foo', 'bar')], b'payload', environ\n        )\n        environ['asgi.send'].assert_any_await(\n            {\n                'type': 'http.response.start',\n                'status': 202,\n                'headers': [(b'foo', b'bar')],\n            }\n        )\n        environ['asgi.send'].assert_any_await(\n            {'type': 'http.response.body', 'body': b'payload'}\n        )\n\n    async def test_make_response_websocket_accept(self):\n        environ = {\n            'asgi.send': mock.AsyncMock(),\n            'asgi.scope': {'type': 'websocket'},\n        }\n        await async_asgi.make_response(\n            '200 OK', [('foo', 'bar')], b'payload', environ\n        )\n        environ['asgi.send'].assert_awaited_with(\n            {'type': 'websocket.accept', 'headers': [(b'foo', b'bar')]}\n        )\n\n    async def test_make_response_websocket_reject(self):\n        environ = {\n            'asgi.send': mock.AsyncMock(),\n            'asgi.scope': {'type': 'websocket'},\n        }\n        await async_asgi.make_response(\n            '401 UNAUTHORIZED', [('foo', 'bar')], b'payload', environ\n        )\n        environ['asgi.send'].assert_awaited_with(\n            {'type': 'websocket.close', 'reason': 'payload'}\n        )\n\n    async def test_make_response_websocket_reject_no_payload(self):\n        environ = {\n            'asgi.send': mock.AsyncMock(),\n            'asgi.scope': {'type': 'websocket'},\n        }\n        await async_asgi.make_response(\n            '401 UNAUTHORIZED', [('foo', 'bar')], None, environ\n        )\n        environ['asgi.send'].assert_awaited_with(\n            {'type': 'websocket.close'}\n        )\n\n    async def test_sub_app_routing(self):\n\n        class ASGIDispatcher:\n            def __init__(self, routes):\n                self.routes = routes\n\n            async def __call__(self, scope, receive, send):\n                path = scope['path']\n                for prefix, app in self.routes.items():\n                    if path.startswith(prefix):\n                        await app(scope, receive, send)\n                        return\n                assert False, 'No route found'\n\n        other_app = mock.AsyncMock()\n        mock_server = mock.MagicMock()\n        mock_server.handle_request = mock.AsyncMock()\n        eio_app = async_asgi.ASGIApp(mock_server, engineio_path=None)\n        root_app = ASGIDispatcher({'/foo': other_app, '/eio': eio_app})\n        scope = {'type': 'http', 'path': '/foo/bar'}\n        await root_app(scope, 'receive', 'send')\n        other_app.assert_awaited_once_with(scope, 'receive', 'send')\n        scope = {'type': 'http', 'path': '/eio/'}\n        await root_app(scope, 'receive', 'send')\n        eio_app.engineio_server.handle_request.assert_awaited_once_with(\n            scope, 'receive', 'send')\n"
  },
  {
    "path": "tests/async/test_client.py",
    "content": "import asyncio\nimport ssl\nfrom unittest import mock\n\ntry:\n    import aiohttp\nexcept ImportError:\n    aiohttp = None\nimport pytest\n\nfrom engineio import async_client\nfrom engineio import base_client\nfrom engineio import exceptions\nfrom engineio import packet\nfrom engineio import payload\n\n\nclass TestAsyncClient:\n    def mock_queue(self, client):\n        client.queue = mock.MagicMock()\n        client.queue_empty = RuntimeError\n        client.queue.get_nowait.side_effect = client.queue_empty\n        client.queue.get = mock.AsyncMock()\n        client.queue.put = mock.AsyncMock()\n        client.queue.join = mock.AsyncMock()\n\n    @staticmethod\n    def mock_ws_timeout(ws_close):\n        return ws_close\n\n    async def test_is_asyncio_based(self):\n        c = async_client.AsyncClient()\n        assert c.is_asyncio_based()\n\n    async def test_already_connected(self):\n        c = async_client.AsyncClient()\n        c.state = 'connected'\n        with pytest.raises(ValueError):\n            await c.connect('http://foo')\n\n    async def test_invalid_transports(self):\n        c = async_client.AsyncClient()\n        with pytest.raises(ValueError):\n            await c.connect('http://foo', transports=['foo', 'bar'])\n\n    async def test_some_invalid_transports(self):\n        c = async_client.AsyncClient()\n        c._connect_websocket = mock.AsyncMock()\n        await c.connect('http://foo', transports=['foo', 'websocket', 'bar'])\n        assert c.transports == ['websocket']\n\n    async def test_connect_polling(self):\n        c = async_client.AsyncClient()\n        c._connect_polling = mock.AsyncMock(return_value='foo')\n        assert await c.connect('http://foo') == 'foo'\n        c._connect_polling.assert_awaited_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n        c = async_client.AsyncClient()\n        c._connect_polling = mock.AsyncMock(return_value='foo')\n        assert await c.connect('http://foo', transports=['polling']) == 'foo'\n        c._connect_polling.assert_awaited_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n        c = async_client.AsyncClient()\n        c._connect_polling = mock.AsyncMock(return_value='foo')\n        assert (\n            await c.connect('http://foo', transports=['polling', 'websocket'])\n            == 'foo'\n        )\n        c._connect_polling.assert_awaited_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n    async def test_connect_websocket(self):\n        c = async_client.AsyncClient()\n        c._connect_websocket = mock.AsyncMock(return_value='foo')\n        assert await c.connect('http://foo', transports=['websocket']) == 'foo'\n        c._connect_websocket.assert_awaited_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n        c = async_client.AsyncClient()\n        c._connect_websocket = mock.AsyncMock(return_value='foo')\n        assert await c.connect('http://foo', transports='websocket') == 'foo'\n        c._connect_websocket.assert_awaited_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n    async def test_connect_query_string(self):\n        c = async_client.AsyncClient()\n        c._connect_polling = mock.AsyncMock(return_value='foo')\n        assert await c.connect('http://foo?bar=baz') == 'foo'\n        c._connect_polling.assert_awaited_once_with(\n            'http://foo?bar=baz', {}, 'engine.io'\n        )\n\n    async def test_connect_custom_headers(self):\n        c = async_client.AsyncClient()\n        c._connect_polling = mock.AsyncMock(return_value='foo')\n        assert await c.connect('http://foo', headers={'Foo': 'Bar'}) == 'foo'\n        c._connect_polling.assert_awaited_once_with(\n            'http://foo', {'Foo': 'Bar'}, 'engine.io'\n        )\n\n    async def test_wait(self):\n        c = async_client.AsyncClient()\n        done = []\n\n        async def fake_read_look_task():\n            done.append(True)\n\n        c.read_loop_task = fake_read_look_task()\n        await c.wait()\n        assert done == [True]\n\n    async def test_wait_no_task(self):\n        c = async_client.AsyncClient()\n        c.read_loop_task = None\n        await c.wait()\n\n    async def test_send(self):\n        c = async_client.AsyncClient()\n        saved_packets = []\n\n        async def fake_send_packet(pkt):\n            saved_packets.append(pkt)\n\n        c._send_packet = fake_send_packet\n        await c.send('foo')\n        await c.send('foo')\n        await c.send(b'foo')\n        assert saved_packets[0].packet_type == packet.MESSAGE\n        assert saved_packets[0].data == 'foo'\n        assert not saved_packets[0].binary\n        assert saved_packets[1].packet_type == packet.MESSAGE\n        assert saved_packets[1].data == 'foo'\n        assert not saved_packets[1].binary\n        assert saved_packets[2].packet_type == packet.MESSAGE\n        assert saved_packets[2].data == b'foo'\n        assert saved_packets[2].binary\n\n    async def test_disconnect_not_connected(self):\n        c = async_client.AsyncClient()\n        c.state = 'foo'\n        c.sid = 'bar'\n        await c.disconnect()\n        assert c.state == 'disconnected'\n        assert c.sid is None\n\n    async def test_disconnect_polling(self):\n        c = async_client.AsyncClient()\n        base_client.connected_clients.append(c)\n        c.state = 'connected'\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.read_loop_task = mock.AsyncMock()()\n        c.ws = mock.MagicMock()\n        c.ws.close = mock.AsyncMock()\n        c._trigger_event = mock.AsyncMock()\n        await c.disconnect()\n        c.ws.close.assert_not_awaited()\n        assert c not in base_client.connected_clients\n        c._trigger_event.assert_awaited_once_with(\n            'disconnect', c.reason.CLIENT_DISCONNECT, run_async=False\n        )\n\n    async def test_disconnect_websocket(self):\n        c = async_client.AsyncClient()\n        base_client.connected_clients.append(c)\n        c.state = 'connected'\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.read_loop_task = mock.AsyncMock()()\n        c.ws = mock.MagicMock()\n        c.ws.close = mock.AsyncMock()\n        c._trigger_event = mock.AsyncMock()\n        await c.disconnect()\n        c.ws.close.assert_awaited_once_with()\n        assert c not in base_client.connected_clients\n        c._trigger_event.assert_awaited_once_with(\n            'disconnect', c.reason.CLIENT_DISCONNECT, run_async=False\n        )\n\n    async def test_disconnect_polling_abort(self):\n        c = async_client.AsyncClient()\n        base_client.connected_clients.append(c)\n        c.state = 'connected'\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.read_loop_task = mock.AsyncMock()()\n        c.ws = mock.MagicMock()\n        c.ws.close = mock.AsyncMock()\n        await c.disconnect(abort=True)\n        c.queue.join.assert_not_awaited()\n        c.ws.close.assert_not_awaited()\n        assert c not in base_client.connected_clients\n\n    async def test_disconnect_websocket_abort(self):\n        c = async_client.AsyncClient()\n        base_client.connected_clients.append(c)\n        c.state = 'connected'\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.read_loop_task = mock.AsyncMock()()\n        c.ws = mock.MagicMock()\n        c.ws.close = mock.AsyncMock()\n        await c.disconnect(abort=True)\n        c.queue.join.assert_not_awaited()\n        c.ws.assert_not_called()\n        assert c not in base_client.connected_clients\n\n    async def test_background_tasks(self):\n        r = []\n\n        async def foo(arg):\n            r.append(arg)\n\n        c = async_client.AsyncClient()\n        await c.start_background_task(foo, 'bar')\n        assert r == ['bar']\n\n    async def test_sleep(self):\n        c = async_client.AsyncClient()\n        await c.sleep(0)\n\n    async def test_create_queue(self):\n        c = async_client.AsyncClient()\n        q = c.create_queue()\n        with pytest.raises(c.queue_empty):\n            q.get_nowait()\n\n    async def test_create_event(self):\n        c = async_client.AsyncClient()\n        e = c.create_event()\n        assert not e.is_set()\n        e.set()\n        assert e.is_set()\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    async def test_polling_connection_failed(self, _time):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock(return_value=None)\n        with pytest.raises(exceptions.ConnectionError):\n            await c.connect('http://foo', headers={'Foo': 'Bar'})\n        c._send_request.assert_awaited_once_with(\n            'GET',\n            'http://foo/engine.io/?transport=polling&EIO=4&t=123.456',\n            headers={'Foo': 'Bar'},\n            timeout=5,\n        )\n\n    async def test_polling_connection_404(self):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 404\n        c._send_request.return_value.json = mock.AsyncMock(\n            return_value={'foo': 'bar'}\n        )\n        try:\n            await c.connect('http://foo')\n        except exceptions.ConnectionError as exc:\n            assert len(exc.args) == 2\n            assert (\n                exc.args[0] == 'Unexpected status code 404 in server response'\n            )\n            assert exc.args[1] == {'foo': 'bar'}\n\n    async def test_polling_connection_404_no_json(self):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 404\n        c._send_request.return_value.json = mock.AsyncMock(\n            side_effect=aiohttp.ContentTypeError('foo', 'bar')\n        )\n        try:\n            await c.connect('http://foo')\n        except exceptions.ConnectionError as exc:\n            assert len(exc.args) == 2\n            assert (\n                exc.args[0] == 'Unexpected status code 404 in server response'\n            )\n            assert exc.args[1] is None\n\n    async def test_polling_connection_invalid_packet(self):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        c._send_request.return_value.read = mock.AsyncMock(return_value=b'foo')\n        with pytest.raises(exceptions.ConnectionError):\n            await c.connect('http://foo')\n\n    async def test_polling_connection_no_open_packet(self):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        c._send_request.return_value.read = mock.AsyncMock(\n            return_value=payload.Payload(\n                packets=[\n                    packet.Packet(\n                        packet.CLOSE,\n                        {\n                            'sid': '123',\n                            'upgrades': [],\n                            'pingInterval': 10,\n                            'pingTimeout': 20,\n                        },\n                    )\n                ]\n            ).encode().encode('utf-8')\n        )\n        with pytest.raises(exceptions.ConnectionError):\n            await c.connect('http://foo')\n\n    async def test_polling_connection_successful(self):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        c._send_request.return_value.read = mock.AsyncMock(\n            return_value=payload.Payload(\n                packets=[\n                    packet.Packet(\n                        packet.OPEN,\n                        {\n                            'sid': '123',\n                            'upgrades': [],\n                            'pingInterval': 1000,\n                            'pingTimeout': 2000,\n                        },\n                    )\n                ]\n            ).encode().encode('utf-8')\n        )\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.AsyncMock()\n        c.on('connect', on_connect)\n        await c.connect('http://foo')\n\n        c._read_loop_polling.assert_called_once_with()\n        c._read_loop_websocket.assert_not_called()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_awaited_once_with()\n        assert c in base_client.connected_clients\n        assert (\n            c.base_url\n            == 'http://foo/engine.io/?transport=polling&EIO=4&sid=123'\n        )\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == []\n        assert c.transport() == 'polling'\n\n    async def test_polling_https_noverify_connection_successful(self):\n        c = async_client.AsyncClient(ssl_verify=False)\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        c._send_request.return_value.read = mock.AsyncMock(\n            return_value=payload.Payload(\n                packets=[\n                    packet.Packet(\n                        packet.OPEN,\n                        {\n                            'sid': '123',\n                            'upgrades': [],\n                            'pingInterval': 1000,\n                            'pingTimeout': 2000,\n                        },\n                    )\n                ]\n            ).encode().encode('utf-8')\n        )\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.AsyncMock()\n        c.on('connect', on_connect)\n        await c.connect('https://foo')\n\n        c._read_loop_polling.assert_called_once_with()\n        c._read_loop_websocket.assert_not_called()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_awaited_once_with()\n        assert c in base_client.connected_clients\n        assert (\n            c.base_url\n            == 'https://foo/engine.io/?transport=polling&EIO=4&sid=123'\n        )\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == []\n        assert c.transport() == 'polling'\n\n    async def test_polling_connection_with_more_packets(self):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        c._send_request.return_value.read = mock.AsyncMock(\n            return_value=payload.Payload(\n                packets=[\n                    packet.Packet(\n                        packet.OPEN,\n                        {\n                            'sid': '123',\n                            'upgrades': [],\n                            'pingInterval': 1000,\n                            'pingTimeout': 2000,\n                        },\n                    ),\n                    packet.Packet(packet.NOOP),\n                ]\n            ).encode().encode('utf-8')\n        )\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        c._receive_packet = mock.AsyncMock()\n        on_connect = mock.AsyncMock()\n        c.on('connect', on_connect)\n        await c.connect('http://foo')\n        assert c._receive_packet.await_count == 1\n        assert (\n            c._receive_packet.await_args_list[0][0][0].packet_type\n            == packet.NOOP\n        )\n\n    async def test_polling_connection_upgraded(self):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        c._send_request.return_value.read = mock.AsyncMock(\n            return_value=payload.Payload(\n                packets=[\n                    packet.Packet(\n                        packet.OPEN,\n                        {\n                            'sid': '123',\n                            'upgrades': ['websocket'],\n                            'pingInterval': 1000,\n                            'pingTimeout': 2000,\n                        },\n                    )\n                ]\n            ).encode().encode('utf-8')\n        )\n        c._connect_websocket = mock.AsyncMock(return_value=True)\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        await c.connect('http://foo')\n\n        c._connect_websocket.assert_awaited_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n        assert (\n            c.base_url\n            == 'http://foo/engine.io/?transport=polling&EIO=4&sid=123'\n        )\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == ['websocket']\n\n    async def test_polling_connection_not_upgraded(self):\n        c = async_client.AsyncClient()\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        c._send_request.return_value.read = mock.AsyncMock(\n            return_value=payload.Payload(\n                packets=[\n                    packet.Packet(\n                        packet.OPEN,\n                        {\n                            'sid': '123',\n                            'upgrades': ['websocket'],\n                            'pingInterval': 1000,\n                            'pingTimeout': 2000,\n                        },\n                    )\n                ]\n            ).encode().encode('utf-8')\n        )\n        c._connect_websocket = mock.AsyncMock(return_value=False)\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        await c.connect('http://foo')\n\n        c._connect_websocket.assert_awaited_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n        c._read_loop_polling.assert_called_once_with()\n        c._read_loop_websocket.assert_not_called()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch('engineio.async_client.aiohttp.ClientWSTimeout',\n                new=mock_ws_timeout)\n    async def test_websocket_connection_failed(self, _time):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock(\n            side_effect=[aiohttp.client_exceptions.ServerConnectionError()]\n        )\n        with pytest.raises(exceptions.ConnectionError):\n            await c.connect(\n                'http://foo',\n                transports=['websocket'],\n                headers={'Foo': 'Bar'},\n            )\n        c.http.ws_connect.assert_awaited_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            headers={'Foo': 'Bar'},\n            timeout=5\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    async def test_websocket_connection_extra(self, _time):\n        c = async_client.AsyncClient(websocket_extra_options={\n            'headers': {'Baz': 'Qux'},\n            'timeout': 10\n        })\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock(\n            side_effect=[aiohttp.client_exceptions.ServerConnectionError()]\n        )\n        with pytest.raises(exceptions.ConnectionError):\n            await c.connect(\n                'http://foo',\n                transports=['websocket'],\n                headers={'Foo': 'Bar'},\n            )\n        c.http.ws_connect.assert_awaited_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            headers={'Foo': 'Bar', 'Baz': 'Qux'},\n            timeout=10,\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch('engineio.async_client.aiohttp.ClientWSTimeout',\n                new=mock_ws_timeout)\n    async def test_websocket_upgrade_failed(self, _time):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock(\n            side_effect=[aiohttp.client_exceptions.ServerConnectionError()]\n        )\n        c.sid = '123'\n        assert not await c.connect('http://foo', transports=['websocket'])\n        c.http.ws_connect.assert_awaited_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&sid=123&t=123.456',\n            headers={},\n            timeout=5,\n        )\n\n    async def test_websocket_connection_no_open_packet(self):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock()\n        ws = c.http.ws_connect.return_value\n        ws.receive = mock.AsyncMock()\n        ws.receive.return_value.data = packet.Packet(\n            packet.CLOSE\n        ).encode()\n        with pytest.raises(exceptions.ConnectionError):\n            await c.connect('http://foo', transports=['websocket'])\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch('engineio.async_client.aiohttp.ClientWSTimeout',\n                new=mock_ws_timeout)\n    async def test_websocket_connection_successful(self, _time):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock()\n        ws = c.http.ws_connect.return_value\n        ws.receive = mock.AsyncMock()\n        ws.receive.return_value.data = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        await c.connect('ws://foo', transports=['websocket'])\n\n        c._read_loop_polling.assert_not_called()\n        c._read_loop_websocket.assert_called_once_with()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n        assert c.base_url == 'ws://foo/engine.io/?transport=websocket&EIO=4'\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == []\n        assert c.transport() == 'websocket'\n        assert c.ws == ws\n        c.http.ws_connect.assert_awaited_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            headers={},\n            timeout=5,\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    async def test_websocket_https_noverify_connection_successful(self, _time):\n        c = async_client.AsyncClient(ssl_verify=False)\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock()\n        ws = c.http.ws_connect.return_value\n        ws.receive = mock.AsyncMock()\n        ws.receive.return_value.data = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        await c.connect('wss://foo', transports=['websocket'])\n\n        c._read_loop_polling.assert_not_called()\n        c._read_loop_websocket.assert_called_once_with()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n        assert c.base_url == 'wss://foo/engine.io/?transport=websocket&EIO=4'\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == []\n        assert c.transport() == 'websocket'\n        assert c.ws == ws\n        _, kwargs = c.http.ws_connect.await_args\n        assert 'ssl' in kwargs\n        assert isinstance(kwargs['ssl'], ssl.SSLContext)\n        assert kwargs['ssl'].verify_mode == ssl.CERT_NONE\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch('engineio.async_client.aiohttp.ClientWSTimeout',\n                new=mock_ws_timeout)\n    async def test_websocket_connection_with_cookies(self, _time):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock()\n        ws = c.http.ws_connect.return_value\n        ws.receive = mock.AsyncMock()\n        ws.receive.return_value.data = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        c.http._cookie_jar = [mock.MagicMock(), mock.MagicMock()]\n        c.http._cookie_jar[0].key = 'key'\n        c.http._cookie_jar[0].value = 'value'\n        c.http._cookie_jar[1].key = 'key2'\n        c.http._cookie_jar[1].value = 'value2'\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        await c.connect('ws://foo', transports=['websocket'])\n        c.http.ws_connect.assert_awaited_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            headers={},\n            timeout=5,\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch('engineio.async_client.aiohttp.ClientWSTimeout',\n                new=mock_ws_timeout)\n    async def test_websocket_connection_with_cookie_header(self, _time):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock()\n        ws = c.http.ws_connect.return_value\n        ws.receive = mock.AsyncMock()\n        ws.receive.return_value.data = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        c.http._cookie_jar = []\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        await c.connect(\n            'ws://foo',\n            headers={'Cookie': 'key=value; key2=value2; key3=\"value3=\"'},\n            transports=['websocket'],\n        )\n        c.http.ws_connect.assert_awaited_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            headers={},\n            timeout=5,\n        )\n        c.http.cookie_jar.update_cookies.assert_called_once_with(\n            {'key': 'value', 'key2': 'value2', 'key3': 'value3='}\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch('engineio.async_client.aiohttp.ClientWSTimeout',\n                new=mock_ws_timeout)\n    async def test_websocket_connection_with_cookies_and_headers(self, _time):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock()\n        ws = c.http.ws_connect.return_value\n        ws.receive = mock.AsyncMock()\n        ws.receive.return_value.data = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        c.http._cookie_jar = [mock.MagicMock(), mock.MagicMock()]\n        c.http._cookie_jar[0].key = 'key'\n        c.http._cookie_jar[0].value = 'value'\n        c.http._cookie_jar[1].key = 'key2'\n        c.http._cookie_jar[1].value = 'value2'\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        await c.connect(\n            'ws://foo',\n            headers={'Foo': 'Bar', 'Cookie': 'key3=value3'},\n            transports=['websocket'],\n        )\n        c.http.ws_connect.assert_awaited_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            headers={'Foo': 'Bar'},\n            timeout=5,\n        )\n        c.http.cookie_jar.update_cookies.assert_called_once_with(\n            {'key3': 'value3'}\n        )\n\n    async def test_websocket_upgrade_no_pong(self):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock()\n        ws = c.http.ws_connect.return_value\n        ws.receive = mock.AsyncMock()\n        ws.receive.return_value.data = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        ws.send_str = mock.AsyncMock()\n        c.sid = '123'\n        c.current_transport = 'polling'\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        assert not await c.connect('ws://foo', transports=['websocket'])\n\n        c._read_loop_polling.assert_not_called()\n        c._read_loop_websocket.assert_not_called()\n        c._write_loop.assert_not_called()\n        on_connect.assert_not_called()\n        assert c.transport() == 'polling'\n        ws.send_str.assert_awaited_once_with('2probe')\n\n    async def test_websocket_upgrade_successful(self):\n        c = async_client.AsyncClient()\n        c.http = mock.MagicMock(closed=False)\n        c.http.ws_connect = mock.AsyncMock()\n        ws = c.http.ws_connect.return_value\n        ws.receive = mock.AsyncMock()\n        ws.receive.return_value.data = packet.Packet(\n            packet.PONG, 'probe'\n        ).encode()\n        ws.send_str = mock.AsyncMock()\n        c.sid = '123'\n        c.base_url = 'http://foo'\n        c.current_transport = 'polling'\n        c._read_loop_polling = mock.AsyncMock()\n        c._read_loop_websocket = mock.AsyncMock()\n        c._write_loop = mock.AsyncMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        assert await c.connect('ws://foo', transports=['websocket'])\n\n        c._read_loop_polling.assert_not_called()\n        c._read_loop_websocket.assert_called_once_with()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_not_called()  # was called by polling\n        assert c not in base_client.connected_clients  # was added by polling\n        assert c.base_url == 'http://foo'  # not changed\n        assert c.sid == '123'  # not changed\n        assert c.transport() == 'websocket'\n        assert c.ws == ws\n        assert ws.send_str.await_args_list[0] == (('2probe',),)  # ping\n        assert ws.send_str.await_args_list[1] == (('5',),)  # upgrade\n\n    async def test_receive_unknown_packet(self):\n        c = async_client.AsyncClient()\n        await c._receive_packet(packet.Packet(encoded_packet='9'))\n        # should be ignored\n\n    async def test_receive_noop_packet(self):\n        c = async_client.AsyncClient()\n        await c._receive_packet(packet.Packet(packet.NOOP))\n        # should be ignored\n\n    async def test_receive_ping_packet(self):\n        c = async_client.AsyncClient()\n        c._send_packet = mock.AsyncMock()\n        await c._receive_packet(packet.Packet(packet.PING))\n        assert c._send_packet.await_args_list[0][0][0].encode() == '3'\n\n    async def test_receive_message_packet(self):\n        c = async_client.AsyncClient()\n        c._trigger_event = mock.AsyncMock()\n        await c._receive_packet(packet.Packet(packet.MESSAGE, {'foo': 'bar'}))\n        c._trigger_event.assert_awaited_once_with(\n            'message', {'foo': 'bar'}, run_async=True\n        )\n\n    async def test_receive_close_packet(self):\n        c = async_client.AsyncClient()\n        c.disconnect = mock.AsyncMock()\n        await c._receive_packet(packet.Packet(packet.CLOSE))\n        c.disconnect.assert_awaited_once_with(\n            abort=True, reason=c.reason.SERVER_DISCONNECT)\n\n    async def test_send_packet_disconnected(self):\n        c = async_client.AsyncClient()\n        c.queue = c.create_queue()\n        c.state = 'disconnected'\n        await c._send_packet(packet.Packet(packet.NOOP))\n        assert c.queue.empty()\n\n    async def test_send_packet(self):\n        c = async_client.AsyncClient()\n        c.queue = c.create_queue()\n        c.state = 'connected'\n        await c._send_packet(packet.Packet(packet.NOOP))\n        assert not c.queue.empty()\n        pkt = await c.queue.get()\n        assert pkt.packet_type == packet.NOOP\n\n    async def test_trigger_event_function(self):\n        result = []\n\n        def foo_handler(arg):\n            result.append('ok')\n            result.append(arg)\n\n        c = async_client.AsyncClient()\n        c.on('message', handler=foo_handler)\n        await c._trigger_event('message', 'bar')\n        assert result == ['ok', 'bar']\n\n    async def test_trigger_event_coroutine(self):\n        result = []\n\n        async def foo_handler(arg):\n            result.append('ok')\n            result.append(arg)\n\n        c = async_client.AsyncClient()\n        c.on('message', handler=foo_handler)\n        await c._trigger_event('message', 'bar')\n        assert result == ['ok', 'bar']\n\n    async def test_trigger_event_function_error(self):\n        def connect_handler(arg):\n            return 1 / 0\n\n        def foo_handler(arg):\n            return 1 / 0\n\n        c = async_client.AsyncClient()\n        c.on('connect', handler=connect_handler)\n        c.on('message', handler=foo_handler)\n        assert not await c._trigger_event('connect', '123')\n        assert await c._trigger_event('message', 'bar') is None\n\n    async def test_trigger_event_coroutine_error(self):\n        async def connect_handler(arg):\n            return 1 / 0\n\n        async def foo_handler(arg):\n            return 1 / 0\n\n        c = async_client.AsyncClient()\n        c.on('connect', handler=connect_handler)\n        c.on('message', handler=foo_handler)\n        assert not await c._trigger_event('connect', '123')\n        assert await c._trigger_event('message', 'bar') is None\n\n    async def test_trigger_event_function_async(self):\n        result = []\n\n        def foo_handler(arg):\n            result.append('ok')\n            result.append(arg)\n\n        c = async_client.AsyncClient()\n        c.on('message', handler=foo_handler)\n        fut = await c._trigger_event('message', 'bar', run_async=True)\n        await fut\n        assert result == ['ok', 'bar']\n\n    async def test_trigger_event_coroutine_async(self):\n        result = []\n\n        async def foo_handler(arg):\n            result.append('ok')\n            result.append(arg)\n\n        c = async_client.AsyncClient()\n        c.on('message', handler=foo_handler)\n        fut = await c._trigger_event('message', 'bar', run_async=True)\n        await fut\n        assert result == ['ok', 'bar']\n\n    async def test_trigger_event_function_async_error(self):\n        result = []\n\n        def foo_handler(arg):\n            result.append(arg)\n            return 1 / 0\n\n        c = async_client.AsyncClient()\n        c.on('message', handler=foo_handler)\n        fut = await c._trigger_event('message', 'bar', run_async=True)\n        with pytest.raises(ZeroDivisionError):\n            await fut\n        assert result == ['bar']\n\n    async def test_trigger_event_coroutine_async_error(self):\n        result = []\n\n        async def foo_handler(arg):\n            result.append(arg)\n            return 1 / 0\n\n        c = async_client.AsyncClient()\n        c.on('message', handler=foo_handler)\n        fut = await c._trigger_event('message', 'bar', run_async=True)\n        with pytest.raises(ZeroDivisionError):\n            await fut\n        assert result == ['bar']\n\n    async def test_trigger_unknown_event(self):\n        c = async_client.AsyncClient()\n        await c._trigger_event('connect', run_async=False)\n        await c._trigger_event('message', 123, run_async=True)\n        # should do nothing\n\n    async def test_trigger_legacy_disconnect_event(self):\n        c = async_client.AsyncClient()\n\n        @c.on('disconnect')\n        def baz():\n            return 'baz'\n\n        r = await c._trigger_event('disconnect', 'foo')\n        assert r == 'baz'\n\n    async def test_trigger_legacy_disconnect_event_async(self):\n        c = async_client.AsyncClient()\n\n        @c.on('disconnect')\n        async def baz():\n            return 'baz'\n\n        r = await c._trigger_event('disconnect', 'foo')\n        assert r == 'baz'\n\n    async def test_read_loop_polling_disconnected(self):\n        c = async_client.AsyncClient()\n        c.state = 'disconnected'\n        c._trigger_event = mock.AsyncMock()\n        c.write_loop_task = mock.AsyncMock()()\n        await c._read_loop_polling()\n        c._trigger_event.assert_not_awaited()\n        # should not block\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    async def test_read_loop_polling_no_response(self, _time):\n        c = async_client.AsyncClient()\n        c.ping_interval = 25\n        c.ping_timeout = 5\n        c.state = 'connected'\n        c.base_url = 'http://foo'\n        self.mock_queue(c)\n        c._send_request = mock.AsyncMock(return_value=None)\n        c._trigger_event = mock.AsyncMock()\n        c.write_loop_task = mock.AsyncMock()()\n        await c._read_loop_polling()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_awaited_once_with(None)\n        c._send_request.assert_awaited_once_with(\n            'GET', 'http://foo&t=123.456', timeout=30\n        )\n        c._trigger_event.assert_awaited_once_with(\n            'disconnect', c.reason.TRANSPORT_ERROR, run_async=False\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    async def test_read_loop_polling_bad_status(self, _time):\n        c = async_client.AsyncClient()\n        c.ping_interval = 25\n        c.ping_timeout = 5\n        c.state = 'connected'\n        c.base_url = 'http://foo'\n        self.mock_queue(c)\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 400\n        c.write_loop_task = mock.AsyncMock()()\n        await c._read_loop_polling()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_awaited_once_with(None)\n        c._send_request.assert_awaited_once_with(\n            'GET', 'http://foo&t=123.456', timeout=30\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    async def test_read_loop_polling_bad_packet(self, _time):\n        c = async_client.AsyncClient()\n        c.ping_interval = 25\n        c.ping_timeout = 60\n        c.state = 'connected'\n        c.base_url = 'http://foo'\n        self.mock_queue(c)\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        c._send_request.return_value.read = mock.AsyncMock(return_value=b'foo')\n        c.write_loop_task = mock.AsyncMock()()\n        await c._read_loop_polling()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_awaited_once_with(None)\n        c._send_request.assert_awaited_once_with(\n            'GET', 'http://foo&t=123.456', timeout=65\n        )\n\n    async def test_read_loop_polling(self):\n        c = async_client.AsyncClient()\n        c.ping_interval = 25\n        c.ping_timeout = 5\n        c.state = 'connected'\n        c.base_url = 'http://foo'\n        self.mock_queue(c)\n        c._send_request = mock.AsyncMock()\n        c._send_request.side_effect = [\n            mock.MagicMock(\n                status=200,\n                read=mock.AsyncMock(\n                    return_value=payload.Payload(\n                        packets=[\n                            packet.Packet(packet.PING),\n                            packet.Packet(packet.NOOP),\n                        ]\n                    ).encode().encode('utf-8')\n                ),\n            ),\n            None,\n        ]\n        c.write_loop_task = mock.AsyncMock()()\n        c._receive_packet = mock.AsyncMock()\n        await c._read_loop_polling()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_awaited_once_with(None)\n        assert c._send_request.await_count == 2\n        assert c._receive_packet.await_count == 2\n        assert c._receive_packet.await_args_list[0][0][0].encode() == '2'\n        assert c._receive_packet.await_args_list[1][0][0].encode() == '6'\n\n    async def test_read_loop_websocket_disconnected(self):\n        c = async_client.AsyncClient()\n        c.state = 'disconnected'\n        c.write_loop_task = mock.AsyncMock()()\n        await c._read_loop_websocket()\n        # should not block\n\n    async def test_read_loop_websocket_timeout(self):\n        c = async_client.AsyncClient()\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.base_url = 'ws://foo'\n        c.state = 'connected'\n        self.mock_queue(c)\n        c.ws = mock.MagicMock()\n        c.ws.receive = mock.AsyncMock(side_effect=asyncio.TimeoutError())\n        c.write_loop_task = mock.AsyncMock()()\n        await c._read_loop_websocket()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_awaited_once_with(None)\n\n    async def test_read_loop_websocket_no_response(self):\n        c = async_client.AsyncClient()\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.base_url = 'ws://foo'\n        c.state = 'connected'\n        self.mock_queue(c)\n        c.ws = mock.MagicMock()\n        c.ws.receive = mock.AsyncMock(\n            side_effect=aiohttp.client_exceptions.ServerDisconnectedError()\n        )\n        c.write_loop_task = mock.AsyncMock()()\n        await c._read_loop_websocket()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_awaited_once_with(None)\n\n    async def test_read_loop_websocket_unexpected_error(self):\n        c = async_client.AsyncClient()\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.base_url = 'ws://foo'\n        c.state = 'connected'\n        self.mock_queue(c)\n        c.ws = mock.MagicMock()\n        c.ws.receive = mock.AsyncMock(side_effect=ValueError)\n        c.write_loop_task = mock.AsyncMock()()\n        await c._read_loop_websocket()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_awaited_once_with(None)\n\n    async def test_read_loop_websocket(self):\n        c = async_client.AsyncClient()\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.base_url = 'ws://foo'\n        c.state = 'connected'\n        self.mock_queue(c)\n        c.ws = mock.MagicMock()\n        c.ws.receive = mock.AsyncMock(\n            side_effect=[\n                mock.MagicMock(data=packet.Packet(packet.PING).encode()),\n                ValueError,\n            ]\n        )\n        c.write_loop_task = mock.AsyncMock()()\n        c._receive_packet = mock.AsyncMock()\n        await c._read_loop_websocket()\n        assert c.state == 'disconnected'\n        assert c._receive_packet.await_args_list[0][0][0].encode() == '2'\n        c.queue.put.assert_awaited_once_with(None)\n\n    async def test_write_loop_disconnected(self):\n        c = async_client.AsyncClient()\n        c.state = 'disconnected'\n        await c._write_loop()\n        # should not block\n\n    async def test_write_loop_no_packets(self):\n        c = async_client.AsyncClient()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(return_value=None)\n        await c._write_loop()\n        c.queue.task_done.assert_called_once_with()\n        c.queue.get.assert_awaited_once_with()\n\n    async def test_write_loop_empty_queue(self):\n        c = async_client.AsyncClient()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(side_effect=c.queue_empty)\n        await c._write_loop()\n        c.queue.get.assert_awaited_once_with()\n\n    async def test_write_loop_polling_one_packet(self):\n        c = async_client.AsyncClient()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                c.queue_empty,\n            ]\n        )\n        c.queue.get_nowait = mock.MagicMock(side_effect=c.queue_empty)\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        await c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        p = payload.Payload(\n            packets=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})]\n        )\n        c._send_request.assert_awaited_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n\n    async def test_write_loop_polling_three_packets(self):\n        c = async_client.AsyncClient()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                c.queue_empty,\n            ]\n        )\n        c.queue.get_nowait = mock.MagicMock(\n            side_effect=[\n                packet.Packet(packet.PING),\n                packet.Packet(packet.NOOP),\n                c.queue_empty,\n            ]\n        )\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        await c._write_loop()\n        assert c.queue.task_done.call_count == 3\n        p = payload.Payload(\n            packets=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                packet.Packet(packet.PING),\n                packet.Packet(packet.NOOP),\n            ]\n        )\n        c._send_request.assert_awaited_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n\n    async def test_write_loop_polling_two_packets_done(self):\n        c = async_client.AsyncClient()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                c.queue_empty,\n            ]\n        )\n        c.queue.get_nowait = mock.MagicMock(\n            side_effect=[packet.Packet(packet.PING), None]\n        )\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 200\n        await c._write_loop()\n        assert c.queue.task_done.call_count == 3\n        p = payload.Payload(\n            packets=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                packet.Packet(packet.PING),\n            ]\n        )\n        c._send_request.assert_awaited_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n        assert c.state == 'connected'\n\n    async def test_write_loop_polling_bad_connection(self):\n        c = async_client.AsyncClient()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})]\n        )\n        c.queue.get_nowait = mock.MagicMock(side_effect=[c.queue_empty])\n        c._send_request = mock.AsyncMock(return_value=None)\n        await c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        p = payload.Payload(\n            packets=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})]\n        )\n        c._send_request.assert_awaited_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n        assert c.state == 'connected'\n\n    async def test_write_loop_polling_bad_status(self):\n        c = async_client.AsyncClient()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})]\n        )\n        c.queue.get_nowait = mock.MagicMock(side_effect=[c.queue_empty])\n        c._send_request = mock.AsyncMock()\n        c._send_request.return_value.status = 500\n        await c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        p = payload.Payload(\n            packets=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})]\n        )\n        c._send_request.assert_awaited_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n        assert c.state == 'connected'\n        assert c.write_loop_task is None\n\n    async def test_write_loop_websocket_one_packet(self):\n        c = async_client.AsyncClient()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                c.queue_empty,\n            ]\n        )\n        c.queue.get_nowait = mock.MagicMock(side_effect=[c.queue_empty])\n        c.ws = mock.MagicMock()\n        c.ws.send_str = mock.AsyncMock()\n        await c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        assert c.ws.send_str.await_count == 1\n        c.ws.send_str.assert_awaited_once_with('4{\"foo\":\"bar\"}')\n\n    async def test_write_loop_websocket_three_packets(self):\n        c = async_client.AsyncClient()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                c.queue_empty,\n            ]\n        )\n        c.queue.get_nowait = mock.MagicMock(\n            side_effect=[\n                packet.Packet(packet.PING),\n                packet.Packet(packet.NOOP),\n                c.queue_empty,\n            ]\n        )\n        c.ws = mock.MagicMock()\n        c.ws.send_str = mock.AsyncMock()\n        await c._write_loop()\n        assert c.queue.task_done.call_count == 3\n        assert c.ws.send_str.await_count == 3\n        assert c.ws.send_str.await_args_list[0][0][0] == '4{\"foo\":\"bar\"}'\n        assert c.ws.send_str.await_args_list[1][0][0] == '2'\n        assert c.ws.send_str.await_args_list[2][0][0] == '6'\n\n    async def test_write_loop_websocket_one_packet_binary(self):\n        c = async_client.AsyncClient()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[packet.Packet(packet.MESSAGE, b'foo'), c.queue_empty]\n        )\n        c.queue.get_nowait = mock.MagicMock(side_effect=[c.queue_empty])\n        c.ws = mock.MagicMock()\n        c.ws.send_bytes = mock.AsyncMock()\n        await c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        assert c.ws.send_bytes.await_count == 1\n        c.ws.send_bytes.assert_awaited_once_with(b'foo')\n\n    async def test_write_loop_websocket_bad_connection(self):\n        c = async_client.AsyncClient()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.queue.get = mock.AsyncMock(\n            side_effect=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                c.queue_empty,\n            ]\n        )\n        c.queue.get_nowait = mock.MagicMock(side_effect=[c.queue_empty])\n        c.ws = mock.MagicMock()\n        c.ws.send_str = mock.AsyncMock(\n            side_effect=aiohttp.client_exceptions.ServerDisconnectedError()\n        )\n        await c._write_loop()\n        assert c.state == 'connected'\n\n    @mock.patch('engineio.base_client.original_signal_handler')\n    async def test_signal_handler(self, original_handler):\n        clients = [mock.MagicMock(), mock.MagicMock()]\n        base_client.connected_clients = clients[:]\n        base_client.connected_clients[0].is_asyncio_based.return_value = False\n        base_client.connected_clients[1].is_asyncio_based.return_value = True\n        base_client.connected_clients[1].disconnect = mock.AsyncMock()\n\n        async_client.async_signal_handler()\n        with pytest.raises(asyncio.CancelledError):\n            await asyncio.sleep(0)\n\n        clients[0].disconnect.assert_not_called()\n        clients[1].disconnect.assert_called_once_with()\n"
  },
  {
    "path": "tests/async/test_sanic.py",
    "content": "from engineio.async_drivers import sanic as async_sanic  # noqa: F401\n"
  },
  {
    "path": "tests/async/test_server.py",
    "content": "import asyncio\nimport gzip\nimport io\nimport logging\nfrom unittest import mock\nimport zlib\n\nimport pytest\n\nfrom engineio import async_server\nfrom engineio.async_drivers import aiohttp as async_aiohttp\nfrom engineio import exceptions\nfrom engineio import json\nfrom engineio import packet\nfrom engineio import payload\n\n\nclass TestAsyncServer:\n    @staticmethod\n    def get_async_mock(environ={'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''}):\n        if environ.get('QUERY_STRING'):\n            if 'EIO=' not in environ['QUERY_STRING']:\n                environ['QUERY_STRING'] = 'EIO=4&' + environ['QUERY_STRING']\n        else:\n            environ['QUERY_STRING'] = 'EIO=4'\n        a = mock.MagicMock()\n        a._async = {\n            'asyncio': True,\n            'create_route': mock.MagicMock(),\n            'translate_request': mock.MagicMock(),\n            'make_response': mock.MagicMock(),\n            'websocket': 'w',\n        }\n        a._async['translate_request'].return_value = environ\n        a._async['make_response'].return_value = 'response'\n        return a\n\n    def _get_mock_socket(self):\n        mock_socket = mock.MagicMock()\n        mock_socket.connected = False\n        mock_socket.closed = False\n        mock_socket.closing = False\n        mock_socket.upgraded = False\n        mock_socket.send = mock.AsyncMock()\n        mock_socket.handle_get_request = mock.AsyncMock()\n        mock_socket.handle_post_request = mock.AsyncMock()\n        mock_socket.check_ping_timeout = mock.AsyncMock()\n        mock_socket.close = mock.AsyncMock()\n        mock_socket.session = {}\n        return mock_socket\n\n    @classmethod\n    def setup_class(cls):\n        async_server.AsyncServer._default_monitor_clients = False\n\n    @classmethod\n    def teardown_class(cls):\n        async_server.AsyncServer._default_monitor_clients = True\n\n    def setup_method(self):\n        logging.getLogger('engineio').setLevel(logging.NOTSET)\n\n    def teardown_method(self):\n        # restore JSON encoder, in case a test changed it\n        packet.Packet.json = json\n\n    async def test_is_asyncio_based(self):\n        s = async_server.AsyncServer()\n        assert s.is_asyncio_based()\n\n    async def test_async_modes(self):\n        s = async_server.AsyncServer()\n        assert s.async_modes() == ['aiohttp', 'sanic', 'tornado', 'asgi']\n\n    async def test_async_mode_aiohttp(self):\n        s = async_server.AsyncServer(async_mode='aiohttp')\n        assert s.async_mode == 'aiohttp'\n        assert s._async['asyncio']\n        assert s._async['create_route'] == async_aiohttp.create_route\n        assert s._async['translate_request'] == async_aiohttp.translate_request\n        assert s._async['make_response'] == async_aiohttp.make_response\n        assert s._async['websocket'].__name__ == 'WebSocket'\n\n    @mock.patch('importlib.import_module')\n    async def test_async_mode_auto_aiohttp(self, import_module):\n        import_module.side_effect = [self.get_async_mock()]\n        s = async_server.AsyncServer()\n        assert s.async_mode == 'aiohttp'\n\n    async def test_async_modes_wsgi(self):\n        with pytest.raises(ValueError):\n            async_server.AsyncServer(async_mode='eventlet')\n        with pytest.raises(ValueError):\n            async_server.AsyncServer(async_mode='gevent')\n        with pytest.raises(ValueError):\n            async_server.AsyncServer(async_mode='gevent_uwsgi')\n        with pytest.raises(ValueError):\n            async_server.AsyncServer(async_mode='threading')\n\n    @mock.patch('importlib.import_module')\n    async def test_attach(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.attach('app', engineio_path='abc')\n        a._async['create_route'].assert_called_with('app', s, '/abc/')\n        s.attach('app', engineio_path='/def/')\n        a._async['create_route'].assert_called_with('app', s, '/def/')\n        s.attach('app', engineio_path='/ghi')\n        a._async['create_route'].assert_called_with('app', s, '/ghi/')\n        s.attach('app', engineio_path='jkl/')\n        a._async['create_route'].assert_called_with('app', s, '/jkl/')\n\n    async def test_session(self):\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = self._get_mock_socket()\n\n        async def _func():\n            async with s.session('foo') as session:\n                await s.sleep(0)\n                session['username'] = 'bar'\n            assert await s.get_session('foo') == {'username': 'bar'}\n\n        await _func()\n\n    async def test_disconnect(self):\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        await s.disconnect('foo')\n        assert mock_socket.close.await_count == 1\n        mock_socket.close.assert_awaited_once_with(\n            reason=s.reason.SERVER_DISCONNECT)\n        assert 'foo' not in s.sockets\n\n    async def test_disconnect_all(self):\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_foo = self._get_mock_socket()\n        s.sockets['bar'] = mock_bar = self._get_mock_socket()\n        await s.disconnect()\n        assert mock_foo.close.await_count == 1\n        assert mock_bar.close.await_count == 1\n        mock_foo.close.assert_awaited_once_with(\n            reason=s.reason.SERVER_DISCONNECT)\n        mock_bar.close.assert_awaited_once_with(\n            reason=s.reason.SERVER_DISCONNECT)\n        assert 'foo' not in s.sockets\n        assert 'bar' not in s.sockets\n\n    @mock.patch('importlib.import_module')\n    async def test_jsonp_not_supported(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'j=abc'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        response = await s.handle_request('request')\n        assert response == 'response'\n        a._async['translate_request'].assert_called_once_with('request')\n        assert a._async['make_response'].call_count == 1\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    async def test_jsonp_index(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'j=233'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        response = await s.handle_request('request')\n        assert response == 'response'\n        a._async['translate_request'].assert_called_once_with('request')\n        assert a._async['make_response'].call_count == 1\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        assert (\n            a._async['make_response']\n            .call_args[0][2]\n            .startswith(b'___eio[233](\"')\n        )\n        assert a._async['make_response'].call_args[0][2].endswith(b'\");')\n\n    @mock.patch('importlib.import_module')\n    async def test_connect(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert len(s.sockets) == 1\n        assert a._async['make_response'].call_count == 1\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        assert ('Content-Type', 'text/plain; charset=UTF-8') in a._async[\n            'make_response'\n        ].call_args[0][1]\n        packets = payload.Payload(\n            encoded_payload=a._async['make_response'].call_args[0][2].decode(\n                'utf-8')).packets\n        assert len(packets) == 1\n        assert packets[0].packet_type == packet.OPEN\n        assert 'upgrades' in packets[0].data\n        assert packets[0].data['upgrades'] == ['websocket']\n        assert 'sid' in packets[0].data\n        assert packets[0].data['pingTimeout'] == 20000\n        assert packets[0].data['pingInterval'] == 25000\n        assert packets[0].data['maxPayload'] == 1000000\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_async_request_response_handlers(\n            self, import_module):\n        a = self.get_async_mock()\n        a._async['translate_request'] = mock.AsyncMock(\n            return_value=a._async['translate_request'].return_value\n        )\n        a._async['make_response'] = mock.AsyncMock(\n            return_value=a._async['make_response'].return_value\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert len(s.sockets) == 1\n        assert a._async['make_response'].await_count == 1\n        assert a._async['make_response'].await_args[0][0] == '200 OK'\n        assert ('Content-Type', 'text/plain; charset=UTF-8') in a._async[\n            'make_response'\n        ].await_args[0][1]\n        packets = payload.Payload(\n            encoded_payload=a._async['make_response'].await_args[0][\n                2].decode('utf-8')).packets\n        assert len(packets) == 1\n        assert packets[0].packet_type == packet.OPEN\n        assert 'upgrades' in packets[0].data\n        assert packets[0].data['upgrades'] == ['websocket']\n        assert 'sid' in packets[0].data\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_no_upgrades(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(allow_upgrades=False)\n        await s.handle_request('request')\n        packets = payload.Payload(\n            encoded_payload=a._async['make_response'].call_args[0][2].decode(\n                'utf-8')).packets\n        assert packets[0].data['upgrades'] == []\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_bad_eio_version(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=1'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert a._async['make_response'].call_count == 1\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n        assert b'unsupported version' in \\\n            a._async['make_response'].call_args[0][2]\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_custom_ping_times(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(ping_timeout=123, ping_interval=456,\n                                     max_http_buffer_size=12345678)\n        await s.handle_request('request')\n        packets = payload.Payload(\n            encoded_payload=a._async['make_response'].call_args[0][2].decode(\n                'utf-8')).packets\n        assert packets[0].data['pingTimeout'] == 123000\n        assert packets[0].data['pingInterval'] == 456000\n        assert packets[0].data['maxPayload'] == 12345678\n\n    @mock.patch('importlib.import_module')\n    @mock.patch('engineio.async_server.async_socket.AsyncSocket')\n    async def test_connect_bad_poll(self, AsyncSocket, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        AsyncSocket.return_value = self._get_mock_socket()\n        AsyncSocket.return_value.poll.side_effect = [exceptions.QueueEmpty]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert a._async['make_response'].call_count == 1\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    @mock.patch('engineio.async_server.async_socket.AsyncSocket')\n    async def test_connect_transport_websocket(self, AsyncSocket,\n                                               import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'transport=websocket',\n                'HTTP_UPGRADE': 'websocket',\n            }\n        )\n        import_module.side_effect = [a]\n        AsyncSocket.return_value = self._get_mock_socket()\n        s = async_server.AsyncServer()\n        s.generate_id = mock.MagicMock(return_value='123')\n        # force socket to stay open, so that we can check it later\n        AsyncSocket().closed = False\n        await s.handle_request('request')\n        assert (\n            s.sockets['123'].send.await_args[0][0].packet_type\n            == packet.OPEN\n        )\n\n    @mock.patch('importlib.import_module')\n    @mock.patch('engineio.async_server.async_socket.AsyncSocket')\n    async def test_http_upgrade_case_insensitive(self, AsyncSocket,\n                                                 import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'transport=websocket',\n                'HTTP_UPGRADE': 'WebSocket',\n            }\n        )\n        import_module.side_effect = [a]\n        AsyncSocket.return_value = self._get_mock_socket()\n        s = async_server.AsyncServer()\n        s.generate_id = mock.MagicMock(return_value='123')\n        # force socket to stay open, so that we can check it later\n        AsyncSocket().closed = False\n        await s.handle_request('request')\n        assert (\n            s.sockets['123'].send.await_args[0][0].packet_type\n            == packet.OPEN\n        )\n\n    @mock.patch('importlib.import_module')\n    @mock.patch('engineio.async_server.async_socket.AsyncSocket')\n    async def test_connect_transport_websocket_closed(\n            self, AsyncSocket, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'transport=websocket',\n                'HTTP_UPGRADE': 'websocket'\n            }\n        )\n        import_module.side_effect = [a]\n        AsyncSocket.return_value = self._get_mock_socket()\n        s = async_server.AsyncServer()\n        s.generate_id = mock.MagicMock(return_value='123')\n\n        # this mock handler just closes the socket, as it would happen on a\n        # real websocket exchange\n        async def mock_handle(environ):\n            s.sockets['123'].closed = True\n\n        AsyncSocket().handle_get_request = mock_handle\n        await s.handle_request('request')\n        assert '123' not in s.sockets  # socket should close on its own\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_transport_invalid(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert a._async['make_response'].call_count == 1\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_transport_websocket_without_upgrade(\n            self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=websocket'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert a._async['make_response'].call_count == 1\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_headers(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Credentials', 'true') in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_allowed_origin(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'b'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins=['a', 'b'])\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'b') in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_allowed_origin_with_callable(\n            self, import_module):\n        def cors(origin):\n            return origin == 'a'\n\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': '',\n            'HTTP_ORIGIN': 'a'\n        }\n        a = self.get_async_mock(environ)\n        import_module.side_effect = [a]\n\n        s = async_server.AsyncServer(cors_allowed_origins=cors)\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'a') in headers\n\n        environ['HTTP_ORIGIN'] = 'b'\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_not_allowed_origin(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'c'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins=['a', 'b'])\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'c') not in headers\n        assert ('Access-Control-Allow-Origin', '*') not in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_not_allowed_origin_async_response(\n        self, import_module\n    ):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'c'}\n        )\n        a._async['make_response'] = mock.AsyncMock(\n            return_value=a._async['make_response'].return_value\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins=['a', 'b'])\n        await s.handle_request('request')\n        assert (\n            a._async['make_response'].await_args[0][0] == '400 BAD REQUEST'\n        )\n        headers = a._async['make_response'].await_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'c') not in headers\n        assert ('Access-Control-Allow-Origin', '*') not in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_str_cors_all_origins(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins='*')\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'foo') in headers\n        assert ('Access-Control-Allow-Credentials', 'true') in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_list_cors_all_origins(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins=['*'])\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'foo') in headers\n        assert ('Access-Control-Allow-Credentials', 'true') in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_one_origin(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'a'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins='a')\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'a') in headers\n        assert ('Access-Control-Allow-Credentials', 'true') in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_one_origin_not_allowed(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'b'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins='a')\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'b') not in headers\n        assert ('Access-Control-Allow-Origin', '*') not in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_headers_default_origin(self, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': '',\n                'wsgi.url_scheme': 'http',\n                'HTTP_HOST': 'foo',\n                'HTTP_ORIGIN': 'http://foo',\n            }\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'http://foo') in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_no_credentials(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_credentials=False)\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Access-Control-Allow-Credentials', 'true') not in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_options(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'OPTIONS', 'QUERY_STRING': ''}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_credentials=False)\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        assert (\n            'Access-Control-Allow-Methods',\n            'OPTIONS, GET, POST',\n        ) in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_disabled(self, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': '',\n                'HTTP_ORIGIN': 'http://foo',\n            }\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins=[])\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        for header in headers:\n            assert not header[0].startswith('Access-Control-')\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_default_no_origin(self, import_module):\n        a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''})\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins=[])\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        for header in headers:\n            assert header[0] != 'Access-Control-Allow-Origin'\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_str_cors_all_no_origin(self, import_module):\n        a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''})\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins='*')\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        for header in headers:\n            assert header[0] != 'Access-Control-Allow-Origin'\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_list_cors_all_no_origin(self, import_module):\n        a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''})\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins=['*'])\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        for header in headers:\n            assert header[0] != 'Access-Control-Allow-Origin'\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_cors_disabled_no_origin(self, import_module):\n        a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''})\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cors_allowed_origins=[])\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        headers = a._async['make_response'].call_args[0][1]\n        for header in headers:\n            assert header[0] != 'Access-Control-Allow-Origin'\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_event(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.generate_id = mock.MagicMock(return_value='123')\n\n        def mock_connect(sid, environ):\n            return True\n\n        s.on('connect', handler=mock_connect)\n        await s.handle_request('request')\n        assert len(s.sockets) == 1\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_event_rejects(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.generate_id = mock.MagicMock(return_value='123')\n\n        def mock_connect(sid, environ):\n            return False\n\n        s.on('connect')(mock_connect)\n        await s.handle_request('request')\n        assert len(s.sockets) == 0\n        assert a._async['make_response'].call_args[0][0] == '401 UNAUTHORIZED'\n        assert a._async['make_response'].call_args[0][2] == b'\"Unauthorized\"'\n\n    @mock.patch('importlib.import_module')\n    async def test_connect_event_rejects_with_message(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.generate_id = mock.MagicMock(return_value='123')\n\n        def mock_connect(sid, environ):\n            return {'not': 'allowed'}\n\n        s.on('connect')(mock_connect)\n        await s.handle_request('request')\n        assert len(s.sockets) == 0\n        assert a._async['make_response'].call_args[0][0] == '401 UNAUTHORIZED'\n        assert (\n            a._async['make_response'].call_args[0][2] == b'{\"not\": \"allowed\"}'\n        )\n\n    @mock.patch('importlib.import_module')\n    async def test_method_not_found(self, import_module):\n        a = self.get_async_mock({'REQUEST_METHOD': 'PUT', 'QUERY_STRING': ''})\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert len(s.sockets) == 0\n        assert (\n            a._async['make_response'].call_args[0][0] == '405 METHOD NOT FOUND'\n        )\n\n    @mock.patch('importlib.import_module')\n    async def test_get_request_with_bad_sid(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert len(s.sockets) == 0\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    async def test_get_request_bad_websocket_transport(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET',\n             'QUERY_STRING': 'EIO=4&transport=websocket&sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.upgraded = False\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    async def test_get_request_bad_polling_transport(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET',\n             'QUERY_STRING': 'EIO=4&transport=polling&sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.upgraded = True\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    async def test_post_request_with_bad_sid(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        await s.handle_request('request')\n        assert len(s.sockets) == 0\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch('importlib.import_module')\n    async def test_send(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        await s.send('foo', 'hello')\n        assert mock_socket.send.await_count == 1\n        assert (\n            mock_socket.send.await_args[0][0].packet_type == packet.MESSAGE\n        )\n        assert mock_socket.send.await_args[0][0].data == 'hello'\n\n    @mock.patch('importlib.import_module')\n    async def test_send_unknown_socket(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        # just ensure no exceptions are raised\n        await s.send('foo', 'hello')\n\n    @mock.patch('importlib.import_module')\n    async def test_get_request(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request.return_value = [\n            packet.Packet(packet.MESSAGE, data='hello')\n        ]\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n        packets = payload.Payload(\n            encoded_payload=a._async['make_response'].call_args[0][2].decode(\n                'utf-8')\n        ).packets\n        assert len(packets) == 1\n        assert packets[0].packet_type == packet.MESSAGE\n\n    @mock.patch('importlib.import_module')\n    async def test_get_request_custom_response(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request.return_value = 'resp'\n        r = await s.handle_request('request')\n        assert r == 'resp'\n\n    @mock.patch('importlib.import_module')\n    async def test_get_request_closes_socket(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n\n        async def mock_get_request(*args, **kwargs):\n            mock_socket.closed = True\n            return 'resp'\n\n        mock_socket.handle_get_request = mock_get_request\n        r = await s.handle_request('request')\n        assert r == 'resp'\n        assert 'foo' not in s.sockets\n\n    @mock.patch('importlib.import_module')\n    async def test_get_request_error(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n\n        async def mock_get_request(*args, **kwargs):\n            raise exceptions.QueueEmpty()\n\n        mock_socket.handle_get_request = mock_get_request\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n        assert len(s.sockets) == 0\n\n    @mock.patch('importlib.import_module')\n    async def test_post_request(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = self._get_mock_socket()\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '200 OK'\n\n    @mock.patch('importlib.import_module')\n    async def test_post_request_error(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'sid=foo'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer()\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n\n        async def mock_post_request(*args, **kwargs):\n            raise exceptions.ContentTooLongError()\n\n        mock_socket.handle_post_request = mock_post_request\n        await s.handle_request('request')\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n\n    @staticmethod\n    def _gzip_decompress(b):\n        bytesio = io.BytesIO(b)\n        with gzip.GzipFile(fileobj=bytesio, mode='r') as gz:\n            return gz.read()\n\n    @mock.patch('importlib.import_module')\n    async def test_gzip_compression(self, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'sid=foo',\n                'HTTP_ACCEPT_ENCODING': 'gzip,deflate',\n            }\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(compression_threshold=0)\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request.return_value = [\n            packet.Packet(packet.MESSAGE, data='hello')\n        ]\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Content-Encoding', 'gzip') in headers\n        self._gzip_decompress(a._async['make_response'].call_args[0][2])\n\n    @mock.patch('importlib.import_module')\n    async def test_deflate_compression(self, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'sid=foo',\n                'HTTP_ACCEPT_ENCODING': 'deflate;q=1,gzip',\n            }\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(compression_threshold=0)\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request.return_value = [\n            packet.Packet(packet.MESSAGE, data='hello')\n        ]\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Content-Encoding', 'deflate') in headers\n        zlib.decompress(a._async['make_response'].call_args[0][2])\n\n    @mock.patch('importlib.import_module')\n    async def test_gzip_compression_threshold(self, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'sid=foo',\n                'HTTP_ACCEPT_ENCODING': 'gzip',\n            }\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(compression_threshold=1000)\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request.return_value = [\n            packet.Packet(packet.MESSAGE, data='hello')\n        ]\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        for header, value in headers:\n            assert header != 'Content-Encoding'\n        with pytest.raises(IOError):\n            print(a._async['make_response'].call_args[0][2])\n            self._gzip_decompress(a._async['make_response'].call_args[0][2])\n\n    @mock.patch('importlib.import_module')\n    async def test_compression_disabled(self, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'sid=foo',\n                'HTTP_ACCEPT_ENCODING': 'gzip',\n            }\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(\n            http_compression=False, compression_threshold=0\n        )\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request.return_value = [\n            packet.Packet(packet.MESSAGE, data='hello')\n        ]\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        for header, value in headers:\n            assert header != 'Content-Encoding'\n        with pytest.raises(IOError):\n            self._gzip_decompress(a._async['make_response'].call_args[0][2])\n\n    @mock.patch('importlib.import_module')\n    async def test_compression_unknown(self, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'sid=foo',\n                'HTTP_ACCEPT_ENCODING': 'rar',\n            }\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(compression_threshold=0)\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request.return_value = [\n            packet.Packet(packet.MESSAGE, data='hello')\n        ]\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        for header, value in headers:\n            assert header != 'Content-Encoding'\n        with pytest.raises(IOError):\n            self._gzip_decompress(a._async['make_response'].call_args[0][2])\n\n    @mock.patch('importlib.import_module')\n    async def test_compression_no_encoding(self, import_module):\n        a = self.get_async_mock(\n            {\n                'REQUEST_METHOD': 'GET',\n                'QUERY_STRING': 'sid=foo',\n                'HTTP_ACCEPT_ENCODING': '',\n            }\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(compression_threshold=0)\n        s.sockets['foo'] = mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request.return_value = [\n            packet.Packet(packet.MESSAGE, data='hello')\n        ]\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        for header, value in headers:\n            assert header != 'Content-Encoding'\n        with pytest.raises(IOError):\n            self._gzip_decompress(a._async['make_response'].call_args[0][2])\n\n    @mock.patch('importlib.import_module')\n    async def test_cookie(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cookie='sid')\n        s.generate_id = mock.MagicMock(return_value='123')\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Set-Cookie', 'sid=123; path=/; SameSite=Lax') in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_cookie_dict(self, import_module):\n        def get_path():\n            return '/a'\n\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cookie={\n            'name': 'test',\n            'path': get_path,\n            'SameSite': 'None',\n            'Secure': True,\n            'HttpOnly': True\n        })\n        s.generate_id = mock.MagicMock(return_value='123')\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        assert ('Set-Cookie', 'test=123; path=/a; SameSite=None; Secure; '\n                'HttpOnly') in headers\n\n    @mock.patch('importlib.import_module')\n    async def test_no_cookie(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(cookie=None)\n        s.generate_id = mock.MagicMock(return_value='123')\n        await s.handle_request('request')\n        headers = a._async['make_response'].call_args[0][1]\n        for header, value in headers:\n            assert header != 'Set-Cookie'\n\n    async def test_logger(self):\n        s = async_server.AsyncServer(logger=False)\n        assert s.logger.getEffectiveLevel() == logging.ERROR\n        s.logger.setLevel(logging.NOTSET)\n        s = async_server.AsyncServer(logger=True)\n        assert s.logger.getEffectiveLevel() == logging.INFO\n        s.logger.setLevel(logging.WARNING)\n        s = async_server.AsyncServer(logger=True)\n        assert s.logger.getEffectiveLevel() == logging.WARNING\n        s.logger.setLevel(logging.NOTSET)\n        my_logger = logging.Logger('foo')\n        s = async_server.AsyncServer(logger=my_logger)\n        assert s.logger == my_logger\n\n    async def test_custom_json(self):\n        # Warning: this test cannot run in parallel with other tests, as it\n        # changes the JSON encoding/decoding functions\n\n        class CustomJSON:\n            @staticmethod\n            def dumps(*args, **kwargs):\n                return '*** encoded ***'\n\n            @staticmethod\n            def loads(*args, **kwargs):\n                return '+++ decoded +++'\n\n        async_server.AsyncServer(json=CustomJSON)\n        pkt = packet.Packet(packet.MESSAGE, data={'foo': 'bar'})\n        assert pkt.encode() == '4*** encoded ***'\n        pkt2 = packet.Packet(encoded_packet=pkt.encode())\n        assert pkt2.data == '+++ decoded +++'\n\n        # restore the default JSON module\n        packet.Packet.json = json\n\n    async def test_background_tasks(self):\n        r = []\n\n        async def foo(arg):\n            r.append(arg)\n\n        async def main():\n            s = async_server.AsyncServer()\n            task = s.start_background_task(foo, 'bar')\n            await task\n\n        await main()\n        assert r == ['bar']\n\n    async def test_sleep(self):\n        s = async_server.AsyncServer()\n        await s.sleep(0)\n\n    async def test_trigger_event_function(self):\n        result = []\n\n        def foo_handler(arg):\n            result.append('ok')\n            result.append(arg)\n\n        s = async_server.AsyncServer()\n        s.on('message', handler=foo_handler)\n        await s._trigger_event('message', 'bar')\n        assert result == ['ok', 'bar']\n\n    async def test_trigger_event_coroutine(self):\n        result = []\n\n        async def foo_handler(arg):\n            result.append('ok')\n            result.append(arg)\n\n        s = async_server.AsyncServer()\n        s.on('message', handler=foo_handler)\n        await s._trigger_event('message', 'bar')\n        assert result == ['ok', 'bar']\n\n    async def test_trigger_event_function_error(self):\n        def connect_handler(arg):\n            return 1 / 0\n\n        def foo_handler(arg):\n            return 1 / 0\n\n        s = async_server.AsyncServer()\n        s.on('connect', handler=connect_handler)\n        s.on('message', handler=foo_handler)\n        assert not await s._trigger_event('connect', '123')\n        assert await s._trigger_event('message', 'bar') is None\n\n    async def test_trigger_event_coroutine_error(self):\n        async def connect_handler(arg):\n            return 1 / 0\n\n        async def foo_handler(arg):\n            return 1 / 0\n\n        s = async_server.AsyncServer()\n        s.on('connect', handler=connect_handler)\n        s.on('message', handler=foo_handler)\n        assert not await s._trigger_event('connect', '123')\n        assert await s._trigger_event('message', 'bar') is None\n\n    async def test_trigger_event_function_async(self):\n        result = []\n\n        def foo_handler(arg):\n            result.append('ok')\n            result.append(arg)\n\n        s = async_server.AsyncServer()\n        s.on('message', handler=foo_handler)\n        fut = await s._trigger_event('message', 'bar', run_async=True)\n        await fut\n        assert result == ['ok', 'bar']\n\n    async def test_trigger_event_coroutine_async(self):\n        result = []\n\n        async def foo_handler(arg):\n            result.append('ok')\n            result.append(arg)\n\n        s = async_server.AsyncServer()\n        s.on('message', handler=foo_handler)\n        fut = await s._trigger_event('message', 'bar', run_async=True)\n        await fut\n        assert result == ['ok', 'bar']\n\n    async def test_trigger_event_function_async_error(self):\n        result = []\n\n        def foo_handler(arg):\n            result.append(arg)\n            return 1 / 0\n\n        s = async_server.AsyncServer()\n        s.on('message', handler=foo_handler)\n        fut = await s._trigger_event('message', 'bar', run_async=True)\n        await fut\n        assert result == ['bar']\n\n    async def test_trigger_event_coroutine_async_error(self):\n        result = []\n\n        async def foo_handler(arg):\n            result.append(arg)\n            return 1 / 0\n\n        s = async_server.AsyncServer()\n        s.on('message', handler=foo_handler)\n        fut = await s._trigger_event('message', 'bar', run_async=True)\n        await fut\n        assert result == ['bar']\n\n    async def test_trigger_legacy_disconnect_event(self):\n        s = async_server.AsyncServer()\n\n        @s.on('disconnect')\n        def baz(sid):\n            return sid\n\n        r = await s._trigger_event('disconnect', 'foo', 'bar')\n        assert r == 'foo'\n\n    async def test_trigger_legacy_disconnect_event_async(self):\n        s = async_server.AsyncServer()\n\n        @s.on('disconnect')\n        async def baz(sid):\n            return sid\n\n        r = await s._trigger_event('disconnect', 'foo', 'bar')\n        assert r == 'foo'\n\n    async def test_create_queue(self):\n        s = async_server.AsyncServer()\n        q = s.create_queue()\n        empty = s.get_queue_empty_exception()\n        with pytest.raises(empty):\n            q.get_nowait()\n\n    async def test_create_event(self):\n        s = async_server.AsyncServer()\n        e = s.create_event()\n        assert not e.is_set()\n        e.set()\n        assert e.is_set()\n\n    @mock.patch('importlib.import_module')\n    async def test_service_task_started(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(monitor_clients=True)\n        s._service_task = mock.AsyncMock()\n        await s.handle_request('request')\n        await asyncio.sleep(0)\n        s._service_task.assert_awaited_once_with()\n\n    @mock.patch('importlib.import_module')\n    async def test_shutdown(self, import_module):\n        a = self.get_async_mock()\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(monitor_clients=True)\n        await s.handle_request('request')\n        await asyncio.sleep(0)\n        assert s.service_task_handle is not None\n        await s.shutdown()\n        assert s.service_task_handle is None\n\n    @mock.patch('importlib.import_module')\n    async def test_transports_disallowed(self, import_module):\n        a = self.get_async_mock(\n            {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=polling'}\n        )\n        import_module.side_effect = [a]\n        s = async_server.AsyncServer(transports='websocket')\n        response = await s.handle_request('request')\n        assert response == 'response'\n        a._async['translate_request'].assert_called_once_with('request')\n        assert a._async['make_response'].call_count == 1\n        assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST'\n"
  },
  {
    "path": "tests/async/test_socket.py",
    "content": "import asyncio\nimport time\nfrom unittest import mock\n\nimport pytest\n\nfrom engineio import async_socket\nfrom engineio import exceptions\nfrom engineio import packet\nfrom engineio import payload\n\n\nclass TestSocket:\n    def _get_read_mock_coro(self, payload):\n        mock_input = mock.MagicMock()\n        mock_input.read = mock.AsyncMock()\n        mock_input.read.return_value = payload\n        return mock_input\n\n    def _get_mock_server(self):\n        mock_server = mock.Mock()\n        mock_server.ping_timeout = 0.2\n        mock_server.ping_interval = 0.2\n        mock_server.ping_interval_grace_period = 0.001\n        mock_server.async_handlers = False\n        mock_server.max_http_buffer_size = 128\n        mock_server._async = {\n            'asyncio': True,\n            'create_route': mock.MagicMock(),\n            'translate_request': mock.MagicMock(),\n            'make_response': mock.MagicMock(),\n            'websocket': 'w',\n        }\n        mock_server._async['translate_request'].return_value = 'request'\n        mock_server._async['make_response'].return_value = 'response'\n        mock_server._trigger_event = mock.AsyncMock()\n\n        def bg_task(target, *args, **kwargs):\n            return asyncio.ensure_future(target(*args, **kwargs))\n\n        def create_queue(*args, **kwargs):\n            queue = asyncio.Queue(*args, **kwargs)\n            queue.Empty = asyncio.QueueEmpty\n            return queue\n\n        mock_server.start_background_task = bg_task\n        mock_server.create_queue = create_queue\n        return mock_server\n\n    async def test_create(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        assert s.server == mock_server\n        assert s.sid == 'sid'\n        assert not s.upgraded\n        assert not s.closed\n        assert hasattr(s.queue, 'get')\n        assert hasattr(s.queue, 'put')\n        assert hasattr(s.queue, 'task_done')\n        assert hasattr(s.queue, 'join')\n\n    async def test_empty_poll(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        with pytest.raises(exceptions.QueueEmpty):\n            await s.poll()\n\n    async def test_poll(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        pkt1 = packet.Packet(packet.MESSAGE, data='hello')\n        pkt2 = packet.Packet(packet.MESSAGE, data='bye')\n        await s.send(pkt1)\n        await s.send(pkt2)\n        assert await s.poll() == [pkt1, pkt2]\n\n    async def test_poll_none(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        await s.queue.put(None)\n        assert await s.poll() == []\n\n    async def test_poll_none_after_packet(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        pkt = packet.Packet(packet.MESSAGE, data='hello')\n        await s.send(pkt)\n        await s.queue.put(None)\n        assert await s.poll() == [pkt]\n        assert await s.poll() == []\n\n    async def test_schedule_ping(self):\n        mock_server = self._get_mock_server()\n        mock_server.ping_interval = 0.01\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.send = mock.AsyncMock()\n\n        async def schedule_ping():\n            s.schedule_ping()\n            await asyncio.sleep(0.05)\n\n        await schedule_ping()\n        assert s.last_ping is not None\n        assert s.send.await_args_list[0][0][0].encode() == '2'\n\n    async def test_schedule_ping_closed_socket(self):\n        mock_server = self._get_mock_server()\n        mock_server.ping_interval = 0.01\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.send = mock.AsyncMock()\n        s.closed = True\n\n        async def schedule_ping():\n            s.schedule_ping()\n            await asyncio.sleep(0.05)\n\n        await schedule_ping()\n        assert s.last_ping is None\n        s.send.assert_not_awaited()\n\n    async def test_pong(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.schedule_ping = mock.MagicMock()\n        await s.receive(packet.Packet(packet.PONG, data='abc'))\n        s.schedule_ping.assert_called_once_with()\n\n    async def test_message_sync_handler(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        await s.receive(packet.Packet(packet.MESSAGE, data='foo'))\n        mock_server._trigger_event.assert_awaited_once_with(\n            'message', 'sid', 'foo', run_async=False\n        )\n\n    async def test_message_async_handler(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        mock_server.async_handlers = True\n        await s.receive(packet.Packet(packet.MESSAGE, data='foo'))\n        mock_server._trigger_event.assert_awaited_once_with(\n            'message', 'sid', 'foo', run_async=True\n        )\n\n    async def test_invalid_packet(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        with pytest.raises(exceptions.UnknownPacketError):\n            await s.receive(packet.Packet(packet.OPEN))\n\n    async def test_timeout(self):\n        mock_server = self._get_mock_server()\n        mock_server.ping_interval = 6\n        mock_server.ping_interval_grace_period = 2\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.last_ping = time.time() - 9\n        s.close = mock.AsyncMock()\n        await s.send('packet')\n        s.close.assert_awaited_once_with(\n            wait=False, abort=False, reason=mock_server.reason.PING_TIMEOUT)\n\n    async def test_polling_read(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'foo')\n        pkt1 = packet.Packet(packet.MESSAGE, data='hello')\n        pkt2 = packet.Packet(packet.MESSAGE, data='bye')\n        await s.send(pkt1)\n        await s.send(pkt2)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        packets = await s.handle_get_request(environ)\n        assert packets == [pkt1, pkt2]\n\n    async def test_polling_read_error(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'foo')\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        with pytest.raises(exceptions.QueueEmpty):\n            await s.handle_get_request(environ)\n\n    async def test_polling_write(self):\n        mock_server = self._get_mock_server()\n        mock_server.max_http_buffer_size = 1000\n        pkt1 = packet.Packet(packet.MESSAGE, data='hello')\n        pkt2 = packet.Packet(packet.MESSAGE, data='bye')\n        p = payload.Payload(packets=[pkt1, pkt2]).encode().encode('utf-8')\n        s = async_socket.AsyncSocket(mock_server, 'foo')\n        s.receive = mock.AsyncMock()\n        environ = {\n            'REQUEST_METHOD': 'POST',\n            'QUERY_STRING': 'sid=foo',\n            'CONTENT_LENGTH': len(p),\n            'wsgi.input': self._get_read_mock_coro(p),\n        }\n        await s.handle_post_request(environ)\n        assert s.receive.await_count == 2\n\n    async def test_polling_write_too_large(self):\n        mock_server = self._get_mock_server()\n        pkt1 = packet.Packet(packet.MESSAGE, data='hello')\n        pkt2 = packet.Packet(packet.MESSAGE, data='bye')\n        p = payload.Payload(packets=[pkt1, pkt2]).encode().encode('utf-8')\n        mock_server.max_http_buffer_size = len(p) - 1\n        s = async_socket.AsyncSocket(mock_server, 'foo')\n        s.receive = mock.AsyncMock()\n        environ = {\n            'REQUEST_METHOD': 'POST',\n            'QUERY_STRING': 'sid=foo',\n            'CONTENT_LENGTH': len(p),\n            'wsgi.input': self._get_read_mock_coro(p),\n        }\n        with pytest.raises(exceptions.ContentTooLongError):\n            await s.handle_post_request(environ)\n\n    async def test_upgrade_handshake(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'foo')\n        s._upgrade_websocket = mock.AsyncMock()\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'sid=foo',\n            'HTTP_CONNECTION': 'Foo,Upgrade,Bar',\n            'HTTP_UPGRADE': 'websocket',\n        }\n        await s.handle_get_request(environ)\n        s._upgrade_websocket.assert_awaited_once_with(environ)\n\n    async def test_upgrade(self):\n        mock_server = self._get_mock_server()\n        mock_server._async['websocket'] = mock.MagicMock()\n        mock_ws = mock.AsyncMock()\n        mock_server._async['websocket'].return_value = mock_ws\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        environ = \"foo\"\n        await s._upgrade_websocket(environ)\n        mock_server._async['websocket'].assert_called_once_with(\n            s._websocket_handler, mock_server\n        )\n        mock_ws.assert_awaited_once_with(environ)\n\n    async def test_upgrade_twice(self):\n        mock_server = self._get_mock_server()\n        mock_server._async['websocket'] = mock.MagicMock()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        s.upgraded = True\n        environ = \"foo\"\n        with pytest.raises(IOError):\n            await s._upgrade_websocket(environ)\n\n    async def test_upgrade_packet(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        await s.receive(packet.Packet(packet.UPGRADE))\n        r = await s.poll()\n        assert len(r) == 1\n        assert r[0].encode() == packet.Packet(packet.NOOP).encode()\n\n    async def test_upgrade_no_probe(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        ws = mock.MagicMock()\n        ws.wait = mock.AsyncMock()\n        ws.wait.return_value = packet.Packet(packet.NOOP).encode()\n        await s._websocket_handler(ws)\n        assert not s.upgraded\n\n    async def test_upgrade_no_upgrade_packet(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.AsyncMock(return_value=None)\n        ws = mock.MagicMock()\n        ws.send = mock.AsyncMock()\n        ws.wait = mock.AsyncMock()\n        probe = 'probe'\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.NOOP).encode(),\n        ]\n        await s._websocket_handler(ws)\n        ws.send.assert_awaited_once_with(\n            packet.Packet(packet.PONG, data=probe).encode()\n        )\n        assert (await s.queue.get()).packet_type == packet.NOOP\n        assert not s.upgraded\n\n    async def test_upgrade_not_supported(self):\n        mock_server = self._get_mock_server()\n        mock_server._async['websocket'] = None\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        environ = \"foo\"\n        await s._upgrade_websocket(environ)\n        mock_server._bad_request.assert_called_once_with()\n\n    async def test_close_packet(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        s.close = mock.AsyncMock()\n        await s.receive(packet.Packet(packet.CLOSE))\n        s.close.assert_awaited_once_with(\n            wait=False, abort=True,\n            reason=mock_server.reason.CLIENT_DISCONNECT)\n\n    async def test_websocket_read_write(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = False\n        s.queue.join = mock.AsyncMock(return_value=None)\n        foo = 'foo'\n        bar = 'bar'\n        s.poll = mock.AsyncMock(\n            side_effect=[[packet.Packet(packet.MESSAGE, data=bar)], None]\n        )\n        ws = mock.MagicMock()\n        ws.send = mock.AsyncMock()\n        ws.wait = mock.AsyncMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.MESSAGE, data=foo).encode(),\n            None,\n        ]\n        ws.close = mock.AsyncMock()\n        await s._websocket_handler(ws)\n        assert s.connected\n        assert s.upgraded\n        assert mock_server._trigger_event.await_count == 2\n        mock_server._trigger_event.assert_has_awaits(\n            [\n                mock.call('message', 'sid', 'foo', run_async=False),\n                mock.call('disconnect', 'sid',\n                          mock_server.reason.TRANSPORT_CLOSE, run_async=False),\n            ]\n        )\n        ws.send.assert_awaited_with('4bar')\n        ws.close.assert_awaited()\n\n    async def test_websocket_upgrade_read_write(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.AsyncMock(return_value=None)\n        foo = 'foo'\n        bar = 'bar'\n        probe = 'probe'\n        s.poll = mock.AsyncMock(\n            side_effect=[\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                exceptions.QueueEmpty,\n            ]\n        )\n        ws = mock.MagicMock()\n        ws.send = mock.AsyncMock()\n        ws.wait = mock.AsyncMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.UPGRADE).encode(),\n            packet.Packet(packet.MESSAGE, data=foo).encode(),\n            None,\n        ]\n        ws.close = mock.AsyncMock()\n        await s._websocket_handler(ws)\n        assert s.upgraded\n        assert mock_server._trigger_event.await_count == 2\n        mock_server._trigger_event.assert_has_awaits(\n            [\n                mock.call('message', 'sid', 'foo', run_async=False),\n                mock.call('disconnect', 'sid',\n                          mock_server.reason.TRANSPORT_CLOSE, run_async=False),\n            ]\n        )\n        ws.send.assert_awaited_with('4bar')\n        ws.close.assert_awaited()\n\n    async def test_websocket_upgrade_with_payload(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.AsyncMock(return_value=None)\n        probe = 'probe'\n        ws = mock.MagicMock()\n        ws.send = mock.AsyncMock()\n        ws.wait = mock.AsyncMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.UPGRADE, data='2').encode(),\n        ]\n        ws.close = mock.AsyncMock()\n        await s._websocket_handler(ws)\n        assert s.upgraded\n\n    async def test_websocket_upgrade_with_backlog(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.AsyncMock(return_value=None)\n        probe = 'probe'\n        foo = 'foo'\n        ws = mock.MagicMock()\n        ws.send = mock.AsyncMock()\n        ws.wait = mock.AsyncMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.UPGRADE, data='2').encode(),\n        ]\n        ws.close = mock.AsyncMock()\n        s.upgrading = True\n        await s.send(packet.Packet(packet.MESSAGE, data=foo))\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=sid'}\n        packets = await s.handle_get_request(environ)\n        assert len(packets) == 1\n        assert packets[0].encode() == '6'\n        packets = await s.poll()\n        assert len(packets) == 1\n        assert packets[0].encode() == '4foo'\n\n        await s._websocket_handler(ws)\n        assert s.upgraded\n        assert not s.upgrading\n        packets = await s.handle_get_request(environ)\n        assert len(packets) == 1\n        assert packets[0].encode() == '6'\n\n    async def test_websocket_read_write_wait_fail(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = False\n        s.queue.join = mock.AsyncMock(return_value=None)\n        foo = 'foo'\n        bar = 'bar'\n        s.poll = mock.AsyncMock(\n            side_effect=[\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                exceptions.QueueEmpty,\n            ]\n        )\n        ws = mock.MagicMock()\n        ws.send = mock.AsyncMock()\n        ws.wait = mock.AsyncMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.MESSAGE, data=foo).encode(),\n            RuntimeError,\n        ]\n        ws.send.side_effect = [None, RuntimeError]\n        ws.close = mock.AsyncMock()\n        await s._websocket_handler(ws)\n        assert s.closed\n\n    async def test_websocket_upgrade_with_large_packet(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.AsyncMock(return_value=None)\n        probe = 'probe'\n        ws = mock.MagicMock()\n        ws.send = mock.AsyncMock()\n        ws.wait = mock.AsyncMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.UPGRADE, data='2' * 128).encode(),\n        ]\n        with pytest.raises(ValueError):\n            await s._websocket_handler(ws)\n        assert not s.upgraded\n\n    async def test_websocket_ignore_invalid_packet(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.connected = False\n        s.queue.join = mock.AsyncMock(return_value=None)\n        foo = 'foo'\n        bar = 'bar'\n        s.poll = mock.AsyncMock(\n            side_effect=[\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                exceptions.QueueEmpty,\n            ]\n        )\n        ws = mock.MagicMock()\n        ws.send = mock.AsyncMock()\n        ws.wait = mock.AsyncMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.OPEN).encode(),\n            packet.Packet(packet.MESSAGE, data=foo).encode(),\n            None,\n        ]\n        ws.close = mock.AsyncMock()\n        await s._websocket_handler(ws)\n        assert s.connected\n        assert mock_server._trigger_event.await_count == 2\n        mock_server._trigger_event.assert_has_awaits(\n            [\n                mock.call('message', 'sid', foo, run_async=False),\n                mock.call('disconnect', 'sid',\n                          mock_server.reason.TRANSPORT_CLOSE, run_async=False),\n            ]\n        )\n        ws.send.assert_awaited_with('4bar')\n        ws.close.assert_awaited()\n\n    async def test_send_after_close(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        await s.close(wait=False)\n        with pytest.raises(exceptions.SocketIsClosedError):\n            await s.send(packet.Packet(packet.NOOP))\n\n    async def test_close_after_close(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        await s.close(wait=False)\n        assert s.closed\n        assert mock_server._trigger_event.await_count == 1\n        mock_server._trigger_event.assert_awaited_once_with(\n            'disconnect', 'sid', mock_server.reason.SERVER_DISCONNECT,\n            run_async=False\n        )\n        await s.close()\n        assert mock_server._trigger_event.await_count == 1\n\n    async def test_close_and_wait(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.queue = mock.MagicMock()\n        s.queue.put = mock.AsyncMock()\n        s.queue.join = mock.AsyncMock()\n        await s.close(wait=True)\n        s.queue.join.assert_awaited_once_with()\n\n    async def test_close_without_wait(self):\n        mock_server = self._get_mock_server()\n        s = async_socket.AsyncSocket(mock_server, 'sid')\n        s.queue = mock.MagicMock()\n        s.queue.put = mock.AsyncMock()\n        s.queue.join = mock.AsyncMock()\n        await s.close(wait=False)\n        assert s.queue.join.await_count == 0\n"
  },
  {
    "path": "tests/async/test_tornado.py",
    "content": "from unittest import mock\n\ntry:\n    import tornado.web\nexcept ImportError:\n    pass\n\nfrom engineio.async_drivers import tornado as async_tornado\n\n\nclass TestTornado:\n    async def test_get_tornado_handler(self):\n        mock_server = mock.MagicMock()\n        handler = async_tornado.get_tornado_handler(mock_server)\n        assert issubclass(handler, tornado.websocket.WebSocketHandler)\n\n    async def test_translate_request(self):\n        mock_handler = mock.MagicMock()\n        mock_handler.request.method = 'PUT'\n        mock_handler.request.path = '/foo/bar'\n        mock_handler.request.query = 'baz=1'\n        mock_handler.request.version = '1.1'\n        mock_handler.request.headers = {\n            'a': 'b',\n            'c': 'd',\n            'content-type': 'application/json',\n            'content-length': 123,\n        }\n        mock_handler.request.body = b'hello world'\n        environ = async_tornado.translate_request(mock_handler)\n        expected_environ = {\n            'REQUEST_METHOD': 'PUT',\n            'PATH_INFO': '/foo/bar',\n            'QUERY_STRING': 'baz=1',\n            'CONTENT_TYPE': 'application/json',\n            'CONTENT_LENGTH': 123,\n            'HTTP_A': 'b',\n            'HTTP_C': 'd',\n            'RAW_URI': '/foo/bar?baz=1',\n            'SERVER_PROTOCOL': 'HTTP/1.1',\n            # 'wsgi.input': b'hello world',\n            'tornado.handler': mock_handler,\n        }\n        for k, v in expected_environ.items():\n            assert v == environ[k]\n        payload = await environ['wsgi.input'].read(1)\n        payload += await environ['wsgi.input'].read()\n        assert payload == b'hello world'\n\n    async def test_make_response(self):\n        mock_handler = mock.MagicMock()\n        mock_environ = {'tornado.handler': mock_handler}\n        async_tornado.make_response(\n            '202 ACCEPTED', [('foo', 'bar')], b'payload', mock_environ\n        )\n        mock_handler.set_status.assert_called_once_with(202)\n        mock_handler.set_header.assert_called_once_with('foo', 'bar')\n        mock_handler.write.assert_called_once_with(b'payload')\n        mock_handler.finish.assert_called_once_with()\n"
  },
  {
    "path": "tests/common/__init__.py",
    "content": ""
  },
  {
    "path": "tests/common/files/file.txt",
    "content": "file\n"
  },
  {
    "path": "tests/common/files/index.html",
    "content": "<html>file</html>\n"
  },
  {
    "path": "tests/common/index.html",
    "content": "<html></html>\n"
  },
  {
    "path": "tests/common/test_client.py",
    "content": "import logging\nimport ssl\nimport time\nfrom unittest import mock\n\nimport pytest\nimport websocket\n\nfrom engineio import base_client\nfrom engineio import client\nfrom engineio import exceptions\nfrom engineio import json\nfrom engineio import packet\nfrom engineio import payload\n\n\nclass TestClient:\n    def mock_queue(self, client):\n        client.queue = mock.MagicMock()\n        client.queue_empty = RuntimeError\n        client.queue.get_nowait.side_effect = client.queue_empty\n\n    def test_is_asyncio_based(self):\n        c = client.Client()\n        assert not c.is_asyncio_based()\n\n    def test_create(self):\n        c = client.Client()\n        assert c.handlers == {}\n        for attr in [\n            'base_url',\n            'transports',\n            'sid',\n            'upgrades',\n            'ping_interval',\n            'ping_timeout',\n            'http',\n            'ws',\n            'read_loop_task',\n            'write_loop_task',\n        ]:\n            assert getattr(c, attr) is None, attr + ' is not None'\n        assert c.state == 'disconnected'\n        assert c.queue.__class__.__name__ == 'Queue'\n        assert c.queue_empty.__name__ == 'Empty'\n\n    def test_custom_json(self):\n        client.Client()\n        assert packet.Packet.json == json\n        client.Client(json='foo')\n        assert packet.Packet.json == 'foo'\n        packet.Packet.json = json\n\n    def test_logger(self):\n        c = client.Client(logger=False)\n        assert c.logger.getEffectiveLevel() == logging.ERROR\n        c.logger.setLevel(logging.NOTSET)\n        c = client.Client(logger=True)\n        assert c.logger.getEffectiveLevel() == logging.INFO\n        c.logger.setLevel(logging.WARNING)\n        c = client.Client(logger=True)\n        assert c.logger.getEffectiveLevel() == logging.WARNING\n        c.logger.setLevel(logging.NOTSET)\n        my_logger = logging.Logger('foo')\n        c = client.Client(logger=my_logger)\n        assert c.logger == my_logger\n\n    def test_custom_timeout(self):\n        c = client.Client()\n        assert c.request_timeout == 5\n        c = client.Client(request_timeout=27)\n        assert c.request_timeout == 27\n\n    def test_timestamp_requests(self):\n        c = client.Client()\n        assert c.timestamp_requests\n        assert c._get_url_timestamp().startswith('&t=')\n        c = client.Client(timestamp_requests=False)\n        assert not c.timestamp_requests\n        assert c._get_url_timestamp() == ''\n\n    def test_on_event(self):\n        c = client.Client()\n\n        @c.on('connect')\n        def foo():\n            pass\n\n        c.on('disconnect', foo)\n\n        assert c.handlers['connect'] == foo\n        assert c.handlers['disconnect'] == foo\n\n    def test_on_event_invalid(self):\n        c = client.Client()\n        with pytest.raises(ValueError):\n            c.on('invalid')\n\n    def test_already_connected(self):\n        c = client.Client()\n        c.state = 'connected'\n        with pytest.raises(ValueError):\n            c.connect('http://foo')\n\n    def test_invalid_transports(self):\n        c = client.Client()\n        with pytest.raises(ValueError):\n            c.connect('http://foo', transports=['foo', 'bar'])\n\n    def test_some_invalid_transports(self):\n        c = client.Client()\n        c._connect_websocket = mock.MagicMock()\n        c.connect('http://foo', transports=['foo', 'websocket', 'bar'])\n        assert c.transports == ['websocket']\n\n    def test_connect_polling(self):\n        c = client.Client()\n        c._connect_polling = mock.MagicMock(return_value='foo')\n        assert c.connect('http://foo') == 'foo'\n        c._connect_polling.assert_called_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n        c = client.Client()\n        c._connect_polling = mock.MagicMock(return_value='foo')\n        assert c.connect('http://foo', transports=['polling']) == 'foo'\n        c._connect_polling.assert_called_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n        c = client.Client()\n        c._connect_polling = mock.MagicMock(return_value='foo')\n        assert (\n            c.connect('http://foo', transports=['polling', 'websocket'])\n            == 'foo'\n        )\n        c._connect_polling.assert_called_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n    def test_connect_websocket(self):\n        c = client.Client()\n        c._connect_websocket = mock.MagicMock(return_value='foo')\n        assert c.connect('http://foo', transports=['websocket']) == 'foo'\n        c._connect_websocket.assert_called_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n        c = client.Client()\n        c._connect_websocket = mock.MagicMock(return_value='foo')\n        assert c.connect('http://foo', transports='websocket') == 'foo'\n        c._connect_websocket.assert_called_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n\n    def test_connect_query_string(self):\n        c = client.Client()\n        c._connect_polling = mock.MagicMock(return_value='foo')\n        assert c.connect('http://foo?bar=baz') == 'foo'\n        c._connect_polling.assert_called_once_with(\n            'http://foo?bar=baz', {}, 'engine.io'\n        )\n\n    def test_connect_custom_headers(self):\n        c = client.Client()\n        c._connect_polling = mock.MagicMock(return_value='foo')\n        assert c.connect('http://foo', headers={'Foo': 'Bar'}) == 'foo'\n        c._connect_polling.assert_called_once_with(\n            'http://foo', {'Foo': 'Bar'}, 'engine.io'\n        )\n\n    def test_wait(self):\n        c = client.Client()\n        c.read_loop_task = mock.MagicMock()\n        c.wait()\n        c.read_loop_task.join.assert_called_once_with()\n\n    def test_wait_no_task(self):\n        c = client.Client()\n        c.read_loop_task = None\n        c.wait()  # should not block\n\n    def test_send(self):\n        c = client.Client()\n        saved_packets = []\n\n        def fake_send_packet(pkt):\n            saved_packets.append(pkt)\n\n        c._send_packet = fake_send_packet\n        c.send('foo')\n        c.send('foo')\n        c.send(b'foo')\n        assert saved_packets[0].packet_type == packet.MESSAGE\n        assert saved_packets[0].data == 'foo'\n        assert not saved_packets[0].binary\n        assert saved_packets[1].packet_type == packet.MESSAGE\n        assert saved_packets[1].data == 'foo'\n        assert not saved_packets[1].binary\n        assert saved_packets[2].packet_type == packet.MESSAGE\n        assert saved_packets[2].data == b'foo'\n        assert saved_packets[2].binary\n\n    def test_disconnect_not_connected(self):\n        c = client.Client()\n        c.state = 'foo'\n        c.sid = 'bar'\n        c.disconnect()\n        assert c.state == 'disconnected'\n        assert c.sid is None\n\n    def test_disconnect_polling(self):\n        c = client.Client()\n        base_client.connected_clients.append(c)\n        c.state = 'connected'\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.read_loop_task = mock.MagicMock()\n        c.ws = mock.MagicMock()\n        c._trigger_event = mock.MagicMock()\n        c.disconnect()\n        c.read_loop_task.join.assert_called_once_with()\n        c.ws.mock.assert_not_called()\n        assert c not in base_client.connected_clients\n        c._trigger_event.assert_called_once_with(\n            'disconnect', c.reason.CLIENT_DISCONNECT, run_async=False)\n\n    def test_disconnect_websocket(self):\n        c = client.Client()\n        base_client.connected_clients.append(c)\n        c.state = 'connected'\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.read_loop_task = mock.MagicMock()\n        c.ws = mock.MagicMock()\n        c._trigger_event = mock.MagicMock()\n        c.disconnect()\n        c.read_loop_task.join.assert_called_once_with()\n        c.ws.close.assert_called_once_with()\n        assert c not in base_client.connected_clients\n        c._trigger_event.assert_called_once_with(\n            'disconnect', c.reason.CLIENT_DISCONNECT, run_async=False)\n\n    def test_disconnect_polling_abort(self):\n        c = client.Client()\n        base_client.connected_clients.append(c)\n        c.state = 'connected'\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.read_loop_task = mock.MagicMock()\n        c.ws = mock.MagicMock()\n        c.disconnect(abort=True)\n        c.queue.join.assert_not_called()\n        c.read_loop_task.join.assert_not_called()\n        c.ws.mock.assert_not_called()\n        assert c not in base_client.connected_clients\n\n    def test_disconnect_websocket_abort(self):\n        c = client.Client()\n        base_client.connected_clients.append(c)\n        c.state = 'connected'\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.read_loop_task = mock.MagicMock()\n        c.ws = mock.MagicMock()\n        c.disconnect(abort=True)\n        c.queue.join.assert_not_called()\n        c.read_loop_task.join.assert_not_called()\n        c.ws.mock.assert_not_called()\n        assert c not in base_client.connected_clients\n\n    def test_current_transport(self):\n        c = client.Client()\n        c.current_transport = 'foo'\n        assert c.transport() == 'foo'\n\n    def test_background_tasks(self):\n        flag = {}\n\n        def bg_task():\n            flag['task'] = True\n\n        c = client.Client()\n        task = c.start_background_task(bg_task)\n        task.join()\n        assert 'task' in flag\n        assert flag['task']\n\n    def test_sleep(self):\n        c = client.Client()\n        t = time.time()\n        c.sleep(0.1)\n        assert time.time() - t > 0.1\n\n    def test_create_queue(self):\n        c = client.Client()\n        q = c.create_queue()\n        with pytest.raises(c.queue_empty):\n            q.get(timeout=0.01)\n\n    def test_create_event(self):\n        c = client.Client()\n        e = c.create_event()\n        assert not e.is_set()\n        e.set()\n        assert e.is_set()\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch('engineio.client.Client._send_request', return_value=None)\n    def test_polling_connection_failed(self, _send_request, _time):\n        c = client.Client()\n        with pytest.raises(exceptions.ConnectionError):\n            c.connect('http://foo', headers={'Foo': 'Bar'})\n        _send_request.assert_called_once_with(\n            'GET',\n            'http://foo/engine.io/?transport=polling&EIO=4&t=123.456',\n            headers={'Foo': 'Bar'},\n            timeout=5,\n        )\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_connection_404(self, _send_request):\n        _send_request.return_value.status_code = 404\n        _send_request.return_value.json.return_value = {'foo': 'bar'}\n        c = client.Client()\n        try:\n            c.connect('http://foo')\n        except exceptions.ConnectionError as exc:\n            assert len(exc.args) == 2\n            assert (\n                exc.args[0] == 'Unexpected status code 404 in server response'\n            )\n            assert exc.args[1] == {'foo': 'bar'}\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_connection_404_no_json(self, _send_request):\n        _send_request.return_value.status_code = 404\n        _send_request.return_value.json.side_effect = json.JSONDecodeError(\n            'error', '<html></html>', 0)\n        c = client.Client()\n        try:\n            c.connect('http://foo')\n        except exceptions.ConnectionError as exc:\n            assert len(exc.args) == 2\n            assert (\n                exc.args[0] == 'Unexpected status code 404 in server response'\n            )\n            assert exc.args[1] is None\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_connection_invalid_packet(self, _send_request):\n        _send_request.return_value.status_code = 200\n        _send_request.return_value.content = b'foo'\n        c = client.Client()\n        with pytest.raises(exceptions.ConnectionError):\n            c.connect('http://foo')\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_connection_no_open_packet(self, _send_request):\n        _send_request.return_value.status_code = 200\n        _send_request.return_value.content = payload.Payload(\n            packets=[\n                packet.Packet(\n                    packet.CLOSE,\n                    {\n                        'sid': '123',\n                        'upgrades': [],\n                        'pingInterval': 10,\n                        'pingTimeout': 20,\n                    },\n                )\n            ]\n        ).encode().encode('utf-8')\n        c = client.Client()\n        with pytest.raises(exceptions.ConnectionError):\n            c.connect('http://foo')\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_connection_successful(self, _send_request):\n        _send_request.return_value.status_code = 200\n        _send_request.return_value.content = payload.Payload(\n            packets=[\n                packet.Packet(\n                    packet.OPEN,\n                    {\n                        'sid': '123',\n                        'upgrades': [],\n                        'pingInterval': 1000,\n                        'pingTimeout': 2000,\n                    },\n                )\n            ]\n        ).encode().encode('utf-8')\n        c = client.Client()\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('http://foo')\n        time.sleep(0.1)\n\n        c._read_loop_polling.assert_called_once_with()\n        c._read_loop_websocket.assert_not_called()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n        assert (\n            c.base_url\n            == 'http://foo/engine.io/?transport=polling&EIO=4&sid=123'\n        )\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == []\n        assert c.transport() == 'polling'\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_https_noverify_connection_successful(self, _send_request):\n        _send_request.return_value.status_code = 200\n        _send_request.return_value.content = payload.Payload(\n            packets=[\n                packet.Packet(\n                    packet.OPEN,\n                    {\n                        'sid': '123',\n                        'upgrades': [],\n                        'pingInterval': 1000,\n                        'pingTimeout': 2000,\n                    },\n                )\n            ]\n        ).encode().encode('utf-8')\n        c = client.Client(ssl_verify=False)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('https://foo')\n        time.sleep(0.1)\n\n        c._read_loop_polling.assert_called_once_with()\n        c._read_loop_websocket.assert_not_called()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n        assert (\n            c.base_url\n            == 'https://foo/engine.io/?transport=polling&EIO=4&sid=123'\n        )\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == []\n        assert c.transport() == 'polling'\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_connection_with_more_packets(self, _send_request):\n        _send_request.return_value.status_code = 200\n        _send_request.return_value.content = payload.Payload(\n            packets=[\n                packet.Packet(\n                    packet.OPEN,\n                    {\n                        'sid': '123',\n                        'upgrades': [],\n                        'pingInterval': 1000,\n                        'pingTimeout': 2000,\n                    },\n                ),\n                packet.Packet(packet.NOOP),\n            ]\n        ).encode().encode('utf-8')\n        c = client.Client()\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        c._receive_packet = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('http://foo')\n        time.sleep(0.1)\n        assert c._receive_packet.call_count == 1\n        assert (\n            c._receive_packet.call_args_list[0][0][0].packet_type\n            == packet.NOOP\n        )\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_connection_upgraded(self, _send_request):\n        _send_request.return_value.status_code = 200\n        _send_request.return_value.content = payload.Payload(\n            packets=[\n                packet.Packet(\n                    packet.OPEN,\n                    {\n                        'sid': '123',\n                        'upgrades': ['websocket'],\n                        'pingInterval': 1000,\n                        'pingTimeout': 2000,\n                    },\n                )\n            ]\n        ).encode().encode('utf-8')\n        c = client.Client()\n        c._connect_websocket = mock.MagicMock(return_value=True)\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('http://foo')\n\n        c._connect_websocket.assert_called_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n        assert (\n            c.base_url\n            == 'http://foo/engine.io/?transport=polling&EIO=4&sid=123'\n        )\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == ['websocket']\n\n    @mock.patch('engineio.client.Client._send_request')\n    def test_polling_connection_not_upgraded(self, _send_request):\n        _send_request.return_value.status_code = 200\n        _send_request.return_value.content = payload.Payload(\n            packets=[\n                packet.Packet(\n                    packet.OPEN,\n                    {\n                        'sid': '123',\n                        'upgrades': ['websocket'],\n                        'pingInterval': 1000,\n                        'pingTimeout': 2000,\n                    },\n                )\n            ]\n        ).encode().encode('utf-8')\n        c = client.Client()\n        c._connect_websocket = mock.MagicMock(return_value=False)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('http://foo')\n        time.sleep(0.1)\n\n        c._connect_websocket.assert_called_once_with(\n            'http://foo', {}, 'engine.io'\n        )\n        c._read_loop_polling.assert_called_once_with()\n        c._read_loop_websocket.assert_not_called()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch(\n        'engineio.client.websocket.create_connection',\n        side_effect=[ConnectionError],\n    )\n    def test_websocket_connection_failed(self, create_connection, _time):\n        c = client.Client()\n        with pytest.raises(exceptions.ConnectionError):\n            c.connect(\n                'http://foo', transports=['websocket'], headers={'Foo': 'Bar'}\n            )\n        create_connection.assert_called_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            header={'Foo': 'Bar'},\n            cookie=None,\n            enable_multithread=True,\n            timeout=5\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch(\n        'engineio.client.websocket.create_connection',\n        side_effect=[ConnectionError],\n    )\n    def test_websocket_connection_extra(self, create_connection, _time):\n        c = client.Client(websocket_extra_options={'header': {'Baz': 'Qux'},\n                                                   'timeout': 10})\n        with pytest.raises(exceptions.ConnectionError):\n            c.connect(\n                'http://foo', transports=['websocket'], headers={'Foo': 'Bar'}\n            )\n        create_connection.assert_called_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            header={'Foo': 'Bar', 'Baz': 'Qux'},\n            cookie=None,\n            enable_multithread=True,\n            timeout=10\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch(\n        'engineio.client.websocket.create_connection',\n        side_effect=[websocket.WebSocketException],\n    )\n    def test_websocket_connection_failed_with_websocket_error(\n        self, create_connection, _time\n    ):\n        c = client.Client()\n        with pytest.raises(exceptions.ConnectionError):\n            c.connect(\n                'http://foo', transports=['websocket'], headers={'Foo': 'Bar'}\n            )\n        create_connection.assert_called_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456',\n            header={'Foo': 'Bar'},\n            cookie=None,\n            enable_multithread=True,\n            timeout=5\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    @mock.patch(\n        'engineio.client.websocket.create_connection',\n        side_effect=[ConnectionError],\n    )\n    def test_websocket_upgrade_failed(self, create_connection, _time):\n        c = client.Client()\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.sid = '123'\n        assert not c.connect('http://foo', transports=['websocket'])\n        create_connection.assert_called_once_with(\n            'ws://foo/engine.io/?transport=websocket&EIO=4&sid=123&t=123.456',\n            header={},\n            cookie=None,\n            enable_multithread=True,\n            timeout=5\n        )\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_no_open_packet(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.CLOSE\n        ).encode()\n        c = client.Client()\n        with pytest.raises(exceptions.ConnectionError):\n            c.connect('http://foo', transports=['websocket'])\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_successful(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        c = client.Client()\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('ws://foo', transports=['websocket'])\n        time.sleep(0.1)\n\n        c._read_loop_polling.assert_not_called()\n        c._read_loop_websocket.assert_called_once_with()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n        assert c.base_url == 'ws://foo/engine.io/?transport=websocket&EIO=4'\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == []\n        assert c.transport() == 'websocket'\n        assert c.ws == create_connection.return_value\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'header': {},\n            'cookie': None,\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_https_noverify_connection_successful(\n        self, create_connection\n    ):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        c = client.Client(ssl_verify=False)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('wss://foo', transports=['websocket'])\n        time.sleep(0.1)\n\n        c._read_loop_polling.assert_not_called()\n        c._read_loop_websocket.assert_called_once_with()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_called_once_with()\n        assert c in base_client.connected_clients\n        assert c.base_url == 'wss://foo/engine.io/?transport=websocket&EIO=4'\n        assert c.sid == '123'\n        assert c.ping_interval == 1\n        assert c.ping_timeout == 2\n        assert c.upgrades == []\n        assert c.transport() == 'websocket'\n        assert c.ws == create_connection.return_value\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'header': {},\n            'cookie': None,\n            'enable_multithread': True,\n            'timeout': 5,\n            'sslopt': {'cert_reqs': ssl.CERT_NONE},\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_with_cookies(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = [mock.MagicMock(), mock.MagicMock()]\n        http.cookies[0].name = 'key'\n        http.cookies[0].value = 'value'\n        http.cookies[1].name = 'key2'\n        http.cookies[1].value = 'value2'\n        http.auth = None\n        http.proxies = None\n        http.cert = None\n        c = client.Client(http_session=http)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('ws://foo', transports=['websocket'])\n        time.sleep(0.1)\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'header': {},\n            'cookie': 'key=value; key2=value2',\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_with_cookie_header(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = []\n        http.auth = None\n        http.proxies = None\n        http.cert = None\n        c = client.Client(http_session=http)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect(\n            'ws://foo',\n            headers={'Foo': 'bar', 'Cookie': 'key=value'},\n            transports=['websocket'],\n        )\n        time.sleep(0.1)\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'header': {'Foo': 'bar'},\n            'cookie': 'key=value',\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_with_cookies_and_headers(\n        self, create_connection\n    ):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = [mock.MagicMock(), mock.MagicMock()]\n        http.cookies[0].name = 'key'\n        http.cookies[0].value = 'value'\n        http.cookies[1].name = 'key2'\n        http.cookies[1].value = 'value2'\n        http.auth = None\n        http.proxies = None\n        http.cert = None\n        c = client.Client(http_session=http)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect(\n            'ws://foo',\n            headers={'Cookie': 'key3=value3'},\n            transports=['websocket'],\n        )\n        time.sleep(0.1)\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'header': {},\n            'enable_multithread': True,\n            'timeout': 5,\n            'cookie': 'key=value; key2=value2; key3=value3',\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_with_auth(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = []\n        http.auth = ('foo', 'bar')\n        http.proxies = None\n        http.cert = None\n        c = client.Client(http_session=http)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('ws://foo', transports=['websocket'])\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'header': {'Authorization': 'Basic Zm9vOmJhcg=='},\n            'cookie': '',\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_with_cert(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = []\n        http.auth = None\n        http.proxies = None\n        http.cert = 'foo.crt'\n        c = client.Client(http_session=http, ssl_verify=False)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('ws://foo', transports=['websocket'])\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'sslopt': {'cert_reqs': ssl.CERT_NONE, 'certfile': 'foo.crt'},\n            'header': {},\n            'cookie': '',\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_with_cert_and_key(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = []\n        http.auth = None\n        http.proxies = None\n        http.cert = ('foo.crt', 'key.pem')\n        c = client.Client(http_session=http)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('ws://foo', transports=['websocket'])\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'sslopt': {'certfile': 'foo.crt', 'keyfile': 'key.pem'},\n            'header': {},\n            'cookie': '',\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_verify_with_cert_and_key(\n        self, create_connection\n    ):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = []\n        http.auth = None\n        http.proxies = None\n        http.cert = ('foo.crt', 'key.pem')\n        http.verify = 'ca-bundle.crt'\n        c = client.Client(http_session=http)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('ws://foo', transports=['websocket'])\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'sslopt': {\n                'certfile': 'foo.crt',\n                'keyfile': 'key.pem',\n                'ca_certs': 'ca-bundle.crt'\n            },\n            'header': {},\n            'cookie': '',\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_with_proxies(self, create_connection):\n        all_urls = [\n            'ws://foo',\n            'ws://foo',\n            'ws://foo',\n            'ws://foo',\n            'ws://foo',\n            'wss://foo',\n            'wss://foo',\n        ]\n        all_proxies = [\n            {'http': 'foo.com:1234'},\n            {'https': 'foo.com:1234'},\n            {'http': 'foo.com:1234', 'ws': 'bar.com:4321'},\n            {},\n            {'http': 'user:pass@foo.com:1234'},\n            {'https': 'foo.com:1234'},\n            {'https': 'foo.com:1234', 'wss': 'bar.com:4321'},\n        ]\n        all_results = [\n            ('foo.com', 1234, None),\n            None,\n            ('bar.com', 4321, None),\n            None,\n            ('foo.com', 1234, ('user', 'pass')),\n            ('foo.com', 1234, None),\n            ('bar.com', 4321, None),\n        ]\n        for url, proxies, results in zip(all_urls, all_proxies, all_results):\n            create_connection.reset_mock()\n            create_connection.return_value.recv.return_value = packet.Packet(\n                packet.OPEN,\n                {\n                    'sid': '123',\n                    'upgrades': [],\n                    'pingInterval': 1000,\n                    'pingTimeout': 2000,\n                },\n            ).encode()\n            http = mock.MagicMock()\n            http.cookies = []\n            http.auth = None\n            http.proxies = proxies\n            http.cert = None\n            c = client.Client(http_session=http)\n            c._read_loop_polling = mock.MagicMock()\n            c._read_loop_websocket = mock.MagicMock()\n            c._write_loop = mock.MagicMock()\n            on_connect = mock.MagicMock()\n            c.on('connect', on_connect)\n            c.connect(url, transports=['websocket'])\n\n            assert len(create_connection.call_args_list) == 1\n            expected_results = {\n                'header': {},\n                'cookie': '',\n                'enable_multithread': True,\n                'timeout': 5,\n            }\n            if results:\n                expected_results.update({\n                    'http_proxy_host': results[0],\n                    'http_proxy_port': results[1],\n                    'http_proxy_auth': results[2]})\n            assert create_connection.call_args[1] == expected_results\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_without_verify(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = []\n        http.auth = None\n        http.proxies = None\n        http.cert = None\n        http.verify = False\n        c = client.Client(http_session=http)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('ws://foo', transports=['websocket'])\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'sslopt': {\"cert_reqs\": ssl.CERT_NONE},\n            'header': {},\n            'cookie': '',\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_connection_with_verify(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        http = mock.MagicMock()\n        http.cookies = []\n        http.auth = None\n        http.proxies = None\n        http.cert = None\n        http.verify = 'ca-bundle.crt'\n        c = client.Client(http_session=http)\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        c.connect('ws://foo', transports=['websocket'])\n\n        assert len(create_connection.call_args_list) == 1\n        assert create_connection.call_args[1] == {\n            'sslopt': {'ca_certs': 'ca-bundle.crt'},\n            'header': {},\n            'cookie': '',\n            'enable_multithread': True,\n            'timeout': 5,\n        }\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_upgrade_no_pong(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.OPEN,\n            {\n                'sid': '123',\n                'upgrades': [],\n                'pingInterval': 1000,\n                'pingTimeout': 2000,\n            },\n        ).encode()\n        c = client.Client()\n        c.sid = '123'\n        c.current_transport = 'polling'\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        assert not c.connect('ws://foo', transports=['websocket'])\n\n        c._read_loop_polling.assert_not_called()\n        c._read_loop_websocket.assert_not_called()\n        c._write_loop.assert_not_called()\n        on_connect.assert_not_called()\n        assert c.transport() == 'polling'\n\n    @mock.patch('engineio.client.websocket.create_connection')\n    def test_websocket_upgrade_successful(self, create_connection):\n        create_connection.return_value.recv.return_value = packet.Packet(\n            packet.PONG, 'probe').encode()\n        c = client.Client()\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.sid = '123'\n        c.base_url = 'http://foo'\n        c.current_transport = 'polling'\n        c._read_loop_polling = mock.MagicMock()\n        c._read_loop_websocket = mock.MagicMock()\n        c._write_loop = mock.MagicMock()\n        on_connect = mock.MagicMock()\n        c.on('connect', on_connect)\n        assert c.connect('ws://foo', transports=['websocket'])\n        time.sleep(0.1)\n\n        c._read_loop_polling.assert_not_called()\n        c._read_loop_websocket.assert_called_once_with()\n        c._write_loop.assert_called_once_with()\n        on_connect.assert_not_called()  # was called by polling\n        assert c not in base_client.connected_clients  # was added by polling\n        assert c.base_url == 'http://foo'  # not changed\n        assert c.sid == '123'  # not changed\n        assert c.transport() == 'websocket'\n        assert c.ws == create_connection.return_value\n        assert create_connection.return_value.send.call_args_list[0] == (\n            (packet.Packet(packet.PING, 'probe').encode(),),\n        )  # ping\n        assert create_connection.return_value.send.call_args_list[1] == (\n            (packet.Packet(packet.UPGRADE).encode(),),\n        )  # upgrade\n\n    def test_receive_unknown_packet(self):\n        c = client.Client()\n        c._receive_packet(packet.Packet(encoded_packet='9'))\n        # should be ignored\n\n    def test_receive_noop_packet(self):\n        c = client.Client()\n        c._receive_packet(packet.Packet(packet.NOOP))\n        # should be ignored\n\n    def test_receive_ping_packet(self):\n        c = client.Client()\n        c._send_packet = mock.MagicMock()\n        c._receive_packet(packet.Packet(packet.PING))\n        assert c._send_packet.call_args_list[0][0][0].encode() == '3'  # PONG\n\n    def test_receive_message_packet(self):\n        c = client.Client()\n        c._trigger_event = mock.MagicMock()\n        c._receive_packet(packet.Packet(packet.MESSAGE, {'foo': 'bar'}))\n        c._trigger_event.assert_called_once_with(\n            'message', {'foo': 'bar'}, run_async=True\n        )\n\n    def test_receive_close_packet(self):\n        c = client.Client()\n        c.disconnect = mock.MagicMock()\n        c._receive_packet(packet.Packet(packet.CLOSE))\n        c.disconnect.assert_called_once_with(\n            abort=True, reason=c.reason.SERVER_DISCONNECT)\n\n    def test_send_packet_disconnected(self):\n        c = client.Client()\n        c.queue = c.create_queue()\n        c.state = 'disconnected'\n        c._send_packet(packet.Packet(packet.NOOP))\n        assert c.queue.empty()\n\n    def test_send_packet(self):\n        c = client.Client()\n        c.queue = c.create_queue()\n        c.state = 'connected'\n        c._send_packet(packet.Packet(packet.NOOP))\n        assert not c.queue.empty()\n        pkt = c.queue.get()\n        assert pkt.packet_type == packet.NOOP\n\n    def test_trigger_event(self):\n        c = client.Client()\n        f = {}\n\n        @c.on('connect')\n        def foo():\n            return 'foo'\n\n        @c.on('message')\n        def bar(data):\n            f['bar'] = data\n            return 'bar'\n\n        @c.on('disconnect')\n        def baz(reason):\n            return reason\n\n        r = c._trigger_event('connect', run_async=False)\n        assert r == 'foo'\n        r = c._trigger_event('message', 123, run_async=True)\n        r.join()\n        assert f['bar'] == 123\n        r = c._trigger_event('message', 321)\n        assert r == 'bar'\n        r = c._trigger_event('disconnect', 'foo')\n        assert r == 'foo'\n\n    def test_trigger_legacy_disconnect_event(self):\n        c = client.Client()\n\n        @c.on('disconnect')\n        def baz():\n            return 'baz'\n\n        r = c._trigger_event('disconnect', 'foo')\n        assert r == 'baz'\n\n    def test_trigger_unknown_event(self):\n        c = client.Client()\n        c._trigger_event('connect', run_async=False)\n        c._trigger_event('message', 123, run_async=True)\n        # should do nothing\n\n    def test_trigger_event_error(self):\n        c = client.Client()\n\n        @c.on('connect')\n        def foo():\n            return 1 / 0\n\n        @c.on('message')\n        def bar(data):\n            return 1 / 0\n\n        r = c._trigger_event('connect', run_async=False)\n        assert r is None\n        r = c._trigger_event('message', 123, run_async=False)\n        assert r is None\n\n    def test_engineio_url(self):\n        c = client.Client()\n        assert (\n            c._get_engineio_url('http://foo', 'bar', 'polling')\n            == 'http://foo/bar/?transport=polling&EIO=4'\n        )\n        assert (\n            c._get_engineio_url('http://foo', 'bar', 'websocket')\n            == 'ws://foo/bar/?transport=websocket&EIO=4'\n        )\n        assert (\n            c._get_engineio_url('ws://foo', 'bar', 'polling')\n            == 'http://foo/bar/?transport=polling&EIO=4'\n        )\n        assert (\n            c._get_engineio_url('ws://foo', 'bar', 'websocket')\n            == 'ws://foo/bar/?transport=websocket&EIO=4'\n        )\n        assert (\n            c._get_engineio_url('https://foo', 'bar', 'polling')\n            == 'https://foo/bar/?transport=polling&EIO=4'\n        )\n        assert (\n            c._get_engineio_url('https://foo', 'bar', 'websocket')\n            == 'wss://foo/bar/?transport=websocket&EIO=4'\n        )\n        assert (\n            c._get_engineio_url('http://foo?baz=1', 'bar', 'polling')\n            == 'http://foo/bar/?baz=1&transport=polling&EIO=4'\n        )\n        assert (\n            c._get_engineio_url('http://foo#baz', 'bar', 'polling')\n            == 'http://foo/bar/?transport=polling&EIO=4'\n        )\n\n    def test_read_loop_polling_disconnected(self):\n        c = client.Client()\n        c.state = 'disconnected'\n        c._trigger_event = mock.MagicMock()\n        c.write_loop_task = mock.MagicMock()\n        c._read_loop_polling()\n        c.write_loop_task.join.assert_called_once_with()\n        c._trigger_event.assert_not_called()\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    def test_read_loop_polling_no_response(self, _time):\n        c = client.Client()\n        c.ping_interval = 25\n        c.ping_timeout = 5\n        c.state = 'connected'\n        c.base_url = 'http://foo'\n        self.mock_queue(c)\n        c._send_request = mock.MagicMock(return_value=None)\n        c._trigger_event = mock.MagicMock()\n        c.write_loop_task = mock.MagicMock()\n        c._read_loop_polling()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_called_once_with(None)\n        c.write_loop_task.join.assert_called_once_with()\n        c._send_request.assert_called_once_with(\n            'GET', 'http://foo&t=123.456', timeout=30\n        )\n        c._trigger_event.assert_called_once_with(\n            'disconnect', c.reason.TRANSPORT_ERROR, run_async=False)\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    def test_read_loop_polling_bad_status(self, _time):\n        c = client.Client()\n        c.ping_interval = 25\n        c.ping_timeout = 5\n        c.state = 'connected'\n        c.base_url = 'http://foo'\n        self.mock_queue(c)\n        c._send_request = mock.MagicMock()\n        c._send_request.return_value.status_code = 400\n        c.write_loop_task = mock.MagicMock()\n        c._read_loop_polling()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_called_once_with(None)\n        c.write_loop_task.join.assert_called_once_with()\n        c._send_request.assert_called_once_with(\n            'GET', 'http://foo&t=123.456', timeout=30\n        )\n\n    @mock.patch('engineio.client.time.time', return_value=123.456)\n    def test_read_loop_polling_bad_packet(self, _time):\n        c = client.Client()\n        c.ping_interval = 25\n        c.ping_timeout = 60\n        c.state = 'connected'\n        c.base_url = 'http://foo'\n        self.mock_queue(c)\n        c._send_request = mock.MagicMock()\n        c._send_request.return_value.status_code = 200\n        c._send_request.return_value.content = b'foo'\n        c.write_loop_task = mock.MagicMock()\n        c._read_loop_polling()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_called_once_with(None)\n        c.write_loop_task.join.assert_called_once_with()\n        c._send_request.assert_called_once_with(\n            'GET', 'http://foo&t=123.456', timeout=65\n        )\n\n    def test_read_loop_polling(self):\n        c = client.Client()\n        c.ping_interval = 25\n        c.ping_timeout = 5\n        c.state = 'connected'\n        c.base_url = 'http://foo'\n        self.mock_queue(c)\n        c._send_request = mock.MagicMock()\n        c._send_request.side_effect = [\n            mock.MagicMock(\n                status_code=200,\n                content=payload.Payload(\n                    packets=[\n                        packet.Packet(packet.PING),\n                        packet.Packet(packet.NOOP),\n                    ]\n                ).encode().encode('utf-8'),\n            ),\n            None,\n        ]\n        c.write_loop_task = mock.MagicMock()\n        c._receive_packet = mock.MagicMock()\n        c._read_loop_polling()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_called_once_with(None)\n        assert c._send_request.call_count == 2\n        assert c._receive_packet.call_count == 2\n        assert c._receive_packet.call_args_list[0][0][0].encode() == '2'\n        assert c._receive_packet.call_args_list[1][0][0].encode() == '6'\n\n    def test_read_loop_websocket_disconnected(self):\n        c = client.Client()\n        c.state = 'disconnected'\n        c.write_loop_task = mock.MagicMock()\n        c._read_loop_websocket()\n        c.write_loop_task.join.assert_called_once_with()\n\n    def test_read_loop_websocket_timeout(self):\n        c = client.Client()\n        c.state = 'connected'\n        self.mock_queue(c)\n        c.ws = mock.MagicMock()\n        c.ws.recv.side_effect = websocket.WebSocketTimeoutException\n        c.write_loop_task = mock.MagicMock()\n        c._read_loop_websocket()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_called_once_with(None)\n        c.write_loop_task.join.assert_called_once_with()\n\n    def test_read_loop_websocket_no_response(self):\n        c = client.Client()\n        c.state = 'connected'\n        self.mock_queue(c)\n        c.ws = mock.MagicMock()\n        c.ws.recv.side_effect = websocket.WebSocketConnectionClosedException\n        c.write_loop_task = mock.MagicMock()\n        c._read_loop_websocket()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_called_once_with(None)\n        c.write_loop_task.join.assert_called_once_with()\n\n    def test_read_loop_websocket_unexpected_error(self):\n        c = client.Client()\n        c.state = 'connected'\n        self.mock_queue(c)\n        c.ws = mock.MagicMock()\n        c.ws.recv.side_effect = ValueError\n        c.write_loop_task = mock.MagicMock()\n        c._read_loop_websocket()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_called_once_with(None)\n        c.write_loop_task.join.assert_called_once_with()\n\n    def test_read_loop_websocket(self):\n        c = client.Client()\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.state = 'connected'\n        self.mock_queue(c)\n        c.ws = mock.MagicMock()\n        c.ws.recv.side_effect = [\n            packet.Packet(packet.PING).encode(),\n            ValueError,\n        ]\n        c.write_loop_task = mock.MagicMock()\n        c._receive_packet = mock.MagicMock()\n        c._read_loop_websocket()\n        assert c.state == 'disconnected'\n        c.queue.put.assert_called_once_with(None)\n        c.write_loop_task.join.assert_called_once_with()\n        assert c._receive_packet.call_args_list[0][0][0].encode() == '2'\n\n    def test_write_loop_disconnected(self):\n        c = client.Client()\n        c.state = 'disconnected'\n        c._write_loop()\n        # should not block\n\n    def test_write_loop_no_packets(self):\n        c = client.Client()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        self.mock_queue(c)\n        c.queue.get.return_value = None\n        c._write_loop()\n        c.queue.task_done.assert_called_once_with()\n        c.queue.get.assert_called_once_with(timeout=7)\n\n    def test_write_loop_empty_queue(self):\n        c = client.Client()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        self.mock_queue(c)\n        c.queue.get.side_effect = c.queue_empty\n        c._write_loop()\n        c.queue.get.assert_called_once_with(timeout=7)\n\n    def test_write_loop_polling_one_packet(self):\n        c = client.Client()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n            c.queue_empty,\n            c.queue_empty,\n        ]\n        c._send_request = mock.MagicMock()\n        c._send_request.return_value.status_code = 200\n        c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        p = payload.Payload(\n            packets=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})]\n        )\n        c._send_request.assert_called_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n\n    def test_write_loop_polling_three_packets(self):\n        c = client.Client()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n            packet.Packet(packet.PING),\n            packet.Packet(packet.NOOP),\n            c.queue_empty,\n            c.queue_empty,\n        ]\n        c._send_request = mock.MagicMock()\n        c._send_request.return_value.status_code = 200\n        c._write_loop()\n        assert c.queue.task_done.call_count == 3\n        p = payload.Payload(\n            packets=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                packet.Packet(packet.PING),\n                packet.Packet(packet.NOOP),\n            ]\n        )\n        c._send_request.assert_called_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n\n    def test_write_loop_polling_two_packets_done(self):\n        c = client.Client()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n            packet.Packet(packet.PING),\n            None,\n            c.queue_empty,\n        ]\n        c._send_request = mock.MagicMock()\n        c._send_request.return_value.status_code = 200\n        c._write_loop()\n        assert c.queue.task_done.call_count == 3\n        p = payload.Payload(\n            packets=[\n                packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n                packet.Packet(packet.PING),\n            ]\n        )\n        c._send_request.assert_called_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n        assert c.state == 'connected'\n\n    def test_write_loop_polling_bad_connection(self):\n        c = client.Client()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n            c.queue_empty,\n        ]\n        c._send_request = mock.MagicMock()\n        c._send_request.return_value = None\n        c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        p = payload.Payload(\n            packets=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})]\n        )\n        c._send_request.assert_called_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n        assert c.state == 'connected'\n\n    def test_write_loop_polling_bad_status(self):\n        c = client.Client()\n        c.base_url = 'http://foo'\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'polling'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n            c.queue_empty,\n        ]\n        c._send_request = mock.MagicMock()\n        c._send_request.return_value.status_code = 500\n        c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        p = payload.Payload(\n            packets=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})]\n        )\n        c._send_request.assert_called_once_with(\n            'POST',\n            'http://foo',\n            body=p.encode(),\n            headers={'Content-Type': 'text/plain'},\n            timeout=5,\n        )\n        assert c.state == 'connected'\n        assert c.write_loop_task is None\n\n    def test_write_loop_websocket_one_packet(self):\n        c = client.Client()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n            c.queue_empty,\n            c.queue_empty,\n        ]\n        c.ws = mock.MagicMock()\n        c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        assert c.ws.send.call_count == 1\n        assert c.ws.send_binary.call_count == 0\n        c.ws.send.assert_called_once_with('4{\"foo\":\"bar\"}')\n\n    def test_write_loop_websocket_three_packets(self):\n        c = client.Client()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n            packet.Packet(packet.PING),\n            packet.Packet(packet.NOOP),\n            c.queue_empty,\n            c.queue_empty,\n        ]\n        c.ws = mock.MagicMock()\n        c._write_loop()\n        assert c.queue.task_done.call_count == 3\n        assert c.ws.send.call_count == 3\n        assert c.ws.send_binary.call_count == 0\n        assert c.ws.send.call_args_list[0][0][0] == '4{\"foo\":\"bar\"}'\n        assert c.ws.send.call_args_list[1][0][0] == '2'\n        assert c.ws.send.call_args_list[2][0][0] == '6'\n\n    def test_write_loop_websocket_one_packet_binary(self):\n        c = client.Client()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, b'foo'),\n            c.queue_empty,\n            c.queue_empty,\n        ]\n        c.ws = mock.MagicMock()\n        c._write_loop()\n        assert c.queue.task_done.call_count == 1\n        assert c.ws.send.call_count == 0\n        assert c.ws.send_binary.call_count == 1\n        c.ws.send_binary.assert_called_once_with(b'foo')\n\n    def test_write_loop_websocket_bad_connection(self):\n        c = client.Client()\n        c.state = 'connected'\n        c.ping_interval = 1\n        c.ping_timeout = 2\n        c.current_transport = 'websocket'\n        self.mock_queue(c)\n        c.queue.get.side_effect = [\n            packet.Packet(packet.MESSAGE, {'foo': 'bar'}),\n            c.queue_empty,\n            c.queue_empty,\n        ]\n        c.ws = mock.MagicMock()\n        c.ws.send.side_effect = websocket.WebSocketConnectionClosedException\n        c._write_loop()\n        assert c.state == 'connected'\n\n    @mock.patch('engineio.base_client.original_signal_handler')\n    def test_signal_handler(self, original_handler):\n        clients = [mock.MagicMock(), mock.MagicMock()]\n        base_client.connected_clients = clients[:]\n        base_client.connected_clients[0].is_asyncio_based.return_value = False\n        base_client.connected_clients[1].is_asyncio_based.return_value = True\n        base_client.signal_handler('sig', 'frame')\n        clients[0].disconnect.assert_called_once_with()\n        clients[1].disconnect.assert_not_called()\n"
  },
  {
    "path": "tests/common/test_middleware.py",
    "content": "import os\nfrom unittest import mock\n\nimport engineio\n\n\nclass TestWSGIApp:\n    def test_wsgi_routing(self):\n        mock_wsgi_app = mock.MagicMock()\n        mock_eio_app = 'foo'\n        m = engineio.WSGIApp(mock_eio_app, mock_wsgi_app)\n        environ = {'PATH_INFO': '/foo'}\n        start_response = \"foo\"\n        m(environ, start_response)\n        mock_wsgi_app.assert_called_once_with(environ, start_response)\n\n    def test_eio_routing(self):\n        mock_wsgi_app = 'foo'\n        mock_eio_app = mock.Mock()\n        mock_eio_app.handle_request = mock.MagicMock()\n        m = engineio.WSGIApp(mock_eio_app, mock_wsgi_app)\n        environ = {'PATH_INFO': '/engine.io/'}\n        start_response = \"foo\"\n        m(environ, start_response)\n        mock_eio_app.handle_request.assert_called_once_with(\n            environ, start_response\n        )\n\n    def test_static_files(self):\n        root_dir = os.path.dirname(__file__)\n        m = engineio.WSGIApp(\n            'foo',\n            None,\n            static_files={\n                '/': root_dir + '/index.html',\n                '/foo': {\n                    'content_type': 'text/plain',\n                    'filename': root_dir + '/index.html',\n                },\n                '/static': root_dir,\n                '/static/test/': root_dir + '/',\n                '/static2/test/': {'filename': root_dir + '/',\n                                   'content_type': 'image/gif'},\n            },\n        )\n\n        def check_path(path, status_code, content_type, body):\n            environ = {'PATH_INFO': path}\n            start_response = mock.MagicMock()\n            r = m(environ, start_response)\n            assert r == [body.encode('utf-8')]\n            start_response.assert_called_once_with(\n                status_code, [('Content-Type', content_type)]\n            )\n\n        check_path('/', '200 OK', 'text/html', '<html></html>\\n')\n        check_path('/foo', '200 OK', 'text/plain', '<html></html>\\n')\n        check_path('/foo/bar', '404 Not Found', 'text/plain', 'Not Found')\n        check_path(\n            '/static/index.html', '200 OK', 'text/html', '<html></html>\\n'\n        )\n        check_path(\n            '/static/foo.bar', '404 Not Found', 'text/plain', 'Not Found'\n        )\n        check_path(\n            '/static/test/index.html', '200 OK', 'text/html', '<html></html>\\n'\n        )\n        check_path('/static/test/', '200 OK', 'text/html', '<html></html>\\n')\n        check_path('/static/test/index.html', '200 OK', 'text/html',\n                   '<html></html>\\n')\n        check_path('/static/test/files/', '200 OK', 'text/html',\n                   '<html>file</html>\\n')\n        check_path('/static/test/files/file.txt', '200 OK', 'text/plain',\n                   'file\\n')\n        check_path('/static/test/files/x.html', '404 Not Found', 'text/plain',\n                   'Not Found')\n        check_path('/static2/test/', '200 OK', 'image/gif', '<html></html>\\n')\n        check_path('/static2/test/index.html', '200 OK', 'image/gif',\n                   '<html></html>\\n')\n        check_path('/static2/test/files/', '200 OK', 'image/gif',\n                   '<html>file</html>\\n')\n        check_path('/static2/test/files/file.txt', '200 OK', 'image/gif',\n                   'file\\n')\n        check_path('/static2/test/files/x.html', '404 Not Found', 'text/plain',\n                   'Not Found')\n        check_path('/bar/foo', '404 Not Found', 'text/plain', 'Not Found')\n        check_path('', '404 Not Found', 'text/plain', 'Not Found')\n\n        m.static_files[''] = 'index.html'\n        check_path('/static/test/', '200 OK', 'text/html', '<html></html>\\n')\n\n        m.static_files[''] = {'filename': 'index.html'}\n        check_path('/static/test/', '200 OK', 'text/html', '<html></html>\\n')\n\n        m.static_files[''] = {\n            'filename': 'index.html',\n            'content_type': 'image/gif',\n        }\n        check_path('/static/test/', '200 OK', 'image/gif', '<html></html>\\n')\n\n        m.static_files[''] = {'filename': 'test.gif'}\n        check_path('/static/test/', '404 Not Found', 'text/plain', 'Not Found')\n\n        m.static_files = {}\n        check_path(\n            '/static/test/index.html',\n            '404 Not Found',\n            'text/plain',\n            'Not Found',\n        )\n\n    def test_404(self):\n        mock_wsgi_app = None\n        mock_eio_app = mock.Mock()\n        m = engineio.WSGIApp(mock_eio_app, mock_wsgi_app)\n        environ = {'PATH_INFO': '/foo/bar'}\n        start_response = mock.MagicMock()\n        r = m(environ, start_response)\n        assert r == [b'Not Found']\n        start_response.assert_called_once_with(\n            \"404 Not Found\", [('Content-Type', 'text/plain')]\n        )\n\n    def test_custom_eio_path(self):\n        mock_wsgi_app = None\n        mock_eio_app = mock.Mock()\n        mock_eio_app.handle_request = mock.MagicMock()\n        m = engineio.WSGIApp(mock_eio_app, mock_wsgi_app, engineio_path='foo')\n        environ = {'PATH_INFO': '/engine.io/'}\n        start_response = mock.MagicMock()\n        r = m(environ, start_response)\n        assert r == [b'Not Found']\n        start_response.assert_called_once_with(\n            \"404 Not Found\", [('Content-Type', 'text/plain')]\n        )\n\n        environ = {'PATH_INFO': '/foo/'}\n        m(environ, start_response)\n        mock_eio_app.handle_request.assert_called_once_with(\n            environ, start_response\n        )\n\n    def test_custom_eio_path_slashes(self):\n        mock_wsgi_app = None\n        mock_eio_app = mock.Mock()\n        mock_eio_app.handle_request = mock.MagicMock()\n        m = engineio.WSGIApp(\n            mock_eio_app, mock_wsgi_app, engineio_path='/foo/'\n        )\n        environ = {'PATH_INFO': '/foo/'}\n        start_response = mock.MagicMock()\n        m(environ, start_response)\n        mock_eio_app.handle_request.assert_called_once_with(\n            environ, start_response\n        )\n\n    def test_custom_eio_path_leading_slash(self):\n        mock_wsgi_app = None\n        mock_eio_app = mock.Mock()\n        mock_eio_app.handle_request = mock.MagicMock()\n        m = engineio.WSGIApp(mock_eio_app, mock_wsgi_app, engineio_path='/foo')\n        environ = {'PATH_INFO': '/foo/'}\n        start_response = mock.MagicMock()\n        m(environ, start_response)\n        mock_eio_app.handle_request.assert_called_once_with(\n            environ, start_response\n        )\n\n    def test_custom_eio_path_trailing_slash(self):\n        mock_wsgi_app = None\n        mock_eio_app = mock.Mock()\n        mock_eio_app.handle_request = mock.MagicMock()\n        m = engineio.WSGIApp(mock_eio_app, mock_wsgi_app, engineio_path='foo/')\n        environ = {'PATH_INFO': '/foo/'}\n        start_response = mock.MagicMock()\n        m(environ, start_response)\n        mock_eio_app.handle_request.assert_called_once_with(\n            environ, start_response\n        )\n\n    def test_gunicorn_socket(self):\n        mock_wsgi_app = None\n        mock_eio_app = mock.Mock()\n        m = engineio.WSGIApp(mock_eio_app, mock_wsgi_app)\n        environ = {'gunicorn.socket': 123, 'PATH_INFO': '/foo/bar'}\n        start_response = mock.MagicMock()\n        m(environ, start_response)\n        assert 'eventlet.input' in environ\n        assert environ['eventlet.input'].get_socket() == 123\n\n    def test_legacy_middleware_class(self):\n        m = engineio.Middleware('eio', 'wsgi', 'eio_path')\n        assert m.engineio_app == 'eio'\n        assert m.wsgi_app == 'wsgi'\n        assert m.static_files == {}\n        assert m.engineio_path == '/eio_path/'\n"
  },
  {
    "path": "tests/common/test_packet.py",
    "content": "import pytest\n\nfrom engineio import packet\n\n\nclass TestPacket:\n    def test_encode_default_packet(self):\n        pkt = packet.Packet()\n        assert pkt.packet_type == packet.NOOP\n        assert pkt.data is None\n        assert not pkt.binary\n        assert pkt.encode() == '6'\n\n    def test_decode_default_packet(self):\n        pkt = packet.Packet(encoded_packet='6')\n        assert pkt.encode() == '6'\n\n    def test_encode_text_packet(self):\n        data = 'text'\n        pkt = packet.Packet(packet.MESSAGE, data=data)\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == data\n        assert not pkt.binary\n        assert pkt.encode() == '4text'\n\n    def test_decode_text_packet(self):\n        pkt = packet.Packet(encoded_packet=b'4text')\n        assert pkt.encode() == b'4text'\n\n    def test_encode_empty_text_packet(self):\n        data = ''\n        pkt = packet.Packet(packet.MESSAGE, data=data)\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == data\n        assert not pkt.binary\n        assert pkt.encode() == '4'\n\n    def test_decode_empty_text_packet(self):\n        pkt = packet.Packet(encoded_packet=b'4')\n        assert pkt.encode() == b'4'\n\n    def test_encode_binary_packet(self):\n        pkt = packet.Packet(packet.MESSAGE, data=b'\\x01\\x02\\x03')\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == b'\\x01\\x02\\x03'\n        assert pkt.binary\n        assert pkt.encode() == b'\\x01\\x02\\x03'\n\n    def test_encode_binary_bytearray_packet(self):\n        pkt = packet.Packet(packet.MESSAGE, data=bytearray(b'\\x01\\x02\\x03'))\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == b'\\x01\\x02\\x03'\n        assert pkt.binary\n        assert pkt.encode() == b'\\x01\\x02\\x03'\n\n    def test_encode_binary_b64_packet(self):\n        pkt = packet.Packet(packet.MESSAGE, data=b'\\x01\\x02\\x03\\x04')\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == b'\\x01\\x02\\x03\\x04'\n        assert pkt.binary\n        assert pkt.encode(b64=True) == 'bAQIDBA=='\n\n    def test_encode_empty_binary_packet(self):\n        pkt = packet.Packet(packet.MESSAGE, data=b'')\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == b''\n        assert pkt.binary\n        assert pkt.encode() == b''\n\n    def test_decode_binary_packet(self):\n        pkt = packet.Packet(encoded_packet=b'\\x04\\x01\\x02\\x03')\n        assert pkt.encode() == b'\\x04\\x01\\x02\\x03'\n\n    def test_decode_binary_bytearray_packet(self):\n        pkt = packet.Packet(encoded_packet=bytearray(b'\\x04\\x01\\x02\\x03'))\n        assert pkt.encode() == b'\\x04\\x01\\x02\\x03'\n\n    def test_decode_binary_b64_packet(self):\n        pkt = packet.Packet(encoded_packet='bBAECAw==')\n        assert pkt.encode() == b'\\x04\\x01\\x02\\x03'\n\n    def test_decode_empty_binary_packet(self):\n        pkt = packet.Packet(encoded_packet=b'')\n        assert pkt.encode() == b''\n\n    def test_encode_json_packet(self):\n        pkt = packet.Packet(packet.MESSAGE, data={'a': 123, 'b': '456'})\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == {'a': 123, 'b': '456'}\n        assert not pkt.binary\n        assert pkt.encode() in [\n            '4{\"a\":123,\"b\":\"456\"}',\n            '4{\"b\":\"456\",\"a\":123}',\n        ]\n\n    def test_decode_json_packet(self):\n        pkt = packet.Packet(encoded_packet='4{\"a\":123,\"b\":\"456\"}')\n        assert pkt.encode() in [\n            '4{\"a\":123,\"b\":\"456\"}',\n            '4{\"b\":\"456\",\"a\":123}',\n        ]\n\n    def test_decode_json_packet_long_int(self):\n        pkt = packet.Packet(encoded_packet='4{\"a\":' + '1' * 100 + '}')\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == {'a': int('1' * 100)}\n        pkt = packet.Packet(encoded_packet='4{\"a\":' + '1' * 101 + '}')\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == '{\"a\":' + '1' * 101 + '}'\n\n    def test_encode_number_packet(self):\n        pkt = packet.Packet(packet.MESSAGE, data=123)\n        assert pkt.packet_type == packet.MESSAGE\n        assert pkt.data == 123\n        assert not pkt.binary\n        assert pkt.encode() == '4123'\n\n    def test_decode_number_packet(self):\n        pkt = packet.Packet(encoded_packet='4123')\n        assert pkt.packet_type == packet.MESSAGE\n        # integer payloads are parsed as strings, see\n        # https://github.com/miguelgrinberg/python-engineio/issues/75\n        # for background on this decision\n        assert pkt.data == '123'\n        assert not pkt.binary\n        assert pkt.encode() == '4123'\n\n    def test_binary_non_message_packet(self):\n        with pytest.raises(ValueError):\n            packet.Packet(packet.NOOP, b'\\x01\\x02\\x03')\n\n    def test_decode_invalid_empty_text_packet(self):\n        with pytest.raises(ValueError):\n            packet.Packet(encoded_packet='')\n\n    def test_encode_cache(self):\n        pkt = packet.Packet(packet.MESSAGE, data=123)\n        assert pkt.encode() == '4123'\n        pkt.data = 456\n        assert pkt.encode() == '4123'\n        pkt.encode_cache = None\n        assert pkt.encode() == '4456'\n"
  },
  {
    "path": "tests/common/test_payload.py",
    "content": "import pytest\n\nfrom engineio import packet\nfrom engineio import payload\n\n\nclass TestPayload:\n    def test_encode_empty_payload(self):\n        p = payload.Payload()\n        assert p.packets == []\n        assert p.encode() == ''\n\n    def test_decode_empty_payload(self):\n        p = payload.Payload(encoded_payload='')\n        assert p.encode() == ''\n\n    def test_encode_payload_text(self):\n        pkt = packet.Packet(packet.MESSAGE, data='abc')\n        p = payload.Payload([pkt])\n        assert p.packets == [pkt]\n        assert p.encode() == '4abc'\n\n    def test_encode_payload_text_multiple(self):\n        pkt = packet.Packet(packet.MESSAGE, data='abc')\n        pkt2 = packet.Packet(packet.MESSAGE, data='def')\n        p = payload.Payload([pkt, pkt2])\n        assert p.packets == [pkt, pkt2]\n        assert p.encode() == '4abc\\x1e4def'\n\n    def test_encode_payload_binary(self):\n        pkt = packet.Packet(packet.MESSAGE, data=b'\\x00\\x01\\x02')\n        p = payload.Payload([pkt])\n        assert p.packets == [pkt]\n        assert p.encode() == 'bAAEC'\n\n    def test_encode_payload_binary_multiple(self):\n        pkt = packet.Packet(packet.MESSAGE, data=b'\\x00\\x01\\x02')\n        pkt2 = packet.Packet(packet.MESSAGE, data=b'\\x03\\x04\\x05\\x06')\n        p = payload.Payload([pkt, pkt2])\n        assert p.packets == [pkt, pkt2]\n        assert p.encode() == 'bAAEC\\x1ebAwQFBg=='\n\n    def test_encode_payload_text_binary_multiple(self):\n        pkt = packet.Packet(packet.MESSAGE, data='abc')\n        pkt2 = packet.Packet(packet.MESSAGE, data=b'\\x03\\x04\\x05\\x06')\n        p = payload.Payload([pkt, pkt2, pkt2, pkt])\n        assert p.packets == [pkt, pkt2, pkt2, pkt]\n        assert p.encode() == '4abc\\x1ebAwQFBg==\\x1ebAwQFBg==\\x1e4abc'\n\n    def test_encode_jsonp_payload(self):\n        pkt = packet.Packet(packet.MESSAGE, data='abc')\n        p = payload.Payload([pkt])\n        assert p.packets == [pkt]\n        assert p.encode(jsonp_index=233) == '___eio[233](\"4abc\");'\n\n    def test_decode_jsonp_payload(self):\n        p = payload.Payload(encoded_payload='d=4abc')\n        assert p.encode() == '4abc'\n\n    def test_decode_invalid_payload(self):\n        with pytest.raises(ValueError):\n            payload.Payload(encoded_payload='bad payload')\n\n    def test_decode_multi_payload_with_too_many_packets(self):\n        with pytest.raises(ValueError):\n            payload.Payload(encoded_payload='4abc\\x1e4def\\x1e' * 9 + '6')\n"
  },
  {
    "path": "tests/common/test_server.py",
    "content": "import gzip\nimport importlib\nimport io\nimport logging\nimport sys\nimport time\nfrom unittest import mock\nimport zlib\n\nimport pytest\n\nfrom engineio import exceptions\nfrom engineio import json\nfrom engineio import packet\nfrom engineio import payload\nfrom engineio import server\n\noriginal_import_module = importlib.import_module\n\n\ndef _mock_import(module, *args, **kwargs):\n    if module.startswith('engineio.'):\n        return original_import_module(module, *args, **kwargs)\n    return module\n\n\nclass TestServer:\n    _mock_async = mock.MagicMock()\n    _mock_async._async = {\n        'thread': 't',\n        'queue': 'q',\n        'queue_empty': RuntimeError,\n        'websocket': 'w',\n    }\n\n    def _get_mock_socket(self):\n        mock_socket = mock.MagicMock()\n        mock_socket.closed = False\n        mock_socket.closing = False\n        mock_socket.upgraded = False\n        mock_socket.session = {}\n        return mock_socket\n\n    @classmethod\n    def setup_class(cls):\n        server.Server._default_monitor_clients = False\n\n    @classmethod\n    def teardown_class(cls):\n        server.Server._default_monitor_clients = True\n\n    def setup_method(self):\n        logging.getLogger('engineio').setLevel(logging.NOTSET)\n\n    def teardown_method(self):\n        # restore JSON encoder, in case a test changed it\n        packet.Packet.json = json\n\n    def test_is_asyncio_based(self):\n        s = server.Server()\n        assert not s.is_asyncio_based()\n\n    def test_async_modes(self):\n        s = server.Server()\n        assert s.async_modes() == [\n            'eventlet',\n            'gevent_uwsgi',\n            'gevent',\n            'threading',\n        ]\n\n    def test_create(self):\n        kwargs = {\n            'ping_timeout': 1,\n            'ping_interval': 2,\n            'max_http_buffer_size': 3,\n            'allow_upgrades': False,\n            'http_compression': False,\n            'compression_threshold': 4,\n            'cookie': 'foo',\n            'cors_allowed_origins': ['foo', 'bar', 'baz'],\n            'cors_credentials': False,\n            'async_handlers': False,\n        }\n        s = server.Server(**kwargs)\n        for arg in kwargs.keys():\n            assert getattr(s, arg) == kwargs[arg]\n        assert s.ping_interval_grace_period == 0\n\n    def test_create_with_grace_period(self):\n        s = server.Server(ping_interval=(1, 2))\n        assert s.ping_interval == 1\n        assert s.ping_interval_grace_period == 2\n\n    def test_create_ignores_kwargs(self):\n        server.Server(foo='bar')  # this should not raise\n\n    def test_async_mode_threading(self):\n        sys.modules['simple_websocket'] = mock.MagicMock()\n        s = server.Server(async_mode='threading')\n        assert s.async_mode == 'threading'\n\n        from engineio.async_drivers import threading as async_threading\n        import queue\n\n        assert s._async['thread'] == async_threading.DaemonThread\n        assert s._async['queue'] == queue.Queue\n        assert s._async['websocket'] == async_threading.SimpleWebSocketWSGI\n        del sys.modules['simple_websocket']\n        del sys.modules['engineio.async_drivers.threading']\n\n    def test_async_mode_eventlet(self):\n        sys.modules['eventlet'] = mock.MagicMock()\n        sys.modules['eventlet'].green = mock.MagicMock()\n        sys.modules['eventlet.green'] = sys.modules['eventlet'].green\n        sys.modules['eventlet.green'].threading = mock.MagicMock()\n        sys.modules['eventlet.green.threading'] = \\\n            sys.modules['eventlet.green'].threading\n        sys.modules['eventlet'].websocket = mock.MagicMock()\n        sys.modules['eventlet.websocket'] = sys.modules['eventlet'].websocket\n        s = server.Server(async_mode='eventlet')\n        assert s.async_mode == 'eventlet'\n\n        from eventlet import queue\n        from engineio.async_drivers import eventlet as async_eventlet\n\n        assert s._async['thread'] == async_eventlet.EventletThread\n        assert s._async['queue'] == queue.Queue\n        assert s._async['websocket'] == async_eventlet.WebSocketWSGI\n        del sys.modules['eventlet']\n        del sys.modules['eventlet.green']\n        del sys.modules['eventlet.green.threading']\n        del sys.modules['eventlet.websocket']\n        del sys.modules['engineio.async_drivers.eventlet']\n\n    @mock.patch('importlib.import_module', side_effect=_mock_import)\n    def test_async_mode_gevent_uwsgi(self, import_module):\n        sys.modules['gevent'] = mock.MagicMock()\n        sys.modules['gevent'].queue = mock.MagicMock()\n        sys.modules['gevent.queue'] = sys.modules['gevent'].queue\n        sys.modules['gevent.queue'].JoinableQueue = 'foo'\n        sys.modules['gevent.queue'].Empty = RuntimeError\n        sys.modules['gevent.event'] = mock.MagicMock()\n        sys.modules['gevent.event'].Event = 'bar'\n        sys.modules['uwsgi'] = mock.MagicMock()\n        s = server.Server(async_mode='gevent_uwsgi')\n        assert s.async_mode == 'gevent_uwsgi'\n\n        from engineio.async_drivers import gevent_uwsgi as async_gevent_uwsgi\n\n        assert s._async['thread'] == async_gevent_uwsgi.Thread\n        assert s._async['queue'] == 'foo'\n        assert s._async['queue_empty'] == RuntimeError\n        assert s._async['event'] == 'bar'\n        assert s._async['websocket'] == async_gevent_uwsgi.uWSGIWebSocket\n        del sys.modules['gevent']\n        del sys.modules['gevent.queue']\n        del sys.modules['gevent.event']\n        del sys.modules['uwsgi']\n        del sys.modules['engineio.async_drivers.gevent_uwsgi']\n\n    @mock.patch('importlib.import_module', side_effect=_mock_import)\n    def test_async_mode_gevent_uwsgi_without_uwsgi(self, import_module):\n        sys.modules['gevent'] = mock.MagicMock()\n        sys.modules['gevent'].queue = mock.MagicMock()\n        sys.modules['gevent.queue'] = sys.modules['gevent'].queue\n        sys.modules['gevent.queue'].JoinableQueue = 'foo'\n        sys.modules['gevent.queue'].Empty = RuntimeError\n        sys.modules['gevent.event'] = mock.MagicMock()\n        sys.modules['gevent.event'].Event = 'bar'\n        sys.modules['uwsgi'] = None\n        with pytest.raises(ValueError):\n            server.Server(async_mode='gevent_uwsgi')\n        del sys.modules['gevent']\n        del sys.modules['gevent.queue']\n        del sys.modules['gevent.event']\n        del sys.modules['uwsgi']\n\n    @mock.patch('importlib.import_module', side_effect=_mock_import)\n    def test_async_mode_gevent_uwsgi_without_websocket(self, import_module):\n        sys.modules['gevent'] = mock.MagicMock()\n        sys.modules['gevent'].queue = mock.MagicMock()\n        sys.modules['gevent.queue'] = sys.modules['gevent'].queue\n        sys.modules['gevent.queue'].JoinableQueue = 'foo'\n        sys.modules['gevent.queue'].Empty = RuntimeError\n        sys.modules['gevent.event'] = mock.MagicMock()\n        sys.modules['gevent.event'].Event = 'bar'\n        sys.modules['uwsgi'] = mock.MagicMock()\n        del sys.modules['uwsgi'].websocket_handshake\n        s = server.Server(async_mode='gevent_uwsgi')\n        assert s.async_mode == 'gevent_uwsgi'\n\n        from engineio.async_drivers import gevent_uwsgi as async_gevent_uwsgi\n\n        assert s._async['thread'] == async_gevent_uwsgi.Thread\n        assert s._async['queue'] == 'foo'\n        assert s._async['queue_empty'] == RuntimeError\n        assert s._async['event'] == 'bar'\n        assert s._async['websocket'] is None\n        del sys.modules['gevent']\n        del sys.modules['gevent.queue']\n        del sys.modules['gevent.event']\n        del sys.modules['uwsgi']\n        del sys.modules['engineio.async_drivers.gevent_uwsgi']\n\n    @mock.patch('importlib.import_module', side_effect=_mock_import)\n    def test_async_mode_gevent(self, import_module):\n        sys.modules['gevent'] = mock.MagicMock()\n        sys.modules['gevent'].queue = mock.MagicMock()\n        sys.modules['gevent.queue'] = sys.modules['gevent'].queue\n        sys.modules['gevent.queue'].JoinableQueue = 'foo'\n        sys.modules['gevent.queue'].Empty = RuntimeError\n        sys.modules['gevent.event'] = mock.MagicMock()\n        sys.modules['gevent.event'].Event = 'bar'\n        sys.modules['geventwebsocket'] = 'geventwebsocket'\n        s = server.Server(async_mode='gevent')\n        assert s.async_mode == 'gevent'\n\n        from engineio.async_drivers import gevent as async_gevent\n\n        assert s._async['thread'] == async_gevent.Thread\n        assert s._async['queue'] == 'foo'\n        assert s._async['queue_empty'] == RuntimeError\n        assert s._async['event'] == 'bar'\n        assert s._async['websocket'] == async_gevent.WebSocketWSGI\n        del sys.modules['gevent']\n        del sys.modules['gevent.queue']\n        del sys.modules['gevent.event']\n        del sys.modules['geventwebsocket']\n        del sys.modules['engineio.async_drivers.gevent']\n\n    @mock.patch('importlib.import_module', side_effect=_mock_import)\n    def test_async_mode_aiohttp(self, import_module):\n        sys.modules['aiohttp'] = mock.MagicMock()\n        with pytest.raises(ValueError):\n            server.Server(async_mode='aiohttp')\n\n    @mock.patch('importlib.import_module', side_effect=[ImportError])\n    def test_async_mode_invalid(self, import_module):\n        with pytest.raises(ValueError):\n            server.Server(async_mode='foo')\n\n    @mock.patch(\n        'importlib.import_module',\n        side_effect=[_mock_async],\n    )\n    def test_async_mode_auto_eventlet(self, import_module):\n        s = server.Server()\n        assert s.async_mode == 'eventlet'\n\n    @mock.patch(\n        'importlib.import_module', side_effect=[ImportError, _mock_async]\n    )\n    def test_async_mode_auto_gevent_uwsgi(self, import_module):\n        s = server.Server()\n        assert s.async_mode == 'gevent_uwsgi'\n\n    @mock.patch(\n        'importlib.import_module',\n        side_effect=[ImportError, ImportError, _mock_async],\n    )\n    def test_async_mode_auto_gevent(self, import_module):\n        s = server.Server()\n        assert s.async_mode == 'gevent'\n\n    @mock.patch(\n        'importlib.import_module',\n        side_effect=[ImportError, ImportError, ImportError, _mock_async],\n    )\n    def test_async_mode_auto_threading(self, import_module):\n        s = server.Server()\n        assert s.async_mode == 'threading'\n\n    def test_generate_id(self):\n        s = server.Server()\n        assert s.generate_id() != s.generate_id()\n\n    def test_on_event(self):\n        s = server.Server()\n\n        @s.on('connect')\n        def foo():\n            pass\n\n        s.on('disconnect', foo)\n\n        assert s.handlers['connect'] == foo\n        assert s.handlers['disconnect'] == foo\n\n    def test_on_event_invalid(self):\n        s = server.Server()\n        with pytest.raises(ValueError):\n            s.on('invalid')\n\n    def test_trigger_event(self):\n        s = server.Server(async_mode='threading')\n        f = {}\n\n        @s.on('connect')\n        def foo(sid, environ):\n            return sid + environ\n\n        @s.on('message')\n        def bar(sid, data):\n            f['bar'] = sid + data\n            return 'bar'\n\n        @s.on('disconnect')\n        def baz(sid, reason):\n            return sid + reason\n\n        r = s._trigger_event('connect', 1, 2, run_async=False)\n        assert r == 3\n        r = s._trigger_event('message', 3, 4, run_async=True)\n        r.join()\n        assert f['bar'] == 7\n        r = s._trigger_event('message', 5, 6)\n        assert r == 'bar'\n        r = s._trigger_event('disconnect', 'foo', 'bar')\n        assert r == 'foobar'\n\n    def test_trigger_legacy_disconnect_event(self):\n        s = server.Server(async_mode='threading')\n\n        @s.on('disconnect')\n        def baz(sid):\n            return sid\n\n        r = s._trigger_event('disconnect', 'foo', 'bar')\n        assert r == 'foo'\n\n    def test_trigger_event_error(self):\n        s = server.Server()\n\n        @s.on('connect')\n        def foo(sid, environ):\n            return 1 / 0\n\n        @s.on('message')\n        def bar(sid, data):\n            return 1 / 0\n\n        r = s._trigger_event('connect', 1, 2, run_async=False)\n        assert not r\n        r = s._trigger_event('message', 3, 4, run_async=False)\n        assert r is None\n\n    def test_session(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        s.sockets['foo'] = mock_socket\n        with s.session('foo') as session:\n            assert session == {}\n            session['username'] = 'bar'\n        assert s.get_session('foo') == {'username': 'bar'}\n\n    def test_close_one_socket(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        s.sockets['foo'] = mock_socket\n        s.disconnect('foo')\n        assert mock_socket.close.call_count == 1\n        assert 'foo' not in s.sockets\n\n    def test_close_all_sockets(self):\n        s = server.Server()\n        mock_sockets = {}\n        for sid in ['foo', 'bar', 'baz']:\n            mock_sockets[sid] = self._get_mock_socket()\n            s.sockets[sid] = mock_sockets[sid]\n        s.disconnect()\n        for socket in mock_sockets.values():\n            assert socket.close.call_count == 1\n        assert s.sockets == {}\n\n    def test_upgrades(self):\n        s = server.Server()\n        s.sockets['foo'] = self._get_mock_socket()\n        assert s._upgrades('foo', 'polling') == ['websocket']\n        assert s._upgrades('foo', 'websocket') == []\n        s.sockets['foo'].upgraded = True\n        assert s._upgrades('foo', 'polling') == []\n        assert s._upgrades('foo', 'websocket') == []\n        s.allow_upgrades = False\n        s.sockets['foo'].upgraded = True\n        assert s._upgrades('foo', 'polling') == []\n        assert s._upgrades('foo', 'websocket') == []\n\n    def test_transport(self):\n        s = server.Server()\n        s.sockets['foo'] = self._get_mock_socket()\n        s.sockets['foo'].upgraded = False\n        s.sockets['bar'] = self._get_mock_socket()\n        s.sockets['bar'].upgraded = True\n        assert s.transport('foo') == 'polling'\n        assert s.transport('bar') == 'websocket'\n\n    def test_bad_session(self):\n        s = server.Server()\n        s.sockets['foo'] = 'client'\n        with pytest.raises(KeyError):\n            s._get_socket('bar')\n\n    def test_closed_socket(self):\n        s = server.Server()\n        s.sockets['foo'] = self._get_mock_socket()\n        s.sockets['foo'].closed = True\n        with pytest.raises(KeyError):\n            s._get_socket('foo')\n\n    def test_jsonp_with_bad_index(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4&j=abc'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    def test_jsonp_index(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4&j=233'}\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        assert r[0].startswith(b'___eio[233](\"')\n        assert r[0].endswith(b'\");')\n\n    def test_connect(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        assert len(s.sockets) == 1\n        assert start_response.call_count == 1\n        assert start_response.call_args[0][0] == '200 OK'\n        assert (\n            'Content-Type',\n            'text/plain; charset=UTF-8',\n        ) in start_response.call_args[0][1]\n        assert len(r) == 1\n        packets = payload.Payload(encoded_payload=r[0].decode('utf-8')).packets\n        assert len(packets) == 1\n        assert packets[0].packet_type == packet.OPEN\n        assert 'upgrades' in packets[0].data\n        assert packets[0].data['upgrades'] == ['websocket']\n        assert 'sid' in packets[0].data\n        assert packets[0].data['pingTimeout'] == 20000\n        assert packets[0].data['pingInterval'] == 25000\n        assert packets[0].data['maxPayload'] == 1000000\n\n    def test_connect_no_upgrades(self):\n        s = server.Server(allow_upgrades=False)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        packets = payload.Payload(encoded_payload=r[0].decode('utf-8')).packets\n        assert packets[0].data['upgrades'] == []\n\n    def test_connect_bad_eio_version(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=1'}\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0], '400 BAD REQUEST'\n        assert b'unsupported version' in r[0]\n\n    def test_connect_custom_ping_times(self):\n        s = server.Server(ping_timeout=123, ping_interval=456,\n                          max_http_buffer_size=12345678)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        packets = payload.Payload(encoded_payload=r[0].decode('utf-8')).packets\n        assert packets[0].data['pingTimeout'] == 123000\n        assert packets[0].data['pingInterval'] == 456000\n        assert packets[0].data['maxPayload'] == 12345678\n\n    @mock.patch(\n        'engineio.socket.Socket.poll', side_effect=exceptions.QueueEmpty\n    )\n    def test_connect_bad_poll(self, poll):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    @mock.patch(\n        'engineio.socket.Socket',\n        return_value=mock.MagicMock(connected=False, closed=False),\n    )\n    def test_connect_transport_websocket(self, Socket):\n        s = server.Server()\n        s.generate_id = mock.MagicMock(return_value='123')\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&transport=websocket',\n            'HTTP_UPGRADE': 'websocket',\n        }\n        start_response = mock.MagicMock()\n        # force socket to stay open, so that we can check it later\n        Socket().closed = False\n        s.handle_request(environ, start_response)\n        assert s.sockets['123'].send.call_args[0][0].packet_type == packet.OPEN\n\n    @mock.patch(\n        'engineio.socket.Socket',\n        return_value=mock.MagicMock(connected=False, closed=False),\n    )\n    def test_http_upgrade_case_insensitive(self, Socket):\n        s = server.Server()\n        s.generate_id = mock.MagicMock(return_value='123')\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&transport=websocket',\n            'HTTP_UPGRADE': 'WebSocket',\n        }\n        start_response = mock.MagicMock()\n        # force socket to stay open, so that we can check it later\n        Socket().closed = False\n        s.handle_request(environ, start_response)\n        assert s.sockets['123'].send.call_args[0][0].packet_type == packet.OPEN\n\n    @mock.patch(\n        'engineio.socket.Socket',\n        return_value=mock.MagicMock(connected=False, closed=False),\n    )\n    def test_connect_transport_websocket_closed(self, Socket):\n        s = server.Server()\n        s.generate_id = mock.MagicMock(return_value='123')\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&transport=websocket',\n            'HTTP_UPGRADE': 'websocket',\n        }\n        start_response = mock.MagicMock()\n\n        def mock_handle(environ, start_response):\n            s.sockets['123'].closed = True\n\n        Socket().handle_get_request = mock_handle\n        s.handle_request(environ, start_response)\n        assert '123' not in s.sockets\n\n    def test_connect_transport_invalid(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET',\n                   'QUERY_STRING': 'EIO=4&transport=foo'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    def test_connect_transport_websocket_without_upgrade(self):\n        s = server.Server()\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&transport=websocket',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    def test_connect_cors_headers(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Credentials', 'true') in headers\n\n    def test_connect_cors_allowed_origin(self):\n        s = server.Server(cors_allowed_origins=['a', 'b'])\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ORIGIN': 'b',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'b') in headers\n\n    def test_connect_cors_allowed_origin_with_callable(self):\n        def cors(origin):\n            return origin == 'a'\n\n        s = server.Server(cors_allowed_origins=cors)\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ORIGIN': 'a',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'a') in headers\n\n        environ['HTTP_ORIGIN'] = 'b'\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    def test_connect_cors_not_allowed_origin(self):\n        s = server.Server(cors_allowed_origins=['a', 'b'])\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ORIGIN': 'c',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'c') not in headers\n        assert ('Access-Control-Allow-Origin', '*') not in headers\n\n    def test_connect_str_cors_headers_all_origins(self):\n        s = server.Server(cors_allowed_origins='*')\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ORIGIN': 'foo',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'foo') in headers\n        assert ('Access-Control-Allow-Credentials', 'true') in headers\n\n    def test_connect_list_cors_headers_all_origins(self):\n        s = server.Server(cors_allowed_origins=['*'])\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ORIGIN': 'foo',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'foo') in headers\n        assert ('Access-Control-Allow-Credentials', 'true') in headers\n\n    def test_connect_cors_headers_one_origin(self):\n        s = server.Server(cors_allowed_origins='a')\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ORIGIN': 'a',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'a') in headers\n        assert ('Access-Control-Allow-Credentials', 'true') in headers\n\n    def test_connect_cors_headers_one_origin_not_allowed(self):\n        s = server.Server(cors_allowed_origins='a')\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ORIGIN': 'b',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'b') not in headers\n        assert ('Access-Control-Allow-Origin', '*') not in headers\n\n    def test_connect_cors_headers_default_origin(self):\n        s = server.Server()\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'wsgi.url_scheme': 'http',\n            'HTTP_HOST': 'foo',\n            'HTTP_ORIGIN': 'http://foo',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'http://foo') in headers\n\n    def test_connect_cors_headers_default_origin_proxy_server(self):\n        s = server.Server()\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'wsgi.url_scheme': 'http',\n            'HTTP_HOST': 'foo',\n            'HTTP_ORIGIN': 'https://foo',\n            'HTTP_X_FORWARDED_PROTO': 'https, ftp',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'https://foo') in headers\n\n    def test_connect_cors_headers_default_origin_proxy_server2(self):\n        s = server.Server()\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'wsgi.url_scheme': 'http',\n            'HTTP_HOST': 'foo',\n            'HTTP_ORIGIN': 'https://bar',\n            'HTTP_X_FORWARDED_PROTO': 'https, ftp',\n            'HTTP_X_FORWARDED_HOST': 'bar , baz',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Origin', 'https://bar') in headers\n\n    def test_connect_cors_no_credentials(self):\n        s = server.Server(cors_credentials=False)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Credentials', 'true') not in headers\n\n    def test_cors_options(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'OPTIONS', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert (\n            'Access-Control-Allow-Methods',\n            'OPTIONS, GET, POST',\n        ) in headers\n\n    def test_cors_request_headers(self):\n        s = server.Server()\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ACCESS_CONTROL_REQUEST_HEADERS': 'Foo, Bar',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        assert ('Access-Control-Allow-Headers', 'Foo, Bar') in headers\n\n    def test_connect_cors_disabled(self):\n        s = server.Server(cors_allowed_origins=[])\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4',\n            'HTTP_ORIGIN': 'http://foo',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        headers = start_response.call_args[0][1]\n        for header in headers:\n            assert not header[0].startswith('Access-Control-')\n\n    def test_connect_cors_default_no_origin(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        headers = start_response.call_args[0][1]\n        for header in headers:\n            assert header[0] != 'Access-Control-Allow-Origin'\n\n    def test_connect_str_cors_all_no_origin(self):\n        s = server.Server(cors_allowed_origins='*')\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        headers = start_response.call_args[0][1]\n        for header in headers:\n            assert header[0] != 'Access-Control-Allow-Origin'\n\n    def test_connect_list_cors_all_no_origin(self):\n        s = server.Server(cors_allowed_origins=['*'])\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        headers = start_response.call_args[0][1]\n        for header in headers:\n            assert header[0] != 'Access-Control-Allow-Origin'\n\n    def test_connect_cors_disabled_no_origin(self):\n        s = server.Server(cors_allowed_origins=[])\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        headers = start_response.call_args[0][1]\n        for header in headers:\n            assert header[0] != 'Access-Control-Allow-Origin'\n\n    def test_connect_event(self):\n        s = server.Server()\n        s.generate_id = mock.MagicMock(return_value='123')\n        mock_event = mock.MagicMock(return_value=None)\n        s.on('connect')(mock_event)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        mock_event.assert_called_once_with('123', environ)\n        assert len(s.sockets) == 1\n\n    def test_connect_event_rejects(self):\n        s = server.Server()\n        s.generate_id = mock.MagicMock(return_value='123')\n        mock_event = mock.MagicMock(return_value=False)\n        s.on('connect')(mock_event)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        ret = s.handle_request(environ, start_response)\n        assert len(s.sockets) == 0\n        assert start_response.call_args[0][0] == '401 UNAUTHORIZED'\n        assert ret == [b'\"Unauthorized\"']\n\n    def test_connect_event_rejects_with_message(self):\n        s = server.Server()\n        s.generate_id = mock.MagicMock(return_value='123')\n        mock_event = mock.MagicMock(return_value='not allowed')\n        s.on('connect')(mock_event)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        ret = s.handle_request(environ, start_response)\n        assert len(s.sockets) == 0\n        assert start_response.call_args[0][0] == '401 UNAUTHORIZED'\n        assert ret == [b'\"not allowed\"']\n\n    def test_method_not_found(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'PUT', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '405 METHOD NOT FOUND'\n\n    def test_get_request_with_bad_sid(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4&sid=foo'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    def test_post_request_with_bad_sid(self):\n        s = server.Server()\n        environ = {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'EIO=4&sid=foo'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    def test_send(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        s.sockets['foo'] = mock_socket\n        s.send('foo', 'hello')\n        assert mock_socket.send.call_count == 1\n        assert mock_socket.send.call_args[0][0].packet_type == packet.MESSAGE\n        assert mock_socket.send.call_args[0][0].data == 'hello'\n\n    def test_send_unknown_socket(self):\n        s = server.Server()\n        # just ensure no exceptions are raised\n        s.send('foo', 'hello')\n\n    def test_get_request(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(\n            return_value=[packet.Packet(packet.MESSAGE, data='hello')]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4&sid=foo'}\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n        assert len(r) == 1\n        packets = payload.Payload(encoded_payload=r[0].decode('utf-8')).packets\n        assert len(packets) == 1\n        assert packets[0].packet_type == packet.MESSAGE\n\n    def test_get_request_custom_response(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(side_effect=['resp'])\n        s.sockets['foo'] = mock_socket\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4&sid=foo'}\n        start_response = mock.MagicMock()\n        assert s.handle_request(environ, start_response) == 'resp'\n\n    def test_get_request_closes_socket(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n\n        def mock_get_request(*args, **kwargs):\n            mock_socket.closed = True\n            return 'resp'\n\n        mock_socket.handle_get_request = mock_get_request\n        s.sockets['foo'] = mock_socket\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4&sid=foo'}\n        start_response = mock.MagicMock()\n        assert s.handle_request(environ, start_response) == 'resp'\n        assert 'foo' not in s.sockets\n\n    def test_get_request_error(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(\n            side_effect=[exceptions.QueueEmpty]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4&sid=foo'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n        assert len(s.sockets) == 0\n\n    def test_get_request_bad_websocket_transport(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        mock_socket.upgraded = False\n        s.sockets['foo'] = mock_socket\n        environ = {'REQUEST_METHOD': 'GET',\n                   'QUERY_STRING': 'EIO=4&transport=websocket&sid=foo'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    def test_get_request_bad_polling_transport(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        mock_socket.upgraded = True\n        s.sockets['foo'] = mock_socket\n        environ = {'REQUEST_METHOD': 'GET',\n                   'QUERY_STRING': 'EIO=4&transport=polling&sid=foo'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n\n    def test_post_request(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_post_request = mock.MagicMock()\n        s.sockets['foo'] = mock_socket\n        environ = {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'EIO=4&sid=foo'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '200 OK'\n\n    def test_post_request_error(self):\n        s = server.Server()\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_post_request = mock.MagicMock(\n            side_effect=[exceptions.EngineIOError]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'EIO=4&sid=foo'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n        assert 'foo' not in s.sockets\n\n    @staticmethod\n    def _gzip_decompress(b):\n        bytesio = io.BytesIO(b)\n        with gzip.GzipFile(fileobj=bytesio, mode='r') as gz:\n            return gz.read()\n\n    def test_gzip_compression(self):\n        s = server.Server(compression_threshold=0)\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(\n            return_value=[packet.Packet(packet.MESSAGE, data='hello')]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&sid=foo',\n            'HTTP_ACCEPT_ENCODING': 'gzip,deflate',\n        }\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        assert ('Content-Encoding', 'gzip') in start_response.call_args[0][1]\n        self._gzip_decompress(r[0])\n\n    def test_deflate_compression(self):\n        s = server.Server(compression_threshold=0)\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(\n            return_value=[packet.Packet(packet.MESSAGE, data='hello')]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&sid=foo',\n            'HTTP_ACCEPT_ENCODING': 'deflate;q=1,gzip',\n        }\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        assert ('Content-Encoding', 'deflate') in start_response.call_args[0][\n            1\n        ]\n        zlib.decompress(r[0])\n\n    def test_gzip_compression_threshold(self):\n        s = server.Server(compression_threshold=1000)\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(\n            return_value=[packet.Packet(packet.MESSAGE, data='hello')]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&sid=foo',\n            'HTTP_ACCEPT_ENCODING': 'gzip',\n        }\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        for header, value in start_response.call_args[0][1]:\n            assert header != 'Content-Encoding'\n        with pytest.raises(IOError):\n            self._gzip_decompress(r[0])\n\n    def test_compression_disabled(self):\n        s = server.Server(http_compression=False, compression_threshold=0)\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(\n            return_value=[packet.Packet(packet.MESSAGE, data='hello')]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&sid=foo',\n            'HTTP_ACCEPT_ENCODING': 'gzip',\n        }\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        for header, value in start_response.call_args[0][1]:\n            assert header != 'Content-Encoding'\n        with pytest.raises(IOError):\n            self._gzip_decompress(r[0])\n\n    def test_compression_unknown(self):\n        s = server.Server(compression_threshold=0)\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(\n            return_value=[packet.Packet(packet.MESSAGE, data='hello')]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&sid=foo',\n            'HTTP_ACCEPT_ENCODING': 'rar',\n        }\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        for header, value in start_response.call_args[0][1]:\n            assert header != 'Content-Encoding'\n        with pytest.raises(IOError):\n            self._gzip_decompress(r[0])\n\n    def test_compression_no_encoding(self):\n        s = server.Server(compression_threshold=0)\n        mock_socket = self._get_mock_socket()\n        mock_socket.handle_get_request = mock.MagicMock(\n            return_value=[packet.Packet(packet.MESSAGE, data='hello')]\n        )\n        s.sockets['foo'] = mock_socket\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'EIO=4&sid=foo',\n            'HTTP_ACCEPT_ENCODING': '',\n        }\n        start_response = mock.MagicMock()\n        r = s.handle_request(environ, start_response)\n        for header, value in start_response.call_args[0][1]:\n            assert header != 'Content-Encoding'\n        with pytest.raises(IOError):\n            self._gzip_decompress(r[0])\n\n    def test_cookie(self):\n        s = server.Server(cookie='sid')\n        s.generate_id = mock.MagicMock(return_value='123')\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert ('Set-Cookie', 'sid=123; path=/; SameSite=Lax') \\\n            in start_response.call_args[0][1]\n\n    def test_cookie_dict(self):\n        def get_path():\n            return '/a'\n\n        s = server.Server(cookie={\n            'name': 'test',\n            'path': get_path,\n            'SameSite': 'None',\n            'Secure': True,\n            'HttpOnly': True\n        })\n        s.generate_id = mock.MagicMock(return_value='123')\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert ('Set-Cookie', 'test=123; path=/a; SameSite=None; Secure; '\n                'HttpOnly') in start_response.call_args[0][1]\n\n    def test_no_cookie(self):\n        s = server.Server(cookie=None)\n        s.generate_id = mock.MagicMock(return_value='123')\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        for header, value in start_response.call_args[0][1]:\n            assert header != 'Set-Cookie'\n\n    def test_logger(self):\n        s = server.Server(logger=False)\n        assert s.logger.getEffectiveLevel() == logging.ERROR\n        s.logger.setLevel(logging.NOTSET)\n        s = server.Server(logger=True)\n        assert s.logger.getEffectiveLevel() == logging.INFO\n        s.logger.setLevel(logging.WARNING)\n        s = server.Server(logger=True)\n        assert s.logger.getEffectiveLevel() == logging.WARNING\n        s.logger.setLevel(logging.NOTSET)\n        my_logger = logging.Logger('foo')\n        s = server.Server(logger=my_logger)\n        assert s.logger == my_logger\n\n    def test_custom_json(self):\n        # Warning: this test cannot run in parallel with other tests, as it\n        # changes the JSON encoding/decoding functions\n\n        class CustomJSON:\n            @staticmethod\n            def dumps(*args, **kwargs):\n                return '*** encoded ***'\n\n            @staticmethod\n            def loads(*args, **kwargs):\n                return '+++ decoded +++'\n\n        server.Server(json=CustomJSON)\n        pkt = packet.Packet(packet.MESSAGE, data={'foo': 'bar'})\n        assert pkt.encode() == '4*** encoded ***'\n        pkt2 = packet.Packet(encoded_packet=pkt.encode())\n        assert pkt2.data == '+++ decoded +++'\n\n        # restore the default JSON module\n        packet.Packet.json = json\n\n    def test_background_tasks(self):\n        flag = {}\n\n        def bg_task():\n            flag['task'] = True\n\n        s = server.Server(async_mode='threading')\n        task = s.start_background_task(bg_task)\n        task.join()\n        assert 'task' in flag\n        assert flag['task']\n\n    def test_sleep(self):\n        s = server.Server()\n        t = time.time()\n        s.sleep(0.1)\n        assert time.time() - t > 0.1\n\n    def test_create_queue(self):\n        s = server.Server()\n        q = s.create_queue()\n        empty = s.get_queue_empty_exception()\n        with pytest.raises(empty):\n            q.get(timeout=0.01)\n\n    def test_create_event(self):\n        s = server.Server()\n        e = s.create_event()\n        assert not e.is_set()\n        e.set()\n        assert e.is_set()\n\n    def test_log_error_once(self):\n        s = server.Server(logger=mock.MagicMock())\n        s._log_error_once('foo', 'foo-key')\n        s._log_error_once('foo', 'foo-key')\n        s.logger.error.assert_called_with(\n            'foo (further occurrences of this error will be logged with '\n            'level INFO)')\n        s.logger.info.assert_called_with('foo')\n\n    def test_service_task_started(self):\n        s = server.Server(async_mode='threading', monitor_clients=True)\n        s._service_task = mock.MagicMock()\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        for _ in range(3):\n            if s._service_task.call_count > 0:\n                break\n            time.sleep(0.05)\n        s._service_task.assert_called_once_with()\n\n    def test_shutdown(self):\n        s = server.Server(async_mode='threading', monitor_clients=True)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'}\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert s.service_task_handle is not None\n        s.shutdown()\n        assert s.service_task_handle is None\n\n    def test_transports_invalid(self):\n        with pytest.raises(ValueError):\n            server.Server(transports='invalid')\n        with pytest.raises(ValueError):\n            server.Server(transports=['invalid', 'foo'])\n\n    def test_transports_disallowed(self):\n        s = server.Server(transports='websocket')\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'transport=polling',\n        }\n        start_response = mock.MagicMock()\n        s.handle_request(environ, start_response)\n        assert start_response.call_args[0][0] == '400 BAD REQUEST'\n"
  },
  {
    "path": "tests/common/test_socket.py",
    "content": "import io\nimport time\nfrom unittest import mock\n\nimport pytest\n\nfrom engineio import exceptions\nfrom engineio import packet\nfrom engineio import payload\nfrom engineio import socket\n\n\nclass TestSocket:\n    def setup_method(self):\n        self.bg_tasks = []\n\n    def _get_mock_server(self):\n        mock_server = mock.Mock()\n        mock_server.ping_timeout = 0.2\n        mock_server.ping_interval = 0.2\n        mock_server.ping_interval_grace_period = 0.001\n        mock_server.async_handlers = True\n        mock_server.max_http_buffer_size = 128\n\n        try:\n            import queue\n        except ImportError:\n            import Queue as queue\n        import threading\n\n        mock_server._async = {\n            'threading': threading.Thread,\n            'queue': queue.Queue,\n            'websocket': None,\n        }\n\n        def bg_task(target, *args, **kwargs):\n            th = threading.Thread(target=target, args=args, kwargs=kwargs)\n            self.bg_tasks.append(th)\n            th.start()\n            return th\n\n        def create_queue(*args, **kwargs):\n            return queue.Queue(*args, **kwargs)\n\n        mock_server.start_background_task = bg_task\n        mock_server.create_queue = create_queue\n        mock_server.get_queue_empty_exception.return_value = queue.Empty\n        return mock_server\n\n    def _join_bg_tasks(self):\n        for task in self.bg_tasks:\n            task.join()\n\n    def test_create(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        assert s.server == mock_server\n        assert s.sid == 'sid'\n        assert not s.upgraded\n        assert not s.closed\n        assert hasattr(s.queue, 'get')\n        assert hasattr(s.queue, 'put')\n        assert hasattr(s.queue, 'task_done')\n        assert hasattr(s.queue, 'join')\n\n    def test_empty_poll(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        with pytest.raises(exceptions.QueueEmpty):\n            s.poll()\n\n    def test_poll(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        pkt1 = packet.Packet(packet.MESSAGE, data='hello')\n        pkt2 = packet.Packet(packet.MESSAGE, data='bye')\n        s.send(pkt1)\n        s.send(pkt2)\n        assert s.poll() == [pkt1, pkt2]\n\n    def test_poll_none(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.queue.put(None)\n        assert s.poll() == []\n\n    def test_poll_none_after_packet(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        pkt = packet.Packet(packet.MESSAGE, data='hello')\n        s.send(pkt)\n        s.queue.put(None)\n        assert s.poll() == [pkt]\n        assert s.poll() == []\n\n    def test_schedule_ping(self):\n        mock_server = self._get_mock_server()\n        mock_server.ping_interval = 0.01\n        s = socket.Socket(mock_server, 'sid')\n        s.send = mock.MagicMock()\n        s.schedule_ping()\n        time.sleep(0.05)\n        assert s.last_ping is not None\n        assert s.send.call_args_list[0][0][0].encode() == '2'\n\n    def test_schedule_ping_closed_socket(self):\n        mock_server = self._get_mock_server()\n        mock_server.ping_interval = 0.01\n        s = socket.Socket(mock_server, 'sid')\n        s.send = mock.MagicMock()\n        s.closed = True\n        s.schedule_ping()\n        time.sleep(0.05)\n        assert s.last_ping is None\n        s.send.assert_not_called()\n\n    def test_pong(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.schedule_ping = mock.MagicMock()\n        s.receive(packet.Packet(packet.PONG))\n        s.schedule_ping.assert_called_once_with()\n\n    def test_message_async_handler(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.receive(packet.Packet(packet.MESSAGE, data='foo'))\n        mock_server._trigger_event.assert_called_once_with(\n            'message', 'sid', 'foo', run_async=True\n        )\n\n    def test_message_sync_handler(self):\n        mock_server = self._get_mock_server()\n        mock_server.async_handlers = False\n        s = socket.Socket(mock_server, 'sid')\n        s.receive(packet.Packet(packet.MESSAGE, data='foo'))\n        mock_server._trigger_event.assert_called_once_with(\n            'message', 'sid', 'foo', run_async=False\n        )\n\n    def test_invalid_packet(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        with pytest.raises(exceptions.UnknownPacketError):\n            s.receive(packet.Packet(packet.OPEN))\n\n    def test_timeout(self):\n        mock_server = self._get_mock_server()\n        mock_server.ping_interval = 6\n        mock_server.ping_interval_grace_period = 2\n        s = socket.Socket(mock_server, 'sid')\n        s.last_ping = time.time() - 9\n        s.close = mock.MagicMock()\n        s.send('packet')\n        s.close.assert_called_once_with(wait=False, abort=False,\n                                        reason=mock_server.reason.PING_TIMEOUT)\n\n    def test_polling_read(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'foo')\n        pkt1 = packet.Packet(packet.MESSAGE, data='hello')\n        pkt2 = packet.Packet(packet.MESSAGE, data='bye')\n        s.send(pkt1)\n        s.send(pkt2)\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        start_response = mock.MagicMock()\n        packets = s.handle_get_request(environ, start_response)\n        assert packets == [pkt1, pkt2]\n\n    def test_polling_read_error(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'foo')\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'}\n        start_response = mock.MagicMock()\n        with pytest.raises(exceptions.QueueEmpty):\n            s.handle_get_request(environ, start_response)\n\n    def test_polling_write(self):\n        mock_server = self._get_mock_server()\n        mock_server.max_http_buffer_size = 1000\n        pkt1 = packet.Packet(packet.MESSAGE, data='hello')\n        pkt2 = packet.Packet(packet.MESSAGE, data='bye')\n        p = payload.Payload(packets=[pkt1, pkt2]).encode().encode('utf-8')\n        s = socket.Socket(mock_server, 'foo')\n        s.receive = mock.MagicMock()\n        environ = {\n            'REQUEST_METHOD': 'POST',\n            'QUERY_STRING': 'sid=foo',\n            'CONTENT_LENGTH': len(p),\n            'wsgi.input': io.BytesIO(p),\n        }\n        s.handle_post_request(environ)\n        assert s.receive.call_count == 2\n\n    def test_polling_write_too_large(self):\n        mock_server = self._get_mock_server()\n        pkt1 = packet.Packet(packet.MESSAGE, data='hello')\n        pkt2 = packet.Packet(packet.MESSAGE, data='bye')\n        p = payload.Payload(packets=[pkt1, pkt2]).encode().encode('utf-8')\n        mock_server.max_http_buffer_size = len(p) - 1\n        s = socket.Socket(mock_server, 'foo')\n        s.receive = mock.MagicMock()\n        environ = {\n            'REQUEST_METHOD': 'POST',\n            'QUERY_STRING': 'sid=foo',\n            'CONTENT_LENGTH': len(p),\n            'wsgi.input': io.BytesIO(p),\n        }\n        with pytest.raises(exceptions.ContentTooLongError):\n            s.handle_post_request(environ)\n\n    def test_upgrade_handshake(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'foo')\n        s._upgrade_websocket = mock.MagicMock()\n        environ = {\n            'REQUEST_METHOD': 'GET',\n            'QUERY_STRING': 'sid=foo',\n            'HTTP_CONNECTION': 'Foo,Upgrade,Bar',\n            'HTTP_UPGRADE': 'websocket',\n        }\n        start_response = mock.MagicMock()\n        s.handle_get_request(environ, start_response)\n        s._upgrade_websocket.assert_called_once_with(environ, start_response)\n\n    def test_upgrade(self):\n        mock_server = self._get_mock_server()\n        mock_server._async['websocket'] = mock.MagicMock()\n        mock_ws = mock.MagicMock()\n        mock_server._async['websocket'].return_value = mock_ws\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        environ = \"foo\"\n        start_response = \"bar\"\n        s._upgrade_websocket(environ, start_response)\n        mock_server._async['websocket'].assert_called_once_with(\n            s._websocket_handler, mock_server\n        )\n        mock_ws.assert_called_once_with(environ, start_response)\n\n    def test_upgrade_twice(self):\n        mock_server = self._get_mock_server()\n        mock_server._async['websocket'] = mock.MagicMock()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        s.upgraded = True\n        environ = \"foo\"\n        start_response = \"bar\"\n        with pytest.raises(IOError):\n            s._upgrade_websocket(environ, start_response)\n\n    def test_upgrade_packet(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        s.receive(packet.Packet(packet.UPGRADE))\n        r = s.poll()\n        assert len(r) == 1\n        assert r[0].encode() == packet.Packet(packet.NOOP).encode()\n\n    def test_upgrade_no_probe(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        ws = mock.MagicMock()\n        ws.wait.return_value = packet.Packet(packet.NOOP).encode()\n        s._websocket_handler(ws)\n        assert not s.upgraded\n\n    def test_upgrade_no_upgrade_packet(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.MagicMock(return_value=None)\n        ws = mock.MagicMock()\n        probe = 'probe'\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.NOOP).encode(),\n        ]\n        s._websocket_handler(ws)\n        ws.send.assert_called_once_with(\n            packet.Packet(packet.PONG, data=probe).encode()\n        )\n        assert s.queue.get().packet_type == packet.NOOP\n        assert not s.upgraded\n\n    def test_close_packet(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        s.close = mock.MagicMock()\n        s.receive(packet.Packet(packet.CLOSE))\n        s.close.assert_called_once_with(\n            wait=False, abort=True,\n            reason=mock_server.reason.CLIENT_DISCONNECT)\n\n    def test_invalid_packet_type(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        pkt = packet.Packet(packet_type=99)\n        with pytest.raises(exceptions.UnknownPacketError):\n            s.receive(pkt)\n\n    def test_upgrade_not_supported(self):\n        mock_server = self._get_mock_server()\n        mock_server._async['websocket'] = None\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        environ = \"foo\"\n        start_response = \"bar\"\n        s._upgrade_websocket(environ, start_response)\n        mock_server._bad_request.assert_called_once_with()\n\n    def test_websocket_read_write(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = False\n        s.queue.join = mock.MagicMock(return_value=None)\n        foo = 'foo'\n        bar = 'bar'\n        s.poll = mock.MagicMock(\n            side_effect=[\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                exceptions.QueueEmpty,\n            ]\n        )\n        ws = mock.MagicMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.MESSAGE, data=foo).encode(),\n            None,\n        ]\n        s._websocket_handler(ws)\n        self._join_bg_tasks()\n        assert s.connected\n        assert s.upgraded\n        assert mock_server._trigger_event.call_count == 2\n        mock_server._trigger_event.assert_has_calls(\n            [\n                mock.call('message', 'sid', 'foo', run_async=True),\n                mock.call('disconnect', 'sid',\n                          mock_server.reason.TRANSPORT_CLOSE,\n                          run_async=False)\n            ]\n        )\n        ws.send.assert_called_with('4bar')\n\n    def test_websocket_upgrade_read_write(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.MagicMock(return_value=None)\n        foo = 'foo'\n        bar = 'bar'\n        probe = 'probe'\n        s.poll = mock.MagicMock(\n            side_effect=[\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                exceptions.QueueEmpty,\n            ]\n        )\n        ws = mock.MagicMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.UPGRADE).encode(),\n            packet.Packet(packet.MESSAGE, data=foo).encode(),\n            None,\n        ]\n        s._websocket_handler(ws)\n        self._join_bg_tasks()\n        assert s.upgraded\n        assert mock_server._trigger_event.call_count == 2\n        mock_server._trigger_event.assert_has_calls(\n            [\n                mock.call('message', 'sid', 'foo', run_async=True),\n                mock.call('disconnect', 'sid',\n                          mock_server.reason.TRANSPORT_CLOSE,\n                          run_async=False)\n            ]\n        )\n        ws.send.assert_called_with('4bar')\n\n    def test_websocket_upgrade_with_payload(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.MagicMock(return_value=None)\n        probe = 'probe'\n        ws = mock.MagicMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.UPGRADE, data='2').encode(),\n        ]\n        s._websocket_handler(ws)\n        self._join_bg_tasks()\n        assert s.upgraded\n\n    def test_websocket_upgrade_with_backlog(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.MagicMock(return_value=None)\n        probe = 'probe'\n        foo = 'foo'\n        ws = mock.MagicMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.UPGRADE, data='2').encode(),\n        ]\n        s.upgrading = True\n        s.send(packet.Packet(packet.MESSAGE, data=foo))\n        environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=sid'}\n        start_response = mock.MagicMock()\n        packets = s.handle_get_request(environ, start_response)\n        assert len(packets) == 1\n        assert packets[0].encode() == '6'\n        packets = s.poll()\n        assert len(packets) == 1\n        assert packets[0].encode() == '4foo'\n\n        s._websocket_handler(ws)\n        self._join_bg_tasks()\n        assert s.upgraded\n        assert not s.upgrading\n        packets = s.handle_get_request(environ, start_response)\n        assert len(packets) == 1\n        assert packets[0].encode() == '6'\n\n    def test_websocket_read_write_wait_fail(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = False\n        s.queue.join = mock.MagicMock(return_value=None)\n        foo = 'foo'\n        bar = 'bar'\n        s.poll = mock.MagicMock(\n            side_effect=[\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                exceptions.QueueEmpty,\n            ]\n        )\n        ws = mock.MagicMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.MESSAGE, data=foo).encode(),\n            RuntimeError,\n        ]\n        ws.send.side_effect = [None, RuntimeError]\n        s._websocket_handler(ws)\n        self._join_bg_tasks()\n        assert s.closed\n\n    def test_websocket_upgrade_with_large_packet(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = True\n        s.queue.join = mock.MagicMock(return_value=None)\n        probe = 'probe'\n        ws = mock.MagicMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.PING, data=probe).encode(),\n            packet.Packet(packet.UPGRADE, data='2' * 128).encode(),\n        ]\n        with pytest.raises(ValueError):\n            s._websocket_handler(ws)\n        self._join_bg_tasks()\n        assert not s.upgraded\n\n    def test_websocket_ignore_invalid_packet(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.connected = False\n        s.queue.join = mock.MagicMock(return_value=None)\n        foo = 'foo'\n        bar = 'bar'\n        s.poll = mock.MagicMock(\n            side_effect=[\n                [packet.Packet(packet.MESSAGE, data=bar)],\n                exceptions.QueueEmpty,\n            ]\n        )\n        ws = mock.MagicMock()\n        ws.wait.side_effect = [\n            packet.Packet(packet.OPEN).encode(),\n            packet.Packet(packet.MESSAGE, data=foo).encode(),\n            None,\n        ]\n        s._websocket_handler(ws)\n        self._join_bg_tasks()\n        assert s.connected\n        assert mock_server._trigger_event.call_count == 2\n        mock_server._trigger_event.assert_has_calls(\n            [\n                mock.call('message', 'sid', foo, run_async=True),\n                mock.call('disconnect', 'sid',\n                          mock_server.reason.TRANSPORT_CLOSE,\n                          run_async=False)\n            ]\n        )\n        ws.send.assert_called_with('4bar')\n\n    def test_send_after_close(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.close(wait=False)\n        with pytest.raises(exceptions.SocketIsClosedError):\n            s.send(packet.Packet(packet.NOOP))\n\n    def test_close_after_close(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.close(wait=False)\n        assert s.closed\n        assert mock_server._trigger_event.call_count == 1\n        mock_server._trigger_event.assert_called_once_with(\n            'disconnect', 'sid', mock_server.reason.SERVER_DISCONNECT,\n            run_async=False\n        )\n        s.close()\n        assert mock_server._trigger_event.call_count == 1\n\n    def test_close_and_wait(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.queue = mock.MagicMock()\n        s.close(wait=True)\n        s.queue.join.assert_called_once_with()\n\n    def test_close_without_wait(self):\n        mock_server = self._get_mock_server()\n        s = socket.Socket(mock_server, 'sid')\n        s.queue = mock.MagicMock()\n        s.close(wait=False)\n        assert s.queue.join.call_count == 0\n"
  },
  {
    "path": "tests/performance/README.md",
    "content": "Performance\n===========\n\nThis directory contains several scripts and tools to test the performance of\nthe project.\n"
  },
  {
    "path": "tests/performance/binary_b64_packet.py",
    "content": "import time\nfrom engineio import packet\n\n\ndef test():\n    p = packet.Packet(packet.MESSAGE, b'hello world')\n    start = time.time()\n    count = 0\n    while True:\n        p = packet.Packet(encoded_packet=p.encode(b64=True))\n        count += 1\n        if time.time() - start >= 5:\n            break\n    return count\n\n\nif __name__ == '__main__':\n    count = test()\n    print('binary_b64_packet:', count, 'packets processed.')\n"
  },
  {
    "path": "tests/performance/binary_packet.py",
    "content": "import time\nfrom engineio import packet\n\n\ndef test():\n    p = packet.Packet(packet.MESSAGE, b'hello world')\n    start = time.time()\n    count = 0\n    while True:\n        p = packet.Packet(encoded_packet=p.encode())\n        count += 1\n        if time.time() - start >= 5:\n            break\n    return count\n\n\nif __name__ == '__main__':\n    count = test()\n    print('binary_packet:', count, 'packets processed.')\n"
  },
  {
    "path": "tests/performance/json_packet.py",
    "content": "import time\nfrom engineio import packet\n\n\ndef test():\n    p = packet.Packet(packet.MESSAGE, {'hello': 'world'})\n    start = time.time()\n    count = 0\n    while True:\n        p = packet.Packet(encoded_packet=p.encode())\n        count += 1\n        if time.time() - start >= 5:\n            break\n    return count\n\n\nif __name__ == '__main__':\n    count = test()\n    print('json_packet:', count, 'packets processed.')\n"
  },
  {
    "path": "tests/performance/payload.py",
    "content": "import time\nfrom engineio import packet, payload\n\n\ndef test():\n    p = payload.Payload(\n        packets=[packet.Packet(packet.MESSAGE, b'hello world')] * 10)\n    start = time.time()\n    count = 0\n    while True:\n        p = payload.Payload(encoded_payload=p.encode())\n        count += 1\n        if time.time() - start >= 5:\n            break\n    return count\n\n\nif __name__ == '__main__':\n    count = test()\n    print('payload:', count, 'payloads processed.')\n"
  },
  {
    "path": "tests/performance/run.sh",
    "content": "#!/bin/bash\npython text_packet.py\npython binary_packet.py\npython binary_b64_packet.py\npython json_packet.py\npython payload.py\npython server_receive.py\n"
  },
  {
    "path": "tests/performance/server_receive.py",
    "content": "import io\nimport sys\nimport time\nimport engineio\n\n\ndef test(eio_version, payload):\n    s = engineio.Server()\n    start = time.time()\n    count = 0\n    s.handle_request({\n        'REQUEST_METHOD': 'GET',\n        'QUERY_STRING': eio_version,\n    }, lambda s, h: None)\n    sid = list(s.sockets.keys())[0]\n    while True:\n        environ = {\n            'REQUEST_METHOD': 'POST',\n            'QUERY_STRING': eio_version + '&sid=' + sid,\n            'CONTENT_LENGTH': '6',\n            'wsgi.input': io.BytesIO(payload)\n        }\n        s.handle_request(environ, lambda s, h: None)\n        count += 1\n        if time.time() - start >= 5:\n            break\n    return count\n\n\nif __name__ == '__main__':\n    eio_version = 'EIO=4'\n    payload = b'4hello'\n    if len(sys.argv) > 1 and sys.argv[1] == '3':\n        eio_version = 'EIO=3'\n        payload = b'\\x00\\x06\\xff4hello'\n    count = test(eio_version, payload)\n    print('server_receive:', count, 'packets received.')\n"
  },
  {
    "path": "tests/performance/text_packet.py",
    "content": "import time\nfrom engineio import packet\n\n\ndef test():\n    p = packet.Packet(packet.MESSAGE, 'hello world')\n    start = time.time()\n    count = 0\n    while True:\n        p = packet.Packet(encoded_packet=p.encode())\n        count += 1\n        if time.time() - start >= 5:\n            break\n    return count\n\n\nif __name__ == '__main__':\n    count = test()\n    print('text_packet:', count, 'packets processed.')\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nenvlist=flake8,py310,py311,py312,py313,py314,pypy3,docs\nskip_missing_interpreters=True\n\n[gh-actions]\npython =\n    3.10: py310\n    3.11: py311\n    3.12: py312\n    3.13: py313\n    3.14: py314\n    pypy-3: pypy3\n\n[testenv]\ncommands=\n    pip install -e .\n    pytest -p no:logging --cov=engineio --cov-branch --cov-report=term-missing --cov-report=xml\ndeps=\n    pytest\n    pytest-cov\n    pytest-asyncio\n    aiohttp\n    tornado\n    requests\n    websocket-client\n\n[testenv:pypy3]\n\n[testenv:flake8]\ndeps=\n    flake8\ncommands=\n    flake8 --exclude=\".*\" --ignore=W503,E402,E722 src/engineio tests examples\n\n[testenv:docs]\nchangedir=docs\ndeps=\n    sphinx\n    furo\nallowlist_externals=\n    make\ncommands=\n    make html\n"
  }
]