abbel/main.go

127 lines
2.2 KiB
Go

package main
import (
"fmt"
"log"
"net"
"git.freifunk-franken.de/jkimmel/abbel/tlv"
"golang.org/x/net/ipv6"
)
type options struct {
Group net.IP
Port uint16
Ifs []net.Interface
}
func parseOpts() (options, error) {
var opt options
var err error
opt.Group = net.ParseIP("ff02::1:6")
opt.Port = 6696
ifi, err := net.InterfaceByName("babel")
if err != nil {
return opt, err
}
opt.Ifs = []net.Interface{*ifi}
return opt, err
}
func run(opt options) error {
var err error
uc, err := net.ListenUDP("udp6", &net.UDPAddr{Port: int(opt.Port)})
if err != nil {
return err
}
defer uc.Close()
up := ipv6.NewPacketConn(uc)
if err := up.SetControlMessage(ipv6.FlagDst, true); err != nil {
return err
}
for ifi := range opt.Ifs {
if err := up.JoinGroup(&opt.Ifs[ifi], &net.UDPAddr{IP: opt.Group}); err != nil {
return err
}
}
b := make([]byte, 1500)
for {
n, rcm, src, err := up.ReadFrom(b)
if err != nil {
return err
}
_ = rcm
magic := b[0]
version := b[1]
length := uint16(b[2])<<8 + uint16(b[3])
if magic != 42 {
continue
}
if int(length)+4 > n {
fmt.Println("invalid length")
}
fmt.Println(src, rcm, magic, version, length, n)
var u tlv.PacketUpdate
var s tlv.PacketDecoder
ts := tlv.NewTLVScanner(b[4 : 4+length])
for ts.Scan() {
t, v := ts.TLV()
switch t {
case tlv.Update:
u, err = s.UpdateFromBytes(v)
if err != nil {
fmt.Println(u.PacketUpdateHeader, &u.Prefix, err)
} else {
if u.PacketUpdateHeader.Metric == 0xFFFF {
fmt.Print("\x1B[1m")
}
fmt.Printf("%43s: %+v\x1B[0m\n", &u.Prefix, u.PacketUpdateHeader)
}
default:
fmt.Printf(" T: %12s (%2d), L: %3d\n", t, t, len(v))
}
}
if ts.Err() != nil {
fmt.Println(err)
}
//{
// var bbuf bytes.Buffer
// lzww := lzw.NewWriter(&bbuf, lzw.LSB, 8)
// lzww.Write(b[:n])
// lzww.Close()
// fmt.Println(n, len(bbuf.Bytes()))
//}
//{
// var bbuf bytes.Buffer
// gzw, _ := gzip.NewWriterLevel(&bbuf, 9)
// gzw.Write(b[:n])
// gzw.Close()
// fmt.Println(n, len(bbuf.Bytes()))
//}
}
return nil
}
func main() {
opt, err := parseOpts()
if err != nil {
log.Fatal(err)
}
if err := run(opt); err != nil {
log.Fatal(err)
}
}