Skip to content

Commit

Permalink
Enforce server max packet (#121)
Browse files Browse the repository at this point in the history
* Enforce Server Maximum Packet Size on client read
* Fix tests
  • Loading branch information
mochi-co authored Dec 16, 2022
1 parent 88861c2 commit d8f28cb
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 2 deletions.
4 changes: 4 additions & 0 deletions clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ func (cl *Client) ReadFixedHeader(fh *packets.FixedHeader) error {
return err
}

if cl.ops.capabilities.MaximumPacketSize > 0 && uint32(fh.Remaining+1) > cl.ops.capabilities.MaximumPacketSize {
return packets.ErrPacketTooLarge // [MQTT-3.2.2-15]
}

atomic.AddInt64(&cl.ops.info.BytesReceived, int64(bu+1))
return nil
}
Expand Down
16 changes: 16 additions & 0 deletions clients_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,22 @@ func TestClientReadFixedHeaderDecodeError(t *testing.T) {
require.Error(t, err)
}

func TestClientReadFixedHeaderPacketOversized(t *testing.T) {
cl, r, _ := newTestClient()
cl.ops.capabilities.MaximumPacketSize = 2
defer cl.Stop(errClientStop)

go func() {
r.Write(packets.TPacketData[packets.Publish].Get(packets.TPublishQos1Dup).RawBytes)
r.Close()
}()

fh := new(packets.FixedHeader)
err := cl.ReadFixedHeader(fh)
require.Error(t, err)
require.ErrorIs(t, err, packets.ErrPacketTooLarge)
}

func TestClientReadFixedHeaderReadEOF(t *testing.T) {
cl, r, _ := newTestClient()
defer cl.Stop(errClientStop)
Expand Down
7 changes: 5 additions & 2 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1126,12 +1126,15 @@ func (s *Server) DisconnectClient(cl *Client, code packets.Code) error {

// We already have a code we are using to disconnect the client, so we are not
// interested if the write packet fails due to a closed connection (as we are closing it).
_ = cl.WritePacket(out)
err := cl.WritePacket(out)
if !s.Options.Capabilities.Compatibilities.PassiveClientDisconnect {
cl.Stop(code)
if code.Code >= packets.ErrUnspecifiedError.Code {
return code
}
}

return code
return err
}

// publishSysTopics publishes the current values to the server $SYS topics.
Expand Down
15 changes: 15 additions & 0 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2291,6 +2291,21 @@ func TestServerRecievePacketDisconnectClientZeroNonZero(t *testing.T) {
require.Equal(t, packets.TPacketData[packets.Disconnect].Get(packets.TDisconnectZeroNonZeroExpiry).RawBytes, buf)
}

func TestServerRecievePacketDisconnectClient(t *testing.T) {
s := newServer()
cl, r, w := newTestClient()

go func() {
err := s.DisconnectClient(cl, packets.CodeDisconnect)
require.NoError(t, err)
w.Close()
}()

buf, err := io.ReadAll(r)
require.NoError(t, err)
require.Equal(t, packets.TPacketData[packets.Disconnect].Get(packets.TDisconnect).RawBytes, buf)
}

func TestServerProcessPacketDisconnect(t *testing.T) {
s := newServer()
cl, _, _ := newTestClient()
Expand Down

0 comments on commit d8f28cb

Please sign in to comment.