mirror of
https://github.com/soypat/lneto.git
synced 2026-09-08 15:59:10 +00:00
add maximum segment size option on TCP connection init
This commit is contained in:
+39
-6
@@ -378,15 +378,48 @@ func (kind OptionKind) IsDefined() bool {
|
||||
return kind <= 30 || kind == 34 || kind == 69 || kind == 172 || kind == 174
|
||||
}
|
||||
|
||||
type OptionParser struct {
|
||||
SkipSizeValidation bool
|
||||
SkipObsolete bool
|
||||
type OptionCodec struct {
|
||||
Flags OptionFlags
|
||||
}
|
||||
|
||||
func (op *OptionParser) ForEachOption(opts []byte, fn func(OptionKind, []byte) error) error {
|
||||
type OptionFlags uint8
|
||||
|
||||
const (
|
||||
OptFlagSkipSizeValidation OptionFlags = 1 << iota
|
||||
OptFlagSkipObsolete
|
||||
)
|
||||
|
||||
func (flags OptionFlags) HasAny(ofTheseFlags OptionFlags) bool {
|
||||
return flags&ofTheseFlags != 0
|
||||
}
|
||||
|
||||
func (op OptionCodec) PutOption16(dst []byte, kind OptionKind, v uint16) (int, error) {
|
||||
return op.PutOption(dst, kind, byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
func (op OptionCodec) PutOption32(dst []byte, kind OptionKind, v uint32) (int, error) {
|
||||
return op.PutOption(dst, kind, byte(v>>24), byte(v>>16), byte(v>>7), byte(v))
|
||||
}
|
||||
|
||||
func (op OptionCodec) PutOption(dst []byte, kind OptionKind, data ...byte) (int, error) {
|
||||
putSize := 2 + len(data)
|
||||
if len(dst) < putSize {
|
||||
return -1, errBufferTooSmall
|
||||
} else if putSize > 255 {
|
||||
return -1, errors.New("option data too large")
|
||||
} else if kind == OptNop || kind == OptEnd {
|
||||
return -1, errors.New("cant put Nop or End option type")
|
||||
}
|
||||
dst[0] = byte(kind)
|
||||
dst[1] = byte(putSize)
|
||||
copy(dst[2:], data)
|
||||
return putSize, nil
|
||||
}
|
||||
|
||||
func (op OptionCodec) ForEachOption(opts []byte, fn func(OptionKind, []byte) error) error {
|
||||
off := 0
|
||||
skipSizeValidation := op.SkipSizeValidation
|
||||
skipObsolete := op.SkipObsolete
|
||||
skipSizeValidation := op.Flags.HasAny(OptFlagSkipSizeValidation)
|
||||
skipObsolete := op.Flags.HasAny(OptFlagSkipObsolete)
|
||||
for off < len(opts) && opts[off] != 0 {
|
||||
kind := OptionKind(opts[off])
|
||||
off++
|
||||
|
||||
+12
-4
@@ -30,8 +30,9 @@ type Handler struct {
|
||||
// connid is a conenction counter that is incremented each time a new
|
||||
// connection is established via Open calls. This disambiguate's whether
|
||||
// Read and Write calls belong to the current connection.
|
||||
connid uint16
|
||||
closing bool
|
||||
connid uint16
|
||||
optcodec OptionCodec
|
||||
closing bool
|
||||
}
|
||||
|
||||
func (h *Handler) SetLoggers(handler, scb *slog.Logger) {
|
||||
@@ -206,10 +207,14 @@ func (h *Handler) Send(b []byte) (int, error) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
offset := uint8(5)
|
||||
var segment Segment
|
||||
if h.AwaitingSynSend() {
|
||||
// Handling init syn segment.
|
||||
segment = ClientSynSegment(h.scb.ISS(), h.scb.RecvWindow())
|
||||
h.optcodec.PutOption16(b[sizeHeaderTCP:], OptMaxSegmentSize, uint16(len(b)))
|
||||
offset++
|
||||
} else {
|
||||
var ok bool
|
||||
available := min(h.bufTx.Buffered(), len(b)-sizeHeaderTCP)
|
||||
@@ -225,6 +230,9 @@ func (h *Handler) Send(b []byte) (int, error) {
|
||||
} else if n != int(segment.DATALEN) {
|
||||
panic("expected n == available")
|
||||
}
|
||||
} else if segment.Flags == synack {
|
||||
h.optcodec.PutOption16(b[sizeHeaderTCP:], OptMaxSegmentSize, uint16(len(b)))
|
||||
offset++
|
||||
}
|
||||
}
|
||||
prevState := h.scb.State()
|
||||
@@ -236,9 +244,9 @@ func (h *Handler) Send(b []byte) (int, error) {
|
||||
}
|
||||
tfrm.SetSourcePort(h.localPort)
|
||||
tfrm.SetDestinationPort(h.remotePort)
|
||||
tfrm.SetSegment(segment, 5) // No TCP options.
|
||||
tfrm.SetSegment(segment, offset) // No TCP options.
|
||||
tfrm.SetUrgentPtr(0)
|
||||
return sizeHeaderTCP + int(segment.DATALEN), nil
|
||||
return int(offset)*4 + int(segment.DATALEN), nil
|
||||
}
|
||||
|
||||
// Free returns the amount of space free in the transmit buffer. A call to [Handler.Write] with a larger buffer will fail.
|
||||
|
||||
Reference in New Issue
Block a user