func statsMessage(topic string, stat int64) *packets.PublishPacket { p := packets.NewControlPacket(packets.Publish).(*packets.PublishPacket) p.Qos = 1 p.Retain = true p.Dup = false p.TopicName = topic p.Payload = []byte(fmt.Sprintf("%v", stat)) return p }
func (c *incomingConn) reader() { var err error var zeroTime time.Time var m packets.ControlPacket for { if c.KeepaliveTimer > 0 { c.conn.SetReadDeadline(time.Now().Add(time.Duration(c.KeepaliveTimer) * time.Second)) } else { c.conn.SetReadDeadline(zeroTime) } m, err = packets.ReadPacket(c.conn) if err != nil { break } c.svr.stats.messageRecv() if c.svr.Dump { log.Printf("INFO: dump in: %T", m) } switch m := m.(type) { case *packets.ConnectPacket: rc := m.Validate() if rc != packets.Accepted { err = packets.ConnErrors[rc] log.Printf("ERROR: Connection refused for %v: %v", c.conn.RemoteAddr(), err) goto exit } // TODO: authorize // connack connack := packets.NewControlPacket(packets.Connack) connack.(*packets.ConnackPacket).ReturnCode = rc c.submit(connack) c.clientid = m.ClientIdentifier c.KeepaliveTimer = m.KeepaliveTimer c.connect = m // Disconnect existing connections. if existing := c.add(); existing != nil { disconnect := packets.NewControlPacket(packets.Disconnect) r := existing.submitSync(disconnect) r.waitTimeout(time.Second) } c.add() // Log in mosquitto format. clean := 0 if m.CleanSession { clean = 1 } log.Printf("INFO: New client connected from %v as %v (c%v, k%v).", c.conn.RemoteAddr(), c.clientid, clean, m.KeepaliveTimer) case *packets.PublishPacket: switch m.Qos { case 2: pr := packets.NewControlPacket(packets.Pubrec).(*packets.PubrecPacket) pr.PacketID = m.PacketID c.submit(pr) c.svr.subs.submit(c, m) case 1: c.svr.subs.submit(c, m) pa := packets.NewControlPacket(packets.Puback).(*packets.PubackPacket) pa.PacketID = m.PacketID c.submit(pa) case 0: c.svr.subs.submit(c, m) } case *packets.PubackPacket: case *packets.PubrecPacket: prel := packets.NewControlPacket(packets.Pubrel).(*packets.PubrelPacket) prel.PacketID = m.PacketID c.submit(prel) case *packets.PubrelPacket: pc := packets.NewControlPacket(packets.Pubcomp).(*packets.PubcompPacket) pc.PacketID = m.PacketID c.submit(pc) case *packets.PubcompPacket: case *packets.PingreqPacket: pr := packets.NewControlPacket(packets.Pingresp) c.submit(pr) case *packets.SubscribePacket: for i := 0; i < len(m.Topics); i++ { topic := m.Topics[i] c.svr.subs.add(topic, c) } suback := packets.NewControlPacket(packets.Suback).(*packets.SubackPacket) suback.PacketID = m.PacketID suback.GrantedQoss = m.Qoss c.submit(suback) for _, topic := range m.Topics { c.svr.subs.sendRetain(topic, c) } case *packets.UnsubscribePacket: unsuback := packets.NewControlPacket(packets.Unsuback).(*packets.UnsubackPacket) unsuback.PacketID = m.PacketID for _, t := range m.Topics { c.svr.subs.unsub(t, c) } c.submit(unsuback) case *packets.DisconnectPacket: goto exit default: err = fmt.Errorf("unknown msg type %T", m) goto exit } } exit: if err != nil { if err != io.EOF && !strings.Contains(err.Error(), "use of closed") { log.Printf("ERROR: failed to reader - %s", err) } if c.connect.WillFlag { pub := packets.NewControlPacket(packets.Publish).(*packets.PublishPacket) pub.Qos = c.connect.WillQos pub.Retain = c.connect.WillRetain pub.TopicName = c.connect.WillTopic pub.Payload = c.connect.WillMessage c.svr.subs.submit(c, pub) } } c.del() c.svr.subs.unsubAll(c) c.svr.stats.clientDisconnect() c.conn.Close() close(c.stop) }