Skip to content

Commit

Permalink
packet.go: Significantly less allocations in packet and acknowledgeme…
Browse files Browse the repository at this point in the history
…nt writing/reading.
  • Loading branch information
Sandertv committed Apr 7, 2024
1 parent 3f5d72f commit a9f32dd
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 165 deletions.
56 changes: 44 additions & 12 deletions binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package raknet

import (
"bytes"
"fmt"
"io"
)

// uint24 represents an integer existing out of 3 bytes. It is actually a
Expand All @@ -11,20 +11,52 @@ type uint24 uint32

// readUint24 reads 3 bytes from the buffer passed and combines it into a
// uint24. If there were no 3 bytes to read, an error is returned.
func readUint24(b *bytes.Buffer) (uint24, error) {
ba, _ := b.ReadByte()
bb, _ := b.ReadByte()
bc, err := b.ReadByte()
if err != nil {
return 0, fmt.Errorf("error reading uint24: %v", err)
func readUint24(buf *bytes.Buffer) (uint24, error) {
b := make([]byte, 3)
if _, err := buf.Read(b); err != nil {
return 0, io.ErrUnexpectedEOF
}
return uint24(ba) | (uint24(bb) << 8) | (uint24(bc) << 16), nil
return uint24(b[0]) | (uint24(b[1]) << 8) | (uint24(b[2]) << 16), nil
}

func readUint16(buf *bytes.Buffer) (uint16, error) {
b := make([]byte, 2)
if _, err := buf.Read(b); err != nil {
return 0, io.ErrUnexpectedEOF
}
return (uint16(b[0]) << 8) | uint16(b[1]), nil
}

func readUint32(buf *bytes.Buffer) (uint32, error) {
b := make([]byte, 4)
if _, err := buf.Read(b); err != nil {
return 0, io.ErrUnexpectedEOF
}
return (uint32(b[0]) << 24) | (uint32(b[1]) << 16) | (uint32(b[2]) << 8) | uint32(b[3]), nil
}

// writeUint24 writes a uint24 to the buffer passed as 3 bytes. If not
// successful, an error is returned.
func writeUint24(b *bytes.Buffer, value uint24) {
b.WriteByte(byte(value))
b.WriteByte(byte(value >> 8))
b.WriteByte(byte(value >> 16))
func writeUint24(b *bytes.Buffer, v uint24) {
b.Write([]byte{
byte(v),
byte(v >> 8),
byte(v >> 16),
})
}

func writeUint16(b *bytes.Buffer, v uint16) {
b.Write([]byte{
byte(v >> 8),
byte(v),
})
}

func writeUint32(b *bytes.Buffer, v uint32) {
b.Write([]byte{
byte(v >> 24),
byte(v >> 16),
byte(v >> 8),
byte(v),
})
}
9 changes: 3 additions & 6 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,14 +526,14 @@ func (conn *Conn) receiveDatagram(b *bytes.Buffer) error {
func (conn *Conn) handleDatagram(b *bytes.Buffer) error {
for b.Len() > 0 {
if err := conn.pk.read(b); err != nil {
return fmt.Errorf("error decoding datagram packet: %v", err)
return fmt.Errorf("handle datagram: decode packet: %v", err)
}
handle := conn.receivePacket
if conn.pk.split {
handle = conn.receiveSplitPacket
}
if err := handle(conn.pk); err != nil {
return fmt.Errorf("error handling packet in datagram: %v", err)
return fmt.Errorf("handle datagram: handle packet: %v", err)
}
}
return nil
Expand Down Expand Up @@ -732,10 +732,7 @@ func (conn *Conn) sendAcknowledgement(packets []uint24, bitflag byte, buf *bytes

for len(ack.packets) != 0 {
buf.WriteByte(bitflag | bitFlagDatagram)
n, err := ack.write(buf, conn.mtu)
if err != nil {
panic(fmt.Sprintf("error encoding ACK packet: %v", err))
}
n := ack.write(buf, conn.mtu)
// We managed to write n packets in the ACK with this MTU size, write
// the next of the packets in a new ACK.
ack.packets = ack.packets[n:]
Expand Down
9 changes: 9 additions & 0 deletions internal/message/open_connection_request_1.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ type OpenConnectionRequest1 struct {
MaximumSizeNotDropped uint16
}

var cachedOCR1 = map[uint16][]byte{}

func (pk *OpenConnectionRequest1) MarshalBinary() (data []byte, err error) {
if b, ok := cachedOCR1[pk.MaximumSizeNotDropped]; ok {
// Cache OpenConnectionRequest1 data. These are independent of any other
// inputs and are pretty big.
return b, nil
}
b := make([]byte, pk.MaximumSizeNotDropped-20-8) // IP Header: 20 bytes, UDP Header: 8 bytes.
b[0] = IDOpenConnectionRequest1
copy(b[1:], unconnectedMessageSequence[:])
b[17] = pk.Protocol

cachedOCR1[pk.MaximumSizeNotDropped] = b
return b, nil
}

Expand Down
Loading

0 comments on commit a9f32dd

Please sign in to comment.