{"id":15415835,"url":"https://github.com/davidje13/echochamber","last_synced_at":"2026-04-19T05:31:48.527Z","repository":{"id":57148443,"uuid":"157918770","full_name":"davidje13/EchoChamber","owner":"davidje13","description":"WebSocket echo chamber server","archived":false,"fork":false,"pushed_at":"2020-08-30T14:17:09.000Z","size":29,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-11T00:39:14.556Z","etag":null,"topics":["nodejs","websocket"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidje13.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-16T20:37:41.000Z","updated_at":"2020-12-18T19:38:16.000Z","dependencies_parsed_at":"2022-09-06T19:31:07.797Z","dependency_job_id":null,"html_url":"https://github.com/davidje13/EchoChamber","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/davidje13/EchoChamber","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FEchoChamber","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FEchoChamber/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FEchoChamber/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FEchoChamber/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidje13","download_url":"https://codeload.github.com/davidje13/EchoChamber/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FEchoChamber/sbom","scorecard":{"id":326899,"data":{"date":"2025-08-11","repo":{"name":"github.com/davidje13/EchoChamber","commit":"1b7bd2387b80c8ef461e420a44db6d34e2baa005"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/14 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-18T02:40:35.473Z","repository_id":57148443,"created_at":"2025-08-18T02:40:35.473Z","updated_at":"2025-08-18T02:40:35.473Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279015056,"owners_count":26085643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nodejs","websocket"],"created_at":"2024-10-01T17:09:55.050Z","updated_at":"2025-10-13T12:41:07.901Z","avatar_url":"https://github.com/davidje13.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WebSocket Echo Chamber\n\nLow-overhead implementation of a WebSocket communication hub.\n\nChambers are identified by URL. All connections to the same chamber\nwill hear each other's messages reflected back and be notified when\nconnections are made and closed.\n\n## Usage\n\n```sh\nnpm start [\u003cport\u003e [\u003cdomain\u003e]]\n```\n\nIf `domain` is specified, the `Origin` header will be checked against\nit. It should be a comma-separated list of permitted domains.\n\nExample allowing local access during development:\n\n```sh\nnpm start 8080 file://\n```\n\nYou can include this in another project using npm:\n\n```sh\nnpm install --save websocket-echo-chamber\n```\n\nOnce added, you can start the server from the command line:\n\n```sh\necho-chamber 8080 file://\n```\n\nOr create your own server programmatically:\n\n```javascript\nconst {EchoChamberHalls, WebSocketServer} = require('websocket-echo-chamber');\n\nconst domains = [];\n\n// Max memory usage is approximately (bytes):\n// (MAX_QUEUE_DATA + HEADERS_MAX_LENGTH) * CHAMBER_MAX_CONNECTIONS * MAX_CHAMBERS\n// + some overhead from data structures\n// Memory usage will typically be much lower (unless explicitly attacked)\n// The values below result in ~0.25GB peak memory usage\n\nconst echoChamber = new EchoChamberHalls('/', domains, {\n\tMAX_QUEUE_ITEMS: 1024,\n\tMAX_QUEUE_DATA: 16 * 1024,\n\tHEADERS_MAX_LENGTH: 1024,\n\tCHAMBER_MAX_CONNECTIONS: 64,\n\tMAX_CHAMBERS: 256,\n});\n\n// 2-person echo chambers do not require a queue, so we can support more of them\nconst p2EchoChamber = new EchoChamberHalls('/p2/', domains, {\n\tMAX_QUEUE_ITEMS: 0,\n\tMAX_QUEUE_DATA: 0,\n\tHEADERS_MAX_LENGTH: 1024,\n\tCHAMBER_MAX_CONNECTIONS: 2,\n\tMAX_CHAMBERS: 512,\n});\n\nnew WebSocketServer()\n\t.addHandler(p2EchoChamber)\n\t.addHandler(echoChamber)\n\t.listen(8080, '127.0.0.1')\n\t.then((server) =\u003e server.printListeningInfo(process.stdout));\n```\n\n## Protocol\n\nConnect to a chamber with:\n\n```javascript\nsocket = new WebSocket(baseURL + chamberName, ['echo']);\n```\n\nAll received messages will begin with colon-separated metadata. Each\nitem begins with a letter which denotes its type, followed by\ntype-specific data. The metadata types are:\n\n* `I\u003cn\u003e`: received when first connecting; gives the unique ID for this\n  connection\n* `H\u003cn\u003e`: \"hi\" received when a connection is made\n* `B\u003cn\u003e`: \"bye\" received when a connection is closed or lost\n* `F\u003cn\u003e`: \"from\" the message which follows came from the noted\n  connection\n* `X`: \"truncated\" the preceeding message was truncated\n\nAfter all metadata, there may be a newline followed by an arbitrary\nmessage. If there is no metadata, the message will start with a\nnewline.\n\nAll sent messages will have metadata attached and be distributed to all\nother connections (excluding the one which sent the data).\n\nUser IDs are currently numeric, but may change to UUIDs or any\nalphanumeric format in the future.\n\nSee the sources in `test-client` for an example.\n\n### Example server-to-client messages:\n\n#### Begin connection to new room\n\nNew connection is assigned ID \"100\"\n\n```\nI100\n```\n\n#### Begin connection to existing room\n\nRoom already contains \"3\" and \"22\", new connection is assigned ID \"29\"\n\n```\nI29:H3:H22\n```\n\n#### Message received\n\nMessage sent from connection \"19\"\n\n```\nF19\nMessage here\n(may contain extra newlines)\n```\n\n#### Partial message received\n\nMessage sent from connection \"22\" but connection is lost before all\ndata is uploaded, or another data stream forced this one to close\n\n```\nF22\nPartial messa\n```\n\n```\nX\n```\n\n(the first message appears to complete normally, but is immediately\nfollowed by a header-only message showing the error - `X` = previous\nmessage truncated)\n\n### Example client-to-server messages:\n\n#### Send message to all connections except self\n\n```\n\nMessage here\n```\n\n#### Send message to any arbitrary connection except self\n\n(will favour long-lived connections which are currently idle)\n\n```\nT*\nMessage here\n```\n\n#### Send message to all connections including self\n\n```\nT**\nMessage here\n```\n\n#### Send message to specific connection(s) (can include self)\n\nSend to connection \"22\" and \"18\"\n\n```\nT22,18\nMessage here\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Fechochamber","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidje13%2Fechochamber","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Fechochamber/lists"}