This repository was archived by the owner on Jul 25, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
145 lines (127 loc) · 3.58 KB
/
main.go
File metadata and controls
145 lines (127 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package main
import (
"flag"
"fmt"
"io"
"log"
"net"
"strings"
"unicode/utf8"
"go.bug.st/serial"
"go.bug.st/serial/enumerator"
)
func main() {
// Command-line options
device := flag.String("device", "", "Path to the serial device (e.g., /dev/ttyUSB0 or COM3)")
listenAddr := flag.String("listen", "0.0.0.0:5000", "TCP listen address and port")
baudRate := flag.Int("baud", 9600, "Baud rate for the serial device")
allowedIPs := flag.String("allowed", "", "Comma-separated list of allowed source IPs (leave empty to allow all)")
verbose := flag.Bool("verbose", false, "Enable verbose logging for IN/OUT data")
decode := flag.Bool("decode", false, "Attempt to decode data into human-readable text")
flag.Parse()
// Validate the device argument
if *device == "" {
fmt.Println("Available serial devices:")
ports, err := enumerator.GetDetailedPortsList()
if err != nil {
log.Fatalf("Failed to list serial ports: %v", err)
}
for _, port := range ports {
fmt.Printf("- %s (isUSB: %v)\n", port.Name, port.IsUSB)
}
log.Fatal("Please specify a serial device using the -device flag.")
}
// Parse allowed IPs into a map for quick lookup
allowedIPSet := make(map[string]bool)
if *allowedIPs != "" {
for _, ip := range strings.Split(*allowedIPs, ",") {
allowedIPSet[ip] = true
}
}
// Open the serial device
mode := &serial.Mode{
BaudRate: *baudRate,
}
serialPort, err := serial.Open(*device, mode)
if err != nil {
log.Fatalf("Failed to open serial port: %v", err)
}
defer serialPort.Close()
log.Printf("Serial device %s opened at %d baud", *device, *baudRate)
// Start the TCP server
listener, err := net.Listen("tcp", *listenAddr)
if err != nil {
log.Fatalf("Failed to start TCP server: %v", err)
}
defer listener.Close()
log.Printf("Server listening on %s and forwarding to %s at %d baud", *listenAddr, *device, *baudRate)
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("Failed to accept connection: %v", err)
continue
}
clientIP := strings.Split(conn.RemoteAddr().String(), ":")[0]
if len(allowedIPSet) > 0 && !allowedIPSet[clientIP] {
log.Printf("Connection from disallowed IP: %s", clientIP)
conn.Close()
continue
}
log.Printf("Accepted connection from %s", conn.RemoteAddr())
// Handle client connection
go handleConnection(conn, serialPort, *verbose, *decode)
}
}
func handleConnection(conn net.Conn, serialPort serial.Port, verbose, decode bool) {
defer conn.Close()
// Forward data from TCP to serial
go func() {
buffer := make([]byte, 1024)
for {
n, err := conn.Read(buffer)
if err != nil {
if err != io.EOF {
log.Printf("Error reading from TCP: %v", err)
}
break
}
if verbose {
log.Printf("IN (TCP->Serial): %s", formatData(buffer[:n], decode))
}
_, err = serialPort.Write(buffer[:n])
if err != nil {
log.Printf("Error writing to serial: %v", err)
break
}
}
}()
// Forward data from serial to TCP
buffer := make([]byte, 1024)
for {
n, err := serialPort.Read(buffer)
if err != nil {
if err != io.EOF {
log.Printf("Error reading from serial: %v", err)
}
break
}
if verbose {
log.Printf("OUT (Serial->TCP): %s", formatData(buffer[:n], decode))
}
_, err = conn.Write(buffer[:n])
if err != nil {
log.Printf("Error writing to TCP: %v", err)
break
}
}
}
// formatData formats the byte data based on the decode flag
func formatData(data []byte, decode bool) string {
if decode {
if utf8.Valid(data) {
return fmt.Sprintf("%q", string(data))
}
return fmt.Sprintf("(binary: %x)", data)
}
return fmt.Sprintf("%x", data)
}