func TestSessionPublishAckqueue(t *testing.T) { sess := &Session{} cmsg := newConnectMessage() err := sess.Init(cmsg) require.NoError(t, err) for i := 0; i < 12; i++ { msg := newPublishMessage(uint16(i), 1) sess.Pub1ack.Wait(msg, nil) } require.Equal(t, 12, sess.Pub1ack.len()) ack1 := message.NewPubackMessage() ack1.SetPacketId(1) sess.Pub1ack.Ack(ack1) acked := sess.Pub1ack.Acked() require.Equal(t, 0, len(acked)) ack0 := message.NewPubackMessage() ack0.SetPacketId(0) sess.Pub1ack.Ack(ack0) acked = sess.Pub1ack.Acked() require.Equal(t, 2, len(acked)) }
func TestAckQueueOutOfOrder(t *testing.T) { q := newAckqueue(5) require.Equal(t, 8, q.cap()) for i := 0; i < 12; i++ { msg := newPublishMessage(uint16(i), 1) q.Wait(msg, nil) } require.Equal(t, 12, q.len()) ack1 := message.NewPubackMessage() ack1.SetPacketId(1) q.Ack(ack1) acked := q.Acked() require.Equal(t, 0, len(acked)) ack0 := message.NewPubackMessage() ack0.SetPacketId(0) q.Ack(ack0) acked = q.Acked() require.Equal(t, 2, len(acked)) }
// For PUBLISH message, we should figure out what QoS it is and process accordingly // If QoS == 0, we should just take the next step, no ack required // If QoS == 1, we should send back PUBACK, then take the next step // If QoS == 2, we need to put it in the ack queue, send back PUBREC func (this *service) processPublish(msg *message.PublishMessage) error { switch msg.QoS() { case message.QosExactlyOnce: this.sess.Pub2in.Wait(msg, nil) resp := message.NewPubrecMessage() resp.SetPacketId(msg.PacketId()) _, err := this.writeMessage(resp) return err case message.QosAtLeastOnce: resp := message.NewPubackMessage() resp.SetPacketId(msg.PacketId()) if _, err := this.writeMessage(resp); err != nil { return err } return this.onPublish(msg) case message.QosAtMostOnce: return this.onPublish(msg) } return fmt.Errorf("(%s) invalid message QoS %d.", this.cid(), msg.QoS()) }