M3DA (Machine-to-Machine Data Access) is a secure and bandwidth-efficient protocol designed for IoT and embedded systems communication. This document provides comprehensive documentation of the M3DA protocol based on reverse engineering of the Java reference implementation.
┌─────────────────────────────────────────────────┐
│ Application Layer │
├─────────────────────────────────────────────────┤
│ M3DA Messages (Message, Response, Vectors) │
├─────────────────────────────────────────────────┤
│ M3DA Envelope (Header, Payload, Footer) │
├─────────────────────────────────────────────────┤
│ Bysant Binary Serialization │
├─────────────────────────────────────────────────┤
│ TCP Transport (Length-Prefixed Frames) │
├─────────────────────────────────────────────────┤
│ Security Layer (Optional AES + HMAC) │
└─────────────────────────────────────────────────┘
M3DA uses the Bysant binary serialization format for efficient data encoding. Bysant is a self-describing, context-aware binary format.
The Bysant protocol defines 7 different encoding contexts:
- Context 0 (Global): Default context for general objects
- Context 1 (UIS): Unsigned Integers and Strings (uint32 max)
- Context 2 (Numbers): Optimized for numeric values
- Context 3 (Int32): 32-bit signed integers only
- Context 4 (Float): 32-bit floating point numbers
- Context 5 (Double): 64-bit floating point numbers
- Context 6 (Lists & Maps): Container objects
Every M3DA communication is wrapped in an envelope:
type M3daEnvelope struct {
Header map[string]interface{} // Control information
Payload []byte // Bysant-encoded messages
Footer map[string]interface{} // Additional metadata
}| Key | Type | Description |
|---|---|---|
id |
string | Client identifier |
status |
int64 | Response status code |
nonce |
int64 | Cryptographic nonce |
challenge |
[]byte | Authentication challenge |
mac |
[]byte | HMAC signature |
Standard data message for sending telemetry or commands:
type M3daMessage struct {
Path string // Message path (e.g., "@sys.telemetry")
TicketID *int64 // Optional correlation ID
Body map[string]interface{} // Message payload
}Response to a message with ticket ID:
type M3daResponse struct {
TicketID int64 // Correlation ID from request
Status int64 // HTTP-like status code
Message string // Optional status message
}M3DA provides specialized data structures for efficient compression of time-series data.
Compresses sequences of similar values using deltas:
type M3daDeltasVector struct {
Factor interface{} // Scale factor
Start interface{} // Starting value
Deltas []interface{} // Delta values
}Example: Temperature readings [23.5, 23.6, 23.4, 23.7] can be compressed as:
- Factor: 0.1
- Start: 235 (23.5 * 10)
- Deltas: [1, -2, 3] (representing +0.1, -0.2, +0.3)
Compresses periodic data with variations:
type M3daQuasiPeriodicVector struct {
Period interface{} // Base period
Start interface{} // Starting value
Shifts []interface{} // Timing variations
}Example: Timestamps with 60-second intervals but slight variations.
M3DA supports comprehensive security through encryption and authentication.
- HMAC-MD5: Legacy support
- HMAC-SHA1: Recommended standard
- None: No authentication
- AES-CBC-128: 128-bit AES in CBC mode
- AES-CBC-256: 256-bit AES in CBC mode
- AES-CTR-128: 128-bit AES in CTR mode
- AES-CTR-256: 256-bit AES in CTR mode (recommended)
- None: No encryption
M3DA uses HTTP-like status codes:
| Code | Status | Description |
|---|---|---|
| 200 | OK | Success |
| 400 | BAD_REQUEST | Malformed request |
| 401 | UNAUTHORIZED | Invalid credentials |
| 403 | FORBIDDEN | Access denied |
| 407 | AUTHENTICATION_REQUIRED | No credentials |
| 450 | ENCRYPTION_NEEDED | Encryption required |
| 500 | UNEXPECTED_ERROR | Server error |
| 503 | SERVICE_UNAVAILABLE | Server unavailable |
M3DA uses TCP with length-prefixed framing:
- Length Prefix: 4-byte big-endian length
- Envelope Data: Bysant-encoded envelope
- Connection: Persistent TCP connection on port 44900
- Client connects to server (TCP port 44900)
- Client sends envelope with message(s)
- Server processes and responds with envelope
- Connection remains open for subsequent exchanges
- Client configures security (encryption + authentication)
- For each envelope:
- Generate cryptographic nonce
- Encrypt payload (if configured)
- Calculate HMAC over envelope
- Send secured envelope
- Server verifies HMAC and decrypts payload
- Server responds with secured envelope
- Integers: Use int64 for all integer values
- Floats: Support both float32 and float64
- Strings: UTF-8 encoded, binary data as []byte
- Nonces: Use int64, not uint64 (Bysant limitation)
- Message paths: Use UIS context (Context 1)
- Message bodies: Use Lists & Maps context (Context 6)
- Numeric data: Use Numbers context (Context 2) when appropriate
- Always check status codes in responses
- Handle security errors (450, 407) appropriately
- Implement proper timeout handling
This documentation is based on analysis of the Java reference implementation, including:
- Packet capture analysis
- Java source code examination
- Protocol behavior observation
- Binary format reverse engineering
The Go implementation maintains compatibility with the Java reference while providing a modern, idiomatic Go API.