Example #1
0
func TestClient_Connect_restoreSession(t *testing.T) {
	cli := New(&Options{
		ErrorHandler: func(_ error) {},
	})

	cli.sess = newSession(false, []byte("cliendID"))

	publish, err := packet.NewPUBLISH(&packet.PUBLISHOptions{
		PacketID: 1,
	})
	if err != nil {
		nilErrorExpected(t, err)
	}

	cli.sess.sendingPackets[1] = publish

	pubrel, err := packet.NewPUBREL(&packet.PUBRELOptions{
		PacketID: 2,
	})
	if err != nil {
		nilErrorExpected(t, err)
	}

	cli.sess.sendingPackets[2] = pubrel

	cli.sess.sendingPackets[3] = packet.NewPINGREQ()

	err = cli.Connect(&ConnectOptions{
		Network: "tcp",
		Address: testAddress,
	})
	if err != nil {
		nilErrorExpected(t, err)
	}
}
Example #2
0
// sendPackets sends Packets to the Server.
func (cli *Client) sendPackets(keepAlive time.Duration, pingrespTimeout time.Duration) {
	defer func() {
		// Lock for reading and updating pingrespcs.
		cli.conn.muPINGRESPs.Lock()

		// Close the channels which handle a signal which
		// notifies the arrival of the PINGREQ Packet.
		for _, pingresp := range cli.conn.pingresps {
			close(pingresp)
		}

		// Initialize pingrespcs
		cli.conn.pingresps = make([]chan struct{}, 0)

		// Unlock.
		cli.conn.muPINGRESPs.Unlock()

		cli.conn.wg.Done()
	}()

	for {
		var keepAlivec <-chan time.Time

		if keepAlive > 0 {
			keepAlivec = time.After(keepAlive * time.Second)
		}

		select {
		case p := <-cli.conn.send:
			// Lock for sending the Packet.
			cli.muConn.RLock()

			// Send the Packet to the Server.
			err := cli.send(p)

			// Unlock.
			cli.muConn.RUnlock()

			if err != nil {
				// Handle the error and disconnect the Network Connection.
				cli.handleErrorAndDisconn(err)

				// End this function.
				return
			}
		case <-keepAlivec:
			// Lock for sending the Packet.
			cli.muConn.RLock()

			// Send a PINGREQ Packet to the Server.
			err := cli.send(packet.NewPINGREQ())

			// Unlock.
			cli.muConn.RUnlock()

			if err != nil {
				// Handle the error and disconnect the Network Connection.
				cli.handleErrorAndDisconn(err)

				// End this function.
				return
			}

			// Create a channel which handles the signal to notify the arrival of
			// the PINGRESP Packet.
			pingresp := make(chan struct{})

			// Lock for appending the channel to pingrespcs.
			cli.conn.muPINGRESPs.Lock()

			// Append the channel to pingrespcs.
			cli.conn.pingresps = append(cli.conn.pingresps, pingresp)

			// Unlock.
			cli.conn.muPINGRESPs.Unlock()

			// Launch a goroutine which waits for receiving the PINGRESP Packet.
			cli.conn.wg.Add(1)
			go cli.waitPacket(pingresp, pingrespTimeout, ErrPINGRESPTimeout)
		case <-cli.conn.sendEnd:
			// End this function.
			return
		}
	}
}