Documentation
¶
Index ¶
- Variables
- func AbortConn(conn net.Conn) error
- type Push
- func (push *Push) Add(id uint16, sub PushSubscribe)
- func (push *Push) CanAdd(id uint16, tlv dsomessage.Subscribe) (sub PushSubscribe, rcode uint8, err error)
- func (push *Push) IsActive() bool
- func (push *Push) Reconfirm(tlv dsomessage.Reconfirm)
- func (push *Push) Refresh()
- func (push *Push) Remove(tlv dsomessage.Unsubscribe) (dsomessage.Subscribe, bool)
- func (push *Push) Serve(ctx context.Context, writer io.Writer, upstream PushLookuper, ...) error
- func (push *Push) Subscriptions() iter.Seq[dsomessage.Subscribe]
- type PushDebugWriter
- type PushLookuper
- type PushSubscribe
- type Session
- type State
Constants ¶
This section is empty.
Variables ¶
var ( ErrState = fmt.Errorf("bad DSO state") ErrStateClosed = fmt.Errorf("%w - closed", ErrState) )
var ErrDuplicateSub = errors.New("duplicate Push subscription")
var SessionGracefulCloseTimeout = 5 * time.Second
SessionGracefulCloseTimeout is amount of time before aborting after termination is initiated.
RFC 8490, Section 6.6.1: After sending a DSO Retry Delay message, the server SHOULD allow the client five seconds to close the connection.
Functions ¶
Types ¶
type Push ¶
type Push struct {
// contains filtered or unexported fields
}
Push stores DSO Push subscriptions.
func NewPush ¶
NewPush returns new Push service.
Classes and types, which Push takes ownership of, control allowed subscriptions and wildcard expansion. Must be sorted in increasing order.
func (*Push) CanAdd ¶
func (push *Push) CanAdd(id uint16, tlv dsomessage.Subscribe) (sub PushSubscribe, rcode uint8, err error)
CanAdd checks if subscription can be added.
Non-nil error indicates fatal protocol violation. Rcode indicates whether and how subscription request should be rejected. Only dns.RcodeSuccess indicates that subscription is vetted for Push.Add.
func (*Push) Reconfirm ¶
func (push *Push) Reconfirm(tlv dsomessage.Reconfirm)
Reconfirm schedules check that confirms whether RDATA is accurate.
func (*Push) Refresh ¶
func (push *Push) Refresh()
Refresh subscriptions ahead of periodic interval.
func (*Push) Remove ¶
func (push *Push) Remove(tlv dsomessage.Unsubscribe) (dsomessage.Subscribe, bool)
Remove stops refreshing subscription. It's permitted to remove non-existent subscriptions.
func (*Push) Serve ¶
func (push *Push) Serve(ctx context.Context, writer io.Writer, upstream PushLookuper, debounceDelay, refreshInterval time.Duration) error
Serve serves Push session by updating clients until context is cancelled.
Subscriptions are periodically refreshed (refreshInterval) via upstream lookups. Initial subscription burst is countered by debounceDelay. The difference is sent to client.
See also PushDebugWriter.
Returns context.Context.Err if stopped gracefully. Otherwise returns resolving, packing or writing error.
func (*Push) Subscriptions ¶
func (push *Push) Subscriptions() iter.Seq[dsomessage.Subscribe]
Subscriptions returns currently active subscriptions.
type PushDebugWriter ¶ added in v0.2.0
type PushDebugWriter interface {
io.Writer
// WritePushChange receives deep copy of change after it's written.
WritePushChange(change []dns.RR)
}
PushDebugWriter can be optionally implemented by writer passed to Push.Serve to observe changes sent to client.
type PushLookuper ¶
type PushLookuper interface {
// Lookup returns RRset that corresponds to given subscription.
//
// Lookup can be abandoned once context is cancelled.
// Returned RRset must follow RFC 8765, Section 6.3.1
LookupPushSubscription(ctx context.Context, tlv dsomessage.Subscribe) (rrs []dns.RR, ok bool)
}
PushLookuper resolves subscription on behalf of Push.
type PushSubscribe ¶
type PushSubscribe struct {
dsomessage.Subscribe
// contains filtered or unexported fields
}
PushSubscribe is dsomessage.Subscribe vetted by Push.CanAdd.
type Session ¶
Session implements server-side state management of RFC 8490 DNS Stateful Operations session.
- Initially, state is StateWaiting
- First written DSO response with RCODE=0 is establishing response, it changes state to StatePending
- If write fails state is reset back to StateWaiting. Otherwise it's changed to StateEstablished
- First written unidirectional with dsomessage.RetryDelay primary TLV initiates termination and changes state to StateClosing
- Once connection is closed, state is changed to StateClosed
Once session termination is initiated, no more messages can be written. If write of terminating message fails state remains StateClosing until Session.Close or Session.Abort is called.
func (*Session) Abort ¶
Abort forcibly closes underlying connection, e.g. with RST.
Abort is implemented by calling NetConn() and SetLinger(0) on underlying connection, if possible.
func (*Session) Drain ¶
Drain drains connection including its underlying transport, if any.
Draining makes peer responsible to send FIN and thus avoids TIME-WAIT on socket behind Session.Conn.
RFC 8490, Section 5.3: Where this specification requires a connection to be closed gracefully, the requirement to initiate that graceful close is placed on the client in order to place the burden of TCP's TIME-WAIT state on the client rather than the server.
func (*Session) Write ¶
Write writes length-prefixed message and updates session's state if needed.
Returns ErrStateClosed if session is closed, ErrState if it's in wrong state. Otherwise IO error is returned, if any.
Session terminating dsomessage.RetryDelay unidirectional is recognized: it's last allowed message.
type State ¶
type State uint32
const ( // StateWaiting is state where session is waiting for establishing response: // - Any DNS can be read or written // - Only DSO requests can be read // - Only DSO responses can be written StateWaiting State = iota // StatePending is state where session is handling writing establishing response: // - Any DNS can be read or written // - Any DSO can be read // - Only DSO responses can be written StatePending // StateEstablished is state where session is successfully established: // - Any DNS can be read or written // - Any DSO can be read or written StateEstablished // StateClosing is state where session is closed but underlying connect may still functional: // - Any DNS can be read or written // - Any DSO can be read // - No DSO can be written StateClosing // StateClosed is state where session is closed and underlying connection is non-functional: // - No DNS can be read or written // - No DSO can be read or written StateClosed )