snapshot: sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1

Содержимое пина, зафиксированного в go.mod sing-box-lx, одним коммитом
без истории. Полная история SagerNet/gvisor — 1.45 ГБ и клонируется в
каждой CI-джобе; наша дельта — одна вставка в одну функцию, история для
неё не нужна.

Module path github.com/sagernet/gvisor сохранён намеренно: на него
опирается replace-директива суперпроекта.

Патч поверх — отдельным коммитом, чтобы дельта читалась одним git show
и переносилась на новый пин копированием.

SPECS/TASKS/048-GVISOR_HANDSHAKE_NIL_CRASH
This commit is contained in:
Leadaxe 2026-08-04 15:50:08 +03:00
commit 2c4ae3b0a4
712 changed files with 185689 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,96 @@
// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package udp
import (
"context"
"time"
"github.com/sagernet/gvisor/pkg/log"
"github.com/sagernet/gvisor/pkg/tcpip"
"github.com/sagernet/gvisor/pkg/tcpip/stack"
"github.com/sagernet/gvisor/pkg/tcpip/transport"
)
// saveReceivedAt is invoked by stateify.
func (p *udpPacket) saveReceivedAt() int64 {
return p.receivedAt.UnixNano()
}
// loadReceivedAt is invoked by stateify.
func (p *udpPacket) loadReceivedAt(_ context.Context, nsec int64) {
p.receivedAt = time.Unix(0, nsec)
}
// afterLoad is invoked by stateify.
func (e *endpoint) afterLoad(ctx context.Context) {
if e.stack.IsSaveRestoreEnabled() {
e.stack.RegisterRestoredEndpoint(e)
} else {
stack.RestoreStackFromContext(ctx).RegisterRestoredEndpoint(e)
}
}
// beforeSave is invoked by stateify.
func (e *endpoint) beforeSave() {
e.freeze()
e.stack.RegisterResumableEndpoint(e)
}
// Restore implements tcpip.RestoredEndpoint.Restore.
func (e *endpoint) Restore(s *stack.Stack) {
e.mu.Lock()
defer e.mu.Unlock()
if err := e.net.Resume(s); err != nil {
log.Warningf("Closing the UDP endpoint as it cannot be restored, err: %v", err)
e.closeLocked()
return
}
// Unfreeze the endpoint to handle packets.
e.frozen = false
if e.stack.IsSaveRestoreEnabled() {
e.ops.InitHandler(e, e.stack, tcpip.GetStackSendBufferLimits, tcpip.GetStackReceiveBufferLimits)
return
}
e.stack = s
e.ops.InitHandler(e, e.stack, tcpip.GetStackSendBufferLimits, tcpip.GetStackReceiveBufferLimits)
switch state := e.net.State(); state {
case transport.DatagramEndpointStateInitial, transport.DatagramEndpointStateClosed:
case transport.DatagramEndpointStateBound, transport.DatagramEndpointStateConnected:
// Our saved state had a port, but we don't actually have a
// reservation. We need to remove the port from our state, but still
// pass it to the reservation machinery.
var err tcpip.Error
id := e.net.Info().ID
id.LocalPort = e.localPort
id.RemotePort = e.remotePort
id, e.boundBindToDevice, err = e.registerWithStack(e.effectiveNetProtos, id)
if err != nil {
panic("registering udp endpoint with the stack failed during restore")
}
e.localPort = id.LocalPort
e.remotePort = id.RemotePort
default:
panic("unhandled state")
}
}
// Resume implements tcpip.ResumableEndpoint.Resume.
func (e *endpoint) Resume() {
e.thaw()
}

View file

