func TestClientKeepAliveTimeout(t *testing.T) { connect := connectPacket() connect.KeepAlive = 0 pingreq := packet.NewPingreqPacket() broker := tools.NewFlow(). Receive(connect). Send(connackPacket()). Receive(pingreq). End() done, port := fakeBroker(t, broker) wait := make(chan struct{}) c := New() c.Callback = func(msg *packet.Message, err error) { assert.Nil(t, msg) assert.Equal(t, ErrClientMissingPong, err) close(wait) } config := NewConfig("tcp://localhost:" + port) config.KeepAlive = "5ms" future, err := c.Connect(config) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) <-wait <-done }
// manages the sending of ping packets to keep the connection alive func (c *Client) pinger() error { for { // get current window window := c.tracker.window() // check if ping is due if window < 0 { // check if a pong has already been sent if c.tracker.pending() { return c.die(ErrClientMissingPong, true) } // send pingreq packet err := c.send(packet.NewPingreqPacket(), true) if err != nil { return c.die(err, false) } // save ping attempt c.tracker.ping() } else { // log keep alive delay if c.Logger != nil { c.Logger(fmt.Sprintf("Delay KeepAlive by %s", window.String())) } } select { case <-c.tomb.Dying(): return tomb.ErrDying case <-time.After(window): continue } } }
func TestClientKeepAlive(t *testing.T) { connect := connectPacket() connect.KeepAlive = 0 pingreq := packet.NewPingreqPacket() pingresp := packet.NewPingrespPacket() broker := tools.NewFlow(). Receive(connect). Send(connackPacket()). Receive(pingreq). Send(pingresp). Receive(pingreq). Send(pingresp). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) c := New() c.Callback = errorCallback(t) var reqCounter int32 var respCounter int32 c.Logger = func(message string) { if strings.Contains(message, "Pingreq") { atomic.AddInt32(&reqCounter, 1) } else if strings.Contains(message, "Pingresp") { atomic.AddInt32(&respCounter, 1) } } config := NewConfig("tcp://localhost:" + port) config.KeepAlive = "100ms" future, err := c.Connect(config) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) <-time.After(250 * time.Millisecond) err = c.Disconnect() assert.NoError(t, err) assert.Equal(t, int32(2), atomic.LoadInt32(&reqCounter)) assert.Equal(t, int32(2), atomic.LoadInt32(&respCounter)) <-done }