From 8e0f25abe914fa9824e22200aee9a78edf21eb63 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Tue, 18 Nov 2025 21:30:06 -0600 Subject: [PATCH] add SLIP framing --- internals/framing/slip.go | 52 +++++++++++++++++++++++++++++++++++++++ tcp-client.go | 2 ++ tcp-server.go | 2 ++ 3 files changed, 56 insertions(+) create mode 100644 internals/framing/slip.go diff --git a/internals/framing/slip.go b/internals/framing/slip.go new file mode 100644 index 0000000..607d94f --- /dev/null +++ b/internals/framing/slip.go @@ -0,0 +1,52 @@ +package framing + +type SlipFramer struct { + buffer []byte +} + +func NewSlipFramer() *SlipFramer { + return &SlipFramer{buffer: []byte{}} +} + +func (sf *SlipFramer) Frame(data []byte) [][]byte { + messages := [][]byte{} + END := byte(0xc0) + ESC := byte(0xdb) + ESC_END := byte(0xdc) + ESC_ESC := byte(0xdd) + + escapeNext := false + for _, packetByte := range data { + + if packetByte == ESC { + escapeNext = true + continue + } + + if escapeNext { + if packetByte == ESC_END { + sf.buffer = append(sf.buffer, END) + } else if packetByte == ESC_ESC { + sf.buffer = append(sf.buffer, ESC) + } + escapeNext = false + } else if packetByte == END { + if len(sf.buffer) == 0 { + // opening END byte, can discard + continue + } else { + message := sf.buffer + messages = append(messages, message) + } + sf.buffer = []byte{} + } else { + sf.buffer = append(sf.buffer, packetByte) + } + } + + return messages +} + +func (sf *SlipFramer) Clear() { + sf.buffer = []byte{} +} diff --git a/tcp-client.go b/tcp-client.go index e1f18a6..7bd4720 100644 --- a/tcp-client.go +++ b/tcp-client.go @@ -65,6 +65,8 @@ func init() { framer = framing.NewByteSeparatorFramer([]byte{'\n'}) case "CRLF": framer = framing.NewByteSeparatorFramer([]byte{'\r', '\n'}) + case "SLIP": + framer = framing.NewSlipFramer() default: return nil, fmt.Errorf("unknown framing method: %s", framingMethodString) } diff --git a/tcp-server.go b/tcp-server.go index f32d160..3fc6385 100644 --- a/tcp-server.go +++ b/tcp-server.go @@ -67,6 +67,8 @@ func (ts TCPServer) HandleClient(ctx context.Context, client net.Conn) { framer = framing.NewByteSeparatorFramer([]byte{'\r'}) case "CRLF": framer = framing.NewByteSeparatorFramer([]byte{'\r', '\n'}) + case "SLIP": + framer = framing.NewSlipFramer() } buffer := make([]byte, 1024)