@ -0,0 +1,112 @@
// Copyright 2019 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package udp
import (
"github.com/sagernet/gvisor/pkg/tcpip"
"github.com/sagernet/gvisor/pkg/tcpip/stack"
"github.com/sagernet/gvisor/pkg/waiter"
)
// ForwarderHandler handles incoming requests. Returning true marks the
// request as handled, returning false marks the request as unhandled.
// Stack may send an ICMP port unreachable message for unhandled requests.
type ForwarderHandler func(*ForwarderRequest) (handled bool)
// Forwarder is a session request forwarder, which allows clients to decide
// what to do with a session request, for example: ignore it, or process it.
//
// The canonical way of using it is to pass the Forwarder.HandlePacket function
// to stack.SetTransportProtocolHandler.
type Forwarder struct {
handler ForwarderHandler
stack *stack.Stack
}
// NewForwarder allocates and initializes a new forwarder.
func NewForwarder(s *stack.Stack, handler ForwarderHandler) *Forwarder {
return &Forwarder{
stack: s,
handler: handler,
}
}
// HandlePacket handles all packets.
//
// This function is expected to be passed as an argument to the
// stack.SetTransportProtocolHandler function.
func (f *Forwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.PacketBuffer) bool {
return f.handler(&ForwarderRequest{
stack: f.stack,
id: id,
pkt: pkt.Clone(),
})
}
// ForwarderRequest represents a session request received by the forwarder and
// passed to the client. Clients may optionally create an endpoint to represent
// it via CreateEndpoint.
type ForwarderRequest struct {
stack *stack.Stack
id stack.TransportEndpointID
pkt *stack.PacketBuffer
}
// ID returns the 4-tuple (src address, src port, dst address, dst port) that
// represents the session request.
func (r *ForwarderRequest) ID() stack.TransportEndpointID {
return r.id
}
// CreateEndpoint creates a connected UDP endpoint for the session request.
func (r *ForwarderRequest) CreateEndpoint(queue *waiter.Queue) (tcpip.Endpoint, tcpip.Error) {
ep := newEndpoint(r.stack, r.pkt.NetworkProtocolNumber, queue)
ep.mu.Lock()
defer ep.mu.Unlock()
netHdr := r.pkt.Network()
if err := ep.net.Bind(tcpip.FullAddress{NIC: r.pkt.NICID, Addr: netHdr.DestinationAddress(), Port: r.id.LocalPort}); err != nil {
ep.closeLocked()
return nil, err
}
if err := ep.net.Connect(tcpip.FullAddress{NIC: r.pkt.NICID, Addr: netHdr.SourceAddress(), Port: r.id.RemotePort}); err != nil {
ep.closeLocked()
return nil, err
}
if err := r.stack.RegisterTransportEndpoint([]tcpip.NetworkProtocolNumber{r.pkt.NetworkProtocolNumber}, ProtocolNumber, r.id, ep, ep.portFlags, tcpip.NICID(ep.ops.GetBindToDevice())); err != nil {
ep.closeLocked()
return nil, err
}
ep.localPort = r.id.LocalPort
ep.remotePort = r.id.RemotePort
ep.effectiveNetProtos = []tcpip.NetworkProtocolNumber{r.pkt.NetworkProtocolNumber}
ep.boundPortFlags = ep.portFlags
ep.rcvMu.Lock()
ep.rcvReady = true
ep.rcvMu.Unlock()
ep.HandlePacket(r.id, r.pkt)
return ep, nil
}
func (r *ForwarderRequest) Packet() *stack.PacketBuffer {
return r.pkt
}

View file

