mirror of
https://github.com/mochi-mqtt/server.git
synced 2025-10-29 10:42:38 +08:00
Process Publish+Recv
This commit is contained in:
106
mqtt.go
106
mqtt.go
@@ -245,42 +245,6 @@ DONE:
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeClient writes packets to a client connection.
|
|
||||||
func (s *Server) writeClient(cl *client, pk packets.Packet) error {
|
|
||||||
|
|
||||||
// Ensure Writer is open.
|
|
||||||
if cl.p.W == nil {
|
|
||||||
return ErrConnectionClosed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode packet to a pooled byte buffer.
|
|
||||||
buf := s.buffers.Get()
|
|
||||||
defer s.buffers.Put(buf)
|
|
||||||
err := pk.Encode(buf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write packet to client.
|
|
||||||
_, err = buf.WriteTo(cl.p.W)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cl.p.W.Flush()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh deadline to keep the connection alive.
|
|
||||||
cl.p.RefreshDeadline(cl.keepalive)
|
|
||||||
|
|
||||||
// Log $SYS stats.
|
|
||||||
// @TODO ...
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// processPacket processes an inbound packet for a client.
|
// processPacket processes an inbound packet for a client.
|
||||||
func (s *Server) processPacket(cl *client, pk packets.Packet) error {
|
func (s *Server) processPacket(cl *client, pk packets.Packet) error {
|
||||||
log.Println("PROCESSING PACKET", cl, pk)
|
log.Println("PROCESSING PACKET", cl, pk)
|
||||||
@@ -329,18 +293,29 @@ func (s *Server) processPacket(cl *client, pk packets.Packet) error {
|
|||||||
log.Println(client, id, qos)
|
log.Println(client, id, qos)
|
||||||
|
|
||||||
// Make a copy of the packet to send to client.
|
// Make a copy of the packet to send to client.
|
||||||
outgoing := msg.Copy()
|
out := msg.Copy()
|
||||||
log.Println(outgoing)
|
|
||||||
// If the subscriber has a higher qos, inherit it.
|
|
||||||
/* if subscriptions.qos > outgoing.Qos {
|
|
||||||
outgoing.Qos = subscriptions.qos
|
|
||||||
}
|
|
||||||
|
|
||||||
// If QoS byte is set, ensure the message has an id.
|
// If the client subscription has a higher qos, inherit it.
|
||||||
if outgoing.Qos > 0 && outgoing.PacketID == 0 {
|
if qos > out.Qos {
|
||||||
//outgoing.PacketID = client.nextPacketID()
|
out.Qos = qos
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
// If QoS byte is set, ensure the message has an id.
|
||||||
|
if out.Qos > 0 && out.PacketID == 0 {
|
||||||
|
out.PacketID = uint16(client.nextPacketID())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the publish packet out to the receiving client.
|
||||||
|
err := s.writeClient(client, out)
|
||||||
|
if err != nil {
|
||||||
|
s.closeClient(client, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If QoS byte is set, save as message to inflight index so we
|
||||||
|
// can track delivery.
|
||||||
|
if out.Qos > 0 {
|
||||||
|
// client.handleQOS(out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,6 +358,45 @@ func (s *Server) processPacket(cl *client, pk packets.Packet) error {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// writeClient writes packets to a client connection.
|
||||||
|
func (s *Server) writeClient(cl *client, pk packets.Packet) error {
|
||||||
|
|
||||||
|
// Ensure Writer is open.
|
||||||
|
if cl.p.W == nil {
|
||||||
|
return ErrConnectionClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode packet to a pooled byte buffer.
|
||||||
|
buf := s.buffers.Get()
|
||||||
|
defer s.buffers.Put(buf)
|
||||||
|
err := pk.Encode(buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("==", buf.Bytes())
|
||||||
|
|
||||||
|
// Write packet to client.
|
||||||
|
_, err = buf.WriteTo(cl.p.W)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cl.p.W.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Println("WRITE CLIENT", cl.id)
|
||||||
|
|
||||||
|
// Refresh deadline to keep the connection alive.
|
||||||
|
cl.p.RefreshDeadline(cl.keepalive)
|
||||||
|
|
||||||
|
// Log $SYS stats.
|
||||||
|
// @TODO ...
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// closeClient closes a client connection and publishes any LWT messages.
|
// closeClient closes a client connection and publishes any LWT messages.
|
||||||
func (s *Server) closeClient(cl *client, sendLWT bool) error {
|
func (s *Server) closeClient(cl *client, sendLWT bool) error {
|
||||||
|
|
||||||
|
|||||||
47
mqtt_test.go
47
mqtt_test.go
@@ -601,18 +601,23 @@ func TestServerProcessPacketPINGClose(t *testing.T) {
|
|||||||
func TestServerProcessPacketPublishOK(t *testing.T) {
|
func TestServerProcessPacketPublishOK(t *testing.T) {
|
||||||
s := New()
|
s := New()
|
||||||
|
|
||||||
|
// Sender
|
||||||
r, w := net.Pipe()
|
r, w := net.Pipe()
|
||||||
p := packets.NewParser(r, newBufioReader(r), newBufioWriter(w))
|
c1 := newClient(
|
||||||
c1 := newClient(p, &packets.ConnectPacket{ClientIdentifier: "c1"})
|
packets.NewParser(r, newBufioReader(r), newBufioWriter(w)),
|
||||||
|
&packets.ConnectPacket{ClientIdentifier: "c1"},
|
||||||
|
)
|
||||||
s.clients.add(c1)
|
s.clients.add(c1)
|
||||||
s.topics.Subscribe("a/b/c", c1.id, 0)
|
|
||||||
s.topics.Subscribe("a/+/c", c1.id, 1)
|
|
||||||
|
|
||||||
|
// Subscriber
|
||||||
r2, w2 := net.Pipe()
|
r2, w2 := net.Pipe()
|
||||||
p2 := packets.NewParser(r2, newBufioReader(r2), newBufioWriter(w2))
|
c2 := newClient(
|
||||||
c2 := newClient(p2, &packets.ConnectPacket{ClientIdentifier: "c2"})
|
packets.NewParser(r2, newBufioReader(r2), newBufioWriter(w2)),
|
||||||
|
&packets.ConnectPacket{ClientIdentifier: "c2"},
|
||||||
|
)
|
||||||
s.clients.add(c2)
|
s.clients.add(c2)
|
||||||
s.topics.Subscribe("a/b/+", c2.id, 0)
|
s.topics.Subscribe("a/b/+", c2.id, 0)
|
||||||
|
s.topics.Subscribe("a/+/c", c2.id, 1)
|
||||||
|
|
||||||
o := make(chan error, 2)
|
o := make(chan error, 2)
|
||||||
go func() {
|
go func() {
|
||||||
@@ -623,16 +628,34 @@ func TestServerProcessPacketPublishOK(t *testing.T) {
|
|||||||
TopicName: "a/b/c",
|
TopicName: "a/b/c",
|
||||||
Payload: []byte("hello"),
|
Payload: []byte("hello"),
|
||||||
})
|
})
|
||||||
|
r.Close()
|
||||||
|
w.Close()
|
||||||
|
w2.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
recv := make(chan []byte)
|
||||||
require.NoError(t, <-o)
|
go func() {
|
||||||
close(o)
|
buf, err := ioutil.ReadAll(r2)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
recv <- buf
|
||||||
|
}()
|
||||||
|
|
||||||
w.Close()
|
require.NoError(t, <-o)
|
||||||
r.Close()
|
require.Equal(t,
|
||||||
|
[]byte{
|
||||||
|
byte(packets.Publish<<4 | 2), 14, // Fixed header
|
||||||
|
0, 5, // Topic Name - LSB+MSB
|
||||||
|
'a', '/', 'b', '/', 'c', // Topic Name
|
||||||
|
0, 1, // packet id from qos=1
|
||||||
|
'h', 'e', 'l', 'l', 'o', // Payload
|
||||||
|
},
|
||||||
|
<-recv,
|
||||||
|
)
|
||||||
|
close(o)
|
||||||
|
close(recv)
|
||||||
r2.Close()
|
r2.Close()
|
||||||
w2.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServerProcessPacketPublishRetain(t *testing.T) {
|
func TestServerProcessPacketPublishRetain(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user