From cae50e4ab15fdfe689da4df974e40085e1f95de6 Mon Sep 17 00:00:00 2001 From: Vinzenz Weist Date: Thu, 2 Nov 2023 01:46:42 +0100 Subject: [PATCH 1/3] [M] updated protocol definition --- DEFINITION.md | 58 +++++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/DEFINITION.md b/DEFINITION.md index 5131faa..c77884f 100644 --- a/DEFINITION.md +++ b/DEFINITION.md @@ -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: @@ -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. From 3081cfdb275a9f447bba12b3faccccedcde43ca2 Mon Sep 17 00:00:00 2001 From: Vinzenz Weist Date: Wed, 8 Nov 2023 22:18:15 +0100 Subject: [PATCH 2/3] [M] updated framer --- Sources/FusionKit/Model/FKConnectionFramer.swift | 12 +++++++----- .../Protocols/FKConnectionFramerProtocol.swift | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Sources/FusionKit/Model/FKConnectionFramer.swift b/Sources/FusionKit/Model/FKConnectionFramer.swift index 195de23..3356826 100644 --- a/Sources/FusionKit/Model/FKConnectionFramer.swift +++ b/Sources/FusionKit/Model/FKConnectionFramer.swift @@ -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. @@ -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 /// @@ -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))) @@ -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.. Date: Mon, 20 Nov 2023 23:50:28 +0100 Subject: [PATCH 3/3] [M] make test work again --- Tests/FusionKitTests/FusionKitTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/FusionKitTests/FusionKitTests.swift b/Tests/FusionKitTests/FusionKitTests.swift index cd3d8e4..f719fa9 100644 --- a/Tests/FusionKitTests/FusionKitTests.swift +++ b/Tests/FusionKitTests/FusionKitTests.swift @@ -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