package coap import ( "net" "sparrow/pkg/server" "time" ) const ( // ResponseTimeout is the amount of time to wait for a // response. ResponseTimeout = time.Second * 2 // ResponseRandomFactor is a multiplier for response backoff. ResponseRandomFactor = 1.5 // MaxRetransmit is the maximum number of times a message will // be retransmitted. MaxRetransmit = 4 maxPktlen = 1500 ) type Handler interface { ServeCOAP(l *net.UDPConn, a *net.UDPAddr, m Message) Message } type Manager struct { rh funcHandler } func NewManager() *Manager { return &Manager{} } func (m *Manager) FuncHandler(f func(l *net.UDPConn, a *net.UDPAddr, m Message) Message) Handler { m.rh = f return funcHandler(f) } type funcHandler func(l *net.UDPConn, a *net.UDPAddr, m Message) Message func (f funcHandler) ServeCOAP(l *net.UDPConn, a *net.UDPAddr, m Message) Message { return f(l, a, m) } func (m *Manager) Handler(conn *net.UDPConn) { buf := make([]byte, maxPktlen) for { nr, addr, err := conn.ReadFromUDP(buf) if err != nil { if neterr, ok := err.(net.Error); ok && (neterr.Temporary() || neterr.Timeout()) { time.Sleep(5 * time.Millisecond) continue } } tmp := make([]byte, nr) copy(tmp, buf) go m.handlerPacket(conn, tmp, addr) } } func (m *Manager) handlerPacket(l *net.UDPConn, data []byte, a *net.UDPAddr) { msg, err := ParseMessage(data) if err != nil { server.Log.Error(err) } rv := m.rh.ServeCOAP(l, a, msg) if rv != nil { Transmit(l, a, msg) } } func Transmit(l *net.UDPConn, a *net.UDPAddr, m Message) error { d, err := m.Encode() if err != nil { return err } if a == nil { _, err = l.Write(d) } else { _, err = l.WriteTo(d, a) } return err } // Receive a message. func Receive(l *net.UDPConn, buf []byte) (Message, error) { l.SetReadDeadline(time.Now().Add(ResponseTimeout)) nr, _, err := l.ReadFromUDP(buf) if err != nil { return &BaseMessage{}, err } return ParseMessage(buf[:nr]) }