-
Notifications
You must be signed in to change notification settings - Fork 53
/
Copy pathmain.go
160 lines (131 loc) · 3.43 KB
/
main.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
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package main
import (
"context"
"flag"
"log/slog"
"os"
"os/signal"
"strings"
"time"
"github.com/go-routeros/routeros/v3"
)
var (
debug = flag.Bool("debug", false, "debug log level mode")
command = flag.String("command", "/ip/firewall/address-list/listen", "RouterOS command")
address = flag.String("address", "127.0.0.1:8728", "RouterOS address and port")
username = flag.String("username", "admin", "User name")
password = flag.String("password", "admin", "Password")
timeout = flag.Duration("timeout", 10*time.Second, "Cancel after")
async = flag.Bool("async", false, "Call Async()")
useTLS = flag.Bool("tls", false, "Use TLS")
)
func dial(ctx context.Context) (*routeros.Client, error) {
if *useTLS {
return routeros.DialTLSContext(ctx, *address, *username, *password, nil)
}
return routeros.DialContext(ctx, *address, *username, *password)
}
func fatal(log *slog.Logger, message string, err error) {
log.Error(message, slog.Any("error", err))
os.Exit(2)
}
func main() {
var err error
if err = flag.CommandLine.Parse(os.Args[1:]); err != nil {
panic(err)
}
logLevel := slog.LevelInfo
if debug != nil && *debug {
logLevel = slog.LevelDebug
}
handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
AddSource: true,
Level: logLevel,
})
log := slog.New(handler)
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
var cli *routeros.Client
if cli, err = dial(ctx); err != nil {
fatal(log, "could not dial", err)
}
cli.SetLogHandler(handler)
defer func() {
if errClose := cli.Close(); errClose != nil {
log.Error("could not close routerOS client", slog.Any("error", errClose))
}
}()
cli.Queue = 100
if *async {
explicitAsync(ctx, log, cli)
} else {
implicitAsync(ctx, log, cli)
}
if err = cli.Close(); err != nil {
fatal(log, "could not close client", err)
}
}
func explicitAsync(ctx context.Context, log *slog.Logger, c *routeros.Client) {
errC := c.Async()
log.Debug("Running explicitAsync mode...")
ctx, cancel := context.WithCancel(ctx)
defer cancel()
go func() {
l, err := c.ListenArgsContext(ctx, strings.Split(*command, " "))
if err != nil {
fatal(log, "could not listen", err)
}
go func() {
time.Sleep(*timeout)
log.Debug("Cancelling the RouterOS command...")
if _, errCancel := l.CancelContext(ctx); errCancel != nil {
fatal(log, "could not cancel context", errCancel)
}
log.Debug("cancelled")
cancel()
}()
log.Info("Waiting for !re...")
for sen := range l.Chan() {
log.Info("Update", slog.String("sentence", sen.String()))
}
if err = l.Err(); err != nil {
fatal(log, "received an error", err)
}
}()
select {
case <-ctx.Done():
return
case err := <-errC:
if err != nil {
fatal(log, "received an error", err)
}
}
}
func implicitAsync(ctx context.Context, log *slog.Logger, c *routeros.Client) {
l, err := c.ListenArgsContext(ctx, strings.Split(*command, " "))
if err != nil {
fatal(log, "could not listen", err)
}
go func() {
time.Sleep(*timeout)
log.Debug("Cancelling the RouterOS command...")
if _, errCancel := l.Cancel(); errCancel != nil {
fatal(log, "could not cancel", errCancel)
}
}()
loop:
for {
select {
case <-ctx.Done():
break loop
case sen, ok := <-l.Chan():
if !ok {
break loop
}
log.Info("Update", slog.String("sentence", sen.String()))
}
}
if err = l.Err(); err != nil {
fatal(log, "received an error", err)
}
}