Skip to content

Commit e76728a

Browse files
committed
conn.go: Removed (half broken, useless) deadline methods and cleaned up logic in (re)sending.
1 parent 9df78e9 commit e76728a

File tree

6 files changed

+57
-90
lines changed

6 files changed

+57
-90
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ API used to listen for connections or connect to servers.
1010
## Getting started
1111

1212
### Prerequisites
13-
**As of go-raknet version 1.13.0, go-raknet requires at least Go 1.21**. Version 1.12.1 of go-raknet is
13+
**As of go-raknet version 1.14.0, go-raknet requires at least Go 1.22**. Version 1.12.1 of go-raknet is
1414
the last version of the library that supports Go 1.18 and above.
1515

1616
### Usage

binary.go

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ import (
99
// uint32, but is an alias for the sake of clarity.
1010
type uint24 uint32
1111

12+
// Inc increments a uint24 and returns the old value.
13+
func (u *uint24) Inc() (old uint24) {
14+
ret := *u
15+
*u += 1
16+
return ret
17+
}
18+
1219
// readUint24 reads 3 bytes from the buffer passed and combines it into a
1320
// uint24. If there were no 3 bytes to read, an error is returned.
1421
func readUint24(buf *bytes.Buffer) (uint24, error) {

conn.go

+37-84
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ package raknet
22

33
import (
44
"bytes"
5-
"context"
65
"encoding"
76
"errors"
87
"fmt"
98
"github.com/sandertv/go-raknet/internal/message"
109
"io"
1110
"net"
1211
"net/netip"
12+
"slices"
1313
"sync"
1414
"sync/atomic"
1515
"time"
@@ -85,11 +85,6 @@ type Conn struct {
8585
// datagram sequence number.
8686
retransmission *resendMap
8787

88-
// readDeadline is a channel that receives a time.Time after a specific
89-
// time. It is used to listen for timeouts in Read after calling
90-
// SetReadDeadline.
91-
readDeadline <-chan time.Time
92-
9388
lastActivity atomic.Pointer[time.Time]
9489
}
9590

@@ -111,8 +106,8 @@ func newConn(conn net.PacketConn, raddr net.Addr, mtu uint16, h connectionHandle
111106
packetQueue: newPacketQueue(),
112107
retransmission: newRecoveryQueue(),
113108
buf: bytes.NewBuffer(make([]byte, 0, mtu)),
114-
ackBuf: bytes.NewBuffer(make([]byte, 0, 256)),
115-
nackBuf: bytes.NewBuffer(make([]byte, 0, 256)),
109+
ackBuf: bytes.NewBuffer(make([]byte, 0, 128)),
110+
nackBuf: bytes.NewBuffer(make([]byte, 0, 64)),
116111
}
117112
t := time.Now()
118113
c.lastActivity.Store(&t)
@@ -142,34 +137,34 @@ func (conn *Conn) startTicking() {
142137
case t := <-ticker.C:
143138
i++
144139
conn.flushACKs()
145-
if i%2 == 0 {
146-
// Ping the other end periodically to prevent timeouts.
147-
_ = conn.send(&message.ConnectedPing{ClientTimestamp: timestamp()})
148-
}
149140
if i%3 == 0 {
150141
conn.checkResend(t)
151142
}
152-
if i%5 == 0 {
153-
conn.mu.Lock()
154-
if t.Sub(*conn.lastActivity.Load()) > time.Second*5+conn.retransmission.rtt()*2 {
155-
// No activity for too long: Start timeout.
156-
_ = conn.Close()
157-
}
158-
conn.mu.Unlock()
159-
}
160143
if unix := conn.closing.Load(); unix != 0 {
161144
before := acksLeft
162145
conn.mu.Lock()
163146
acksLeft = len(conn.retransmission.unacknowledged)
164147
conn.mu.Unlock()
148+
165149
if before != 0 && acksLeft == 0 {
166150
conn.closeImmediately()
167151
}
168-
169152
since := time.Since(time.Unix(unix, 0))
170-
if (acksLeft == 0 && since > time.Second) || since > time.Second*8 {
153+
if (acksLeft == 0 && since > time.Second) || since > time.Second*5 {
171154
conn.closeImmediately()
172155
}
156+
continue
157+
}
158+
if i%5 == 0 {
159+
// Ping the other end periodically to prevent timeouts.
160+
_ = conn.send(&message.ConnectedPing{ClientTimestamp: timestamp()})
161+
162+
conn.mu.Lock()
163+
if t.Sub(*conn.lastActivity.Load()) > time.Second*5+conn.retransmission.rtt()*2 {
164+
// No activity for too long: Start timeout.
165+
_ = conn.Close()
166+
}
167+
conn.mu.Unlock()
173168
}
174169
case <-conn.closed:
175170
return
@@ -227,7 +222,7 @@ func (conn *Conn) Write(b []byte) (n int, err error) {
227222
default:
228223
conn.mu.Lock()
229224
defer conn.mu.Unlock()
230-
n, err := conn.write(b)
225+
n, err = conn.write(b)
231226
return n, conn.error(err, "write")
232227
}
233228
}
@@ -239,8 +234,7 @@ func (conn *Conn) Write(b []byte) (n int, err error) {
239234
// Write, write will not lock.
240235
func (conn *Conn) write(b []byte) (n int, err error) {
241236
fragments := split(b, conn.effectiveMTU())
242-
orderIndex := conn.orderIndex
243-
conn.orderIndex++
237+
orderIndex := conn.orderIndex.Inc()
244238

245239
splitID := uint16(conn.splitID)
246240
if len(fragments) > 1 {
@@ -258,9 +252,7 @@ func (conn *Conn) write(b []byte) (n int, err error) {
258252
copy(pk.content, content)
259253

260254
pk.orderIndex = orderIndex
261-
pk.messageIndex = conn.messageIndex
262-
conn.messageIndex++
263-
255+
pk.messageIndex = conn.messageIndex.Inc()
264256
if pk.split = len(fragments) > 1; pk.split {
265257
// If there were more than one fragment, the pk was split, so we
266258
// need to make sure we set the appropriate fields.
@@ -284,13 +276,11 @@ func (conn *Conn) Read(b []byte) (n int, err error) {
284276
select {
285277
case pk := <-conn.packets:
286278
if len(b) < len(*pk) {
287-
err = conn.error(errBufferTooSmall, "read")
279+
err = conn.error(ErrBufferTooSmall, "read")
288280
}
289281
return copy(b, *pk), err
290282
case <-conn.closed:
291283
return 0, conn.error(net.ErrClosed, "read")
292-
case <-conn.readDeadline:
293-
return 0, conn.error(context.DeadlineExceeded, "read")
294284
}
295285
}
296286

@@ -303,8 +293,6 @@ func (conn *Conn) ReadPacket() (b []byte, err error) {
303293
return *pk, err
304294
case <-conn.closed:
305295
return nil, conn.error(net.ErrClosed, "read")
306-
case <-conn.readDeadline:
307-
return nil, conn.error(context.DeadlineExceeded, "read")
308296
}
309297
}
310298

@@ -338,35 +326,14 @@ func (conn *Conn) LocalAddr() net.Addr {
338326
return conn.conn.LocalAddr()
339327
}
340328

341-
// SetReadDeadline sets the read deadline of the connection. An error is
342-
// returned only if the time passed is before time.Now(). Calling
343-
// SetReadDeadline means the next Read call that exceeds the deadline will fail
344-
// and return an error. Setting the read deadline to the default value of
345-
// time.Time removes the deadline.
346-
func (conn *Conn) SetReadDeadline(t time.Time) error {
347-
if t.IsZero() {
348-
conn.readDeadline = make(chan time.Time)
349-
return nil
350-
}
351-
if t.Before(time.Now()) {
352-
panic(fmt.Errorf("read deadline cannot be before now"))
353-
}
354-
conn.readDeadline = time.After(time.Until(t))
355-
return nil
356-
}
329+
// SetReadDeadline is unimplemented. It always returns ErrNotSupported.
330+
func (conn *Conn) SetReadDeadline(time.Time) error { return ErrNotSupported }
357331

358-
// SetWriteDeadline has no behaviour. It is merely there to satisfy the
359-
// net.Conn interface.
360-
func (conn *Conn) SetWriteDeadline(time.Time) error {
361-
return nil
362-
}
332+
// SetWriteDeadline is unimplemented. It always returns ErrNotSupported.
333+
func (conn *Conn) SetWriteDeadline(time.Time) error { return ErrNotSupported }
363334

364-
// SetDeadline sets the deadline of the connection for both Read and Write.
365-
// SetDeadline is equivalent to calling both SetReadDeadline and
366-
// SetWriteDeadline.
367-
func (conn *Conn) SetDeadline(t time.Time) error {
368-
return conn.SetReadDeadline(t)
369-
}
335+
// SetDeadline is unimplemented. It always returns ErrNotSupported.
336+
func (conn *Conn) SetDeadline(time.Time) error { return ErrNotSupported }
370337

371338
// Latency returns a rolling average of rtt between the sending and the
372339
// receiving end of the connection. The rtt returned is updated continuously
@@ -541,26 +508,14 @@ func (conn *Conn) receiveSplitPacket(p *packet) error {
541508
}
542509
m[p.splitIndex] = p.content
543510

544-
size := 0
545-
for _, fragment := range m {
546-
if len(fragment) == 0 {
547-
// We haven't yet received all split fragments, so we cannot add the
548-
// packets together yet.
549-
return nil
550-
}
551-
// First we calculate the total size required to hold the content of the
552-
// combined content.
553-
size += len(fragment)
554-
}
555-
556-
content := make([]byte, 0, size)
557-
for _, fragment := range m {
558-
content = append(content, fragment...)
511+
if slices.ContainsFunc(m, func(i []byte) bool { return len(i) == 0 }) {
512+
// We haven't yet received all split fragments, so we cannot add the
513+
// packets together yet.
514+
return nil
559515
}
516+
p.content = slices.Concat(m...)
560517

561518
delete(conn.splits, p.splitID)
562-
563-
p.content = content
564519
return conn.receivePacket(p)
565520
}
566521

@@ -611,11 +566,10 @@ func (conn *Conn) handleACK(b []byte) error {
611566
}
612567
for _, sequenceNumber := range ack.packets {
613568
// Take out all stored packets from the recovery queue.
614-
p, ok := conn.retransmission.acknowledge(sequenceNumber)
615-
if ok {
569+
if p, ok := conn.retransmission.acknowledge(sequenceNumber); ok {
616570
// Clear the packet and return it to the pool so that it may be
617571
// re-used.
618-
p.content = nil
572+
p.content = p.content[:0]
619573
packetPool.Put(p)
620574
}
621575
}
@@ -654,9 +608,8 @@ func (conn *Conn) resend(sequenceNumbers []uint24) (err error) {
654608
// passed. It is assigned a new sequence number and added to the retransmission.
655609
func (conn *Conn) sendDatagram(pk *packet) error {
656610
conn.buf.WriteByte(bitFlagDatagram | bitFlagNeedsBAndAS)
657-
newSeqNum := conn.seq
658-
conn.seq++
659-
writeUint24(conn.buf, newSeqNum)
611+
seq := conn.seq.Inc()
612+
writeUint24(conn.buf, seq)
660613
pk.write(conn.buf)
661614

662615
// We then send the pk to the connection.
@@ -665,7 +618,7 @@ func (conn *Conn) sendDatagram(pk *packet) error {
665618
}
666619
// We then re-add the pk to the recovery queue in case the new one gets
667620
// lost too, in which case we need to resend it again.
668-
conn.retransmission.add(newSeqNum, pk)
621+
conn.retransmission.add(seq, pk)
669622
conn.buf.Reset()
670623
return nil
671624
}

err.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@ import (
66
)
77

88
var (
9-
errBufferTooSmall = errors.New("a message sent was larger than the buffer used to receive the message into")
10-
errListenerClosed = errors.New("use of closed listener")
9+
// ErrBufferTooSmall is returned when Conn.Read is called with a byte slice
10+
// that is too small to contain the packet to be read.
11+
ErrBufferTooSmall = errors.New("a message sent was larger than the buffer used to receive the message into")
12+
// ErrListenerClosed is returned when Listener.Accept is called on a closed
13+
// listener.
14+
ErrListenerClosed = errors.New("use of closed listener")
15+
// ErrNotSupported is returned for deadline methods of a Conn, which are not
16+
// supported on a raknet.Conn.
17+
ErrNotSupported = errors.New("feature not supported")
1118
)
1219

1320
// error wraps the error passed into a net.OpError with the op as operation and

listener.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func Listen(address string) (*Listener, error) {
110110
func (listener *Listener) Accept() (net.Conn, error) {
111111
conn, ok := <-listener.incoming
112112
if !ok {
113-
return nil, &net.OpError{Op: "accept", Net: "raknet", Source: nil, Addr: nil, Err: errListenerClosed}
113+
return nil, &net.OpError{Op: "accept", Net: "raknet", Source: nil, Addr: nil, Err: ErrListenerClosed}
114114
}
115115
return conn, nil
116116
}

resend_map.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ func (m *resendMap) remove(index uint24, mul int) (*packet, bool) {
6161
// into the recovery queue and the taking out of it again. It is measured over
6262
// the last delayRecordCount values add in.
6363
func (m *resendMap) rtt() time.Duration {
64-
const averageDuration = time.Second * 5
64+
const maxRTT = time.Second * 5
6565
var (
6666
total, records time.Duration
6767
now = time.Now()
6868
)
6969
for t, rtt := range m.delays {
70-
if now.Sub(t) > averageDuration {
70+
if now.Sub(t) > maxRTT {
7171
delete(m.delays, t)
7272
continue
7373
}

0 commit comments

Comments
 (0)