diff options
Diffstat (limited to 'pkg/tcpip/transport')
-rw-r--r-- | pkg/tcpip/transport/icmp/endpoint.go | 7 | ||||
-rw-r--r-- | pkg/tcpip/transport/icmp/icmp_state_autogen.go | 59 | ||||
-rw-r--r-- | pkg/tcpip/transport/packet/endpoint.go | 3 | ||||
-rw-r--r-- | pkg/tcpip/transport/packet/packet_state_autogen.go | 63 | ||||
-rw-r--r-- | pkg/tcpip/transport/raw/endpoint.go | 3 | ||||
-rw-r--r-- | pkg/tcpip/transport/raw/raw_state_autogen.go | 63 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/endpoint.go | 40 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/tcp_state_autogen.go | 259 | ||||
-rw-r--r-- | pkg/tcpip/transport/udp/endpoint.go | 40 | ||||
-rw-r--r-- | pkg/tcpip/transport/udp/udp_state_autogen.go | 131 |
10 files changed, 338 insertions, 330 deletions
diff --git a/pkg/tcpip/transport/icmp/endpoint.go b/pkg/tcpip/transport/icmp/endpoint.go index fe6514bcd..39560a9fa 100644 --- a/pkg/tcpip/transport/icmp/endpoint.go +++ b/pkg/tcpip/transport/icmp/endpoint.go @@ -49,6 +49,7 @@ const ( // +stateify savable type endpoint struct { stack.TransportEndpointInfo + tcpip.DefaultSocketOptionsHandler // The following fields are initialized at creation time and are // immutable. @@ -85,7 +86,7 @@ type endpoint struct { } func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProto tcpip.TransportProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { - return &endpoint{ + ep := &endpoint{ stack: s, TransportEndpointInfo: stack.TransportEndpointInfo{ NetProto: netProto, @@ -96,7 +97,9 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProt sndBufSize: 32 * 1024, state: stateInitial, uniqueID: s.UniqueID(), - }, nil + } + ep.ops.InitHandler(ep) + return ep, nil } // UniqueID implements stack.TransportEndpoint.UniqueID. diff --git a/pkg/tcpip/transport/icmp/icmp_state_autogen.go b/pkg/tcpip/transport/icmp/icmp_state_autogen.go index 81d864da0..0fcfe0dd8 100644 --- a/pkg/tcpip/transport/icmp/icmp_state_autogen.go +++ b/pkg/tcpip/transport/icmp/icmp_state_autogen.go @@ -47,6 +47,7 @@ func (e *endpoint) StateTypeName() string { func (e *endpoint) StateFields() []string { return []string{ "TransportEndpointInfo", + "DefaultSocketOptionsHandler", "waiterQueue", "uniqueID", "rcvReady", @@ -67,39 +68,41 @@ func (e *endpoint) StateFields() []string { func (e *endpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() var rcvBufSizeMaxValue int = e.saveRcvBufSizeMax() - stateSinkObject.SaveValue(5, rcvBufSizeMaxValue) + stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) stateSinkObject.Save(0, &e.TransportEndpointInfo) - stateSinkObject.Save(1, &e.waiterQueue) - stateSinkObject.Save(2, &e.uniqueID) - stateSinkObject.Save(3, &e.rcvReady) - stateSinkObject.Save(4, &e.rcvList) - stateSinkObject.Save(6, &e.rcvBufSize) - stateSinkObject.Save(7, &e.rcvClosed) - stateSinkObject.Save(8, &e.sndBufSize) - stateSinkObject.Save(9, &e.shutdownFlags) - stateSinkObject.Save(10, &e.state) - stateSinkObject.Save(11, &e.ttl) - stateSinkObject.Save(12, &e.linger) - stateSinkObject.Save(13, &e.owner) - stateSinkObject.Save(14, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.waiterQueue) + stateSinkObject.Save(3, &e.uniqueID) + stateSinkObject.Save(4, &e.rcvReady) + stateSinkObject.Save(5, &e.rcvList) + stateSinkObject.Save(7, &e.rcvBufSize) + stateSinkObject.Save(8, &e.rcvClosed) + stateSinkObject.Save(9, &e.sndBufSize) + stateSinkObject.Save(10, &e.shutdownFlags) + stateSinkObject.Save(11, &e.state) + stateSinkObject.Save(12, &e.ttl) + stateSinkObject.Save(13, &e.linger) + stateSinkObject.Save(14, &e.owner) + stateSinkObject.Save(15, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.TransportEndpointInfo) - stateSourceObject.Load(1, &e.waiterQueue) - stateSourceObject.Load(2, &e.uniqueID) - stateSourceObject.Load(3, &e.rcvReady) - stateSourceObject.Load(4, &e.rcvList) - stateSourceObject.Load(6, &e.rcvBufSize) - stateSourceObject.Load(7, &e.rcvClosed) - stateSourceObject.Load(8, &e.sndBufSize) - stateSourceObject.Load(9, &e.shutdownFlags) - stateSourceObject.Load(10, &e.state) - stateSourceObject.Load(11, &e.ttl) - stateSourceObject.Load(12, &e.linger) - stateSourceObject.Load(13, &e.owner) - stateSourceObject.Load(14, &e.ops) - stateSourceObject.LoadValue(5, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &e.waiterQueue) + stateSourceObject.Load(3, &e.uniqueID) + stateSourceObject.Load(4, &e.rcvReady) + stateSourceObject.Load(5, &e.rcvList) + stateSourceObject.Load(7, &e.rcvBufSize) + stateSourceObject.Load(8, &e.rcvClosed) + stateSourceObject.Load(9, &e.sndBufSize) + stateSourceObject.Load(10, &e.shutdownFlags) + stateSourceObject.Load(11, &e.state) + stateSourceObject.Load(12, &e.ttl) + stateSourceObject.Load(13, &e.linger) + stateSourceObject.Load(14, &e.owner) + stateSourceObject.Load(15, &e.ops) + stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/packet/endpoint.go b/pkg/tcpip/transport/packet/endpoint.go index 3bff3755a..35d1be792 100644 --- a/pkg/tcpip/transport/packet/endpoint.go +++ b/pkg/tcpip/transport/packet/endpoint.go @@ -60,6 +60,8 @@ type packet struct { // +stateify savable type endpoint struct { stack.TransportEndpointInfo + tcpip.DefaultSocketOptionsHandler + // The following fields are initialized at creation time and are // immutable. stack *stack.Stack `state:"manual"` @@ -107,6 +109,7 @@ func NewEndpoint(s *stack.Stack, cooked bool, netProto tcpip.NetworkProtocolNumb rcvBufSizeMax: 32 * 1024, sndBufSize: 32 * 1024, } + ep.ops.InitHandler(ep) // Override with stack defaults. var ss stack.SendBufferSizeOption diff --git a/pkg/tcpip/transport/packet/packet_state_autogen.go b/pkg/tcpip/transport/packet/packet_state_autogen.go index 2ce71eb84..42236056b 100644 --- a/pkg/tcpip/transport/packet/packet_state_autogen.go +++ b/pkg/tcpip/transport/packet/packet_state_autogen.go @@ -50,6 +50,7 @@ func (ep *endpoint) StateTypeName() string { func (ep *endpoint) StateFields() []string { return []string{ "TransportEndpointInfo", + "DefaultSocketOptionsHandler", "netProto", "waiterQueue", "cooked", @@ -71,42 +72,44 @@ func (ep *endpoint) StateFields() []string { func (ep *endpoint) StateSave(stateSinkObject state.Sink) { ep.beforeSave() var rcvBufSizeMaxValue int = ep.saveRcvBufSizeMax() - stateSinkObject.SaveValue(5, rcvBufSizeMaxValue) + stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) var lastErrorValue string = ep.saveLastError() - stateSinkObject.SaveValue(14, lastErrorValue) + stateSinkObject.SaveValue(15, lastErrorValue) stateSinkObject.Save(0, &ep.TransportEndpointInfo) - stateSinkObject.Save(1, &ep.netProto) - stateSinkObject.Save(2, &ep.waiterQueue) - stateSinkObject.Save(3, &ep.cooked) - stateSinkObject.Save(4, &ep.rcvList) - stateSinkObject.Save(6, &ep.rcvBufSize) - stateSinkObject.Save(7, &ep.rcvClosed) - stateSinkObject.Save(8, &ep.sndBufSize) - stateSinkObject.Save(9, &ep.sndBufSizeMax) - stateSinkObject.Save(10, &ep.closed) - stateSinkObject.Save(11, &ep.bound) - stateSinkObject.Save(12, &ep.boundNIC) - stateSinkObject.Save(13, &ep.linger) - stateSinkObject.Save(15, &ep.ops) + stateSinkObject.Save(1, &ep.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &ep.netProto) + stateSinkObject.Save(3, &ep.waiterQueue) + stateSinkObject.Save(4, &ep.cooked) + stateSinkObject.Save(5, &ep.rcvList) + stateSinkObject.Save(7, &ep.rcvBufSize) + stateSinkObject.Save(8, &ep.rcvClosed) + stateSinkObject.Save(9, &ep.sndBufSize) + stateSinkObject.Save(10, &ep.sndBufSizeMax) + stateSinkObject.Save(11, &ep.closed) + stateSinkObject.Save(12, &ep.bound) + stateSinkObject.Save(13, &ep.boundNIC) + stateSinkObject.Save(14, &ep.linger) + stateSinkObject.Save(16, &ep.ops) } func (ep *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &ep.TransportEndpointInfo) - stateSourceObject.Load(1, &ep.netProto) - stateSourceObject.Load(2, &ep.waiterQueue) - stateSourceObject.Load(3, &ep.cooked) - stateSourceObject.Load(4, &ep.rcvList) - stateSourceObject.Load(6, &ep.rcvBufSize) - stateSourceObject.Load(7, &ep.rcvClosed) - stateSourceObject.Load(8, &ep.sndBufSize) - stateSourceObject.Load(9, &ep.sndBufSizeMax) - stateSourceObject.Load(10, &ep.closed) - stateSourceObject.Load(11, &ep.bound) - stateSourceObject.Load(12, &ep.boundNIC) - stateSourceObject.Load(13, &ep.linger) - stateSourceObject.Load(15, &ep.ops) - stateSourceObject.LoadValue(5, new(int), func(y interface{}) { ep.loadRcvBufSizeMax(y.(int)) }) - stateSourceObject.LoadValue(14, new(string), func(y interface{}) { ep.loadLastError(y.(string)) }) + stateSourceObject.Load(1, &ep.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &ep.netProto) + stateSourceObject.Load(3, &ep.waiterQueue) + stateSourceObject.Load(4, &ep.cooked) + stateSourceObject.Load(5, &ep.rcvList) + stateSourceObject.Load(7, &ep.rcvBufSize) + stateSourceObject.Load(8, &ep.rcvClosed) + stateSourceObject.Load(9, &ep.sndBufSize) + stateSourceObject.Load(10, &ep.sndBufSizeMax) + stateSourceObject.Load(11, &ep.closed) + stateSourceObject.Load(12, &ep.bound) + stateSourceObject.Load(13, &ep.boundNIC) + stateSourceObject.Load(14, &ep.linger) + stateSourceObject.Load(16, &ep.ops) + stateSourceObject.LoadValue(6, new(int), func(y interface{}) { ep.loadRcvBufSizeMax(y.(int)) }) + stateSourceObject.LoadValue(15, new(string), func(y interface{}) { ep.loadLastError(y.(string)) }) stateSourceObject.AfterLoad(ep.afterLoad) } diff --git a/pkg/tcpip/transport/raw/endpoint.go b/pkg/tcpip/transport/raw/endpoint.go index 0a1e1fbb3..e64392f7b 100644 --- a/pkg/tcpip/transport/raw/endpoint.go +++ b/pkg/tcpip/transport/raw/endpoint.go @@ -58,6 +58,8 @@ type rawPacket struct { // +stateify savable type endpoint struct { stack.TransportEndpointInfo + tcpip.DefaultSocketOptionsHandler + // The following fields are initialized at creation time and are // immutable. stack *stack.Stack `state:"manual"` @@ -116,6 +118,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProt associated: associated, hdrIncluded: !associated, } + e.ops.InitHandler(e) // Override with stack defaults. var ss stack.SendBufferSizeOption diff --git a/pkg/tcpip/transport/raw/raw_state_autogen.go b/pkg/tcpip/transport/raw/raw_state_autogen.go index 26fc86a27..4874e4636 100644 --- a/pkg/tcpip/transport/raw/raw_state_autogen.go +++ b/pkg/tcpip/transport/raw/raw_state_autogen.go @@ -47,6 +47,7 @@ func (e *endpoint) StateTypeName() string { func (e *endpoint) StateFields() []string { return []string{ "TransportEndpointInfo", + "DefaultSocketOptionsHandler", "waiterQueue", "associated", "hdrIncluded", @@ -68,41 +69,43 @@ func (e *endpoint) StateFields() []string { func (e *endpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() var rcvBufSizeMaxValue int = e.saveRcvBufSizeMax() - stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) + stateSinkObject.SaveValue(7, rcvBufSizeMaxValue) stateSinkObject.Save(0, &e.TransportEndpointInfo) - stateSinkObject.Save(1, &e.waiterQueue) - stateSinkObject.Save(2, &e.associated) - stateSinkObject.Save(3, &e.hdrIncluded) - stateSinkObject.Save(4, &e.rcvList) - stateSinkObject.Save(5, &e.rcvBufSize) - stateSinkObject.Save(7, &e.rcvClosed) - stateSinkObject.Save(8, &e.sndBufSize) - stateSinkObject.Save(9, &e.sndBufSizeMax) - stateSinkObject.Save(10, &e.closed) - stateSinkObject.Save(11, &e.connected) - stateSinkObject.Save(12, &e.bound) - stateSinkObject.Save(13, &e.linger) - stateSinkObject.Save(14, &e.owner) - stateSinkObject.Save(15, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.waiterQueue) + stateSinkObject.Save(3, &e.associated) + stateSinkObject.Save(4, &e.hdrIncluded) + stateSinkObject.Save(5, &e.rcvList) + stateSinkObject.Save(6, &e.rcvBufSize) + stateSinkObject.Save(8, &e.rcvClosed) + stateSinkObject.Save(9, &e.sndBufSize) + stateSinkObject.Save(10, &e.sndBufSizeMax) + stateSinkObject.Save(11, &e.closed) + stateSinkObject.Save(12, &e.connected) + stateSinkObject.Save(13, &e.bound) + stateSinkObject.Save(14, &e.linger) + stateSinkObject.Save(15, &e.owner) + stateSinkObject.Save(16, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.TransportEndpointInfo) - stateSourceObject.Load(1, &e.waiterQueue) - stateSourceObject.Load(2, &e.associated) - stateSourceObject.Load(3, &e.hdrIncluded) - stateSourceObject.Load(4, &e.rcvList) - stateSourceObject.Load(5, &e.rcvBufSize) - stateSourceObject.Load(7, &e.rcvClosed) - stateSourceObject.Load(8, &e.sndBufSize) - stateSourceObject.Load(9, &e.sndBufSizeMax) - stateSourceObject.Load(10, &e.closed) - stateSourceObject.Load(11, &e.connected) - stateSourceObject.Load(12, &e.bound) - stateSourceObject.Load(13, &e.linger) - stateSourceObject.Load(14, &e.owner) - stateSourceObject.Load(15, &e.ops) - stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &e.waiterQueue) + stateSourceObject.Load(3, &e.associated) + stateSourceObject.Load(4, &e.hdrIncluded) + stateSourceObject.Load(5, &e.rcvList) + stateSourceObject.Load(6, &e.rcvBufSize) + stateSourceObject.Load(8, &e.rcvClosed) + stateSourceObject.Load(9, &e.sndBufSize) + stateSourceObject.Load(10, &e.sndBufSizeMax) + stateSourceObject.Load(11, &e.closed) + stateSourceObject.Load(12, &e.connected) + stateSourceObject.Load(13, &e.bound) + stateSourceObject.Load(14, &e.linger) + stateSourceObject.Load(15, &e.owner) + stateSourceObject.Load(16, &e.ops) + stateSourceObject.LoadValue(7, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index 36b915510..f893324c2 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -362,6 +362,7 @@ func (*EndpointInfo) IsEndpointInfo() {} // +stateify savable type endpoint struct { EndpointInfo + tcpip.DefaultSocketOptionsHandler // endpointEntry is used to queue endpoints for processing to the // a given tcp processor goroutine. @@ -884,6 +885,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue windowClamp: DefaultReceiveBufferSize, maxSynRetries: DefaultSynRetries, } + e.ops.InitHandler(e) var ss tcpip.TCPSendBufferSizeRangeOption if err := s.TransportProtocolOption(ProtocolNumber, &ss); err == nil { @@ -1627,6 +1629,20 @@ func (e *endpoint) windowCrossedACKThresholdLocked(deltaBefore int) (crossed boo return false, false } +// OnReuseAddressSet implements tcpip.SocketOptionsHandler.OnReuseAddressSet. +func (e *endpoint) OnReuseAddressSet(v bool) { + e.LockUser() + e.portFlags.TupleOnly = v + e.UnlockUser() +} + +// OnReusePortSet implements tcpip.SocketOptionsHandler.OnReusePortSet. +func (e *endpoint) OnReusePortSet(v bool) { + e.LockUser() + e.portFlags.LoadBalanced = v + e.UnlockUser() +} + // SetSockOptBool sets a socket option. func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { switch opt { @@ -1666,16 +1682,6 @@ func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { } atomic.StoreUint32(&e.slowAck, o) - case tcpip.ReuseAddressOption: - e.LockUser() - e.portFlags.TupleOnly = v - e.UnlockUser() - - case tcpip.ReusePortOption: - e.LockUser() - e.portFlags.LoadBalanced = v - e.UnlockUser() - case tcpip.V6OnlyOption: // We only recognize this option on v6 endpoints. if e.NetProto != header.IPv6ProtocolNumber { @@ -1995,20 +2001,6 @@ func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) { v := atomic.LoadUint32(&e.slowAck) == 0 return v, nil - case tcpip.ReuseAddressOption: - e.LockUser() - v := e.portFlags.TupleOnly - e.UnlockUser() - - return v, nil - - case tcpip.ReusePortOption: - e.LockUser() - v := e.portFlags.LoadBalanced - e.UnlockUser() - - return v, nil - case tcpip.V6OnlyOption: // We only recognize this option on v6 endpoints. if e.NetProto != header.IPv6ProtocolNumber { diff --git a/pkg/tcpip/transport/tcp/tcp_state_autogen.go b/pkg/tcpip/transport/tcp/tcp_state_autogen.go index 56b58d41d..e9599cb6d 100644 --- a/pkg/tcpip/transport/tcp/tcp_state_autogen.go +++ b/pkg/tcpip/transport/tcp/tcp_state_autogen.go @@ -157,6 +157,7 @@ func (e *endpoint) StateTypeName() string { func (e *endpoint) StateFields() []string { return []string{ "EndpointInfo", + "DefaultSocketOptionsHandler", "waiterQueue", "uniqueID", "hardError", @@ -227,143 +228,145 @@ func (e *endpoint) StateFields() []string { func (e *endpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() var hardErrorValue string = e.saveHardError() - stateSinkObject.SaveValue(3, hardErrorValue) + stateSinkObject.SaveValue(4, hardErrorValue) var lastErrorValue string = e.saveLastError() - stateSinkObject.SaveValue(4, lastErrorValue) + stateSinkObject.SaveValue(5, lastErrorValue) var stateValue EndpointState = e.saveState() - stateSinkObject.SaveValue(12, stateValue) + stateSinkObject.SaveValue(13, stateValue) var recentTSTimeValue unixTime = e.saveRecentTSTime() - stateSinkObject.SaveValue(26, recentTSTimeValue) + stateSinkObject.SaveValue(27, recentTSTimeValue) var acceptedChanValue []*endpoint = e.saveAcceptedChan() - stateSinkObject.SaveValue(52, acceptedChanValue) + stateSinkObject.SaveValue(53, acceptedChanValue) stateSinkObject.Save(0, &e.EndpointInfo) - stateSinkObject.Save(1, &e.waiterQueue) - stateSinkObject.Save(2, &e.uniqueID) - stateSinkObject.Save(5, &e.rcvList) - stateSinkObject.Save(6, &e.rcvClosed) - stateSinkObject.Save(7, &e.rcvBufSize) - stateSinkObject.Save(8, &e.rcvBufUsed) - stateSinkObject.Save(9, &e.rcvAutoParams) - stateSinkObject.Save(10, &e.rcvMemUsed) - stateSinkObject.Save(11, &e.ownedByUser) - stateSinkObject.Save(13, &e.boundNICID) - stateSinkObject.Save(14, &e.ttl) - stateSinkObject.Save(15, &e.v6only) - stateSinkObject.Save(16, &e.isConnectNotified) - stateSinkObject.Save(17, &e.portFlags) - stateSinkObject.Save(18, &e.boundBindToDevice) - stateSinkObject.Save(19, &e.boundPortFlags) - stateSinkObject.Save(20, &e.boundDest) - stateSinkObject.Save(21, &e.effectiveNetProtos) - stateSinkObject.Save(22, &e.workerRunning) - stateSinkObject.Save(23, &e.workerCleanup) - stateSinkObject.Save(24, &e.sendTSOk) - stateSinkObject.Save(25, &e.recentTS) - stateSinkObject.Save(27, &e.tsOffset) - stateSinkObject.Save(28, &e.shutdownFlags) - stateSinkObject.Save(29, &e.sackPermitted) - stateSinkObject.Save(30, &e.sack) - stateSinkObject.Save(31, &e.bindToDevice) - stateSinkObject.Save(32, &e.delay) - stateSinkObject.Save(33, &e.cork) - stateSinkObject.Save(34, &e.scoreboard) - stateSinkObject.Save(35, &e.slowAck) - stateSinkObject.Save(36, &e.segmentQueue) - stateSinkObject.Save(37, &e.synRcvdCount) - stateSinkObject.Save(38, &e.userMSS) - stateSinkObject.Save(39, &e.maxSynRetries) - stateSinkObject.Save(40, &e.windowClamp) - stateSinkObject.Save(41, &e.sndBufSize) - stateSinkObject.Save(42, &e.sndBufUsed) - stateSinkObject.Save(43, &e.sndClosed) - stateSinkObject.Save(44, &e.sndBufInQueue) - stateSinkObject.Save(45, &e.sndQueue) - stateSinkObject.Save(46, &e.cc) - stateSinkObject.Save(47, &e.packetTooBigCount) - stateSinkObject.Save(48, &e.sndMTU) - stateSinkObject.Save(49, &e.keepalive) - stateSinkObject.Save(50, &e.userTimeout) - stateSinkObject.Save(51, &e.deferAccept) - stateSinkObject.Save(53, &e.rcv) - stateSinkObject.Save(54, &e.snd) - stateSinkObject.Save(55, &e.connectingAddress) - stateSinkObject.Save(56, &e.amss) - stateSinkObject.Save(57, &e.sendTOS) - stateSinkObject.Save(58, &e.gso) - stateSinkObject.Save(59, &e.tcpLingerTimeout) - stateSinkObject.Save(60, &e.closed) - stateSinkObject.Save(61, &e.txHash) - stateSinkObject.Save(62, &e.owner) - stateSinkObject.Save(63, &e.linger) - stateSinkObject.Save(64, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.waiterQueue) + stateSinkObject.Save(3, &e.uniqueID) + stateSinkObject.Save(6, &e.rcvList) + stateSinkObject.Save(7, &e.rcvClosed) + stateSinkObject.Save(8, &e.rcvBufSize) + stateSinkObject.Save(9, &e.rcvBufUsed) + stateSinkObject.Save(10, &e.rcvAutoParams) + stateSinkObject.Save(11, &e.rcvMemUsed) + stateSinkObject.Save(12, &e.ownedByUser) + stateSinkObject.Save(14, &e.boundNICID) + stateSinkObject.Save(15, &e.ttl) + stateSinkObject.Save(16, &e.v6only) + stateSinkObject.Save(17, &e.isConnectNotified) + stateSinkObject.Save(18, &e.portFlags) + stateSinkObject.Save(19, &e.boundBindToDevice) + stateSinkObject.Save(20, &e.boundPortFlags) + stateSinkObject.Save(21, &e.boundDest) + stateSinkObject.Save(22, &e.effectiveNetProtos) + stateSinkObject.Save(23, &e.workerRunning) + stateSinkObject.Save(24, &e.workerCleanup) + stateSinkObject.Save(25, &e.sendTSOk) + stateSinkObject.Save(26, &e.recentTS) + stateSinkObject.Save(28, &e.tsOffset) + stateSinkObject.Save(29, &e.shutdownFlags) + stateSinkObject.Save(30, &e.sackPermitted) + stateSinkObject.Save(31, &e.sack) + stateSinkObject.Save(32, &e.bindToDevice) + stateSinkObject.Save(33, &e.delay) + stateSinkObject.Save(34, &e.cork) + stateSinkObject.Save(35, &e.scoreboard) + stateSinkObject.Save(36, &e.slowAck) + stateSinkObject.Save(37, &e.segmentQueue) + stateSinkObject.Save(38, &e.synRcvdCount) + stateSinkObject.Save(39, &e.userMSS) + stateSinkObject.Save(40, &e.maxSynRetries) + stateSinkObject.Save(41, &e.windowClamp) + stateSinkObject.Save(42, &e.sndBufSize) + stateSinkObject.Save(43, &e.sndBufUsed) + stateSinkObject.Save(44, &e.sndClosed) + stateSinkObject.Save(45, &e.sndBufInQueue) + stateSinkObject.Save(46, &e.sndQueue) + stateSinkObject.Save(47, &e.cc) + stateSinkObject.Save(48, &e.packetTooBigCount) + stateSinkObject.Save(49, &e.sndMTU) + stateSinkObject.Save(50, &e.keepalive) + stateSinkObject.Save(51, &e.userTimeout) + stateSinkObject.Save(52, &e.deferAccept) + stateSinkObject.Save(54, &e.rcv) + stateSinkObject.Save(55, &e.snd) + stateSinkObject.Save(56, &e.connectingAddress) + stateSinkObject.Save(57, &e.amss) + stateSinkObject.Save(58, &e.sendTOS) + stateSinkObject.Save(59, &e.gso) + stateSinkObject.Save(60, &e.tcpLingerTimeout) + stateSinkObject.Save(61, &e.closed) + stateSinkObject.Save(62, &e.txHash) + stateSinkObject.Save(63, &e.owner) + stateSinkObject.Save(64, &e.linger) + stateSinkObject.Save(65, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.EndpointInfo) - stateSourceObject.LoadWait(1, &e.waiterQueue) - stateSourceObject.Load(2, &e.uniqueID) - stateSourceObject.LoadWait(5, &e.rcvList) - stateSourceObject.Load(6, &e.rcvClosed) - stateSourceObject.Load(7, &e.rcvBufSize) - stateSourceObject.Load(8, &e.rcvBufUsed) - stateSourceObject.Load(9, &e.rcvAutoParams) - stateSourceObject.Load(10, &e.rcvMemUsed) - stateSourceObject.Load(11, &e.ownedByUser) - stateSourceObject.Load(13, &e.boundNICID) - stateSourceObject.Load(14, &e.ttl) - stateSourceObject.Load(15, &e.v6only) - stateSourceObject.Load(16, &e.isConnectNotified) - stateSourceObject.Load(17, &e.portFlags) - stateSourceObject.Load(18, &e.boundBindToDevice) - stateSourceObject.Load(19, &e.boundPortFlags) - stateSourceObject.Load(20, &e.boundDest) - stateSourceObject.Load(21, &e.effectiveNetProtos) - stateSourceObject.Load(22, &e.workerRunning) - stateSourceObject.Load(23, &e.workerCleanup) - stateSourceObject.Load(24, &e.sendTSOk) - stateSourceObject.Load(25, &e.recentTS) - stateSourceObject.Load(27, &e.tsOffset) - stateSourceObject.Load(28, &e.shutdownFlags) - stateSourceObject.Load(29, &e.sackPermitted) - stateSourceObject.Load(30, &e.sack) - stateSourceObject.Load(31, &e.bindToDevice) - stateSourceObject.Load(32, &e.delay) - stateSourceObject.Load(33, &e.cork) - stateSourceObject.Load(34, &e.scoreboard) - stateSourceObject.Load(35, &e.slowAck) - stateSourceObject.LoadWait(36, &e.segmentQueue) - stateSourceObject.Load(37, &e.synRcvdCount) - stateSourceObject.Load(38, &e.userMSS) - stateSourceObject.Load(39, &e.maxSynRetries) - stateSourceObject.Load(40, &e.windowClamp) - stateSourceObject.Load(41, &e.sndBufSize) - stateSourceObject.Load(42, &e.sndBufUsed) - stateSourceObject.Load(43, &e.sndClosed) - stateSourceObject.Load(44, &e.sndBufInQueue) - stateSourceObject.LoadWait(45, &e.sndQueue) - stateSourceObject.Load(46, &e.cc) - stateSourceObject.Load(47, &e.packetTooBigCount) - stateSourceObject.Load(48, &e.sndMTU) - stateSourceObject.Load(49, &e.keepalive) - stateSourceObject.Load(50, &e.userTimeout) - stateSourceObject.Load(51, &e.deferAccept) - stateSourceObject.LoadWait(53, &e.rcv) - stateSourceObject.LoadWait(54, &e.snd) - stateSourceObject.Load(55, &e.connectingAddress) - stateSourceObject.Load(56, &e.amss) - stateSourceObject.Load(57, &e.sendTOS) - stateSourceObject.Load(58, &e.gso) - stateSourceObject.Load(59, &e.tcpLingerTimeout) - stateSourceObject.Load(60, &e.closed) - stateSourceObject.Load(61, &e.txHash) - stateSourceObject.Load(62, &e.owner) - stateSourceObject.Load(63, &e.linger) - stateSourceObject.Load(64, &e.ops) - stateSourceObject.LoadValue(3, new(string), func(y interface{}) { e.loadHardError(y.(string)) }) - stateSourceObject.LoadValue(4, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) - stateSourceObject.LoadValue(12, new(EndpointState), func(y interface{}) { e.loadState(y.(EndpointState)) }) - stateSourceObject.LoadValue(26, new(unixTime), func(y interface{}) { e.loadRecentTSTime(y.(unixTime)) }) - stateSourceObject.LoadValue(52, new([]*endpoint), func(y interface{}) { e.loadAcceptedChan(y.([]*endpoint)) }) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.LoadWait(2, &e.waiterQueue) + stateSourceObject.Load(3, &e.uniqueID) + stateSourceObject.LoadWait(6, &e.rcvList) + stateSourceObject.Load(7, &e.rcvClosed) + stateSourceObject.Load(8, &e.rcvBufSize) + stateSourceObject.Load(9, &e.rcvBufUsed) + stateSourceObject.Load(10, &e.rcvAutoParams) + stateSourceObject.Load(11, &e.rcvMemUsed) + stateSourceObject.Load(12, &e.ownedByUser) + stateSourceObject.Load(14, &e.boundNICID) + stateSourceObject.Load(15, &e.ttl) + stateSourceObject.Load(16, &e.v6only) + stateSourceObject.Load(17, &e.isConnectNotified) + stateSourceObject.Load(18, &e.portFlags) + stateSourceObject.Load(19, &e.boundBindToDevice) + stateSourceObject.Load(20, &e.boundPortFlags) + stateSourceObject.Load(21, &e.boundDest) + stateSourceObject.Load(22, &e.effectiveNetProtos) + stateSourceObject.Load(23, &e.workerRunning) + stateSourceObject.Load(24, &e.workerCleanup) + stateSourceObject.Load(25, &e.sendTSOk) + stateSourceObject.Load(26, &e.recentTS) + stateSourceObject.Load(28, &e.tsOffset) + stateSourceObject.Load(29, &e.shutdownFlags) + stateSourceObject.Load(30, &e.sackPermitted) + stateSourceObject.Load(31, &e.sack) + stateSourceObject.Load(32, &e.bindToDevice) + stateSourceObject.Load(33, &e.delay) + stateSourceObject.Load(34, &e.cork) + stateSourceObject.Load(35, &e.scoreboard) + stateSourceObject.Load(36, &e.slowAck) + stateSourceObject.LoadWait(37, &e.segmentQueue) + stateSourceObject.Load(38, &e.synRcvdCount) + stateSourceObject.Load(39, &e.userMSS) + stateSourceObject.Load(40, &e.maxSynRetries) + stateSourceObject.Load(41, &e.windowClamp) + stateSourceObject.Load(42, &e.sndBufSize) + stateSourceObject.Load(43, &e.sndBufUsed) + stateSourceObject.Load(44, &e.sndClosed) + stateSourceObject.Load(45, &e.sndBufInQueue) + stateSourceObject.LoadWait(46, &e.sndQueue) + stateSourceObject.Load(47, &e.cc) + stateSourceObject.Load(48, &e.packetTooBigCount) + stateSourceObject.Load(49, &e.sndMTU) + stateSourceObject.Load(50, &e.keepalive) + stateSourceObject.Load(51, &e.userTimeout) + stateSourceObject.Load(52, &e.deferAccept) + stateSourceObject.LoadWait(54, &e.rcv) + stateSourceObject.LoadWait(55, &e.snd) + stateSourceObject.Load(56, &e.connectingAddress) + stateSourceObject.Load(57, &e.amss) + stateSourceObject.Load(58, &e.sendTOS) + stateSourceObject.Load(59, &e.gso) + stateSourceObject.Load(60, &e.tcpLingerTimeout) + stateSourceObject.Load(61, &e.closed) + stateSourceObject.Load(62, &e.txHash) + stateSourceObject.Load(63, &e.owner) + stateSourceObject.Load(64, &e.linger) + stateSourceObject.Load(65, &e.ops) + stateSourceObject.LoadValue(4, new(string), func(y interface{}) { e.loadHardError(y.(string)) }) + stateSourceObject.LoadValue(5, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) + stateSourceObject.LoadValue(13, new(EndpointState), func(y interface{}) { e.loadState(y.(EndpointState)) }) + stateSourceObject.LoadValue(27, new(unixTime), func(y interface{}) { e.loadRecentTSTime(y.(unixTime)) }) + stateSourceObject.LoadValue(53, new([]*endpoint), func(y interface{}) { e.loadAcceptedChan(y.([]*endpoint)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go index 5aa16bf35..e57833644 100644 --- a/pkg/tcpip/transport/udp/endpoint.go +++ b/pkg/tcpip/transport/udp/endpoint.go @@ -77,6 +77,7 @@ func (s EndpointState) String() string { // +stateify savable type endpoint struct { stack.TransportEndpointInfo + tcpip.DefaultSocketOptionsHandler // The following fields are initialized at creation time and do not // change throughout the lifetime of the endpoint. @@ -194,6 +195,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue state: StateInitial, uniqueID: s.UniqueID(), } + e.ops.InitHandler(e) // Override with stack defaults. var ss stack.SendBufferSizeOption @@ -574,6 +576,20 @@ func (e *endpoint) Peek([][]byte) (int64, tcpip.ControlMessages, *tcpip.Error) { return 0, tcpip.ControlMessages{}, nil } +// OnReuseAddressSet implements tcpip.SocketOptionsHandler.OnReuseAddressSet. +func (e *endpoint) OnReuseAddressSet(v bool) { + e.mu.Lock() + e.portFlags.MostRecent = v + e.mu.Unlock() +} + +// OnReusePortSet implements tcpip.SocketOptionsHandler.OnReusePortSet. +func (e *endpoint) OnReusePortSet(v bool) { + e.mu.Lock() + e.portFlags.LoadBalanced = v + e.mu.Unlock() +} + // SetSockOptBool implements tcpip.Endpoint.SetSockOptBool. func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { switch opt { @@ -602,16 +618,6 @@ func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { e.receiveIPPacketInfo = v e.mu.Unlock() - case tcpip.ReuseAddressOption: - e.mu.Lock() - e.portFlags.MostRecent = v - e.mu.Unlock() - - case tcpip.ReusePortOption: - e.mu.Lock() - e.portFlags.LoadBalanced = v - e.mu.Unlock() - case tcpip.V6OnlyOption: // We only recognize this option on v6 endpoints. if e.NetProto != header.IPv6ProtocolNumber { @@ -875,20 +881,6 @@ func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) { e.mu.RUnlock() return v, nil - case tcpip.ReuseAddressOption: - e.mu.RLock() - v := e.portFlags.MostRecent - e.mu.RUnlock() - - return v, nil - - case tcpip.ReusePortOption: - e.mu.RLock() - v := e.portFlags.LoadBalanced - e.mu.RUnlock() - - return v, nil - case tcpip.V6OnlyOption: // We only recognize this option on v6 endpoints. if e.NetProto != header.IPv6ProtocolNumber { diff --git a/pkg/tcpip/transport/udp/udp_state_autogen.go b/pkg/tcpip/transport/udp/udp_state_autogen.go index 9350a4809..cb05b5cd8 100644 --- a/pkg/tcpip/transport/udp/udp_state_autogen.go +++ b/pkg/tcpip/transport/udp/udp_state_autogen.go @@ -53,6 +53,7 @@ func (e *endpoint) StateTypeName() string { func (e *endpoint) StateFields() []string { return []string{ "TransportEndpointInfo", + "DefaultSocketOptionsHandler", "waiterQueue", "uniqueID", "rcvReady", @@ -91,76 +92,78 @@ func (e *endpoint) StateFields() []string { func (e *endpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() var rcvBufSizeMaxValue int = e.saveRcvBufSizeMax() - stateSinkObject.SaveValue(5, rcvBufSizeMaxValue) + stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) var lastErrorValue string = e.saveLastError() - stateSinkObject.SaveValue(20, lastErrorValue) + stateSinkObject.SaveValue(21, lastErrorValue) stateSinkObject.Save(0, &e.TransportEndpointInfo) - stateSinkObject.Save(1, &e.waiterQueue) - stateSinkObject.Save(2, &e.uniqueID) - stateSinkObject.Save(3, &e.rcvReady) - stateSinkObject.Save(4, &e.rcvList) - stateSinkObject.Save(6, &e.rcvBufSize) - stateSinkObject.Save(7, &e.rcvClosed) - stateSinkObject.Save(8, &e.sndBufSize) - stateSinkObject.Save(9, &e.sndBufSizeMax) - stateSinkObject.Save(10, &e.state) - stateSinkObject.Save(11, &e.dstPort) - stateSinkObject.Save(12, &e.v6only) - stateSinkObject.Save(13, &e.ttl) - stateSinkObject.Save(14, &e.multicastTTL) - stateSinkObject.Save(15, &e.multicastAddr) - stateSinkObject.Save(16, &e.multicastNICID) - stateSinkObject.Save(17, &e.multicastLoop) - stateSinkObject.Save(18, &e.portFlags) - stateSinkObject.Save(19, &e.bindToDevice) - stateSinkObject.Save(21, &e.boundBindToDevice) - stateSinkObject.Save(22, &e.boundPortFlags) - stateSinkObject.Save(23, &e.sendTOS) - stateSinkObject.Save(24, &e.receiveTOS) - stateSinkObject.Save(25, &e.receiveTClass) - stateSinkObject.Save(26, &e.receiveIPPacketInfo) - stateSinkObject.Save(27, &e.shutdownFlags) - stateSinkObject.Save(28, &e.multicastMemberships) - stateSinkObject.Save(29, &e.effectiveNetProtos) - stateSinkObject.Save(30, &e.owner) - stateSinkObject.Save(31, &e.linger) - stateSinkObject.Save(32, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.waiterQueue) + stateSinkObject.Save(3, &e.uniqueID) + stateSinkObject.Save(4, &e.rcvReady) + stateSinkObject.Save(5, &e.rcvList) + stateSinkObject.Save(7, &e.rcvBufSize) + stateSinkObject.Save(8, &e.rcvClosed) + stateSinkObject.Save(9, &e.sndBufSize) + stateSinkObject.Save(10, &e.sndBufSizeMax) + stateSinkObject.Save(11, &e.state) + stateSinkObject.Save(12, &e.dstPort) + stateSinkObject.Save(13, &e.v6only) + stateSinkObject.Save(14, &e.ttl) + stateSinkObject.Save(15, &e.multicastTTL) + stateSinkObject.Save(16, &e.multicastAddr) + stateSinkObject.Save(17, &e.multicastNICID) + stateSinkObject.Save(18, &e.multicastLoop) + stateSinkObject.Save(19, &e.portFlags) + stateSinkObject.Save(20, &e.bindToDevice) + stateSinkObject.Save(22, &e.boundBindToDevice) + stateSinkObject.Save(23, &e.boundPortFlags) + stateSinkObject.Save(24, &e.sendTOS) + stateSinkObject.Save(25, &e.receiveTOS) + stateSinkObject.Save(26, &e.receiveTClass) + stateSinkObject.Save(27, &e.receiveIPPacketInfo) + stateSinkObject.Save(28, &e.shutdownFlags) + stateSinkObject.Save(29, &e.multicastMemberships) + stateSinkObject.Save(30, &e.effectiveNetProtos) + stateSinkObject.Save(31, &e.owner) + stateSinkObject.Save(32, &e.linger) + stateSinkObject.Save(33, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.TransportEndpointInfo) - stateSourceObject.Load(1, &e.waiterQueue) - stateSourceObject.Load(2, &e.uniqueID) - stateSourceObject.Load(3, &e.rcvReady) - stateSourceObject.Load(4, &e.rcvList) - stateSourceObject.Load(6, &e.rcvBufSize) - stateSourceObject.Load(7, &e.rcvClosed) - stateSourceObject.Load(8, &e.sndBufSize) - stateSourceObject.Load(9, &e.sndBufSizeMax) - stateSourceObject.Load(10, &e.state) - stateSourceObject.Load(11, &e.dstPort) - stateSourceObject.Load(12, &e.v6only) - stateSourceObject.Load(13, &e.ttl) - stateSourceObject.Load(14, &e.multicastTTL) - stateSourceObject.Load(15, &e.multicastAddr) - stateSourceObject.Load(16, &e.multicastNICID) - stateSourceObject.Load(17, &e.multicastLoop) - stateSourceObject.Load(18, &e.portFlags) - stateSourceObject.Load(19, &e.bindToDevice) - stateSourceObject.Load(21, &e.boundBindToDevice) - stateSourceObject.Load(22, &e.boundPortFlags) - stateSourceObject.Load(23, &e.sendTOS) - stateSourceObject.Load(24, &e.receiveTOS) - stateSourceObject.Load(25, &e.receiveTClass) - stateSourceObject.Load(26, &e.receiveIPPacketInfo) - stateSourceObject.Load(27, &e.shutdownFlags) - stateSourceObject.Load(28, &e.multicastMemberships) - stateSourceObject.Load(29, &e.effectiveNetProtos) - stateSourceObject.Load(30, &e.owner) - stateSourceObject.Load(31, &e.linger) - stateSourceObject.Load(32, &e.ops) - stateSourceObject.LoadValue(5, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) - stateSourceObject.LoadValue(20, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &e.waiterQueue) + stateSourceObject.Load(3, &e.uniqueID) + stateSourceObject.Load(4, &e.rcvReady) + stateSourceObject.Load(5, &e.rcvList) + stateSourceObject.Load(7, &e.rcvBufSize) + stateSourceObject.Load(8, &e.rcvClosed) + stateSourceObject.Load(9, &e.sndBufSize) + stateSourceObject.Load(10, &e.sndBufSizeMax) + stateSourceObject.Load(11, &e.state) + stateSourceObject.Load(12, &e.dstPort) + stateSourceObject.Load(13, &e.v6only) + stateSourceObject.Load(14, &e.ttl) + stateSourceObject.Load(15, &e.multicastTTL) + stateSourceObject.Load(16, &e.multicastAddr) + stateSourceObject.Load(17, &e.multicastNICID) + stateSourceObject.Load(18, &e.multicastLoop) + stateSourceObject.Load(19, &e.portFlags) + stateSourceObject.Load(20, &e.bindToDevice) + stateSourceObject.Load(22, &e.boundBindToDevice) + stateSourceObject.Load(23, &e.boundPortFlags) + stateSourceObject.Load(24, &e.sendTOS) + stateSourceObject.Load(25, &e.receiveTOS) + stateSourceObject.Load(26, &e.receiveTClass) + stateSourceObject.Load(27, &e.receiveIPPacketInfo) + stateSourceObject.Load(28, &e.shutdownFlags) + stateSourceObject.Load(29, &e.multicastMemberships) + stateSourceObject.Load(30, &e.effectiveNetProtos) + stateSourceObject.Load(31, &e.owner) + stateSourceObject.Load(32, &e.linger) + stateSourceObject.Load(33, &e.ops) + stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) + stateSourceObject.LoadValue(21, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) stateSourceObject.AfterLoad(e.afterLoad) } |