-
Notifications
You must be signed in to change notification settings - Fork 1
/
udp4-listen.go
109 lines (93 loc) · 2.33 KB
/
udp4-listen.go
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
/*
* Synopsis:
* Listen on udp4 port and write human readable packets to stderr.
* Usage:
* udp4-listen <listen-ip4> <port> <output-path|stdout|stderr>
* udp4-listen 192.168.1.175 10514 raspberry-pi.log
* udp4-listen 192.168.1.175 10514 stderr
* Note:
* Consider replacing the default output of msg+"\n" to a pipe to
* long running background process to further masage the udp4 message.
* By the way, this piping trick may actually be possible using socats
* ability to fork subprocesses. not sure.
*
* This program only exists since socat can not terminate udp4 packets
* with a newline. Various piping to a script were more cumbersone than
* than just writing this program.
*/
package main
import (
"fmt"
"net"
"os"
"os/signal"
"syscall"
)
func die(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, "ERROR: " + format + "\n", args...)
fmt.Fprintf(
os.Stderr,
"usage: udp4-listen <host> <port> <out-path|stdout|stderr>",
)
os.Exit(1)
}
func slurp(in *net.UDPConn, out *os.File) {
for {
var buf [2048]byte // larger than udp packet
nb, err := in.Read(buf[:])
if err != nil {
die("in.Read(udp4) failed: %s", err)
}
if nb == 0 {
die("in.Read(udp4): zero bytes")
}
if buf[nb - 1] != '\n' {
buf[nb] = '\n'
nb++
}
_, err = out.Write(buf[:nb])
if err != nil {
die("out.Write(out) failed: %s", err)
}
}
}
func main() {
argc := len(os.Args) - 1
if argc != 3 {
die("wrong number of cli args: got %d, expected 3", argc)
}
// open output
var out *os.File
out_path := os.Args[3]
if out_path == "stdout" {
out = os.Stdout
} else if out_path == "stderr" {
out = os.Stderr
} else {
var err error
out, err = os.OpenFile(
out_path,
os.O_APPEND|os.O_WRONLY|os.O_CREATE,
0755,
)
if err != nil {
die("os.File.Open(%s) failed: %s", out_path, err)
}
}
// open udp4 listener
service := fmt.Sprintf("%s:%s", os.Args[1], os.Args[2])
addr, err := net.ResolveUDPAddr("udp4", service)
if err != nil {
die("net.ResolveUDPAddr(%s) failed: %s", service, err)
}
in, err := net.ListenUDP("udp4", addr)
if err != nil {
die("net.ListenUDP(%s) failed: %s", addr, err)
}
go slurp(in, out)
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigc
fmt.Println("\nudp4-listen: caught signal:", sig)
os.Exit(0)
}