@ -0,0 +1,138 @@
// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package udp contains the implementation of the UDP transport protocol.
package udp
import (
"github.com/sagernet/gvisor/pkg/tcpip"
"github.com/sagernet/gvisor/pkg/tcpip/header"
"github.com/sagernet/gvisor/pkg/tcpip/header/parse"
"github.com/sagernet/gvisor/pkg/tcpip/stack"
"github.com/sagernet/gvisor/pkg/tcpip/transport/raw"
"github.com/sagernet/gvisor/pkg/waiter"
)
const (
// ProtocolNumber is the udp protocol number.
ProtocolNumber = header.UDPProtocolNumber
// MinBufferSize is the smallest size of a receive or send buffer.
MinBufferSize = 4 << 10 // 4KiB bytes.
// DefaultSendBufferSize is the default size of the send buffer for
// an endpoint.
DefaultSendBufferSize = 32 << 10 // 32KiB
// DefaultReceiveBufferSize is the default size of the receive buffer
// for an endpoint.
DefaultReceiveBufferSize = 32 << 10 // 32KiB
// MaxBufferSize is the largest size a receive/send buffer can grow to.
MaxBufferSize = 4 << 20 // 4MiB
)
// +stateify savable
type protocol struct {
stack *stack.Stack
}
// Number returns the udp protocol number.
func (*protocol) Number() tcpip.TransportProtocolNumber {
return ProtocolNumber
}
// NewEndpoint creates a new udp endpoint.
func (p *protocol) NewEndpoint(netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, tcpip.Error) {
return newEndpoint(p.stack, netProto, waiterQueue), nil
}
// NewRawEndpoint creates a new raw UDP endpoint. It implements
// stack.TransportProtocol.NewRawEndpoint.
func (p *protocol) NewRawEndpoint(netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, tcpip.Error) {
return raw.NewEndpoint(p.stack, netProto, header.UDPProtocolNumber, waiterQueue)
}
// MinimumPacketSize returns the minimum valid udp packet size.
func (*protocol) MinimumPacketSize() int {
return header.UDPMinimumSize
}
// ParsePorts returns the source and destination ports stored in the given udp
// packet.
func (*protocol) ParsePorts(v []byte) (src, dst uint16, err tcpip.Error) {
h := header.UDP(v)
return h.SourcePort(), h.DestinationPort(), nil
}
// HandleUnknownDestinationPacket handles packets that are targeted at this
// protocol but don't match any existing endpoint.
func (p *protocol) HandleUnknownDestinationPacket(id stack.TransportEndpointID, pkt *stack.PacketBuffer) stack.UnknownDestinationPacketDisposition {
hdr := header.UDP(pkt.TransportHeader().Slice())
netHdr := pkt.Network()
lengthValid, csumValid := header.UDPValid(
hdr,
func() uint16 { return pkt.Data().Checksum() },
uint16(pkt.Data().Size()),
pkt.NetworkProtocolNumber,
netHdr.SourceAddress(),
netHdr.DestinationAddress(),
pkt.RXChecksumValidated)
if !lengthValid {
p.stack.Stats().UDP.MalformedPacketsReceived.Increment()
return stack.UnknownDestinationPacketMalformed
}
if !csumValid {
p.stack.Stats().UDP.ChecksumErrors.Increment()
return stack.UnknownDestinationPacketMalformed
}
return stack.UnknownDestinationPacketUnhandled
}
// SetOption implements stack.TransportProtocol.SetOption.
func (*protocol) SetOption(tcpip.SettableTransportProtocolOption) tcpip.Error {
return &tcpip.ErrUnknownProtocolOption{}
}
// Option implements stack.TransportProtocol.Option.
func (*protocol) Option(tcpip.GettableTransportProtocolOption) tcpip.Error {
return &tcpip.ErrUnknownProtocolOption{}
}
// Close implements stack.TransportProtocol.Close.
func (*protocol) Close() {}
// Wait implements stack.TransportProtocol.Wait.
func (*protocol) Wait() {}
// Pause implements stack.TransportProtocol.Pause.
func (*protocol) Pause() {}
// Resume implements stack.TransportProtocol.Resume.
func (*protocol) Resume() {}
// Restore implements stack.TransportProtocol.Restore.
func (*protocol) Restore() {}
// Parse implements stack.TransportProtocol.Parse.
func (*protocol) Parse(pkt *stack.PacketBuffer) bool {
return parse.UDP(pkt)
}
// NewProtocol returns a UDP transport protocol.
func NewProtocol(s *stack.Stack) stack.TransportProtocol {
return &protocol{stack: s}
}

View file

