Exemple #1
0
func abstractConnCountersTest(t *testing.T, protocol string) {
	conn2, done := connectionPair(protocol, func(conn1 Conn) {
		pkt, err := conn1.Receive()
		assert.NoError(t, err)
		assert.Equal(t, int64(pkt.Len()), conn1.BytesRead())

		pkt2 := packet.NewConnackPacket()
		conn1.Send(pkt2)
		assert.Equal(t, int64(pkt2.Len()), conn1.BytesWritten())

		err = conn1.Close()
		assert.NoError(t, err)
	})

	pkt := packet.NewConnectPacket()
	conn2.Send(pkt)
	assert.Equal(t, int64(pkt.Len()), conn2.BytesWritten())

	pkt2, err := conn2.Receive()
	assert.NoError(t, err)
	assert.Equal(t, int64(pkt2.Len()), conn2.BytesRead())

	err = conn2.Close()
	assert.NoError(t, err)

	<-done
}
Exemple #2
0
func abstractConnBufferedSendTest(t *testing.T, protocol string) {
	conn2, done := connectionPair(protocol, func(conn1 Conn) {
		pkt, err := conn1.Receive()
		assert.Equal(t, pkt.Type(), packet.CONNECT)
		assert.NoError(t, err)

		err = conn1.BufferedSend(packet.NewConnackPacket())
		assert.NoError(t, err)

		pkt, err = conn1.Receive()
		assert.Nil(t, pkt)
		assert.Equal(t, ConnectionClose, toError(err).Code())
	})

	err := conn2.BufferedSend(packet.NewConnectPacket())
	assert.NoError(t, err)

	pkt, err := conn2.Receive()
	assert.Equal(t, pkt.Type(), packet.CONNACK)
	assert.NoError(t, err)

	err = conn2.Close()
	assert.NoError(t, err)

	<-done
}
Exemple #3
0
func abstractConnSendAndCloseTest(t *testing.T, protocol string) {
	wait := make(chan struct{})

	conn2, done := connectionPair(protocol, func(conn1 Conn) {
		err := conn1.Send(packet.NewConnectPacket())
		assert.NoError(t, err)

		err = conn1.Close()
		assert.NoError(t, err)

		close(wait)
	})

	<-wait

	pkt, err := conn2.Receive()
	assert.Equal(t, pkt.Type(), packet.CONNECT)
	assert.NoError(t, err)

	pkt, err = conn2.Receive()
	assert.Nil(t, pkt)
	assert.Equal(t, ConnectionClose, toError(err).Code())

	<-done
}
Exemple #4
0
func abstractConnBufferedSendAfterCloseTest(t *testing.T, protocol string) {
	conn2, done := connectionPair(protocol, func(conn1 Conn) {
		err := conn1.Close()
		assert.NoError(t, err)
	})

	pkt, err := conn2.Receive()
	assert.Nil(t, pkt)
	assert.Equal(t, ConnectionClose, toError(err).Code())

	err = conn2.BufferedSend(packet.NewConnectPacket())
	assert.NoError(t, err)

	<-time.After(2 * flushTimeout)

	err = conn2.BufferedSend(packet.NewConnectPacket())
	assert.Equal(t, NetworkError, toError(err).Code())

	<-done
}
Exemple #5
0
func abstractConnCloseWhileSendTest(t *testing.T, protocol string) {
	conn2, done := connectionPair(protocol, func(conn1 Conn) {
		err := conn1.Send(packet.NewConnectPacket())
		assert.NoError(t, err)

		err = conn1.Close()
		assert.NoError(t, err)
	})

	pkt, err := conn2.Receive()
	assert.NotNil(t, pkt)
	assert.NoError(t, err)

	for {
		// keep writing
		err := conn2.Send(packet.NewConnectPacket())
		if err != nil {
			assert.Equal(t, ConnectionClose, toError(err).Code())
			break
		}
	}

	<-done
}
Exemple #6
0
func abstractConnReadLimitTest(t *testing.T, protocol string) {
	conn2, done := connectionPair(protocol, func(conn1 Conn) {
		conn1.SetReadLimit(1)

		pkt, err := conn1.Receive()
		assert.Nil(t, pkt)
		assert.Equal(t, NetworkError, toError(err).Code())
		assert.Equal(t, ErrReadLimitExceeded, toError(err).Err())
	})

	err := conn2.Send(packet.NewConnectPacket())
	assert.NoError(t, err)

	pkt, err := conn2.Receive()
	assert.Nil(t, pkt)
	assert.Equal(t, ConnectionClose, toError(err).Code())

	<-done
}
Exemple #7
0
func abstractServerTest(t *testing.T, protocol string) {
	port := tools.NewPort()

	server, err := testLauncher.Launch(port.URL(protocol))
	require.NoError(t, err)

	go func() {
		conn1, err := server.Accept()
		require.NoError(t, err)

		pkt, err := conn1.Receive()
		assert.Equal(t, pkt.Type(), packet.CONNECT)
		assert.NoError(t, err)

		err = conn1.Send(packet.NewConnackPacket())
		assert.NoError(t, err)

		pkt, err = conn1.Receive()
		assert.Nil(t, pkt)
		assert.Equal(t, ConnectionClose, toError(err).Code())
	}()

	conn2, err := testDialer.Dial(port.URL(protocol))
	require.NoError(t, err)

	err = conn2.Send(packet.NewConnectPacket())
	assert.NoError(t, err)

	pkt, err := conn2.Receive()
	assert.Equal(t, pkt.Type(), packet.CONNACK)
	assert.NoError(t, err)

	err = conn2.Close()
	assert.NoError(t, err)

	err = server.Close()
	assert.NoError(t, err)
}
Exemple #8
0
// Connect opens the connection to the broker and sends a ConnectPacket. It will
// return a ConnectFuture that gets completed once a ConnackPacket has been
// received. If the ConnectPacket couldn't be transmitted it will return an error.
func (c *Client) Connect(config *Config) (*ConnectFuture, error) {
	if config == nil {
		panic("No config specified")
	}

	c.mutex.Lock()
	defer c.mutex.Unlock()

	// save config
	c.config = config

	// check if already connecting
	if c.state.get() >= clientConnecting {
		return nil, ErrClientAlreadyConnecting
	}

	// parse url
	urlParts, err := url.ParseRequestURI(config.BrokerURL)
	if err != nil {
		return nil, err
	}

	// check client id
	if !config.CleanSession && config.ClientID == "" {
		return nil, ErrClientMissingID
	}

	// parse keep alive
	keepAlive, err := time.ParseDuration(config.KeepAlive)
	if err != nil {
		return nil, err
	}

	// allocate and initialize tracker
	c.tracker = newTracker(keepAlive)

	// dial broker (with custom dialer if present)
	if config.Dialer != nil {
		c.conn, err = config.Dialer.Dial(config.BrokerURL)
		if err != nil {
			return nil, err
		}
	} else {
		c.conn, err = transport.Dial(config.BrokerURL)
		if err != nil {
			return nil, err
		}
	}

	// set to connecting as from this point the client cannot be reused
	c.state.set(clientConnecting)

	// from now on the connection has been used and we have to close the
	// connection and cleanup on any subsequent error

	// save clean
	c.clean = config.CleanSession

	// reset store
	if c.clean {
		err = c.Session.Reset()
		if err != nil {
			return nil, c.cleanup(err, true, false)
		}
	}

	// allocate packet
	connect := packet.NewConnectPacket()
	connect.ClientID = config.ClientID
	connect.KeepAlive = uint16(keepAlive.Seconds())
	connect.CleanSession = config.CleanSession

	// check for credentials
	if urlParts.User != nil {
		connect.Username = urlParts.User.Username()
		connect.Password, _ = urlParts.User.Password()
	}

	// set will
	connect.Will = config.WillMessage

	// create new ConnackFuture
	c.connectFuture = &ConnectFuture{}
	c.connectFuture.initialize()

	// send connect packet
	err = c.send(connect, false)
	if err != nil {
		return nil, c.cleanup(err, false, false)
	}

	// start process routine
	c.tomb.Go(c.processor)

	// start keep alive if greater than zero
	if keepAlive > 0 {
		c.tomb.Go(c.pinger)
	}

	return c.connectFuture, nil
}
Exemple #9
0
func connectPacket() *packet.ConnectPacket {
	pkt := packet.NewConnectPacket()
	pkt.CleanSession = true
	pkt.KeepAlive = 30
	return pkt
}
Exemple #10
0
func Example() {
	// launch server
	server, err := Launch("tcp://localhost:1337")
	if err != nil {
		panic(err)
	}

	go func() {
		// accept next incoming connection
		conn, err := server.Accept()
		if err != nil {
			panic(err)
		}

		// receive next packet
		pkt, err := conn.Receive()
		if err != nil {
			panic(err)
		}

		// check packet type
		if _, ok := pkt.(*packet.ConnectPacket); ok {
			// send a connack packet
			err = conn.Send(packet.NewConnackPacket())
			if err != nil {
				panic(err)
			}
		} else {
			panic("unexpected packet")
		}
	}()

	// dial to server
	conn, err := Dial("tcp://localhost:1337")
	if err != nil {
		panic(err)
	}

	// send connect packet
	err = conn.Send(packet.NewConnectPacket())
	if err != nil {
		panic(err)
	}

	// receive next packet
	pkt, err := conn.Receive()
	if err != nil {
		panic(err)
	}

	// check packet type
	if connackPacket, ok := pkt.(*packet.ConnackPacket); ok {
		fmt.Println(connackPacket)

		// close connection
		err = conn.Close()
		if err != nil {
			panic(err)
		}
	} else {
		panic("unexpected packet")
	}

	// close server
	err = server.Close()
	if err != nil {
		panic(err)
	}

	// Output:
	// <ConnackPacket SessionPresent=false ReturnCode=0>
}