Skip to content

Commit

Permalink
Merge pull request #41 from Vinz1911/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
Vinz1911 authored Nov 20, 2023
2 parents ae65d91 + 72832c8 commit 1e30a69
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 43 deletions.
58 changes: 22 additions & 36 deletions DEFINITION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,60 @@

## Abstract

This document specifies a new binary framing protocol, called Fusion Framing Protocol. The protocol provides a generic and efficient way to send text, binary, and control messages over a network connection. It is designed to be simple, flexible, and extensible, while maintaining the integrity and security of data. This protocol is suitable for use in various network applications, such as client-server and peer-to-peer communication.
This document specifies a new binary framing protocol, called Fusion Framing Protocol. The protocol provides a generic and efficient way to send text, binary, and control messages over a network connection. It is designed to be simple, flexible, and extensible. This protocol is suitable for use in various network applications, such as client-server and peer-to-peer communication.

## Table of Contents

1. Introduction
2. Protocol Overview
3. Framing
- 3.1 Frame Format
- 3.2 Frame Types
- 3.3 Control Frames
- 3.1 Frame Format
- 3.2 Frame Types
- 3.3 Control Frames
4. Message Handling
5. Security Considerations
6. IANA Considerations

## 1. Introduction

As network applications become more complex and diverse, there is a growing need for a simple and efficient way to send different types of messages over a network connection. The Fusion Framing Protocol (FFP) is designed to meet this need by providing a generic and extensible binary framing protocol. The protocol supports the transmission of text, binary, and control messages, and ensures the integrity and security of data by including a message hash in each frame.
As network applications become more complex and diverse, there is a growing need for a simple and efficient way to send different types of messages over a network connection. The Fusion Framing Protocol (FFP) is designed to meet this need by providing a generic and extensible binary framing protocol. The protocol supports the transmission of text, binary, and control messages.

This document defines the framing format, frame types, and message handling procedures for the FFP. It also discusses security considerations and IANA considerations related to the protocol.

## 2. Protocol Overview

The FFP is a binary framing protocol that uses a simple header and payload structure. The header contains an opcode that indicates the type of the frame, the length of the frame, and a hash value computed over the control data of the frame. The payload contains the actual message data.
The FFP is a binary framing protocol that uses a simple header and payload structure. The header contains an opcode that indicates the type of the frame and the length of the frame. The payload contains the actual message data.

The protocol supports three types of frames:

Text frames, for transmitting UTF-8 encoded text messages
Binary frames, for transmitting arbitrary binary data
Control frames, for transmitting control messages, such as pings
To ensure the integrity of the data, each frame includes a hash value computed using the SHA-256 algorithm. The receiver can verify the hash value to ensure that the frame has not been tampered with or corrupted during transmission.
- Text frames, for transmitting UTF-8 encoded text messages
- Binary frames, for transmitting arbitrary binary data
- Control frames, for transmitting control messages, such as pings

## 3. Framing

### 3.1 Frame Format
Each frame in the FFP consists of a header and a payload.
Frames in the Framing Protocol have the following structure:
Each frame in the FFP consists of a header and a payload. Frames in the Fusion Framing Protocol have the following structure:

```shell
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
0 1 2 3 4 5 6 7 8 9 0 1 2 ... n
+-+-------+---------------------+
|O|Length | Hash SHA256 |
|P| (4) | (32) |
|O| Len | Payload Data |
|P| (4) | (n) |
|C| | |
+---------+ - - - - - - - - - - +
| hash value continued |
+ - - - - +---------------------+
| | Payload Data |
+ - - - - + - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+-------------------------------+
```

The header contains the following fields:

- Opcode (1 byte): Indicates the type of the frame (text, binary, or control)
- Length (4 bytes): Specifies the total length of the frame, including the header and payload, in network byte order (big-endian)
- Hash (32 bytes): A SHA-256 hash computed over the control data of the frame (i.e., the opcode and length fields)
- The payload contains the actual message data, which can be text, binary, or control data, depending on the frame type.

The payload contains the actual message data, which can be text, binary, or control data, depending on the frame type.

### 3.2 Frame Types
The FFP supports three types of frames, as indicated by the opcode field in the header:
Expand All @@ -77,25 +71,17 @@ A ping message is a control frame with a payload consisting of a 16-bit unsigned

## 4. Message Handling

When receiving a frame, an endpoint should perform the following steps:
When receiving a frame, an endpoint should verify the frame's type and length and then process the payload accordingly:
1. Verify the frame's hash value by computing the SHA-256 hash over the control data of the frame (opcode and length fields) and comparing it to the hash value in the frame header. If the hash values do not match, the frame is considered invalid and should be discarded.
2. Depending on the frame type, process the payload as follows:
- For text frames, decode the UTF-8 encoded payload as a text message and pass it to the application layer.
- For binary frames, pass the binary payload to the application layer.
- For control frames, process the control message according to its type (e.g., respond to a ping message with a pong message).

