// Receive UDP packets, decode them, and output them // The packet format is (by byte): flags, group, node_id, kind, data... func (u *UDPGateway) Receiver() { for { glog.V(2).Infoln("******************************") pkt := make([]byte, 1600) pktLen, pktSrc, err := u.sock.ReadFromUDP(pkt) if err != nil { glog.Warning("UDP error: " + err.Error()) continue } if pktLen < 3 { glog.Infof("UDP: got too short a packet (%d) from %v", pktLen, pktSrc) continue } if pktLen > 66+3 { glog.Infof("UDP: got too long a packet (%d) from %v", pktLen, pktSrc) continue } // got a reasonable packet data := pkt[0:pktLen] flags := data[0] groupId := data[1] nodeId := data[2] // Record the groupId -> addr mapping _ = u.groupMap.saveGroupToAddr(groupId, pktSrc) switch flags { // CTL + ACK + DST -> boot protocol pairing request // I.e: a node sends us its HW ID and we reply with groupId/nodeId/nodeType case 8: u.handlePairingRequest(pktSrc, groupId, nodeId, data) // CTL + ACK -> boot protocol upgrade or download request // I.e.: a node asks for the software Id & checksum or downloads a chunk case 5: switch pktLen { case UpgradeRequestLen + 3: u.handleUpgradeRequest(pktSrc, groupId, nodeId, data) case DownloadRequestLen + 3: u.handleDownloadRequest(pktSrc, groupId, nodeId, data) default: glog.Warningf(" Incorrect length=%d (!= %d)", pktLen, PairingRequestLen+3) } // Special packet to log from UDP GW itself case 9: glog.Infof("UDP-GW %d: %s", groupId, string(data[3:])) m := gears.RFMessage{ Group: groupId, Node: nodeId, At: time.Now().UnixNano() / 1000000, Kind: 2, // LOG module Data: append([]byte("GW "), data[3:]...), } u.Recv <- m // Standard data packet, produce a Message case 0, 1: m := gears.RFMessage{ Group: groupId, Node: nodeId, At: time.Now().UnixNano() / 1000000, } if nodeId == 31 && len(m.Data)&1 == 0 { // hack to handle the fact that the early versions of the UDP GW node // don't use a _kind_ byte in the messages m.Kind = 8 // GW_RSSI_MODULE m.Data = data[3:] } else if pktLen > 3 { m.Kind = data[3] m.Data = data[4:] } else { m.Data = data[3:] } glog.Infof("UDP Recv: %s len=%d", m.RfTag(), pktLen) glog.V(4).Infof(" src=%v Pkt=%+v", pktSrc, m.Data[0:min(len(m.Data), 10)]) // If an ACK is requested we should send that asap if flags&1 != 0 { u.sendPacket(groupId, nodeId, 0x6, []byte{}) } // Now process what we got u.Recv <- m } } }