@ -0,0 +1,239 @@
package udp
// ElementMapper provides an identity mapping by default.
//
// This can be replaced to provide a struct that maps elements to linker
// objects, if they are not the same. An ElementMapper is not typically
// required if: Linker is left as is, Element is left as is, or Linker and
// Element are the same type.
type udpPacketElementMapper struct{}
// linkerFor maps an Element to a Linker.
//
// This default implementation should be inlined.
//
//go:nosplit
func (udpPacketElementMapper) linkerFor(elem *udpPacket) *udpPacket { return elem }
// List is an intrusive list. Entries can be added to or removed from the list
// in O(1) time and with no additional memory allocations.
//
// The zero value for List is an empty list ready to use.
//
// To iterate over a list (where l is a List):
//
// for e := l.Front(); e != nil; e = e.Next() {
// // do something with e.
// }
//
// +stateify savable
type udpPacketList struct {
head *udpPacket
tail *udpPacket
}
// Reset resets list l to the empty state.
func (l *udpPacketList) Reset() {
l.head = nil
l.tail = nil
}
// Empty returns true iff the list is empty.
//
//go:nosplit
func (l *udpPacketList) Empty() bool {
return l.head == nil
}
// Front returns the first element of list l or nil.
//
//go:nosplit
func (l *udpPacketList) Front() *udpPacket {
return l.head
}
// Back returns the last element of list l or nil.
//
//go:nosplit
func (l *udpPacketList) Back() *udpPacket {
return l.tail
}
// Len returns the number of elements in the list.
//
// NOTE: This is an O(n) operation.
//
//go:nosplit
func (l *udpPacketList) Len() (count int) {
for e := l.Front(); e != nil; e = (udpPacketElementMapper{}.linkerFor(e)).Next() {
count++
}
return count
}
// PushFront inserts the element e at the front of list l.
//
//go:nosplit
func (l *udpPacketList) PushFront(e *udpPacket) {
linker := udpPacketElementMapper{}.linkerFor(e)
linker.SetNext(l.head)
linker.SetPrev(nil)
if l.head != nil {
udpPacketElementMapper{}.linkerFor(l.head).SetPrev(e)
} else {
l.tail = e
}
l.head = e
}
// PushFrontList inserts list m at the start of list l, emptying m.
//
//go:nosplit
func (l *udpPacketList) PushFrontList(m *udpPacketList) {
if l.head == nil {
l.head = m.head
l.tail = m.tail
} else if m.head != nil {
udpPacketElementMapper{}.linkerFor(l.head).SetPrev(m.tail)
udpPacketElementMapper{}.linkerFor(m.tail).SetNext(l.head)
l.head = m.head
}
m.head = nil
m.tail = nil
}
// PushBack inserts the element e at the back of list l.
//
//go:nosplit
func (l *udpPacketList) PushBack(e *udpPacket) {
linker := udpPacketElementMapper{}.linkerFor(e)
linker.SetNext(nil)
linker.SetPrev(l.tail)
if l.tail != nil {
udpPacketElementMapper{}.linkerFor(l.tail).SetNext(e)
} else {
l.head = e
}
l.tail = e
}
// PushBackList inserts list m at the end of list l, emptying m.
//
//go:nosplit
func (l *udpPacketList) PushBackList(m *udpPacketList) {
if l.head == nil {
l.head = m.head
l.tail = m.tail
} else if m.head != nil {
udpPacketElementMapper{}.linkerFor(l.tail).SetNext(m.head)
udpPacketElementMapper{}.linkerFor(m.head).SetPrev(l.tail)
l.tail = m.tail
}
m.head = nil
m.tail = nil
}
// InsertAfter inserts e after b.
//
//go:nosplit
func (l *udpPacketList) InsertAfter(b, e *udpPacket) {
bLinker := udpPacketElementMapper{}.linkerFor(b)
eLinker := udpPacketElementMapper{}.linkerFor(e)
a := bLinker.Next()
eLinker.SetNext(a)
eLinker.SetPrev(b)
bLinker.SetNext(e)
if a != nil {
udpPacketElementMapper{}.linkerFor(a).SetPrev(e)
} else {
l.tail = e
}
}
// InsertBefore inserts e before a.
//
//go:nosplit
func (l *udpPacketList) InsertBefore(a, e *udpPacket) {
aLinker := udpPacketElementMapper{}.linkerFor(a)
eLinker := udpPacketElementMapper{}.linkerFor(e)
b := aLinker.Prev()
eLinker.SetNext(a)
eLinker.SetPrev(b)
aLinker.SetPrev(e)
if b != nil {
udpPacketElementMapper{}.linkerFor(b).SetNext(e)
} else {
l.head = e
}
}
// Remove removes e from l.
//
//go:nosplit
func (l *udpPacketList) Remove(e *udpPacket) {
linker := udpPacketElementMapper{}.linkerFor(e)
prev := linker.Prev()
next := linker.Next()
if prev != nil {
udpPacketElementMapper{}.linkerFor(prev).SetNext(next)
} else if l.head == e {
l.head = next
}
if next != nil {
udpPacketElementMapper{}.linkerFor(next).SetPrev(prev)
} else if l.tail == e {
l.tail = prev
}
linker.SetNext(nil)
linker.SetPrev(nil)
}
// Entry is a default implementation of Linker. Users can add anonymous fields
// of this type to their structs to make them automatically implement the
// methods needed by List.
//
// +stateify savable
type udpPacketEntry struct {
next *udpPacket
prev *udpPacket
}
// Next returns the entry that follows e in the list.
//
//go:nosplit
func (e *udpPacketEntry) Next() *udpPacket {
return e.next
}
// Prev returns the entry that precedes e in the list.
//
//go:nosplit
func (e *udpPacketEntry) Prev() *udpPacket {
return e.prev
}
// SetNext assigns 'entry' as the entry that follows e in the list.
//
//go:nosplit
func (e *udpPacketEntry) SetNext(elem *udpPacket) {
e.next = elem
}
// SetPrev assigns 'entry' as the entry that precedes e in the list.
//
//go:nosplit
func (e *udpPacketEntry) SetPrev(elem *udpPacket) {
e.prev = elem
}