When sending a message, an endpoint should perform the following steps:
- For text frames, decode the UTF-8 encoded payload as a text message and pass it to the application layer.
- For binary frames, pass the binary payload to the application layer.
- For control frames, process the control message according to its type (e.g., respond to a ping message with a pong message).
1. Create a frame with the appropriate opcode for the message type (text, binary, or control).
2. Compute the length of the frame, including the header and payload, and set the length field in the header.
3. Compute the SHA-256 hash over the control data of the frame (opcode and length fields) and set the hash field in the header.
4. Append the message payload to the frame.
5. Transmit the frame over the network connection.
When sending a message, an endpoint should create a frame with the appropriate opcode for the message type (text, binary, or control), set the length field in the header, append the message payload to the frame, and transmit the frame over the network connection.
## 5. Security Considerations
The FFP includes a hash value in each frame to ensure the integrity of the data. However, this hash value does not provide any confidentiality or authentication. To secure the communication between endpoints, the FFP should be used in conjunction with a secure transport layer, such as Transport Layer Security (TLS).
The FFP does not include any inherent mechanisms for ensuring data integrity, confidentiality, or authentication. To secure the communication between endpoints, the FFP should be used in conjunction with a secure transport layer, such as Transport Layer Security (TLS).
Additionally, the protocol does not provide any built-in mechanism for handling malicious or malformed frames. It is the responsibility of the application layer to handle such cases appropriately, for example, by closing the connection or implementing rate-limiting mechanisms.
Expand Down
12 changes: 7 additions & 5 deletions Sources/FusionKit/Model/FKConnectionFramer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
import CryptoKit

internal final class FKConnectionFramer: FKConnectionFramerProtocol {
private var buffer: DispatchData = .empty
private var buffer: DispatchData
internal func reset() { buffer = .empty }

/// The `FKConnectionFramer` represents the fusion framing protocol.
Expand All @@ -20,7 +20,9 @@ internal final class FKConnectionFramer: FKConnectionFramerProtocol {
///
/// This protocol is based on a standardized Type-Length-Value Design Scheme.

internal required init() { }
internal required init(buffer: DispatchData = .empty) {
self.buffer = buffer
}

/// Create a protocol conform message frame
///
Expand All @@ -46,7 +48,7 @@ internal final class FKConnectionFramer: FKConnectionFramerProtocol {
guard buffer.count <= FKConnectionConstants.frame.rawValue else { completion(.failure(FKConnectionError.readBufferOverflow)); return }
guard buffer.count >= FKConnectionConstants.control.rawValue, buffer.count >= length else { return }
while buffer.count >= length && length != .zero {
guard let bytes = extractMessage() else { completion(.failure(FKConnectionError.parsingFailed)); return }
guard let bytes = extractMessage(length: length) else { completion(.failure(FKConnectionError.parsingFailed)); return }
switch buffer.first {
case FKConnectionOpcodes.binary.rawValue: completion(.success(bytes))
case FKConnectionOpcodes.ping.rawValue: completion(.success(UInt16(bytes.count)))
Expand All @@ -71,10 +73,10 @@ private extension FKConnectionFramer {

/// Extract the message and remove the overhead,
/// if not possible it returns nil
/// - Parameter length: the length of the extracting message
/// - Returns: the extracted message as `Data`
private func extractMessage() -> Data? {
private func extractMessage(length: UInt32) -> Data? {
guard buffer.count >= FKConnectionConstants.control.rawValue else { return nil }
guard let length = extractSize() else { return nil }
guard length > FKConnectionConstants.control.rawValue else { return Data() }
return Data(buffer.subdata(in: FKConnectionConstants.control.rawValue..<Int(length)))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal protocol FKConnectionFramerProtocol {
/// The protocol's overhead per message is only `0x5` bytes, resulting in high performance.
///
/// This protocol is based on a standardized Type-Length-Value Design Scheme.
init()
init(buffer: DispatchData)

/// Create a protocol conform message frame
///
Expand Down
2 changes: 1 addition & 1 deletion Tests/FusionKitTests/FusionKitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ private enum TestCase {
}

class FusionKitTests: XCTestCase {
private var connection = FKConnection(host: "localhost", port: 7878)
private var connection = FKConnection(host: "atonet.de", port: 7878)
private var buffer = "50000"
private let timeout = 10.0
private let uuid = UUID().uuidString
Expand Down

0 comments on commit 1e30a69

Please sign in to comment.