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 }
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 }
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 }
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 }
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 }
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 }
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) }
// 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 }
func connectPacket() *packet.ConnectPacket { pkt := packet.NewConnectPacket() pkt.CleanSession = true pkt.KeepAlive = 30 return pkt }
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> }