View file

@ -0,0 +1,225 @@
// automatically generated by stateify.
package udp
import (
"context"
"github.com/sagernet/gvisor/pkg/state"
)
func (p *udpPacket) StateTypeName() string {
return "pkg/tcpip/transport/udp.udpPacket"
}
func (p *udpPacket) StateFields() []string {
return []string{
"udpPacketEntry",
"netProto",
"senderAddress",
"destinationAddress",
"packetInfo",
"pkt",
"receivedAt",
"tosOrTClass",
"ttlOrHopLimit",
}
}
func (p *udpPacket) beforeSave() {}
// +checklocksignore
func (p *udpPacket) StateSave(stateSinkObject state.Sink) {
p.beforeSave()
var receivedAtValue int64
receivedAtValue = p.saveReceivedAt()
stateSinkObject.SaveValue(6, receivedAtValue)
stateSinkObject.Save(0, &p.udpPacketEntry)
stateSinkObject.Save(1, &p.netProto)
stateSinkObject.Save(2, &p.senderAddress)
stateSinkObject.Save(3, &p.destinationAddress)
stateSinkObject.Save(4, &p.packetInfo)
stateSinkObject.Save(5, &p.pkt)
stateSinkObject.Save(7, &p.tosOrTClass)
stateSinkObject.Save(8, &p.ttlOrHopLimit)
}
func (p *udpPacket) afterLoad(context.Context) {}
// +checklocksignore
func (p *udpPacket) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &p.udpPacketEntry)
stateSourceObject.Load(1, &p.netProto)
stateSourceObject.Load(2, &p.senderAddress)
stateSourceObject.Load(3, &p.destinationAddress)
stateSourceObject.Load(4, &p.packetInfo)
stateSourceObject.Load(5, &p.pkt)
stateSourceObject.Load(7, &p.tosOrTClass)
stateSourceObject.Load(8, &p.ttlOrHopLimit)
stateSourceObject.LoadValue(6, new(int64), func(y any) { p.loadReceivedAt(ctx, y.(int64)) })
}
func (e *endpoint) StateTypeName() string {
return "pkg/tcpip/transport/udp.endpoint"
}
func (e *endpoint) StateFields() []string {
return []string{
"DefaultSocketOptionsHandler",
"stack",
"waiterQueue",
"net",
"stats",
"ops",
"rcvReady",
"rcvList",
"rcvBufSize",
"rcvClosed",
"lastError",
"portFlags",
"boundBindToDevice",
"boundPortFlags",
"readShutdown",
"effectiveNetProtos",
"frozen",
"localPort",
"remotePort",
}
}
// +checklocksignore
func (e *endpoint) StateSave(stateSinkObject state.Sink) {
e.beforeSave()
stateSinkObject.Save(0, &e.DefaultSocketOptionsHandler)
stateSinkObject.Save(1, &e.stack)
stateSinkObject.Save(2, &e.waiterQueue)
stateSinkObject.Save(3, &e.net)
stateSinkObject.Save(4, &e.stats)
stateSinkObject.Save(5, &e.ops)
stateSinkObject.Save(6, &e.rcvReady)
stateSinkObject.Save(7, &e.rcvList)
stateSinkObject.Save(8, &e.rcvBufSize)
stateSinkObject.Save(9, &e.rcvClosed)
stateSinkObject.Save(10, &e.lastError)
stateSinkObject.Save(11, &e.portFlags)
stateSinkObject.Save(12, &e.boundBindToDevice)
stateSinkObject.Save(13, &e.boundPortFlags)
stateSinkObject.Save(14, &e.readShutdown)
stateSinkObject.Save(15, &e.effectiveNetProtos)
stateSinkObject.Save(16, &e.frozen)
stateSinkObject.Save(17, &e.localPort)
stateSinkObject.Save(18, &e.remotePort)
}
// +checklocksignore
func (e *endpoint) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &e.DefaultSocketOptionsHandler)
stateSourceObject.Load(1, &e.stack)
stateSourceObject.Load(2, &e.waiterQueue)
stateSourceObject.Load(3, &e.net)
stateSourceObject.Load(4, &e.stats)
stateSourceObject.Load(5, &e.ops)
stateSourceObject.Load(6, &e.rcvReady)
stateSourceObject.Load(7, &e.rcvList)
stateSourceObject.Load(8, &e.rcvBufSize)
stateSourceObject.Load(9, &e.rcvClosed)
stateSourceObject.Load(10, &e.lastError)
stateSourceObject.Load(11, &e.portFlags)
stateSourceObject.Load(12, &e.boundBindToDevice)
stateSourceObject.Load(13, &e.boundPortFlags)
stateSourceObject.Load(14, &e.readShutdown)
stateSourceObject.Load(15, &e.effectiveNetProtos)
stateSourceObject.Load(16, &e.frozen)
stateSourceObject.Load(17, &e.localPort)
stateSourceObject.Load(18, &e.remotePort)
stateSourceObject.AfterLoad(func() { e.afterLoad(ctx) })
}
func (p *protocol) StateTypeName() string {
return "pkg/tcpip/transport/udp.protocol"
}
func (p *protocol) StateFields() []string {
return []string{
"stack",
}
}
func (p *protocol) beforeSave() {}
// +checklocksignore
func (p *protocol) StateSave(stateSinkObject state.Sink) {
p.beforeSave()
stateSinkObject.Save(0, &p.stack)
}
func (p *protocol) afterLoad(context.Context) {}
// +checklocksignore
func (p *protocol) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &p.stack)
}
func (l *udpPacketList) StateTypeName() string {
return "pkg/tcpip/transport/udp.udpPacketList"
}
func (l *udpPacketList) StateFields() []string {
return []string{
"head",
"tail",
}
}
func (l *udpPacketList) beforeSave() {}
// +checklocksignore
func (l *udpPacketList) StateSave(stateSinkObject state.Sink) {
l.beforeSave()
stateSinkObject.Save(0, &l.head)
stateSinkObject.Save(1, &l.tail)
}
func (l *udpPacketList) afterLoad(context.Context) {}
// +checklocksignore
func (l *udpPacketList) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &l.head)
stateSourceObject.Load(1, &l.tail)
}
func (e *udpPacketEntry) StateTypeName() string {
return "pkg/tcpip/transport/udp.udpPacketEntry"
}
func (e *udpPacketEntry) StateFields() []string {
return []string{
"next",
"prev",
}
}
func (e *udpPacketEntry) beforeSave() {}
// +checklocksignore
func (e *udpPacketEntry) StateSave(stateSinkObject state.Sink) {
e.beforeSave()
stateSinkObject.Save(0, &e.next)
stateSinkObject.Save(1, &e.prev)
}
func (e *udpPacketEntry) afterLoad(context.Context) {}
// +checklocksignore
func (e *udpPacketEntry) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &e.next)
stateSourceObject.Load(1, &e.prev)
}
func init() {
state.Register((*udpPacket)(nil))
state.Register((*endpoint)(nil))
state.Register((*protocol)(nil))
state.Register((*udpPacketList)(nil))
state.Register((*udpPacketEntry)(nil))
}