diff --git a/respond/collector.go b/respond/collector.go index 6d2156b..d2cc54d 100644 --- a/respond/collector.go +++ b/respond/collector.go @@ -1,16 +1,11 @@ package respond import ( - "bytes" - "compress/flate" - "encoding/json" "fmt" - "io/ioutil" "net" "time" "github.com/bdlm/log" - "github.com/tidwall/gjson" "github.com/FreifunkBremen/yanic/data" "github.com/FreifunkBremen/yanic/database" @@ -74,7 +69,7 @@ func (coll *Collector) listenUDP(iface InterfaceConfig) { } } - multicastAddress := multicastAddressDefault + multicastAddress := MulticastAddressDefault if iface.MulticastAddress != "" { multicastAddress = iface.MulticastAddress } @@ -88,7 +83,7 @@ func (coll *Collector) listenUDP(iface InterfaceConfig) { if err != nil { log.Panic(err) } - conn.SetReadBuffer(maxDataGramSize) + conn.SetReadBuffer(MaxDataGramSize) coll.connections = append(coll.connections, multicastConn{ Conn: conn, @@ -213,7 +208,7 @@ func (coll *Collector) SendPacket(destination net.IP) { func (coll *Collector) sendPacket(conn *net.UDPConn, destination net.IP) { addr := net.UDPAddr{ IP: destination, - Port: port, + Port: PortDefault, Zone: conn.LocalAddr().(*net.UDPAddr).Zone, } @@ -247,36 +242,6 @@ func (coll *Collector) parser() { } } -func (res *Response) parse(customFields []CustomFieldConfig) (*data.ResponseData, error) { - // Deflate - deflater := flate.NewReader(bytes.NewReader(res.Raw)) - defer deflater.Close() - - jsonData, err := ioutil.ReadAll(deflater) - if err != nil { - return nil, err - } - - // Unmarshal - rdata := &data.ResponseData{} - err = json.Unmarshal(jsonData, rdata) - - rdata.CustomFields = make(map[string]interface{}) - if !gjson.Valid(string(jsonData)) { - log.WithField("jsonData", jsonData).Info("JSON data is invalid") - } else { - jsonParsed := gjson.Parse(string(jsonData)) - for _, customField := range customFields { - field := jsonParsed.Get(customField.Path) - if field.Exists() { - rdata.CustomFields[customField.Name] = field.String() - } - } - } - - return rdata, err -} - func (coll *Collector) saveResponse(addr *net.UDPAddr, res *data.ResponseData) { // Search for NodeID var nodeID string @@ -328,7 +293,7 @@ func (coll *Collector) saveResponse(addr *net.UDPAddr, res *data.ResponseData) { } func (coll *Collector) receiver(conn *net.UDPConn) { - buf := make([]byte, maxDataGramSize) + buf := make([]byte, MaxDataGramSize) for { n, src, err := conn.ReadFromUDP(buf) diff --git a/respond/respond.go b/respond/respond.go index a8e3927..3bc6261 100644 --- a/respond/respond.go +++ b/respond/respond.go @@ -1,18 +1,28 @@ package respond import ( + "bytes" + "compress/flate" + "encoding/json" + "io" + "io/ioutil" "net" + + "github.com/bdlm/log" + "github.com/tidwall/gjson" + + "github.com/FreifunkBremen/yanic/data" ) const ( // default multicast group used by announced - multicastAddressDefault = "ff05:0:0:0:0:0:2:1001" + MulticastAddressDefault = "ff05:0:0:0:0:0:2:1001" // default udp port used by announced - port = 1001 + PortDefault = 1001 // maximum receivable size - maxDataGramSize = 8192 + MaxDataGramSize = 8192 ) // Response of the respond request @@ -20,3 +30,53 @@ type Response struct { Address *net.UDPAddr Raw []byte } + +func NewRespone(res *data.ResponseData, addr *net.UDPAddr) (*Response, error) { + buf := new(bytes.Buffer) + flater, err := flate.NewWriter(buf, flate.BestCompression) + if err != nil { + return nil, err + } + defer flater.Close() + + if err = json.NewEncoder(flater).Encode(res); err != nil { + return nil, err + } + + err = flater.Flush() + + return &Response{ + Raw: buf.Bytes(), + Address: addr, + }, err +} + +func (res *Response) parse(customFields []CustomFieldConfig) (*data.ResponseData, error) { + // Deflate + deflater := flate.NewReader(bytes.NewReader(res.Raw)) + defer deflater.Close() + + jsonData, err := ioutil.ReadAll(deflater) + if err != nil && err != io.ErrUnexpectedEOF { + return nil, err + } + + // Unmarshal + rdata := &data.ResponseData{} + err = json.Unmarshal(jsonData, rdata) + + rdata.CustomFields = make(map[string]interface{}) + if !gjson.Valid(string(jsonData)) { + log.WithField("jsonData", jsonData).Info("JSON data is invalid") + } else { + jsonParsed := gjson.Parse(string(jsonData)) + for _, customField := range customFields { + field := jsonParsed.Get(customField.Path) + if field.Exists() { + rdata.CustomFields[customField.Name] = field.String() + } + } + } + + return rdata, err +} diff --git a/respond/respond_test.go b/respond/respond_test.go new file mode 100644 index 0000000..73c0415 --- /dev/null +++ b/respond/respond_test.go @@ -0,0 +1,20 @@ +package respond + +import ( + "net" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewRespone(t *testing.T) { + assert := assert.New(t) + + addr, err := net.ResolveUDPAddr("udp6", "[fe80::2]:8080") + assert.NoError(err) + + data, err := NewRespone(nil, addr) + assert.NoError(err) + assert.Equal("[fe80::2]:8080", data.Address.String()) + assert.Equal([]uint8{0xca, 0x2b, 0xcd, 0xc9, 0xe1, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff}, data.Raw) +}