Initial updates
This commit is contained in:
191
BENNC_PROTOCOL_SPEC.md
Normal file
191
BENNC_PROTOCOL_SPEC.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# BENNC Protocol Implementation Guide
|
||||
|
||||
**BENNCv1** (Butlersaurus Ephemeral No NONCEnse Chat) - Complete implementation documentation for a binary pub/sub messaging protocol with encryption and compression.
|
||||
|
||||
## Quick Implementation Checklist
|
||||
|
||||
1. **Connect** to server (TCP or WebSocket)
|
||||
2. **Subscribe** to message types you want to receive
|
||||
3. **Encrypt** data with Romulus-M (except subscribe/unsubscribe)
|
||||
4. **Send keepalive** every 30 seconds when idle
|
||||
5. **Handle** incoming messages and sender IDs
|
||||
|
||||
## Connection Endpoints
|
||||
|
||||
| Protocol | Endpoint |
|
||||
|----------|----------|
|
||||
| TCP | `chat.3t.network:10009` |
|
||||
| WebSocket (TLS) | `wss://chat.3t.network:443/BENNC` |
|
||||
| WebSocket | `ws://chat.3t.network:80/BENNC` |
|
||||
|
||||
## Core Requirements
|
||||
|
||||
- **Encoding**: Big-endian integers, UTF-8 strings
|
||||
- **Encryption**: Romulus-M with 16-byte nonce + message type as additional data (big-endian uint16)
|
||||
- **Compression**: ZSTD (when specified per message type)
|
||||
- **Max Data Size**: 1000 bytes per message (including nonce for encrypted messages)
|
||||
- **Keepalive**: Send every 30 seconds when idle
|
||||
- **Reserved IDs**: 0xFFFFFF00-0xFFFFFFFF for client internal use (256 IDs for local messages, system notifications, etc.)
|
||||
|
||||
## Message Structure
|
||||
|
||||
**Client → Server:**
|
||||
```
|
||||
┌─────────────┬─────────────┬─────────────────────────┐
|
||||
│ Message Type│ Length │ Data │
|
||||
│ (2 bytes) │ (2 bytes) │ (0-1000 bytes) │
|
||||
└─────────────┴─────────────┴─────────────────────────┘
|
||||
```
|
||||
|
||||
**Server → Client:**
|
||||
```
|
||||
┌─────────────┬─────────────┬─────────────┬─────────────────────┐
|
||||
│ Message Type│ Sender ID │ Length │ Data │
|
||||
│ (2 bytes) │ (4 bytes) │ (2 bytes) │ (0-1000 bytes) │
|
||||
└─────────────┴─────────────┴─────────────┴─────────────────────┘
|
||||
```
|
||||
|
||||
*Sender ID is randomly generated per connection to identify message source.*
|
||||
|
||||
## Encryption Implementation
|
||||
|
||||
**For encrypted messages (types 0x0001, 0x0002, 0x0003, 0x0006, 0x0007):**
|
||||
|
||||
1. Generate random 16-byte nonce
|
||||
2. Prepare additional data: message type as big-endian uint16
|
||||
3. Encrypt plaintext using Romulus-M AEAD
|
||||
4. Prepend nonce to ciphertext
|
||||
5. Total data = nonce (16 bytes) + ciphertext ≤ 1000 bytes
|
||||
|
||||
## Compression Implementation
|
||||
|
||||
- **Algorithm**: ZSTD (Zstandard) at default compression level
|
||||
- **Application**: Per message type (all messages of type or none)
|
||||
- **Order**: Compression applied **before** encryption
|
||||
- **Scope**: Only the data portion, headers remain uncompressed
|
||||
- **Currently used by**: Advanced Text Messages (0x0006, 0x0007)
|
||||
|
||||
## Message Types Reference
|
||||
|
||||
| ID | Name | Subscribable | Encrypted | Compressed | Purpose |
|
||||
|----|------|--------------|-----------|------------|---------|
|
||||
| 0x0000 | Subscribe | ❌ | ❌ | ❌ | Subscribe to message type |
|
||||
| 0x0001 | Basic Message | ✅ | ✅ | ❌ | Chat messages |
|
||||
| 0x0002 | Request User Data | ✅ | ✅ | ❌ | Request user info |
|
||||
| 0x0003 | User Data Response | ✅ | ✅ | ❌ | Respond with user info |
|
||||
| 0x0005 | Keepalive | ❌ | ❌ | ❌ | Prevent connection timeout |
|
||||
| 0x0006 | Advanced Text | ✅ | ✅ | ✅ | Long/rich text messages |
|
||||
| 0x0007 | Edit Advanced Text | ✅ | ✅ | ✅ | Edit/delete advanced text |
|
||||
| 0xFFFF | Unsubscribe | ❌ | ❌ | ❌ | Unsubscribe from message type |
|
||||
|
||||
---
|
||||
|
||||
## Message Type Specifications
|
||||
|
||||
### Subscribe (0x0000)
|
||||
Subscribe to receive messages of specified type. Must resubscribe after disconnect.
|
||||
|
||||
**Data:** Message type to subscribe to (2 bytes, big-endian)
|
||||
|
||||
---
|
||||
|
||||
### Basic Message (0x0001)
|
||||
UTF-8 chat messages. 16-byte nonce + encrypted data ≤ 1000 bytes total.
|
||||
|
||||
**Data:** Encrypted UTF-8 string
|
||||
|
||||
---
|
||||
|
||||
### Request User Data (0x0002)
|
||||
Request user information from all users. Clients should respond with User Data Response (0x0003).
|
||||
|
||||
**Data Structure:**
|
||||
- Username length (2 bytes, big-endian)
|
||||
- Username (up to 32 bytes, UTF-8)
|
||||
- Color RGB (3 bytes: R, G, B values)
|
||||
- Client identifier length (2 bytes, big-endian)
|
||||
- Client identifier (up to 32 bytes, UTF-8)
|
||||
|
||||
---
|
||||
|
||||
### User Data Response (0x0003)
|
||||
Send user information in response to Request User Data (0x0002).
|
||||
|
||||
**Data Structure:** Same as Request User Data
|
||||
- Username length (2 bytes, big-endian)
|
||||
- Username (up to 32 bytes, UTF-8)
|
||||
- Color RGB (3 bytes: R, G, B values)
|
||||
- Client identifier length (2 bytes, big-endian)
|
||||
- Client identifier (up to 32 bytes, UTF-8)
|
||||
|
||||
---
|
||||
|
||||
### Keepalive (0x0005)
|
||||
Prevent connection timeout when idle. Send every 30 seconds when no other traffic. Not forwarded to other clients and cannot be subscribed to.
|
||||
|
||||
**Data:** None - empty message
|
||||
|
||||
---
|
||||
|
||||
### Unsubscribe (0xFFFF)
|
||||
Stop receiving messages of specified type.
|
||||
|
||||
**Data:** Message type to unsubscribe from (2 bytes, big-endian)
|
||||
|
||||
---
|
||||
|
||||
### Advanced Text (0x0006)
|
||||
Multi-packet messages for long text with markdown formatting and ZSTD compression.
|
||||
|
||||
**Implementation Notes:**
|
||||
- Text is compressed **before** splitting into packets
|
||||
- Header is not compressed
|
||||
- Packets may arrive out of order - use packet numbers to reconstruct
|
||||
- Message ID identifies the complete message, not individual packets
|
||||
- Warn users before displaying very large messages
|
||||
|
||||
**Data Structure:**
|
||||
- Message ID (4 bytes, big-endian)
|
||||
- Packet number (2 bytes, big-endian, 0-indexed)
|
||||
- Final packet number (2 bytes, big-endian, 0-indexed)
|
||||
- Compressed markdown text (remaining bytes, ZSTD)
|
||||
|
||||
### Edit Advanced Text (0x0007)
|
||||
Edit or delete existing Advanced Text messages. Use same Message ID to replace existing message. Empty compressed text deletes the message. Client replaces original when final packet received.
|
||||
|
||||
**Data Structure:** Same as Advanced Text (0x0006)
|
||||
|
||||
---
|
||||
|
||||
## Implementation Guidelines
|
||||
|
||||
### Validation Requirements
|
||||
- All length fields must not exceed their specified maximums
|
||||
- Username/Client ID lengths must match actual string lengths
|
||||
- Message data must not exceed 1000 bytes (including nonce)
|
||||
- Packet numbers must be sequential and within final packet range
|
||||
|
||||
### Connection Lifecycle
|
||||
1. **Connect** to server (TCP/WebSocket)
|
||||
2. **Subscribe** to required message types
|
||||
3. **Send keepalive** every 30 seconds when idle
|
||||
4. **Resubscribe** after any disconnection
|
||||
5. **Handle** out-of-order packets for Advanced Text
|
||||
|
||||
### Common Issues
|
||||
- **Encryption fails**: Ensure message type in additional data matches packet header
|
||||
- **Messages dropped**: Check total size ≤ 1000 bytes including nonce
|
||||
- **Connection timeout**: Verify keepalive frequency
|
||||
- **Advanced Text garbled**: Reconstruct packets in correct order before decompression
|
||||
|
||||
---
|
||||
|
||||
## Protocol Features
|
||||
|
||||
- **Binary pub/sub messaging** with server-side routing
|
||||
- **End-to-end encryption** using Romulus-M AEAD
|
||||
- **ZSTD compression** for large text messages
|
||||
- **Multi-packet support** for long messages
|
||||
- **TCP and WebSocket** transport options
|
||||
|
||||
This is a documentation-only repository. The protocol specification is final and changes are not permitted.
|
||||
60
CLAUDE.md
Normal file
60
CLAUDE.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is bennc-js, a TypeScript implementation of the BENNCv1 (Butlersaurus Ephemeral No NONCEnse Chat) protocol specification. It provides client functionality for a binary pub/sub messaging protocol with encryption and compression support.
|
||||
|
||||
## Development Commands
|
||||
|
||||
- `npm run build` - Compile TypeScript to JavaScript (outputs to `dist/`)
|
||||
- `npm run test` - Run Jest test suite
|
||||
- `npm run lint` - Check code formatting with Prettier
|
||||
- `npm run format` - Format code with Prettier
|
||||
- `npm install` - Install dependencies (automatically runs `tsc` via postinstall)
|
||||
|
||||
## Architecture
|
||||
|
||||
The codebase implements the BENNC protocol specification with the following structure:
|
||||
|
||||
### Core Files
|
||||
|
||||
- `src/index.ts` - Main entry point exporting all public APIs
|
||||
- `src/mapping.ts` - Central registry mapping message types (0x0000-0xFFFF) to their pack/unpack functions
|
||||
- `src/common.ts` - Protocol constants including `MAX_DATA_LENGTH` (1000 bytes), `DEFAULT_KEY`, and `MessageTypes` enum
|
||||
- `src/messages/packet.ts` - Core packet handling with `packOutgoingPacket` and `unpackIncomingPacket` functions
|
||||
|
||||
### Message Types Implementation
|
||||
|
||||
Each BENNC message type has its own module in `src/messages/`:
|
||||
|
||||
- `subscribe.ts` (0x0000) - Subscribe to message types
|
||||
- `basic.ts` (0x0001) - Basic encrypted chat messages
|
||||
- `userDataRequest.ts` (0x0002) - Request user information
|
||||
- `userDataResponse.ts` (0x0003) - Respond with user information
|
||||
- `keepalive.ts` (0x0005) - Connection keepalive messages
|
||||
- `history.ts` (0xFFFE) - Message history requests
|
||||
- `unsubscribe.ts` (0xFFFF) - Unsubscribe from message types
|
||||
|
||||
### Protocol Implementation Details
|
||||
|
||||
- **Binary Protocol**: Big-endian integers, UTF-8 strings
|
||||
- **Message Structure**: Client sends [Type(2)|Length(2)|Data(0-1000)], Server responds [Type(2)|SenderId(4)|Length(2)|Data(0-1000)]
|
||||
- **Encryption**: Uses Romulus-M AEAD (via `romulus-js` dependency) with 16-byte nonces for message types 0x0001, 0x0002, 0x0003
|
||||
- **Max Data Size**: 1000 bytes including nonce for encrypted messages
|
||||
- **Dependencies**: Includes local `romulus-js` cryptography implementation and `color` library for user data
|
||||
|
||||
### Utilities
|
||||
|
||||
- `src/utilities/number.ts` - Big-endian number conversion functions (`numberToUint16BE`, `numberToUint32BE`)
|
||||
- `src/utilities/smart-buffer.ts` - Buffer manipulation utility for packet construction/parsing
|
||||
|
||||
### Key Architecture Patterns
|
||||
|
||||
- **Mapping System**: Central `packers` and `unpackers` objects in `mapping.ts` provide type-safe message handling
|
||||
- **Interface Separation**: `IncomingPacket` vs `OutgoingPacket` interfaces handle client/server message structure differences
|
||||
- **Encryption Integration**: Encrypted message types automatically handle nonce generation and Romulus-M encryption
|
||||
- **Protocol Compliance**: Strict adherence to BENNC specification including reserved sender IDs (0xFFFFFF00-0xFFFFFFFF)
|
||||
|
||||
The codebase serves as a complete client-side implementation for connecting to BENNC chat servers via TCP or WebSocket protocols.
|
||||
@@ -1,5 +1,5 @@
|
||||
# BENNC-JS
|
||||
[](https://drone.jacknet.io/TerribleCodeClub/bennc-js) [](https://standardjs.com)
|
||||
[](https://drone.jacknet.io/TerribleCodeClub/bennc-js)
|
||||
|
||||
An implementation of the [BENNC](https://wiki.jacknet.io/books/simontech/chapter/bennc) client specification.
|
||||
|
||||
@@ -48,9 +48,3 @@ This repository contains the necessary configuration files to debug, test and bu
|
||||
Run the build task (`Ctrl+Shift+B` or `⇧⌘B`) to automatically compile the Typescript source files in the background.
|
||||
|
||||
Unit tests use the [Jest](https://jestjs.io/) library. Support for Visual Studio Code is offered through the [Jest marketplace package](https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest) maintained by Orta.
|
||||
|
||||
## Contribution guidelines
|
||||
|
||||
[](https://github.com/standard/standard)
|
||||
|
||||
This library uses [ts-standard](https://github.com/standard/ts-standard), based on [JavaScript Standard Style](https://standardjs.com/rules.html). Please ensure all contributions are ts-standard compliant before submitting a pull request.
|
||||
|
||||
5991
package-lock.json
generated
5991
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,8 @@
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"lint": "ts-standard",
|
||||
"lint": "prettier --check .",
|
||||
"format": "prettier --write .",
|
||||
"test": "jest",
|
||||
"build": "tsc",
|
||||
"postinstall": "tsc"
|
||||
@@ -32,6 +33,6 @@
|
||||
"dependencies": {
|
||||
"color": "^4.2.0",
|
||||
"@types/color": "^3.0.3",
|
||||
"romulus-js": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git"
|
||||
"romulus-js": "file:./romulus-js"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user