Compare commits
1 Commits
main
...
feat/mnis-
| Author | SHA1 | Date | |
|---|---|---|---|
| e759f13d97 |
@@ -73,6 +73,7 @@ type config struct {
|
||||
|
||||
RESTPlainHTTP bool `mapstructure:"rest_plain_http"`
|
||||
GRPCPlain bool `mapstructure:"grpc_plain"`
|
||||
MNISClient bool `mapstructure:"mnis_client"`
|
||||
|
||||
TLS struct {
|
||||
Cert string `mapstructure:"cert"`
|
||||
@@ -141,6 +142,7 @@ func registerDaemonFlags(cmd *cobra.Command) {
|
||||
f.String("rest-addr", ":8443", "REST listen address")
|
||||
f.Bool("rest-plain-http", false, "Serve REST over plain HTTP (loopback only)")
|
||||
f.Bool("grpc-plain", false, "Serve gRPC without TLS (DEV ONLY, no auth)")
|
||||
f.Bool("mnis-client", true, "Use ephemeral ports (coexist with MNIS); false binds the well-known ports directly")
|
||||
f.String("tls-cert", "", "Server TLS certificate (PEM)")
|
||||
f.String("tls-key", "", "Server TLS key (PEM)")
|
||||
f.String("tls-client-ca", "", "PEM bundle of CAs allowed to issue client certs")
|
||||
@@ -158,6 +160,7 @@ var flagToKey = map[string]string{
|
||||
"rest-addr": "rest_addr",
|
||||
"rest-plain-http": "rest_plain_http",
|
||||
"grpc-plain": "grpc_plain",
|
||||
"mnis-client": "mnis_client",
|
||||
"tls-cert": "tls.cert",
|
||||
"tls-key": "tls.key",
|
||||
"tls-client-ca": "tls.client_ca",
|
||||
@@ -180,6 +183,7 @@ func loadConfig(v *viper.Viper, cmd *cobra.Command, cfgFile string) error {
|
||||
v.SetDefault("rest_addr", ":8443")
|
||||
v.SetDefault("rest_plain_http", false)
|
||||
v.SetDefault("grpc_plain", false)
|
||||
v.SetDefault("mnis_client", true)
|
||||
v.SetDefault("ntfy.url", "https://ntfy.sh")
|
||||
|
||||
used, err := cfgloader.Load(v, cfgloader.Options{AppName: appName, Explicit: cfgFile})
|
||||
@@ -210,14 +214,15 @@ func runWithConfig(ctx context.Context, cfg config) error {
|
||||
return fmt.Errorf("invalid bind_ip %q", cfg.BindIP)
|
||||
}
|
||||
tr, err := mnis.NewUDP(mnis.UDPConfig{
|
||||
BindIP: bindIP,
|
||||
Ports: []int{tms.Port, ars.Port, lrrp.Port},
|
||||
BindIP: bindIP,
|
||||
Ports: []int{tms.Port, ars.Port, lrrp.Port},
|
||||
ClientMode: cfg.MNISClient,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("mnis: %w", err)
|
||||
}
|
||||
defer tr.Close()
|
||||
log.Info("mnis transport bound", "ip", bindIP, "ports", []int{tms.Port, ars.Port, lrrp.Port})
|
||||
log.Info("mnis transport ready", "ip", bindIP, "ports", []int{tms.Port, ars.Port, lrrp.Port}, "client_mode", cfg.MNISClient)
|
||||
|
||||
// Contacts.
|
||||
store, err := contacts.Open(cfg.DataDir)
|
||||
|
||||
@@ -7,7 +7,12 @@
|
||||
# /etc/mototrbo/mototrbod.toml
|
||||
# Override with --config. Env vars (MOTOTRBO_*) and --flags override file.
|
||||
|
||||
bind_ip = "127.0.0.1"
|
||||
bind_ip = "127.0.0.1"
|
||||
|
||||
# Client mode (default true): use ephemeral ports so mototrbod can
|
||||
# coexist with MNIS. Set to false only if MNIS is not running and
|
||||
# mototrbod should bind ports 4005/4007/4001 directly.
|
||||
mnis_client = true
|
||||
# data_dir defaults to %PROGRAMDATA%\mototrbo\data on Windows and
|
||||
# ./var/badger elsewhere. Set explicitly to override.
|
||||
data_dir = "./var/badger"
|
||||
|
||||
@@ -66,6 +66,12 @@ type UDPConfig struct {
|
||||
// allowed for any port, but inbound traffic is only delivered for
|
||||
// ports that have a bound socket.
|
||||
Ports []int
|
||||
// ClientMode, when true, binds ephemeral local ports instead of
|
||||
// the well-known service ports. This lets mototrbod coexist with
|
||||
// MNIS (which already owns ports 4005/4007/4001). Outbound
|
||||
// packets are still addressed to the well-known port on the
|
||||
// radio's tunnel IP; replies arrive on the ephemeral socket.
|
||||
ClientMode bool
|
||||
}
|
||||
|
||||
// udpTransport is a Transport that uses one net.UDPConn per service port.
|
||||
@@ -97,12 +103,16 @@ func NewUDP(cfg UDPConfig) (Transport, error) {
|
||||
}
|
||||
|
||||
for _, p := range cfg.Ports {
|
||||
conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: bind, Port: p})
|
||||
localPort := p
|
||||
if cfg.ClientMode {
|
||||
localPort = 0 // ephemeral — let the OS pick
|
||||
}
|
||||
conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: bind, Port: localPort})
|
||||
if err != nil {
|
||||
t.closeAllConns()
|
||||
return nil, fmt.Errorf("listen %s:%d: %w", bind, p, err)
|
||||
return nil, fmt.Errorf("listen %s:%d: %w", bind, localPort, err)
|
||||
}
|
||||
t.conns[p] = conn
|
||||
t.conns[p] = conn // keyed by well-known port, not local port
|
||||
t.wg.Add(1)
|
||||
go t.readLoop(p, conn)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user