diff --git a/README.md b/README.md index f8ffe1ea0b..60355ca2f9 100644 --- a/README.md +++ b/README.md @@ -444,3 +444,43 @@ go run github.com/loov/goda@latest graph github.com/skycoin/skywire/... | dot -T ``` ![Dependency Graph](docs/skywire-goda-graph.svg "github.com/skycoin/skywire Dependency Graph") + +## Lines of Code + +Made with [gocloc](https://github.com/hhatto/gocloc) (excludes `vendor/`, `node_modules/`, `.git/`): + +``` +gocloc --not-match-d='(vendor|node_modules|\.git)' . +``` + +``` +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Go 1740 45601 65791 267754 +Markdown 660 12807 39 40089 +JSON 1453 380 0 36078 +TypeScript 156 3825 6460 22780 +HTML 103 1292 1221 15820 +JavaScript 33 392 858 6811 +Sass 90 1239 350 6529 +BASH 41 365 701 1661 +TOML 10 215 37 1656 +Plain Text 6 342 0 1351 +YAML 8 40 127 1094 +Makefile 3 145 34 553 +Protocol Buffers 1 66 385 349 +Starlark 23 59 424 271 +Nix 3 38 151 245 +WiX 2 31 14 145 +Batch 2 13 0 105 +PowerShell 1 11 0 91 +XML 2 0 0 51 +C 1 14 24 46 +Bourne Shell 5 14 0 43 +CSS 3 4 10 32 +Assembly 3 9 13 20 +------------------------------------------------------------------------------- +TOTAL 4349 66902 76639 403574 +------------------------------------------------------------------------------- +``` diff --git a/cmd/apps/skychat/commands/cxo_tcp.go b/cmd/apps/skychat/commands/cxo_tcp.go index 27dee3a99c..64e2fd446c 100644 --- a/cmd/apps/skychat/commands/cxo_tcp.go +++ b/cmd/apps/skychat/commands/cxo_tcp.go @@ -251,8 +251,14 @@ func startCXOGroup(ctx context.Context) error { // zero, i.e. never connected). Once a peer connects and its first Root // lands, lastInbound is set and the treestore watchdog takes over // quiet-reconnects, so we stop poking it. + // + // Cadence is short (a few seconds): two members that start close together + // each fail the other's initial dial (peer not listening yet), so at the + // old 15s cadence a late joiner's first message took ~30-40s to arrive + // (measured). The loop skips already-attached peers, so once everyone is + // connected it idles cheaply — a fast tick only costs work while warming up. go func() { - t := time.NewTicker(15 * time.Second) + t := time.NewTicker(3 * time.Second) defer t.Stop() for { select { @@ -263,7 +269,7 @@ func startCXOGroup(ctx context.Context) error { if ppk == pk || !sess.PeerLastInbound(ppk).IsZero() { continue } - rctx, cancel := context.WithTimeout(ctx, 20*time.Second) + rctx, cancel := context.WithTimeout(ctx, 10*time.Second) if rerr := sess.ReconnectPeer(rctx, ppk); rerr != nil { appLog("skychat: cxo-group reconnect %s: %v", ppk, rerr) } diff --git a/cmd/apps/skychat/commands/sendack.go b/cmd/apps/skychat/commands/sendack.go index a5fc416e3b..d591921f81 100644 --- a/cmd/apps/skychat/commands/sendack.go +++ b/cmd/apps/skychat/commands/sendack.go @@ -30,24 +30,21 @@ package commands import ( - "encoding/json" "sync" "time" + + "github.com/skycoin/skywire/pkg/skychat/message" ) -// chatEnvelope is the on-the-wire shape for both chat-msg (carries -// body) and chat-ack (just id). Fields are encoded omitempty so the -// two share one Go struct without leaking irrelevant fields. -type chatEnvelope struct { - Type string `json:"type"` - ID string `json:"id"` - Body string `json:"body,omitempty"` - Ack bool `json:"ack,omitempty"` // chat-msg only: request ack-on-receipt -} +// chatEnvelope / chatTypeMsg / chatTypeAck alias the shared skychat wire types +// (pkg/skychat/message) so this file's ack routing and the envelope construction +// in skychat.go keep their familiar local names while the on-the-wire shape lives +// in exactly one place. +type chatEnvelope = message.Envelope const ( - chatTypeMsg = "chat-msg" - chatTypeAck = "chat-ack" + chatTypeMsg = message.TypeMsg + chatTypeAck = message.TypeAck ) // ackWaiters routes an inbound chat-ack envelope back to the @@ -107,12 +104,8 @@ func deliverAck(id string) { // "not an envelope" so plain-text JSON-looking chat (e.g. someone // typing literal {} into a chat window) still reaches its peer. func tryHandleChatEnvelope(payload []byte, peerPKHex string, sendAck func(id string)) (handled bool, body string, id string) { - trimmed := bytesTrimSpace(payload) - if len(trimmed) == 0 || trimmed[0] != '{' { - return false, "", "" - } - var env chatEnvelope - if err := json.Unmarshal(trimmed, &env); err != nil { + env, ok := message.ParseEnvelope(payload) + if !ok { return false, "", "" } switch env.Type { diff --git a/cmd/apps/skychat/commands/skychat.go b/cmd/apps/skychat/commands/skychat.go index a974415983..c435686b7b 100644 --- a/cmd/apps/skychat/commands/skychat.go +++ b/cmd/apps/skychat/commands/skychat.go @@ -9,7 +9,6 @@ import ( "encoding/json" "errors" "fmt" - "io" "io/fs" "log" "net" @@ -38,73 +37,29 @@ import ( "github.com/skycoin/skywire/pkg/logging" "github.com/skycoin/skywire/pkg/netutil" "github.com/skycoin/skywire/pkg/routing" + "github.com/skycoin/skywire/pkg/skychat/message" "github.com/skycoin/skywire/pkg/skyenv" "github.com/skycoin/skywire/pkg/visor" ) var r = netutil.NewRetrier(nil, 50*time.Millisecond, netutil.DefaultMaxBackoff, 5, 2) -// Wire-protocol constants for skychat's peer-to-peer messages. +// skychat's peer-to-peer wire format — length-prefixed frames plus the +// chat-msg/chat-ack envelope — now lives in one place: pkg/skychat/message. +// framedConn is a thin alias over message.Conn so the many call sites in this +// file keep their local name; newFramedConn wraps a raw appnet conn with framing +// and a write mutex (needed because the /message handler and the pair-control +// sender can race to write the same conn — interleaving one frame's length prefix +// with another's payload would desync the receiver permanently). // -// Pre-2026-05-12 the protocol was "one conn.Write = one conn.Read": -// every message was sent as a raw byte slice and the receiver -// assumed each Read returned exactly one message. That held for -// dmsg (noise-framed up to 4 KB) but broke on the skynet route -// path — appnet.directConn wraps transport.VStream, which is a -// TCP-style stream that can split a single Write across multiple -// Reads at arbitrary boundaries depending on route MTU. A -// 600-byte chat message would arrive as two "messages" on the -// receiver and the second half would surface as a separate chat -// entry, looking to operators like the message was truncated. -// -// New protocol: length-prefixed frames. Each message is a 4-byte -// big-endian length followed by exactly that many bytes of -// payload. Old binaries can no longer talk to new ones — peers -// must update together. The pair-control envelope (JSON `{type: -// "pair-invite" | ...}`) keeps the same on-the-wire bytes; only -// the framing around it changed. -const skychatMaxFrameSize = 64 * 1024 - -// framedConn wraps an appnet conn with length-prefixed framing -// and a write mutex. The write mutex matters because two -// callers (the HTTP /message handler and the pair-control -// sender) can race to write to the same underlying conn — and -// with framing, interleaving the length prefix of one message -// with the payload of another would desync the receiver -// permanently. The read path has a single owner (handleConn) -// so no read mutex is needed. -type framedConn struct { - net.Conn - writeMu sync.Mutex -} - -func newFramedConn(c net.Conn) *framedConn { return &framedConn{Conn: c} } +// History: pre-2026-05-12 the protocol was "one Write = one Read" (a raw byte +// slice per message). That held on dmsg (noise-framed) but broke on skynet +// routes, where a VStream can split one Write across several Reads at arbitrary +// boundaries — a 600-byte message arrived as two chat entries. The length-prefixed +// frame fixed that; old unframed binaries can't talk to framed ones. +type framedConn = message.Conn -// WriteFrame writes a length-prefixed message. Returns an error -// if the payload is empty or exceeds skychatMaxFrameSize. -// -// Unbounded — if the underlying net.Conn's Write blocks (peer not -// draining, transport stuck), the call blocks indefinitely and the -// caller's request goroutine is wedged. messageHandler uses -// WriteFrameDeadline below instead so a slow peer can't pin the -// /message handler forever. -func (c *framedConn) WriteFrame(payload []byte) error { - if len(payload) == 0 { - return errors.New("skychat: empty payload") - } - if len(payload) > skychatMaxFrameSize { - return fmt.Errorf("skychat: payload %d > max %d", len(payload), skychatMaxFrameSize) - } - c.writeMu.Lock() - defer c.writeMu.Unlock() - var hdr [4]byte - binary.BigEndian.PutUint32(hdr[:], uint32(len(payload))) //nolint:gosec - if _, err := c.Conn.Write(hdr[:]); err != nil { - return err - } - _, err := c.Conn.Write(payload) - return err -} +func newFramedConn(c net.Conn) *framedConn { return message.NewConn(c) } // messageWriteTimeout bounds a single WriteFrame call from the // /message HTTP handler. Picked above the typical successful-send @@ -126,57 +81,6 @@ func (c *framedConn) WriteFrame(payload []byte) error { // caller's send is freed. const messageWriteTimeout = 5 * time.Second -// WriteFrameDeadline is the bounded variant used from -// messageHandler. Sets a write deadline on the underlying net.Conn -// for the duration of this Write call, then resets it on the way -// out — so the deadline scope is exactly the framed write and -// future calls aren't accidentally pre-expired by a lingering -// deadline. A net.Conn-level timeout surfaces as an error from -// Write whose Timeout() method returns true, which the caller can -// distinguish from a connection-reset or peer-close. -// -// timeout must be > 0; pass 0 to fall back to plain WriteFrame -// (no deadline). The reset uses time.Time{} which net.Conn -// documents as "no deadline". -func (c *framedConn) WriteFrameDeadline(payload []byte, timeout time.Duration) error { - if timeout <= 0 { - return c.WriteFrame(payload) - } - // Acquire writeMu BEFORE setting the deadline so the deadline - // scope tracks the actual on-wire write rather than including - // time spent waiting behind a concurrent same-peer writer. If - // the wait itself wedges, the caller's HTTP context-deadline - // is the outer ceiling. - c.writeMu.Lock() - defer c.writeMu.Unlock() - - if err := c.Conn.SetWriteDeadline(time.Now().Add(timeout)); err != nil { - // SetWriteDeadline failure is rare on a healthy net.Conn; - // fall through to a best-effort unbounded write rather - // than blocking the message entirely on a metadata error. - // Subsequent SetWriteDeadline(time.Time{}) reset on the - // way out is also best-effort. - _ = err //nolint:errcheck - } - defer func() { - _ = c.Conn.SetWriteDeadline(time.Time{}) //nolint:errcheck - }() - - if len(payload) == 0 { - return errors.New("skychat: empty payload") - } - if len(payload) > skychatMaxFrameSize { - return fmt.Errorf("skychat: payload %d > max %d", len(payload), skychatMaxFrameSize) - } - var hdr [4]byte - binary.BigEndian.PutUint32(hdr[:], uint32(len(payload))) //nolint:gosec - if _, err := c.Conn.Write(hdr[:]); err != nil { - return err - } - _, err := c.Conn.Write(payload) - return err -} - // dialAndCache dials the peer at addr (using the package retrier), // wraps the raw conn in framing, registers it in the conns cache, // and starts the read loop. Used both from the cache-miss path in @@ -256,29 +160,6 @@ func tryNetworkFallback(ctx context.Context, pk cipher.PubKey, currentNet appnet return conn, altAddr } -// ReadFrame reads exactly one length-prefixed message. Rejects -// frames over skychatMaxFrameSize so a malicious or out-of-sync -// peer can't allocate gigabytes of memory by claiming a giant -// length. -func (c *framedConn) ReadFrame() ([]byte, error) { - var hdr [4]byte - if _, err := io.ReadFull(c.Conn, hdr[:]); err != nil { - return nil, err - } - length := binary.BigEndian.Uint32(hdr[:]) - if length == 0 { - return nil, errors.New("skychat: zero-length frame") - } - if length > skychatMaxFrameSize { - return nil, fmt.Errorf("skychat: frame %d > max %d (peer running old unframed protocol?)", length, skychatMaxFrameSize) - } - payload := make([]byte, length) - if _, err := io.ReadFull(c.Conn, payload); err != nil { - return nil, err - } - return payload, nil -} - var ( addr string appCl *app.Client diff --git a/cmd/apps/skychat/group/manager.go b/cmd/apps/skychat/group/manager.go index daff2fdb6e..2bfcab4082 100644 --- a/cmd/apps/skychat/group/manager.go +++ b/cmd/apps/skychat/group/manager.go @@ -42,12 +42,13 @@ import ( // Manager owns the persistent record set and live Session instances. // Safe for concurrent use. type Manager struct { - store *Store - dmsgC *dmsg.Client - myPK cipher.PubKey - mySK cipher.SecKey - dataDir string - log *logging.Logger + store *Store + dmsgC *dmsg.Client + myPK cipher.PubKey + mySK cipher.SecKey + dataDir string + inMemoryDB bool + log *logging.Logger // portAlloc decides which DMSG port to assign to a brand-new // owner-side group. Defaults to a random pick from a reserved @@ -99,6 +100,11 @@ type ManagerConfig struct { DataDir string Logger *logging.Logger + // InMemoryDB runs every session's CXO tree in memory (no DataDir / + // filesystem). Required for the browser (js/wasm) visor. When set, DataDir + // may be empty. Forwarded to each group.Config the Manager opens. + InMemoryDB bool + // HeartbeatInterval, when > 0, makes every owner-role session // opened by this Manager emit a periodic no-op heartbeat probe. // Members observe these to detect a silently-stalled CXO @@ -122,8 +128,8 @@ func NewManager(cfg ManagerConfig) (*Manager, error) { if cfg.DmsgC == nil { return nil, errors.New("group: NewManager: DmsgC required") } - if cfg.DataDir == "" { - return nil, errors.New("group: NewManager: DataDir required") + if cfg.DataDir == "" && !cfg.InMemoryDB { + return nil, errors.New("group: NewManager: DataDir required (unless InMemoryDB)") } log := cfg.Logger if log == nil { @@ -135,6 +141,7 @@ func NewManager(cfg ManagerConfig) (*Manager, error) { myPK: cfg.MyPK, mySK: cfg.MySK, dataDir: cfg.DataDir, + inMemoryDB: cfg.InMemoryDB, log: log, portAlloc: defaultPortAlloc, sessions: make(map[string]*Session), @@ -598,6 +605,19 @@ func (m *Manager) Resume() error { // isn't dial-hammered. const reconnectInterval = 30 * time.Second +// reconnectWarmupInterval is the fast cadence the reconnect loop uses while a +// session still has a peer that has NEVER connected (its initial peer-sub dial +// failed because the peer wasn't listening yet — the common case when two +// members start close together, or a member joins late). At the steady +// reconnectInterval (30s) that peer's first message took ~30-40s to arrive +// (measured, 2026-07-02). While any peer is still "warming" (never connected and +// under its failure budget) the loop ticks at this cadence so a late joiner +// converges in a few seconds; it eases back to reconnectInterval once every peer +// is attached, so steady-state groups keep their low-churn 30s cadence. A +// genuinely dead peer stops qualifying once it exhausts reconnectBackoffFailures1 +// attempts, so one dead peer can't pin the loop fast forever. +const reconnectWarmupInterval = 3 * time.Second + // subscriberStaleThreshold is the lag (now - Session.LastInbound()) // above which a member session is considered stale enough to warrant // a reconnect attempt. Set to 3× the owner heartbeat cadence (~30s) @@ -673,7 +693,14 @@ func (m *Manager) startReconnectLoop() { // - warn: every backoff-interval transition func (m *Manager) runReconnectLoop(ctx context.Context) { defer m.reconnectWG.Done() - t := time.NewTicker(reconnectInterval) + // Adaptive cadence: fast (reconnectWarmupInterval) while any peer is still + // warming up, easing back to reconnectInterval once every peer is attached. + // This is the recovery side of the "late joiner takes ~30-40s to receive its + // first message" fix — the initial peer-sub Connect can fail (peer not + // listening yet) and this loop is what retries it; at 30s that retry was slow. + // A single timer (not a fixed Ticker) so the interval can change per pass. + interval := reconnectWarmupInterval + t := time.NewTimer(interval) defer t.Stop() for { select { @@ -682,7 +709,62 @@ func (m *Manager) runReconnectLoop(ctx context.Context) { case <-t.C: } m.detectStaleAndReconnect(ctx) + if m.hasWarmingPeer() { + interval = reconnectWarmupInterval + } else if interval < reconnectInterval { + if interval *= 2; interval > reconnectInterval { + interval = reconnectInterval + } + } + t.Reset(interval) + } +} + +// hasWarmingPeer reports whether any active/pending session still has a peer that +// has never connected (zero PeerLastInbound) and is still within its fast-retry +// budget (fewer than reconnectBackoffFailures1 failures). The reconnect loop uses +// this to hold the fast warmup cadence while a freshly-joined or late-arriving +// peer converges, then ease back to the steady 30s once everyone is attached. A +// dead peer stops qualifying once it exhausts its budget (it then falls to the +// 5min/30min backoff), so one dead peer can't keep the loop fast forever. +func (m *Manager) hasWarmingPeer() bool { + records, err := m.store.List() + if err != nil { + return false + } + for _, r := range records { + if r.Status != StatusActive && r.Status != StatusPending { + continue + } + m.mu.RLock() + sess := m.sessions[r.ID] + m.mu.RUnlock() + if sess == nil { + continue + } + for _, pk := range sess.PeerPKs() { + if !sess.PeerLastInbound(pk).IsZero() { + continue // already attached + } + if m.peerReconnectFailures(r.ID, pk) < reconnectBackoffFailures1 { + return true + } + } + } + return false +} + +// peerReconnectFailures returns the recorded consecutive-failure count for a +// (group, peer) reconnect entry, or 0 if none is tracked yet. +func (m *Manager) peerReconnectFailures(id string, pk cipher.PubKey) uint32 { + m.reconnectMu.Lock() + defer m.reconnectMu.Unlock() + if peers, ok := m.peerReconnectState[id]; ok { + if st, ok := peers[pk]; ok { + return st.failures + } } + return 0 } // detectStaleAndReconnect walks every session (both owner-role AND @@ -1365,6 +1447,7 @@ func (m *Manager) openLocked(r Record) (*Session, error) { Record: r, DmsgC: m.dmsgC, DataDir: m.dataDir, + InMemoryDB: m.inMemoryDB, Logger: m.log, HeartbeatInterval: m.heartbeatInterval, }) diff --git a/cmd/apps/skychat/group/session.go b/cmd/apps/skychat/group/session.go index 0798d051b7..bbe7d1a30e 100644 --- a/cmd/apps/skychat/group/session.go +++ b/cmd/apps/skychat/group/session.go @@ -38,7 +38,6 @@ import ( "encoding/json" "errors" "fmt" - "io" "net" "path/filepath" "sort" @@ -56,6 +55,7 @@ import ( "github.com/skycoin/skywire/pkg/dmsg/dmsg" "github.com/skycoin/skywire/pkg/logging" "github.com/skycoin/skywire/pkg/routing" + "github.com/skycoin/skywire/pkg/skychat/message" ) // cryptoRandRead aliases crypto/rand.Read so newRelayMsgID reads @@ -225,9 +225,19 @@ type Config struct { DmsgC *dmsg.Client // DataDir is the per-visor parent directory for CXO state. Each - // Session carves its own group// subtree inside it. + // Session carves its own group// subtree inside it. Ignored (and + // may be empty) when InMemoryDB is set. DataDir string + // InMemoryDB runs the session's CXO tree entirely in memory, with no + // DataDir / filesystem access. Required for the browser (js/wasm) visor, + // which has no disk. The native-TCP standalone path already forces this + // internally (see newPublisher); this flag extends it to the dmsg path so a + // wasm visor can be a full federated group member — it publishes its own + // feed in memory and subscribes to peers over dmsg, and the network retains + // whatever it published (state resets on tab reload; re-subscribe replays). + InMemoryDB bool + // Logger is optional; nil falls back to a tag-based default. Logger *logging.Logger @@ -525,11 +535,6 @@ type RelayAck struct { MsgID string `json:"msg_id,omitempty"` } -// relayMaxFrameSize bounds the claimed-length sanity check on the -// owner's read side. 64 KiB matches every other framed-wire in the -// skychat tree. -const relayMaxFrameSize = 64 * 1024 - // relayAckReadTimeout caps how long the member waits for the // owner's RelayAck before giving up. Sized for "owner publishAs // completes in a normal CXO commit window" — bbolt-backed @@ -548,6 +553,13 @@ const relayAckReadTimeout = 5 * time.Second // transport: DMSG when cfg.DmsgC is set, otherwise the CXO node's // native TCP transport on cfg.TCPListenAddr (no dmsg/discovery). func (cfg Config) newPublisher(pc treestore.PubConfig) (*treestore.Publisher, error) { + if cfg.InMemoryDB { + // Browser (js/wasm) visor: no filesystem. Run the CXO tree in memory — + // content-addressed and republished from the in-memory tree, same as the + // native-TCP path below. Applies to the dmsg transport too so a wasm + // visor can be a full federated member. + pc.InMemoryDB = true + } if cfg.DmsgC != nil { return treestore.NewWithDMSG(cfg.DmsgC, cfg.MySK, pc) } @@ -581,8 +593,8 @@ func Open(cfg Config) (*Session, error) { if cfg.Record.Mode == ModePrivate && len(cfg.Record.AESKey) != 32 { return nil, fmt.Errorf("group: Open: private mode requires 32-byte AESKey, got %d", len(cfg.Record.AESKey)) } - if cfg.DataDir == "" { - return nil, errors.New("group: Open: DataDir required") + if cfg.DataDir == "" && !cfg.InMemoryDB { + return nil, errors.New("group: Open: DataDir required (unless InMemoryDB)") } log := cfg.Logger @@ -1793,7 +1805,7 @@ func (s *Session) bindRelaySkynet(port uint16) { // own messages — with sender attribution from the relay envelope // instead of the owner's PK. func (s *Session) handleRelay(c net.Conn) { - payload, err := readFrame(c) + payload, err := message.ReadFrame(c) if err != nil { s.log.WithError(err).Debug("group: relay read") return @@ -1834,7 +1846,7 @@ func (s *Session) handleRelay(c net.Conn) { s.log.WithError(err).Debug("group: relay ack marshal") return } - if err := writeFrame(c, body); err != nil { + if err := message.WriteFrame(c, body); err != nil { s.log.WithError(err).Debug("group: relay ack write") } } @@ -2059,7 +2071,7 @@ var ErrRelayNoAck = errors.New("group: relay: no ack within timeout (owner pre-a // on missing/timeout-out ack but successful write, or a wrapped // error on write failure. func writeAndReadAck(c net.Conn, body []byte, msgID string) error { - if err := writeFrame(c, body); err != nil { + if err := message.WriteFrame(c, body); err != nil { return fmt.Errorf("write: %w", err) } if msgID == "" { @@ -2071,7 +2083,7 @@ func writeAndReadAck(c net.Conn, body []byte, msgID string) error { if dl, ok := c.(interface{ SetReadDeadline(time.Time) error }); ok { _ = dl.SetReadDeadline(time.Now().Add(relayAckReadTimeout)) //nolint:errcheck } - payload, err := readFrame(c) + payload, err := message.ReadFrame(c) if err != nil { return ErrRelayNoAck } @@ -2107,44 +2119,10 @@ func dialSkynetRelay(ctx context.Context, addr appnet.Addr) (net.Conn, error) { return appnet.DialContext(dialCtx, addr) } -// readFrame / writeFrame mirror the visor-app skychat post-#2504 -// length-prefixed wire so a member's relay write and an owner's -// relay read interoperate with the same bit layout other framed -// wires in this tree use. -func readFrame(c net.Conn) ([]byte, error) { - var hdr [4]byte - if _, err := io.ReadFull(c, hdr[:]); err != nil { - return nil, err - } - length := binary.BigEndian.Uint32(hdr[:]) - if length == 0 { - return nil, errors.New("group: zero-length frame") - } - if length > relayMaxFrameSize { - return nil, fmt.Errorf("group: frame %d > max %d", length, relayMaxFrameSize) - } - payload := make([]byte, length) - if _, err := io.ReadFull(c, payload); err != nil { - return nil, err - } - return payload, nil -} - -func writeFrame(c net.Conn, payload []byte) error { - if len(payload) == 0 { - return errors.New("group: empty payload") - } - if len(payload) > relayMaxFrameSize { - return fmt.Errorf("group: payload %d > max %d", len(payload), relayMaxFrameSize) - } - var hdr [4]byte - binary.BigEndian.PutUint32(hdr[:], uint32(len(payload))) //nolint:gosec - if _, err := c.Write(hdr[:]); err != nil { - return err - } - _, err := c.Write(payload) - return err -} +// Relay framing now uses the shared skychat wire codec (pkg/skychat/message): +// message.ReadFrame / message.WriteFrame — the same length-prefixed layout the +// member's relay write and the owner's relay read have always used, minus the +// third private copy this file used to carry. // ReplayHistoryThrough pumps the last `cap` messages from every // publisher/subscriber tree this session can reach through the diff --git a/cmd/apps/skychat/group/store.go b/cmd/apps/skychat/group/store_bbolt.go similarity index 94% rename from cmd/apps/skychat/group/store.go rename to cmd/apps/skychat/group/store_bbolt.go index af345dc059..83d6ef0281 100644 --- a/cmd/apps/skychat/group/store.go +++ b/cmd/apps/skychat/group/store_bbolt.go @@ -1,5 +1,9 @@ -// Package group — cmd/apps/skychat/group/store.go: bbolt-backed -// persistence for chat groups. +//go:build !js + +// Package group — cmd/apps/skychat/group/store_bbolt.go: bbolt-backed +// persistence for chat groups (native builds; bbolt can't compile under +// js/wasm, so the browser visor uses the in-memory store_memory.go — same API, +// wire-identical JSON records). // // One bucket "groups" with key = group UUID, value = JSON Record. // Layout parallels pairing.Store deliberately so an operator who diff --git a/cmd/apps/skychat/group/store_memory.go b/cmd/apps/skychat/group/store_memory.go new file mode 100644 index 0000000000..7b3ea76b8a --- /dev/null +++ b/cmd/apps/skychat/group/store_memory.go @@ -0,0 +1,149 @@ +//go:build js + +// cmd/apps/skychat/group/store_memory.go: in-memory group record store for +// js/wasm, where bbolt can't compile (arch-const MaxAllocSize + mmap) and a +// browser tab has no filesystem. Drop-in for the bbolt store (store_bbolt.go): +// same *Store type + method set, and records are held as JSON bytes keyed by +// group ID so value semantics — independent copies on read, legacy-Admins +// normalization — match the bbolt path exactly. +// +// Ephemeral: a browser visor's group records reset on tab reload. That's fine +// for the federated model — every member is authoritative only for its own +// feed, so anything this visor published is retained by the peers that +// subscribed to it, and on reload it re-subscribes and history-replays. A +// durable variant can hydrate this map from + flush it to IndexedDB behind the +// identical API (in-memory stays the synchronous working set; IndexedDB is the +// async persistence tier — IndexedDB, not localStorage, for the quota headroom +// and native binary storage). + +package group + +import ( + "encoding/json" + "fmt" + "sort" + "sync" + "time" + + "github.com/skycoin/skywire/pkg/cipher" +) + +// Store is an in-memory group record store. Safe for concurrent use. +type Store struct { + mu sync.RWMutex + kvs map[string][]byte // group ID -> JSON Record (mirrors the bbolt value shape) +} + +// OpenStore returns an in-memory store. path is accepted for signature parity +// with the bbolt store but ignored — there is no filesystem in js/wasm. +func OpenStore(path string) (*Store, error) { + _ = path + return &Store{kvs: make(map[string][]byte)}, nil +} + +// Close is a no-op (nothing to release). +func (s *Store) Close() error { return nil } + +// Put writes (or replaces) the record for r.ID. +func (s *Store) Put(r Record) error { + if r.ID == "" { + return fmt.Errorf("group: Put: empty ID") + } + body, err := json.Marshal(r) + if err != nil { + return fmt.Errorf("group: marshal record: %w", err) + } + s.mu.Lock() + defer s.mu.Unlock() + s.kvs[r.ID] = body + return nil +} + +// Get returns the record for id and a boolean indicating presence. +func (s *Store) Get(id string) (Record, bool, error) { + s.mu.RLock() + raw, ok := s.kvs[id] + s.mu.RUnlock() + var r Record + if !ok { + return r, false, nil + } + if err := json.Unmarshal(raw, &r); err != nil { + return r, true, err + } + // Match store_bbolt.Get: normalize legacy records (nil Admins) so IsAdmin + // and admin-gated ops see a consistent shape. + r.EnsureFounderInAdmins() + return r, true, nil +} + +// List returns every persisted record in lexicographic ID order (matching +// bbolt's bucket-sorted iteration so order-dependent callers behave identically). +func (s *Store) List() ([]Record, error) { + s.mu.RLock() + ids := make([]string, 0, len(s.kvs)) + for id := range s.kvs { + ids = append(ids, id) + } + raws := make([][]byte, len(ids)) + sort.Strings(ids) + for i, id := range ids { + raws[i] = s.kvs[id] + } + s.mu.RUnlock() + out := make([]Record, 0, len(ids)) + for _, raw := range raws { + var r Record + if err := json.Unmarshal(raw, &r); err != nil { + return out, err + } + r.EnsureFounderInAdmins() + out = append(out, r) + } + return out, nil +} + +// Delete removes the record for id. No-op if absent. +func (s *Store) Delete(id string) error { + s.mu.Lock() + defer s.mu.Unlock() + delete(s.kvs, id) + return nil +} + +// SetStatus updates only the Status field of an existing record. +func (s *Store) SetStatus(id string, status Status) error { + return s.update(id, func(r *Record) { r.Status = status }) +} + +// MarkMessage updates LastMessageAt to the given timestamp. +func (s *Store) MarkMessage(id string, ts time.Time) error { + return s.update(id, func(r *Record) { r.LastMessageAt = ts }) +} + +// SetMembers replaces the Members slice. +func (s *Store) SetMembers(id string, members []cipher.PubKey) error { + return s.update(id, func(r *Record) { r.Members = members }) +} + +// update is the shared read-modify-write helper. Returns an error if no record +// exists for id. +func (s *Store) update(id string, fn func(*Record)) error { + s.mu.Lock() + defer s.mu.Unlock() + raw, ok := s.kvs[id] + if !ok { + return fmt.Errorf("group: no record for %s", id) + } + var r Record + if err := json.Unmarshal(raw, &r); err != nil { + return err + } + fn(&r) + body, err := json.Marshal(&r) + if err != nil { + return err + } + s.kvs[id] = body + return nil +} diff --git a/cmd/mux-probe-assert/main.go b/cmd/mux-probe-assert/main.go index c5053877e7..960ee5f8cc 100644 --- a/cmd/mux-probe-assert/main.go +++ b/cmd/mux-probe-assert/main.go @@ -81,9 +81,9 @@ const ( exitOK = 0 exitUsage = 1 exitTopologyDegrade = 2 - exitIntegrity = 3 //nolint:unused,deadcode // reserved + exitIntegrity = 3 //nolint:unused // reserved exitThroughputRegress = 4 - exitHOLBreach = 5 //nolint:unused,deadcode // reserved + exitHOLBreach = 5 //nolint:unused // reserved ) func main() { diff --git a/cmd/wasm-visor/group_js.go b/cmd/wasm-visor/group_js.go new file mode 100644 index 0000000000..1f581b3b8e --- /dev/null +++ b/cmd/wasm-visor/group_js.go @@ -0,0 +1,245 @@ +//go:build js && wasm + +// cmd/wasm-visor/group_js.go: in-browser federated GROUP chat. The wasm visor +// runs the same group.Manager the native visor does (roster, signing, gossip, +// per-member CXO feeds), over its dmsg client, with an IN-MEMORY store + CXO tree +// (no filesystem in a tab). So a browser tab is a full federated group member: it +// publishes its own feed and subscribes to the other members' feeds over dmsg; +// the network retains whatever it published (local state resets on tab reload). +// +// JS surface on skywireVisor: +// +// skychatGroupCreate(name[, "public"|"private"]) -> Promise<{id,name,invite}> +// skychatGroupJoin(inviteLink) -> Promise<{id,name}> +// skychatGroupSend(id, text) -> Promise +// skychatGroupAddMember(id, peerPkHex) -> Promise<{id,members}> +// skychatGroupList() -> JSON [{id,name,mode,role,members,status}] +// skychatGroupMessages([id]) -> JSON [{group_id,from,text,ts}] (newest last) +package main + +import ( + "context" + "encoding/json" + "fmt" + "sync" + "syscall/js" + "time" + + "github.com/skycoin/skywire/cmd/apps/skychat/group" + "github.com/skycoin/skywire/pkg/cipher" + "github.com/skycoin/skywire/pkg/logging" +) + +const groupLogCap = 1000 + +var ( + groupMgr *group.Manager + groupMu sync.Mutex + groupLog []groupMsg // in-memory ring of received group messages +) + +// groupMsg is one group message surfaced to the page (skychatGroupMessages()). +type groupMsg struct { + GroupID string `json:"group_id"` + From string `json:"from"` // sender PK hex + Text string `json:"text"` + TS int64 `json:"ts"` // unix milliseconds +} + +func appendGroupMsg(m groupMsg) { + groupMu.Lock() + groupLog = append(groupLog, m) + if len(groupLog) > groupLogCap { + groupLog = groupLog[len(groupLog)-groupLogCap:] + } + groupMu.Unlock() +} + +// startGroupChat brings up the in-browser group Manager over the wasm dmsg client +// with an in-memory store + CXO tree. Best-effort; called once from bootEdge after +// dmsg + the 1:1 skychat app are up. Any failure just leaves group chat disabled. +func startGroupChat(sk cipher.SecKey, log *logging.Logger) { + if dmsgC == nil || selfPK.Null() { + return + } + store, err := group.OpenStore("") // js build -> in-memory (path ignored) + if err != nil { + vlog("group: store open failed: " + err.Error()) + return + } + mgr, err := group.NewManager(group.ManagerConfig{ + Store: store, + DmsgC: dmsgC, + MyPK: selfPK, + MySK: sk, + InMemoryDB: true, // no filesystem in a tab; CXO tree lives in memory + Logger: log, + HeartbeatInterval: group.DefaultHeartbeatInterval, + }) + if err != nil { + vlog("group: NewManager failed: " + err.Error()) + return + } + mgr.SetMessageHandler(func(groupID string, sender cipher.PubKey, msg group.Message) { + appendGroupMsg(groupMsg{GroupID: groupID, From: sender.Hex(), Text: msg.Text, TS: msg.TS.UnixMilli()}) + vlog(fmt.Sprintf("group: message in %s from %s: %q", shortID(groupID), shortPK(sender.Hex()), msg.Text)) + }) + groupMgr = mgr + if err := mgr.Resume(); err != nil { + vlog("group: Resume: " + err.Error()) + } + vlog("group: chat manager up — in-memory federated groups over dmsg") +} + +func shortID(id string) string { + if len(id) > 8 { + return id[:8] + } + return id +} + +// groupView is the compact record shape returned by skychatGroupList(). +type groupView struct { + ID string `json:"id"` + Name string `json:"name"` + Mode string `json:"mode"` + Role string `json:"role"` + Members int `json:"members"` + Status string `json:"status"` +} + +// jsGroupCreate(name[, mode]) → Promise<{id,name,invite}>. mode is "public" +// (default) or "private". +func jsGroupCreate(_ js.Value, args []js.Value) interface{} { + if groupMgr == nil { + return errPromise("group chat not ready") + } + if len(args) < 1 || args[0].String() == "" { + return errPromise("skychatGroupCreate(name[, mode])") + } + name := args[0].String() + mode := group.ModePublic + if len(args) >= 2 && args[1].String() == "private" { + mode = group.ModePrivate + } + return promise(func() (interface{}, error) { + rec, err := groupMgr.Create(name, mode, nil) + if err != nil { + return nil, err + } + invite, err := groupMgr.BuildInvite(rec.ID) + if err != nil { + return nil, err + } + return map[string]interface{}{"id": rec.ID, "name": rec.Name, "invite": invite}, nil + }) +} + +// jsGroupJoin(inviteLink) → Promise<{id,name}>. +func jsGroupJoin(_ js.Value, args []js.Value) interface{} { + if groupMgr == nil { + return errPromise("group chat not ready") + } + if len(args) < 1 || args[0].String() == "" { + return errPromise("skychatGroupJoin(inviteLink)") + } + link := args[0].String() + return promise(func() (interface{}, error) { + inv, err := group.DecodeInvite(link) + if err != nil { + return nil, fmt.Errorf("bad invite: %w", err) + } + rec, err := groupMgr.Join(inv) + if err != nil { + return nil, err + } + return map[string]interface{}{"id": rec.ID, "name": rec.Name}, nil + }) +} + +// jsGroupSend(id, text) → Promise. +func jsGroupSend(_ js.Value, args []js.Value) interface{} { + if groupMgr == nil { + return errPromise("group chat not ready") + } + if len(args) < 2 { + return errPromise("skychatGroupSend(id, text)") + } + id, text := args[0].String(), args[1].String() + return promise(func() (interface{}, error) { + sctx, cancel := context.WithTimeout(ctx, 15*time.Second) + defer cancel() + return nil, groupMgr.SendToGroup(sctx, id, text) + }) +} + +// jsGroupAddMember(id, peerPkHex) → Promise<{id,members}> (owner extends the allowlist). +func jsGroupAddMember(_ js.Value, args []js.Value) interface{} { + if groupMgr == nil { + return errPromise("group chat not ready") + } + if len(args) < 2 { + return errPromise("skychatGroupAddMember(id, peerPkHex)") + } + id, pkHex := args[0].String(), args[1].String() + return promise(func() (interface{}, error) { + var pk cipher.PubKey + if err := pk.Set(pkHex); err != nil { + return nil, fmt.Errorf("bad member pk: %w", err) + } + rec, err := groupMgr.AddMember(id, pk) + if err != nil { + return nil, err + } + return map[string]interface{}{"id": rec.ID, "members": len(rec.Members)}, nil + }) +} + +// jsGroupList() → JSON [{id,name,mode,role,members,status}]. +func jsGroupList(js.Value, []js.Value) interface{} { + if groupMgr == nil { + return "[]" + } + recs, err := groupMgr.List() + if err != nil { + return "[]" + } + out := make([]groupView, 0, len(recs)) + for _, r := range recs { + out = append(out, groupView{ + ID: r.ID, Name: r.Name, Mode: string(r.Mode), + Role: string(r.Role), Members: len(r.Members), Status: string(r.Status), + }) + } + b, _ := json.Marshal(out) //nolint:errcheck + return string(b) +} + +// jsGroupMessages([id]) → JSON of buffered group messages (newest last), +// optionally filtered to one group id. +func jsGroupMessages(_ js.Value, args []js.Value) interface{} { + filter := "" + if len(args) >= 1 && args[0].Type() == js.TypeString { + filter = args[0].String() + } + groupMu.Lock() + var view []groupMsg + if filter == "" { + view = append(view, groupLog...) + } else { + for _, m := range groupLog { + if m.GroupID == filter { + view = append(view, m) + } + } + } + groupMu.Unlock() + b, _ := json.Marshal(view) //nolint:errcheck + return string(b) +} + +// errPromise returns an already-rejected Promise with the given message, so the +// group hooks fail gracefully (reject) rather than throwing synchronously. +func errPromise(msg string) interface{} { + return promise(func() (interface{}, error) { return nil, fmt.Errorf("%s", msg) }) +} diff --git a/cmd/wasm-visor/main.go b/cmd/wasm-visor/main.go index ab5aad0579..4449f8481a 100644 --- a/cmd/wasm-visor/main.go +++ b/cmd/wasm-visor/main.go @@ -136,24 +136,31 @@ func pageHTTPS() bool { func main() { ctx = context.Background() js.Global().Set("skywireVisor", js.ValueOf(map[string]interface{}{ - "boot": js.FuncOf(jsBoot), - "status": js.FuncOf(jsStatus), - "hvApi": js.FuncOf(jsHvAPI), - "tpdEdge": js.FuncOf(jsTPDEdge), - "dialTransport": js.FuncOf(jsDialTransport), - "fetchDmsg": js.FuncOf(jsFetchDmsg), + "boot": js.FuncOf(jsBoot), + "status": js.FuncOf(jsStatus), + "hvApi": js.FuncOf(jsHvAPI), + "tpdEdge": js.FuncOf(jsTPDEdge), + "dialTransport": js.FuncOf(jsDialTransport), + "fetchDmsg": js.FuncOf(jsFetchDmsg), "serveContent": js.FuncOf(jsServeContent), "hostedContent": js.FuncOf(jsHostedContent), "unserveContent": js.FuncOf(jsUnserveContent), "setContentEnabled": js.FuncOf(jsSetContentEnabled), - "serveRPC": js.FuncOf(jsServeRPC), - "dialRoute": js.FuncOf(jsDialRoute), - "checkRegistered": js.FuncOf(jsCheckRegistered), - "fetchClearnet": js.FuncOf(jsFetchClearnet), - "proxyVerbose": js.FuncOf(jsProxyVerbose), - "closeWindow": js.FuncOf(jsCloseWindow), - "skychatSend": js.FuncOf(jsSkychatSend), - "skychatMessages": js.FuncOf(jsSkychatMessages), + "serveRPC": js.FuncOf(jsServeRPC), + "dialRoute": js.FuncOf(jsDialRoute), + "checkRegistered": js.FuncOf(jsCheckRegistered), + "fetchClearnet": js.FuncOf(jsFetchClearnet), + "proxyVerbose": js.FuncOf(jsProxyVerbose), + "closeWindow": js.FuncOf(jsCloseWindow), + "skychatSend": js.FuncOf(jsSkychatSend), + "skychatMessages": js.FuncOf(jsSkychatMessages), + // Federated group chat (in-memory over dmsg) — see group_js.go. + "skychatGroupCreate": js.FuncOf(jsGroupCreate), + "skychatGroupJoin": js.FuncOf(jsGroupJoin), + "skychatGroupSend": js.FuncOf(jsGroupSend), + "skychatGroupAddMember": js.FuncOf(jsGroupAddMember), + "skychatGroupList": js.FuncOf(jsGroupList), + "skychatGroupMessages": js.FuncOf(jsGroupMessages), })) fmt.Println("wasm-visor: ready — call skywireVisor.boot(sk, seedPk, seedWs, discDmsgAddr)") select {} // block forever @@ -367,6 +374,12 @@ func bootEdge(skHex, seedPKHex, seedWSURL, discDmsgAddr string) (cipher.PubKey, tm.InitDmsgClient(ctx, dmsgC) vlog("tp_manager: dmsg client inited; serving…") go tm.Serve(ctx) + + // In-memory CXO telemetry: report this tab's transport bandwidth + latency to + // TPD (via its cxo-aggregator), so the browser visor's transports show up in + // TPD /metrics like a native visor's — see telemetry_js.go. + go startTelemetry(sk, tpdPK, mLog.PackageLogger("wasm-telemetry")) + go startGroupChat(sk, mLog.PackageLogger("wasm-group")) vlog("tp_manager: serving") // Register the browser-dialable direct transport clients. Their Start() fails // closed under TinyGo (a tab can't run a WS/WT listener) — logged, non-fatal — diff --git a/cmd/wasm-visor/skychat_js.go b/cmd/wasm-visor/skychat_js.go index ea2c7d2f56..9013a4c2e0 100644 --- a/cmd/wasm-visor/skychat_js.go +++ b/cmd/wasm-visor/skychat_js.go @@ -19,10 +19,8 @@ package main import ( "context" - "encoding/binary" "encoding/json" "fmt" - "io" "net" "sync" "syscall/js" @@ -31,6 +29,7 @@ import ( "github.com/skycoin/skywire/pkg/app" "github.com/skycoin/skywire/pkg/app/appnet" "github.com/skycoin/skywire/pkg/cipher" + "github.com/skycoin/skywire/pkg/skychat/message" ) // skychatPort is skychat's well-known routing port: native skychat dials peers @@ -38,9 +37,6 @@ import ( // reachable, and dials peers there in turn. const skychatPort = 1 -// skychatMaxFrame bounds one framed message (matches native skychatMaxFrameSize). -const skychatMaxFrame = 64 * 1024 - // chatMsg is one buffered message surfaced to the page (skychatMessages()). type chatMsg struct { From string `json:"from"` // peer PK hex (the other end) @@ -49,34 +45,18 @@ type chatMsg struct { Out bool `json:"out"` // true = we sent it, false = received } -// chatConn wraps a skychat conn with a write mutex: a peer conn is written from -// two goroutines — sendChat (outbound message) and readChatConn (the chat-ack it -// sends back on receipt) — so framing must be serialized or the 4-byte header and -// body of two frames could interleave and corrupt the stream. -type chatConn struct { - net.Conn - wmu sync.Mutex -} - -func (c *chatConn) writeFrameLocked(payload []byte) error { - c.wmu.Lock() - defer c.wmu.Unlock() - return writeFrame(c.Conn, payload) -} - -// chatAckEnvelope is the chat-ack reply the sender's --wait blocks on (native -// wire format: {"type":"chat-ack","id":""}). We only ever encode acks; the -// full chat-msg/chat-ack schema lives in the native skychat app. -type chatAckEnvelope struct { - Type string `json:"type"` - ID string `json:"id"` -} +// Peer conns use the shared skychat wire codec: message.Conn carries the +// length-prefixed framing plus the write mutex a bidirectional skychat conn needs +// (sendChat writes outbound messages while readChatConn writes chat-ack replies on +// the same conn — the two must be serialized or their frames interleave). The +// chat-ack envelope and frame codec live in pkg/skychat/message, shared with the +// native app. var ( chatMu sync.Mutex chatLog []chatMsg chatClient *app.Client - chatConns = map[cipher.PubKey]*chatConn{} // cached conns keyed by peer PK + chatConns = map[string]*message.Conn{} // cached outbound conns keyed by "|" ) func appendChat(m chatMsg) { @@ -129,7 +109,7 @@ func acceptChatLoop(lis net.Listener) { if err != nil { return } - go readChatConn(&chatConn{Conn: conn}) + go readChatConn(message.NewConn(conn)) } } @@ -138,18 +118,18 @@ func acceptChatLoop(lis net.Listener) { // (outbound) conns — a skychat conn is bidirectional. When the peer sends an // ack-requesting chat-msg (native `send --wait`), we reply with a chat-ack on the // same conn so the sender's wait resolves instead of falsely timing out. -func readChatConn(conn *chatConn) { +func readChatConn(conn *message.Conn) { defer conn.Close() //nolint:errcheck from := peerPKHex(conn) for { - payload, err := readFrame(conn) + payload, err := conn.ReadFrame() if err != nil { return } text, ackID := decodeChatPayload(payload) if ackID != "" { - if b, mErr := json.Marshal(chatAckEnvelope{Type: "chat-ack", ID: ackID}); mErr == nil { - if wErr := conn.writeFrameLocked(b); wErr != nil { + if b, mErr := (message.Envelope{Type: message.TypeAck, ID: ackID}).Marshal(); mErr == nil { + if wErr := conn.WriteFrame(b); wErr != nil { vlog(fmt.Sprintf("skychat: ack to %s failed: %s", shortPK(from), wErr.Error())) } } @@ -162,96 +142,80 @@ func readChatConn(conn *chatConn) { } } -// sendChat dials the peer on dmsg:1 (reusing a cached conn) and writes one -// plain-text frame — the format native skychat accepts on its read loop. -func sendChat(pkHex, text string) error { +// sendChat dials the peer on :1 (reusing a cached conn) and writes one +// plain-text frame — the format native skychat accepts on its read loop. network +// is "dmsg" (default) or "skynet"; conns are cached per (network, peer) so the two +// transports don't clobber each other. The dial/connect/send steps are vlog'd so +// the chat window's log pane can surface them (like the skysocks-lite route setup). +func sendChat(pkHex, text, network string) error { if chatClient == nil { return fmt.Errorf("skychat not started yet") } if text == "" { return fmt.Errorf("empty message") } + var net appnet.Type + switch network { + case "", "dmsg": + net = appnet.TypeDmsg + case "skynet": + net = appnet.TypeSkynet + default: + return fmt.Errorf("unknown network %q (use dmsg or skynet)", network) + } var pk cipher.PubKey if err := pk.Set(pkHex); err != nil { return fmt.Errorf("bad peer pk: %w", err) } + key := string(net) + "|" + pkHex chatMu.Lock() - conn := chatConns[pk] + conn := chatConns[key] chatMu.Unlock() if conn == nil { - c, err := chatClient.Dial(appnet.Addr{Net: appnet.TypeDmsg, PubKey: pk, Port: skychatPort}) + vlog(fmt.Sprintf("skychat: dialing %s %s:%d…", net, shortPK(pkHex), skychatPort)) + c, err := chatClient.Dial(appnet.Addr{Net: net, PubKey: pk, Port: skychatPort}) if err != nil { - return fmt.Errorf("dial %s: %w", shortPK(pkHex), err) + vlog(fmt.Sprintf("skychat: dial %s %s failed: %s", net, shortPK(pkHex), err.Error())) + return fmt.Errorf("dial %s over %s: %w", shortPK(pkHex), net, err) } - conn = &chatConn{Conn: c} + vlog(fmt.Sprintf("skychat: connected to %s over %s", shortPK(pkHex), net)) + conn = message.NewConn(c) chatMu.Lock() - chatConns[pk] = conn + chatConns[key] = conn chatMu.Unlock() // Read replies on the same conn; drop it from the cache when it closes. go func() { readChatConn(conn) chatMu.Lock() - delete(chatConns, pk) + delete(chatConns, key) chatMu.Unlock() }() } - if err := conn.writeFrameLocked([]byte(text)); err != nil { + if err := conn.WriteFrame([]byte(text)); err != nil { chatMu.Lock() - delete(chatConns, pk) + delete(chatConns, key) chatMu.Unlock() conn.Close() //nolint:errcheck,gosec return fmt.Errorf("send: %w", err) } + vlog(fmt.Sprintf("skychat: sent %d bytes to %s over %s", len(text), shortPK(pkHex), net)) appendChat(chatMsg{From: pkHex, Text: text, TS: nowMs(), Out: true}) return nil } -// readFrame reads one length-prefixed frame (skychat wire format). -func readFrame(conn net.Conn) ([]byte, error) { - var hdr [4]byte - if _, err := io.ReadFull(conn, hdr[:]); err != nil { - return nil, err - } - n := binary.BigEndian.Uint32(hdr[:]) - if n == 0 || n > skychatMaxFrame { - return nil, fmt.Errorf("skychat: bad frame length %d", n) - } - buf := make([]byte, n) - if _, err := io.ReadFull(conn, buf); err != nil { - return nil, err - } - return buf, nil -} - -func writeFrame(conn net.Conn, payload []byte) error { - var hdr [4]byte - binary.BigEndian.PutUint32(hdr[:], uint32(len(payload))) //nolint:gosec - if _, err := conn.Write(hdr[:]); err != nil { - return err - } - _, err := conn.Write(payload) - return err -} - // decodeChatPayload extracts the message text from a frame, plus the ack id to // reply with (non-empty only when the peer's chat-msg requested an ack — native // `send --wait`). Native skychat sends either plain UTF-8 bytes (default) or a -// JSON envelope {type,id,body,ack}: we return the body for a "chat-msg", ("","") -// for a "chat-ack", else the raw bytes. Recognition is conservative (must start -// with '{' and carry a known chat-* type) so literal JSON typed into a chat still -// reaches the peer as plain text. +// chat-* JSON envelope: we return the body for a "chat-msg", ("","") for a +// "chat-ack", else the raw bytes. Recognition (message.ParseEnvelope) is +// conservative — a known chat-* type only — so literal JSON typed into a chat +// still reaches the peer as plain text. func decodeChatPayload(payload []byte) (text, ackID string) { - var env struct { - Type string `json:"type"` - ID string `json:"id"` - Body string `json:"body"` - Ack bool `json:"ack"` - } - if len(payload) > 0 && payload[0] == '{' && json.Unmarshal(payload, &env) == nil { + if env, ok := message.ParseEnvelope(payload); ok { switch env.Type { - case "chat-ack": + case message.TypeAck: return "", "" - case "chat-msg": + case message.TypeMsg: if env.Ack && env.ID != "" { return env.Body, env.ID } @@ -277,14 +241,19 @@ func shortPK(pk string) string { func nowMs() int64 { return time.Now().UnixMilli() } -// jsSkychatSend(peerPkHex, text) → Promise (rejects on error). +// jsSkychatSend(peerPkHex, text[, network]) → Promise (rejects on error). +// network is "dmsg" (default) or "skynet". func jsSkychatSend(_ js.Value, args []js.Value) interface{} { if len(args) < 2 { - return js.Global().Get("Error").New("skychatSend(peerPkHex, text)") + return js.Global().Get("Error").New("skychatSend(peerPkHex, text[, network])") } pkHex, text := args[0].String(), args[1].String() + network := "dmsg" + if len(args) >= 3 && args[2].Type() == js.TypeString { + network = args[2].String() + } return promise(func() (interface{}, error) { - return nil, sendChat(pkHex, text) + return nil, sendChat(pkHex, text, network) }) } diff --git a/cmd/wasm-visor/skysocks_js.go b/cmd/wasm-visor/skysocks_js.go index 7b66319c69..74ad94967d 100644 --- a/cmd/wasm-visor/skysocks_js.go +++ b/cmd/wasm-visor/skysocks_js.go @@ -90,18 +90,25 @@ func emitProxyLog(winID, msg string) { // lazily establishing it over a fresh route group (rtr.DialRoutes — the routing // layer). Cached per exit; a closed session is re-dialed. func skysocksSession(winID string, serverPK cipher.PubKey) (*yamux.Session, error) { - skysocksMu.Lock() - defer skysocksMu.Unlock() key := skysocksKey(winID, serverPK) + // Fast path under the lock: an established, still-open session is reused. + skysocksMu.Lock() if s, ok := skysocksSessions[key]; ok && !s.IsClosed() { + skysocksMu.Unlock() if proxyVerbose { emitProxyLog(winID, fmt.Sprintf("[skysocks-lite %s] reuse session to exit %s", winID, serverPK.Hex()[:8])) } return s, nil } + skysocksMu.Unlock() if rtr == nil { return nil, errors.New("not booted; call boot() first") } + // Route setup can take many seconds. Do it WITHOUT holding skysocksMu — the + // lock only guards the map. Holding it across DialRoutes serialized every + // concurrent session (a 2nd browser window dialing a different exit would + // block up to 45s behind the first), piling up goroutines. Now different + // exits (and different windows) establish in parallel. t0 := time.Now() emitProxyLog(winID, fmt.Sprintf("[skysocks-lite %s] connecting to exit %s — setting up route…", winID, serverPK.Hex()[:8])) dctx, cancel := context.WithTimeout(ctx, 45*time.Second) @@ -123,7 +130,16 @@ func skysocksSession(winID string, serverPK cipher.PubKey) (*yamux.Session, erro _ = conn.Close() //nolint:errcheck return nil, fmt.Errorf("yamux client: %w", err) } + // Re-acquire to publish. If a concurrent call for the SAME key won the race + // while we were dialing, discard ours and reuse theirs (avoid leaking a route). + skysocksMu.Lock() + if s, ok := skysocksSessions[key]; ok && !s.IsClosed() { + skysocksMu.Unlock() + _ = sess.Close() //nolint:errcheck + return s, nil + } skysocksSessions[key] = sess + skysocksMu.Unlock() emitProxyLog(winID, fmt.Sprintf("[skysocks-lite %s] route+session to exit %s established (%dms)", winID, serverPK.Hex()[:8], time.Since(t0).Milliseconds())) return sess, nil } diff --git a/cmd/wasm-visor/telemetry_js.go b/cmd/wasm-visor/telemetry_js.go new file mode 100644 index 0000000000..d18e228aa3 --- /dev/null +++ b/cmd/wasm-visor/telemetry_js.go @@ -0,0 +1,145 @@ +//go:build js && wasm + +// Package main — in-browser CXO telemetry. A native visor reports each transport's +// bandwidth + latency to TPD by publishing a CXO TreeStore feed that TPD's +// cxo-aggregator subscribes to (pkg/visor/init_stats.go). A browser tab has no +// filesystem, so it can't use the native bbolt-backed stats.Store — but the CXO +// publisher itself runs fine with an IN-MEMORY datastore (treestore InMemoryDB; +// the CXDS/IdxDB drives are build-tag-split so this compiles under js/wasm). +// +// This wires that up: an in-memory publisher, the transport manager's entry/ +// tombstone leaves, a per-transport transports//current leaf (bandwidth + +// latency) sampled each minute, and an announce loop so TPD subscribes. Without +// it a browser visor's transports never reach TPD /metrics (invisible to rewards). +// Telemetry resets on tab reload (no persistence) — fine; TPD retains published +// rollups within its own window. +package main + +import ( + "context" + "encoding/json" + "fmt" + "time" + + "github.com/skycoin/skywire/pkg/cipher" + "github.com/skycoin/skywire/pkg/cxo/treestore" + "github.com/skycoin/skywire/pkg/logging" + "github.com/skycoin/skywire/pkg/transport" +) + +// liveSnapshot mirrors the wire shape TPD's cxo-aggregator parses for +// transports//current (bandwidth + latency). The aggregator re-declares the +// same struct on its side to keep the dependency one-way; field JSON tags must +// match both places (pkg/transport-discovery/cxoaggregator/aggregator.go). +type liveSnapshot struct { + SentBytes uint64 `json:"sent_bytes"` + RecvBytes uint64 `json:"recv_bytes"` + LatencyMinMS float64 `json:"latency_min_ms,omitempty"` + LatencyMaxMS float64 `json:"latency_max_ms,omitempty"` + LatencyAvgMS float64 `json:"latency_avg_ms,omitempty"` + SampledAt time.Time `json:"sampled_at"` + Type string `json:"type,omitempty"` +} + +var telemetryPub *treestore.Publisher + +const ( + telemetrySampleInterval = time.Minute + telemetryAnnounceInterval = 30 * time.Second +) + +// startTelemetry brings up the in-memory CXO publisher, wires the transport +// manager to publish transports//entry + tombstone leaves, samples each live +// transport's bandwidth/latency into transports//current every minute, and +// announces to TPD so its cxo-aggregator subscribes to this visor's feed. Called +// once from bootEdge after the transport manager is serving. Best-effort: any +// failure leaves the rest of the visor running. +func startTelemetry(sk cipher.SecKey, tpdPK cipher.PubKey, log *logging.Logger) { + if dmsgC == nil || tpM == nil { + return + } + pub, err := treestore.NewWithDMSG(dmsgC, sk, treestore.PubConfig{ + InMemoryDB: true, // no filesystem in a tab — content-addressed cache is fine in memory + BatchWindow: 10 * time.Second, + Logger: log, + }) + if err != nil { + vlog("telemetry: CXO publisher init failed: " + err.Error()) + return + } + telemetryPub = pub + tpM.SetTPDLeafPublisher(pub) // register/deregister → transports//entry + /tombstone + vlog(fmt.Sprintf("telemetry: in-memory CXO publisher up (feed %s) — reporting transport bandwidth+latency to TPD %s", + pub.Feed().Hex()[:8], tpdPK.Hex()[:8])) + go telemetrySampleLoop() + go telemetryAnnounceLoop(tpdPK) +} + +func telemetrySampleLoop() { + t := time.NewTicker(telemetrySampleInterval) + defer t.Stop() + sampleTransports() + for { + select { + case <-ctx.Done(): + return + case <-t.C: + sampleTransports() + } + } +} + +// sampleTransports publishes a transports//current leaf per live transport, +// carrying its cumulative bandwidth + latency stats. +func sampleTransports() { + if tpM == nil || telemetryPub == nil { + return + } + now := time.Now() + tpM.WalkTransports(func(tp *transport.ManagedTransport) bool { + if tp.IsClosed() { + return true + } + bw := tp.GetBandwidth() + lat := tp.GetLatencyStats() + snap := liveSnapshot{ + SentBytes: bw.SentBytes, + RecvBytes: bw.RecvBytes, + LatencyMinMS: lat.Min, + LatencyMaxMS: lat.Max, + LatencyAvgMS: lat.Avg, + SampledAt: now, + Type: string(tp.Entry.Type), + } + if b, err := json.Marshal(snap); err == nil { + if perr := telemetryPub.Put("transports/"+tp.Entry.ID.String()+"/current", b); perr != nil { + vlog("telemetry: publish current failed: " + perr.Error()) + } + } + return true + }) +} + +func telemetryAnnounceLoop(tpdPK cipher.PubKey) { + t := time.NewTicker(telemetryAnnounceInterval) + defer t.Stop() + announce := func() { + if telemetryPub == nil { + return + } + // Per-attempt deadline: AnnounceTo dials TPD over dmsg (can block on a + // half-dead transport); cap it so a stuck dial can't starve the next tick. + dctx, cancel := context.WithTimeout(ctx, telemetryAnnounceInterval/2) + defer cancel() + _ = telemetryPub.AnnounceTo(dctx, tpdPK) //nolint:errcheck // transient during boot/dmsg churn; retried next tick + } + announce() + for { + select { + case <-ctx.Done(): + return + case <-t.C: + announce() + } + } +} diff --git a/docs/img/wasm-visor/01-visor-dashboard.png b/docs/img/wasm-visor/01-visor-dashboard.png new file mode 100644 index 0000000000..c8ba031e8c Binary files /dev/null and b/docs/img/wasm-visor/01-visor-dashboard.png differ diff --git a/docs/img/wasm-visor/02-app-menu.png b/docs/img/wasm-visor/02-app-menu.png new file mode 100644 index 0000000000..b37b87ecba Binary files /dev/null and b/docs/img/wasm-visor/02-app-menu.png differ diff --git a/docs/img/wasm-visor/03-skynet-browser.png b/docs/img/wasm-visor/03-skynet-browser.png new file mode 100644 index 0000000000..f04d10c8ac Binary files /dev/null and b/docs/img/wasm-visor/03-skynet-browser.png differ diff --git a/docs/img/wasm-visor/04-skychat.png b/docs/img/wasm-visor/04-skychat.png new file mode 100644 index 0000000000..5604d7a1b4 Binary files /dev/null and b/docs/img/wasm-visor/04-skychat.png differ diff --git a/docs/img/wasm-visor/05-host-content.png b/docs/img/wasm-visor/05-host-content.png new file mode 100644 index 0000000000..cc064e40db Binary files /dev/null and b/docs/img/wasm-visor/05-host-content.png differ diff --git a/docs/img/wasm-visor/06-console.png b/docs/img/wasm-visor/06-console.png new file mode 100644 index 0000000000..978422b94c Binary files /dev/null and b/docs/img/wasm-visor/06-console.png differ diff --git a/docs/img/wasm-visor/07-logs.png b/docs/img/wasm-visor/07-logs.png new file mode 100644 index 0000000000..442ce16ebc Binary files /dev/null and b/docs/img/wasm-visor/07-logs.png differ diff --git a/docs/skychat-refactor-rfc.md b/docs/skychat-refactor-rfc.md new file mode 100644 index 0000000000..6e0601aa26 --- /dev/null +++ b/docs/skychat-refactor-rfc.md @@ -0,0 +1,219 @@ +# Skychat Refactor RFC + +status: draft +date: 2026-07-02 +supersedes-in-part: docs/skychat_group_gossip_rfc.md (federation), docs/skychat_cxo_tcp_standalone.md (standalone) +related: pkg/cxo/treestore, pkg/servicedisc, pkg/visor/visorcore (convergence pattern) + +## 1. Problem + +Skychat grew feature-by-feature without a shared core. The result works but is +hard to make *robust* because the same logic exists two or three times and the +copies drift: + +- **Three parallel implementations.** The native app (`cmd/apps/skychat/commands/skychat.go`, + ~2160 lines), the browser-tab wasm reimplementation (`cmd/wasm-visor/skychat_js.go`), + and the visor-side RPC wrapper (`pkg/visor/group.go` + friends). The + length-prefixed frame protocol (4-byte big-endian length, 64 KiB cap, + `chat-msg`/`chat-ack` envelopes) is written out **three times**, each with its + own constant and write-mutex. +- **Three message models.** Framed 1:1 (no struct, arrival-ordered), pair-CXO + (`Message{Text,TS}`), group-CXO (`Message{SenderPK,TS,Text,Ciphertext,Nonce,Signature}`). + No shared identity or ordering. +- **Two group generations coexist** in one package: the original owner-relay + (owner offline ⇒ read-only SPOF) and the newer federated per-member peerSubs + mesh, with dead legacy fields kept for parse-compat. `group/session.go` is + ~2400 lines, `group/manager.go` ~1430 — each mixing state, crypto, transport, + and reconnect state machines in one type. +- **Five transports** (dmsg, skynet routes, TCP-direct, CXO-native-TCP, `--via`), + each with its own send/receive plumbing. +- **Ordering is wall-clock naive** everywhere; dedup is a best-effort bounded set. +- **No discovery.** You can only join a group whose members you already know. +- **Global mutable state** (package-level conns, hub, counters, flags registered twice). + +This is the same divergence class the visor itself had before the `visorcore` +convergence (native vs wasm drifting apart, the #3277 bug family). The fix is the +same: extract one shared, platform-neutral core; make the runtimes thin adapters. + +## 2. Goals / non-goals + +Goals: +1. One shared `pkg/skychat` core used by native app AND wasm visor — no reimplementation. +2. One message model + one wire codec (delete the three framing copies). +3. One group model (federated), owner-relay demoted to a bootstrap, not a SPOF. +4. Transport behind a single interface; the five transports become adapters. +5. **Public group discovery** via the existing service-discovery (`type=skychat`). +6. Causal-ish ordering so display order stops flipping under clock skew. +7. skychat as a first-class desktop window in the wasm mini-desktop (done, §7). + +Non-goals (for this RFC): +- Replacing CXO/treestore as the group data plane (it stays). +- A DHT for discovery (SD-first; DHT is a later swap behind the same interface). +- Changing the on-the-wire crypto (per-message secp256k1 signatures stay). + +## 3. Proposed package layout + +Mirror the visorcore move — a shared core, thin adapters, build-tag splits for +the platform-hostile pieces (exactly the CXO cxds/idxdb `!js` / `js` split used +for the in-memory telemetry publisher). + +``` +pkg/skychat/ + message/ ONE model {ID, SenderPK, TS, Seq, Body, Sig} + ONE wire codec + (4-byte length prefix, 64 KiB cap, chat-msg/chat-ack envelopes). + Replaces framedConn (native), chatConn (wasm), RelayMessage framing. + session/ peer/group session state-machine (data + methods), transport-agnostic: + depends on a small Conn/Dialer interface, not on dmsg/app-client/TCP. + group/ group record + roster + signed gossip. Federated-only. Owner-relay + kept only as an optional bootstrap listener, never required for liveness. + discovery/ NEW: SD-backed public-group directory (§6). PublishGroup / ListPublicGroups / + JoinPublic over servicedisc.Client. + store/ history behind an interface; bbolt (native, //go:build !js) + + in-memory ring (wasm, //go:build js). Same pattern as cxds/idxdb. + +cmd/apps/skychat → thin adapter: core + app-client transport + HTTP/SSE UI + bbolt store +cmd/wasm-visor/skychat_js.go → thin adapter: SAME core + DmsgNetworker + in-memory store + JS hooks +pkg/visor/*group*/*pairing* → RPC surface over the core (unchanged externally) +``` + +Transport abstraction: one `Transport` interface (`Dial(pk, port) (Conn, error)`, +`Listen(port) (Listener, error)`), with adapters: +`appclient` (native, over the visor app surface), `dmsgdirect` (wasm DmsgNetworker), +`tcpdirect`, `cxotcp`. "Five ways a message travels" become five adapters behind +one interface — accept-interface-at-the-consumer, per the Go coding standard (K7). + +Applies the standard's kernel directly: K2 (one owning type per shared collection, +no package globals), K6 (build-tag platform splits), K7 (small consumer-side +interfaces), and the visorcore convergence precedent. + +## 4. Message model & ordering + +One struct: + +```go +type Message struct { + ID MessageID // deterministic: hash(SenderPK, Seq) — stable across resend + SenderPK cipher.PubKey + Room RoomID // zero value = 1:1 DM (peer is the other endpoint) + TS int64 // sender wall-clock, unix nanos (display hint only) + Seq uint64 // per-sender monotonic counter (authoritative within a sender) + Body []byte // UTF-8 text (or, for private groups, ciphertext) + Sig []byte // secp256k1 over the canonical encoding +} +``` + +Ordering: today it is wall-clock `msgs//`, which reorders under +skew. Proposal: keep `(SenderPK, Seq)` as the authoritative per-sender order, and +for cross-sender display use a **small bounded reorder buffer** sorted by +`(TS, SenderPK, Seq)` with a short grace window (e.g. 2s) before commit. This is +not a full CRDT/vector clock — it is a pragmatic "sort within a window" that +removes the visible flip without a consensus protocol. A vector-clock upgrade can +land later behind the same `Message` shape (Seq already carries per-sender causality). + +Dedup: content-identity by `ID` into the existing bounded `recentSet`. + +## 5. Group model (federated) + +Collapse the two generations to **federated-only**: +- Every member (owner included) publishes to its **own** CXO feed. +- Each session holds one `treestore.Subscriber` per other member (peerSubs). +- Roster/admin changes are signed `RosterMutation`/`AdminMutation` gossiped over + feed prefixes and reconciled per-visor (as today, `group/gossip.go`). +- Owner-relay (`Record.Port + 1` listener) is retained ONLY as an optional + bootstrap/fallback path; group liveness never depends on the owner being online. + +This removes the documented owner-offline SPOF and deletes the dead +mirror-prefix / legacy `sub` field carried for parse-compat. + +## 6. Public group service discovery (the new capability) + +A public group is just a new **service type** in the existing service-discovery. +No new service, no new infrastructure. + +Add to `pkg/servicedisc/types.go`: + +```go +ServiceTypeSkychat = "skychat" +``` + +### Publish +A visor hosting a *public* group registers one SD entry per room: +- `type: skychat` +- `address: :` — the feed/relay entry point +- metadata: `group_id` (uuid), `name`, `topic`, `mode: public`, `feed_pk`, `members` (count) + +SD entries are keyed by the advertiser's PK, so "who hosts this room" is +authenticated for free — no separate signing needed for the directory entry. + +### Discover +Any client queries the same endpoint the wasm proxy panel already uses for +`type=proxy`: + +``` +GET sd.dmsg /api/services?type=skychat +→ [{ address: ":", group_id, name, topic, mode, members }, …] +``` + +The UI list pattern already exists (`browse.js` populates the skysocks dropdown +from `?type=proxy`); a "public rooms" list reuses it verbatim. + +### Join +1. Pick a room from the directory. +2. Subscribe to the owner's CXO feed (public ⇒ read is open). +3. To write: publish to your own feed; roster gossip auto-admits in public mode + (vs owner-allowlist in private mode). +4. Roster gossip propagates the new member to everyone. + +### Public-mode considerations +- **Moderation.** Public = anyone joins = spam risk. Reuse the existing signed + roster eviction (`SetAllowlist` / `AdminMutation`) for bans; add per-sender + rate limiting; optionally a "read-only until approved" tier. +- **Encryption.** Private groups share an AES key out-of-band. Public rooms run + either unencrypted (it is public anyway) or with a *published* room key; either + way per-message signatures stay for authenticity. +- **Trust.** SD is a semi-central *directory* (like a tracker/DNS); the chat data + plane stays P2P/federated over CXO. Matches skywire's overall model, and a + future Kademlia DHT can replace SD-for-discovery behind the `discovery` + interface without touching the data plane. + +`pkg/skychat/discovery` API: + +```go +PublishGroup(ctx, GroupInfo) error // owner advertises a public room +ListPublicGroups(ctx) ([]GroupInfo, error) // client browses the directory +JoinPublic(ctx, GroupInfo) (*Session, error) +``` + +## 7. Wasm desktop chat window (landed with this RFC) + +`pkg/wasmhv/browseui/browse.js` gains `createChatWindow` — a 1:1 skychat client +as a WinBox desktop window, the missing peer to the skynet browser. It drives the +two existing wasm-visor JS hooks: +`skychatSend(peerPkHex, text) → Promise` and `skychatMessages() → JSON [{from,text,ts,out}]`. +Distinct `from` PKs in the buffer are surfaced as clickable chips, so an incoming +message from an unknown peer is discoverable without knowing their key first. +Gated on `skywireVisor.skychatSend` (wasm-visor only; native keeps its Angular +skychat tab), exactly like the `host` window. Added to the ☰ app menu as `chat`. + +This is deliberately a thin client over the current wasm hooks; once §3 lands, it +re-points at the shared core (groups + discovery) with no UI rewrite. + +## 8. Sequencing + +1. **Wasm desktop chat window** — done (§7). +2. **`pkg/skychat/message` + wire codec** — collapse the 3 framing copies; lowest-risk + structural win; native + wasm adopt it behind the `Transport` interface. +3. **`ServiceTypeSkychat` + `pkg/skychat/discovery`** + a "public rooms" list in the + wasm desktop and the Angular tab — the discovery feature (§6). +4. **Collapse group generations** to federated-only; decompose the god files + (`commands/skychat.go`, `group/session.go`, `group/manager.go`). +5. **Reorder buffer** for causal-ish display ordering (§4). + +Each step is independently shippable and leaves the app working. + +## 9. Open questions + +- Public-room key distribution: published room key vs plaintext — per-room policy flag? +- Should SD carry a coarse `members`/`activity` count (staleness vs usefulness)? +- Rate-limit budget for public rooms — per-sender, per-room, or both? +- Do we advertise 1:1 "reachable for DM" presence in SD too, or only group rooms? diff --git a/docs/skywire-goda-graph.svg b/docs/skywire-goda-graph.svg index 03fc4f31c7..e7676a4719 100644 --- a/docs/skywire-goda-graph.svg +++ b/docs/skywire-goda-graph.svg @@ -4,76 +4,76 @@ - - + + G - + github.com/skycoin/skywire - -github.com/skycoin/skywire -25 / 610B + +github.com/skycoin/skywire +25 / 610B - + github.com/skycoin/skywire/cmd/skywire/commands - - -github.com/skycoin/skywire/cmd/skywire/commands -1220 / 48.3KB + + +github.com/skycoin/skywire/cmd/skywire/commands +1234 / 49.0KB github.com/skycoin/skywire:e->github.com/skycoin/skywire/cmd/skywire/commands - - + + - + github.com/skycoin/skywire/pkg/buildinfo - - -github.com/skycoin/skywire/pkg/buildinfo -198 / 6.2KB + + +github.com/skycoin/skywire/pkg/buildinfo +198 / 6.2KB github.com/skycoin/skywire:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/flags - - -github.com/skycoin/skywire/pkg/flags -271 / 10.4KB + + +github.com/skycoin/skywire/pkg/flags +271 / 10.4KB github.com/skycoin/skywire:e->github.com/skycoin/skywire/pkg/flags - - + + github.com/skycoin/skywire/cmd/apps/pty - -github.com/skycoin/skywire/cmd/apps/pty -41 / 1.7KB + +github.com/skycoin/skywire/cmd/apps/pty +41 / 1.7KB @@ -81,73 +81,73 @@ github.com/skycoin/skywire/cmd/apps/pty/commands - -github.com/skycoin/skywire/cmd/apps/pty/commands -171 / 6.6KB + +github.com/skycoin/skywire/cmd/apps/pty/commands +171 / 6.6KB github.com/skycoin/skywire/cmd/apps/pty:e->github.com/skycoin/skywire/cmd/apps/pty/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands - - -github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands -259 / 8.0KB + + +github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands +259 / 8.0KB github.com/skycoin/skywire/cmd/apps/pty/commands:e->github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands - - -github.com/skycoin/skywire/cmd/dmsg/pty-host/commands -462 / 16.5KB + + +github.com/skycoin/skywire/cmd/dmsg/pty-host/commands +462 / 16.5KB github.com/skycoin/skywire/cmd/apps/pty/commands:e->github.com/skycoin/skywire/cmd/dmsg/pty-host/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands - - -github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands -60 / 2.0KB + + +github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands +60 / 2.0KB github.com/skycoin/skywire/cmd/apps/pty/commands:e->github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands - - + + github.com/skycoin/skywire/cmd/apps/skychat - -github.com/skycoin/skywire/cmd/apps/skychat -38 / 1.5KB + +github.com/skycoin/skywire/cmd/apps/skychat +38 / 1.5KB @@ -155,373 +155,373 @@ github.com/skycoin/skywire/cmd/apps/skychat/commands - -github.com/skycoin/skywire/cmd/apps/skychat/commands -3779 / 138.2KB + +github.com/skycoin/skywire/cmd/apps/skychat/commands +3779 / 138.2KB github.com/skycoin/skywire/cmd/apps/skychat:e->github.com/skycoin/skywire/cmd/apps/skychat/commands - - + + github.com/skycoin/skywire/cmd/apps/skychat/group - -github.com/skycoin/skywire/cmd/apps/skychat/group -4697 / 190.5KB + +github.com/skycoin/skywire/cmd/apps/skychat/group +4697 / 190.5KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/cmd/apps/skychat/group - - + + github.com/skycoin/skywire/cmd/apps/skychat/history - -github.com/skycoin/skywire/cmd/apps/skychat/history -738 / 23.3KB + +github.com/skycoin/skywire/cmd/apps/skychat/history +738 / 23.3KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/cmd/apps/skychat/history - - + + - + github.com/skycoin/skywire/pkg/app - - -github.com/skycoin/skywire/pkg/app -437 / 13.4KB + + +github.com/skycoin/skywire/pkg/app +440 / 13.7KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/app - - + + - + github.com/skycoin/skywire/pkg/app/appnet - - -github.com/skycoin/skywire/pkg/app/appnet -1504 / 50.0KB + + +github.com/skycoin/skywire/pkg/app/appnet +1573 / 52.5KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/app/appserver - - -github.com/skycoin/skywire/pkg/app/appserver -2590 / 77.7KB + + +github.com/skycoin/skywire/pkg/app/appserver +2713 / 83.0KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/pkg/app/launcher - - -github.com/skycoin/skywire/pkg/app/launcher -745 / 25.7KB + + +github.com/skycoin/skywire/pkg/app/launcher +752 / 26.1KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/app/launcher - - + + github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/calvin - - -github.com/skycoin/skywire/pkg/calvin -121 / 5.4KB + + +github.com/skycoin/skywire/pkg/calvin +121 / 5.4KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/pkg/cipher - - -github.com/skycoin/skywire/pkg/cipher -419 / 13.7KB + + +github.com/skycoin/skywire/pkg/cipher +441 / 14.8KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore - - -github.com/skycoin/skywire/pkg/cxo/treestore -2329 / 84.9KB + + +github.com/skycoin/skywire/pkg/cxo/treestore +2329 / 84.9KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/cxo/treestore - - + + - + github.com/skycoin/skywire/pkg/logging - - -github.com/skycoin/skywire/pkg/logging -798 / 24.4KB + + +github.com/skycoin/skywire/pkg/logging +783 / 23.9KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/netutil - - -github.com/skycoin/skywire/pkg/netutil -731 / 21.8KB + + +github.com/skycoin/skywire/pkg/netutil +749 / 22.5KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/routing - - -github.com/skycoin/skywire/pkg/routing -1616 / 54.5KB + + +github.com/skycoin/skywire/pkg/routing +1588 / 53.3KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/skyenv - - -github.com/skycoin/skywire/pkg/skyenv -325 / 17.5KB + + +github.com/skycoin/skywire/pkg/skyenv +292 / 14.0KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/skywire/tcpnoise - - -github.com/skycoin/skywire/pkg/skywire/tcpnoise -119 / 4.7KB + + +github.com/skycoin/skywire/pkg/skywire/tcpnoise +119 / 4.7KB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/skywire/tcpnoise - - + + - + github.com/skycoin/skywire/pkg/visor - - -github.com/skycoin/skywire/pkg/visor -36807 / 1.3MB + + +github.com/skycoin/skywire/pkg/visor +38537 / 1.4MB github.com/skycoin/skywire/cmd/apps/skychat/commands:e->github.com/skycoin/skywire/pkg/visor - - + + github.com/skycoin/skywire/cmd/apps/skychat/group:e->github.com/skycoin/skywire/pkg/app/appnet - - + + github.com/skycoin/skywire/cmd/apps/skychat/group:e->github.com/skycoin/skywire/pkg/cipher - - + + github.com/skycoin/skywire/cmd/apps/skychat/group:e->github.com/skycoin/skywire/pkg/cxo/treestore - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg - - -github.com/skycoin/skywire/pkg/dmsg/dmsg -5226 / 184.2KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsg +6571 / 244.9KB github.com/skycoin/skywire/cmd/apps/skychat/group:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + github.com/skycoin/skywire/cmd/apps/skychat/group:e->github.com/skycoin/skywire/pkg/logging - - + + github.com/skycoin/skywire/cmd/apps/skychat/group:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/util/bbolthealth - - -github.com/skycoin/skywire/pkg/util/bbolthealth -158 / 6.8KB + + +github.com/skycoin/skywire/pkg/util/bbolthealth +158 / 6.8KB github.com/skycoin/skywire/cmd/apps/skychat/group:e->github.com/skycoin/skywire/pkg/util/bbolthealth - - + + github.com/skycoin/skywire/cmd/apps/skychat/pairing - -github.com/skycoin/skywire/cmd/apps/skychat/pairing -931 / 32.4KB + +github.com/skycoin/skywire/cmd/apps/skychat/pairing +931 / 32.4KB github.com/skycoin/skywire/cmd/apps/skychat/pairing:e->github.com/skycoin/skywire/pkg/cipher - - + + github.com/skycoin/skywire/cmd/apps/skychat/pairing:e->github.com/skycoin/skywire/pkg/cxo/treestore - - + + github.com/skycoin/skywire/cmd/apps/skychat/pairing:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + github.com/skycoin/skywire/cmd/apps/skychat/pairing:e->github.com/skycoin/skywire/pkg/logging - - + + github.com/skycoin/skywire/cmd/apps/skychat/pairing:e->github.com/skycoin/skywire/pkg/skyenv - - + + github.com/skycoin/skywire/cmd/apps/skynet - -github.com/skycoin/skywire/cmd/apps/skynet -38 / 1.5KB + +github.com/skycoin/skywire/cmd/apps/skynet +38 / 1.5KB @@ -529,135 +529,135 @@ github.com/skycoin/skywire/cmd/apps/skynet/commands - -github.com/skycoin/skywire/cmd/apps/skynet/commands -165 / 5.7KB + +github.com/skycoin/skywire/cmd/apps/skynet/commands +165 / 5.7KB github.com/skycoin/skywire/cmd/apps/skynet:e->github.com/skycoin/skywire/cmd/apps/skynet/commands - - + + github.com/skycoin/skywire/cmd/apps/skynet-client/commands - - -github.com/skycoin/skywire/cmd/apps/skynet-client/commands -269 / 11.0KB + + +github.com/skycoin/skywire/cmd/apps/skynet-client/commands +282 / 12.0KB github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/app - - + + github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/app/appnet - - + + github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/app/appserver - - + + github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/app/launcher - - + + github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/routing - - + + github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/skynet - - -github.com/skycoin/skywire/pkg/skynet -504 / 15.4KB + + +github.com/skycoin/skywire/pkg/skynet +504 / 15.4KB github.com/skycoin/skywire/cmd/apps/skynet-client/commands:e->github.com/skycoin/skywire/pkg/skynet - - + + github.com/skycoin/skywire/cmd/apps/skynet/commands:e->github.com/skycoin/skywire/pkg/app - - + + github.com/skycoin/skywire/cmd/apps/skynet/commands:e->github.com/skycoin/skywire/pkg/app/appserver - - + + github.com/skycoin/skywire/cmd/apps/skynet/commands:e->github.com/skycoin/skywire/pkg/app/launcher - - + + github.com/skycoin/skywire/cmd/apps/skynet/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + github.com/skycoin/skywire/cmd/apps/skynet/commands:e->github.com/skycoin/skywire/pkg/logging - - + + github.com/skycoin/skywire/cmd/apps/skynet/commands:e->github.com/skycoin/skywire/pkg/visor - - + + github.com/skycoin/skywire/cmd/apps/skysocks - -github.com/skycoin/skywire/cmd/apps/skysocks -38 / 1.5KB + +github.com/skycoin/skywire/cmd/apps/skysocks +38 / 1.5KB @@ -665,187 +665,187 @@ github.com/skycoin/skywire/cmd/apps/skysocks/commands - -github.com/skycoin/skywire/cmd/apps/skysocks/commands -144 / 4.1KB + +github.com/skycoin/skywire/cmd/apps/skysocks/commands +144 / 4.1KB github.com/skycoin/skywire/cmd/apps/skysocks:e->github.com/skycoin/skywire/cmd/apps/skysocks/commands - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client - -github.com/skycoin/skywire/cmd/apps/skysocks-client -38 / 1.5KB + +github.com/skycoin/skywire/cmd/apps/skysocks-client +38 / 1.5KB github.com/skycoin/skywire/cmd/apps/skysocks-client/commands - - -github.com/skycoin/skywire/cmd/apps/skysocks-client/commands -302 / 10.2KB + + +github.com/skycoin/skywire/cmd/apps/skysocks-client/commands +314 / 11.0KB github.com/skycoin/skywire/cmd/apps/skysocks-client:e->github.com/skycoin/skywire/cmd/apps/skysocks-client/commands - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/app - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/app/appnet - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/app/appserver - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/app/launcher - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/netutil - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/routing - - + + github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/skysocks - - -github.com/skycoin/skywire/pkg/skysocks -393 / 10.5KB + + +github.com/skycoin/skywire/pkg/skysocks +400 / 10.9KB github.com/skycoin/skywire/cmd/apps/skysocks-client/commands:e->github.com/skycoin/skywire/pkg/skysocks - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/app - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/app/appnet - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/app/appserver - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/app/launcher - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/routing - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/skyenv - - + + github.com/skycoin/skywire/cmd/apps/skysocks/commands:e->github.com/skycoin/skywire/pkg/skysocks - - + + github.com/skycoin/skywire/cmd/apps/vpn-client - -github.com/skycoin/skywire/cmd/apps/vpn-client -38 / 1.5KB + +github.com/skycoin/skywire/cmd/apps/vpn-client +38 / 1.5KB @@ -853,105 +853,105 @@ github.com/skycoin/skywire/cmd/apps/vpn-client/commands - -github.com/skycoin/skywire/cmd/apps/vpn-client/commands -291 / 8.8KB + +github.com/skycoin/skywire/cmd/apps/vpn-client/commands +291 / 8.8KB github.com/skycoin/skywire/cmd/apps/vpn-client:e->github.com/skycoin/skywire/cmd/apps/vpn-client/commands - - + + github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/app - - + + - + github.com/skycoin/skywire/pkg/app/appevent - - -github.com/skycoin/skywire/pkg/app/appevent -496 / 14.3KB + + +github.com/skycoin/skywire/pkg/app/appevent +497 / 14.4KB github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/app/appevent - - + + github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/app/appserver - - + + github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/app/launcher - - + + github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/routing - - + + github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/vpn - - -github.com/skycoin/skywire/pkg/vpn -1958 / 62.2KB + + +github.com/skycoin/skywire/pkg/vpn +1958 / 62.2KB github.com/skycoin/skywire/cmd/apps/vpn-client/commands:e->github.com/skycoin/skywire/pkg/vpn - - + + github.com/skycoin/skywire/cmd/apps/vpn-server - -github.com/skycoin/skywire/cmd/apps/vpn-server -38 / 1.5KB + +github.com/skycoin/skywire/cmd/apps/vpn-server +38 / 1.5KB @@ -959,79 +959,79 @@ github.com/skycoin/skywire/cmd/apps/vpn-server/commands - -github.com/skycoin/skywire/cmd/apps/vpn-server/commands -195 / 5.9KB + +github.com/skycoin/skywire/cmd/apps/vpn-server/commands +195 / 5.9KB github.com/skycoin/skywire/cmd/apps/vpn-server:e->github.com/skycoin/skywire/cmd/apps/vpn-server/commands - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/app - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/app/appnet - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/app/appserver - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/app/launcher - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/routing - - + + github.com/skycoin/skywire/cmd/apps/vpn-server/commands:e->github.com/skycoin/skywire/pkg/vpn - - + + github.com/skycoin/skywire/cmd/cxo - -github.com/skycoin/skywire/cmd/cxo -7 / 109B + +github.com/skycoin/skywire/cmd/cxo +7 / 109B @@ -1039,11511 +1039,11857 @@ github.com/skycoin/skywire/cmd/cxo/commands - -github.com/skycoin/skywire/cmd/cxo/commands -1210 / 31.7KB + +github.com/skycoin/skywire/cmd/cxo/commands +1210 / 31.7KB github.com/skycoin/skywire/cmd/cxo:e->github.com/skycoin/skywire/cmd/cxo/commands - - + + github.com/skycoin/skywire/cmd/cxo/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/pkg/cxo/node - - -github.com/skycoin/skywire/pkg/cxo/node -4954 / 142.9KB + + +github.com/skycoin/skywire/pkg/cxo/node +4954 / 142.9KB github.com/skycoin/skywire/cmd/cxo/commands:e->github.com/skycoin/skywire/pkg/cxo/node - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject - - -github.com/skycoin/skywire/pkg/cxo/skyobject -3636 / 98.3KB + + +github.com/skycoin/skywire/pkg/cxo/skyobject +3641 / 98.7KB github.com/skycoin/skywire/cmd/cxo/commands:e->github.com/skycoin/skywire/pkg/cxo/skyobject - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject/registry - - -github.com/skycoin/skywire/pkg/cxo/skyobject/registry -5109 / 143.8KB + + +github.com/skycoin/skywire/pkg/cxo/skyobject/registry +5109 / 143.8KB github.com/skycoin/skywire/cmd/cxo/commands:e->github.com/skycoin/skywire/pkg/cxo/skyobject/registry - - + + - + +github.com/skycoin/skywire/cmd/dmsg-tinygo-probe + + +github.com/skycoin/skywire/cmd/dmsg-tinygo-probe +21 / 0.9KB + + + + + +github.com/skycoin/skywire/cmd/dmsg-tinygo-probe:e->github.com/skycoin/skywire/pkg/cipher + + + + + +github.com/skycoin/skywire/pkg/dmsg/disc + + +github.com/skycoin/skywire/pkg/dmsg/disc +1160 / 40.6KB + + + + + +github.com/skycoin/skywire/cmd/dmsg-tinygo-probe:e->github.com/skycoin/skywire/pkg/dmsg/disc + + + + + +github.com/skycoin/skywire/cmd/dmsg-tinygo-probe:e->github.com/skycoin/skywire/pkg/dmsg/dmsg + + + + + github.com/skycoin/skywire/cmd/dmsg/conf - - -github.com/skycoin/skywire/cmd/dmsg/conf -12 / 246B + + +github.com/skycoin/skywire/cmd/dmsg/conf +12 / 246B - + github.com/skycoin/skywire/cmd/dmsg/conf/commands - - -github.com/skycoin/skywire/cmd/dmsg/conf/commands -199 / 7.1KB + + +github.com/skycoin/skywire/cmd/dmsg/conf/commands +199 / 7.1KB - + github.com/skycoin/skywire/cmd/dmsg/conf:e->github.com/skycoin/skywire/cmd/dmsg/conf/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/conf:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/deployment - - -github.com/skycoin/skywire/deployment -689 / 25.3KB + + +github.com/skycoin/skywire/deployment +812 / 30.5KB - + github.com/skycoin/skywire/cmd/dmsg/conf/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/dmsg/conf/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/direct - - -github.com/skycoin/skywire/pkg/dmsg/direct -186 / 5.7KB + + +github.com/skycoin/skywire/pkg/dmsg/direct +208 / 7.0KB - + github.com/skycoin/skywire/cmd/dmsg/conf/commands:e->github.com/skycoin/skywire/pkg/dmsg/direct - - - - - -github.com/skycoin/skywire/pkg/dmsg/disc - - -github.com/skycoin/skywire/pkg/dmsg/disc -1115 / 37.8KB - - + + - + github.com/skycoin/skywire/cmd/dmsg/conf/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/dmsg/conf/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - -github.com/skycoin/skywire/pkg/dmsg/dmsgclient -642 / 26.2KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsgclient +1407 / 58.0KB - + github.com/skycoin/skywire/cmd/dmsg/conf/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - -github.com/skycoin/skywire/pkg/dmsg/dmsghttp -673 / 23.5KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsghttp +728 / 26.6KB - + github.com/skycoin/skywire/cmd/dmsg/conf/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/cmd/dmsg/conf/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial - - -github.com/skycoin/skywire/cmd/dmsg/dial -12 / 246B + + +github.com/skycoin/skywire/cmd/dmsg/dial +12 / 246B - + github.com/skycoin/skywire/cmd/dmsg/dial/commands - - -github.com/skycoin/skywire/cmd/dmsg/dial/commands -162 / 5.7KB + + +github.com/skycoin/skywire/cmd/dmsg/dial/commands +162 / 5.7KB - + github.com/skycoin/skywire/cmd/dmsg/dial:e->github.com/skycoin/skywire/cmd/dmsg/dial/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/cmdutil - - -github.com/skycoin/skywire/pkg/cmdutil -1152 / 37.0KB + + +github.com/skycoin/skywire/pkg/cmdutil +1256 / 41.3KB - + github.com/skycoin/skywire/cmd/dmsg/dial/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/dial/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg - - -github.com/skycoin/skywire/cmd/dmsg/dmsg -12 / 247B + + +github.com/skycoin/skywire/cmd/dmsg/dmsg +12 / 247B - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsg/commands -148 / 4.4KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsg/commands +148 / 4.4KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg:e->github.com/skycoin/skywire/cmd/dmsg/dmsg/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery - - -github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery -12 / 276B + + +github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery +12 / 276B - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands -404 / 14.2KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands +404 / 14.2KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery:e->github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/dmsg/cmdutil - - -github.com/skycoin/skywire/pkg/dmsg/cmdutil -228 / 7.5KB + + +github.com/skycoin/skywire/pkg/dmsg/cmdutil +228 / 7.5KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/dmsg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/pkg/services - - -github.com/skycoin/skywire/pkg/services -327 / 10.9KB + + +github.com/skycoin/skywire/pkg/services +327 / 10.9KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc - - -github.com/skycoin/skywire/pkg/services/dmsgdisc -473 / 16.8KB + + +github.com/skycoin/skywire/pkg/services/dmsgdisc +532 / 19.5KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands:e->github.com/skycoin/skywire/pkg/services/dmsgdisc - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server - - -github.com/skycoin/skywire/cmd/dmsg/dmsg-server -12 / 267B + + +github.com/skycoin/skywire/cmd/dmsg/dmsg-server +12 / 267B - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands -39 / 1.3KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands +39 / 1.3KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server:e->github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/config - - -github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/config -54 / 1.6KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/config +54 / 1.6KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/config - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start - - -github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start -77 / 2.7KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start +77 / 2.7KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver - - -github.com/skycoin/skywire/pkg/dmsg/dmsgserver -457 / 16.3KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsgserver +561 / 22.6KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/config:e->github.com/skycoin/skywire/pkg/dmsg/dmsgserver - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start:e->github.com/skycoin/skywire/pkg/dmsg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start:e->github.com/skycoin/skywire/pkg/dmsg/dmsgserver - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv - - -github.com/skycoin/skywire/pkg/services/dmsgsrv -426 / 15.7KB + + +github.com/skycoin/skywire/pkg/services/dmsgsrv +563 / 23.0KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands/start:e->github.com/skycoin/skywire/pkg/services/dmsgsrv - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5 - - -github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5 -12 / 267B + + +github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5 +12 / 267B - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands -275 / 9.0KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands +275 / 9.0KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5:e->github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands:e->github.com/skycoin/skywire/pkg/dmsg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/conf/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dial/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsg-discovery/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsg-server/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsg-socks5/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands -399 / 12.9KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands +399 / 12.9KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands -283 / 7.8KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands +283 / 7.8KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands -117 / 3.7KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands +117 / 3.7KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands -162 / 5.5KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands +162 / 5.5KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands - - -github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands -533 / 17.9KB + + +github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands +533 / 17.9KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/pty-host/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/self-ping/commands - - -github.com/skycoin/skywire/cmd/dmsg/self-ping/commands -117 / 4.4KB + + +github.com/skycoin/skywire/cmd/dmsg/self-ping/commands +117 / 4.4KB - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/cmd/dmsg/self-ping/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsg/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl - - -github.com/skycoin/skywire/cmd/dmsg/dmsgcurl -12 / 258B + + +github.com/skycoin/skywire/cmd/dmsg/dmsgcurl +12 / 258B - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl:e->github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgcurl/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp - - -github.com/skycoin/skywire/cmd/dmsg/dmsghttp -12 / 270B + + +github.com/skycoin/skywire/cmd/dmsg/dmsghttp +12 / 270B - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp:e->github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands:e->github.com/skycoin/skywire/pkg/dmsg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsghttp/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip - - -github.com/skycoin/skywire/cmd/dmsg/dmsgip -12 / 256B + + +github.com/skycoin/skywire/cmd/dmsg/dmsgip +12 / 256B - + github.com/skycoin/skywire/cmd/dmsg/dmsgip:e->github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgip/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe - - -github.com/skycoin/skywire/cmd/dmsg/dmsgprobe -12 / 266B + + +github.com/skycoin/skywire/cmd/dmsg/dmsgprobe +12 / 266B - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe:e->github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands:e->github.com/skycoin/skywire/pkg/skywire/tcpnoise - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb - - -github.com/skycoin/skywire/cmd/dmsg/dmsgweb -12 / 255B + + +github.com/skycoin/skywire/cmd/dmsg/dmsgweb +12 / 255B - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb:e->github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands:e->github.com/skycoin/skywire/pkg/dmsg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/pkg/dmsgweb - - -github.com/skycoin/skywire/pkg/dmsgweb -544 / 19.1KB + + +github.com/skycoin/skywire/pkg/dmsgweb +965 / 38.4KB - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands:e->github.com/skycoin/skywire/pkg/dmsgweb - - + + - + github.com/skycoin/skywire/cmd/dmsg/dmsgweb/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli - - -github.com/skycoin/skywire/cmd/dmsg/pty-cli -12 / 263B + + +github.com/skycoin/skywire/cmd/dmsg/pty-cli +12 / 263B - + github.com/skycoin/skywire/cmd/dmsg/pty-cli:e->github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/pkg/pty - - -github.com/skycoin/skywire/pkg/pty -4095 / 135.4KB + + +github.com/skycoin/skywire/pkg/pty +4095 / 135.4KB - + github.com/skycoin/skywire/cmd/dmsg/pty-cli/commands:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host - - -github.com/skycoin/skywire/cmd/dmsg/pty-host -12 / 266B + + +github.com/skycoin/skywire/cmd/dmsg/pty-host +12 / 266B - + github.com/skycoin/skywire/cmd/dmsg/pty-host:e->github.com/skycoin/skywire/cmd/dmsg/pty-host/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/dmsg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-host/commands:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-ui - - -github.com/skycoin/skywire/cmd/dmsg/pty-ui -12 / 260B + + +github.com/skycoin/skywire/cmd/dmsg/pty-ui +12 / 260B - + github.com/skycoin/skywire/cmd/dmsg/pty-ui:e->github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-ui:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/pty-ui/commands:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/dmsg/self-ping/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/dmsg/self-ping/commands:e->github.com/skycoin/skywire/pkg/dmsg/direct - - + + - + github.com/skycoin/skywire/cmd/dmsg/self-ping/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/dmsg/self-ping/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/dmsg/self-ping/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/cmd/dmsg/self-ping/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/gen - - -github.com/skycoin/skywire/cmd/gen -92 / 3.2KB + + +github.com/skycoin/skywire/cmd/gen +92 / 3.2KB - + github.com/skycoin/skywire/cmd/mux-probe-assert - - -github.com/skycoin/skywire/cmd/mux-probe-assert -301 / 10.7KB + + +github.com/skycoin/skywire/cmd/mux-probe-assert +301 / 10.6KB - + github.com/skycoin/skywire/cmd/skycoin-skywire - - -github.com/skycoin/skywire/cmd/skycoin-skywire -25 / 630B + + +github.com/skycoin/skywire/cmd/skycoin-skywire +25 / 630B - + github.com/skycoin/skywire/cmd/skycoin-skywire:e->github.com/skycoin/skywire/cmd/skywire/commands - - + + - + github.com/skycoin/skywire/cmd/skycoin-skywire:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/skycoin-skywire:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/skywire - - -github.com/skycoin/skywire/cmd/skywire -15 / 249B + + +github.com/skycoin/skywire/cmd/skywire +15 / 249B - + github.com/skycoin/skywire/cmd/skywire:e->github.com/skycoin/skywire/cmd/skywire/commands - - + + - + github.com/skycoin/skywire/cmd/skywire:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/skywire-cli - - -github.com/skycoin/skywire/cmd/skywire-cli -12 / 246B + + +github.com/skycoin/skywire/cmd/skywire-cli +12 / 246B - + github.com/skycoin/skywire/cmd/skywire-cli/commands - - -github.com/skycoin/skywire/cmd/skywire-cli/commands -249 / 10.0KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands +251 / 10.1KB - + github.com/skycoin/skywire/cmd/skywire-cli:e->github.com/skycoin/skywire/cmd/skywire-cli/commands - - + + - + github.com/skycoin/skywire/cmd/skywire-cli:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/cliuptime - - -github.com/skycoin/skywire/cmd/skywire-cli/cliuptime -773 / 25.0KB + + +github.com/skycoin/skywire/cmd/skywire-cli/cliuptime +773 / 25.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc -954 / 37.3KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc +1037 / 40.8KB - + github.com/skycoin/skywire/cmd/skywire-cli/cliuptime:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/cliuptime:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/uptimestats - - -github.com/skycoin/skywire/pkg/uptimestats -349 / 11.4KB + + +github.com/skycoin/skywire/pkg/uptimestats +349 / 11.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/cliuptime:e->github.com/skycoin/skywire/pkg/uptimestats - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - -github.com/skycoin/skywire/cmd/skywire-cli/cliutil -127 / 4.2KB + + +github.com/skycoin/skywire/cmd/skywire-cli/cliutil +127 / 4.2KB - + github.com/skycoin/skywire/cmd/skywire-cli/cliutil:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/cliutil:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/cliutil/livetui - - -github.com/skycoin/skywire/cmd/skywire-cli/cliutil/livetui -210 / 6.1KB + + +github.com/skycoin/skywire/cmd/skywire-cli/cliutil/livetui +210 / 6.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/completion - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/completion -38 / 1.0KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/completion +38 / 1.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/completion - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/config -3077 / 121.2KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/config +3081 / 122.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/config - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg -3421 / 120.6KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg +3467 / 122.2KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/got - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/got -567 / 16.9KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/got +567 / 16.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/got - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop -969 / 30.1KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop +969 / 30.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop - - + + - + +github.com/skycoin/skywire/cmd/skywire-cli/commands/hv + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/hv +484 / 22.2KB + + + + + +github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/hv + + + + + github.com/skycoin/skywire/cmd/skywire-cli/commands/log - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/log -1444 / 51.2KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/log +1473 / 52.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/log - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mail - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/mail -110 / 4.0KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/mail +110 / 4.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/mail - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc -194 / 7.1KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc +194 / 7.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy -3064 / 111.0KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy +3064 / 111.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pty - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/pty -55 / 2.5KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/pty +55 / 2.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/pty - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pv - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/pv -264 / 9.5KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/pv +264 / 9.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/pv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/resolver - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/resolver -459 / 18.0KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/resolver +459 / 18.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/resolver - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/reward -670 / 23.1KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/reward +667 / 22.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/reward - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards -2721 / 101.9KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards +2782 / 105.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rg - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/rg -226 / 7.0KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/rg +226 / 7.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/route -2063 / 74.2KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/route +2117 / 76.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/route - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sd - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/sd -412 / 13.9KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/sd +412 / 13.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/sd - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/serve - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/serve -358 / 13.3KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/serve +364 / 13.7KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/serve - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat -4212 / 148.9KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat +4212 / 148.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skycoin - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/skycoin -216 / 7.5KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/skycoin +216 / 7.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/skycoin - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet -795 / 28.3KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet +889 / 32.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/survey -148 / 5.2KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/survey +151 / 5.3KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/survey - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/svc -653 / 23.6KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/svc +676 / 25.2KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/svc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/tp -3859 / 134.8KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/tp +3869 / 135.7KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/tp - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tps - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/tps -156 / 5.8KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/tps +156 / 5.8KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/tps - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ut - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/ut -423 / 15.2KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/ut +423 / 15.2KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/ut - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/util - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/util -695 / 21.5KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/util +695 / 21.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/util - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/version - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/version -293 / 10.1KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/version +293 / 10.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/version - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/visor -5384 / 182.9KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/visor +5457 / 186.7KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn -956 / 31.1KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn +956 / 31.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/pkg/dmsgc - - -github.com/skycoin/skywire/pkg/dmsgc -147 / 6.4KB + + +github.com/skycoin/skywire/pkg/dmsgc +181 / 8.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/dmsgc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/transport/network - - -github.com/skycoin/skywire/pkg/transport/network -1542 / 52.0KB + + +github.com/skycoin/skywire/pkg/transport/network +4194 / 149.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/transport/network - - + + - + github.com/skycoin/skywire/pkg/visor/rewardconfig - - -github.com/skycoin/skywire/pkg/visor/rewardconfig -115 / 4.8KB + + +github.com/skycoin/skywire/pkg/visor/rewardconfig +115 / 4.8KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/visor/rewardconfig - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig - - -github.com/skycoin/skywire/pkg/visor/visorconfig -2371 / 92.0KB + + +github.com/skycoin/skywire/pkg/visor/visorconfig +2593 / 104.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/config:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/smb/commands - - -github.com/skycoin/skywire/cmd/smb/commands -192 / 6.8KB + + +github.com/skycoin/skywire/cmd/smb/commands +192 / 6.8KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/cmd/smb/commands - - + + - + github.com/skycoin/skywire/cmd/sub/commands - - -github.com/skycoin/skywire/cmd/sub/commands -267 / 8.8KB + + +github.com/skycoin/skywire/cmd/sub/commands +267 / 8.8KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/cmd/sub/commands - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/cmdutil - - - - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgscp - - -github.com/skycoin/skywire/pkg/dmsg/dmsgscp -1003 / 36.4KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsgscp +1003 / 36.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/dmsg/dmsgscp - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/skywire/tcpnoise - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty -239 / 8.6KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty +239 / 8.6KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/edit - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/edit -86 / 2.2KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/edit +86 / 2.2KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/got:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/got:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/got - - -github.com/skycoin/skywire/pkg/got -694 / 19.7KB + + +github.com/skycoin/skywire/pkg/got +694 / 19.7KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/got:e->github.com/skycoin/skywire/pkg/got - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/got:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/visor/rpcgrpc - - -github.com/skycoin/skywire/pkg/visor/rpcgrpc -8018 / 299.2KB + + +github.com/skycoin/skywire/pkg/visor/rpcgrpc +8018 / 299.2KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/pkg/visor/rpcgrpc - - + + - + github.com/skycoin/skywire/third_party/VictoriaMetrics/metrics - - -github.com/skycoin/skywire/third_party/VictoriaMetrics/metrics -3103 / 103.3KB + + +github.com/skycoin/skywire/third_party/VictoriaMetrics/metrics +3103 / 103.3KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/third_party/VictoriaMetrics/metrics - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4 - - -github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4 -296 / 9.5KB + + +github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4 +296 / 9.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4 - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/colorschemes - - -github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/colorschemes -268 / 7.5KB + + +github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/colorschemes +268 / 7.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/colorschemes - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/devices - - -github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/devices -940 / 27.6KB + + +github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/devices +940 / 27.6KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/devices - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/layout - - -github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/layout -464 / 13.0KB + + +github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/layout +464 / 13.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/layout - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets - - -github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets -1586 / 45.9KB + + +github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets +1586 / 45.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/gotop:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets - - + + + + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/hv:e->github.com/skycoin/skywire/pkg/cipher + + + + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/hv:e->github.com/skycoin/skywire/pkg/visor + + + + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/hv:e->github.com/skycoin/skywire/pkg/visor/visorconfig + + + + + +github.com/skycoin/skywire/pkg/wasmhv + + +github.com/skycoin/skywire/pkg/wasmhv +1445 / 55.2KB + + + + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/hv:e->github.com/skycoin/skywire/pkg/wasmhv + + + + + +github.com/skycoin/skywire/pkg/wasmhv/ctlbridge + + +github.com/skycoin/skywire/pkg/wasmhv/ctlbridge +268 / 8.5KB + + + + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/hv:e->github.com/skycoin/skywire/pkg/wasmhv/ctlbridge + + + + + +github.com/skycoin/skywire/pkg/wasmhv/wasmbin + + +github.com/skycoin/skywire/pkg/wasmhv/wasmbin +33 / 1.3KB + + + + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/hv:e->github.com/skycoin/skywire/pkg/wasmhv/wasmbin + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/jq - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/jq -147 / 3.4KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/jq +147 / 3.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/log:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/log:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/log:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/log:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/log:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/log:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/log:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/log:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mail:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mail:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mail:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/servicedisc - - -github.com/skycoin/skywire/pkg/servicedisc -588 / 17.1KB + + +github.com/skycoin/skywire/pkg/servicedisc +588 / 17.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pty:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs -736 / 27.5KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs +732 / 27.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pty:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ssh - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/ssh -245 / 9.9KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/ssh +245 / 9.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pty:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/ssh - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd -256 / 9.6KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd +256 / 9.6KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pty:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/pkg/cmdutil - - - - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ptyfs:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pv:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pv:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pv:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pv:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/pkg/transport - - -github.com/skycoin/skywire/pkg/transport -3179 / 109.9KB + + +github.com/skycoin/skywire/pkg/transport +3339 / 117.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/pv:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/resolver:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/resolver:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/pkg/skynetca - - -github.com/skycoin/skywire/pkg/skynetca -382 / 12.7KB + + +github.com/skycoin/skywire/pkg/skynetca +382 / 12.7KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/resolver:e->github.com/skycoin/skywire/pkg/skynetca - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/resolver:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/cipher - - + + - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/cmdutil + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/visor/rewardconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/rewards - - -github.com/skycoin/skywire/rewards -28 / 0.8KB + + +github.com/skycoin/skywire/rewards +28 / 0.8KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/reward:e->github.com/skycoin/skywire/rewards - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/log - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server -5503 / 507.4KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server +5517 / 508.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/tgbot - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/tgbot -102 / 3.3KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/tgbot +102 / 3.3KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/tgbot - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/svc/geoip/commands - - -github.com/skycoin/skywire/cmd/svc/geoip/commands -268 / 8.2KB + + +github.com/skycoin/skywire/cmd/svc/geoip/commands +268 / 8.2KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/cmd/svc/geoip/commands - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/pkg/visor/rewardconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards:e->github.com/skycoin/skywire/rewards - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/cmd/svc/geoip/commands - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient + + - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp + + - + github.com/skycoin/skywire/pkg/httputil - - -github.com/skycoin/skywire/pkg/httputil -318 / 10.7KB + + +github.com/skycoin/skywire/pkg/httputil +319 / 10.8KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/tpviz - - -github.com/skycoin/skywire/pkg/tpviz -2341 / 79.2KB + + +github.com/skycoin/skywire/pkg/tpviz +2506 / 86.3KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/tpviz - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server:e->github.com/skycoin/skywire/pkg/visor/rewardconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rg:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rg:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil/livetui - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rg:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rg:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil/livetui - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/rfclient - - -github.com/skycoin/skywire/pkg/rfclient -184 / 5.9KB + + +github.com/skycoin/skywire/pkg/rfclient +201 / 6.5KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/rfclient - - + + - + github.com/skycoin/skywire/pkg/route-finder/store - - -github.com/skycoin/skywire/pkg/route-finder/store -419 / 14.3KB + + +github.com/skycoin/skywire/pkg/route-finder/store +420 / 14.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/route-finder/store - - + + - + github.com/skycoin/skywire/pkg/router - - -github.com/skycoin/skywire/pkg/router -12342 / 455.2KB + + +github.com/skycoin/skywire/pkg/router +13171 / 491.7KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/router/policy - - -github.com/skycoin/skywire/pkg/router/policy -1994 / 72.1KB + + +github.com/skycoin/skywire/pkg/router/policy +1994 / 72.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/router/policy - - + + - + github.com/skycoin/skywire/pkg/router/policy/wasm - - -github.com/skycoin/skywire/pkg/router/policy/wasm -886 / 31.1KB + + +github.com/skycoin/skywire/pkg/router/policy/wasm +886 / 31.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/router/policy/wasm - - + + - + github.com/skycoin/skywire/pkg/router/setupmetrics - - -github.com/skycoin/skywire/pkg/router/setupmetrics -857 / 31.6KB + + +github.com/skycoin/skywire/pkg/router/setupmetrics +873 / 32.3KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/router/setupmetrics - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/store - - -github.com/skycoin/skywire/pkg/transport-discovery/store -2688 / 94.0KB + + +github.com/skycoin/skywire/pkg/transport-discovery/store +2688 / 94.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/pkg/transport/types - - -github.com/skycoin/skywire/pkg/transport/types -71 / 2.4KB + + +github.com/skycoin/skywire/pkg/transport/types +174 / 8.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/visor/rpcgrpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/route:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/clicache - - -github.com/skycoin/skywire/pkg/clicache -201 / 6.9KB + + +github.com/skycoin/skywire/pkg/clicache +201 / 6.9KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/clicache - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + + + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/dmsgc + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc:e->github.com/skycoin/skywire/pkg/visor/rpcgrpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sd:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sd:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sd:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sd:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/serve:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/serve:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/serve:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/serve:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat:e->github.com/skycoin/skywire/cmd/apps/skychat/group - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat:e->github.com/skycoin/skywire/pkg/skywire/tcpnoise - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skychat:e->github.com/skycoin/skywire/pkg/visor/rpcgrpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skycoin:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skycoin:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skycoin:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skycoin:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/skynet:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ssh:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ssh:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ssh:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ssh:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/sshd:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/survey:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/pkg/dmsg/direct - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/serviceuptime - - -github.com/skycoin/skywire/pkg/serviceuptime -764 / 25.0KB + + +github.com/skycoin/skywire/pkg/serviceuptime +764 / 25.0KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/pkg/serviceuptime - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/svc:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil/livetui - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/tpviz - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/uptimestats - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tp:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tps:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tps:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/tps:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ut:e->github.com/skycoin/skywire/cmd/skywire-cli/cliuptime - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ut:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ut:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ut:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/ut:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/util:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/edit - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/util:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/jq - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/version:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/version:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil/livetui - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor/ping - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/visor/ping -2806 / 101.4KB + + +github.com/skycoin/skywire/cmd/skywire-cli/commands/visor/ping +2806 / 101.4KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/visor/ping - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/app/appcommon - - -github.com/skycoin/skywire/pkg/app/appcommon -778 / 23.3KB + + +github.com/skycoin/skywire/pkg/app/appcommon +801 / 24.1KB - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/app/appcommon - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/serviceuptime - - - - - -github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/transport/network - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor/ping:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor/ping:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor/ping:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/visor/ping:e->github.com/skycoin/skywire/pkg/visor/rpcgrpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/cmd/skywire-cli/cliutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/visor - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire-visor - - -github.com/skycoin/skywire/cmd/skywire-visor -12 / 260B + + +github.com/skycoin/skywire/cmd/skywire-visor +12 / 260B - + github.com/skycoin/skywire/cmd/skywire-visor:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/skywire-visor:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/apps/pty/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/apps/skychat/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/apps/skynet-client/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/apps/skynet/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/apps/skysocks-client/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/apps/skysocks/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/apps/vpn-client/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/apps/vpn-server/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/cxo/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsg/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/dmsg/dmsgprobe/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/skywire-cli/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands/doc - - -github.com/skycoin/skywire/cmd/skywire/commands/doc -538 / 22.4KB + + +github.com/skycoin/skywire/cmd/skywire/commands/doc +538 / 22.4KB - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/skywire/commands/doc - - + + + + + +github.com/skycoin/skywire/cmd/skywire/commands/web + + +github.com/skycoin/skywire/cmd/skywire/commands/web +480 / 16.2KB + + + + + +github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/skywire/commands/web + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands - - -github.com/skycoin/skywire/cmd/svc/skywire-services/commands -95 / 3.1KB + + +github.com/skycoin/skywire/cmd/svc/skywire-services/commands +95 / 3.1KB - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/cmd/svc/skywire-services/commands - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/skywireconfig/autoconfigcmd - - -github.com/skycoin/skywire/pkg/skywireconfig/autoconfigcmd -414 / 26.3KB + + +github.com/skycoin/skywire/pkg/skywireconfig/autoconfigcmd +414 / 26.3KB - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/pkg/skywireconfig/autoconfigcmd - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/skywire/commands:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/cmd/skywire/commands/doc:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/smb - - -github.com/skycoin/skywire/cmd/smb -52 / 2.1KB + + +github.com/skycoin/skywire/cmd/smb +52 / 2.1KB - + github.com/skycoin/skywire/cmd/smb:e->github.com/skycoin/skywire/cmd/smb/commands - - + + - + github.com/skycoin/skywire/cmd/smb/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/smb/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/smb/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/smb/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/smb/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/smb/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/smb/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/skymailbridge - - -github.com/skycoin/skywire/pkg/skymailbridge -454 / 16.0KB + + +github.com/skycoin/skywire/pkg/skymailbridge +454 / 16.0KB - + github.com/skycoin/skywire/cmd/smb/commands:e->github.com/skycoin/skywire/pkg/skymailbridge - - + + - + github.com/skycoin/skywire/cmd/sub - - -github.com/skycoin/skywire/cmd/sub -46 / 1.8KB + + +github.com/skycoin/skywire/cmd/sub +46 / 1.8KB - + github.com/skycoin/skywire/cmd/sub:e->github.com/skycoin/skywire/cmd/sub/commands - - + + - + github.com/skycoin/skywire/cmd/sub/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/sub/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/sub/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/sub/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/sub/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/sub/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/sub/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/skyudpbridge - - -github.com/skycoin/skywire/pkg/skyudpbridge -429 / 13.3KB + + +github.com/skycoin/skywire/pkg/skyudpbridge +429 / 13.3KB - + github.com/skycoin/skywire/cmd/sub/commands:e->github.com/skycoin/skywire/pkg/skyudpbridge - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver - - -github.com/skycoin/skywire/cmd/svc/address-resolver -12 / 282B + + +github.com/skycoin/skywire/cmd/svc/address-resolver +12 / 282B - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands - - -github.com/skycoin/skywire/cmd/svc/address-resolver/commands -280 / 9.2KB + + +github.com/skycoin/skywire/cmd/svc/address-resolver/commands +280 / 9.2KB - + github.com/skycoin/skywire/cmd/svc/address-resolver:e->github.com/skycoin/skywire/cmd/svc/address-resolver/commands - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api - - -github.com/skycoin/skywire/pkg/address-resolver/api -857 / 32.4KB + + +github.com/skycoin/skywire/pkg/address-resolver/api +880 / 33.5KB - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/address-resolver/api - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/ar - - -github.com/skycoin/skywire/pkg/services/ar -254 / 7.6KB + + +github.com/skycoin/skywire/pkg/services/ar +255 / 7.7KB - + github.com/skycoin/skywire/cmd/svc/address-resolver/commands:e->github.com/skycoin/skywire/pkg/services/ar - - + + - + github.com/skycoin/skywire/cmd/svc/conf - - -github.com/skycoin/skywire/cmd/svc/conf -12 / 246B + + +github.com/skycoin/skywire/cmd/svc/conf +12 / 246B - + github.com/skycoin/skywire/cmd/svc/conf/commands - - -github.com/skycoin/skywire/cmd/svc/conf/commands -129 / 4.2KB + + +github.com/skycoin/skywire/cmd/svc/conf/commands +129 / 4.2KB - + github.com/skycoin/skywire/cmd/svc/conf:e->github.com/skycoin/skywire/cmd/svc/conf/commands - - + + - + github.com/skycoin/skywire/cmd/svc/conf:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/conf/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper - - -github.com/skycoin/skywire/cmd/svc/config-bootstrapper -12 / 278B + + +github.com/skycoin/skywire/cmd/svc/config-bootstrapper +12 / 278B - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands - - -github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands -200 / 7.0KB + + +github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands +206 / 7.5KB - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper:e->github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/config-bootstrapper/api - - -github.com/skycoin/skywire/pkg/config-bootstrapper/api -241 / 8.2KB + + +github.com/skycoin/skywire/pkg/config-bootstrapper/api +231 / 7.9KB - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/config-bootstrapper/api - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/metricsutil - - -github.com/skycoin/skywire/pkg/metricsutil -234 / 7.8KB + + +github.com/skycoin/skywire/pkg/metricsutil +234 / 7.8KB - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/svcmode - - -github.com/skycoin/skywire/pkg/svcmode -342 / 13.7KB + + +github.com/skycoin/skywire/pkg/svcmode +351 / 14.3KB - + github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands:e->github.com/skycoin/skywire/pkg/svcmode - - + + - + github.com/skycoin/skywire/cmd/svc/geoip - - -github.com/skycoin/skywire/cmd/svc/geoip -12 / 249B + + +github.com/skycoin/skywire/cmd/svc/geoip +12 / 249B - + github.com/skycoin/skywire/cmd/svc/geoip:e->github.com/skycoin/skywire/cmd/svc/geoip/commands - - + + - + github.com/skycoin/skywire/cmd/svc/geoip:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/geoip/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/geoip/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/pkg/geoip - - -github.com/skycoin/skywire/pkg/geoip -78 / 2.8KB + + +github.com/skycoin/skywire/pkg/geoip +78 / 2.8KB - + github.com/skycoin/skywire/cmd/svc/geoip/commands:e->github.com/skycoin/skywire/pkg/geoip - - + + - + github.com/skycoin/skywire/cmd/svc/geoip/commands:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor - - -github.com/skycoin/skywire/cmd/svc/network-monitor -12 / 279B + + +github.com/skycoin/skywire/cmd/svc/network-monitor +12 / 279B - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands - - -github.com/skycoin/skywire/cmd/svc/network-monitor/commands -348 / 12.9KB + + +github.com/skycoin/skywire/cmd/svc/network-monitor/commands +348 / 12.9KB - + github.com/skycoin/skywire/cmd/svc/network-monitor:e->github.com/skycoin/skywire/cmd/svc/network-monitor/commands - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/network-monitor/api - - -github.com/skycoin/skywire/pkg/network-monitor/api -586 / 17.6KB + + +github.com/skycoin/skywire/pkg/network-monitor/api +586 / 17.6KB - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/network-monitor/api - - + + - + github.com/skycoin/skywire/pkg/network-monitor/store - - -github.com/skycoin/skywire/pkg/network-monitor/store -53 / 1.3KB + + +github.com/skycoin/skywire/pkg/network-monitor/store +53 / 1.3KB - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/network-monitor/store - - + + - + github.com/skycoin/skywire/pkg/network-monitor/types - - -github.com/skycoin/skywire/pkg/network-monitor/types -28 / 1.0KB + + +github.com/skycoin/skywire/pkg/network-monitor/types +28 / 1.0KB - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/network-monitor/types - - + + - + github.com/skycoin/skywire/pkg/storeconfig - - -github.com/skycoin/skywire/pkg/storeconfig -33 / 0.9KB + + +github.com/skycoin/skywire/pkg/storeconfig +33 / 0.9KB - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/tcpproxy - - -github.com/skycoin/skywire/pkg/tcpproxy -29 / 0.7KB + + +github.com/skycoin/skywire/pkg/tcpproxy +29 / 0.7KB - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/tcpproxy - - + + - + github.com/skycoin/skywire/cmd/svc/network-monitor/commands:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder - - -github.com/skycoin/skywire/cmd/svc/route-finder -12 / 270B + + +github.com/skycoin/skywire/cmd/svc/route-finder +12 / 270B - + github.com/skycoin/skywire/cmd/svc/route-finder/commands - - -github.com/skycoin/skywire/cmd/svc/route-finder/commands -216 / 6.7KB + + +github.com/skycoin/skywire/cmd/svc/route-finder/commands +216 / 6.7KB - + github.com/skycoin/skywire/cmd/svc/route-finder:e->github.com/skycoin/skywire/cmd/svc/route-finder/commands - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/svc/route-finder/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/rf - - -github.com/skycoin/skywire/pkg/services/rf -213 / 6.3KB + + +github.com/skycoin/skywire/pkg/services/rf +218 / 6.7KB - + github.com/skycoin/skywire/cmd/svc/route-finder/commands:e->github.com/skycoin/skywire/pkg/services/rf - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery - - -github.com/skycoin/skywire/cmd/svc/service-discovery -12 / 289B + + +github.com/skycoin/skywire/cmd/svc/service-discovery +12 / 289B - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands - - -github.com/skycoin/skywire/cmd/svc/service-discovery/commands -249 / 8.3KB + + +github.com/skycoin/skywire/cmd/svc/service-discovery/commands +249 / 8.3KB - + github.com/skycoin/skywire/cmd/svc/service-discovery:e->github.com/skycoin/skywire/cmd/svc/service-discovery/commands - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/sd - - -github.com/skycoin/skywire/pkg/services/sd -265 / 8.1KB + + +github.com/skycoin/skywire/pkg/services/sd +266 / 8.2KB - + github.com/skycoin/skywire/cmd/svc/service-discovery/commands:e->github.com/skycoin/skywire/pkg/services/sd - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node - - -github.com/skycoin/skywire/cmd/svc/setup-node -12 / 264B + + +github.com/skycoin/skywire/cmd/svc/setup-node +12 / 264B - + github.com/skycoin/skywire/cmd/svc/setup-node/commands - - -github.com/skycoin/skywire/cmd/svc/setup-node/commands -192 / 5.9KB + + +github.com/skycoin/skywire/cmd/svc/setup-node/commands +197 / 6.2KB - + github.com/skycoin/skywire/cmd/svc/setup-node:e->github.com/skycoin/skywire/cmd/svc/setup-node/commands - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - - - - -github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/dmsgc - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/services/sn - - -github.com/skycoin/skywire/pkg/services/sn -309 / 10.4KB + + +github.com/skycoin/skywire/pkg/services/sn +310 / 10.4KB - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/services/sn - - + + - + github.com/skycoin/skywire/cmd/svc/setup-node/commands:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services - - -github.com/skycoin/skywire/cmd/svc/skywire-services -12 / 274B + + +github.com/skycoin/skywire/cmd/svc/skywire-services +12 / 274B - + github.com/skycoin/skywire/cmd/svc/skywire-services:e->github.com/skycoin/skywire/cmd/svc/skywire-services/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/address-resolver/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/conf/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/config-bootstrapper/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/geoip/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/network-monitor/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/route-finder/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/service-discovery/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/setup-node/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands/run - - -github.com/skycoin/skywire/cmd/svc/skywire-services/commands/run -94 / 3.3KB + + +github.com/skycoin/skywire/cmd/svc/skywire-services/commands/run +94 / 3.3KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/skywire-services/commands/run - - + + - + github.com/skycoin/skywire/cmd/svc/stun-server/commands - - -github.com/skycoin/skywire/cmd/svc/stun-server/commands -71 / 2.4KB + + +github.com/skycoin/skywire/cmd/svc/stun-server/commands +71 / 2.4KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/stun-server/commands - - + + - + github.com/skycoin/skywire/cmd/svc/sw-env/commands - - -github.com/skycoin/skywire/cmd/svc/sw-env/commands -80 / 2.4KB + + +github.com/skycoin/skywire/cmd/svc/sw-env/commands +80 / 2.4KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/sw-env/commands - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands - - -github.com/skycoin/skywire/cmd/svc/transport-discovery/commands -323 / 11.5KB + + +github.com/skycoin/skywire/cmd/svc/transport-discovery/commands +323 / 11.5KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/transport-discovery/commands - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands - - -github.com/skycoin/skywire/cmd/svc/transport-setup/commands -240 / 7.7KB + + +github.com/skycoin/skywire/cmd/svc/transport-setup/commands +240 / 7.7KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/transport-setup/commands - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands - - -github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands -280 / 10.3KB + + +github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands +283 / 10.5KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/ar - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/dmsgdisc - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/dmsgsrv - - + + - + github.com/skycoin/skywire/pkg/services/noop - - -github.com/skycoin/skywire/pkg/services/noop -74 / 2.1KB + + +github.com/skycoin/skywire/pkg/services/noop +74 / 2.1KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/noop - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/rf - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/sd - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/sn - - + + - + github.com/skycoin/skywire/pkg/services/stun - - -github.com/skycoin/skywire/pkg/services/stun -95 / 2.8KB + + +github.com/skycoin/skywire/pkg/services/stun +95 / 2.8KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/stun - - + + - + github.com/skycoin/skywire/pkg/services/tpd - - -github.com/skycoin/skywire/pkg/services/tpd -395 / 13.4KB + + +github.com/skycoin/skywire/pkg/services/tpd +396 / 13.5KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/tpd - - + + - + github.com/skycoin/skywire/pkg/services/tps - - -github.com/skycoin/skywire/pkg/services/tps -131 / 3.9KB + + +github.com/skycoin/skywire/pkg/services/tps +131 / 3.9KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/tps - - + + - + github.com/skycoin/skywire/pkg/services/visor - - -github.com/skycoin/skywire/pkg/services/visor -85 / 2.8KB + + +github.com/skycoin/skywire/pkg/services/visor +85 / 2.8KB - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands:e->github.com/skycoin/skywire/pkg/services/visor - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands/run:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands/run:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/skywire-services/commands/run:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/cmd/svc/stun-server/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/stun-server/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/stun-server/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/svc/stun-server/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/stun-server/commands:e->github.com/skycoin/skywire/pkg/services/stun - - + + - + github.com/skycoin/skywire/cmd/svc/sw-env - - -github.com/skycoin/skywire/cmd/svc/sw-env -12 / 252B + + +github.com/skycoin/skywire/cmd/svc/sw-env +12 / 252B - + github.com/skycoin/skywire/cmd/svc/sw-env:e->github.com/skycoin/skywire/cmd/svc/sw-env/commands - - + + - + github.com/skycoin/skywire/cmd/svc/sw-env:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/sw-env/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/sw-env/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/pkg/serviceconfig - - -github.com/skycoin/skywire/pkg/serviceconfig -498 / 18.4KB + + +github.com/skycoin/skywire/pkg/serviceconfig +498 / 18.4KB - + github.com/skycoin/skywire/cmd/svc/sw-env/commands:e->github.com/skycoin/skywire/pkg/serviceconfig - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery - - -github.com/skycoin/skywire/cmd/svc/transport-discovery -12 / 291B + + +github.com/skycoin/skywire/cmd/svc/transport-discovery +12 / 291B - + github.com/skycoin/skywire/cmd/svc/transport-discovery:e->github.com/skycoin/skywire/cmd/svc/transport-discovery/commands - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/services/tpd - - + + - + github.com/skycoin/skywire/cmd/svc/transport-discovery/commands:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup - - -github.com/skycoin/skywire/cmd/svc/transport-setup -12 / 279B + + +github.com/skycoin/skywire/cmd/svc/transport-setup +12 / 279B - + github.com/skycoin/skywire/cmd/svc/transport-setup:e->github.com/skycoin/skywire/cmd/svc/transport-setup/commands - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/dmsgc - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/services/tps - - + + - + github.com/skycoin/skywire/pkg/transport-setup/api - - -github.com/skycoin/skywire/pkg/transport-setup/api -386 / 13.0KB + + +github.com/skycoin/skywire/pkg/transport-setup/api +481 / 17.3KB - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/transport-setup/api - - + + - + github.com/skycoin/skywire/pkg/transport-setup/config - - -github.com/skycoin/skywire/pkg/transport-setup/config -34 / 1.0KB + + +github.com/skycoin/skywire/pkg/transport-setup/config +34 / 1.0KB - + github.com/skycoin/skywire/cmd/svc/transport-setup/commands:e->github.com/skycoin/skywire/pkg/transport-setup/config - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker - - -github.com/skycoin/skywire/cmd/svc/uptime-tracker -12 / 276B + + +github.com/skycoin/skywire/cmd/svc/uptime-tracker +12 / 276B - + github.com/skycoin/skywire/cmd/svc/uptime-tracker:e->github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/geo - - -github.com/skycoin/skywire/pkg/geo -80 / 2.2KB + + +github.com/skycoin/skywire/pkg/geo +80 / 2.2KB - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/geo - - + + - + github.com/skycoin/skywire/pkg/httpauth - - -github.com/skycoin/skywire/pkg/httpauth -478 / 14.6KB + + +github.com/skycoin/skywire/pkg/httpauth +478 / 14.6KB - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/httpauth - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/pg - - -github.com/skycoin/skywire/pkg/pg -29 / 0.8KB + + +github.com/skycoin/skywire/pkg/pg +29 / 0.8KB - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/pg - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/svcmode - - + + - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/tcpproxy - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api - - -github.com/skycoin/skywire/pkg/uptime-tracker/api -655 / 21.1KB + + +github.com/skycoin/skywire/pkg/uptime-tracker/api +655 / 21.1KB - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/uptime-tracker/api - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/metrics - - -github.com/skycoin/skywire/pkg/uptime-tracker/metrics -33 / 1.0KB + + +github.com/skycoin/skywire/pkg/uptime-tracker/metrics +33 / 1.0KB - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/uptime-tracker/metrics - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/store - - -github.com/skycoin/skywire/pkg/uptime-tracker/store -601 / 20.2KB + + +github.com/skycoin/skywire/pkg/uptime-tracker/store +601 / 20.2KB - + github.com/skycoin/skywire/cmd/svc/uptime-tracker/commands:e->github.com/skycoin/skywire/pkg/uptime-tracker/store - - + + - + github.com/skycoin/skywire/cmd/treeprobe - - -github.com/skycoin/skywire/cmd/treeprobe -58 / 1.7KB + + +github.com/skycoin/skywire/cmd/treeprobe +58 / 1.7KB - + github.com/skycoin/skywire/pkg/util/treeprobe - - -github.com/skycoin/skywire/pkg/util/treeprobe -624 / 20.3KB + + +github.com/skycoin/skywire/pkg/util/treeprobe +624 / 20.3KB - + github.com/skycoin/skywire/cmd/treeprobe:e->github.com/skycoin/skywire/pkg/util/treeprobe - - + + - + github.com/skycoin/skywire/cmd/util/edit - - -github.com/skycoin/skywire/cmd/util/edit -24 / 626B + + +github.com/skycoin/skywire/cmd/util/edit +24 / 626B - + github.com/skycoin/skywire/cmd/util/edit:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/edit - - + + - + github.com/skycoin/skywire/cmd/util/gojq - - -github.com/skycoin/skywire/cmd/util/gojq -24 / 616B + + +github.com/skycoin/skywire/cmd/util/gojq +24 / 616B - + github.com/skycoin/skywire/cmd/util/gojq:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/jq - - + + - + github.com/skycoin/skywire/cmd/util/got - - -github.com/skycoin/skywire/cmd/util/got -24 / 630B + + +github.com/skycoin/skywire/cmd/util/got +24 / 630B - + github.com/skycoin/skywire/cmd/util/got:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/got - - + + - + github.com/skycoin/skywire/cmd/version - - -github.com/skycoin/skywire/cmd/version -12 / 250B + + +github.com/skycoin/skywire/cmd/version +12 / 250B - + github.com/skycoin/skywire/cmd/version/commands - - -github.com/skycoin/skywire/cmd/version/commands -32 / 0.8KB + + +github.com/skycoin/skywire/cmd/version/commands +32 / 0.8KB - + github.com/skycoin/skywire/cmd/version:e->github.com/skycoin/skywire/cmd/version/commands - - + + - + github.com/skycoin/skywire/cmd/version:e->github.com/skycoin/skywire/pkg/flags - - + + - + github.com/skycoin/skywire/cmd/version/commands:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/deployment:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/deployment:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/deployment/cmd/gen - - -github.com/skycoin/skywire/deployment/cmd/gen -218 / 8.4KB + + +github.com/skycoin/skywire/deployment/cmd/gen +228 / 9.0KB - + github.com/skycoin/skywire/example/example-client-app - - -github.com/skycoin/skywire/example/example-client-app -131 / 3.7KB + + +github.com/skycoin/skywire/example/example-client-app +131 / 3.7KB - + github.com/skycoin/skywire/example/example-client-app:e->github.com/skycoin/skywire/pkg/app - - + + - + github.com/skycoin/skywire/example/example-client-app:e->github.com/skycoin/skywire/pkg/app/appcommon - - + + - + github.com/skycoin/skywire/example/example-client-app:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/example/example-client-app:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/example/example-client-app:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/example/example-client-app:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/example/example-client-app:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/example/example-server-app - - -github.com/skycoin/skywire/example/example-server-app -96 / 2.7KB + + +github.com/skycoin/skywire/example/example-server-app +96 / 2.7KB - + github.com/skycoin/skywire/example/example-server-app:e->github.com/skycoin/skywire/pkg/app - - + + - + github.com/skycoin/skywire/example/example-server-app:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/example/example-server-app:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/example/example-server-app:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/example/http-server - - -github.com/skycoin/skywire/example/http-server -75 / 1.9KB + + +github.com/skycoin/skywire/example/http-server +75 / 1.9KB - + github.com/skycoin/skywire/example/http-server/html - - -github.com/skycoin/skywire/example/http-server/html -29 / 626B + + +github.com/skycoin/skywire/example/http-server/html +29 / 626B - + github.com/skycoin/skywire/example/http-server:e->github.com/skycoin/skywire/example/http-server/html - - + + - + github.com/skycoin/skywire/example/http-server:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/example/http-server:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/examples/hello - - -github.com/skycoin/skywire/examples/hello -9 / 194B + + +github.com/skycoin/skywire/examples/hello +9 / 194B - + github.com/skycoin/skywire/internal/dmsg-e2e - - -github.com/skycoin/skywire/internal/dmsg-e2e -0 / 0B + + +github.com/skycoin/skywire/internal/dmsg-e2e +0 / 0B - + github.com/skycoin/skywire/internal/dmsg-e2e/testserver - - -github.com/skycoin/skywire/internal/dmsg-e2e/testserver -43 / 1.2KB + + +github.com/skycoin/skywire/internal/dmsg-e2e/testserver +43 / 1.2KB - + github.com/skycoin/skywire/internal/integration - - -github.com/skycoin/skywire/internal/integration -0 / 0B + + +github.com/skycoin/skywire/internal/integration +0 / 0B - + github.com/skycoin/skywire/pkg/address-resolver/metrics - - -github.com/skycoin/skywire/pkg/address-resolver/metrics -33 / 1.0KB + + +github.com/skycoin/skywire/pkg/address-resolver/metrics +33 / 1.0KB - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/address-resolver/metrics - - + + - + github.com/skycoin/skywire/pkg/address-resolver/store - - -github.com/skycoin/skywire/pkg/address-resolver/store -406 / 13.8KB + + +github.com/skycoin/skywire/pkg/address-resolver/store +414 / 14.2KB - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/address-resolver/store - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/httpauth - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/networkmonitor - - -github.com/skycoin/skywire/pkg/networkmonitor -17 / 569B + + +github.com/skycoin/skywire/pkg/networkmonitor +17 / 569B - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/networkmonitor - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/transport/network - - + + - + github.com/skycoin/skywire/pkg/transport/network/addrresolver - - -github.com/skycoin/skywire/pkg/transport/network/addrresolver -1138 / 39.5KB + + +github.com/skycoin/skywire/pkg/transport/network/addrresolver +1388 / 49.5KB - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/transport/network/addrresolver - - + + - + github.com/skycoin/skywire/pkg/transport/network/handshake - - -github.com/skycoin/skywire/pkg/transport/network/handshake -219 / 6.0KB + + +github.com/skycoin/skywire/pkg/transport/network/handshake +222 / 6.4KB - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/transport/network/handshake - - + + - + github.com/skycoin/skywire/pkg/address-resolver/api:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/address-resolver/metrics:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/address-resolver/store:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/address-resolver/store:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/address-resolver/store:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/address-resolver/store:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/address-resolver/store:e->github.com/skycoin/skywire/pkg/transport/network/addrresolver - - + + - + github.com/skycoin/skywire/pkg/address-resolver/store:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/app:e->github.com/skycoin/skywire/pkg/app/appcommon - - + + - + github.com/skycoin/skywire/pkg/app:e->github.com/skycoin/skywire/pkg/app/appevent - - + + - + github.com/skycoin/skywire/pkg/app:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/app:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/pkg/app/idmanager - - -github.com/skycoin/skywire/pkg/app/idmanager -224 / 5.4KB + + +github.com/skycoin/skywire/pkg/app/idmanager +224 / 5.4KB - + github.com/skycoin/skywire/pkg/app:e->github.com/skycoin/skywire/pkg/app/idmanager - - + + - + github.com/skycoin/skywire/pkg/app:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/app:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/app/appcommon:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/app/appcommon:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/app/appcommon:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/app/appcommon:e->github.com/skycoin/skywire/pkg/util/bbolthealth - - + + - + github.com/skycoin/skywire/pkg/app/appdisc - - -github.com/skycoin/skywire/pkg/app/appdisc -408 / 13.8KB + + +github.com/skycoin/skywire/pkg/app/appdisc +446 / 15.5KB - + github.com/skycoin/skywire/pkg/app/appdisc:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/app/appdisc:e->github.com/skycoin/skywire/pkg/app/appcommon - - + + - + github.com/skycoin/skywire/pkg/app/appdisc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/app/appdisc:e->github.com/skycoin/skywire/pkg/geo - - + + - + github.com/skycoin/skywire/pkg/app/appdisc:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/app/appdisc:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/pkg/app/appdisc:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/app/appevent:e->github.com/skycoin/skywire/pkg/app/appcommon - - + + + + + +github.com/skycoin/skywire/pkg/gobrpc + + +github.com/skycoin/skywire/pkg/gobrpc +34 / 1.4KB + + + + + +github.com/skycoin/skywire/pkg/app/appevent:e->github.com/skycoin/skywire/pkg/gobrpc + + - + github.com/skycoin/skywire/pkg/app/appevent:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/app/appnet:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/app/appnet:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/app/appnet:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/app/appnet:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/app/appnet:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/app/appnet:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/app/appnet:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/app/appnet:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/app/appcommon - - + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/app/appdisc - - + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/app/appevent - - + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/app/appserver/spec - - -github.com/skycoin/skywire/pkg/app/appserver/spec -75 / 3.8KB + + +github.com/skycoin/skywire/pkg/app/appserver/spec +75 / 3.8KB - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/app/appserver/spec - - + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/app/idmanager - - + + + + + +github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/gobrpc + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/util/rpcutil - - -github.com/skycoin/skywire/pkg/util/rpcutil -33 / 0.8KB + + +github.com/skycoin/skywire/pkg/util/rpcutil +33 / 0.8KB - + github.com/skycoin/skywire/pkg/app/appserver:e->github.com/skycoin/skywire/pkg/util/rpcutil - - + + - + github.com/skycoin/skywire/pkg/app/appserver/spec:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/app/launcher:e->github.com/skycoin/skywire/pkg/app/appcommon - - + + - + github.com/skycoin/skywire/pkg/app/launcher:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/app/launcher:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/pkg/app/launcher:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/app/launcher:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/app/launcher:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/util/pathutil - - -github.com/skycoin/skywire/pkg/util/pathutil -57 / 1.6KB + + +github.com/skycoin/skywire/pkg/util/pathutil +57 / 1.6KB - + github.com/skycoin/skywire/pkg/app/launcher:e->github.com/skycoin/skywire/pkg/util/pathutil - - + + - + github.com/skycoin/skywire/pkg/calvin/cmd/calvin - - -github.com/skycoin/skywire/pkg/calvin/cmd/calvin -37 / 1.5KB + + +github.com/skycoin/skywire/pkg/calvin/cmd/calvin +37 / 1.5KB - + github.com/skycoin/skywire/pkg/calvin/cmd/calvin/commands - - -github.com/skycoin/skywire/pkg/calvin/cmd/calvin/commands -40 / 1.1KB + + +github.com/skycoin/skywire/pkg/calvin/cmd/calvin/commands +40 / 1.1KB - + github.com/skycoin/skywire/pkg/calvin/cmd/calvin:e->github.com/skycoin/skywire/pkg/calvin/cmd/calvin/commands - - + + - + github.com/skycoin/skywire/pkg/calvin/cmd/calvin/commands:e->github.com/skycoin/skywire/pkg/calvin - - + + - + github.com/skycoin/skywire/pkg/clicache:e->github.com/skycoin/skywire/pkg/util/bbolthealth - - + + - + github.com/skycoin/skywire/pkg/cmdutil:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/cmdutil:e->github.com/skycoin/skywire/pkg/dmsg/direct - - + + - + github.com/skycoin/skywire/pkg/cmdutil:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/cmdutil:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/cmdutil:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient - - + + - + github.com/skycoin/skywire/pkg/cmdutil:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/cmdutil:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/config-bootstrapper/api:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/config-bootstrapper/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/config-bootstrapper/api:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/config-bootstrapper/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/config-bootstrapper/api:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/cxo/cxoutils - - -github.com/skycoin/skywire/pkg/cxo/cxoutils -102 / 4.0KB + + +github.com/skycoin/skywire/pkg/cxo/cxoutils +102 / 4.0KB - + github.com/skycoin/skywire/pkg/cxo/data - - -github.com/skycoin/skywire/pkg/cxo/data -279 / 9.5KB + + +github.com/skycoin/skywire/pkg/cxo/data +279 / 9.5KB - + github.com/skycoin/skywire/pkg/cxo/cxoutils:e->github.com/skycoin/skywire/pkg/cxo/data - - + + - + github.com/skycoin/skywire/pkg/cxo/cxoutils:e->github.com/skycoin/skywire/pkg/cxo/skyobject - - + + - + github.com/skycoin/skywire/pkg/cxo/data/cxds - - -github.com/skycoin/skywire/pkg/cxo/data/cxds -941 / 25.9KB + + +github.com/skycoin/skywire/pkg/cxo/data/cxds +948 / 26.3KB - + github.com/skycoin/skywire/pkg/cxo/data/cxds:e->github.com/skycoin/skywire/pkg/cxo/data - - + + - + github.com/skycoin/skywire/pkg/cxo/data/cxds:e->github.com/skycoin/skywire/pkg/util/bbolthealth - - + + - + github.com/skycoin/skywire/pkg/cxo/data/idxdb - - -github.com/skycoin/skywire/pkg/cxo/data/idxdb -668 / 19.1KB + + +github.com/skycoin/skywire/pkg/cxo/data/idxdb +672 / 19.3KB - + github.com/skycoin/skywire/pkg/cxo/data/idxdb:e->github.com/skycoin/skywire/pkg/cxo/data - - + + - + github.com/skycoin/skywire/pkg/cxo/data/idxdb:e->github.com/skycoin/skywire/pkg/util/bbolthealth - - + + - + github.com/skycoin/skywire/pkg/cxo/data/tests - - -github.com/skycoin/skywire/pkg/cxo/data/tests -1097 / 24.5KB + + +github.com/skycoin/skywire/pkg/cxo/data/tests +1097 / 24.5KB - + github.com/skycoin/skywire/pkg/cxo/data/tests:e->github.com/skycoin/skywire/pkg/cxo/data - - + + - + github.com/skycoin/skywire/pkg/cxo/node:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/cxo/node:e->github.com/skycoin/skywire/pkg/cxo/data - - + + - + github.com/skycoin/skywire/pkg/cxo/node/log - - -github.com/skycoin/skywire/pkg/cxo/node/log -181 / 5.0KB + + +github.com/skycoin/skywire/pkg/cxo/node/log +181 / 5.0KB - + github.com/skycoin/skywire/pkg/cxo/node:e->github.com/skycoin/skywire/pkg/cxo/node/log - - + + - + github.com/skycoin/skywire/pkg/cxo/node/msg - - -github.com/skycoin/skywire/pkg/cxo/node/msg -374 / 8.9KB + + +github.com/skycoin/skywire/pkg/cxo/node/msg +374 / 8.9KB - + github.com/skycoin/skywire/pkg/cxo/node:e->github.com/skycoin/skywire/pkg/cxo/node/msg - - + + - + github.com/skycoin/skywire/pkg/cxo/node/transport - - -github.com/skycoin/skywire/pkg/cxo/node/transport -534 / 15.7KB + + +github.com/skycoin/skywire/pkg/cxo/node/transport +534 / 15.7KB - + github.com/skycoin/skywire/pkg/cxo/node:e->github.com/skycoin/skywire/pkg/cxo/node/transport - - + + - + github.com/skycoin/skywire/pkg/cxo/node:e->github.com/skycoin/skywire/pkg/cxo/skyobject - - + + - + github.com/skycoin/skywire/pkg/cxo/node:e->github.com/skycoin/skywire/pkg/cxo/skyobject/registry - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject/statutil - - -github.com/skycoin/skywire/pkg/cxo/skyobject/statutil -150 / 3.5KB + + +github.com/skycoin/skywire/pkg/cxo/skyobject/statutil +150 / 3.5KB - + github.com/skycoin/skywire/pkg/cxo/node:e->github.com/skycoin/skywire/pkg/cxo/skyobject/statutil - - + + - + github.com/skycoin/skywire/pkg/cxo/node/transport:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/cxo/node/transport:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/noise - - -github.com/skycoin/skywire/pkg/dmsg/noise -942 / 27.4KB + + +github.com/skycoin/skywire/pkg/dmsg/noise +1230 / 40.6KB - + github.com/skycoin/skywire/pkg/cxo/node/transport:e->github.com/skycoin/skywire/pkg/dmsg/noise - - + + - + github.com/skycoin/skywire/pkg/cxo/node/transport:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject:e->github.com/skycoin/skywire/pkg/cxo/data - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject:e->github.com/skycoin/skywire/pkg/cxo/data/cxds - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject:e->github.com/skycoin/skywire/pkg/cxo/data/idxdb - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject:e->github.com/skycoin/skywire/pkg/cxo/node/log - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject:e->github.com/skycoin/skywire/pkg/cxo/skyobject/registry - - + + - + github.com/skycoin/skywire/pkg/cxo/skyobject:e->github.com/skycoin/skywire/pkg/cxo/skyobject/statutil - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore:e->github.com/skycoin/skywire/pkg/cxo/cxoutils - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore:e->github.com/skycoin/skywire/pkg/cxo/node - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore:e->github.com/skycoin/skywire/pkg/cxo/node/transport - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore:e->github.com/skycoin/skywire/pkg/cxo/skyobject - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore:e->github.com/skycoin/skywire/pkg/cxo/skyobject/registry - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/cxo/treestore:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/cmdutil:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/cmdutil:e->github.com/skycoin/skywire/pkg/dmsg/noise - - + + - + github.com/skycoin/skywire/pkg/dmsg/cmdutil:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/direct:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/direct:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/direct:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/direct:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/disc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/disc:e->github.com/skycoin/skywire/pkg/logging - - - - - -github.com/skycoin/skywire/pkg/dmsg/disc/dmsgfirst - - -github.com/skycoin/skywire/pkg/dmsg/disc/dmsgfirst -289 / 11.3KB - - - - - -github.com/skycoin/skywire/pkg/dmsg/disc/dmsgfirst:e->github.com/skycoin/skywire/pkg/cipher - - - - - -github.com/skycoin/skywire/pkg/dmsg/disc/dmsgfirst:e->github.com/skycoin/skywire/pkg/dmsg/disc - - - - - -github.com/skycoin/skywire/pkg/dmsg/disc/dmsgfirst:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - - - - -github.com/skycoin/skywire/pkg/dmsg/disc/dmsgfirst:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - - - - -github.com/skycoin/skywire/pkg/dmsg/disc/dmsgfirst:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/disc/metrics - - -github.com/skycoin/skywire/pkg/dmsg/disc/metrics -44 / 1.5KB + + +github.com/skycoin/skywire/pkg/dmsg/disc/metrics +44 / 1.5KB - + github.com/skycoin/skywire/pkg/dmsg/disc/metrics:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api - - -github.com/skycoin/skywire/pkg/dmsg/discovery/api -1232 / 44.1KB + + +github.com/skycoin/skywire/pkg/dmsg/discovery/api +1388 / 50.3KB - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/cxo/treestore - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/dmsg/disc/metrics - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/store - - -github.com/skycoin/skywire/pkg/dmsg/discovery/store -831 / 26.6KB + + +github.com/skycoin/skywire/pkg/dmsg/discovery/store +859 / 27.9KB - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/dmsg/discovery/store - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/networkmonitor - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/api:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/store:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/store:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/store:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/store:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/discovery/store:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg/metrics - - -github.com/skycoin/skywire/pkg/dmsg/dmsg/metrics -111 / 3.9KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsg/metrics +118 / 4.3KB - + github.com/skycoin/skywire/pkg/dmsg/dmsg:e->github.com/skycoin/skywire/pkg/dmsg/dmsg/metrics - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg:e->github.com/skycoin/skywire/pkg/dmsg/noise - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg:e->github.com/skycoin/skywire/pkg/netutil - - + + + + + +github.com/skycoin/skywire/pkg/skyquic + + +github.com/skycoin/skywire/pkg/skyquic +213 / 9.1KB + + + + + +github.com/skycoin/skywire/pkg/dmsg/dmsg:e->github.com/skycoin/skywire/pkg/skyquic + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg/metrics:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsg/metrics:e->github.com/skycoin/skywire/third_party/VictoriaMetrics/metrics - - + + + + + +github.com/skycoin/skywire/pkg/dmsg/dmsgclient:e->github.com/skycoin/skywire/deployment + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgclient:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgclient:e->github.com/skycoin/skywire/pkg/dmsg/direct - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgclient:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgclient:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgclient:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - - - - -github.com/skycoin/skywire/pkg/dmsg/ioutil - - -github.com/skycoin/skywire/pkg/dmsg/ioutil -38 / 1.1KB - - - - - -github.com/skycoin/skywire/pkg/dmsg/dmsgclient:e->github.com/skycoin/skywire/pkg/dmsg/ioutil - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgclient:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgctrl - - -github.com/skycoin/skywire/pkg/dmsg/dmsgctrl -178 / 4.0KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsgctrl +178 / 4.0KB - + github.com/skycoin/skywire/pkg/dmsg/dmsgctrl:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgctrl:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgcurl - - -github.com/skycoin/skywire/pkg/dmsg/dmsgcurl -351 / 10.1KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsgcurl +351 / 10.1KB - + github.com/skycoin/skywire/pkg/dmsg/dmsgcurl:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgcurl:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgcurl:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgcurl:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgcurl:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgcurl:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgcurl:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsghttp:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsghttp:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsghttp:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsghttp:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgscp:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgscp:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgscp:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgscp:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgscp:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver:e->github.com/skycoin/skywire/pkg/dmsg/dmsg/metrics - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgserver:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgtest - - -github.com/skycoin/skywire/pkg/dmsg/dmsgtest -216 / 6.3KB + + +github.com/skycoin/skywire/pkg/dmsg/dmsgtest +230 / 6.8KB - + github.com/skycoin/skywire/pkg/dmsg/dmsgtest:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgtest:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsg/dmsgtest:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + + + + +github.com/skycoin/skywire/pkg/dmsg/ioutil + + +github.com/skycoin/skywire/pkg/dmsg/ioutil +38 / 1.1KB + + - + github.com/skycoin/skywire/pkg/dmsg/ioutil:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsg/noise:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsg/noise:e->github.com/skycoin/skywire/pkg/dmsg/ioutil - - + + - + github.com/skycoin/skywire/pkg/dmsg/noise:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsgc:e->github.com/skycoin/skywire/pkg/app/appevent - - + + - + github.com/skycoin/skywire/pkg/dmsgc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsgc:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsgc:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + + + + +github.com/skycoin/skywire/pkg/dmsgc:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient + + - + github.com/skycoin/skywire/pkg/dmsgc/spec - - -github.com/skycoin/skywire/pkg/dmsgc/spec -240 / 9.5KB + + +github.com/skycoin/skywire/pkg/dmsgc/spec +248 / 10.1KB - + github.com/skycoin/skywire/pkg/dmsgc:e->github.com/skycoin/skywire/pkg/dmsgc/spec - - + + - + github.com/skycoin/skywire/pkg/dmsgc:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/dmsgc/spec:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsgc/spec:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/dmsgweb:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/dmsgweb:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/dmsgweb:e->github.com/skycoin/skywire/pkg/dmsg/ioutil - - + + - + github.com/skycoin/skywire/pkg/dmsgweb:e->github.com/skycoin/skywire/pkg/logging - - + + + + + +github.com/skycoin/skywire/pkg/skyenv/svcendpoints + + +github.com/skycoin/skywire/pkg/skyenv/svcendpoints +159 / 8.7KB + + + + + +github.com/skycoin/skywire/pkg/dmsgweb:e->github.com/skycoin/skywire/pkg/skyenv/svcendpoints + + - + github.com/skycoin/skywire/pkg/dmsgweb:e->github.com/skycoin/skywire/pkg/skynetca - - + + - + github.com/skycoin/skywire/pkg/skynetweb - - -github.com/skycoin/skywire/pkg/skynetweb -754 / 27.7KB + + +github.com/skycoin/skywire/pkg/skynetweb +860 / 32.9KB - + github.com/skycoin/skywire/pkg/dmsgweb:e->github.com/skycoin/skywire/pkg/skynetweb - - + + - + github.com/skycoin/skywire/pkg/geo:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/geo:e->github.com/skycoin/skywire/pkg/netutil - - + + + + + +github.com/skycoin/skywire/pkg/gobrpc/gobimpl + + +github.com/skycoin/skywire/pkg/gobrpc/gobimpl +434 / 13.6KB + + - + github.com/skycoin/skywire/pkg/httpauth:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/httpauth:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/httpauth:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/httpauth:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/httpauthclient - - -github.com/skycoin/skywire/pkg/httpauthclient -261 / 7.9KB + + +github.com/skycoin/skywire/pkg/httpauthclient +262 / 7.9KB - + github.com/skycoin/skywire/pkg/httpauthclient:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/httpauthclient:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/httputil:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/httputil:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/metricsutil:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/metricsutil:e->github.com/skycoin/skywire/third_party/VictoriaMetrics/metrics - - + + - + github.com/skycoin/skywire/pkg/network-monitor/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/network-monitor/api:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/network-monitor/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/network-monitor/api:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/network-monitor/api:e->github.com/skycoin/skywire/pkg/network-monitor/store - - + + - + github.com/skycoin/skywire/pkg/network-monitor/api:e->github.com/skycoin/skywire/pkg/network-monitor/types - - + + - + github.com/skycoin/skywire/pkg/network-monitor/api:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/network-monitor/store:e->github.com/skycoin/skywire/pkg/network-monitor/types - - + + - + github.com/skycoin/skywire/pkg/network-monitor/store:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/pty:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/pty:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/pty:e->github.com/skycoin/skywire/pkg/dmsg/noise - - + + - + github.com/skycoin/skywire/pkg/pty:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/pty:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/rewards - - -github.com/skycoin/skywire/pkg/rewards -104 / 3.0KB + + +github.com/skycoin/skywire/pkg/rewards +104 / 3.0KB - + github.com/skycoin/skywire/pkg/rewards:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/rewards:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/rfclient:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/rfclient:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/route-finder/api - - -github.com/skycoin/skywire/pkg/route-finder/api -192 / 6.4KB + + +github.com/skycoin/skywire/pkg/route-finder/api +192 / 6.4KB - + github.com/skycoin/skywire/pkg/route-finder/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/route-finder/api:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/route-finder/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/route-finder/api:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/route-finder/api:e->github.com/skycoin/skywire/pkg/rfclient - - + + - + github.com/skycoin/skywire/pkg/route-finder/api:e->github.com/skycoin/skywire/pkg/route-finder/store - - + + - + github.com/skycoin/skywire/pkg/route-finder/api:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/route-finder/api:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/pkg/route-finder/store:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/route-finder/store:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/route-finder/store:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/route-finder/store:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/pkg/route-finder/store:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/dmsg/direct - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + + + + +github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/dmsg/ioutil - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/dmsg/noise - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/dmsgc - - + + + + + +github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/gobrpc + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/rfclient - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/router/setupmetrics - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/transport/network - - + + - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/util/deadline - - -github.com/skycoin/skywire/pkg/util/deadline -72 / 1.8KB + + +github.com/skycoin/skywire/pkg/util/deadline +72 / 1.8KB - + github.com/skycoin/skywire/pkg/router:e->github.com/skycoin/skywire/pkg/util/deadline - - + + - + github.com/skycoin/skywire/pkg/router/policy:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/router/policy/presets - - -github.com/skycoin/skywire/pkg/router/policy/presets -54 / 1.6KB + + +github.com/skycoin/skywire/pkg/router/policy/presets +54 / 1.6KB - + github.com/skycoin/skywire/pkg/router/policy:e->github.com/skycoin/skywire/pkg/router/policy/presets - - + + - + github.com/skycoin/skywire/pkg/router/policy/wasm:e->github.com/skycoin/skywire/pkg/router/policy - - + + - + github.com/skycoin/skywire/pkg/router/setupmetrics:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/router/setupmetrics:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/router/setupmetrics:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/router/setupmetrics:e->github.com/skycoin/skywire/third_party/VictoriaMetrics/metrics - - + + - + github.com/skycoin/skywire/pkg/routing:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/routing:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api - - -github.com/skycoin/skywire/pkg/service-discovery/api -972 / 34.5KB + + +github.com/skycoin/skywire/pkg/service-discovery/api +972 / 34.5KB - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/cxo/treestore - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/geo - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/httpauth - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/networkmonitor - - + + - + github.com/skycoin/skywire/pkg/service-discovery/metrics - - -github.com/skycoin/skywire/pkg/service-discovery/metrics -69 / 3.0KB + + +github.com/skycoin/skywire/pkg/service-discovery/metrics +69 / 3.0KB - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/service-discovery/metrics - - + + - + github.com/skycoin/skywire/pkg/service-discovery/store - - -github.com/skycoin/skywire/pkg/service-discovery/store -765 / 26.9KB + + +github.com/skycoin/skywire/pkg/service-discovery/store +837 / 29.8KB - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/service-discovery/store - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/pkg/service-discovery/api:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/service-discovery/metrics:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/service-discovery/store:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/service-discovery/store:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/service-discovery/store:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/pkg/serviceconfig:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/pkg/serviceconfig:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/serviceconfig:e->github.com/skycoin/skywire/pkg/dmsg/dmsgserver - - + + - + github.com/skycoin/skywire/pkg/serviceconfig:e->github.com/skycoin/skywire/pkg/dmsgc - - + + - + github.com/skycoin/skywire/pkg/serviceconfig:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/serviceconfig:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/pkg/servicedisc:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/servicedisc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/servicedisc:e->github.com/skycoin/skywire/pkg/geo - - + + - + github.com/skycoin/skywire/pkg/servicedisc:e->github.com/skycoin/skywire/pkg/httpauthclient - - + + - + github.com/skycoin/skywire/pkg/servicedisc:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/servicedisc:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/services:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/address-resolver/api - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/address-resolver/metrics - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/address-resolver/store - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/httpauth - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/services/ar:e->github.com/skycoin/skywire/pkg/svcmode - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/dmsg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/dmsg/direct - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/dmsg/disc/metrics - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/dmsg/discovery/api - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/dmsg/discovery/store - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/dmsgdisc:e->github.com/skycoin/skywire/pkg/svcmode - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/dmsg/direct - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/dmsg/dmsg/metrics - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/dmsg/dmsgserver - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/geoip - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/router/setupmetrics - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/skyenv - - + + + + + +github.com/skycoin/skywire/pkg/services/dmsgsrv:e->github.com/skycoin/skywire/pkg/skyquic + + - + github.com/skycoin/skywire/pkg/services/noop:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/noop:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/route-finder/api - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/svcmode - - + + - + github.com/skycoin/skywire/pkg/services/rf:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/httpauth - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/service-discovery/api - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/service-discovery/metrics - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/service-discovery/store - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/services/sd:e->github.com/skycoin/skywire/pkg/svcmode - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/app/appevent - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/dmsg/dmsgcurl - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/router/setupmetrics - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/transport/network - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/transport/network/addrresolver - - + + - + github.com/skycoin/skywire/pkg/transport/tpdclient - - -github.com/skycoin/skywire/pkg/transport/tpdclient -358 / 12.3KB + + +github.com/skycoin/skywire/pkg/transport/tpdclient +652 / 22.0KB - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/transport/tpdclient - - + + - + github.com/skycoin/skywire/pkg/services/sn:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/services/stun:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/stun:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/stunserver - - -github.com/skycoin/skywire/pkg/stunserver -290 / 9.4KB + + +github.com/skycoin/skywire/pkg/stunserver +290 / 9.4KB - + github.com/skycoin/skywire/pkg/services/stun:e->github.com/skycoin/skywire/pkg/stunserver - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/httpauth - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/serviceuptime - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/svcmode - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api - - -github.com/skycoin/skywire/pkg/transport-discovery/api -2703 / 90.7KB + + +github.com/skycoin/skywire/pkg/transport-discovery/api +2703 / 90.7KB - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/transport-discovery/api - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator - - -github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator -522 / 21.3KB + + +github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator +522 / 21.3KB - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/metrics - - -github.com/skycoin/skywire/pkg/transport-discovery/metrics -61 / 2.0KB + + +github.com/skycoin/skywire/pkg/transport-discovery/metrics +61 / 2.0KB - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/transport-discovery/metrics - - + + - + github.com/skycoin/skywire/pkg/services/tpd:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/pkg/services/tps:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/tps:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/tps:e->github.com/skycoin/skywire/pkg/transport-setup/api - - + + - + github.com/skycoin/skywire/pkg/services/tps:e->github.com/skycoin/skywire/pkg/transport-setup/config - - + + - + github.com/skycoin/skywire/pkg/services/visor:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/services/visor:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/services/visor:e->github.com/skycoin/skywire/pkg/services - - + + - + github.com/skycoin/skywire/pkg/services/visor:e->github.com/skycoin/skywire/pkg/visor - - + + - + github.com/skycoin/skywire/pkg/services/visor:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/pkg/serviceuptime:e->github.com/skycoin/skywire/pkg/util/bbolthealth - - + + - + github.com/skycoin/skywire/pkg/skymailbridge:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/skynet:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/skynet:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/skynetweb:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/skynetweb:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/skynetweb:e->github.com/skycoin/skywire/pkg/skynet - - + + - + github.com/skycoin/skywire/pkg/skynetweb:e->github.com/skycoin/skywire/pkg/skynetca - - + + + + + +github.com/skycoin/skywire/pkg/skyquic:e->github.com/skycoin/skywire/pkg/cipher + + - + github.com/skycoin/skywire/pkg/skysocks:e->github.com/skycoin/skywire/pkg/app - - + + - + github.com/skycoin/skywire/pkg/skysocks:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/skysocks:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/pkg/skysocks:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/skysocks:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/skyudpbridge:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/skywire/tcpnoise:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/skywire/tcpnoise:e->github.com/skycoin/skywire/pkg/dmsg/noise - - + + - + github.com/skycoin/skywire/pkg/skywireconfig/autoconfigcmd:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/skywireconfig/genvisor - - -github.com/skycoin/skywire/pkg/skywireconfig/genvisor -1278 / 38.4KB + + +github.com/skycoin/skywire/pkg/skywireconfig/genvisor +1278 / 38.4KB - + github.com/skycoin/skywire/pkg/skywireconfig/genvisor:e->github.com/skycoin/skywire/pkg/app/appserver/spec - - + + - + github.com/skycoin/skywire/pkg/skywireconfig/genvisor:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/skywireconfig/genvisor:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/skywireconfig/genvisor:e->github.com/skycoin/skywire/pkg/dmsgc/spec - - + + - + github.com/skycoin/skywire/pkg/transport/network/spec - - -github.com/skycoin/skywire/pkg/transport/network/spec -22 / 1.0KB + + +github.com/skycoin/skywire/pkg/transport/network/spec +22 / 1.0KB - + github.com/skycoin/skywire/pkg/skywireconfig/genvisor:e->github.com/skycoin/skywire/pkg/transport/network/spec - - + + - + github.com/skycoin/skywire/pkg/transport/spec - - -github.com/skycoin/skywire/pkg/transport/spec -24 / 1.1KB + + +github.com/skycoin/skywire/pkg/transport/spec +24 / 1.1KB - + github.com/skycoin/skywire/pkg/skywireconfig/genvisor:e->github.com/skycoin/skywire/pkg/transport/spec - - + + - + github.com/skycoin/skywire/pkg/skywireconfig/genvisor:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/pkg/skywireconfig/keypair - - -github.com/skycoin/skywire/pkg/skywireconfig/keypair -43 / 1.7KB + + +github.com/skycoin/skywire/pkg/skywireconfig/keypair +43 / 1.7KB - + github.com/skycoin/skywire/pkg/skywireconfig/keypair:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/svcmode:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/svcmode:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/svcmode:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/svcmode:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/svcmode:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/svcmode:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/svcmode:e->github.com/skycoin/skywire/pkg/tcpproxy - - + + - + github.com/skycoin/skywire/pkg/testhelpers - - -github.com/skycoin/skywire/pkg/testhelpers -9 / 290B + + +github.com/skycoin/skywire/pkg/testhelpers +9 / 290B - + github.com/skycoin/skywire/pkg/tpviz:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/tpviz:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/tpviz:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/tpviz:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/tpviz:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/pkg/tpviz:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/tpviz:e->github.com/skycoin/skywire/pkg/transport/types - - - - - -github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/app/appevent - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/transport/network - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/transport/network/addrresolver - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/transport/spec - - + + - + github.com/skycoin/skywire/pkg/transport:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/cxo/treestore - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/httpauth - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/networkmonitor - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/serviceuptime - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/transport-discovery/metrics - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/api:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/cxo/node - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/cxo/node/transport - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/cxo/skyobject - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/cxo/skyobject/registry - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/cxo/treestore - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/cxoaggregator:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/metrics:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/metrics:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/store:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/store:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/store:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/store:e->github.com/skycoin/skywire/pkg/storeconfig - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/store:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/transport-discovery/store:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/cipher - - + + + + + +github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/dmsg/direct + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + + + + +github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient + + + + + +github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/transport-setup/config - - + + - + github.com/skycoin/skywire/pkg/transport/setup - - -github.com/skycoin/skywire/pkg/transport/setup -171 / 5.5KB + + +github.com/skycoin/skywire/pkg/transport/setup +171 / 5.5KB - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/transport/setup - - + + - + github.com/skycoin/skywire/pkg/transport-setup/api:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport-setup/config:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport-setup/config:e->github.com/skycoin/skywire/pkg/dmsgc - - + + - + github.com/skycoin/skywire/pkg/transport-setup/config:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport/deprecated - - -github.com/skycoin/skywire/pkg/transport/deprecated -14 / 555B + + +github.com/skycoin/skywire/pkg/transport/deprecated +14 / 555B - - -github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/app/appevent - - - - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/dmsg/noise - - + + - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/logging - - + + + + + +github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/skyenv + + + + + +github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/skyquic + + - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/transport/network/addrresolver - - + + - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/transport/network/handshake - - + + - + github.com/skycoin/skywire/pkg/transport/network/packetfilter - - -github.com/skycoin/skywire/pkg/transport/network/packetfilter -69 / 2.1KB + + +github.com/skycoin/skywire/pkg/transport/network/packetfilter +69 / 2.1KB - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/transport/network/packetfilter - - + + - + github.com/skycoin/skywire/pkg/transport/network/porter - - -github.com/skycoin/skywire/pkg/transport/network/porter -69 / 1.6KB + + +github.com/skycoin/skywire/pkg/transport/network/porter +69 / 1.6KB - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/transport/network/porter - - + + - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/transport/network/spec - - + + - + github.com/skycoin/skywire/pkg/transport/network/stcp - - -github.com/skycoin/skywire/pkg/transport/network/stcp -86 / 2.4KB + + +github.com/skycoin/skywire/pkg/transport/network/stcp +92 / 2.6KB - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/transport/network/stcp - - + + - + github.com/skycoin/skywire/pkg/transport/network:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport/network/addrresolver:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport/network/addrresolver:e->github.com/skycoin/skywire/pkg/httpauthclient - - + + - + github.com/skycoin/skywire/pkg/transport/network/addrresolver:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport/network/addrresolver:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/transport/network/addrresolver:e->github.com/skycoin/skywire/pkg/transport/network/packetfilter - - + + - + github.com/skycoin/skywire/pkg/transport/network/addrresolver:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport/network/handshake:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport/network/handshake:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/transport/network/packetfilter:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport/network/spec:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport/network/stcp:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport/setup:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport/setup:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/transport/setup:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport/setup:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/transport/setup:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/transport/setup:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport/spec:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/transport/spec:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/transport/tpdclient:e->github.com/skycoin/skywire/pkg/cipher - - + + + + + +github.com/skycoin/skywire/pkg/transport/tpdclient:e->github.com/skycoin/skywire/pkg/dmsg/dmsg + + + + + +github.com/skycoin/skywire/pkg/transport/tpdclient:e->github.com/skycoin/skywire/pkg/dmsg/dmsgclient + + - + github.com/skycoin/skywire/pkg/transport/tpdclient:e->github.com/skycoin/skywire/pkg/httpauthclient - - + + - + github.com/skycoin/skywire/pkg/transport/tpdclient:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/transport/tpdclient:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/transport/tpdclient:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/geo - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/httpauth - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/uptime-tracker/metrics - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/api:e->github.com/skycoin/skywire/pkg/uptime-tracker/store - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/metrics:e->github.com/skycoin/skywire/pkg/metricsutil - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/store:e->github.com/skycoin/skywire/pkg/geo - - + + - + github.com/skycoin/skywire/pkg/uptime-tracker/store:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/uptimestats:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/utclient - - -github.com/skycoin/skywire/pkg/utclient -165 / 5.1KB + + +github.com/skycoin/skywire/pkg/utclient +165 / 5.1KB - + github.com/skycoin/skywire/pkg/utclient:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/utclient:e->github.com/skycoin/skywire/pkg/httpauthclient - - + + - + github.com/skycoin/skywire/pkg/utclient:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/utclient:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/util/cipherutil - - -github.com/skycoin/skywire/pkg/util/cipherutil -20 / 518B + + +github.com/skycoin/skywire/pkg/util/cipherutil +20 / 518B - + github.com/skycoin/skywire/pkg/util/cipherutil:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/util/osutil - - -github.com/skycoin/skywire/pkg/util/osutil -153 / 4.4KB + + +github.com/skycoin/skywire/pkg/util/osutil +153 / 4.4KB - + github.com/skycoin/skywire/pkg/util/rename - - -github.com/skycoin/skywire/pkg/util/rename -60 / 1.7KB + + +github.com/skycoin/skywire/pkg/util/rename +60 / 1.7KB - + github.com/skycoin/skywire/pkg/util/pathutil:e->github.com/skycoin/skywire/pkg/util/rename - - + + - + github.com/skycoin/skywire/pkg/visnetwork/physics - - -github.com/skycoin/skywire/pkg/visnetwork/physics -950 / 28.5KB + + +github.com/skycoin/skywire/pkg/visnetwork/physics +950 / 28.5KB - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/cmd/apps/skychat/group - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/cmd/apps/skychat/history - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/cmd/apps/skychat/pairing - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/cmd/skywire-cli/commands/rewards/server - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/app - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/app/appcommon - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/app/appdisc - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/app/appevent - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/app/launcher - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/cxo/treestore - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/cmdutil - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/direct - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/disc - - - - - -github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/disc/dmsgfirst - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/dmsgctrl - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/dmsgcurl - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/dmsghttp - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsg/dmsgscp - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsgc - - + + + + + +github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsgc/spec + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/dmsgweb - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/geo - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/geoip - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/rfclient - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/route-finder/store - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/router/policy - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/router/policy/wasm - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/router/setupmetrics - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/servicedisc - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/serviceuptime - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/skymailbridge - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/skynetca - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/skynetweb - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/tpviz - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport-discovery/api - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport/network - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport/network/addrresolver - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport/network/stcp - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport/setup - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport/tpdclient - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/utclient - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/util/cipherutil - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/util/osutil - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/util/pathutil - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/util/rpcutil - - + + - + github.com/skycoin/skywire/pkg/visor/dmsgtracker - - -github.com/skycoin/skywire/pkg/visor/dmsgtracker -339 / 10.5KB + + +github.com/skycoin/skywire/pkg/visor/dmsgtracker +339 / 10.5KB - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/dmsgtracker - - + + - + github.com/skycoin/skywire/pkg/visor/logserver - - -github.com/skycoin/skywire/pkg/visor/logserver -1055 / 38.1KB + + +github.com/skycoin/skywire/pkg/visor/logserver +1438 / 54.2KB - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/logserver - - + + - + github.com/skycoin/skywire/pkg/visor/logstore - - -github.com/skycoin/skywire/pkg/visor/logstore -121 / 4.1KB + + +github.com/skycoin/skywire/pkg/visor/logstore +121 / 4.1KB - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/logstore - - + + + + + +github.com/skycoin/skywire/pkg/visor/netview + + +github.com/skycoin/skywire/pkg/visor/netview +174 / 5.0KB + + + + + +github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/netview + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/rewardconfig - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/rpcgrpc - - + + - + github.com/skycoin/skywire/pkg/visor/stats - - -github.com/skycoin/skywire/pkg/visor/stats -1294 / 44.2KB + + +github.com/skycoin/skywire/pkg/visor/stats +1294 / 44.2KB - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/stats - - + + - + github.com/skycoin/skywire/pkg/visor/usermanager - - -github.com/skycoin/skywire/pkg/visor/usermanager -631 / 18.9KB + + +github.com/skycoin/skywire/pkg/visor/usermanager +634 / 19.3KB - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/usermanager - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore + + +github.com/skycoin/skywire/pkg/visor/visorcore +368 / 14.1KB + + + + + +github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/visorcore + + - + github.com/skycoin/skywire/pkg/visor/visorinit - - -github.com/skycoin/skywire/pkg/visor/visorinit -130 / 3.6KB + + +github.com/skycoin/skywire/pkg/visor/visorinit +130 / 3.6KB - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/visor/visorinit - - + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/vpn - - + + + + + +github.com/skycoin/skywire/pkg/wasmhv/browseui + + +github.com/skycoin/skywire/pkg/wasmhv/browseui +31 / 1.4KB + + + + + +github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/pkg/wasmhv/browseui + + - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/rewards - - + + - + github.com/skycoin/skywire/static/icons - - -github.com/skycoin/skywire/static/icons -8 / 143B + + +github.com/skycoin/skywire/static/icons +8 / 143B - + github.com/skycoin/skywire/pkg/visor:e->github.com/skycoin/skywire/static/icons - - + + - + github.com/skycoin/skywire/pkg/visor/dmsgtracker:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/visor/dmsgtracker:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/visor/dmsgtracker:e->github.com/skycoin/skywire/pkg/dmsg/dmsg - - + + - + github.com/skycoin/skywire/pkg/visor/dmsgtracker:e->github.com/skycoin/skywire/pkg/dmsg/dmsgctrl - - + + - + github.com/skycoin/skywire/pkg/visor/dmsgtracker:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/visor/dmsgtracker:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/pty - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/serviceuptime - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/visor/stats - - + + - + github.com/skycoin/skywire/pkg/visor/logserver:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/pkg/visor/rpcgrpc:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/visor/rpcgrpc:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/visor/rpcgrpc:e->github.com/skycoin/skywire/pkg/route-finder/store - - + + - + github.com/skycoin/skywire/pkg/visor/rpcgrpc:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/visor/rpcgrpc:e->github.com/skycoin/skywire/pkg/transport - - + + - + github.com/skycoin/skywire/pkg/visor/rpcgrpc:e->github.com/skycoin/skywire/pkg/transport-discovery/store - - + + - + github.com/skycoin/skywire/pkg/visor/rpcgrpc:e->github.com/skycoin/skywire/pkg/transport/types - - + + - + github.com/skycoin/skywire/pkg/visor/stats:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/visor/stats:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/visor/stats:e->github.com/skycoin/skywire/pkg/util/bbolthealth - - + + - + github.com/skycoin/skywire/pkg/visor/usermanager:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/visor/usermanager:e->github.com/skycoin/skywire/pkg/httputil - - + + - + github.com/skycoin/skywire/pkg/visor/usermanager:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/visor/usermanager:e->github.com/skycoin/skywire/pkg/util/bbolthealth - - + + - + github.com/skycoin/skywire/pkg/visor/usermanager:e->github.com/skycoin/skywire/pkg/visor/visorconfig - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/deployment - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/app/appserver/spec - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/app/launcher - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/buildinfo - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/dmsg/disc - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/dmsgc/spec - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/transport/network/spec - - + + - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/pkg/transport/spec - - + + - + github.com/skycoin/skywire/third_party/zcalusic/sysinfo - - -github.com/skycoin/skywire/third_party/zcalusic/sysinfo -999 / 32.6KB + + +github.com/skycoin/skywire/third_party/zcalusic/sysinfo +999 / 32.6KB - + github.com/skycoin/skywire/pkg/visor/visorconfig:e->github.com/skycoin/skywire/third_party/zcalusic/sysinfo - - + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/deployment + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/cipher + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/dmsg/dmsg + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/logging + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/rfclient + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/router + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/routing + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/skyenv + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/transport + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/transport/types + + + + + +github.com/skycoin/skywire/pkg/visor/visorcore:e->github.com/skycoin/skywire/pkg/visor/visorconfig + + - + github.com/skycoin/skywire/pkg/visor/visorinit:e->github.com/skycoin/skywire/pkg/logging - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/app - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/app/appnet - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/app/appserver - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/cipher - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/dmsg/dmsgcurl - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/netutil - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/rfclient - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/router - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/routing - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/skyenv - - + + - + github.com/skycoin/skywire/pkg/vpn:e->github.com/skycoin/skywire/pkg/util/osutil - - + + + + + +github.com/skycoin/skywire/pkg/wasmhv:e->github.com/skycoin/skywire/pkg/buildinfo + + + + + +github.com/skycoin/skywire/pkg/wasmhv:e->github.com/skycoin/skywire/pkg/cipher + + + + + +github.com/skycoin/skywire/pkg/wasmhv:e->github.com/skycoin/skywire/pkg/dmsg/dmsg + + + + + +github.com/skycoin/skywire/pkg/wasmhv:e->github.com/skycoin/skywire/pkg/wasmhv/browseui + + + + + +github.com/skycoin/skywire/pkg/wasmrpc + + +github.com/skycoin/skywire/pkg/wasmrpc +118 / 4.2KB + + + + + +github.com/skycoin/skywire/pkg/wasmhv/ctlbridge:e->github.com/skycoin/skywire/pkg/wasmrpc + + - + github.com/skycoin/skywire/scripts - - -github.com/skycoin/skywire/scripts -249 / 6.7KB + + +github.com/skycoin/skywire/scripts +249 / 6.7KB - + github.com/skycoin/skywire/static/skywire-manager-src/node_modules/flatted/golang/pkg/flatted - - -github.com/skycoin/skywire/static/skywire-manager-src/node_modules/flatted/golang/pkg/flatted -254 / 5.9KB + + +github.com/skycoin/skywire/static/skywire-manager-src/node_modules/flatted/golang/pkg/flatted +254 / 5.9KB - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/colorschemes - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/layout:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4 - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/layout:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui - - -github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui -655 / 17.3KB + + +github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui +655 / 17.3KB - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui/drawille-go - - -github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui/drawille-go -229 / 5.0KB + + +github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui/drawille-go +229 / 5.0KB - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui/drawille-go - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/utils - - -github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/utils -101 / 1.9KB + + +github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/utils +101 / 1.9KB - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/utils - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets:e->github.com/skycoin/skywire/third_party/VictoriaMetrics/metrics - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/devices - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/termui - - + + - + github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/widgets:e->github.com/skycoin/skywire/third_party/xxxserxxx/gotop/v4/utils - - + + - + github.com/skycoin/skywire/third_party/zcalusic/sysinfo/cpuid - - -github.com/skycoin/skywire/third_party/zcalusic/sysinfo/cpuid -7 / 324B + + +github.com/skycoin/skywire/third_party/zcalusic/sysinfo/cpuid +7 / 324B - + github.com/skycoin/skywire/third_party/zcalusic/sysinfo:e->github.com/skycoin/skywire/third_party/zcalusic/sysinfo/cpuid - - + + diff --git a/docs/wasm-visor-ui-tour.md b/docs/wasm-visor-ui-tour.md new file mode 100644 index 0000000000..62535bb2da --- /dev/null +++ b/docs/wasm-visor-ui-tour.md @@ -0,0 +1,130 @@ +# The wasm-visor UI — a visual tour + +The **wasm-visor** is a full Skywire visor **and** hypervisor UI that runs entirely +inside a browser tab, compiled to WebAssembly (`GOOS=js GOARCH=wasm`). No install, +no daemon, no filesystem — it dials into the Skywire network over dmsg-over-WebSocket +/ WebTransport / WebRTC, registers in discovery, and carries real transports. This +page is a screenshot tour of its interface. + +Screenshots were captured headless against a live standalone wasm-visor (served by +`skywire cli hv serve`, see below) using `cmd/hvinspect`. Each browser session +generates a fresh ephemeral identity, so the public key differs between shots. + +> Serving it: `skywire cli hv serve --tls` builds the single-file page from the +> embedded wasm + UI and serves it over HTTPS. Open the URL, accept the local +> cert once, and the visor boots in the tab. (The public deployment is +> https://skywire.theskywirenetwork.net.) + +--- + +## 1. The dashboard (visor list) + +![wasm-visor dashboard](img/wasm-visor/01-visor-dashboard.png) + +On boot the tab **is** a visor: it appears as the self entry in the visor list with +its public key, self-reported public IP (via STUN), transport count, and build +version. The top tabs are the same hypervisor surfaces as the native UI — Visor +list, Local Visor, Rewards, Resources, Transports, Network, Network Visualizer, +Deployment, Uptime — driven here by the in-wasm visor core rather than a remote +RPC. The version string carries `os:js arch:wasm`, the tell-tale of a browser visor. + +--- + +## 2. The mini-desktop app menu + +![app menu](img/wasm-visor/02-app-menu.png) + +The wasm-visor adds a **WinBox mini-desktop**: a taskbar with a ☰ launcher opening +draggable, resizable windows over the dashboard. The app menu offers: + +- **browser** — the skynet/dmsg virtual browser (multi-instance) +- **chat** — a 1:1 skychat client (wasm-visor only) +- **host** — serve content from this tab over dmsg (wasm-visor only) +- **console** — a REPL over the visor's API +- **logs** — the live visor log +- **identity** — the visor's keys / mode + +`chat` and `host` appear only on the wasm-visor (they use in-tab JS hooks the +native HV UI doesn't expose); the native UI has its own Angular skychat tab. + +--- + +## 3. Skynet browser + +![skynet browser](img/wasm-visor/03-skynet-browser.png) + +A virtual browser that fetches over Skywire by **public key**, not DNS/IP. Typing +`home:dmsg` (shown) lands on the visor's own resolver page listing reachable +services (`sd.dmsg`, `ar.dmsg`, the deployment discovery services, …). It can +browse `dmsg://` and `.dmsg` sites via the resolving proxy, and clearnet +via a skysocks-lite exit — each window has its own activity-log pane showing the +resolving-proxy / skysocks route setup. + +--- + +## 4. Skychat + +![skychat window](img/wasm-visor/04-skychat.png) + +A 1:1 chat client that talks to any visor running skychat, over the wasm-visor's +own dmsg client. Notable controls: + +- **peer** — paste the other visor's public key; distinct senders from the buffer + surface as clickable chips so an incoming message from an unknown peer is + discoverable. +- **transport** — send over **dmsg** (direct) or **skynet** (routed). +- **🐞 log** — a collapsible activity pane showing skychat's own + dial/connect/send/receive steps (here: `skychat: dialing dmsg :1…`), the same + way the browser window surfaces its proxy route setup. + +Messages are Noise-encrypted end to end; the wire is a length-prefixed frame +(shared codec in `pkg/skychat/message`). + +--- + +## 5. Host content + +![host content window](img/wasm-visor/05-host-content.png) + +The tab can **serve content over dmsg** while it's open — reachable at +`.dmsg:` by any visor. Add a text page, upload files, or a whole +directory; each path is listed with its content type, size, and an enable/disable +toggle. This is a website with no server, no domain, and no IP — addressed purely +by public key. (Demonstrated cross-visor: a native visor's browser can open a page +hosted from a browser tab here.) + +--- + +## 6. Console + +![console REPL](img/wasm-visor/06-console.png) + +A REPL that dispatches to the running visor's API — `about`, `visors`, `net`, +`app ls`, `tp ls`, `route ls`, or `raw `. In the wasm-visor these are +in-process function calls (`hvApi()`), so it works even in a standalone PWA with +no shell. Shown: `about` returning the build (`os:"js"`, `arch:"wasm"`), +`dmsg_connected: true`, and the live dmsg session count. + +--- + +## 7. Logs + +![logs window](img/wasm-visor/07-logs.png) + +A live view of the visor log — the captured console ring buffer — with a level +filter and text filter. The operator can watch dmsg connects, transport setup, +route origination, telemetry, and app activity without browser devtools or a shell. + +--- + +## Regenerating these screenshots + +They're captured with `cmd/hvinspect` (headless Brave via chromedp) against a +running harness: + +``` +skywire cli hv serve --tls --harness --addr :8443 # serve the wasm-visor +HVINSPECT_EVAL='' \ + cmd/hvinspect/hvinspect https://localhost:8443/ 16 /tmp/shot # boot + screenshot +convert /tmp/shot.png -crop 1290x1000+0+0 +repage docs/img/wasm-visor/.png +``` diff --git a/go.mod b/go.mod index c1f9df7645..065c51451e 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d github.com/orandin/lumberjackrus v1.0.1 github.com/oschwald/geoip2-golang/v2 v2.2.0 - github.com/pires/go-proxyproto v0.12.0 + github.com/pires/go-proxyproto v0.14.0 github.com/pterm/pterm v0.12.83 github.com/robert-nix/ansihtml v1.0.1 github.com/sirupsen/logrus v1.9.4 @@ -76,16 +76,16 @@ require ( github.com/peterh/liner v1.2.2 github.com/pgavlin/femto v0.0.0-20201224065653-0c9d20f9cac4 github.com/pion/datachannel v1.6.2 - github.com/pion/webrtc/v4 v4.2.15 + github.com/pion/webrtc/v4 v4.2.16 github.com/pkg/sftp v1.13.10 github.com/quic-go/webtransport-go v0.11.0 github.com/rivo/tview v0.42.0 github.com/soheilhy/cmux v0.1.5 github.com/tetratelabs/wazero v1.12.0 github.com/xxxserxxx/lingo/v2 v2.0.1 - go.starlark.net v0.0.0-20260613233743-8ba36ccb83fb + go.starlark.net v0.0.0-20260630144053-529d8e869a14 golang.org/x/time v0.15.0 - google.golang.org/grpc v1.81.1 + google.golang.org/grpc v1.82.0 google.golang.org/protobuf v1.36.11 ) @@ -116,14 +116,14 @@ require ( github.com/pion/logging v0.2.4 // indirect github.com/pion/mdns/v2 v2.1.0 // indirect github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.16 // indirect - github.com/pion/rtp v1.10.2 // indirect - github.com/pion/sctp v1.10.2 // indirect + github.com/pion/rtcp v1.2.17 // indirect + github.com/pion/rtp v1.10.3 // indirect + github.com/pion/sctp v1.10.3 // indirect github.com/pion/sdp/v3 v3.0.19 // indirect github.com/pion/srtp/v3 v3.0.12 // indirect github.com/pion/stun/v3 v3.1.6 // indirect github.com/pion/transport/v4 v4.0.2 // indirect - github.com/pion/turn/v5 v5.0.10 // indirect + github.com/pion/turn/v5 v5.0.12 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/sergi/go-diff v1.4.0 // indirect github.com/wlynxg/anet v0.0.5 // indirect @@ -185,7 +185,7 @@ require ( github.com/godbus/dbus/v5 v5.2.2 // indirect github.com/gomarkdown/markdown v0.0.0-20260614204949-e08cff860f76 // indirect github.com/gookit/color v1.6.1 // indirect - github.com/gopherjs/gopherjs v1.20.2 // indirect + github.com/gopherjs/gopherjs v1.21.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/itchyny/timefmt-go v0.1.8 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -195,13 +195,13 @@ require ( github.com/jaypipes/pcidb v1.1.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/klauspost/cpuid/v2 v2.4.0 // indirect github.com/klauspost/reedsolomon v1.14.1 // indirect github.com/kyokomi/emoji/v2 v2.2.13 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/lucasb-eyer/go-colorful v1.4.0 // indirect - github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect + github.com/lufia/plan9stats v0.0.0-20260627054121-477a66015f15 // indirect github.com/mattn/go-colorable v0.1.15 // indirect github.com/mattn/go-isatty v0.0.22 // indirect github.com/mattn/go-runewidth v0.0.24 @@ -213,7 +213,7 @@ require ( github.com/onsi/gomega v1.36.3 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/oschwald/maxminddb-golang/v2 v2.4.0 // indirect + github.com/oschwald/maxminddb-golang/v2 v2.4.1 // indirect github.com/pelletier/go-toml/v2 v2.4.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -225,7 +225,7 @@ require ( github.com/sagikazarmark/locafero v0.12.0 // indirect github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 github.com/shirou/gopsutil/v3 v3.24.5 - github.com/shoenig/go-m1cpu v0.2.1 // indirect + github.com/shoenig/go-m1cpu v0.2.2 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect @@ -258,8 +258,8 @@ require ( golang.org/x/image v0.43.0 // indirect golang.org/x/text v0.38.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260630182238-925bb5da69e7 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 // indirect diff --git a/go.sum b/go.sum index 8d1c242049..0242fe6a5c 100644 --- a/go.sum +++ b/go.sum @@ -435,8 +435,8 @@ github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0= github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E= github.com/gookit/color v1.6.1 h1:KoTnDxJPRgrL0SoX0f8rCFg2zI0t4E3GZZBMo2nN8LU= github.com/gookit/color v1.6.1/go.mod h1:9ACFc7/1IpHGBW8RwuDm/0YEnhg3dwwXpoMsmtyHfjs= -github.com/gopherjs/gopherjs v1.20.2 h1:mzF/NBZH47L63jqg19OQgXv32FYRvFZVWom8PiQ2HbU= -github.com/gopherjs/gopherjs v1.20.2/go.mod h1:h+FTmmLgbXMmmtuZFp9bUqXciN429Wx0sJEJuMnpyfM= +github.com/gopherjs/gopherjs v1.21.0 h1:5HEGrz+XhpCchubMGzuyLuGoCTlL/yCT7sGsT5Se/dw= +github.com/gopherjs/gopherjs v1.21.0/go.mod h1:R2HIOen3IzYSzvmvkeD8WOfiLN9wueR/T5Y+6z326Ck= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -523,8 +523,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= +github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= github.com/klauspost/reedsolomon v1.14.1 h1:swE9kzyWXD/wVG+l5Pe8bWnQ0giIY7D1GjCBKk3kG2U= github.com/klauspost/reedsolomon v1.14.1/go.mod h1:yjqqjgMTQkBUHSG97/rm4zipffCNbCiZcB3kTqr++sQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -557,8 +557,8 @@ github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4= github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak= -github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/lufia/plan9stats v0.0.0-20260627054121-477a66015f15 h1:YkjVPl/YH5XlJ+/NiwzJtPYXXKRcyjmEUhsDci6YK3c= +github.com/lufia/plan9stats v0.0.0-20260627054121-477a66015f15/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -647,8 +647,8 @@ github.com/orandin/lumberjackrus v1.0.1 h1:7ysDQ0MHD79zIFN9/EiDHjUcgopNi5ehtxFDy github.com/orandin/lumberjackrus v1.0.1/go.mod h1:xYLt6H8W93pKnQgUQaxsApS0Eb4BwHLOkxk5DVzf5H0= github.com/oschwald/geoip2-golang/v2 v2.2.0 h1:gdkhpnHQMiH9ymOI+zSB0QKFGH+n4TntNt7vz+TxGPY= github.com/oschwald/geoip2-golang/v2 v2.2.0/go.mod h1:xW4tCeQiNU1gqMD1x7zEH2CDNM3d796Ls50yxYDaX0U= -github.com/oschwald/maxminddb-golang/v2 v2.4.0 h1:3ftnrR1/XwiQ788bWIRhsE1DK3GOgJ6tm6S2qTktLm8= -github.com/oschwald/maxminddb-golang/v2 v2.4.0/go.mod h1:7jcFtmhWVDEV+UopVv9NjcPm200uMyEHN14LIVV4hW8= +github.com/oschwald/maxminddb-golang/v2 v2.4.1 h1:OffzqSABE3Sw354GdBThqDsKfpA4GWBqOY2P91V8tjI= +github.com/oschwald/maxminddb-golang/v2 v2.4.1/go.mod h1:CZK8iQQMKfy6mKOifoyUmrj4vTHnMiGVaS7hDaZZxQ0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -673,12 +673,12 @@ github.com/pion/mdns/v2 v2.1.0 h1:3IJ9+Xio6tWYjhN6WwuY142P/1jA0D5ERaIqawg/fOY= github.com/pion/mdns/v2 v2.1.0/go.mod h1:pcez23GdynwcfRU1977qKU0mDxSeucttSHbCSfFOd9A= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo= -github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo= -github.com/pion/rtp v1.10.2 h1:l+f6tTDcAH6xwepaAoW791ddhuYsJlqRATOzirO04Mo= -github.com/pion/rtp v1.10.2/go.mod h1:Au8fc6cEByy8RLTwKTQTEeQqDB/SJDxwL4mZuxYA5Pk= -github.com/pion/sctp v1.10.2 h1:6aezYsMrHAwpjJ6kUdyCiWPqZwgToT00ponT7seJ6a4= -github.com/pion/sctp v1.10.2/go.mod h1:7KFmTwLcoYgJs/Z+99nJvsWL0qDpuyloSI0RbAqlrz0= +github.com/pion/rtcp v1.2.17 h1:PxiT6L79yPZKtXIsXdG1eakBl6dtBj4x+4oVEL0DlSw= +github.com/pion/rtcp v1.2.17/go.mod h1:7kBpuBJaWwax4hzc/pgexY8vkOpvh8atgYDbaKZq0iU= +github.com/pion/rtp v1.10.3 h1:r5nJQdtM9Dc4ZYxtTcPPz7PIFArKJIf/DMlIUxU7+1c= +github.com/pion/rtp v1.10.3/go.mod h1:Au8fc6cEByy8RLTwKTQTEeQqDB/SJDxwL4mZuxYA5Pk= +github.com/pion/sctp v1.10.3 h1:1gBtLMA9lmwNuJkZSZJCdD5/Hz4yJs+7dAqi6ZY97QI= +github.com/pion/sctp v1.10.3/go.mod h1:7KFmTwLcoYgJs/Z+99nJvsWL0qDpuyloSI0RbAqlrz0= github.com/pion/sdp/v3 v3.0.19 h1:1VMKs3gIkTQV5M3hNKfTAPrDXSNrYtOlmOD8+mSZUGQ= github.com/pion/sdp/v3 v3.0.19/go.mod h1:dE5WOSlzXrtiE/iuZqe9n+AcEbOjtAd3k5m5NtlV/qU= github.com/pion/srtp/v3 v3.0.12 h1:U7V17bckl7sI4mb3sepiojByDuBY0wNCqQE+6IlQBbc= @@ -689,12 +689,12 @@ github.com/pion/transport/v3 v3.1.1 h1:Tr684+fnnKlhPceU+ICdrw6KKkTms+5qHMgw6bIkY github.com/pion/transport/v3 v3.1.1/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ= github.com/pion/transport/v4 v4.0.2 h1:ifYlPqNwsy6aKQ9y8yzxXlHae5431ZrH2avkD/Rn6Tk= github.com/pion/transport/v4 v4.0.2/go.mod h1:06hFI+jCFcok2X2MekVufNZ/uzNZXivGBPfviSVcjgM= -github.com/pion/turn/v5 v5.0.10 h1:mOMZjudflXpte5OsCnXztpUKwNXcpXIAzMBnq9TXOSQ= -github.com/pion/turn/v5 v5.0.10/go.mod h1:u3XjBqy2Z4+NhCUpDoOSsNuQDrPLvKStlCGWk6sTQ1E= -github.com/pion/webrtc/v4 v4.2.15 h1:Ir/MauNFCfg+kgyBYPQLiGdVWFlzEcLxqtuzAkYkky0= -github.com/pion/webrtc/v4 v4.2.15/go.mod h1:CPTcyLfIzC4scOkQ4UY4pj6WvbUGhcNLIpK28cP5h6M= -github.com/pires/go-proxyproto v0.12.0 h1:TTCxD66dU898tahivkqc3hoceZp7P44FnorWyo9d5vM= -github.com/pires/go-proxyproto v0.12.0/go.mod h1:qUvfqUMEoX7T8g0q7TQLDnhMjdTrxnG0hvpMn+7ePNI= +github.com/pion/turn/v5 v5.0.12 h1:6+b69ivQQXSlyfkp2AKripqD2k3W32qXK8QzCzpJWPI= +github.com/pion/turn/v5 v5.0.12/go.mod h1:CQACsRDJtjQ+6RSrGHrS2PCIerLwbW3uqXRqOvtjAFg= +github.com/pion/webrtc/v4 v4.2.16 h1:oK1GAg0TWJtZWYB8J/BgTgGWPoV2148gQWocH12vr3Q= +github.com/pion/webrtc/v4 v4.2.16/go.mod h1:y4HjLAkX90LH+C/qPqGOUgz8RA8CbDj3Iar3d+2hdKQ= +github.com/pires/go-proxyproto v0.14.0 h1:2vIGIfVG8eVRsKF0xukEoeT5RWhDXxBU0uv6smLOKdI= +github.com/pires/go-proxyproto v0.14.0/go.mod h1:OXsCrKwrK2tXS9YrI5tkHx5xaQlO8FH3lFW76orFh24= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -769,8 +769,8 @@ github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 h1:Xuk8ma/ibJ1 github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7AwjWCpdPhkSmNAgUv5C7EJ4AbmjEB3r047r3DXWu3Y= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= -github.com/shoenig/go-m1cpu v0.2.1 h1:yqRB4fvOge2+FyRXFkXqsyMoqPazv14Yyy+iyccT2E4= -github.com/shoenig/go-m1cpu v0.2.1/go.mod h1:KkDOw6m3ZJQAPHbrzkZki4hnx+pDRR1Lo+ldA56wD5w= +github.com/shoenig/go-m1cpu v0.2.2 h1:4nc55oVv7nygGnfI9bhLCLzUEs4794y0Bkqx4q2zy7Y= +github.com/shoenig/go-m1cpu v0.2.2/go.mod h1:KkDOw6m3ZJQAPHbrzkZki4hnx+pDRR1Lo+ldA56wD5w= github.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk= github.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= @@ -923,8 +923,8 @@ go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLh go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= -go.starlark.net v0.0.0-20260613233743-8ba36ccb83fb h1:NGUBN0jbH0IR3msRslALnoxlySm+6YvVKvVDjdDJrlA= -go.starlark.net v0.0.0-20260613233743-8ba36ccb83fb/go.mod h1:Iue6g6iirlfLoVi/DYCi5/x0h/bAOuWF3dULTKpt2Vo= +go.starlark.net v0.0.0-20260630144053-529d8e869a14 h1:w4krPU6GwY87DdwH30fr/GygfD3ROuoBq3YWilzFe6A= +go.starlark.net v0.0.0-20260630144053-529d8e869a14/go.mod h1:Iue6g6iirlfLoVi/DYCi5/x0h/bAOuWF3dULTKpt2Vo= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= @@ -1401,10 +1401,10 @@ google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d h1:mpAgMyM9vQHxycBlDq50y1VHpfSfVwzXvrQKtYbXuUY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260630182238-925bb5da69e7 h1:eM/YSd5bBFagF51o1E745Ta7RwzpW0h+z+QDNZOgmQ8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260630182238-925bb5da69e7/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1435,8 +1435,8 @@ google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= -google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/grpc v1.82.0 h1:vguDnZUPjE26w09A63VoxZPnvPjB5Riyc0mkXPFmAIU= +google.golang.org/grpc v1.82.0/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/pkg/cxo/data/cxds/drive.go b/pkg/cxo/data/cxds/drive.go index 9dc645b45f..5f06bbe6fd 100644 --- a/pkg/cxo/data/cxds/drive.go +++ b/pkg/cxo/data/cxds/drive.go @@ -1,3 +1,8 @@ +//go:build !js + +// The bbolt-backed on-disk CXDS. Excluded from js/wasm (bbolt uses arch-specific +// consts + mmap and does not build there); the js build gets stub constructors in +// drive_js.go and uses NewMemoryCXDS via skyobject's InMemoryDB path instead. package cxds import ( @@ -414,10 +419,6 @@ func (d *driveCXDS) Get( return val, rc, err } -func panicf(format string, args ...interface{}) { - panic(fmt.Sprintf(format, args...)) -} - func (d *driveCXDS) addAll(vol int) { d.mx.Lock() defer d.mx.Unlock() diff --git a/pkg/cxo/data/cxds/drive_js.go b/pkg/cxo/data/cxds/drive_js.go new file mode 100644 index 0000000000..d4689ebfe5 --- /dev/null +++ b/pkg/cxo/data/cxds/drive_js.go @@ -0,0 +1,30 @@ +//go:build js + +// js/wasm stubs for the on-disk (bbolt) CXDS. bbolt does not build under js/wasm +// (arch-specific consts + mmap), so the disk implementation lives in drive.go +// (//go:build !js). A wasm visor uses the in-memory CXDS (NewMemoryCXDS) via +// skyobject's InMemoryDB path, so these constructors are never called on that +// path — they exist only so skyobject/container.go compiles for js/wasm. Calling +// one returns an error rather than silently falling back. +package cxds + +import ( + "errors" + + "github.com/skycoin/skywire/pkg/cxo/data" +) + +// errNoDiskDB is returned by the on-disk constructors on js/wasm. +var errNoDiskDB = errors.New("cxds: on-disk (bbolt) datastore is unavailable under js/wasm — use InMemoryDB") + +// DriveOptions mirrors the non-js type so callers (skyobject/container.go) compile +// unchanged. Only NoSync is referenced; it has no effect here. +type DriveOptions struct { + NoSync bool +} + +// NewDriveCXDS is a js/wasm stub — always errors (no on-disk DB under js/wasm). +func NewDriveCXDS(string) (data.CXDS, error) { return nil, errNoDiskDB } + +// NewDriveCXDSWithOptions is a js/wasm stub — always errors. +func NewDriveCXDSWithOptions(string, DriveOptions) (data.CXDS, error) { return nil, errNoDiskDB } diff --git a/pkg/cxo/data/cxds/memory.go b/pkg/cxo/data/cxds/memory.go index 7156e8e3a1..defdda0e8f 100644 --- a/pkg/cxo/data/cxds/memory.go +++ b/pkg/cxo/data/cxds/memory.go @@ -1,6 +1,7 @@ package cxds import ( + "fmt" "sync" "github.com/skycoin/skycoin/src/cipher" @@ -8,6 +9,12 @@ import ( "github.com/skycoin/skywire/pkg/cxo/data" ) +// panicf lives here (untagged) rather than in drive.go so both the memory and the +// on-disk (!js) CXDS can use it — drive.go is excluded from the js/wasm build. +func panicf(format string, args ...interface{}) { + panic(fmt.Sprintf(format, args...)) +} + type memoryCXDS struct { mx sync.RWMutex kvs map[cipher.SHA256]memoryObject diff --git a/pkg/cxo/data/idxdb/drive.go b/pkg/cxo/data/idxdb/drive.go index e9d83f9129..dd7125d2be 100644 --- a/pkg/cxo/data/idxdb/drive.go +++ b/pkg/cxo/data/idxdb/drive.go @@ -1,3 +1,8 @@ +//go:build !js + +// The bbolt-backed on-disk index DB. Excluded from js/wasm (bbolt does not build +// there); the js build gets stub constructors in drive_js.go and uses +// NewMemeoryDB via skyobject's InMemoryDB path instead. package idxdb import ( diff --git a/pkg/cxo/data/idxdb/drive_js.go b/pkg/cxo/data/idxdb/drive_js.go new file mode 100644 index 0000000000..fa08b2c3c5 --- /dev/null +++ b/pkg/cxo/data/idxdb/drive_js.go @@ -0,0 +1,28 @@ +//go:build js + +// js/wasm stubs for the on-disk (bbolt) index DB. bbolt does not build under +// js/wasm, so the disk implementation lives in drive.go (//go:build !js). A wasm +// visor uses the in-memory index (NewMemeoryDB) via skyobject's InMemoryDB path, +// so these constructors are never called there — they exist only so +// skyobject/container.go compiles for js/wasm. +package idxdb + +import ( + "errors" + + "github.com/skycoin/skywire/pkg/cxo/data" +) + +// errNoDiskDB is returned by the on-disk constructors on js/wasm. +var errNoDiskDB = errors.New("idxdb: on-disk (bbolt) index is unavailable under js/wasm — use InMemoryDB") + +// DriveOptions mirrors the non-js type so callers compile unchanged. +type DriveOptions struct { + NoSync bool +} + +// NewDriveIdxDB is a js/wasm stub — always errors (no on-disk DB under js/wasm). +func NewDriveIdxDB(string) (data.IdxDB, error) { return nil, errNoDiskDB } + +// NewDriveIdxDBWithOptions is a js/wasm stub — always errors. +func NewDriveIdxDBWithOptions(string, DriveOptions) (data.IdxDB, error) { return nil, errNoDiskDB } diff --git a/pkg/cxo/skyobject/container.go b/pkg/cxo/skyobject/container.go index 5a0860a1e1..26c3ea74c9 100644 --- a/pkg/cxo/skyobject/container.go +++ b/pkg/cxo/skyobject/container.go @@ -80,7 +80,12 @@ func NewContainer(conf *Config) (c *Container, err error) { func (c *Container) createDB(conf *Config) (err error) { - if conf.DataDir != "" { + // Only create the on-disk data dir when there IS an on-disk DB. In InMemoryDB + // mode the DataDir is unused (the CXDS/IdxDB live in memory), and creating it + // is not just wasteful — it's fatal under js/wasm, where the default DataDir + // resolves to /tmp and mkdir is "not implemented on js". Guarding this lets a + // wasm visor run an in-memory CXO publisher. + if conf.DataDir != "" && !conf.InMemoryDB { if err = mkdirp(conf.DataDir); err != nil { return err } diff --git a/pkg/dmsg/dmsg/util.go b/pkg/dmsg/dmsg/util.go index a374660783..0372f27c97 100644 --- a/pkg/dmsg/dmsg/util.go +++ b/pkg/dmsg/dmsg/util.go @@ -34,5 +34,9 @@ func encodeGob(v interface{}) ([]byte, error) { } func decodeGob(v interface{}, b []byte) error { - return gob.NewDecoder(bytes.NewReader(b)).Decode(v) + // G709 (gosec taint analysis) flags any gob decode of reader-sourced bytes. + // Here b is a dmsg wire frame that already arrived over a Noise-authenticated, + // integrity-checked session, and v is a fixed internal control type — not + // attacker-chosen. gob IS this protocol's framing serialization. + return gob.NewDecoder(bytes.NewReader(b)).Decode(v) //nolint:gosec // G709: gob frame over Noise-authenticated dmsg session, fixed internal decode target } diff --git a/pkg/skychat/message/message.go b/pkg/skychat/message/message.go new file mode 100644 index 0000000000..a8319b8201 --- /dev/null +++ b/pkg/skychat/message/message.go @@ -0,0 +1,167 @@ +// Package message is the single source of truth for skychat's peer-to-peer wire +// format: length-prefixed frames and the chat-msg/chat-ack envelope. +// +// Before this package the same framing (a 4-byte big-endian length followed by +// that many payload bytes, capped at 64 KiB) was implemented three times — the +// native app (cmd/apps/skychat framedConn), the browser-tab wasm visor +// (cmd/wasm-visor chatConn), and the group relay (group/session.go) — each with +// its own constant and write mutex, free to drift. They are now one codec. +// +// The package is pure Go (only io/net/encoding/sync/time), so it compiles under +// GOOS=js GOARCH=wasm as well as native — the wasm visor and the native app share it. +// +// Wire history: pre-2026-05-12 the protocol was "one Write = one Read" (a raw +// byte slice per message). That held on dmsg (noise-framed) but broke on skynet +// routes, where a VStream can split one Write across several Reads at arbitrary +// boundaries, so a long message arrived split into two chat entries. The +// length-prefixed frame fixed that; old unframed binaries can't talk to framed +// ones. The chat-msg/chat-ack envelope (opt-in, JSON) rides inside a frame; a +// default send writes the plain-text body with no envelope, keeping the wire +// byte-identical for ordinary chat. +package message + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "sync" + "time" +) + +// MaxFrameSize bounds a single framed payload. A larger frame on read is rejected +// as an out-of-sync or hostile peer (or an old, unframed binary). +const MaxFrameSize = 64 * 1024 + +var errEmptyPayload = errors.New("skychat: empty payload") + +// WriteFrame writes payload as one length-prefixed frame: a 4-byte big-endian +// length followed by exactly that many bytes. Rejects an empty or oversize payload. +func WriteFrame(w io.Writer, payload []byte) error { + if len(payload) == 0 { + return errEmptyPayload + } + if len(payload) > MaxFrameSize { + return fmt.Errorf("skychat: payload %d > max %d", len(payload), MaxFrameSize) + } + var hdr [4]byte + binary.BigEndian.PutUint32(hdr[:], uint32(len(payload))) //nolint:gosec // len bounded by MaxFrameSize above + if _, err := w.Write(hdr[:]); err != nil { + return err + } + _, err := w.Write(payload) + return err +} + +// ReadFrame reads exactly one length-prefixed frame. Rejects a zero-length or +// oversize frame — the latter usually means the peer is running the pre-framing, +// unbounded protocol. +func ReadFrame(r io.Reader) ([]byte, error) { + var hdr [4]byte + if _, err := io.ReadFull(r, hdr[:]); err != nil { + return nil, err + } + length := binary.BigEndian.Uint32(hdr[:]) + if length == 0 { + return nil, errors.New("skychat: zero-length frame") + } + if length > MaxFrameSize { + return nil, fmt.Errorf("skychat: frame %d > max %d (peer running old unframed protocol?)", length, MaxFrameSize) + } + payload := make([]byte, length) + if _, err := io.ReadFull(r, payload); err != nil { + return nil, err + } + return payload, nil +} + +// Conn wraps a net.Conn with length-prefixed framing and a write mutex. The write +// mutex is required because two callers can race to write to the same underlying +// conn (e.g. an outbound message and the ack reply for an inbound one); +// interleaving one frame's length prefix with another's payload would desync the +// receiver permanently. The read path is expected to have a single owner, so +// there is no read mutex. +type Conn struct { + net.Conn + writeMu sync.Mutex +} + +// NewConn wraps c with framing. +func NewConn(c net.Conn) *Conn { return &Conn{Conn: c} } + +// WriteFrame writes a length-prefixed frame, serialized against other writers. +func (c *Conn) WriteFrame(payload []byte) error { + c.writeMu.Lock() + defer c.writeMu.Unlock() + return WriteFrame(c.Conn, payload) +} + +// WriteFrameDeadline is WriteFrame bounded by a per-call write deadline, so a +// stalled peer (transport half-dead, peer not draining) can't pin the caller's +// goroutine indefinitely while holding the write mutex. timeout <= 0 falls back +// to an unbounded WriteFrame. The deadline is acquired AFTER the write mutex so +// its scope is the on-wire write rather than time spent queued behind another +// writer, and reset to "no deadline" (time.Time{}) on the way out so a later call +// isn't pre-expired. +func (c *Conn) WriteFrameDeadline(payload []byte, timeout time.Duration) error { + if timeout <= 0 { + return c.WriteFrame(payload) + } + c.writeMu.Lock() + defer c.writeMu.Unlock() + // SetWriteDeadline failure is rare on a healthy net.Conn; fall through to a + // best-effort unbounded write rather than failing the message on a metadata + // error. The reset defer is likewise best-effort. + _ = c.Conn.SetWriteDeadline(time.Now().Add(timeout)) //nolint:errcheck,gosec + defer func() { _ = c.Conn.SetWriteDeadline(time.Time{}) }() //nolint:errcheck,gosec + return WriteFrame(c.Conn, payload) +} + +// ReadFrame reads one length-prefixed frame from the underlying conn. +func (c *Conn) ReadFrame() ([]byte, error) { return ReadFrame(c.Conn) } + +// Envelope is the JSON payload shape for the opt-in peer-receipt protocol: +// +// chat-msg: {"type":"chat-msg","id":"","body":"...","ack":true} +// chat-ack: {"type":"chat-ack","id":""} +// +// A default (no --wait) send writes the plain-text body with no envelope, so the +// wire stays byte-identical for ordinary chat; the envelope is opt-in at the sender. +type Envelope struct { + Type string `json:"type"` + ID string `json:"id"` + Body string `json:"body,omitempty"` + Ack bool `json:"ack,omitempty"` // chat-msg only: request ack-on-receipt +} + +// Envelope type values. +const ( + TypeMsg = "chat-msg" + TypeAck = "chat-ack" +) + +// Marshal encodes the envelope as its JSON wire bytes. +func (e Envelope) Marshal() ([]byte, error) { return json.Marshal(e) } + +// ParseEnvelope conservatively recognizes a chat-msg/chat-ack envelope in a frame +// payload: after trimming surrounding whitespace the payload must begin with '{', +// be valid JSON, and carry a known chat-* type. Anything else returns ok=false so +// a plain-text message that happens to look like JSON still reaches its peer as +// text (only known types are consumed as envelopes). +func ParseEnvelope(payload []byte) (env Envelope, ok bool) { + t := bytes.TrimSpace(payload) + if len(t) == 0 || t[0] != '{' { + return Envelope{}, false + } + if err := json.Unmarshal(t, &env); err != nil { + return Envelope{}, false + } + switch env.Type { + case TypeMsg, TypeAck: + return env, true + } + return Envelope{}, false +} diff --git a/pkg/skychat/message/message_test.go b/pkg/skychat/message/message_test.go new file mode 100644 index 0000000000..55069e0c51 --- /dev/null +++ b/pkg/skychat/message/message_test.go @@ -0,0 +1,138 @@ +package message + +import ( + "bytes" + "encoding/binary" + "io" + "net" + "strings" + "testing" +) + +// TestFrameRoundTrip verifies the exact on-wire layout (4-byte big-endian length +// + payload) and that ReadFrame recovers what WriteFrame wrote, back to back. +func TestFrameRoundTrip(t *testing.T) { + var buf bytes.Buffer + msgs := [][]byte{[]byte("hi"), []byte("a longer message with spaces"), {0x00, 0x01, 0x02}} + for _, m := range msgs { + if err := WriteFrame(&buf, m); err != nil { + t.Fatalf("WriteFrame(%q): %v", m, err) + } + } + // Exact layout of the first frame. + if got := binary.BigEndian.Uint32(buf.Bytes()[:4]); int(got) != len(msgs[0]) { + t.Fatalf("first frame length prefix = %d, want %d", got, len(msgs[0])) + } + for i, want := range msgs { + got, err := ReadFrame(&buf) + if err != nil { + t.Fatalf("ReadFrame #%d: %v", i, err) + } + if !bytes.Equal(got, want) { + t.Fatalf("ReadFrame #%d = %q, want %q", i, got, want) + } + } +} + +func TestWriteFrameRejects(t *testing.T) { + var buf bytes.Buffer + if err := WriteFrame(&buf, nil); err == nil { + t.Fatal("empty payload: want error, got nil") + } + if err := WriteFrame(&buf, make([]byte, MaxFrameSize+1)); err == nil { + t.Fatal("oversize payload: want error, got nil") + } + if buf.Len() != 0 { + t.Fatalf("rejected writes should emit no bytes, got %d", buf.Len()) + } +} + +func TestReadFrameRejects(t *testing.T) { + // zero-length frame + zero := []byte{0, 0, 0, 0} + if _, err := ReadFrame(bytes.NewReader(zero)); err == nil { + t.Fatal("zero-length frame: want error, got nil") + } + // oversize length prefix + var big [4]byte + binary.BigEndian.PutUint32(big[:], MaxFrameSize+1) + if _, err := ReadFrame(bytes.NewReader(big[:])); err == nil { + t.Fatal("oversize frame: want error, got nil") + } + // truncated payload + trunc := []byte{0, 0, 0, 8, 'a', 'b'} + if _, err := ReadFrame(bytes.NewReader(trunc)); err != io.ErrUnexpectedEOF { + t.Fatalf("truncated payload: want ErrUnexpectedEOF, got %v", err) + } +} + +// TestConnFramingCompat proves the *Conn wrapper writes the same bytes the raw +// WriteFrame does (so it interoperates with any peer using either API). +func TestConnFramingCompat(t *testing.T) { + a, b := net.Pipe() + fc := NewConn(a) + // net.Pipe write blocks until the other side reads, so write from a goroutine + // and collect its error afterward. + errc := make(chan error, 1) + go func() { errc <- fc.WriteFrame([]byte("ping")) }() + got, err := ReadFrame(b) + if err != nil { + t.Fatalf("ReadFrame from raw side: %v", err) + } + if werr := <-errc; werr != nil { + t.Fatalf("Conn.WriteFrame: %v", werr) + } + if string(got) != "ping" { + t.Fatalf("got %q, want ping", got) + } +} + +func TestParseEnvelope(t *testing.T) { + cases := []struct { + name string + in string + wantOK bool + wantTyp string + wantID string + wantAck bool + }{ + {"chat-msg with ack", `{"type":"chat-msg","id":"deadbeef","body":"hi","ack":true}`, true, TypeMsg, "deadbeef", true}, + {"chat-ack", `{"type":"chat-ack","id":"deadbeef"}`, true, TypeAck, "deadbeef", false}, + {"leading whitespace", " {\"type\":\"chat-ack\",\"id\":\"x\"}", true, TypeAck, "x", false}, + {"plain text", "hello world", false, "", "", false}, + {"json-looking but unknown type", `{"type":"something-else"}`, false, "", "", false}, + {"literal brace text", "{not json}", false, "", "", false}, + {"empty", "", false, "", "", false}, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + env, ok := ParseEnvelope([]byte(c.in)) + if ok != c.wantOK { + t.Fatalf("ok = %v, want %v", ok, c.wantOK) + } + if !ok { + return + } + if env.Type != c.wantTyp || env.ID != c.wantID || env.Ack != c.wantAck { + t.Fatalf("env = %+v, want type=%s id=%s ack=%v", env, c.wantTyp, c.wantID, c.wantAck) + } + }) + } +} + +// TestEnvelopeMarshalDefaultBytes locks the wire bytes: a chat-ack omits body+ack. +func TestEnvelopeMarshalDefaultBytes(t *testing.T) { + b, err := Envelope{Type: TypeAck, ID: "abc"}.Marshal() + if err != nil { + t.Fatal(err) + } + // Check for the quoted JSON keys, not bare substrings — the type value + // "chat-ack" itself contains "ack". + if got := string(b); strings.Contains(got, `"body"`) || strings.Contains(got, `"ack"`) { + t.Fatalf("chat-ack should omit body/ack keys, got %s", got) + } + env, ok := ParseEnvelope(b) + if !ok || env.Type != TypeAck || env.ID != "abc" { + t.Fatalf("round-trip failed: ok=%v env=%+v", ok, env) + } +} diff --git a/pkg/visor/usermanager/user_manager.go b/pkg/visor/usermanager/user_manager.go index 4de7ef8027..3c24804e66 100644 --- a/pkg/visor/usermanager/user_manager.go +++ b/pkg/visor/usermanager/user_manager.go @@ -313,7 +313,9 @@ func (s *UserManager) newSession(w http.ResponseWriter, session Session) error { return fmt.Errorf("encode SID cookie: %w", err) } - http.SetCookie(w, &http.Cookie{ + // G124 (gosec) is a false positive here: Secure/HttpOnly/SameSite ARE set, + // but via config accessors gosec's flow analysis can't see through. + http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set below via s.c accessors Name: sessionCookieName, Value: value, Path: s.c.Path, @@ -404,7 +406,8 @@ func (s *UserManager) delSession(w http.ResponseWriter, r *http.Request) error { delete(s.sessions, sid) s.mu.Unlock() - http.SetCookie(w, &http.Cookie{ + // G124 (gosec) false positive: attributes set via s.c accessors (see newSession). + http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set below via s.c accessors Name: sessionCookieName, Path: s.c.Path, Domain: s.c.Domain, diff --git a/pkg/wasmhv/browseui/browse.js b/pkg/wasmhv/browseui/browse.js index d033a79a9e..ac4bdfb597 100644 --- a/pkg/wasmhv/browseui/browse.js +++ b/pkg/wasmhv/browseui/browse.js @@ -525,6 +525,17 @@ // minimize, maximize, close, and (for url:) the iframe — so the create*Window // helpers only build a body. opts: {title, root, width, height, x, y, // mount|url, onclose}. + // Each new window gets a higher z-index than the last so it opens IN FRONT and + // is focused — a fixed shared index (the old behaviour) left a freshly-opened + // window stacked BEHIND the currently-focused one, obstructing it. Base sits + // above the HV UI but below the always-on taskbar (z 2147483646). + var _winZ = 2147483000; + function nextWinZ() { + _winZ += 1; + if (_winZ > 2147483640) _winZ = 2147483000; // cap well under the taskbar + return _winZ; + } + function makeWin(doc, opts) { var cfg = { title: opts.title || "window", @@ -533,7 +544,7 @@ height: opts.height || "70%", background: "#1b1726", border: "1", - index: 2147483000, + index: nextWinZ(), // no-full hides WinBox's Fullscreen-API button: "maximize" should fill the // area IN-TAB (over the dashboard, below the panel) — not take over the // whole screen. The remaining max button stays within the top/bottom @@ -551,7 +562,12 @@ if (opts.mount) cfg.mount = opts.mount; if (opts.url) cfg.url = opts.url; if (opts.onclose) cfg.onclose = opts.onclose; - return new WinBox(cfg); + var wb = new WinBox(cfg); + // Bring the new window to the front + focus it (WinBox raises the focused + // window's z within its own stack; combined with the incrementing base above + // this guarantees a new window is never obscured by an older one). + try { wb.focus(); } catch (e) {} + return wb; } // createWindow builds ONE browse window — a dmsg virtual browser + host/proxy @@ -1015,6 +1031,147 @@ return { wb: wb, close: function () { wb.close(); } }; } + // createChatWindow is the WinBox desktop's 1:1 skychat client — the missing + // desktop peer to the skynet browser. It drives the two existing wasm-visor JS + // hooks: skychatSend(peerPkHex, text) → Promise and skychatMessages() → JSON of + // [{from,text,ts,out}] (the in-memory ring the browser-tab visor keeps). Because + // receiving is passive (a peer just dials us on dmsg:1), the buffer's distinct + // `from` PKs are surfaced as clickable chips so an incoming message from a new + // peer is discoverable without knowing their key in advance. Wasm-visor only + // (native has its own Angular skychat tab), gated exactly like the host window. + function createChatWindow(doc, opts) { + var sv = globalThis.skywireVisor || {}; + var send = opts.skychatSend || sv.skychatSend; + var fetchMsgs = opts.skychatMessages || sv.skychatMessages; + function selfPK() { try { return (opts.selfPK && opts.selfPK()) || ""; } catch (_) { return ""; } } + var peer = ""; // active conversation peer PK (full hex) + var lastRender = ""; // cheap change-detection so we don't rebuild every tick + + var wrap = doc.createElement("div"); + wrap.style.cssText = "position:absolute;inset:0;background:#0e0c14;color:#cdd2da;font:12px/1.45 monospace;display:flex;flex-direction:column;overflow:hidden"; + var sp = selfPK(); + wrap.innerHTML = + '
' + + '
you: ' + (sp ? esc(sp) : "(boot the visor first)") + '
' + + '
peer ' + + '' + + '
' + + '
transport ' + + '' + + '' + + '
' + + '
' + + '
' + + '
' + + '' + + '
' + + '
' + + ''; + function $(id) { return wrap.querySelector("#" + id); } + var body = $("ch-body"), input = $("ch-in"), chips = $("ch-chips"), status = $("ch-status"); + + function setStatus(t, color) { status.textContent = t || ""; status.style.color = color || "#9aa0a6"; } + function messages() { + if (!fetchMsgs) return []; + try { return JSON.parse(fetchMsgs() || "[]") || []; } catch (_) { return []; } + } + function setPeer(pk) { + peer = (pk || "").trim(); + $("ch-peer").value = peer; + var ready = !!(send && peer); + input.disabled = !ready; $("ch-send").disabled = !ready; + lastRender = ""; render(); + if (ready) setTimeout(function () { input.focus(); }, 30); + } + function renderChips(all) { + var seen = {}, order = []; + for (var i = 0; i < all.length; i++) { var f = all[i].from; if (f && !seen[f]) { seen[f] = true; order.push(f); } } + var key = order.join(",") + "|" + peer; + if (chips.__key === key) return; chips.__key = key; + chips.textContent = ""; + order.forEach(function (f) { + var b = doc.createElement("button"); + b.textContent = f.slice(0, 8) + "…"; + b.title = f; + var active = (f === peer); + b.style.cssText = "cursor:pointer;border-radius:4px;padding:.2em .5em;font:11px monospace;border:1px solid #2a2342;" + + (active ? "background:#2a2342;color:#9d7cff" : "background:#15131c;color:#cdd2da"); + b.onclick = function () { setPeer(f); }; + chips.appendChild(b); + }); + } + function render() { + var all = messages(); + renderChips(all); + var thread = []; + for (var i = 0; i < all.length; i++) { if (all[i].from === peer) thread.push(all[i]); } + var sig = peer + "#" + thread.length + (thread.length ? "#" + thread[thread.length - 1].ts + thread[thread.length - 1].text : ""); + if (sig === lastRender) return; lastRender = sig; + body.textContent = ""; + if (!peer) { var h = doc.createElement("div"); h.style.color = "#9aa0a6"; h.textContent = "Paste a peer public key and press open — or pick a peer above once someone messages you."; body.appendChild(h); return; } + thread.forEach(function (m) { + var row = doc.createElement("div"); + row.style.cssText = "display:flex;flex-direction:column;max-width:82%;" + (m.out ? "align-self:flex-end;align-items:flex-end" : "align-self:flex-start;align-items:flex-start"); + var bub = doc.createElement("div"); + bub.style.cssText = "padding:.3em .55em;border-radius:8px;white-space:pre-wrap;word-break:break-word;" + + (m.out ? "background:#1f2b1a;color:#c8e6a8" : "background:#1b1726;color:#cdd2da"); + bub.textContent = m.text; + var meta = doc.createElement("div"); + meta.style.cssText = "font-size:10px;color:#6b7280;margin:.1em .2em 0"; + meta.textContent = (m.out ? "→ " : "← ") + new Date(m.ts).toTimeString().slice(0, 8); + row.appendChild(bub); row.appendChild(meta); body.appendChild(row); + }); + body.scrollTop = body.scrollHeight; + } + function doSend() { + var text = input.value; if (!text.trim() || !send || !peer) return; + input.value = ""; setStatus("sending…"); + Promise.resolve(send(peer, text, $("ch-net").value)).then(function () { + setStatus(""); lastRender = ""; render(); + }).catch(function (e) { + setStatus("send failed: " + (e && e.message ? e.message : e), "#f7768e"); + input.value = text; // let the operator retry without retyping + }); + } + $("ch-open").onclick = function () { setPeer($("ch-peer").value); }; + $("ch-peer").addEventListener("keydown", function (e) { if (e.key === "Enter") setPeer(this.value); }); + input.addEventListener("keydown", function (e) { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); doSend(); } }); + $("ch-send").onclick = doSend; + + // Activity log pane — surfaces skychat's own dial/connect/send/receive vlog + // lines from the shared window.skywireLog ring (the same source the 'logs' + // window reads), filtered to skychat, so the operator sees the connection / + // route setup like the browser window's skysocks-lite log. Collapsible (🐞). + var logEl = $("ch-log"), logOpen = false; + function chatLogLine(line) { + if (!line || !line.text || !/skychat/i.test(line.text)) return; + var d = doc.createElement("div"); + d.textContent = new Date(line.t || Date.now()).toTimeString().slice(0, 8) + " " + String(line.text).replace(/^\[visor\]\s*/, ""); + logEl.appendChild(d); + if (logEl.childNodes.length > 500) logEl.removeChild(logEl.firstChild); + if (logOpen) logEl.scrollTop = logEl.scrollHeight; + } + var logUnsub = function () {}; + if (window.skywireLog) { + try { window.skywireLog.all().forEach(chatLogLine); } catch (_) {} + logUnsub = window.skywireLog.subscribe(chatLogLine); + } + $("ch-log-toggle").onclick = function () { + logOpen = !logOpen; logEl.style.display = logOpen ? "block" : "none"; + this.style.opacity = logOpen ? "1" : ".6"; + if (logOpen) logEl.scrollTop = logEl.scrollHeight; + }; + + var timer = setInterval(render, 1500); + render(); + if (!send) setStatus("skychat is only available in the browser-tab (wasm) visor", "#e0af68"); + var wb = makeWin(doc, { + title: "skychat", root: opts.root, top: opts.top, bottom: opts.bottom, width: "42%", height: "62%", + mount: wrap, onclose: function () { clearInterval(timer); logUnsub(); if (opts.onClose) opts.onClose(); } + }); + return { wb: wb, close: function () { wb.close(); } }; + } + // createTerminalWindow opens a real dmsgpty terminal as a WinBox iframe to // opts.ptyURL (the visor's /pty/, which serves the xterm + pty WebSocket). // Native-only — the wasm visor has no host shell and sets no ptyURL, so the @@ -1123,7 +1280,9 @@ menu.appendChild(b); } addApp("browser", function () { openBrowse(); }); - // 'host' is wasm-visor only — it self-hosts content over dmsg from the tab. + // 'chat' + 'host' are wasm-visor only — they use in-tab JS hooks the native + // HV UI doesn't expose (native has its own Angular skychat tab). + if (globalThis.skywireVisor && globalThis.skywireVisor.skychatSend) { addApp("chat", function () { openChat(); }); } if (globalThis.skywireVisor && globalThis.skywireVisor.serveContent) { addApp("host", function () { openHost(); }); } addApp("console", function () { openCli(); }); if (opts.ptyURL) addApp("terminal", function () { openTerm(); }); @@ -1186,6 +1345,12 @@ termWin = createTerminalWindow(doc, withRoot({ onClose: function () { untrack(termWin); termWin = null; } })); track(termWin, "terminal"); } + var chatWin = null; + function openChat() { + if (focusExisting(chatWin)) { return; } + chatWin = createChatWindow(doc, withRoot({ onClose: function () { untrack(chatWin); chatWin = null; } })); + track(chatWin, "skychat"); + } var hostWin = null; function openHost() { if (focusExisting(hostWin)) { return; } diff --git a/pkg/wasmhv/wasmbin/wasm-visor.wasm.gz b/pkg/wasmhv/wasmbin/wasm-visor.wasm.gz index 693e8c2d04..af8d978d8a 100644 Binary files a/pkg/wasmhv/wasmbin/wasm-visor.wasm.gz and b/pkg/wasmhv/wasmbin/wasm-visor.wasm.gz differ diff --git a/vendor/github.com/gopherjs/gopherjs/js/js.go b/vendor/github.com/gopherjs/gopherjs/js/js.go index 3ebc0cc4d4..0f6101cdfb 100644 --- a/vendor/github.com/gopherjs/gopherjs/js/js.go +++ b/vendor/github.com/gopherjs/gopherjs/js/js.go @@ -260,6 +260,16 @@ type M map[string]any // S is a simple slice type. It is intended as a shorthand for JavaScript arrays (before conversion). type S []any +// MakeUint64 will take the high and low parts to construct a uint64 number. +// Since JS doesn't have a 64-bit integer we store it as a high and low 32-bit integers. +func MakeUint64(hi, lo float64) uint64 { return 0 } + +// Uint64High will get the high 32-bit integer used when storing uint64. +func Uint64High(x uint64) uint32 { return 0 } + +// Uint64Low will get the low 32-bit integer used when storing uint64. +func Uint64Low(x uint64) uint32 { return 0 } + func init() { // Avoid dead code elimination. e := Error{} diff --git a/vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml b/vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml index 1b695b62c3..14712fe0dd 100644 --- a/vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml +++ b/vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml @@ -29,7 +29,7 @@ archives: name_template: "cpuid-{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" format_overrides: - goos: windows - format: zip + formats: [ 'zip' ] files: - LICENSE checksum: diff --git a/vendor/github.com/klauspost/cpuid/v2/README.md b/vendor/github.com/klauspost/cpuid/v2/README.md index 88d68d5286..a99bbdba36 100644 --- a/vendor/github.com/klauspost/cpuid/v2/README.md +++ b/vendor/github.com/klauspost/cpuid/v2/README.md @@ -2,7 +2,7 @@ Package cpuid provides information about the CPU running the current program. CPU features are detected on startup, and kept for fast access through the life of the application. -Currently x86 / x64 (AMD64/i386) and ARM (ARM64) is supported, and no external C (cgo) code is used, which should make the library very easy to use. +Currently x86 / x64 (AMD64/i386), ARM (ARM64), and RISC-V (RV64) are supported, and no external C (cgo) code is used, which should make the library very easy to use. You can access the CPU information by accessing the shared CPU variable of the cpuid library. @@ -506,6 +506,74 @@ Exit Code 1 | SM3 | SM3 instructions | | SM4 | SM4 instructions | | SVE | Scalable Vector Extension | +| SVE2 | Scalable Vector Extension 2 | +| SB | Speculation barrier (SB instruction) | +| SSBS | Speculative Store Bypass Safe (PSTATE.SSBS) | +| BTI | Branch Target Identification | +| FLAGM2 | Condition flag manipulation version 2 (AXFLAG, XAFLAG) | +| FRINTTS | Floating-point to integer rounding (FRINT32Z, FRINT64Z, etc) | +| DCPODP | Data cache clean to Point of Deep Persistence (DC CVADP) | +| BF16 | BFloat16 instructions (BFDOT, BFMMLA, etc) | +| I8MM | Int8 matrix multiplication (SMMLA, UMMLA, USMMLA) | +| WFXT | WFE/WFI with timeout (WFET, WFIT) | +| MOPS | Memory copy and set instructions (CPYF, SETP, etc) | +| HBC | Hinted conditional branches (BC.cond) | +| CSSC | Common short sequence compression (ABS, SMAX, UMAX, etc) | + +## riscv64 feature detection + +On `riscv64/linux`, CPU features are detected using the `riscv_hwprobe` syscall (Linux 6.4+). +For older kernels, detection falls back to parsing `/proc/cpuinfo` for the ISA string. + +Cache line size is detected via `riscv_hwprobe` (Zicbom block size) or sysfs fallback. +Other cache and topology information is not yet available. + +# RISC-V features: + +| Feature Flag | Description | +|----------------|----------------------------------------------------| +| RV_IMA | IMA base (Integer, Multiply, Atomic) | +| RV_C | Compressed instructions | +| RV_F | Single-precision FP | +| RV_D | Double-precision FP | +| RV_V | Vector extension (V) | +| RV_ZBA | Address generation | +| RV_ZBB | Basic bit manipulation | +| RV_ZBC | Carry-less multiplication | +| RV_ZBS | Single-bit manipulation | +| RV_ZICOND | Integer conditional operations | +| RV_ZIHINTPAUSE | Pause hint | +| RV_ZICBOM | Cache block management operations | +| RV_ZICBOZ | Cache block zero | +| RV_ZICBOP | Cache block prefetch | +| RV_ZFA | Additional floating-point | +| RV_ZFH | Half-precision FP | +| RV_ZFHMIN | Minimal half-precision FP | +| RV_ZTSO | Total store ordering | +| RV_ZACAS | Atomic CAS | +| RV_ZBKB | Bit-manipulation for crypto | +| RV_ZBKC | Carry-less multiply for crypto | +| RV_ZBKX | Crossbar permutations | +| RV_ZKND | NIST Suite: AES decrypt | +| RV_ZKNE | NIST Suite: AES encrypt | +| RV_ZKNH | NIST Suite: SHA-2 (SHA-256/SHA-512) | +| RV_ZKSED | ShangMi Suite: SM4 block cipher | +| RV_ZKSH | ShangMi Suite: SM3 hash | +| RV_ZKT | Data-independent execution latency (Crypto) | +| RV_ZKN | NIST Algorithm Suite (combined from individual) | +| RV_ZKS | ShangMi Algorithm Suite (combined from individual) | +| RV_ZVBB | Vector Basic Bit-manipulation | +| RV_ZVBC | Vector Carry-less multiply | +| RV_ZVKB | Vector Bit-manipulation for crypto | +| RV_ZVKG | Vector GCM/GMAC | +| RV_ZVKNED | NIST Suite: Vector AES encrypt+decrypt | +| RV_ZVKNHA | NIST Suite: Vector SHA-2 (SHA-256) | +| RV_ZVKNHB | NIST Suite: Vector SHA-2 (SHA-512) | +| RV_ZVKSED | ShangMi Suite: Vector SM4 | +| RV_ZVKSH | ShangMi Suite: Vector SM3 hash | +| RV_ZVKT | Vector Data-independent execution latency | +| RV_ZVKNG | NIST Suite with GCM (combined from individual) | +| RV_ZVKSG | ShangMi Suite with GCM (combined from individual) | # license diff --git a/vendor/github.com/klauspost/cpuid/v2/cpuid.go b/vendor/github.com/klauspost/cpuid/v2/cpuid.go index 9cf7738a97..db903f46a4 100644 --- a/vendor/github.com/klauspost/cpuid/v2/cpuid.go +++ b/vendor/github.com/klauspost/cpuid/v2/cpuid.go @@ -3,7 +3,7 @@ // Package cpuid provides information about the CPU running the current program. // // CPU features are detected on startup, and kept for fast access through the life of the application. -// Currently x86 / x64 (AMD64) as well as arm64 is supported. +// Currently x86 / x64 (AMD64), arm64, and riscv64 are supported. // // You can access the CPU information by accessing the shared CPU variable of the cpuid library. // @@ -17,6 +17,7 @@ import ( "math/bits" "os" "runtime" + "slices" "strings" ) @@ -61,6 +62,13 @@ const ( SRE Apple + // RISC-V vendors + SiFive + StarFive + THead + Andes + SpacemiT + lastVendor ) @@ -95,6 +103,7 @@ const ( AVX2 // AVX2 functions AVX512BF16 // AVX-512 BFLOAT16 Instructions AVX512BITALG // AVX-512 Bit Algorithms + AVX512BMM // AVX-512 Bit Manipulation Instructions AVX512BW // AVX-512 Byte and Word Instructions AVX512CD // AVX-512 Conflict Detection Instructions AVX512DQ // AVX-512 Doubleword and Quadword Instructions @@ -139,6 +148,7 @@ const ( FMA4 // Bulldozer FMA4 functions FP128 // AMD: When set, the internal FP/SIMD execution datapath is no more than 128-bits wide FP256 // AMD: When set, the internal FP/SIMD execution datapath is no more than 256-bits wide + FRED // Flexible Return and Event Delivery FSRM // Fast Short Rep Mov FXSR // FXSAVE, FXRESTOR instructions, CR4 bit 9 FXSROPT // FXSAVE/FXRSTOR optimizations @@ -308,6 +318,19 @@ const ( SM3 // SM3 instructions SM4 // SM4 instructions SVE // Scalable Vector Extension + SVE2 // Scalable Vector Extension 2 + SB // Speculation barrier (SB instruction) + SSBS // Speculative Store Bypass Safe (PSTATE.SSBS) + BTI // Branch Target Identification + FLAGM2 // Condition flag manipulation version 2 (AXFLAG, XAFLAG) + FRINTTS // Floating-point to integer rounding (FRINT32Z, FRINT64Z, etc) + DCPODP // Data cache clean to Point of Deep Persistence (DC CVADP) + BF16 // BFloat16 instructions (BFDOT, BFMMLA, etc) + I8MM // Int8 matrix multiplication (SMMLA, UMMLA, USMMLA) + WFXT // WFE/WFI with timeout (WFET, WFIT) + MOPS // Memory copy and set instructions (CPYF, SETP, etc) + HBC // Hinted conditional branches (BC.cond) + CSSC // Common short sequence compression (ABS, SMAX, UMAX, etc) // PMU PMU_FIXEDCOUNTER_CYCLES @@ -315,6 +338,57 @@ const ( PMU_FIXEDCOUNTER_INSTRUCTIONS PMU_FIXEDCOUNTER_TOPDOWN_SLOTS + // RISC-V features + RV_IMA // IMA base (Integer, Multiply, Atomic) + RV_C // Compressed instructions + RV_F // Single-precision FP + RV_D // Double-precision FP + RV_V // Vector extension (V) + RV_ZBA // Address generation + RV_ZBB // Basic bit manipulation + RV_ZBC // Carry-less multiplication + RV_ZBS // Single-bit manipulation + RV_ZICOND // Integer conditional operations + RV_ZIHINTPAUSE // Pause hint + RV_ZICBOM // Cache block management operations + RV_ZICBOZ // Cache block zero + RV_ZICBOP // Cache block prefetch + RV_ZFA // Additional floating-point + RV_ZFH // Half-precision FP + RV_ZFHMIN // Minimal half-precision FP + RV_ZTSO // Total store ordering + RV_ZACAS // Atomic CAS + // Scalar cryptography + RV_ZBKB // Bit-manipulation for crypto + RV_ZBKC // Carry-less multiply for crypto + RV_ZBKX // Crossbar permutations + RV_ZKND // NIST Suite: AES decrypt + RV_ZKNE // NIST Suite: AES encrypt + RV_ZKNH // NIST Suite: SHA-2 (SHA-256/SHA-512) + RV_ZKSED // ShangMi Suite: SM4 block cipher + RV_ZKSH // ShangMi Suite: SM3 hash + RV_ZKT // Data-independent execution latency (Crypto) + + // Scalar crypto suites (combined from individual extensions) + RV_ZKN // NIST Algorithm Suite (Zknd+Zkne+Zknh+Zbkb+Zbkc+Zbkx+Zkt) + RV_ZKS // ShangMi Algorithm Suite (Zksed+Zksh+Zbkb+Zbkc+Zbkx+Zkt) + + // Vector cryptography + RV_ZVBB // Vector Basic Bit-manipulation + RV_ZVBC // Vector Carry-less multiply + RV_ZVKB // Vector Bit-manipulation for crypto + RV_ZVKG // Vector GCM/GMAC + RV_ZVKNED // NIST Suite: Vector AES encrypt+decrypt + RV_ZVKNHA // NIST Suite: Vector SHA-2 (SHA-256) + RV_ZVKNHB // NIST Suite: Vector SHA-2 (SHA-512) + RV_ZVKSED // ShangMi Suite: Vector SM4 + RV_ZVKSH // ShangMi Suite: Vector SM3 hash + RV_ZVKT // Vector Data-independent execution latency + + // Vector crypto suites (combined from individual extensions) + RV_ZVKNG // NIST Suite with GCM (Zvkned+Zvknhb+Zvkg+Zvkb+Zvkt) + RV_ZVKSG // ShangMi Suite with GCM (Zvksed+Zvksh+Zvkg+Zvkb+Zvkt) + // Keep it last. It automatically defines the size of []flagSet lastID @@ -419,8 +493,8 @@ func Detect() { os.Exit(1) } if disableFlag != nil { - s := strings.Split(*disableFlag, ",") - for _, feat := range s { + s := strings.SplitSeq(*disableFlag, ",") + for feat := range s { feat := ParseFeature(strings.TrimSpace(feat)) if feat != UNKNOWN { CPU.featureSet.unset(feat) @@ -471,12 +545,7 @@ func (c *CPUInfo) Has(id FeatureID) bool { // AnyOf returns whether the CPU supports one or more of the requested features. func (c CPUInfo) AnyOf(ids ...FeatureID) bool { - for _, id := range ids { - if c.featureSet.inSet(id) { - return true - } - } - return false + return slices.ContainsFunc(ids, c.featureSet.inSet) } // Features contains several features combined for a fast check using @@ -496,6 +565,11 @@ func (c *CPUInfo) HasAll(f Features) bool { return c.featureSet.hasSetP(f) } +// HasOneOf returns whether the CPU supports one or more of the requested features. +func (c *CPUInfo) HasOneOf(f Features) bool { + return c.featureSet.hasOneOf(f) +} + // https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels var oneOfLevel = CombineFeatures(SYSEE, SYSCALL) var level1Features = CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SSE, SSE2) @@ -503,6 +577,56 @@ var level2Features = CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SSE, SSE2, var level3Features = CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3, AVX, AVX2, BMI1, BMI2, F16C, FMA3, LZCNT, MOVBE, OSXSAVE) var level4Features = CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3, AVX, AVX2, BMI1, BMI2, F16C, FMA3, LZCNT, MOVBE, OSXSAVE, AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL) +// RV_CRYPTO_FEATS contains all RISC-V scalar cryptography instruction extensions (excludes Zkt since it is a timing guarantee, not a computational instruction). +var RV_CRYPTO_FEATS = CombineFeatures(RV_ZBKB, RV_ZBKC, RV_ZBKX, RV_ZKND, RV_ZKNE, RV_ZKNH, RV_ZKSED, RV_ZKSH) + +// RV_VECTOR_CRYPTO_FEATS contains all RISC-V vector cryptography extensions. +var RV_VECTOR_CRYPTO_FEATS = CombineFeatures(RV_ZVBB, RV_ZVBC, RV_ZVKB, RV_ZVKG, RV_ZVKNED, RV_ZVKNHA, RV_ZVKNHB, RV_ZVKSED, RV_ZVKSH) + +// RISC-V application profile feature sets. +// https://github.com/riscv/riscv-profiles +var rvProfile20Features = CombineFeatures(RV_IMA, RV_C, RV_F, RV_D) +var rvProfile22Features = CombineFeatures(RV_IMA, RV_C, RV_F, RV_D, RV_ZBA, RV_ZBB, RV_ZBS, RV_ZFHMIN, RV_ZICBOM, RV_ZICBOP, RV_ZICBOZ, RV_ZIHINTPAUSE) +var rvProfile23Features = CombineFeatures(RV_IMA, RV_C, RV_F, RV_D, RV_ZBA, RV_ZBB, RV_ZBS, RV_ZFHMIN, RV_ZICBOM, RV_ZICBOP, RV_ZICBOZ, RV_ZIHINTPAUSE, RV_V, RV_ZFA, RV_ZICOND, RV_ZVBB, RV_ZVKB) + +// RISC-V crypto suites — combined from individual extensions. +var rvZKNFeatures = CombineFeatures(RV_ZKND, RV_ZKNE, RV_ZKNH, RV_ZBKB, RV_ZBKC, RV_ZBKX, RV_ZKT) +var rvZKSFeatures = CombineFeatures(RV_ZKSED, RV_ZKSH, RV_ZBKB, RV_ZBKC, RV_ZBKX, RV_ZKT) +var rvZVKNFeatures = CombineFeatures(RV_ZVKNED, RV_ZVKNHB, RV_ZVKG, RV_ZVKB, RV_ZVKT) +var rvZVKSFeatures = CombineFeatures(RV_ZVKSED, RV_ZVKSH, RV_ZVKG, RV_ZVKB, RV_ZVKT) + +// ARM64 architecture levels. armV8Levels[m] is the cumulative set of mandatory +// user-space instruction features added up to and including ARMv8.m that this +// package can detect. EL1/system-only features (PAN, VHE, CSV2/CSV3, ECV, ...) +// are excluded since they are irrelevant to user-space code generation, exactly +// as X64Level ignores non-instruction features. +// +// FEAT_SSBS and FEAT_BTI, although mandatory from ARMv8.5, are intentionally NOT +// required. Both are OS-policy-gated security features (speculative store bypass +// safety and branch-target identification) that Go code generation never depends +// on: their HWCAP/sysctl bits are set only when the OS or hypervisor enables the +// protection, not purely from CPU capability, so they are routinely hidden even +// on capable silicon (neither a Neoverse N2 Linux guest nor Apple Silicon reports +// them). Requiring them would cap such CPUs at v8.4. Both are still detected and +// reported through FeatureSet when present. +// https://go.dev/wiki/MinimumRequirements#arm64 +var armV8Levels = [...]Features{ + CombineFeatures(FP, ASIMD), // v8.0 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM), // v8.1 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM, DCPOP), // v8.2 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM, DCPOP, JSCVT, FCMA, LRCPC), // v8.3 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM, DCPOP, JSCVT, FCMA, LRCPC, TS), // v8.4 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM, DCPOP, JSCVT, FCMA, LRCPC, TS, SB, FRINTTS, FLAGM2, DCPODP), // v8.5 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM, DCPOP, JSCVT, FCMA, LRCPC, TS, SB, FRINTTS, FLAGM2, DCPODP, BF16, I8MM), // v8.6 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM, DCPOP, JSCVT, FCMA, LRCPC, TS, SB, FRINTTS, FLAGM2, DCPODP, BF16, I8MM, WFXT), // v8.7 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM, DCPOP, JSCVT, FCMA, LRCPC, TS, SB, FRINTTS, FLAGM2, DCPODP, BF16, I8MM, WFXT, MOPS, HBC), // v8.8 + CombineFeatures(FP, ASIMD, ATOMICS, CRC32, ASIMDRDM, DCPOP, JSCVT, FCMA, LRCPC, TS, SB, FRINTTS, FLAGM2, DCPODP, BF16, I8MM, WFXT, MOPS, HBC, CSSC), // v8.9 +} + +// armCrypto matches the GOARM64 ",crypto" option: FEAT_AES, FEAT_PMULL, +// FEAT_SHA1 and FEAT_SHA256. +var armCrypto = CombineFeatures(AESARM, PMULL, SHA1, SHA2) + // X64Level returns the microarchitecture level detected on the CPU. // If features are lacking or non x64 mode, 0 is returned. // See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels @@ -525,6 +649,67 @@ func (c CPUInfo) X64Level() int { return 0 } +// RVProfile returns the RISC-V application profile level. +// 0 = unknown / base ISA only, 20 = RVA20, 22 = RVA22, 23 = RVA23. +// Returns 0 on non-RISC-V architectures or if not detected. +// https://github.com/riscv/riscv-profiles +func (c CPUInfo) RVProfile() int { + switch { + case c.featureSet.hasSetP(rvProfile23Features): + return 23 + case c.featureSet.hasSetP(rvProfile22Features): + return 22 + case c.featureSet.hasSetP(rvProfile20Features): + return 20 + default: + return 0 + } +} + +// ARM64Level returns the ARMv8/ARMv9 architecture version supported by the CPU +// as (major, minor), e.g. 8, 4 for ARMv8.4-A or 9, 0 for ARMv9.0-A. +// Only mandatory user-space instruction features are considered, so the result +// is the highest level whose required instructions are all present. +// Returns 0, 0 on non-arm64 CPUs or when feature detection was unavailable. +func (c CPUInfo) ARM64Level() (major, minor int) { + if !c.featureSet.hasSetP(armV8Levels[0]) { + return 0, 0 + } + m8 := 0 + for m := len(armV8Levels) - 1; m >= 1; m-- { + if c.featureSet.hasSetP(armV8Levels[m]) { + m8 = m + break + } + } + // ARMv9.x mandates everything in ARMv8.(x+5) plus SVE2. + if m8 >= 5 && c.featureSet.inSet(SVE2) { + return 9, m8 - 5 + } + return 8, m8 +} + +// GOARM64 returns a value usable as the GOARM64 build setting for the detected +// CPU, e.g. "v8.4" or "v9.0,crypto". The ",crypto" suffix is appended when AES, +// PMULL, SHA1 and SHA256 are all present; the ",lse" suffix is appended in the +// rare case LSE is present without the rest of the ARMv8.1 feature set. +// Returns "" on non-arm64 CPUs or when feature detection was unavailable. +// See https://go.dev/wiki/MinimumRequirements#arm64 +func (c CPUInfo) GOARM64() string { + major, minor := c.ARM64Level() + if major == 0 { + return "" + } + v := fmt.Sprintf("v%d.%d", major, minor) + if major == 8 && minor == 0 && c.featureSet.inSet(ATOMICS) { + v += ",lse" + } + if c.featureSet.hasSetP(armCrypto) { + v += ",crypto" + } + return v +} + // Disable will disable one or several features. func (c *CPUInfo) Disable(ids ...FeatureID) bool { for _, id := range ids { @@ -771,7 +956,7 @@ func flagSetWith(feat ...FeatureID) flagSet { // Will return UNKNOWN if not found. func ParseFeature(s string) FeatureID { s = strings.ToUpper(s) - for i := firstID; i < lastID; i++ { + for i := range lastID { if i.String() == s { return i } @@ -785,7 +970,7 @@ func (s flagSet) Strings() []string { return []string{""} } r := make([]string, 0) - for i := firstID; i < lastID; i++ { + for i := range lastID { if s.inSet(i) { r = append(r, i.String()) } @@ -806,7 +991,7 @@ func maxFunctionID() uint32 { func brandName() string { if maxExtendedFunction() >= 0x80000004 { v := make([]uint32, 0, 48) - for i := uint32(0); i < 3; i++ { + for i := range uint32(3) { a, b, c, d := cpuid(0x80000002 + i) v = append(v, a, b, c, d) } @@ -1075,7 +1260,7 @@ func (c *CPUInfo) cacheSize() { // Hack: When we encounter the same entry 100 times we break. nSame := 0 var last uint32 - for i := uint32(0); i < math.MaxUint32; i++ { + for i := range uint32(math.MaxUint32) { eax, ebx, ecx, _ := cpuidex(0x8000001D, i) level := (eax >> 5) & 7 @@ -1329,6 +1514,7 @@ func support() flagSet { fs.setIf(eax1&(1<<10) != 0, MOVSB_ZL) fs.setIf(eax1&(1<<11) != 0, STOSB_SHORT) fs.setIf(eax1&(1<<12) != 0, CMPSB_SCADBS_SHORT) + fs.setIf(eax1&(1<<17) != 0, FRED) fs.setIf(eax1&(1<<22) != 0, HRESET) fs.setIf(eax1&(1<<23) != 0, AVXIFMA) fs.setIf(eax1&(1<<26) != 0, LAM) @@ -1562,6 +1748,7 @@ func support() flagSet { fs.setIf((a>>29)&1 == 1, SRSO_NO) fs.setIf((a>>28)&1 == 1, IBPB_BRTYPE) fs.setIf((a>>27)&1 == 1, SBPB) + fs.setIf((a>>23)&1 == 1, AVX512BMM) fs.setIf((c>>1)&1 == 1, TSA_L1_NO) fs.setIf((c>>2)&1 == 1, TSA_SQ_NO) fs.setIf((a>>5)&1 == 1, TSA_VERW_CLEAR) diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go b/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go index 9ae32d607d..e615b10be7 100644 --- a/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go +++ b/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go @@ -1,7 +1,6 @@ // Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. //go:build arm64 && !gccgo && !noasm && !appengine -// +build arm64,!gccgo,!noasm,!appengine package cpuid @@ -189,6 +188,7 @@ func addInfo(c *CPUInfo, safe bool) { f.setIf(instAttrReg0&(0xf<<60) != 0, RNDR) f.setIf(instAttrReg0&(0xf<<56) != 0, TLB) f.setIf(instAttrReg0&(0xf<<52) != 0, TS) + f.setIf(instAttrReg0&(0xf<<52) == 2<<52, FLAGM2) // TS == 0b0010 (FEAT_FlagM2) f.setIf(instAttrReg0&(0xf<<48) != 0, FHM) f.setIf(instAttrReg0&(0xf<<44) != 0, ASIMDDP) f.setIf(instAttrReg0&(0xf<<40) != 0, SM4) @@ -244,6 +244,13 @@ func addInfo(c *CPUInfo, safe bool) { // fmt.Println("APA") // } f.setIf(instAttrReg1&(0xf<<0) != 0, DCPOP) + f.setIf(instAttrReg1&(0xf<<0) == 2<<0, DCPODP) // DPB == 0b0010 (FEAT_DPB2) + + // Upper ID_AA64ISAR1_EL1 fields, not in the table above. + f.setIf(instAttrReg1&(0xf<<32) != 0, FRINTTS) // bits [35:32] + f.setIf(instAttrReg1&(0xf<<36) != 0, SB) // bits [39:36] + f.setIf(instAttrReg1&(0xf<<44) != 0, BF16) // bits [47:44] + f.setIf(instAttrReg1&(0xf<<52) != 0, I8MM) // bits [55:52] // Store c.featureSet.or(f) diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_ref.go b/vendor/github.com/klauspost/cpuid/v2/detect_ref.go index 574f9389c0..38699f4d78 100644 --- a/vendor/github.com/klauspost/cpuid/v2/detect_ref.go +++ b/vendor/github.com/klauspost/cpuid/v2/detect_ref.go @@ -1,7 +1,6 @@ // Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. -//go:build (!amd64 && !386 && !arm64) || gccgo || noasm || appengine -// +build !amd64,!386,!arm64 gccgo noasm appengine +//go:build (!amd64 && !386 && !arm64 && !riscv64) || ((amd64 || 386) && (gccgo || noasm || appengine)) package cpuid diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_ref_arm64.go b/vendor/github.com/klauspost/cpuid/v2/detect_ref_arm64.go new file mode 100644 index 0000000000..d2ea76ba82 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/v2/detect_ref_arm64.go @@ -0,0 +1,19 @@ +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +//go:build arm64 && (gccgo || noasm || appengine) + +package cpuid + +func initCPU() { + cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } + cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } + xgetbv = func(uint32) (a, b uint32) { return 0, 0 } + rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 } +} + +func addInfo(c *CPUInfo, safe bool) { + c.CacheLine = 64 + detectOS(c) +} + +func getVectorLength() (vl, pl uint64) { return 0, 0 } diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_riscv64.go b/vendor/github.com/klauspost/cpuid/v2/detect_riscv64.go new file mode 100644 index 0000000000..25381f0898 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/v2/detect_riscv64.go @@ -0,0 +1,16 @@ +// Copyright (c) 2026 Klaus Post, released under MIT License. See LICENSE file. + +package cpuid + +func getVectorLength() (vl, pl uint64) { return 0, 0 } + +func initCPU() { + cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } + cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } + xgetbv = func(uint32) (a, b uint32) { return 0, 0 } + rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 } +} + +func addInfo(c *CPUInfo, safe bool) { + detectOS(c) +} diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_x86.go b/vendor/github.com/klauspost/cpuid/v2/detect_x86.go index 14a56b9301..22819ce4a9 100644 --- a/vendor/github.com/klauspost/cpuid/v2/detect_x86.go +++ b/vendor/github.com/klauspost/cpuid/v2/detect_x86.go @@ -1,7 +1,6 @@ // Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. //go:build (386 && !gccgo && !noasm && !appengine) || (amd64 && !gccgo && !noasm && !appengine) -// +build 386,!gccgo,!noasm,!appengine amd64,!gccgo,!noasm,!appengine package cpuid diff --git a/vendor/github.com/klauspost/cpuid/v2/featureid_string.go b/vendor/github.com/klauspost/cpuid/v2/featureid_string.go index 2888bae8fa..f88ead1308 100644 --- a/vendor/github.com/klauspost/cpuid/v2/featureid_string.go +++ b/vendor/github.com/klauspost/cpuid/v2/featureid_string.go @@ -29,234 +29,292 @@ func _() { _ = x[AVX2-19] _ = x[AVX512BF16-20] _ = x[AVX512BITALG-21] - _ = x[AVX512BW-22] - _ = x[AVX512CD-23] - _ = x[AVX512DQ-24] - _ = x[AVX512ER-25] - _ = x[AVX512F-26] - _ = x[AVX512FP16-27] - _ = x[AVX512IFMA-28] - _ = x[AVX512PF-29] - _ = x[AVX512VBMI-30] - _ = x[AVX512VBMI2-31] - _ = x[AVX512VL-32] - _ = x[AVX512VNNI-33] - _ = x[AVX512VP2INTERSECT-34] - _ = x[AVX512VPOPCNTDQ-35] - _ = x[AVXIFMA-36] - _ = x[AVXNECONVERT-37] - _ = x[AVXSLOW-38] - _ = x[AVXVNNI-39] - _ = x[AVXVNNIINT8-40] - _ = x[AVXVNNIINT16-41] - _ = x[BHI_CTRL-42] - _ = x[BMI1-43] - _ = x[BMI2-44] - _ = x[CETIBT-45] - _ = x[CETSS-46] - _ = x[CLDEMOTE-47] - _ = x[CLMUL-48] - _ = x[CLZERO-49] - _ = x[CMOV-50] - _ = x[CMPCCXADD-51] - _ = x[CMPSB_SCADBS_SHORT-52] - _ = x[CMPXCHG8-53] - _ = x[CPBOOST-54] - _ = x[CPPC-55] - _ = x[CX16-56] - _ = x[EFER_LMSLE_UNS-57] - _ = x[ENQCMD-58] - _ = x[ERMS-59] - _ = x[F16C-60] - _ = x[FLUSH_L1D-61] - _ = x[FMA3-62] - _ = x[FMA4-63] - _ = x[FP128-64] - _ = x[FP256-65] - _ = x[FSRM-66] - _ = x[FXSR-67] - _ = x[FXSROPT-68] - _ = x[GFNI-69] - _ = x[HLE-70] - _ = x[HRESET-71] - _ = x[HTT-72] - _ = x[HWA-73] - _ = x[HYBRID_CPU-74] - _ = x[HYPERVISOR-75] - _ = x[IA32_ARCH_CAP-76] - _ = x[IA32_CORE_CAP-77] - _ = x[IBPB-78] - _ = x[IBPB_BRTYPE-79] - _ = x[IBRS-80] - _ = x[IBRS_PREFERRED-81] - _ = x[IBRS_PROVIDES_SMP-82] - _ = x[IBS-83] - _ = x[IBSBRNTRGT-84] - _ = x[IBSFETCHSAM-85] - _ = x[IBSFFV-86] - _ = x[IBSOPCNT-87] - _ = x[IBSOPCNTEXT-88] - _ = x[IBSOPSAM-89] - _ = x[IBSRDWROPCNT-90] - _ = x[IBSRIPINVALIDCHK-91] - _ = x[IBS_FETCH_CTLX-92] - _ = x[IBS_OPDATA4-93] - _ = x[IBS_OPFUSE-94] - _ = x[IBS_PREVENTHOST-95] - _ = x[IBS_ZEN4-96] - _ = x[IDPRED_CTRL-97] - _ = x[INT_WBINVD-98] - _ = x[INVLPGB-99] - _ = x[KEYLOCKER-100] - _ = x[KEYLOCKERW-101] - _ = x[LAHF-102] - _ = x[LAM-103] - _ = x[LBRVIRT-104] - _ = x[LZCNT-105] - _ = x[MCAOVERFLOW-106] - _ = x[MCDT_NO-107] - _ = x[MCOMMIT-108] - _ = x[MD_CLEAR-109] - _ = x[MMX-110] - _ = x[MMXEXT-111] - _ = x[MOVBE-112] - _ = x[MOVDIR64B-113] - _ = x[MOVDIRI-114] - _ = x[MOVSB_ZL-115] - _ = x[MOVU-116] - _ = x[MPX-117] - _ = x[MSRIRC-118] - _ = x[MSRLIST-119] - _ = x[MSR_PAGEFLUSH-120] - _ = x[NRIPS-121] - _ = x[NX-122] - _ = x[OSXSAVE-123] - _ = x[PCONFIG-124] - _ = x[POPCNT-125] - _ = x[PPIN-126] - _ = x[PREFETCHI-127] - _ = x[PSFD-128] - _ = x[RDPRU-129] - _ = x[RDRAND-130] - _ = x[RDSEED-131] - _ = x[RDTSCP-132] - _ = x[RRSBA_CTRL-133] - _ = x[RTM-134] - _ = x[RTM_ALWAYS_ABORT-135] - _ = x[SBPB-136] - _ = x[SERIALIZE-137] - _ = x[SEV-138] - _ = x[SEV_64BIT-139] - _ = x[SEV_ALTERNATIVE-140] - _ = x[SEV_DEBUGSWAP-141] - _ = x[SEV_ES-142] - _ = x[SEV_RESTRICTED-143] - _ = x[SEV_SNP-144] - _ = x[SGX-145] - _ = x[SGXLC-146] - _ = x[SGXPQC-147] - _ = x[SHA-148] - _ = x[SME-149] - _ = x[SME_COHERENT-150] - _ = x[SM3_X86-151] - _ = x[SM4_X86-152] - _ = x[SPEC_CTRL_SSBD-153] - _ = x[SRBDS_CTRL-154] - _ = x[SRSO_MSR_FIX-155] - _ = x[SRSO_NO-156] - _ = x[SRSO_USER_KERNEL_NO-157] - _ = x[SSE-158] - _ = x[SSE2-159] - _ = x[SSE3-160] - _ = x[SSE4-161] - _ = x[SSE42-162] - _ = x[SSE4A-163] - _ = x[SSSE3-164] - _ = x[STIBP-165] - _ = x[STIBP_ALWAYSON-166] - _ = x[STOSB_SHORT-167] - _ = x[SUCCOR-168] - _ = x[SVM-169] - _ = x[SVMDA-170] - _ = x[SVMFBASID-171] - _ = x[SVML-172] - _ = x[SVMNP-173] - _ = x[SVMPF-174] - _ = x[SVMPFT-175] - _ = x[SYSCALL-176] - _ = x[SYSEE-177] - _ = x[TBM-178] - _ = x[TDX_GUEST-179] - _ = x[TLB_FLUSH_NESTED-180] - _ = x[TME-181] - _ = x[TOPEXT-182] - _ = x[TSA_L1_NO-183] - _ = x[TSA_SQ_NO-184] - _ = x[TSA_VERW_CLEAR-185] - _ = x[TSCRATEMSR-186] - _ = x[TSXLDTRK-187] - _ = x[VAES-188] - _ = x[VMCBCLEAN-189] - _ = x[VMPL-190] - _ = x[VMSA_REGPROT-191] - _ = x[VMX-192] - _ = x[VPCLMULQDQ-193] - _ = x[VTE-194] - _ = x[WAITPKG-195] - _ = x[WBNOINVD-196] - _ = x[WRMSRNS-197] - _ = x[X87-198] - _ = x[XGETBV1-199] - _ = x[XOP-200] - _ = x[XSAVE-201] - _ = x[XSAVEC-202] - _ = x[XSAVEOPT-203] - _ = x[XSAVES-204] - _ = x[AESARM-205] - _ = x[ARMCPUID-206] - _ = x[ASIMD-207] - _ = x[ASIMDDP-208] - _ = x[ASIMDHP-209] - _ = x[ASIMDRDM-210] - _ = x[ATOMICS-211] - _ = x[CRC32-212] - _ = x[DCPOP-213] - _ = x[EVTSTRM-214] - _ = x[FCMA-215] - _ = x[FHM-216] - _ = x[FP-217] - _ = x[FPHP-218] - _ = x[GPA-219] - _ = x[JSCVT-220] - _ = x[LRCPC-221] - _ = x[PMULL-222] - _ = x[RNDR-223] - _ = x[TLB-224] - _ = x[TS-225] - _ = x[SHA1-226] - _ = x[SHA2-227] - _ = x[SHA3-228] - _ = x[SHA512-229] - _ = x[SM3-230] - _ = x[SM4-231] - _ = x[SVE-232] - _ = x[PMU_FIXEDCOUNTER_CYCLES-233] - _ = x[PMU_FIXEDCOUNTER_REFCYCLES-234] - _ = x[PMU_FIXEDCOUNTER_INSTRUCTIONS-235] - _ = x[PMU_FIXEDCOUNTER_TOPDOWN_SLOTS-236] - _ = x[lastID-237] + _ = x[AVX512BMM-22] + _ = x[AVX512BW-23] + _ = x[AVX512CD-24] + _ = x[AVX512DQ-25] + _ = x[AVX512ER-26] + _ = x[AVX512F-27] + _ = x[AVX512FP16-28] + _ = x[AVX512IFMA-29] + _ = x[AVX512PF-30] + _ = x[AVX512VBMI-31] + _ = x[AVX512VBMI2-32] + _ = x[AVX512VL-33] + _ = x[AVX512VNNI-34] + _ = x[AVX512VP2INTERSECT-35] + _ = x[AVX512VPOPCNTDQ-36] + _ = x[AVXIFMA-37] + _ = x[AVXNECONVERT-38] + _ = x[AVXSLOW-39] + _ = x[AVXVNNI-40] + _ = x[AVXVNNIINT8-41] + _ = x[AVXVNNIINT16-42] + _ = x[BHI_CTRL-43] + _ = x[BMI1-44] + _ = x[BMI2-45] + _ = x[CETIBT-46] + _ = x[CETSS-47] + _ = x[CLDEMOTE-48] + _ = x[CLMUL-49] + _ = x[CLZERO-50] + _ = x[CMOV-51] + _ = x[CMPCCXADD-52] + _ = x[CMPSB_SCADBS_SHORT-53] + _ = x[CMPXCHG8-54] + _ = x[CPBOOST-55] + _ = x[CPPC-56] + _ = x[CX16-57] + _ = x[EFER_LMSLE_UNS-58] + _ = x[ENQCMD-59] + _ = x[ERMS-60] + _ = x[F16C-61] + _ = x[FLUSH_L1D-62] + _ = x[FMA3-63] + _ = x[FMA4-64] + _ = x[FP128-65] + _ = x[FP256-66] + _ = x[FRED-67] + _ = x[FSRM-68] + _ = x[FXSR-69] + _ = x[FXSROPT-70] + _ = x[GFNI-71] + _ = x[HLE-72] + _ = x[HRESET-73] + _ = x[HTT-74] + _ = x[HWA-75] + _ = x[HYBRID_CPU-76] + _ = x[HYPERVISOR-77] + _ = x[IA32_ARCH_CAP-78] + _ = x[IA32_CORE_CAP-79] + _ = x[IBPB-80] + _ = x[IBPB_BRTYPE-81] + _ = x[IBRS-82] + _ = x[IBRS_PREFERRED-83] + _ = x[IBRS_PROVIDES_SMP-84] + _ = x[IBS-85] + _ = x[IBSBRNTRGT-86] + _ = x[IBSFETCHSAM-87] + _ = x[IBSFFV-88] + _ = x[IBSOPCNT-89] + _ = x[IBSOPCNTEXT-90] + _ = x[IBSOPSAM-91] + _ = x[IBSRDWROPCNT-92] + _ = x[IBSRIPINVALIDCHK-93] + _ = x[IBS_FETCH_CTLX-94] + _ = x[IBS_OPDATA4-95] + _ = x[IBS_OPFUSE-96] + _ = x[IBS_PREVENTHOST-97] + _ = x[IBS_ZEN4-98] + _ = x[IDPRED_CTRL-99] + _ = x[INT_WBINVD-100] + _ = x[INVLPGB-101] + _ = x[KEYLOCKER-102] + _ = x[KEYLOCKERW-103] + _ = x[LAHF-104] + _ = x[LAM-105] + _ = x[LBRVIRT-106] + _ = x[LZCNT-107] + _ = x[MCAOVERFLOW-108] + _ = x[MCDT_NO-109] + _ = x[MCOMMIT-110] + _ = x[MD_CLEAR-111] + _ = x[MMX-112] + _ = x[MMXEXT-113] + _ = x[MOVBE-114] + _ = x[MOVDIR64B-115] + _ = x[MOVDIRI-116] + _ = x[MOVSB_ZL-117] + _ = x[MOVU-118] + _ = x[MPX-119] + _ = x[MSRIRC-120] + _ = x[MSRLIST-121] + _ = x[MSR_PAGEFLUSH-122] + _ = x[NRIPS-123] + _ = x[NX-124] + _ = x[OSXSAVE-125] + _ = x[PCONFIG-126] + _ = x[POPCNT-127] + _ = x[PPIN-128] + _ = x[PREFETCHI-129] + _ = x[PSFD-130] + _ = x[RDPRU-131] + _ = x[RDRAND-132] + _ = x[RDSEED-133] + _ = x[RDTSCP-134] + _ = x[RRSBA_CTRL-135] + _ = x[RTM-136] + _ = x[RTM_ALWAYS_ABORT-137] + _ = x[SBPB-138] + _ = x[SERIALIZE-139] + _ = x[SEV-140] + _ = x[SEV_64BIT-141] + _ = x[SEV_ALTERNATIVE-142] + _ = x[SEV_DEBUGSWAP-143] + _ = x[SEV_ES-144] + _ = x[SEV_RESTRICTED-145] + _ = x[SEV_SNP-146] + _ = x[SGX-147] + _ = x[SGXLC-148] + _ = x[SGXPQC-149] + _ = x[SHA-150] + _ = x[SME-151] + _ = x[SME_COHERENT-152] + _ = x[SM3_X86-153] + _ = x[SM4_X86-154] + _ = x[SPEC_CTRL_SSBD-155] + _ = x[SRBDS_CTRL-156] + _ = x[SRSO_MSR_FIX-157] + _ = x[SRSO_NO-158] + _ = x[SRSO_USER_KERNEL_NO-159] + _ = x[SSE-160] + _ = x[SSE2-161] + _ = x[SSE3-162] + _ = x[SSE4-163] + _ = x[SSE42-164] + _ = x[SSE4A-165] + _ = x[SSSE3-166] + _ = x[STIBP-167] + _ = x[STIBP_ALWAYSON-168] + _ = x[STOSB_SHORT-169] + _ = x[SUCCOR-170] + _ = x[SVM-171] + _ = x[SVMDA-172] + _ = x[SVMFBASID-173] + _ = x[SVML-174] + _ = x[SVMNP-175] + _ = x[SVMPF-176] + _ = x[SVMPFT-177] + _ = x[SYSCALL-178] + _ = x[SYSEE-179] + _ = x[TBM-180] + _ = x[TDX_GUEST-181] + _ = x[TLB_FLUSH_NESTED-182] + _ = x[TME-183] + _ = x[TOPEXT-184] + _ = x[TSA_L1_NO-185] + _ = x[TSA_SQ_NO-186] + _ = x[TSA_VERW_CLEAR-187] + _ = x[TSCRATEMSR-188] + _ = x[TSXLDTRK-189] + _ = x[VAES-190] + _ = x[VMCBCLEAN-191] + _ = x[VMPL-192] + _ = x[VMSA_REGPROT-193] + _ = x[VMX-194] + _ = x[VPCLMULQDQ-195] + _ = x[VTE-196] + _ = x[WAITPKG-197] + _ = x[WBNOINVD-198] + _ = x[WRMSRNS-199] + _ = x[X87-200] + _ = x[XGETBV1-201] + _ = x[XOP-202] + _ = x[XSAVE-203] + _ = x[XSAVEC-204] + _ = x[XSAVEOPT-205] + _ = x[XSAVES-206] + _ = x[AESARM-207] + _ = x[ARMCPUID-208] + _ = x[ASIMD-209] + _ = x[ASIMDDP-210] + _ = x[ASIMDHP-211] + _ = x[ASIMDRDM-212] + _ = x[ATOMICS-213] + _ = x[CRC32-214] + _ = x[DCPOP-215] + _ = x[EVTSTRM-216] + _ = x[FCMA-217] + _ = x[FHM-218] + _ = x[FP-219] + _ = x[FPHP-220] + _ = x[GPA-221] + _ = x[JSCVT-222] + _ = x[LRCPC-223] + _ = x[PMULL-224] + _ = x[RNDR-225] + _ = x[TLB-226] + _ = x[TS-227] + _ = x[SHA1-228] + _ = x[SHA2-229] + _ = x[SHA3-230] + _ = x[SHA512-231] + _ = x[SM3-232] + _ = x[SM4-233] + _ = x[SVE-234] + _ = x[SVE2-235] + _ = x[SB-236] + _ = x[SSBS-237] + _ = x[BTI-238] + _ = x[FLAGM2-239] + _ = x[FRINTTS-240] + _ = x[DCPODP-241] + _ = x[BF16-242] + _ = x[I8MM-243] + _ = x[WFXT-244] + _ = x[MOPS-245] + _ = x[HBC-246] + _ = x[CSSC-247] + _ = x[PMU_FIXEDCOUNTER_CYCLES-248] + _ = x[PMU_FIXEDCOUNTER_REFCYCLES-249] + _ = x[PMU_FIXEDCOUNTER_INSTRUCTIONS-250] + _ = x[PMU_FIXEDCOUNTER_TOPDOWN_SLOTS-251] + _ = x[RV_IMA-252] + _ = x[RV_C-253] + _ = x[RV_F-254] + _ = x[RV_D-255] + _ = x[RV_V-256] + _ = x[RV_ZBA-257] + _ = x[RV_ZBB-258] + _ = x[RV_ZBC-259] + _ = x[RV_ZBS-260] + _ = x[RV_ZICOND-261] + _ = x[RV_ZIHINTPAUSE-262] + _ = x[RV_ZICBOM-263] + _ = x[RV_ZICBOZ-264] + _ = x[RV_ZICBOP-265] + _ = x[RV_ZFA-266] + _ = x[RV_ZFH-267] + _ = x[RV_ZFHMIN-268] + _ = x[RV_ZTSO-269] + _ = x[RV_ZACAS-270] + _ = x[RV_ZBKB-271] + _ = x[RV_ZBKC-272] + _ = x[RV_ZBKX-273] + _ = x[RV_ZKND-274] + _ = x[RV_ZKNE-275] + _ = x[RV_ZKNH-276] + _ = x[RV_ZKSED-277] + _ = x[RV_ZKSH-278] + _ = x[RV_ZKT-279] + _ = x[RV_ZKN-280] + _ = x[RV_ZKS-281] + _ = x[RV_ZVBB-282] + _ = x[RV_ZVBC-283] + _ = x[RV_ZVKB-284] + _ = x[RV_ZVKG-285] + _ = x[RV_ZVKNED-286] + _ = x[RV_ZVKNHA-287] + _ = x[RV_ZVKNHB-288] + _ = x[RV_ZVKSED-289] + _ = x[RV_ZVKSH-290] + _ = x[RV_ZVKT-291] + _ = x[RV_ZVKNG-292] + _ = x[RV_ZVKSG-293] + _ = x[lastID-294] _ = x[firstID-0] } -const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXFP8AMXTILEAMXTF32AMXCOMPLEXAMXTRANSPOSEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8AVXVNNIINT16BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBPB_BRTYPEIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSBPBSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSGXPQCSHASMESME_COHERENTSM3_X86SM4_X86SPEC_CTRL_SSBDSRBDS_CTRLSRSO_MSR_FIXSRSO_NOSRSO_USER_KERNEL_NOSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSA_L1_NOTSA_SQ_NOTSA_VERW_CLEARTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFHMFPFPHPGPAJSCVTLRCPCPMULLRNDRTLBTSSHA1SHA2SHA3SHA512SM3SM4SVEPMU_FIXEDCOUNTER_CYCLESPMU_FIXEDCOUNTER_REFCYCLESPMU_FIXEDCOUNTER_INSTRUCTIONSPMU_FIXEDCOUNTER_TOPDOWN_SLOTSlastID" +const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXFP8AMXTILEAMXTF32AMXCOMPLEXAMXTRANSPOSEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BMMAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8AVXVNNIINT16BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FREDFSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBPB_BRTYPEIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSBPBSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSGXPQCSHASMESME_COHERENTSM3_X86SM4_X86SPEC_CTRL_SSBDSRBDS_CTRLSRSO_MSR_FIXSRSO_NOSRSO_USER_KERNEL_NOSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSA_L1_NOTSA_SQ_NOTSA_VERW_CLEARTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFHMFPFPHPGPAJSCVTLRCPCPMULLRNDRTLBTSSHA1SHA2SHA3SHA512SM3SM4SVESVE2SBSSBSBTIFLAGM2FRINTTSDCPODPBF16I8MMWFXTMOPSHBCCSSCPMU_FIXEDCOUNTER_CYCLESPMU_FIXEDCOUNTER_REFCYCLESPMU_FIXEDCOUNTER_INSTRUCTIONSPMU_FIXEDCOUNTER_TOPDOWN_SLOTSRV_IMARV_CRV_FRV_DRV_VRV_ZBARV_ZBBRV_ZBCRV_ZBSRV_ZICONDRV_ZIHINTPAUSERV_ZICBOMRV_ZICBOZRV_ZICBOPRV_ZFARV_ZFHRV_ZFHMINRV_ZTSORV_ZACASRV_ZBKBRV_ZBKCRV_ZBKXRV_ZKNDRV_ZKNERV_ZKNHRV_ZKSEDRV_ZKSHRV_ZKTRV_ZKNRV_ZKSRV_ZVBBRV_ZVBCRV_ZVKBRV_ZVKGRV_ZVKNEDRV_ZVKNHARV_ZVKNHBRV_ZVKSEDRV_ZVKSHRV_ZVKTRV_ZVKNGRV_ZVKSGlastID" -var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 61, 68, 75, 85, 97, 102, 105, 110, 119, 128, 137, 141, 151, 163, 171, 179, 187, 195, 202, 212, 222, 230, 240, 251, 259, 269, 287, 302, 309, 321, 328, 335, 346, 358, 366, 370, 374, 380, 385, 393, 398, 404, 408, 417, 435, 443, 450, 454, 458, 472, 478, 482, 486, 495, 499, 503, 508, 513, 517, 521, 528, 532, 535, 541, 544, 547, 557, 567, 580, 593, 597, 608, 612, 626, 643, 646, 656, 667, 673, 681, 692, 700, 712, 728, 742, 753, 763, 778, 786, 797, 807, 814, 823, 833, 837, 840, 847, 852, 863, 870, 877, 885, 888, 894, 899, 908, 915, 923, 927, 930, 936, 943, 956, 961, 963, 970, 977, 983, 987, 996, 1000, 1005, 1011, 1017, 1023, 1033, 1036, 1052, 1056, 1065, 1068, 1077, 1092, 1105, 1111, 1125, 1132, 1135, 1140, 1146, 1149, 1152, 1164, 1171, 1178, 1192, 1202, 1214, 1221, 1240, 1243, 1247, 1251, 1255, 1260, 1265, 1270, 1275, 1289, 1300, 1306, 1309, 1314, 1323, 1327, 1332, 1337, 1343, 1350, 1355, 1358, 1367, 1383, 1386, 1392, 1401, 1410, 1424, 1434, 1442, 1446, 1455, 1459, 1471, 1474, 1484, 1487, 1494, 1502, 1509, 1512, 1519, 1522, 1527, 1533, 1541, 1547, 1553, 1561, 1566, 1573, 1580, 1588, 1595, 1600, 1605, 1612, 1616, 1619, 1621, 1625, 1628, 1633, 1638, 1643, 1647, 1650, 1652, 1656, 1660, 1664, 1670, 1673, 1676, 1679, 1702, 1728, 1757, 1787, 1793} +var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 61, 68, 75, 85, 97, 102, 105, 110, 119, 128, 137, 141, 151, 163, 172, 180, 188, 196, 204, 211, 221, 231, 239, 249, 260, 268, 278, 296, 311, 318, 330, 337, 344, 355, 367, 375, 379, 383, 389, 394, 402, 407, 413, 417, 426, 444, 452, 459, 463, 467, 481, 487, 491, 495, 504, 508, 512, 517, 522, 526, 530, 534, 541, 545, 548, 554, 557, 560, 570, 580, 593, 606, 610, 621, 625, 639, 656, 659, 669, 680, 686, 694, 705, 713, 725, 741, 755, 766, 776, 791, 799, 810, 820, 827, 836, 846, 850, 853, 860, 865, 876, 883, 890, 898, 901, 907, 912, 921, 928, 936, 940, 943, 949, 956, 969, 974, 976, 983, 990, 996, 1000, 1009, 1013, 1018, 1024, 1030, 1036, 1046, 1049, 1065, 1069, 1078, 1081, 1090, 1105, 1118, 1124, 1138, 1145, 1148, 1153, 1159, 1162, 1165, 1177, 1184, 1191, 1205, 1215, 1227, 1234, 1253, 1256, 1260, 1264, 1268, 1273, 1278, 1283, 1288, 1302, 1313, 1319, 1322, 1327, 1336, 1340, 1345, 1350, 1356, 1363, 1368, 1371, 1380, 1396, 1399, 1405, 1414, 1423, 1437, 1447, 1455, 1459, 1468, 1472, 1484, 1487, 1497, 1500, 1507, 1515, 1522, 1525, 1532, 1535, 1540, 1546, 1554, 1560, 1566, 1574, 1579, 1586, 1593, 1601, 1608, 1613, 1618, 1625, 1629, 1632, 1634, 1638, 1641, 1646, 1651, 1656, 1660, 1663, 1665, 1669, 1673, 1677, 1683, 1686, 1689, 1692, 1696, 1698, 1702, 1705, 1711, 1718, 1724, 1728, 1732, 1736, 1740, 1743, 1747, 1770, 1796, 1825, 1855, 1861, 1865, 1869, 1873, 1877, 1883, 1889, 1895, 1901, 1910, 1924, 1933, 1942, 1951, 1957, 1963, 1972, 1979, 1987, 1994, 2001, 2008, 2015, 2022, 2029, 2037, 2044, 2050, 2056, 2062, 2069, 2076, 2083, 2090, 2099, 2108, 2117, 2126, 2134, 2141, 2149, 2157, 2163} func (i FeatureID) String() string { - if i < 0 || i >= FeatureID(len(_FeatureID_index)-1) { + idx := int(i) - 0 + if i < 0 || idx >= len(_FeatureID_index)-1 { return "FeatureID(" + strconv.FormatInt(int64(i), 10) + ")" } - return _FeatureID_name[_FeatureID_index[i]:_FeatureID_index[i+1]] + return _FeatureID_name[_FeatureID_index[idx]:_FeatureID_index[idx+1]] } func _() { // An "invalid array index" compiler error signifies that the constant values have changed. @@ -293,16 +351,22 @@ func _() { _ = x[ACRN-28] _ = x[SRE-29] _ = x[Apple-30] - _ = x[lastVendor-31] + _ = x[SiFive-31] + _ = x[StarFive-32] + _ = x[THead-33] + _ = x[Andes-34] + _ = x[SpacemiT-35] + _ = x[lastVendor-36] } -const _Vendor_name = "VendorUnknownIntelAMDVIATransmetaNSCKVMMSVMVMwareXenHVMBhyveHygonSiSRDCAmpereARMBroadcomCaviumDECFujitsuInfineonMotorolaNVIDIAAMCCQualcommMarvellQEMUQNXACRNSREApplelastVendor" +const _Vendor_name = "VendorUnknownIntelAMDVIATransmetaNSCKVMMSVMVMwareXenHVMBhyveHygonSiSRDCAmpereARMBroadcomCaviumDECFujitsuInfineonMotorolaNVIDIAAMCCQualcommMarvellQEMUQNXACRNSREAppleSiFiveStarFiveTHeadAndesSpacemiTlastVendor" -var _Vendor_index = [...]uint8{0, 13, 18, 21, 24, 33, 36, 39, 43, 49, 55, 60, 65, 68, 71, 77, 80, 88, 94, 97, 104, 112, 120, 126, 130, 138, 145, 149, 152, 156, 159, 164, 174} +var _Vendor_index = [...]uint8{0, 13, 18, 21, 24, 33, 36, 39, 43, 49, 55, 60, 65, 68, 71, 77, 80, 88, 94, 97, 104, 112, 120, 126, 130, 138, 145, 149, 152, 156, 159, 164, 170, 178, 183, 188, 196, 206} func (i Vendor) String() string { - if i < 0 || i >= Vendor(len(_Vendor_index)-1) { + idx := int(i) - 0 + if i < 0 || idx >= len(_Vendor_index)-1 { return "Vendor(" + strconv.FormatInt(int64(i), 10) + ")" } - return _Vendor_name[_Vendor_index[i]:_Vendor_index[i+1]] + return _Vendor_name[_Vendor_index[idx]:_Vendor_index[idx+1]] } diff --git a/vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go index da07522e7c..addbfc67b8 100644 --- a/vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go +++ b/vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go @@ -126,4 +126,17 @@ func tryToFillCPUInfoFomSysctl(c *CPUInfo) { setFeature(c, SM3, "hw.optional.arm.FEAT_SM3") // SM3 instructions setFeature(c, SM4, "hw.optional.arm.FEAT_SM4") // SM4 instructions setFeature(c, SVE, "hw.optional.arm.FEAT_SVE") // Scalable Vector Extension + setFeature(c, SVE2, "hw.optional.arm.FEAT_SVE2") // Scalable Vector Extension 2 + setFeature(c, SB, "hw.optional.arm.FEAT_SB") // Speculation barrier + setFeature(c, SSBS, "hw.optional.arm.FEAT_SSBS") // Speculative Store Bypass Safe + setFeature(c, BTI, "hw.optional.arm.FEAT_BTI") // Branch Target Identification + setFeature(c, FLAGM2, "hw.optional.arm.FEAT_FlagM2") // Condition flag manipulation version 2 + setFeature(c, FRINTTS, "hw.optional.arm.FEAT_FRINTTS") // Floating-point to integer rounding + setFeature(c, DCPODP, "hw.optional.arm.FEAT_DPB2") // Data cache clean to Point of Deep Persistence + setFeature(c, BF16, "hw.optional.arm.FEAT_BF16") // BFloat16 instructions + setFeature(c, I8MM, "hw.optional.arm.FEAT_I8MM") // Int8 matrix multiplication + setFeature(c, WFXT, "hw.optional.arm.FEAT_WFxT") // WFE/WFI with timeout + setFeature(c, MOPS, "hw.optional.arm.FEAT_MOPS") // Memory copy and set instructions + setFeature(c, HBC, "hw.optional.arm.FEAT_HBC") // Hinted conditional branches + setFeature(c, CSSC, "hw.optional.arm.FEAT_CSSC") // Common short sequence compression } diff --git a/vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go index d96d24438b..ea9da404c6 100644 --- a/vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go +++ b/vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go @@ -115,15 +115,19 @@ const ( hwcap2_POE = 1 << 63 ) +// hwcap2 holds AT_HWCAP2. Unlike hwcap, the arm64 runtime does not expose it +// through internal/cpu, so detectOS reads it from the auxiliary vector. +var hwcap2 uint + func detectOS(c *CPUInfo) bool { // For now assuming no hyperthreading is reasonable. c.LogicalCores = runtime.NumCPU() c.PhysicalCores = c.LogicalCores c.ThreadsPerCore = 1 - if hwcap == 0 { - // We did not get values from the runtime. - // Try reading /proc/self/auxv - + // hwcap is provided by the runtime through the internal/cpu.HWCap linkname, + // but the runtime does not expose HWCAP2 on arm64. Read the auxiliary vector + // directly to obtain hwcap2 (and hwcap when the linkname is unavailable). + if hwcap == 0 || hwcap2 == 0 { // From https://github.com/golang/sys const ( _AT_HWCAP = 16 @@ -132,37 +136,34 @@ func detectOS(c *CPUInfo) bool { uintSize = int(32 << (^uint(0) >> 63)) ) - buf, err := ioutil.ReadFile("/proc/self/auxv") - if err != nil { - // e.g. on android /proc/self/auxv is not accessible, so silently - // ignore the error and leave Initialized = false. On some - // architectures (e.g. arm64) doinit() implements a fallback - // readout and will set Initialized = true again. - return false - } - bo := binary.LittleEndian - for len(buf) >= 2*(uintSize/8) { - var tag, val uint - switch uintSize { - case 32: - tag = uint(bo.Uint32(buf[0:])) - val = uint(bo.Uint32(buf[4:])) - buf = buf[8:] - case 64: - tag = uint(bo.Uint64(buf[0:])) - val = uint(bo.Uint64(buf[8:])) - buf = buf[16:] - } - switch tag { - case _AT_HWCAP: - hwcap = val - case _AT_HWCAP2: - // Not used + // e.g. on android /proc/self/auxv is not accessible, so silently ignore + // the error and fall back to whatever the runtime provided. + if buf, err := ioutil.ReadFile("/proc/self/auxv"); err == nil { + bo := binary.LittleEndian + for len(buf) >= 2*(uintSize/8) { + var tag, val uint + switch uintSize { + case 32: + tag = uint(bo.Uint32(buf[0:])) + val = uint(bo.Uint32(buf[4:])) + buf = buf[8:] + case 64: + tag = uint(bo.Uint64(buf[0:])) + val = uint(bo.Uint64(buf[8:])) + buf = buf[16:] + } + switch tag { + case _AT_HWCAP: + hwcap = val + case _AT_HWCAP2: + hwcap2 = val + } } } - if hwcap == 0 { - return false - } + } + if hwcap == 0 { + // Nothing detected, e.g. on android or a restricted environment. + return false } // HWCap was populated by the runtime from the auxiliary vector. @@ -184,9 +185,9 @@ func detectOS(c *CPUInfo) bool { c.featureSet.setIf(isSet(hwcap, hwcap_JSCVT), JSCVT) c.featureSet.setIf(isSet(hwcap, hwcap_LRCPC), LRCPC) c.featureSet.setIf(isSet(hwcap, hwcap_PMULL), PMULL) - c.featureSet.setIf(isSet(hwcap, hwcap2_RNG), RNDR) - // c.featureSet.setIf(isSet(hwcap, hwcap_), TLB) - // c.featureSet.setIf(isSet(hwcap, hwcap_), TS) + c.featureSet.setIf(isSet(hwcap2, hwcap2_RNG), RNDR) + // TLB (FEAT_TLBIOS/TLBIRANGE) has no HWCAP bit; only detectable via ID registers. + c.featureSet.setIf(isSet(hwcap, hwcap_FLAGM), TS) c.featureSet.setIf(isSet(hwcap, hwcap_SHA1), SHA1) c.featureSet.setIf(isSet(hwcap, hwcap_SHA2), SHA2) c.featureSet.setIf(isSet(hwcap, hwcap_SHA3), SHA3) @@ -194,6 +195,21 @@ func detectOS(c *CPUInfo) bool { c.featureSet.setIf(isSet(hwcap, hwcap_SM3), SM3) c.featureSet.setIf(isSet(hwcap, hwcap_SM4), SM4) c.featureSet.setIf(isSet(hwcap, hwcap_SVE), SVE) + c.featureSet.setIf(isSet(hwcap, hwcap_SB), SB) + c.featureSet.setIf(isSet(hwcap, hwcap_SSBS), SSBS) + + // Features reported through the second hardware capability word (HWCAP2). + c.featureSet.setIf(isSet(hwcap2, hwcap2_SVE2), SVE2) + c.featureSet.setIf(isSet(hwcap2, hwcap2_BTI), BTI) + c.featureSet.setIf(isSet(hwcap2, hwcap2_FLAGM2), FLAGM2) + c.featureSet.setIf(isSet(hwcap2, hwcap2_FRINT), FRINTTS) + c.featureSet.setIf(isSet(hwcap2, hwcap2_DCPODP), DCPODP) + c.featureSet.setIf(isSet(hwcap2, hwcap2_BF16), BF16) + c.featureSet.setIf(isSet(hwcap2, hwcap2_I8MM), I8MM) + c.featureSet.setIf(isSet(hwcap2, hwcap2_WFXT), WFXT) + c.featureSet.setIf(isSet(hwcap2, hwcap2_MOPS), MOPS) + c.featureSet.setIf(isSet(hwcap2, hwcap2_HBC), HBC) + c.featureSet.setIf(isSet(hwcap2, hwcap2_CSSC), CSSC) // The Samsung S9+ kernel reports support for atomics, but not all cores // actually support them, resulting in SIGILL. See issue #28431. diff --git a/vendor/github.com/klauspost/cpuid/v2/os_linux_riscv64.go b/vendor/github.com/klauspost/cpuid/v2/os_linux_riscv64.go new file mode 100644 index 0000000000..71919a49bd --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/v2/os_linux_riscv64.go @@ -0,0 +1,225 @@ +// Copyright (c) 2026 Klaus Post, released under MIT License. See LICENSE file. + +package cpuid + +import ( + "bufio" + "os" + "runtime" + "strconv" + "strings" + "unsafe" + + "golang.org/x/sys/unix" +) + +const __NR_riscv_hwprobe = 258 + +type riscvHWProbePair struct { + key int64 + value uint64 +} + +// Keys from linux/include/uapi/asm/hwprobe.h +const ( + riscv_hwprobe_key_mvendorid = 0 + riscv_hwprobe_key_marchid = 1 + riscv_hwprobe_key_mimpid = 2 + riscv_hwprobe_key_base_behavior = 3 + riscv_hwprobe_key_ima_ext_0 = 4 + riscv_hwprobe_key_cpuperf_0 = 5 + riscv_hwprobe_key_zicbom_block_size = 12 +) + +// Bits from linux/arch/riscv/include/uapi/asm/hwprobe.h +const ( + riscv_hwprobe_ima_fd = 1 << 0 + riscv_hwprobe_ima_c = 1 << 1 + riscv_hwprobe_ima_v = 1 << 2 + riscv_hwprobe_ext_zba = 1 << 3 + riscv_hwprobe_ext_zbb = 1 << 4 + riscv_hwprobe_ext_zbs = 1 << 5 + riscv_hwprobe_ext_zicboz = 1 << 6 + riscv_hwprobe_ext_zbc = 1 << 7 + riscv_hwprobe_ext_zbkb = 1 << 8 + riscv_hwprobe_ext_zbkc = 1 << 9 + riscv_hwprobe_ext_zbkx = 1 << 10 + riscv_hwprobe_ext_zknd = 1 << 11 + riscv_hwprobe_ext_zkne = 1 << 12 + riscv_hwprobe_ext_zknh = 1 << 13 + riscv_hwprobe_ext_zksed = 1 << 14 + riscv_hwprobe_ext_zksh = 1 << 15 + riscv_hwprobe_ext_zkt = 1 << 16 + riscv_hwprobe_ext_zvbb = 1 << 17 + riscv_hwprobe_ext_zvbc = 1 << 18 + riscv_hwprobe_ext_zvkb = 1 << 19 + riscv_hwprobe_ext_zvkg = 1 << 20 + riscv_hwprobe_ext_zvkned = 1 << 21 + riscv_hwprobe_ext_zvknha = 1 << 22 + riscv_hwprobe_ext_zvknhb = 1 << 23 + riscv_hwprobe_ext_zvksed = 1 << 24 + riscv_hwprobe_ext_zvksh = 1 << 25 + riscv_hwprobe_ext_zvkt = 1 << 26 + riscv_hwprobe_ext_zfh = 1 << 27 + riscv_hwprobe_ext_zfhmin = 1 << 28 + riscv_hwprobe_ext_zihintntl = 1 << 29 + riscv_hwprobe_ext_zvfh = 1 << 30 + riscv_hwprobe_ext_zvfhmin = 1 << 31 + riscv_hwprobe_ext_zfa = 1 << 32 + riscv_hwprobe_ext_ztso = 1 << 33 + riscv_hwprobe_ext_zacas = 1 << 34 + riscv_hwprobe_ext_zicond = 1 << 35 + riscv_hwprobe_ext_zihintpause = 1 << 36 + riscv_hwprobe_ext_zicbom = 1 << 55 + riscv_hwprobe_ext_zicbop = 1 << 60 +) + +func riscvHWProbe(pairs []riscvHWProbePair) int64 { + if len(pairs) == 0 { + return -1 + } + ret, _, _ := unix.Syscall6(__NR_riscv_hwprobe, + uintptr(unsafe.Pointer(&pairs[0])), + uintptr(len(pairs)), + 0, 0, 0, 0) + return int64(ret) +} + +func detectOS(c *CPUInfo) bool { + c.LogicalCores = runtime.NumCPU() + c.PhysicalCores = c.LogicalCores + c.ThreadsPerCore = 1 + + pairs := []riscvHWProbePair{ + {key: riscv_hwprobe_key_mvendorid}, + {key: riscv_hwprobe_key_marchid}, + {key: riscv_hwprobe_key_mimpid}, + {key: riscv_hwprobe_key_ima_ext_0}, + {key: riscv_hwprobe_key_zicbom_block_size}, + } + ret := riscvHWProbe(pairs) + if ret == 0 && pairs[3].value != ^uint64(0) { + detectFromHWProbe(c, pairs) + if pairs[4].value != ^uint64(0) && pairs[4].value > 0 { + c.CacheLine = int(pairs[4].value) + } + return true + } + + c.CacheLine = detectCacheLine() + return detectFromCPUInfo(c) +} + +func detectFromHWProbe(c *CPUInfo, pairs []riscvHWProbePair) { + if pairs[0].value != ^uint64(0) { + c.VendorID = riscvVendorID(pairs[0].value) + c.VendorString = c.VendorID.String() + } + if pairs[1].value != ^uint64(0) { + c.Model = int(pairs[1].value) + } + if pairs[2].value != ^uint64(0) { + c.Family = int(pairs[2].value) + } + + imaExt := pairs[3].value + + if imaExt&riscv_hwprobe_ima_fd != 0 { + c.featureSet.set(RV_D) + c.featureSet.set(RV_F) + } + c.featureSet.setIf(imaExt&riscv_hwprobe_ima_c != 0, RV_C) + c.featureSet.setIf(imaExt&riscv_hwprobe_ima_v != 0, RV_V) + + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zba != 0, RV_ZBA) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zbb != 0, RV_ZBB) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zbc != 0, RV_ZBC) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zbs != 0, RV_ZBS) + + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zicbom != 0, RV_ZICBOM) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zicboz != 0, RV_ZICBOZ) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zicbop != 0, RV_ZICBOP) + + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zicond != 0, RV_ZICOND) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zihintpause != 0, RV_ZIHINTPAUSE) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zfa != 0, RV_ZFA) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zfh != 0, RV_ZFH) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zfhmin != 0, RV_ZFHMIN) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_ztso != 0, RV_ZTSO) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zacas != 0, RV_ZACAS) + + // Scalar cryptography + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zbkb != 0, RV_ZBKB) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zbkc != 0, RV_ZBKC) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zbkx != 0, RV_ZBKX) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zknd != 0, RV_ZKND) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zkne != 0, RV_ZKNE) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zknh != 0, RV_ZKNH) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zksed != 0, RV_ZKSED) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zksh != 0, RV_ZKSH) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zkt != 0, RV_ZKT) + + // Vector cryptography + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvbb != 0, RV_ZVBB) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvbc != 0, RV_ZVBC) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvkb != 0, RV_ZVKB) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvkg != 0, RV_ZVKG) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvkned != 0, RV_ZVKNED) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvknha != 0, RV_ZVKNHA) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvknhb != 0, RV_ZVKNHB) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvksed != 0, RV_ZVKSED) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvksh != 0, RV_ZVKSH) + c.featureSet.setIf(imaExt&riscv_hwprobe_ext_zvkt != 0, RV_ZVKT) + + // Crypto suites (combined from individual features) + c.featureSet.setIf(c.featureSet.hasSetP(rvZKNFeatures), RV_ZKN) + c.featureSet.setIf(c.featureSet.hasSetP(rvZKSFeatures), RV_ZKS) + c.featureSet.setIf(c.featureSet.hasSetP(rvZVKNFeatures), RV_ZVKNG) + c.featureSet.setIf(c.featureSet.hasSetP(rvZVKSFeatures), RV_ZVKSG) + + // Every Linux-capable riscv64 core has I, M, A base. + c.featureSet.set(RV_IMA) +} + +func detectFromCPUInfo(c *CPUInfo) bool { + f, err := os.Open("/proc/cpuinfo") + if err != nil { + return false + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + fields := strings.SplitN(line, ":", 2) + if len(fields) < 2 { + continue + } + key := strings.TrimSpace(fields[0]) + value := strings.TrimSpace(fields[1]) + + switch key { + case "isa": + parseISAString(c, value) + case "mvendorid": + if vid, err := strconv.ParseUint(value, 0, 64); err == nil { + c.VendorID = riscvVendorID(vid) + c.VendorString = c.VendorID.String() + } + case "uarch": + c.BrandName = value + } + } + return scanner.Err() == nil +} + +func detectCacheLine() int { + data, err := os.ReadFile("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size") + if err != nil { + return 0 + } + if n, err := strconv.Atoi(strings.TrimSpace(string(data))); err == nil && n > 0 { + return n + } + return 0 +} diff --git a/vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go index 8733ba3436..debc123922 100644 --- a/vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go +++ b/vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go @@ -1,7 +1,6 @@ // Copyright (c) 2020 Klaus Post, released under MIT License. See LICENSE file. //go:build arm64 && !linux && !darwin -// +build arm64,!linux,!darwin package cpuid diff --git a/vendor/github.com/klauspost/cpuid/v2/os_other_riscv64.go b/vendor/github.com/klauspost/cpuid/v2/os_other_riscv64.go new file mode 100644 index 0000000000..fd86f7d056 --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/v2/os_other_riscv64.go @@ -0,0 +1,14 @@ +// Copyright (c) 2026 Klaus Post, released under MIT License. See LICENSE file. + +//go:build riscv64 && !linux + +package cpuid + +import "runtime" + +func detectOS(c *CPUInfo) bool { + c.PhysicalCores = runtime.NumCPU() + c.ThreadsPerCore = 1 + c.LogicalCores = c.PhysicalCores + return false +} diff --git a/vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go index f8f201b5f7..5b4e8a1b3e 100644 --- a/vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go +++ b/vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go @@ -1,7 +1,6 @@ // Copyright (c) 2021 Klaus Post, released under MIT License. See LICENSE file. //go:build nounsafe -// +build nounsafe package cpuid diff --git a/vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go index 92af622eb8..00158c21c3 100644 --- a/vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go +++ b/vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go @@ -1,7 +1,6 @@ // Copyright (c) 2021 Klaus Post, released under MIT License. See LICENSE file. //go:build !nounsafe -// +build !nounsafe package cpuid diff --git a/vendor/github.com/klauspost/cpuid/v2/riscv_isa.go b/vendor/github.com/klauspost/cpuid/v2/riscv_isa.go new file mode 100644 index 0000000000..5a87679bdb --- /dev/null +++ b/vendor/github.com/klauspost/cpuid/v2/riscv_isa.go @@ -0,0 +1,93 @@ +// Copyright (c) 2026 Klaus Post, released under MIT License. See LICENSE file. + +package cpuid + +import "strings" + +func parseISAString(c *CPUInfo, isa string) { + isa = strings.ToLower(isa) + extMap := make(map[string]bool) + for ext := range strings.SplitSeq(isa, "_") { + ext = strings.TrimSpace(ext) + if strings.HasPrefix(ext, "rv64") { + extMap["i"] = true + for _, ch := range ext[4:] { + extMap[string(ch)] = true + } + } else if ext != "" { + extMap[ext] = true + } + } + + if extMap["g"] { + extMap["i"] = true + extMap["m"] = true + extMap["a"] = true + extMap["f"] = true + extMap["d"] = true + } + + c.featureSet.setIf(extMap["i"] && extMap["m"] && extMap["a"], RV_IMA) + c.featureSet.setIf(extMap["c"], RV_C) + c.featureSet.setIf(extMap["f"], RV_F) + c.featureSet.setIf(extMap["d"], RV_D) + c.featureSet.setIf(extMap["v"], RV_V) + c.featureSet.setIf(extMap["zihintpause"], RV_ZIHINTPAUSE) + c.featureSet.setIf(extMap["zba"], RV_ZBA) + c.featureSet.setIf(extMap["zbb"], RV_ZBB) + c.featureSet.setIf(extMap["zbc"], RV_ZBC) + c.featureSet.setIf(extMap["zbs"], RV_ZBS) + c.featureSet.setIf(extMap["zicond"], RV_ZICOND) + c.featureSet.setIf(extMap["zicbom"], RV_ZICBOM) + c.featureSet.setIf(extMap["zicboz"], RV_ZICBOZ) + c.featureSet.setIf(extMap["zicbop"], RV_ZICBOP) + c.featureSet.setIf(extMap["zfa"], RV_ZFA) + c.featureSet.setIf(extMap["zfh"], RV_ZFH) + c.featureSet.setIf(extMap["zfhmin"], RV_ZFHMIN) + c.featureSet.setIf(extMap["ztso"], RV_ZTSO) + c.featureSet.setIf(extMap["zacas"], RV_ZACAS) + + // Scalar cryptography + c.featureSet.setIf(extMap["zbkb"], RV_ZBKB) + c.featureSet.setIf(extMap["zbkc"], RV_ZBKC) + c.featureSet.setIf(extMap["zbkx"], RV_ZBKX) + c.featureSet.setIf(extMap["zknd"], RV_ZKND) + c.featureSet.setIf(extMap["zkne"], RV_ZKNE) + c.featureSet.setIf(extMap["zknh"], RV_ZKNH) + c.featureSet.setIf(extMap["zksed"], RV_ZKSED) + c.featureSet.setIf(extMap["zksh"], RV_ZKSH) + c.featureSet.setIf(extMap["zkt"], RV_ZKT) + + // Vector cryptography + c.featureSet.setIf(extMap["zvbb"], RV_ZVBB) + c.featureSet.setIf(extMap["zvbc"], RV_ZVBC) + c.featureSet.setIf(extMap["zvkb"], RV_ZVKB) + c.featureSet.setIf(extMap["zvkg"], RV_ZVKG) + c.featureSet.setIf(extMap["zvkned"], RV_ZVKNED) + c.featureSet.setIf(extMap["zvknha"], RV_ZVKNHA) + c.featureSet.setIf(extMap["zvknhb"], RV_ZVKNHB) + c.featureSet.setIf(extMap["zvksed"], RV_ZVKSED) + c.featureSet.setIf(extMap["zvksh"], RV_ZVKSH) + c.featureSet.setIf(extMap["zvkt"], RV_ZVKT) + + // Crypto suites (combined from individual features or bundle tokens) + c.featureSet.setIf(extMap["zkn"] || c.featureSet.hasSetP(rvZKNFeatures), RV_ZKN) + c.featureSet.setIf(extMap["zks"] || c.featureSet.hasSetP(rvZKSFeatures), RV_ZKS) + c.featureSet.setIf(extMap["zvkng"] || c.featureSet.hasSetP(rvZVKNFeatures), RV_ZVKNG) + c.featureSet.setIf(extMap["zvksg"] || c.featureSet.hasSetP(rvZVKSFeatures), RV_ZVKSG) +} + +var riscvVendorMap = map[uint64]Vendor{ + 0x489: SiFive, + 0x5b7: StarFive, + 0x5b1: THead, + 0x31e: Andes, + 0x710: SpacemiT, +} + +func riscvVendorID(mvendorid uint64) Vendor { + if v, ok := riscvVendorMap[mvendorid]; ok { + return v + } + return VendorUnknown +} diff --git a/vendor/github.com/oschwald/maxminddb-golang/v2/CHANGELOG.md b/vendor/github.com/oschwald/maxminddb-golang/v2/CHANGELOG.md index 17a5909a50..39b7d0577f 100644 --- a/vendor/github.com/oschwald/maxminddb-golang/v2/CHANGELOG.md +++ b/vendor/github.com/oschwald/maxminddb-golang/v2/CHANGELOG.md @@ -1,6 +1,21 @@ # Changes -## Unreleased +## 2.4.1 - 2026-06-28 + +- Fixed `Result.Decode` and `Result.DecodePath` after `Reader.Close` so stale + results return closed-database errors instead of reading invalidated data. +- Fixed `Networks` and `NetworksWithin` with `SkipEmptyValues` so malformed + pointer cycles return an error instead of looping indefinitely. +- Fixed top-level `Decode` validation so nil and non-pointer values are rejected + consistently before custom `Unmarshaler` dispatch. +- Fixed `ReadMap` and `ReadSlice` iterator cleanup so callers that stop + iteration early can continue decoding from the correct next value. +- Fixed an oversized data-pointer bounds check so malformed databases return an + offset error instead of risking a panic on 32-bit builds. +- Fixed migration and README examples to reference the public `mmdbdata.Decoder` + type for custom unmarshaling. + +## 2.4.0 - 2026-06-06 - Reduced reflection decoding time and memory allocations. A city-lookup benchmark decoding a geoip2-style result allocates 20% fewer bytes (saving 48 B/op) and diff --git a/vendor/github.com/oschwald/maxminddb-golang/v2/MIGRATION.md b/vendor/github.com/oschwald/maxminddb-golang/v2/MIGRATION.md index cf981ad755..e239db0eaa 100644 --- a/vendor/github.com/oschwald/maxminddb-golang/v2/MIGRATION.md +++ b/vendor/github.com/oschwald/maxminddb-golang/v2/MIGRATION.md @@ -23,9 +23,10 @@ ## Manual decoding improvements -- Custom types can implement `UnmarshalMaxMindDB(d *maxminddb.Decoder) error` - to skip reflection and zero allocations for hot paths. -- `maxminddb.Decoder` mirrors the APIs from `internal/decoder`, giving fine +- Custom types can import `github.com/oschwald/maxminddb-golang/v2/mmdbdata` + and implement `UnmarshalMaxMindDB(d *mmdbdata.Decoder) error` to skip + reflection and zero allocations for hot paths. +- `mmdbdata.Decoder` mirrors the APIs from `internal/decoder`, giving fine grained access to the underlying data section. - `DecodePath` works on the result object, supporting nested lookups without decoding entire records. diff --git a/vendor/github.com/oschwald/maxminddb-golang/v2/README.md b/vendor/github.com/oschwald/maxminddb-golang/v2/README.md index 310bbfb1b3..1fa09f6d14 100644 --- a/vendor/github.com/oschwald/maxminddb-golang/v2/README.md +++ b/vendor/github.com/oschwald/maxminddb-golang/v2/README.md @@ -112,13 +112,15 @@ err = db.Lookup(ip).Decode(&city) ### High-Performance Custom Unmarshaling +Import `github.com/oschwald/maxminddb-golang/v2/mmdbdata` for the decoder type. + ```go type FastCity struct { CountryISO string CityName string } -func (c *FastCity) UnmarshalMaxMindDB(d *maxminddb.Decoder) error { +func (c *FastCity) UnmarshalMaxMindDB(d *mmdbdata.Decoder) error { mapIter, size, err := d.ReadMap() if err != nil { return err @@ -222,8 +224,9 @@ regardless of the data provider. ## Performance Tips -1. **Reuse Reader instances**: The `Reader` is thread-safe and should be reused - across goroutines +1. **Reuse Reader instances**: Lookups, decoding, and iteration are safe to run + concurrently. `Close` invalidates outstanding results and should run after + readers are done. 2. **Use specific structs**: Only decode the fields you need rather than using `any` 3. **Implement Unmarshaler**: For high-throughput applications, implement diff --git a/vendor/github.com/oschwald/maxminddb-golang/v2/internal/decoder/decoder.go b/vendor/github.com/oschwald/maxminddb-golang/v2/internal/decoder/decoder.go index 5cedda2cde..2deba1d390 100644 --- a/vendor/github.com/oschwald/maxminddb-golang/v2/internal/decoder/decoder.go +++ b/vendor/github.com/oschwald/maxminddb-golang/v2/internal/decoder/decoder.go @@ -227,7 +227,7 @@ func (d *Decoder) ReadMap() (iter.Seq2[[]byte, error], uint, error) { iterator := func(yield func([]byte, error) bool) { currentOffset := offset - for range size { + for i := range size { key, keyEndOffset, err := d.d.decodeKey(currentOffset) if err != nil { yield(nil, d.wrapErrorAtOffset(err, currentOffset)) @@ -239,6 +239,7 @@ func (d *Decoder) ReadMap() (iter.Seq2[[]byte, error], uint, error) { ok := yield(key, nil) if !ok { + d.finishMapAfterStop(keyEndOffset, size-i-1) return } @@ -277,14 +278,7 @@ func (d *Decoder) ReadSlice() (iter.Seq[error], uint, error) { ok := yield(nil) if !ok { - // Skip the unvisited elements - remaining := size - i - 1 - if remaining > 0 { - endOffset, err := d.d.nextValueOffset(currentOffset, remaining) - if err == nil { - d.reset(endOffset) - } - } + d.finishSliceAfterStop(currentOffset, size-i) return } @@ -357,6 +351,48 @@ func (d *Decoder) Offset() uint { return pointer } +func (d *Decoder) finishMapAfterStop(keyEndOffset, remainingPairs uint) { + valueEndOffset, err := d.valueEndOffsetAfterYield(keyEndOffset) + if err != nil { + return + } + + remainingValues := remainingPairs * 2 + if remainingValues == 0 { + d.reset(valueEndOffset) + return + } + + endOffset, err := d.d.nextValueOffset(valueEndOffset, remainingValues) + if err == nil { + d.reset(endOffset) + } +} + +func (d *Decoder) finishSliceAfterStop(currentOffset, remainingValues uint) { + endOffset := currentOffset + if d.hasNextOffset { + endOffset = d.nextOffset + remainingValues-- + } + if remainingValues == 0 { + d.reset(endOffset) + return + } + + endOffset, err := d.d.nextValueOffset(endOffset, remainingValues) + if err == nil { + d.reset(endOffset) + } +} + +func (d *Decoder) valueEndOffsetAfterYield(valueOffset uint) (uint, error) { + if d.hasNextOffset { + return d.nextOffset, nil + } + return d.d.nextValueOffset(valueOffset, 1) +} + func (d *Decoder) reset(offset uint) { d.offset = offset d.hasNextOffset = false diff --git a/vendor/github.com/oschwald/maxminddb-golang/v2/internal/decoder/reflection.go b/vendor/github.com/oschwald/maxminddb-golang/v2/internal/decoder/reflection.go index e65b178239..ee5a23eb29 100644 --- a/vendor/github.com/oschwald/maxminddb-golang/v2/internal/decoder/reflection.go +++ b/vendor/github.com/oschwald/maxminddb-golang/v2/internal/decoder/reflection.go @@ -37,6 +37,7 @@ func New(buffer []byte) ReflectionDecoder { // Returns true if the value is a map or array with size 0. func (d *ReflectionDecoder) IsEmptyValueAt(offset uint) (bool, error) { dataOffset := offset + followedPointers := 0 for { kindNum, size, newOffset, err := d.decodeCtrlData(dataOffset) if err != nil { @@ -44,6 +45,12 @@ func (d *ReflectionDecoder) IsEmptyValueAt(offset uint) (bool, error) { } if kindNum == KindPointer { + if followedPointers >= maximumDataStructureDepth { + return false, mmdberrors.NewInvalidDatabaseError( + "exceeded maximum data structure depth; database is likely corrupt", + ) + } + followedPointers++ dataOffset, _, err = d.decodePointer(size, newOffset) if err != nil { return false, err @@ -59,17 +66,16 @@ func (d *ReflectionDecoder) IsEmptyValueAt(offset uint) (bool, error) { // Decode decodes the data value at offset and stores it in the value // pointed at by v. func (d *ReflectionDecoder) Decode(offset uint, v any) error { - // Check if the type implements Unmarshaler interface without reflection - if unmarshaler, ok := v.(Unmarshaler); ok { - decoder := NewDecoder(d.DataDecoder, offset) - return unmarshaler.UnmarshalMaxMindDB(decoder) - } - rv := reflect.ValueOf(v) if rv.Kind() != reflect.Pointer || rv.IsNil() { return errors.New("result param must be a pointer") } + if unmarshaler, ok := v.(Unmarshaler); ok { + decoder := NewDecoder(d.DataDecoder, offset) + return unmarshaler.UnmarshalMaxMindDB(decoder) + } + _, err := d.decode(offset, rv, 0) if err == nil { return nil @@ -586,7 +592,7 @@ func (d *ReflectionDecoder) unmarshalPointer( // Check for pointer-to-pointer by looking at what we're about to decode // This is done efficiently by checking the control byte at the pointer location - if len(d.buffer) > int(pointer) { + if pointer < uint(len(d.buffer)) { controlByte := d.buffer[pointer] if Kind(controlByte>>5) == KindPointer { return 0, mmdberrors.NewInvalidDatabaseError( diff --git a/vendor/github.com/oschwald/maxminddb-golang/v2/reader.go b/vendor/github.com/oschwald/maxminddb-golang/v2/reader.go index ed9e203132..05ffa8861d 100644 --- a/vendor/github.com/oschwald/maxminddb-golang/v2/reader.go +++ b/vendor/github.com/oschwald/maxminddb-golang/v2/reader.go @@ -100,8 +100,8 @@ // // # Thread Safety // -// All Reader methods are thread-safe. The Reader can be safely shared across -// multiple goroutines. +// Reader lookup, decode, and iteration methods are safe to call concurrently. +// Close must not be called concurrently with other Reader or Result methods. package maxminddb import ( @@ -133,8 +133,8 @@ type mmapCleanup struct { // Reader holds the data corresponding to the MaxMind DB file. Its only public // field is Metadata, which contains the metadata from the MaxMind DB file. // -// All of the methods on Reader are thread-safe. The struct may be safely -// shared across goroutines. +// Reader lookup, decode, and iteration methods are safe to call concurrently. +// Close must not be called concurrently with other Reader or Result methods. type Reader struct { hasMappedFile *atomic.Bool decoder decoder.ReflectionDecoder diff --git a/vendor/github.com/oschwald/maxminddb-golang/v2/result.go b/vendor/github.com/oschwald/maxminddb-golang/v2/result.go index d947cfabaa..87752eea56 100644 --- a/vendor/github.com/oschwald/maxminddb-golang/v2/result.go +++ b/vendor/github.com/oschwald/maxminddb-golang/v2/result.go @@ -1,6 +1,7 @@ package maxminddb import ( + "errors" "math" "net/netip" ) @@ -34,6 +35,9 @@ func (r Result) Decode(v any) error { if r.offset == notFound { return nil } + if r.reader == nil || r.reader.buffer == nil { + return errors.New("cannot call Decode on a closed database") + } return r.reader.decoder.Decode(r.offset, v) } @@ -92,6 +96,9 @@ func (r Result) DecodePath(v any, path ...any) error { if r.offset == notFound { return nil } + if r.reader == nil || r.reader.buffer == nil { + return errors.New("cannot call DecodePath on a closed database") + } return r.reader.decoder.DecodePath(r.offset, path, v) } diff --git a/vendor/github.com/pion/rtcp/.gitignore b/vendor/github.com/pion/rtcp/.gitignore index 6e2f206a9f..23945578f7 100644 --- a/vendor/github.com/pion/rtcp/.gitignore +++ b/vendor/github.com/pion/rtcp/.gitignore @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-FileCopyrightText: 2026 The Pion community # SPDX-License-Identifier: MIT ### JetBrains IDE ### diff --git a/vendor/github.com/pion/rtcp/.golangci.yml b/vendor/github.com/pion/rtcp/.golangci.yml index 4b4025fbc8..6c7ceed691 100644 --- a/vendor/github.com/pion/rtcp/.golangci.yml +++ b/vendor/github.com/pion/rtcp/.golangci.yml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-FileCopyrightText: 2026 The Pion community # SPDX-License-Identifier: MIT version: "2" @@ -41,6 +41,7 @@ linters: - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments + - modernize # Replace and suggests simplifications to code - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. @@ -145,3 +146,6 @@ formatters: - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports exclusions: generated: lax +issues: + max-issues-per-linter: 0 + max-same-issues: 0 \ No newline at end of file diff --git a/vendor/github.com/pion/rtcp/.goreleaser.yml b/vendor/github.com/pion/rtcp/.goreleaser.yml index 30093e9d6d..8577d86de9 100644 --- a/vendor/github.com/pion/rtcp/.goreleaser.yml +++ b/vendor/github.com/pion/rtcp/.goreleaser.yml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-FileCopyrightText: 2026 The Pion community # SPDX-License-Identifier: MIT builds: diff --git a/vendor/github.com/pion/rtcp/LICENSE b/vendor/github.com/pion/rtcp/LICENSE index 491caf6b0f..d96df053b9 100644 --- a/vendor/github.com/pion/rtcp/LICENSE +++ b/vendor/github.com/pion/rtcp/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 The Pion community +Copyright (c) 2026 The Pion community Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/vendor/github.com/pion/rtcp/application_defined.go b/vendor/github.com/pion/rtcp/application_defined.go index ca5f844120..86ae1f6039 100644 --- a/vendor/github.com/pion/rtcp/application_defined.go +++ b/vendor/github.com/pion/rtcp/application_defined.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -88,7 +88,7 @@ func (a *ApplicationDefined) Unmarshal(rawPacket []byte) error { return errPacketTooShort } - if int(header.Length+1)*4 != len(rawPacket) { + if (int(header.Length)+1)*4 != len(rawPacket) { return errAppDefinedInvalidLength } diff --git a/vendor/github.com/pion/rtcp/codecov.yml b/vendor/github.com/pion/rtcp/codecov.yml index 263e4d45c6..b9639c2273 100644 --- a/vendor/github.com/pion/rtcp/codecov.yml +++ b/vendor/github.com/pion/rtcp/codecov.yml @@ -3,7 +3,7 @@ # # It is automatically copied from https://github.com/pion/.goassets repository. # -# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-FileCopyrightText: 2026 The Pion community # SPDX-License-Identifier: MIT coverage: diff --git a/vendor/github.com/pion/rtcp/compound_packet.go b/vendor/github.com/pion/rtcp/compound_packet.go index 1752b6412a..018eab0dc6 100644 --- a/vendor/github.com/pion/rtcp/compound_packet.go +++ b/vendor/github.com/pion/rtcp/compound_packet.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp diff --git a/vendor/github.com/pion/rtcp/doc.go b/vendor/github.com/pion/rtcp/doc.go index 22f06cc851..5db749fe24 100644 --- a/vendor/github.com/pion/rtcp/doc.go +++ b/vendor/github.com/pion/rtcp/doc.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT /* diff --git a/vendor/github.com/pion/rtcp/errors.go b/vendor/github.com/pion/rtcp/errors.go index 05e6847f10..9f6e4b7ca2 100644 --- a/vendor/github.com/pion/rtcp/errors.go +++ b/vendor/github.com/pion/rtcp/errors.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -13,6 +13,7 @@ var ( errBadFirstPacket = errors.New("rtcp: first packet in compound must be SR or RR") errMissingCNAME = errors.New("rtcp: compound missing SourceDescription with CNAME") errPacketBeforeCNAME = errors.New("rtcp: feedback packet seen before CNAME") + errTooManySSRCs = errors.New("rtcp: too many SSRCs") errTooManyReports = errors.New("rtcp: too many reports") errTooManyChunks = errors.New("rtcp: too many chunks") errTooManySources = errors.New("rtcp: too many sources") diff --git a/vendor/github.com/pion/rtcp/extended_report.go b/vendor/github.com/pion/rtcp/extended_report.go index 7b025c9040..9bf50e7421 100644 --- a/vendor/github.com/pion/rtcp/extended_report.go +++ b/vendor/github.com/pion/rtcp/extended_report.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp diff --git a/vendor/github.com/pion/rtcp/full_intra_request.go b/vendor/github.com/pion/rtcp/full_intra_request.go index 0d93c5c6f5..2dd6655c0d 100644 --- a/vendor/github.com/pion/rtcp/full_intra_request.go +++ b/vendor/github.com/pion/rtcp/full_intra_request.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // A FIREntry is a (SSRC, seqno) pair, as carried by FullIntraRequest. @@ -59,7 +60,7 @@ func (p *FullIntraRequest) Unmarshal(rawPacket []byte) error { return err } - if len(rawPacket) < (headerLength + int(4*header.Length)) { + if len(rawPacket) < (headerLength + 4*int(header.Length)) { return errPacketTooShort } @@ -68,16 +69,17 @@ func (p *FullIntraRequest) Unmarshal(rawPacket []byte) error { } // The FCI field MUST contain one or more FIR entries - if 4*header.Length-firOffset <= 0 || (4*header.Length)%8 != 0 { + if 4*int(header.Length)-firOffset <= 0 || (4*int(header.Length))%8 != 0 { return errBadLength } p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) - for i := headerLength + firOffset; i < (headerLength + int(header.Length*4)); i += 8 { + for i := headerLength + firOffset; i < (headerLength + 4*int(header.Length)); i += 8 { + entry := rawPacket[i : i+8] p.FIR = append(p.FIR, FIREntry{ - binary.BigEndian.Uint32(rawPacket[i:]), - rawPacket[i+4], + binary.BigEndian.Uint32(entry), + entry[4], }) } @@ -99,13 +101,14 @@ func (p *FullIntraRequest) MarshalSize() int { } func (p *FullIntraRequest) String() string { - out := fmt.Sprintf("FullIntraRequest %x %x", + var out strings.Builder + fmt.Fprintf(&out, "FullIntraRequest %x %x", p.SenderSSRC, p.MediaSSRC) for _, e := range p.FIR { - out += fmt.Sprintf(" (%x %v)", e.SSRC, e.SequenceNumber) + fmt.Fprintf(&out, " (%x %v)", e.SSRC, e.SequenceNumber) } - return out + return out.String() } // DestinationSSRC returns an array of SSRC values that this packet refers to. diff --git a/vendor/github.com/pion/rtcp/goodbye.go b/vendor/github.com/pion/rtcp/goodbye.go index c647743bec..f3a3324ded 100644 --- a/vendor/github.com/pion/rtcp/goodbye.go +++ b/vendor/github.com/pion/rtcp/goodbye.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // The Goodbye packet indicates that one or more sources are no longer active. @@ -154,11 +155,12 @@ func (g *Goodbye) DestinationSSRC() []uint32 { } func (g Goodbye) String() string { - out := "Goodbye\n" + var out strings.Builder + out.WriteString("Goodbye\n") for i, s := range g.Sources { - out += fmt.Sprintf("\tSource %d: %x\n", i, s) + fmt.Fprintf(&out, "\tSource %d: %x\n", i, s) } - out += fmt.Sprintf("\tReason: %s\n", g.Reason) + fmt.Fprintf(&out, "\tReason: %s\n", g.Reason) - return out + return out.String() } diff --git a/vendor/github.com/pion/rtcp/header.go b/vendor/github.com/pion/rtcp/header.go index f392e14ec8..72cee93870 100644 --- a/vendor/github.com/pion/rtcp/header.go +++ b/vendor/github.com/pion/rtcp/header.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -111,9 +111,9 @@ func (h Header) Marshal() ([]byte, error) { if h.Count > 31 { return nil, errInvalidHeader } - rawPacket[0] |= h.Count << countShift + rawPacket[0] |= h.Count << countShift //nolint:gosec // rawPacket is created with length headerLength (4) - rawPacket[1] = uint8(h.Type) + rawPacket[1] = uint8(h.Type) //nolint:gosec // rawPacket is created with length headerLength (4) binary.BigEndian.PutUint16(rawPacket[2:], h.Length) diff --git a/vendor/github.com/pion/rtcp/packet.go b/vendor/github.com/pion/rtcp/packet.go index 637d9cdf4e..447120b045 100644 --- a/vendor/github.com/pion/rtcp/packet.go +++ b/vendor/github.com/pion/rtcp/packet.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -68,7 +68,7 @@ func unmarshal(rawData []byte) (packet Packet, bytesprocessed int, err error) { return nil, 0, err } - bytesprocessed = int(header.Length+1) * 4 + bytesprocessed = (int(header.Length) + 1) * 4 if bytesprocessed > len(rawData) { return nil, 0, errPacketTooShort } diff --git a/vendor/github.com/pion/rtcp/packet_buffer.go b/vendor/github.com/pion/rtcp/packet_buffer.go index 5efaad1bcb..7f53c712e2 100644 --- a/vendor/github.com/pion/rtcp/packet_buffer.go +++ b/vendor/github.com/pion/rtcp/packet_buffer.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -61,7 +61,7 @@ func (b *packetBuffer) write(v any) error { return errWrongMarshalSize } if value.CanInterface() { - b.bytes[0] = byte(value.Uint()) + b.bytes[0] = byte(value.Uint()) //nolint:gosec // value.Kind() == reflect.Uint8 guarantees range } b.bytes = b.bytes[1:] case reflect.Uint16: @@ -109,7 +109,7 @@ func (b *packetBuffer) write(v any) error { return err } } else { - advance := int(value.Field(i).Type().Size()) + advance := int(value.Field(i).Type().Size()) //nolint:gosec // RTCP struct field sizes are small and controlled if len(b.bytes) < advance { return errWrongMarshalSize } @@ -200,7 +200,7 @@ func (b *packetBuffer) read(v any) error { return err } } else { - advance := int(value.Field(i).Type().Size()) + advance := int(value.Field(i).Type().Size()) //nolint:gosec //Size comes from type system and is bounded if len(b.bytes) < advance { return errWrongMarshalSize } @@ -245,7 +245,7 @@ func wireSize(v any) int { if value.Index(i).CanInterface() { size += wireSize(value.Index(i).Interface()) } else { - size += int(value.Index(i).Type().Size()) + size += int(value.Index(i).Type().Size()) //nolint:gosec // RTCP element sizes are small and bounded } } @@ -258,12 +258,12 @@ func wireSize(v any) int { if value.Field(i).CanInterface() { size += wireSize(value.Field(i).Interface()) } else { - size += int(value.Field(i).Type().Size()) + size += int(value.Field(i).Type().Size()) // nolint:gosec // Size comes from type system and is bounded } } default: - size = int(value.Type().Size()) + size = int(value.Type().Size()) // nolint:gosec // Size comes from type system and is bounde } return size diff --git a/vendor/github.com/pion/rtcp/packet_stringifier.go b/vendor/github.com/pion/rtcp/packet_stringifier.go index 8536f2f788..0755eaf9fa 100644 --- a/vendor/github.com/pion/rtcp/packet_stringifier.go +++ b/vendor/github.com/pion/rtcp/packet_stringifier.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -45,7 +45,7 @@ func formatField(name string, format string, f any, indent string) string { return fmt.Sprintf("%s%s: \n", out, name) } - isPacket := reflect.TypeOf(f).Implements(reflect.TypeOf((*Packet)(nil)).Elem()) + isPacket := reflect.TypeOf(f).Implements(reflect.TypeFor[Packet]()) // Resolve pointers to their underlying values if value.Type().Kind() == reflect.Ptr && !value.IsNil() { diff --git a/vendor/github.com/pion/rtcp/picture_loss_indication.go b/vendor/github.com/pion/rtcp/picture_loss_indication.go index 17379cda59..c6080276d6 100644 --- a/vendor/github.com/pion/rtcp/picture_loss_indication.go +++ b/vendor/github.com/pion/rtcp/picture_loss_indication.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp diff --git a/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go b/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go index d422033afc..b29069f794 100644 --- a/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go +++ b/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp diff --git a/vendor/github.com/pion/rtcp/raw_packet.go b/vendor/github.com/pion/rtcp/raw_packet.go index 71ac15281b..35828d43ae 100644 --- a/vendor/github.com/pion/rtcp/raw_packet.go +++ b/vendor/github.com/pion/rtcp/raw_packet.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp diff --git a/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go b/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go index cb6cdae68d..683db1c389 100644 --- a/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go +++ b/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -91,7 +91,11 @@ func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error buf[15] = 'B' // Write the length of the ssrcs to follow at the end - buf[16] = byte(len(p.SSRCs)) + if len(p.SSRCs) > math.MaxUint8 { + return 0, errTooManySSRCs + } + + buf[16] = byte(len(p.SSRCs)) //nolint:gosec // length validated above exp := 0 bitrate := p.Bitrate @@ -118,9 +122,9 @@ func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error // We can't quite use the binary package because // a) it's a uint24 and b) the exponent is only 6-bits // Just trust me; this is big-endian encoding. - buf[17] = byte(exp<<2) | byte(mantissa>>16) - buf[18] = byte(mantissa >> 8) - buf[19] = byte(mantissa) + buf[17] = byte(exp<<2) | byte(mantissa>>16) //nolint: gosec // mantissa is limited to 18 bits + buf[18] = byte(mantissa >> 8) //nolint: gosec // mantissa is limited to 18 bits + buf[19] = byte(mantissa) // nolint: gosec // mantissa is limited to 18 bits // Write the SSRCs at the very end. n = 20 @@ -276,7 +280,7 @@ func (p *ReceiverEstimatedMaximumBitrate) String() string { powers++ } - unit := bitUnits[powers] + unit := bitUnits[powers] //nolint:gosec // powers is bounded by loop condition return fmt.Sprintf("ReceiverEstimatedMaximumBitrate %x %.2f %s/s", p.SenderSSRC, bitrate, unit) } diff --git a/vendor/github.com/pion/rtcp/receiver_report.go b/vendor/github.com/pion/rtcp/receiver_report.go index 84c682daf5..7e08a2a506 100644 --- a/vendor/github.com/pion/rtcp/receiver_report.go +++ b/vendor/github.com/pion/rtcp/receiver_report.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // A ReceiverReport (RR) packet provides reception quality feedback for an RTP stream. @@ -188,12 +189,13 @@ func (r *ReceiverReport) DestinationSSRC() []uint32 { } func (r ReceiverReport) String() string { - out := fmt.Sprintf("ReceiverReport from %x\n", r.SSRC) - out += "\tSSRC \tLost\tLastSequence\n" + var out strings.Builder + fmt.Fprintf(&out, "ReceiverReport from %x\n", r.SSRC) + out.WriteString("\tSSRC \tLost\tLastSequence\n") for _, i := range r.Reports { - out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) + fmt.Fprintf(&out, "\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) } - out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions) + fmt.Fprintf(&out, "\tProfile Extension Data: %v\n", r.ProfileExtensions) - return out + return out.String() } diff --git a/vendor/github.com/pion/rtcp/reception_report.go b/vendor/github.com/pion/rtcp/reception_report.go index f2b45480b1..309e94a53e 100644 --- a/vendor/github.com/pion/rtcp/reception_report.go +++ b/vendor/github.com/pion/rtcp/reception_report.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -78,9 +78,9 @@ func (r ReceptionReport) Marshal() ([]byte, error) { return nil, errInvalidTotalLost } tlBytes := rawPacket[totalLostOffset:] - tlBytes[0] = byte(r.TotalLost >> 16) - tlBytes[1] = byte(r.TotalLost >> 8) - tlBytes[2] = byte(r.TotalLost) + tlBytes[0] = byte(r.TotalLost >> 16) //nolint:gosec // rawPacket is created with length receptionReportLength (24) + tlBytes[1] = byte(r.TotalLost >> 8) //nolint:gosec // rawPacket is created with length receptionReportLength (24) + tlBytes[2] = byte(r.TotalLost) //nolint:gosec // rawPacket is created with length receptionReportLength (24) binary.BigEndian.PutUint32(rawPacket[lastSeqOffset:], r.LastSequenceNumber) binary.BigEndian.PutUint32(rawPacket[jitterOffset:], r.Jitter) diff --git a/vendor/github.com/pion/rtcp/rfc8888.go b/vendor/github.com/pion/rtcp/rfc8888.go index ce5dfb1132..2719551975 100644 --- a/vendor/github.com/pion/rtcp/rfc8888.go +++ b/vendor/github.com/pion/rtcp/rfc8888.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -8,6 +8,7 @@ import ( "errors" "fmt" "math" + "strings" ) // https://www.rfc-editor.org/rfc/rfc8888.html#name-rtcp-congestion-control-fee @@ -144,7 +145,7 @@ func (b CCFeedbackReport) Marshal() ([]byte, error) { if err != nil { return nil, err } - length := 4 * (header.Length + 1) + length := 4 * (int(header.Length) + 1) buf := make([]byte, length) copy(buf[:headerLength], headerBuf) binary.BigEndian.PutUint32(buf[headerLength:], b.SenderSSRC) @@ -164,16 +165,17 @@ func (b CCFeedbackReport) Marshal() ([]byte, error) { } func (b CCFeedbackReport) String() string { - out := fmt.Sprintf("CCFB:\n\tHeader %v\n", b.Header()) - out += fmt.Sprintf("CCFB:\n\tSender SSRC %d\n", b.SenderSSRC) - out += fmt.Sprintf("\tReport Timestamp %d\n", b.ReportTimestamp) - out += "\tFeedback Reports \n" + var out strings.Builder + fmt.Fprintf(&out, "CCFB:\n\tHeader %v\n", b.Header()) + fmt.Fprintf(&out, "CCFB:\n\tSender SSRC %d\n", b.SenderSSRC) + fmt.Fprintf(&out, "\tReport Timestamp %d\n", b.ReportTimestamp) + out.WriteString("\tFeedback Reports \n") for _, report := range b.ReportBlocks { - out += fmt.Sprintf("%v ", report) + fmt.Fprintf(&out, "%v ", report) } - out += "\n" + out.WriteString("\n") - return out + return out.String() } // Unmarshal decodes the Congestion Control Feedback Report from binary. @@ -237,22 +239,21 @@ func (b *CCFeedbackReportBlock) len() int { } func (b CCFeedbackReportBlock) String() string { - out := fmt.Sprintf("\tReport Block Media SSRC %d\n", b.MediaSSRC) - out += fmt.Sprintf("\tReport Begin Sequence Nr %d\n", b.BeginSequence) - out += fmt.Sprintf("\tReport length %d\n\t", len(b.MetricBlocks)) + var out strings.Builder + fmt.Fprintf(&out, "\tReport Block Media SSRC %d\n", b.MediaSSRC) + fmt.Fprintf(&out, "\tReport Begin Sequence Nr %d\n", b.BeginSequence) + fmt.Fprintf(&out, "\tReport length %d\n\t", len(b.MetricBlocks)) for i, block := range b.MetricBlocks { //nolint:gosec // G115 - out += fmt.Sprintf( - "{nr: %d, rx: %v, ts: %v, ecn: %v} ", + fmt.Fprintf(&out, "{nr: %d, rx: %v, ts: %v, ecn: %v} ", b.BeginSequence+uint16(i), block.Received, block.ArrivalTimeOffset, - block.ECN, - ) + block.ECN) } - out += "\n" + out.WriteString("\n") - return out + return out.String() } // marshal encodes the Congestion Control Feedback Report Block in binary. @@ -301,7 +302,7 @@ func (b *CCFeedbackReportBlock) unmarshal(rawPacket []byte) error { } b.MetricBlocks = make([]CCFeedbackMetricBlock, numReports) - for i := int(0); i < numReports; i++ { + for i := range numReports { var mb CCFeedbackMetricBlock offset := reportsOffset + 2*i if err := mb.unmarshal(rawPacket[offset : offset+2]); err != nil { diff --git a/vendor/github.com/pion/rtcp/sender_report.go b/vendor/github.com/pion/rtcp/sender_report.go index 0ad8699492..9e5ed5768c 100644 --- a/vendor/github.com/pion/rtcp/sender_report.go +++ b/vendor/github.com/pion/rtcp/sender_report.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // A SenderReport (SR) packet provides reception quality feedback for an RTP stream. @@ -249,17 +250,18 @@ func (r *SenderReport) Header() Header { } func (r SenderReport) String() string { - out := fmt.Sprintf("SenderReport from %x\n", r.SSRC) - out += fmt.Sprintf("\tNTPTime:\t%d\n", r.NTPTime) - out += fmt.Sprintf("\tRTPTIme:\t%d\n", r.RTPTime) - out += fmt.Sprintf("\tPacketCount:\t%d\n", r.PacketCount) - out += fmt.Sprintf("\tOctetCount:\t%d\n", r.OctetCount) + var out strings.Builder + fmt.Fprintf(&out, "SenderReport from %x\n", r.SSRC) + fmt.Fprintf(&out, "\tNTPTime:\t%d\n", r.NTPTime) + fmt.Fprintf(&out, "\tRTPTIme:\t%d\n", r.RTPTime) + fmt.Fprintf(&out, "\tPacketCount:\t%d\n", r.PacketCount) + fmt.Fprintf(&out, "\tOctetCount:\t%d\n", r.OctetCount) - out += "\tSSRC \tLost\tLastSequence\n" + out.WriteString("\tSSRC \tLost\tLastSequence\n") for _, i := range r.Reports { - out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) + fmt.Fprintf(&out, "\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) } - out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions) + fmt.Fprintf(&out, "\tProfile Extension Data: %v\n", r.ProfileExtensions) - return out + return out.String() } diff --git a/vendor/github.com/pion/rtcp/slice_loss_indication.go b/vendor/github.com/pion/rtcp/slice_loss_indication.go index 43e2d80986..66eda54577 100644 --- a/vendor/github.com/pion/rtcp/slice_loss_indication.go +++ b/vendor/github.com/pion/rtcp/slice_loss_indication.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -72,7 +72,7 @@ func (p *SliceLossIndication) Unmarshal(rawPacket []byte) error { return err } - if len(rawPacket) < (headerLength + int(4*header.Length)) { + if len(rawPacket) < (headerLength + 4*int(header.Length)) { return errPacketTooShort } @@ -82,7 +82,7 @@ func (p *SliceLossIndication) Unmarshal(rawPacket []byte) error { p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) - for i := headerLength + sliOffset; i < (headerLength + int(header.Length*4)); i += 4 { + for i := headerLength + sliOffset; i < (headerLength + 4*int(header.Length)); i += 4 { sli := binary.BigEndian.Uint32(rawPacket[i:]) p.SLI = append(p.SLI, SLIEntry{ First: uint16((sli >> 19) & 0x1FFF), //nolint:gosec // G115 diff --git a/vendor/github.com/pion/rtcp/source_description.go b/vendor/github.com/pion/rtcp/source_description.go index 6d6f2a0a75..951bf8f2c9 100644 --- a/vendor/github.com/pion/rtcp/source_description.go +++ b/vendor/github.com/pion/rtcp/source_description.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // SDESType is the item type used in the RTCP SDES control packet. @@ -313,14 +314,14 @@ func (s SourceDescriptionItem) Marshal() ([]byte, error) { rawPacket := make([]byte, sdesTypeLen+sdesOctetCountLen) - rawPacket[sdesTypeOffset] = uint8(s.Type) + rawPacket[sdesTypeOffset] = uint8(s.Type) //nolint:gosec // rawPacket is created with length 2 txtBytes := []byte(s.Text) octetCount := len(txtBytes) if octetCount > sdesMaxOctetCount { return nil, errSDESTextTooLong } - rawPacket[sdesOctetCountOffset] = uint8(octetCount) + rawPacket[sdesOctetCountOffset] = uint8(octetCount) //nolint:gosec // rawPacket is created with length 2 rawPacket = append(rawPacket, txtBytes...) //nolint:makezero @@ -365,10 +366,11 @@ func (s *SourceDescription) DestinationSSRC() []uint32 { } func (s *SourceDescription) String() string { - out := "Source Description:\n" + var out strings.Builder + out.WriteString("Source Description:\n") for _, c := range s.Chunks { - out += fmt.Sprintf("\t%x: %s\n", c.Source, c.Items) + fmt.Fprintf(&out, "\t%x: %s\n", c.Source, c.Items) } - return out + return out.String() } diff --git a/vendor/github.com/pion/rtcp/transport_layer_cc.go b/vendor/github.com/pion/rtcp/transport_layer_cc.go index de464cb4fa..79176c3a2b 100644 --- a/vendor/github.com/pion/rtcp/transport_layer_cc.go +++ b/vendor/github.com/pion/rtcp/transport_layer_cc.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -10,6 +10,7 @@ import ( "errors" "fmt" "math" + "strings" ) // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5 @@ -223,20 +224,20 @@ func (r *StatusVectorChunk) Unmarshal(rawPacket []byte) error { r.SymbolSize = getNBitsFromByte(rawPacket[0], 1, 1) if r.SymbolSize == TypeTCCSymbolSizeOneBit { - for i := uint16(0); i < 6; i++ { + for i := range uint16(6) { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[0], 2+i, 1)) } - for i := uint16(0); i < 8; i++ { + for i := range uint16(8) { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[1], i, 1)) } return nil } if r.SymbolSize == TypeTCCSymbolSizeTwoBit { - for i := uint16(0); i < 3; i++ { + for i := range uint16(3) { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[0], 2+i*2, 2)) } - for i := uint16(0); i < 4; i++ { + for i := range uint16(4) { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[1], i*2, 2)) } @@ -270,7 +271,7 @@ func (r RecvDelta) Marshal() ([]byte, error) { // small delta if r.Type == TypeTCCPacketReceivedSmallDelta && delta >= 0 && delta <= math.MaxUint8 { deltaChunk := make([]byte, 1) - deltaChunk[0] = byte(delta) + deltaChunk[0] = byte(delta) //nolint:gosec // deltaChunk is created with length 1 return deltaChunk, nil } @@ -278,7 +279,7 @@ func (r RecvDelta) Marshal() ([]byte, error) { // big delta if r.Type == TypeTCCPacketReceivedLargeDelta && delta >= math.MinInt16 && delta <= math.MaxInt16 { deltaChunk := make([]byte, 2) - binary.BigEndian.PutUint16(deltaChunk, uint16(delta)) + binary.BigEndian.PutUint16(deltaChunk, uint16(delta)) //nolint:gosec //delta is validated to fit in uint16 return deltaChunk, nil } @@ -392,24 +393,25 @@ func (t *TransportLayerCC) MarshalSize() int { } func (t TransportLayerCC) String() string { - out := fmt.Sprintf("TransportLayerCC:\n\tHeader %v\n", t.Header) - out += fmt.Sprintf("TransportLayerCC:\n\tSender Ssrc %d\n", t.SenderSSRC) - out += fmt.Sprintf("\tMedia Ssrc %d\n", t.MediaSSRC) - out += fmt.Sprintf("\tBase Sequence Number %d\n", t.BaseSequenceNumber) - out += fmt.Sprintf("\tStatus Count %d\n", t.PacketStatusCount) - out += fmt.Sprintf("\tReference Time %d\n", t.ReferenceTime) - out += fmt.Sprintf("\tFeedback Packet Count %d\n", t.FbPktCount) - out += "\tPacketChunks " + var out strings.Builder + fmt.Fprintf(&out, "TransportLayerCC:\n\tHeader %v\n", t.Header) + fmt.Fprintf(&out, "TransportLayerCC:\n\tSender Ssrc %d\n", t.SenderSSRC) + fmt.Fprintf(&out, "\tMedia Ssrc %d\n", t.MediaSSRC) + fmt.Fprintf(&out, "\tBase Sequence Number %d\n", t.BaseSequenceNumber) + fmt.Fprintf(&out, "\tStatus Count %d\n", t.PacketStatusCount) + fmt.Fprintf(&out, "\tReference Time %d\n", t.ReferenceTime) + fmt.Fprintf(&out, "\tFeedback Packet Count %d\n", t.FbPktCount) + out.WriteString("\tPacketChunks ") for _, chunk := range t.PacketChunks { - out += fmt.Sprintf("%+v ", chunk) + fmt.Fprintf(&out, "%+v ", chunk) } - out += "\n\tRecvDeltas " + out.WriteString("\n\tRecvDeltas ") for _, delta := range t.RecvDeltas { - out += fmt.Sprintf("%+v ", delta) + fmt.Fprintf(&out, "%+v ", delta) } - out += "\n" + out.WriteString("\n") - return out + return out.String() } // Marshal encodes the TransportLayerCC in binary. @@ -470,13 +472,13 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { // https://tools.ietf.org/html/rfc4585#page-33 // header's length + payload's length - totalLength := 4 * (t.Header.Length + 1) + totalLength := 4 * (int(t.Header.Length) + 1) if totalLength < headerLength+packetChunkOffset { return errPacketTooShort } - if len(rawPacket) < int(totalLength) { + if len(rawPacket) < totalLength { return errPacketTooShort } @@ -491,7 +493,7 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { t.ReferenceTime = get24BitsFromBytes(rawPacket[headerLength+referenceTimeOffset : headerLength+referenceTimeOffset+3]) t.FbPktCount = rawPacket[headerLength+fbPktCountOffset] - packetStatusPos := uint16(headerLength + packetChunkOffset) + packetStatusPos := int(headerLength + packetChunkOffset) var processedPacketNum uint16 for processedPacketNum < t.PacketStatusCount { if packetStatusPos+packetStatusChunkLength >= totalLength { @@ -511,7 +513,7 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { packetNumberToProcess := localMin(t.PacketStatusCount-processedPacketNum, packetStatus.RunLength) if packetStatus.PacketStatusSymbol == TypeTCCPacketReceivedSmallDelta || packetStatus.PacketStatusSymbol == TypeTCCPacketReceivedLargeDelta { - for j := uint16(0); j < packetNumberToProcess; j++ { + for range packetNumberToProcess { t.RecvDeltas = append(t.RecvDeltas, &RecvDelta{Type: packetStatus.PacketStatusSymbol}) } } diff --git a/vendor/github.com/pion/rtcp/transport_layer_nack.go b/vendor/github.com/pion/rtcp/transport_layer_nack.go index c0e3b8f8de..1918e05643 100644 --- a/vendor/github.com/pion/rtcp/transport_layer_nack.go +++ b/vendor/github.com/pion/rtcp/transport_layer_nack.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp @@ -7,6 +7,7 @@ import ( "encoding/binary" "fmt" "math" + "strings" ) // PacketBitmap shouldn't be used like a normal integral, @@ -131,7 +132,7 @@ func (p *TransportLayerNack) Unmarshal(rawPacket []byte) error { return err } - if len(rawPacket) < (headerLength + int(4*header.Length)) { + if len(rawPacket) < (headerLength + 4*int(header.Length)) { return errPacketTooShort } @@ -140,13 +141,13 @@ func (p *TransportLayerNack) Unmarshal(rawPacket []byte) error { } // The FCI field MUST contain at least one and MAY contain more than one Generic NACK - if 4*header.Length <= nackOffset { + if 4*int(header.Length) <= nackOffset { return errBadLength } p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) - for i := headerLength + nackOffset; i < (headerLength + int(header.Length*4)); i += 4 { + for i := headerLength + nackOffset; i < (headerLength + 4*int(header.Length)); i += 4 { p.Nacks = append(p.Nacks, NackPair{ binary.BigEndian.Uint16(rawPacket[i:]), PacketBitmap(binary.BigEndian.Uint16(rawPacket[i+2:])), @@ -171,14 +172,15 @@ func (p *TransportLayerNack) Header() Header { } func (p TransportLayerNack) String() string { - out := fmt.Sprintf("TransportLayerNack from %x\n", p.SenderSSRC) - out += fmt.Sprintf("\tMedia Ssrc %x\n", p.MediaSSRC) - out += "\tID\tLostPackets\n" + var out strings.Builder + fmt.Fprintf(&out, "TransportLayerNack from %x\n", p.SenderSSRC) + fmt.Fprintf(&out, "\tMedia Ssrc %x\n", p.MediaSSRC) + out.WriteString("\tID\tLostPackets\n") for _, i := range p.Nacks { - out += fmt.Sprintf("\t%d\t%b\n", i.PacketID, i.LostPackets) + fmt.Fprintf(&out, "\t%d\t%b\n", i.PacketID, i.LostPackets) } - return out + return out.String() } // DestinationSSRC returns an array of SSRC values that this packet refers to. diff --git a/vendor/github.com/pion/rtcp/util.go b/vendor/github.com/pion/rtcp/util.go index 705b290c1e..d4f2c692ff 100644 --- a/vendor/github.com/pion/rtcp/util.go +++ b/vendor/github.com/pion/rtcp/util.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-FileCopyrightText: 2026 The Pion community // SPDX-License-Identifier: MIT package rtcp diff --git a/vendor/github.com/pion/rtp/codecs/common.go b/vendor/github.com/pion/rtp/codecs/common.go index 41ff6f39e7..e44050dbbd 100644 --- a/vendor/github.com/pion/rtp/codecs/common.go +++ b/vendor/github.com/pion/rtp/codecs/common.go @@ -38,3 +38,14 @@ func (d *videoDepacketizer) IsPartitionTail(marker bool, _ []byte) bool { func (d *videoDepacketizer) SetZeroAllocation(zeroAllocation bool) { d.zeroAllocation = zeroAllocation } + +// resizeUint16Slice resizes the provided slice to the desired size, or +// allocates a new slice if needed. The contents are unspecified; the +// caller must overwrite every element. +func resizeUint16Slice(s []uint16, desiredSize int) []uint16 { + if cap(s) >= desiredSize { + return s[:desiredSize] + } + + return make([]uint16, desiredSize) +} diff --git a/vendor/github.com/pion/rtp/codecs/vp9_packet.go b/vendor/github.com/pion/rtp/codecs/vp9_packet.go index 23c1e56e6a..2eff473958 100644 --- a/vendor/github.com/pion/rtp/codecs/vp9_packet.go +++ b/vendor/github.com/pion/rtp/codecs/vp9_packet.go @@ -452,8 +452,8 @@ func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { // nolint p.NG = 0 if p.Y { - p.Width = make([]uint16, NS) - p.Height = make([]uint16, NS) + p.Width = resizeUint16Slice(p.Width, int(NS)) + p.Height = resizeUint16Slice(p.Height, int(NS)) for i := 0; i < int(NS); i++ { if len(packet) <= (pos + 3) { return pos, errShortPacket @@ -482,16 +482,21 @@ func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { // nolint p.PGTID = append(p.PGTID, packet[pos]>>5) p.PGU = append(p.PGU, packet[pos]&0x10 != 0) - R := (packet[pos] >> 2) & 0x3 + reference := int((packet[pos] >> 2) & 0x3) pos++ - p.PGPDiff = append(p.PGPDiff, []uint8{}) + if i >= cap(p.PGPDiff) { + p.PGPDiff = append(p.PGPDiff, []uint8{}) + } else { + p.PGPDiff = p.PGPDiff[:i+1] + p.PGPDiff[i] = p.PGPDiff[i][:0] + } - if len(packet) <= (pos + int(R) - 1) { + if len(packet) <= (pos + reference - 1) { return pos, errShortPacket } - for j := 0; j < int(R); j++ { + for range reference { p.PGPDiff[i] = append(p.PGPDiff[i], packet[pos]) pos++ } diff --git a/vendor/github.com/pion/sctp/association.go b/vendor/github.com/pion/sctp/association.go index 3ce0de88da..366f92fea5 100644 --- a/vendor/github.com/pion/sctp/association.go +++ b/vendor/github.com/pion/sctp/association.go @@ -270,17 +270,18 @@ type Association struct { recvZeroChecksum bool // Congestion control parameters - maxReceiveBufferSize uint32 - maxMessageSize uint32 - cwnd uint32 // my congestion window size - rwnd uint32 // calculated peer's receiver windows size - ssthresh uint32 // slow start threshold - partialBytesAcked uint32 - inFastRecovery bool - fastRecoverExitPoint uint32 - minCwnd uint32 // Minimum congestion window - fastRtxWnd uint32 // Send window for fast retransmit - cwndCAStep uint32 // Step of congestion window increase at Congestion Avoidance + maxReceiveBufferSize uint32 + maxMessageSize uint32 + maxReassemblyQueueEntries uint32 + cwnd uint32 // my congestion window size + rwnd uint32 // calculated peer's receiver windows size + ssthresh uint32 // slow start threshold + partialBytesAcked uint32 + inFastRecovery bool + fastRecoverExitPoint uint32 + minCwnd uint32 // Minimum congestion window + fastRtxWnd uint32 // Send window for fast retransmit + cwndCAStep uint32 // Step of congestion window increase at Congestion Avoidance // RTX & Ack timer rtoMgr *rtoManager @@ -390,6 +391,9 @@ type Config struct { // User message interleaving config options interleaving *interleavingSettings + // Reassembly queue config options + maxReassemblyQueueEntries uint32 + // SNAP/sctp-init snapConfig *snapConfig @@ -558,6 +562,9 @@ func (c Config) applyServer(cfg *Config) error { //nolint:dupl,cyclop if c.MaxMessageSize != 0 { cfg.MaxMessageSize = c.MaxMessageSize } + if c.maxReassemblyQueueEntries != 0 { + cfg.maxReassemblyQueueEntries = c.maxReassemblyQueueEntries + } if c.RTOMax != 0 { cfg.RTOMax = c.RTOMax } @@ -671,6 +678,9 @@ func (c Config) applyClient(cfg *Config) error { //nolint:dupl,cyclop if c.MaxMessageSize != 0 { cfg.MaxMessageSize = c.MaxMessageSize } + if c.maxReassemblyQueueEntries != 0 { + cfg.maxReassemblyQueueEntries = c.maxReassemblyQueueEntries + } if c.RTOMax != 0 { cfg.RTOMax = c.RTOMax } @@ -748,12 +758,13 @@ func createAssociationFromConfigWithTsn(cfg *Config, tsn uint32) *Association { } assoc := &Association{ - netConn: cfg.NetConn, - maxReceiveBufferSize: maxReceiveBufferSize, - maxMessageSize: maxMessageSize, - minCwnd: cfg.MinCwnd, - fastRtxWnd: cfg.FastRtxWnd, - cwndCAStep: cfg.CwndCAStep, + netConn: cfg.NetConn, + maxReceiveBufferSize: maxReceiveBufferSize, + maxMessageSize: maxMessageSize, + maxReassemblyQueueEntries: cfg.maxReassemblyQueueEntries, + minCwnd: cfg.MinCwnd, + fastRtxWnd: cfg.FastRtxWnd, + cwndCAStep: cfg.CwndCAStep, myMaxNumOutboundStreams: math.MaxUint16, myMaxNumInboundStreams: math.MaxUint16, @@ -2444,10 +2455,13 @@ func (a *Association) createStream(streamIdentifier uint16, accept bool) *Stream stream := &Stream{ association: a, streamIdentifier: streamIdentifier, - reassemblyQueue: newReassemblyQueue(streamIdentifier, a.maxReceiveBufferSize), - log: a.log, - name: fmt.Sprintf("%d:%s", streamIdentifier, a.name), - writeDeadline: deadline.New(), + reassemblyQueue: newReassemblyQueue( + streamIdentifier, + a.maxReassemblyQueueEntries, + ), + log: a.log, + name: fmt.Sprintf("%d:%s", streamIdentifier, a.name), + writeDeadline: deadline.New(), } stream.readNotifier = sync.NewCond(&stream.lock) diff --git a/vendor/github.com/pion/sctp/association_options.go b/vendor/github.com/pion/sctp/association_options.go index 6b2d276940..80e21cd023 100644 --- a/vendor/github.com/pion/sctp/association_options.go +++ b/vendor/github.com/pion/sctp/association_options.go @@ -136,6 +136,16 @@ func WithMaxMessageSize(size uint32) AssociationOption { }) } +// WithMaxReassemblyQueueEntries caps the number of DATA entries and I-DATA MIDs queued per stream. +// A value of 0 disables the cap. By default this cap is disabled. +func WithMaxReassemblyQueueEntries(maxEntries uint32) AssociationOption { + return sharedOption(func(c *Config) error { + c.maxReassemblyQueueEntries = maxEntries + + return nil + }) +} + // WithRTOMax sets the max retransmission timeout in ms for the association. func WithRTOMax(rtoMax float64) AssociationOption { return sharedOption(func(c *Config) error { diff --git a/vendor/github.com/pion/sctp/reassembly_queue.go b/vendor/github.com/pion/sctp/reassembly_queue.go index cf1deb8b95..cd9a8311cb 100644 --- a/vendor/github.com/pion/sctp/reassembly_queue.go +++ b/vendor/github.com/pion/sctp/reassembly_queue.go @@ -57,12 +57,14 @@ func newChunkSet(ssn uint16, ppi PayloadProtocolIdentifier) *chunkSet { func (set *chunkSet) push(chunk *chunkPayloadData) bool { // check if dup - for _, c := range set.chunks { - if c.tsn == chunk.tsn { - return false - } + if set.hasTSN(chunk.tsn) { + return false } + return set.pushNoDuplicate(chunk) +} + +func (set *chunkSet) pushNoDuplicate(chunk *chunkPayloadData) bool { // append and sort set.chunks = append(set.chunks, chunk) sortChunksByTSN(set.chunks) @@ -73,6 +75,16 @@ func (set *chunkSet) push(chunk *chunkPayloadData) bool { return complete } +func (set *chunkSet) hasTSN(tsn uint32) bool { + for _, c := range set.chunks { + if c.tsn == tsn { + return true + } + } + + return false +} + func (set *chunkSet) isComplete() bool { // Condition for complete set // 0. Has at least one chunk. @@ -197,29 +209,18 @@ type reassemblyQueue struct { unorderedMIDMap map[uint32]*chunkSetMID useInterleaving bool nBytes uint64 - maxMIDEntries int + maxEntries uint32 } var ( errTryAgain = errors.New("try again") - errReassemblyQueueMIDLimitExceeded = errors.New("reassembly queue i-data message identifier limit exceeded") -) - -const ( - // reassemblyMIDLimitBytesPerEntry is the receive-buffer budget allotted per - // undelivered interleaved (i-data) message. The MID-entry cap is - // maxReceiveBufferSize/reassemblyMIDLimitBytesPerEntry, so reassembly memory - // scales with the configured buffer. the cap only bites pathological floods of tiny or - // header-only messages that a_rwnd cannot bound. - reassemblyMIDLimitBytesPerEntry = 64 + errReassemblyQueueLimitExceeded = errors.New("reassembly queue data limit exceeded") - maxReassemblyQueueMIDEntries = 1024 + errReassemblyQueueMIDLimitExceeded = errors.New("reassembly queue i-data message identifier limit exceeded") ) -func newReassemblyQueue(si uint16, maxReceiveBufferSize uint32) *reassemblyQueue { - maxMIDEntries := max(int(maxReceiveBufferSize/reassemblyMIDLimitBytesPerEntry), maxReassemblyQueueMIDEntries) - +func newReassemblyQueue(si uint16, maxEntries uint32) *reassemblyQueue { // From RFC 4960 Sec 6.5: // The Stream Sequence Number in all the streams MUST start from 0 when // the association is established. Also, when the Stream Sequence @@ -235,8 +236,42 @@ func newReassemblyQueue(si uint16, maxReceiveBufferSize uint32) *reassemblyQueue unorderedMID: make([]*chunkSetMID, 0), orderedMIDMap: map[uint32]*chunkSetMID{}, unorderedMIDMap: map[uint32]*chunkSetMID{}, - maxMIDEntries: maxMIDEntries, + maxEntries: maxEntries, + } +} + +func isReassemblyQueueLimitReached(maxEntries uint32, nEntries int) bool { + return maxEntries > 0 && int64(nEntries) >= int64(maxEntries) +} + +func (r *reassemblyQueue) isDataLimitReached(nEntries int) bool { + return isReassemblyQueueLimitReached(r.maxEntries, nEntries) +} + +func (r *reassemblyQueue) hasDataLimit() bool { + return r.maxEntries > 0 +} + +func (r *reassemblyQueue) isMIDLimitReached(nEntries int) bool { + return isReassemblyQueueLimitReached(r.maxEntries, nEntries) +} + +func (r *reassemblyQueue) orderedDataEntryCount() int { + nEntries := 0 + for _, set := range r.ordered { + nEntries += len(set.chunks) } + + return nEntries +} + +func (r *reassemblyQueue) unorderedDataEntryCount() int { + nEntries := len(r.unorderedChunks) + for _, set := range r.unordered { + nEntries += len(set.chunks) + } + + return nEntries } func (r *reassemblyQueue) push(chunk *chunkPayloadData) bool { @@ -259,6 +294,10 @@ func (r *reassemblyQueue) pushWithError(chunk *chunkPayloadData) (bool, error) { } if chunk.unordered { + if r.hasDataLimit() && r.isDataLimitReached(r.unorderedDataEntryCount()) { + return false, errReassemblyQueueLimitExceeded + } + // First, insert into unorderedChunks array r.unorderedChunks = append(r.unorderedChunks, chunk) atomic.AddUint64(&r.nBytes, uint64(len(chunk.userData))) @@ -303,7 +342,13 @@ func (r *reassemblyQueue) pushWithError(chunk *chunkPayloadData) (bool, error) { } } - // If not found, create a new chunkSet + // Reject a new queued DATA entry once the descriptor cap is reached. + if cset != nil && cset.hasTSN(chunk.tsn) { + return false, nil + } + if r.hasDataLimit() && r.isDataLimitReached(r.orderedDataEntryCount()) { + return false, errReassemblyQueueLimitExceeded + } if cset == nil { cset = newChunkSet(chunk.streamSequenceNumber, chunk.payloadType) r.ordered = append(r.ordered, cset) @@ -314,7 +359,7 @@ func (r *reassemblyQueue) pushWithError(chunk *chunkPayloadData) (bool, error) { atomic.AddUint64(&r.nBytes, uint64(len(chunk.userData))) - return cset.push(chunk), nil + return cset.pushNoDuplicate(chunk), nil } func (r *reassemblyQueue) pushIData(chunk *chunkPayloadData) (bool, error) { @@ -339,7 +384,7 @@ func (r *reassemblyQueue) pushUnorderedIData(chunk *chunkPayloadData) (bool, err } cset := r.unorderedMIDMap[chunk.messageIdentifier] if cset == nil { - if r.unorderedMIDEntryCount() >= r.maxMIDEntries { + if r.isMIDLimitReached(r.unorderedMIDEntryCount()) { return false, errReassemblyQueueMIDLimitExceeded } cset = newChunkSetMID(chunk.messageIdentifier, chunk.payloadType) @@ -372,7 +417,7 @@ func (r *reassemblyQueue) pushOrderedIData(chunk *chunkPayloadData) (bool, error } cset := r.orderedMIDMap[chunk.messageIdentifier] if cset == nil { - if len(r.orderedMIDMap) >= r.maxMIDEntries { + if r.isMIDLimitReached(len(r.orderedMIDMap)) { return false, errReassemblyQueueMIDLimitExceeded } cset = newChunkSetMID(chunk.messageIdentifier, chunk.payloadType) diff --git a/vendor/github.com/pion/turn/v5/internal/client/binding.go b/vendor/github.com/pion/turn/v5/internal/client/binding.go index eefeb17079..89628d150b 100644 --- a/vendor/github.com/pion/turn/v5/internal/client/binding.go +++ b/vendor/github.com/pion/turn/v5/internal/client/binding.go @@ -24,6 +24,8 @@ type bindingState int32 const ( bindingStateIdle bindingState = iota bindingStateRequest + bindingStateUnknown + bindingStateReadyUnknown bindingStateReady bindingStateRefresh bindingStateFailed @@ -64,7 +66,7 @@ func (b *binding) refreshedAt() time.Time { func (b *binding) ok() bool { state := b.state() - return state == bindingStateReady || state == bindingStateRefresh + return state == bindingStateReady || state == bindingStateRefresh || state == bindingStateReadyUnknown } // Thread-safe binding map. diff --git a/vendor/github.com/pion/turn/v5/internal/client/errors.go b/vendor/github.com/pion/turn/v5/internal/client/errors.go index 6991e92383..4aa0e423c9 100644 --- a/vendor/github.com/pion/turn/v5/internal/client/errors.go +++ b/vendor/github.com/pion/turn/v5/internal/client/errors.go @@ -3,9 +3,7 @@ package client -import ( - "errors" -) +import "errors" var ( errFake = errors.New("fake error") @@ -23,6 +21,8 @@ var ( errInvalidTURNAddress = errors.New("invalid TURN server address") errUnexpectedSTUNRequestMessage = errors.New("unexpected STUN request message") errCannotBindChannel = errors.New("cannot bind channel") + errChannelBindBadRequest = errors.New("channel bind bad request") + errChannelBindTransactionFailed = errors.New("channel bind transaction failed") ) type timeoutError struct { diff --git a/vendor/github.com/pion/turn/v5/internal/client/udp_conn.go b/vendor/github.com/pion/turn/v5/internal/client/udp_conn.go index 2f1ed89e8f..95dcc3ab28 100644 --- a/vendor/github.com/pion/turn/v5/internal/client/udp_conn.go +++ b/vendor/github.com/pion/turn/v5/internal/client/udp_conn.go @@ -10,6 +10,7 @@ import ( "io" "math" "net" + "sync" "time" "github.com/pion/stun/v3" @@ -42,6 +43,7 @@ type UDPConn struct { checkBindingsTimer *PeriodicTimer // Thread-safe readCh chan *inboundData // Thread-safe closeCh chan struct{} // Thread-safe + closeMutex sync.Mutex // Thread-safe bindingRefreshInterval time.Duration // Read-only allocation } @@ -188,6 +190,14 @@ func (c *UDPConn) WriteTo(payload []byte, addr net.Addr) (int, error) { //nolint if !ok { return 0, errUDPAddrCast } + if c.isClosed() { + return 0, &net.OpError{ + Op: "write", + Net: c.LocalAddr().Network(), + Addr: c.LocalAddr(), + Err: errClosed, + } + } // Check if we have a permission for the destination IP addr perm, ok := c.permMap.find(addr) @@ -257,6 +267,9 @@ func (c *UDPConn) WriteTo(payload []byte, addr net.Addr) (int, error) { //nolint // Close closes the connection. // Any blocked ReadFrom or WriteTo operations will be unblocked and return errors. func (c *UDPConn) Close() error { + c.closeMutex.Lock() + defer c.closeMutex.Unlock() + c.refreshAllocTimer.Stop() c.refreshPermsTimer.Stop() c.checkBindingsTimer.Stop() @@ -278,6 +291,15 @@ func (c *UDPConn) LocalAddr() net.Addr { return c.relayedAddr } +func (c *UDPConn) isClosed() bool { + select { + case <-c.closeCh: + return true + default: + return false + } +} + // SetDeadline sets the read and write deadlines associated // with the connection. It is equivalent to calling both // SetReadDeadline and SetWriteDeadline. @@ -415,41 +437,113 @@ func (c *UDPConn) FindAddrByChannelNumber(chNum uint16) (net.Addr, bool) { } func (c *UDPConn) maybeBind(bound *binding) { - bind := func() { - var err error - for range maxRetryAttempts { - if err = c.bind(bound); !errors.Is(err, errTryAgain) { - break - } - } - if err != nil { - c.log.Warnf("Failed to bind channel %d: %s", bound.number, err) - bound.setState(bindingStateFailed) - - return - } - bound.setRefreshedAt(time.Now()) - bound.setState(bindingStateReady) - } - // Block only callers with the same binding until // the binding transaction has been complete bound.muBind.Lock() defer bound.muBind.Unlock() - state := bound.state() + startState, ok := c.startBinding(bound) + if !ok { + return + } + + // Establish binding with the server if eligible + // with regard to cases right above. + go c.bindChannel(bound, startState) +} + +func (c *UDPConn) startBinding(bound *binding) (bindingState, bool) { + startState := bound.state() switch { - case state == bindingStateIdle: + case startState == bindingStateIdle || startState == bindingStateUnknown: bound.setState(bindingStateRequest) - case state == bindingStateReady && time.Since(bound.refreshedAt()) > c.bindingRefreshInterval: + case startState == bindingStateReadyUnknown: + bound.setState(bindingStateRefresh) + case startState == bindingStateReady && time.Since(bound.refreshedAt()) > c.bindingRefreshInterval: bound.setState(bindingStateRefresh) default: + return startState, false + } + + return startState, true +} + +func (c *UDPConn) bindChannel(bound *binding, startState bindingState) { + var err error + for range maxRetryAttempts { + if err = c.bind(bound); !errors.Is(err, errTryAgain) { + break + } + } + if err != nil { + c.handleBindChannelError(bound, startState, err) + return } - // Establish binding with the server if eligible - // with regard to cases right above. - go bind() + bound.setRefreshedAt(time.Now()) + bound.setState(bindingStateReady) +} + +func (c *UDPConn) handleBindChannelError(bound *binding, startState bindingState, err error) { + if c.recoverChannelBindBadRequest(bound, startState, err) { + return + } + + c.log.Warnf("Failed to bind channel %d: %s", bound.number, err) + if errors.Is(err, errChannelBindTransactionFailed) { + if bindingStateWasReady(startState) { + bound.setState(bindingStateReadyUnknown) + } else { + bound.setState(bindingStateUnknown) + } + + return + } + + bound.setState(bindingStateFailed) + if errors.Is(err, errChannelBindBadRequest) { + c.closeAfterChannelBindBadRequest(bound) + } +} + +func (c *UDPConn) recoverChannelBindBadRequest(bound *binding, startState bindingState, err error) bool { + if !errors.Is(err, errChannelBindBadRequest) { + return false + } + if !bindingStateWasReady(startState) { + return false + } + + // If this binding was previously confirmed, a refresh transaction failure or + // unexpected 400 does not prove that the saved channel mapping is wrong. The + // server may still have the old binding, and switching channels would be + // worse because it can trigger "same peer with different channel number" (like what we get from Coturn). + // This Keep the saved mapping usable and retry refresh later. + c.log.Warnf( + "ChannelBind returned 400 for saved binding %s on channel %d; keeping binding ready", + bound.addr, + bound.number, + ) + bound.setState(bindingStateReady) + + return true +} + +func bindingStateWasReady(state bindingState) bool { + return state == bindingStateReady || state == bindingStateReadyUnknown +} + +func (c *UDPConn) closeAfterChannelBindBadRequest(bound *binding) { + c.log.Warnf( + "ChannelBind rejected with 400 for %s on channel %d; closing TURN allocation", + bound.addr, + bound.number, + ) + + if err := c.Close(); err != nil && !errors.Is(err, errAlreadyClosed) { + c.log.Warnf("Failed to close TURN allocation after ChannelBind 400: %s", err) + } } func (c *UDPConn) bind(bound *binding) error { @@ -472,29 +566,36 @@ func (c *UDPConn) bind(bound *binding) error { trRes, err := c.client.PerformTransaction(msg, c.serverAddr, false) if err != nil { - return err + return fmt.Errorf("%w: %w", errChannelBindTransactionFailed, err) } res := trRes.Msg if res.Type.Class == stun.ClassErrorResponse { - var code stun.ErrorCodeAttribute - if err = code.GetFrom(res); err == nil { - if code.Code == stun.CodeStaleNonce { - c.setNonceFromMsg(res) + return c.handleChannelBindErrorResponse(res) + } - return errTryAgain - } + c.log.Debugf("Channel binding successful: %s %d", bound.addr, bound.number) - return fmt.Errorf("%w: received error %d", errCannotBindChannel, code.Code) // nolint:err113 - } + // Success. + return nil +} +func (c *UDPConn) handleChannelBindErrorResponse(res *stun.Message) error { + var code stun.ErrorCodeAttribute + if err := code.GetFrom(res); err != nil { return fmt.Errorf("%w: unexpected response type %s", errCannotBindChannel, res.Type) // nolint:err113 } - c.log.Debugf("Channel binding successful: %s %d", bound.addr, bound.number) + switch code.Code { + case stun.CodeStaleNonce: + c.setNonceFromMsg(res) - // Success. - return nil + return errTryAgain + case stun.CodeBadRequest: + return fmt.Errorf("%w: %w: received error %d", errCannotBindChannel, errChannelBindBadRequest, code.Code) + default: + return fmt.Errorf("%w: received error %d", errCannotBindChannel, code.Code) // nolint:err113 + } } func (c *UDPConn) sendChannelData(data []byte, chNum uint16) (int, error) { diff --git a/vendor/github.com/pion/turn/v5/internal/server/turn.go b/vendor/github.com/pion/turn/v5/internal/server/turn.go index 9548e0746b..5bd07cd0e6 100644 --- a/vendor/github.com/pion/turn/v5/internal/server/turn.go +++ b/vendor/github.com/pion/turn/v5/internal/server/turn.go @@ -385,22 +385,27 @@ func handleCreatePermissionRequest(req Request, stunMsg *stun.Message) error { } addCount := 0 + errorCode := stun.CodeBadRequest if err := stunMsg.ForEach(stun.AttrXORPeerAddress, func(m *stun.Message) error { var peerAddress proto.PeerAddress if err := peerAddress.GetFrom(m); err != nil { + errorCode = stun.CodeBadRequest + return err } // RFC 6156: Peer address must match allocation's address family. if !ipMatchesFamily(peerAddress.IP, alloc.AddressFamily()) { req.Log.Infof("peer address family mismatch for client %s to peer %s", req.SrcAddr, peerAddress.IP) + errorCode = stun.CodePeerAddrFamilyMismatch return errPeerAddressFamilyMismatch } if err := req.AllocationManager.GrantPermission(req.SrcAddr, peerAddress.IP); err != nil { req.Log.Infof("permission denied for client %s to peer %s", req.SrcAddr, peerAddress.IP) + errorCode = stun.CodeForbidden return err } @@ -427,12 +432,19 @@ func handleCreatePermissionRequest(req Request, stunMsg *stun.Message) error { if addCount == 0 { respClass = stun.ClassErrorResponse } + attrs := []stun.Setter{messageIntegrity} + if respClass == stun.ClassErrorResponse { + attrs = []stun.Setter{ + &stun.ErrorCodeAttribute{Code: errorCode}, + messageIntegrity, + } + } return buildAndSend( req.Conn, req.SrcAddr, buildMsg(stunMsg.TransactionID, stun.NewType(stun.MethodCreatePermission, respClass), - []stun.Setter{messageIntegrity}...)..., + attrs...)..., ) } diff --git a/vendor/github.com/pion/webrtc/v4/datachannel_js.go b/vendor/github.com/pion/webrtc/v4/datachannel_js.go index 2d5336ba28..6c681654d9 100644 --- a/vendor/github.com/pion/webrtc/v4/datachannel_js.go +++ b/vendor/github.com/pion/webrtc/v4/datachannel_js.go @@ -32,6 +32,14 @@ type DataChannel struct { onBufferedAmountLow *js.Func onErrorHandler *js.Func + // onCloseFunc retains the user-provided OnClose callback so it can still be + // invoked from a self-releasing wrapper installed by Close(). + onCloseFunc func() + + // closeWrapperInstalled guards the self-releasing onclose wrapper in Close() + // so repeated Close calls don't override the first wrapper before it fires. + closeWrapperInstalled bool + // A reference to the associated api object used by this datachannel api *API } @@ -63,6 +71,7 @@ func (d *DataChannel) OnClose(f func()) { oldHandler := d.onCloseHandler defer oldHandler.Release() } + d.onCloseFunc = f onCloseHandler := js.FuncOf(func(this js.Value, args []js.Value) any { go f() return js.Undefined() @@ -177,27 +186,63 @@ func (d *DataChannel) Close() (err error) { } }() - d.underlying.Call("close") - - // Release any handlers as required by the syscall/js API. + // Nullify and release handlers that should not fire after Close is called. if d.onOpenHandler != nil { + d.underlying.Set("onopen", js.Null()) d.onOpenHandler.Release() - } - if d.onCloseHandler != nil { - d.onCloseHandler.Release() + d.onOpenHandler = nil } if d.onClosingHandler != nil { + d.underlying.Set("onclosing", js.Null()) d.onClosingHandler.Release() + d.onClosingHandler = nil } if d.onMessageHandler != nil { + d.underlying.Set("onmessage", js.Null()) d.onMessageHandler.Release() + d.onMessageHandler = nil } if d.onBufferedAmountLow != nil { + d.underlying.Set("onbufferedamountlow", js.Null()) d.onBufferedAmountLow.Release() + d.onBufferedAmountLow = nil } - if d.onErrorHandler != nil { - d.onErrorHandler.Release() + + // Defer nullifying onclose and onerror until the channel has fully closed. + // An error event may still fire during the close handshake (between calling + // close() and the onclose event), and the user-provided OnClose callback + // must still be invoked. Install the wrapper only once so repeated Close() + // calls don't override the original wrapper before it fires. + if !d.closeWrapperInstalled { + oldCloseHandler := d.onCloseHandler + oldErrorHandler := d.onErrorHandler + closeFunc := d.onCloseFunc + + var wrapperHandler js.Func + wrapperHandler = js.FuncOf(func(this js.Value, args []js.Value) any { + if closeFunc != nil { + go closeFunc() + } + d.underlying.Set("onclose", js.Null()) + wrapperHandler.Release() + if oldErrorHandler != nil { + d.underlying.Set("onerror", js.Null()) + oldErrorHandler.Release() + } + d.closeWrapperInstalled = false + return js.Undefined() + }) + d.underlying.Set("onclose", wrapperHandler) + d.closeWrapperInstalled = true + if oldCloseHandler != nil { + oldCloseHandler.Release() + } } + d.onCloseHandler = nil + d.onCloseFunc = nil + d.onErrorHandler = nil + + d.underlying.Call("close") return nil } diff --git a/vendor/github.com/pion/webrtc/v4/dtlstransport.go b/vendor/github.com/pion/webrtc/v4/dtlstransport.go index c9276a19a5..3938364efa 100644 --- a/vendor/github.com/pion/webrtc/v4/dtlstransport.go +++ b/vendor/github.com/pion/webrtc/v4/dtlstransport.go @@ -6,6 +6,7 @@ package webrtc import ( + "context" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" @@ -301,6 +302,19 @@ func (t *DTLSTransport) role() DTLSRole { // Start DTLS transport negotiation with the parameters of the remote DTLS transport. func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { + return t.start(remoteParameters, t.handshakeDTLS) +} + +// StartContext starts DTLS transport negotiation with the parameters of the remote DTLS +// transport. If the context is canceled before the DTLS handshake is complete, the handshake +// is interrupted and an error is returned. +func (t *DTLSTransport) StartContext(ctx context.Context, remoteParameters DTLSParameters) error { + return t.start(remoteParameters, func(dtlsConn *dtls.Conn) error { + return dtlsConn.HandshakeContext(ctx) + }) +} + +func (t *DTLSTransport) start(remoteParameters DTLSParameters, handshake func(*dtls.Conn) error) error { role, certificate, err := t.prepareStart(remoteParameters) if err != nil { return err @@ -319,7 +333,7 @@ func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { return t.failStart(err) } - if err = t.handshakeDTLS(dtlsConn); err != nil { + if err = handshake(dtlsConn); err != nil { dtlsEndpoint.SetOnClose(nil) _ = dtlsConn.Close() diff --git a/vendor/github.com/pion/webrtc/v4/icetransport.go b/vendor/github.com/pion/webrtc/v4/icetransport.go index 0e6d864f34..cf54d47ada 100644 --- a/vendor/github.com/pion/webrtc/v4/icetransport.go +++ b/vendor/github.com/pion/webrtc/v4/icetransport.go @@ -87,7 +87,20 @@ func NewICETransport(gatherer *ICEGatherer, loggerFactory logging.LoggerFactory) } // Start incoming connectivity checks based on its configured role. -func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role *ICERole) error { //nolint:cyclop +func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role *ICERole) error { + return t.StartContext(context.Background(), gatherer, params, role) +} + +// StartContext incoming connectivity checks based on its configured role. +// If the context is canceled, the ICE transport will stop. +// +//nolint:cyclop +func (t *ICETransport) StartContext( + ctx context.Context, + gatherer *ICEGatherer, + params ICEParameters, + role *ICERole, +) error { t.lock.Lock() defer t.lock.Unlock() @@ -134,7 +147,8 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role * } t.role = *role - ctx, ctxCancel := context.WithCancel(context.Background()) + callerCtx := ctx + operationCtx, ctxCancel := context.WithCancel(callerCtx) t.ctxCancel = ctxCancel // Drop the lock here to allow ICE candidates to be @@ -145,12 +159,12 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role * var err error switch *role { case ICERoleControlling: - iceConn, err = agent.Dial(ctx, + iceConn, err = agent.Dial(operationCtx, params.UsernameFragment, params.Password) case ICERoleControlled: - iceConn, err = agent.Accept(ctx, + iceConn, err = agent.Accept(operationCtx, params.UsernameFragment, params.Password) @@ -161,6 +175,17 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role * // Reacquire the lock to set the connection/mux t.lock.Lock() if err != nil { + if ctxErr := callerCtx.Err(); ctxErr != nil { + t.lock.Unlock() + _ = t.Stop() + t.lock.Lock() + + return ctxErr + } + + ctxCancel() + t.ctxCancel = nil + return err } diff --git a/vendor/github.com/pion/webrtc/v4/peerconnection.go b/vendor/github.com/pion/webrtc/v4/peerconnection.go index 7269106ca7..21c70ea1c7 100644 --- a/vendor/github.com/pion/webrtc/v4/peerconnection.go +++ b/vendor/github.com/pion/webrtc/v4/peerconnection.go @@ -2841,9 +2841,12 @@ func (pc *PeerConnection) startRTP( } pc.startRTPReceivers(remoteDesc, currentTransceivers) - if d := haveDataChannel(remoteDesc); d != nil && d.MediaName.Port.Value != 0 { - remoteSctpInit, _ := getSctpInit(d) - pc.startSCTP(getMaxMessageSize(d), remoteSctpInit) + if d := haveDataChannel(remoteDesc); d != nil { + // RFC 8843 Section 6 permits bundle-only media sections to use port zero. + if _, bundleOnly := d.Attribute("bundle-only"); d.MediaName.Port.Value != 0 || bundleOnly { + remoteSctpInit, _ := getSctpInit(d) + pc.startSCTP(getMaxMessageSize(d), remoteSctpInit) + } } } diff --git a/vendor/github.com/pion/webrtc/v4/peerconnection_js.go b/vendor/github.com/pion/webrtc/v4/peerconnection_js.go index 87460bdda6..8745f64b3a 100644 --- a/vendor/github.com/pion/webrtc/v4/peerconnection_js.go +++ b/vendor/github.com/pion/webrtc/v4/peerconnection_js.go @@ -402,24 +402,31 @@ func (pc *PeerConnection) Close() (err error) { // Release any handlers as required by the syscall/js API. if pc.onSignalingStateChangeHandler != nil { + pc.underlying.Set("onsignalingstatechange", js.Null()) pc.onSignalingStateChangeHandler.Release() } if pc.onDataChannelHandler != nil { + pc.underlying.Set("ondatachannel", js.Null()) pc.onDataChannelHandler.Release() } if pc.onNegotiationNeededHandler != nil { + pc.underlying.Set("onnegotiationneeded", js.Null()) pc.onNegotiationNeededHandler.Release() } if pc.onConnectionStateChangeHandler != nil { + pc.underlying.Set("onconnectionstatechange", js.Null()) pc.onConnectionStateChangeHandler.Release() } if pc.onICEConnectionStateChangeHandler != nil { + pc.underlying.Set("oniceconnectionstatechange", js.Null()) pc.onICEConnectionStateChangeHandler.Release() } if pc.onICECandidateHandler != nil { + pc.underlying.Set("onicecandidate", js.Null()) pc.onICECandidateHandler.Release() } if pc.onICEGatheringStateChangeHandler != nil { + pc.underlying.Set("onicegatheringstatechange", js.Null()) pc.onICEGatheringStateChangeHandler.Release() } diff --git a/vendor/github.com/pires/go-proxyproto/.golangci.yml b/vendor/github.com/pires/go-proxyproto/.golangci.yml index 290eff06fa..33b7d8a10c 100644 --- a/vendor/github.com/pires/go-proxyproto/.golangci.yml +++ b/vendor/github.com/pires/go-proxyproto/.golangci.yml @@ -18,6 +18,13 @@ linters: - revive - unconvert - usestdlibvars + settings: + goconst: + # Newer goconst versions default ignore-calls to false, which flags + # idiomatic call-argument strings such as t.Fatalf("err: %v", err) and + # net.Dial("tcp", addr). Restore the prior default so only genuinely + # repeated constant values are reported. + ignore-calls: true run: timeout: 5m @@ -25,3 +32,4 @@ run: issues: max-issues-per-linter: 0 + max-same-issues: 0 diff --git a/vendor/github.com/pires/go-proxyproto/README.md b/vendor/github.com/pires/go-proxyproto/README.md index 2cbc941fed..f56cd655b3 100644 --- a/vendor/github.com/pires/go-proxyproto/README.md +++ b/vendor/github.com/pires/go-proxyproto/README.md @@ -23,134 +23,69 @@ Both protocol versions, 1 (text-based) and 2 (binary-based) are supported. $ go get -u github.com/pires/go-proxyproto ``` +## Examples + +The fastest way to get started is the runnable programs under +[`examples/`](examples) and the API examples on +[pkg.go.dev](https://pkg.go.dev/github.com/pires/go-proxyproto#pkg-examples): + +| Goal | Where to look | +| ---- | ------------- | +| Minimal client | [`examples/client`](examples/client) | +| Minimal server | [`examples/server`](examples/server) | +| HTTP server | [`examples/httpserver`](examples/httpserver) | +| Server + client over TLS (PROXY header before TLS) | [`examples/tlsserver`](examples/tlsserver), [`examples/tlsclient`](examples/tlsclient) | +| `Listener` options: timeout, buffer size, policy, validation | [`ExampleListener_*`](https://pkg.go.dev/github.com/pires/go-proxyproto#example-Listener) | +| `NewConn` options | [`ExampleNewConn_*`](https://pkg.go.dev/github.com/pires/go-proxyproto#example-NewConn) | +| PROXY over TLS, both wrapping orders | [`ExampleListener_tls`](https://pkg.go.dev/github.com/pires/go-proxyproto#example-Listener-Tls), [`ExampleListener_tlsHeaderInsideTLS`](https://pkg.go.dev/github.com/pires/go-proxyproto#example-Listener-TlsHeaderInsideTLS) | + ## Usage -### Client +Use the full runnable examples above for complete programs. The core API shape is +small: + +### Client side ```go -package main - -import ( - "io" - "log" - "net" - - proxyproto "github.com/pires/go-proxyproto" -) - -func chkErr(err error) { - if err != nil { - log.Fatalf("Error: %s", err.Error()) - } -} - -func main() { - // Dial some proxy listener e.g. https://github.com/mailgun/proxyproto - target, err := net.ResolveTCPAddr("tcp", "127.0.0.1:2319") - chkErr(err) - - conn, err := net.DialTCP("tcp", nil, target) - chkErr(err) - - defer conn.Close() - - // Create a proxyprotocol header or use HeaderProxyFromAddrs() if you - // have two conn's - header := &proxyproto.Header{ - Version: 1, - Command: proxyproto.PROXY, - TransportProtocol: proxyproto.TCPv4, - SourceAddr: &net.TCPAddr{ - IP: net.ParseIP("10.1.1.1"), - Port: 1000, - }, - DestinationAddr: &net.TCPAddr{ - IP: net.ParseIP("20.2.2.2"), - Port: 2000, - }, - } - // After the connection was created write the proxy headers first - _, err = header.WriteTo(conn) - chkErr(err) - // Then your data... e.g.: - _, err = io.WriteString(conn, "HELO") - chkErr(err) -} +header := proxyproto.HeaderProxyFromAddrs(1, sourceAddr, destinationAddr) +_, err := header.WriteTo(conn) // write the PROXY header before application data ``` -### Server +See [`examples/client`](examples/client) for a complete TCP client. -```go -package main - -import ( - "log" - "net" - - proxyproto "github.com/pires/go-proxyproto" -) - -func main() { - // Create a listener - addr := "localhost:9876" - list, err := net.Listen("tcp", addr) - if err != nil { - log.Fatalf("couldn't listen to %q: %q\n", addr, err.Error()) - } - - // Wrap listener in a proxyproto listener - proxyListener := &proxyproto.Listener{Listener: list} - defer proxyListener.Close() - - // Wait for a connection and accept it - conn, err := proxyListener.Accept() - defer conn.Close() - - // Print connection details - if conn.LocalAddr() == nil { - log.Fatal("couldn't retrieve local address") - } - log.Printf("local address: %q", conn.LocalAddr().String()) - - if conn.RemoteAddr() == nil { - log.Fatal("couldn't retrieve remote address") - } - log.Printf("remote address: %q", conn.RemoteAddr().String()) -} -``` +### Server side -### HTTP Server ```go -package main - -import ( - "net" - "net/http" - "time" - - "github.com/pires/go-proxyproto" -) - -func main() { - server := http.Server{ - Addr: ":8080", - } - - ln, err := net.Listen("tcp", server.Addr) - if err != nil { - panic(err) - } - - proxyListener := &proxyproto.Listener{ - Listener: ln, - ReadHeaderTimeout: 10 * time.Second, - } - defer proxyListener.Close() - - server.Serve(proxyListener) -} +proxyListener := &proxyproto.Listener{Listener: ln} +conn, err := proxyListener.Accept() +// conn.RemoteAddr() now reports the client address from the PROXY header, when present. ``` +See [`examples/server`](examples/server) for a complete TCP server. For HTTP/1 +and HTTP/2, see [`examples/httpserver`](examples/httpserver), which uses +[`helper/http2`](helper/http2) so one server can accept proxied HTTP/1 and HTTP/2 +connections. + +### TLS + +When combining the PROXY protocol with TLS, choose the wrapping order based on +where the upstream puts the PROXY header relative to the TLS handshake: + +- **Header in cleartext, before the handshake**: proxyproto reads the header + first, so it goes inside the TLS listener: + `tls.NewListener(&proxyproto.Listener{Listener: l}, tlsConfig)`. +- **Header inside the TLS session, after the handshake**: TLS decrypts first, so + proxyproto wraps the TLS listener: + `&proxyproto.Listener{Listener: tls.NewListener(l, tlsConfig)}`. + +In both cases `conn.RemoteAddr()` reports the client carried by the PROXY +header. Runnable code lives in [`examples/tlsserver`](examples/tlsserver) and +[`examples/tlsclient`](examples/tlsclient); the API examples +[`ExampleListener_tls`](https://pkg.go.dev/github.com/pires/go-proxyproto#example-Listener-Tls) +and +[`ExampleListener_tlsHeaderInsideTLS`](https://pkg.go.dev/github.com/pires/go-proxyproto#example-Listener-TlsHeaderInsideTLS) +show both orderings. + ## Special notes ### AWS diff --git a/vendor/github.com/pires/go-proxyproto/header.go b/vendor/github.com/pires/go-proxyproto/header.go index b1a6c33e1d..766c6b3e5f 100644 --- a/vendor/github.com/pires/go-proxyproto/header.go +++ b/vendor/github.com/pires/go-proxyproto/header.go @@ -11,6 +11,13 @@ import ( "time" ) +// Network names for Unix-domain addresses, matching net.UnixAddr.Net values. +// The net package exposes no constants for these. +const ( + networkUnix = "unix" + networkUnixgram = "unixgram" +) + var ( // SIGV1 is the signature for PROXY protocol v1. SIGV1 = []byte{'\x50', '\x52', '\x4F', '\x58', '\x59'} @@ -78,31 +85,50 @@ func HeaderProxyFromAddrs(version byte, sourceAddr, destAddr net.Addr) *Header { } switch sourceAddr := sourceAddr.(type) { case *net.TCPAddr: - if _, ok := destAddr.(*net.TCPAddr); !ok { + // Both ends must be the same Addr type; bind destAddr to read its IP below. + destAddr, ok := destAddr.(*net.TCPAddr) + if !ok { break } - if len(sourceAddr.IP.To4()) == net.IPv4len { + // Pick the family from BOTH addresses, not just the source: use v4 only + // when both are IPv4, otherwise fall back to v6 (the v4 side is then + // serialized as a v4-mapped IPv6, ::ffff:x.x.x.x). The previous + // source-only check mislabeled a v4-source/v6-dest pair as TCPv4 and then + // failed in formatVersion1. + switch { + case sourceAddr.IP.To4() != nil && destAddr.IP.To4() != nil: h.TransportProtocol = TCPv4 - } else if len(sourceAddr.IP) == net.IPv6len { + case sourceAddr.IP.To16() != nil && destAddr.IP.To16() != nil: h.TransportProtocol = TCPv6 } case *net.UDPAddr: - if _, ok := destAddr.(*net.UDPAddr); !ok { + destAddr, ok := destAddr.(*net.UDPAddr) + if !ok { break } - if len(sourceAddr.IP.To4()) == net.IPv4len { + // Same both-ends family selection as TCP above. + switch { + case sourceAddr.IP.To4() != nil && destAddr.IP.To4() != nil: h.TransportProtocol = UDPv4 - } else if len(sourceAddr.IP) == net.IPv6len { + case sourceAddr.IP.To16() != nil && destAddr.IP.To16() != nil: h.TransportProtocol = UDPv6 } case *net.UnixAddr: - if _, ok := destAddr.(*net.UnixAddr); !ok { + destAddr, ok := destAddr.(*net.UnixAddr) + if !ok { + break + } + // Both ends must agree on stream vs datagram: there is no meaningful + // connection mixing the two, so a mismatched pair stays UNSPEC rather than + // being labeled with the source's flavor alone. Mirrors the both-ends + // family selection used for TCP/UDP above. + if sourceAddr.Net != destAddr.Net { break } switch sourceAddr.Net { - case "unix": + case networkUnix: h.TransportProtocol = UnixStream - case "unixgram": + case networkUnixgram: h.TransportProtocol = UnixDatagram } } @@ -199,7 +225,7 @@ func (header *Header) WriteTo(w io.Writer) (int64, error) { return 0, err } - return bytes.NewBuffer(buf).WriteTo(w) + return bytes.NewReader(buf).WriteTo(w) } // Format renders a proxy protocol header in a format to write over the wire. @@ -278,6 +304,17 @@ func Read(reader *bufio.Reader) (*Header, error) { // ReadTimeout acts as Read but takes a timeout. If that timeout is reached, it's assumed // there's no proxy protocol header. +// +// Deprecated: ReadTimeout cannot cancel the read it starts. It only receives a +// *bufio.Reader, so on timeout it has no way to set a deadline on or close the +// underlying connection: the goroutine it spawns stays blocked in Read, peeking +// at the stalled connection, until the peer sends data or the connection is +// closed elsewhere. Each timed-out call therefore leaks that goroutine and the +// connection's file descriptor. Use ReadHeaderTimeout instead, which also takes +// the net.Conn and sets a real read deadline so the read is actually cancelled +// on timeout; or wrap the connection with NewConn or a Listener and configure +// the header timeout via the SetReadHeaderTimeout option or +// Listener.ReadHeaderTimeout. func ReadTimeout(reader *bufio.Reader, timeout time.Duration) (*Header, error) { type header struct { h *Header @@ -300,3 +337,37 @@ func ReadTimeout(reader *bufio.Reader, timeout time.Duration) (*Header, error) { return nil, ErrNoProxyProtocol } } + +// ReadHeaderTimeout reads the PROXY protocol header from conn, giving up after +// timeout. It is the cancellable replacement for the deprecated ReadTimeout: +// because it is given the net.Conn, it sets a read deadline so a stalled read is +// actually interrupted instead of leaking a blocked goroutine and the +// connection's file descriptor. If the timeout is reached it returns +// ErrNoProxyProtocol, assuming no header is present. +// +// reader must be buffered over conn (for example bufio.NewReader(conn)); it is +// used for the header read so that any bytes buffered past the header remain +// available for the caller to read afterwards. A timeout <= 0 reads without a +// deadline. +// +// ReadHeaderTimeout overwrites conn's read deadline and restores the zero (no) +// deadline before returning; re-apply your own read deadline afterwards if you +// had one set. +func ReadHeaderTimeout(conn net.Conn, reader *bufio.Reader, timeout time.Duration) (*Header, error) { + if timeout > 0 { + if err := conn.SetReadDeadline(time.Now().Add(timeout)); err != nil { + return nil, err + } + // Best-effort restore of the zero deadline. A failure here (e.g. the + // peer has already closed) must not mask a header we parsed, so the + // error is intentionally ignored; the header/err from Read is + // authoritative. + defer func() { _ = conn.SetReadDeadline(time.Time{}) }() + } + + header, err := Read(reader) + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + return nil, ErrNoProxyProtocol + } + return header, err +} diff --git a/vendor/github.com/pires/go-proxyproto/policy.go b/vendor/github.com/pires/go-proxyproto/policy.go index 2124e46f2b..1e2cb2709b 100644 --- a/vendor/github.com/pires/go-proxyproto/policy.go +++ b/vendor/github.com/pires/go-proxyproto/policy.go @@ -40,14 +40,14 @@ const ( // IGNORE address from PROXY header, but accept connection. IGNORE // REJECT connection when PROXY header is sent - // Note: even though the first read on the connection returns an error if - // a PROXY header is present, subsequent reads do not. It is the task of - // the code using the connection to handle that case properly. + // Note: if a PROXY header is present the first read returns + // ErrSuperfluousProxyHeader, and every subsequent read returns the same + // error, so the connection should be closed. REJECT // REQUIRE connection to send PROXY header, reject if not present - // Note: even though the first read on the connection returns an error if - // a PROXY header is not present, subsequent reads do not. It is the task - // of the code using the connection to handle that case properly. + // Note: if no PROXY header is present the first read returns + // ErrNoProxyProtocol, and every subsequent read returns the same error, + // so the connection should be closed. REQUIRE // SKIP accepts a connection without requiring the PROXY header. // Note: an example usage can be found in the SkipProxyHeaderForCIDR @@ -151,9 +151,9 @@ func MustLaxWhiteListPolicy(allowed []string) PolicyFunc { // ConnStrictWhiteListPolicy returns a ConnPolicyFunc which decides whether the // upstream ip is allowed to send a proxy header based on a list of allowed // IP addresses and IP ranges. In case upstream IP is not in list reading on -// the connection will be refused on the first read. Please note: subsequent -// reads do not error. It is the task of the code using the connection to -// handle that case properly. If one of the provided IP addresses or IP +// the connection will be refused: the first read returns +// ErrSuperfluousProxyHeader and every subsequent read returns the same error, +// so the connection should be closed. If one of the provided IP addresses or IP // ranges is invalid it will return an error instead of a ConnPolicyFunc. func ConnStrictWhiteListPolicy(allowed []string) (ConnPolicyFunc, error) { allowFrom, err := parse(allowed) @@ -167,9 +167,9 @@ func ConnStrictWhiteListPolicy(allowed []string) (ConnPolicyFunc, error) { // StrictWhiteListPolicy returns a PolicyFunc which decides whether the // upstream ip is allowed to send a proxy header based on a list of allowed // IP addresses and IP ranges. In case upstream IP is not in list reading on -// the connection will be refused on the first read. Please note: subsequent -// reads do not error. It is the task of the code using the connection to -// handle that case properly. If one of the provided IP addresses or IP +// the connection will be refused: the first read returns +// ErrSuperfluousProxyHeader and every subsequent read returns the same error, +// so the connection should be closed. If one of the provided IP addresses or IP // ranges is invalid it will return an error instead of a PolicyFunc. // // Deprecated: use ConnStrictWhiteListPolicy instead. diff --git a/vendor/github.com/pires/go-proxyproto/protocol.go b/vendor/github.com/pires/go-proxyproto/protocol.go index 41bc30d454..3eded83b5c 100644 --- a/vendor/github.com/pires/go-proxyproto/protocol.go +++ b/vendor/github.com/pires/go-proxyproto/protocol.go @@ -40,6 +40,12 @@ var ( // is set, a default of 10s will be used. This can be disabled by setting the // timeout to < 0. // +// Note that ReadHeaderTimeout only bounds how long a single slow connection can +// hold a goroutine and file descriptor during header detection; it is not a +// connection count or accept-rate limit. Deployments exposed to untrusted +// clients should keep ReadHeaderTimeout low and enforce connection/rate limits +// upstream (or around Accept). +// // Only one of Policy or ConnPolicy should be provided. If both are provided then // a panic would occur during accept. type Listener struct { @@ -90,6 +96,8 @@ func ValidateHeader(v Validator) func(*Conn) { } // SetReadHeaderTimeout sets the readHeaderTimeout for a connection when passed as option to NewConn(). +// A value of 0 disables the header read timeout; negative values are ignored, +// leaving the connection's current timeout (the NewConn default) in place. func SetReadHeaderTimeout(t time.Duration) func(*Conn) { return func(c *Conn) { if t >= 0 { @@ -164,13 +172,15 @@ func (p *Listener) Accept() (net.Conn, error) { } newConn := NewConn(conn, opts...) - // If the ReadHeaderTimeout for the listener is unset, use the default timeout. - if p.ReadHeaderTimeout == 0 { - p.ReadHeaderTimeout = DefaultReadHeaderTimeout + // Set the readHeaderTimeout of the new conn to the value of the listener, + // falling back to the default when unset. Read into a local rather than + // writing back to the shared Listener: mutating p here races with + // concurrent Accept calls and would silently rewrite the caller's struct. + readHeaderTimeout := p.ReadHeaderTimeout + if readHeaderTimeout == 0 { + readHeaderTimeout = DefaultReadHeaderTimeout } - - // Set the readHeaderTimeout of the new conn to the value of the listener - newConn.readHeaderTimeout = p.ReadHeaderTimeout + newConn.readHeaderTimeout = readHeaderTimeout return newConn, nil } @@ -189,6 +199,20 @@ func (p *Listener) Addr() net.Addr { // NewConn is used to wrap a net.Conn that may be speaking the PROXY protocol // into a proxyproto.Conn. // +// By default the returned Conn applies DefaultReadHeaderTimeout (10s) while +// detecting the PROXY protocol header, so a client that connects but never +// sends data cannot make header detection block forever. +// +// This bounds header detection only, not the first Read end-to-end: under a +// non-REQUIRE policy, when no header is present Read falls through to a normal +// read of the underlying connection, which can still block on a silent client +// (pinning a goroutine and file descriptor). For an end-to-end bound, set a read +// deadline on the connection, or use the REQUIRE policy, which makes the first +// Read fail when no header arrives within the timeout. +// +// Override the timeout with the SetReadHeaderTimeout option; pass +// SetReadHeaderTimeout(0) to disable it entirely. +// // NOTE: NewConn may interfere with previously set ReadDeadline on the provided net.Conn, // because it sets a temporary deadline when detecting and reading the PROXY protocol header. // If you need to enforce a specific ReadDeadline on the connection, be sure to call Conn.SetReadDeadline @@ -197,8 +221,9 @@ func NewConn(conn net.Conn, opts ...func(*Conn)) *Conn { br := bufio.NewReaderSize(conn, readBufferSize) pConn := &Conn{ - bufReader: br, - conn: conn, + bufReader: br, + conn: conn, + readHeaderTimeout: DefaultReadHeaderTimeout, } for _, opt := range opts { @@ -391,11 +416,17 @@ func (p *Conn) readHeader() error { if t == nil { t = time.Time{} } - if err := p.conn.SetReadDeadline(t.(time.Time)); err != nil { - return err - } + // Restore the user's deadline on a best-effort basis. This must not + // discard a header we already parsed: some connections (notably + // net.Pipe) return an error from SetReadDeadline once the peer has + // closed, which can happen right after the peer sends the header and + // closes. Only surface a restore failure when the read produced neither + // a header nor an error of its own. + restoreErr := p.conn.SetReadDeadline(t.(time.Time)) if netErr, ok := err.(net.Error); ok && netErr.Timeout() { err = ErrNoProxyProtocol + } else if err == nil && header == nil { + err = restoreErr } } diff --git a/vendor/github.com/pires/go-proxyproto/v1.go b/vendor/github.com/pires/go-proxyproto/v1.go index 8574d4a7c8..35d5bf6545 100644 --- a/vendor/github.com/pires/go-proxyproto/v1.go +++ b/vendor/github.com/pires/go-proxyproto/v1.go @@ -13,6 +13,12 @@ import ( const ( crlf = "\r\n" separator = " " + + // v1ProtoTCP4 and v1ProtoTCP6 are the PROXY protocol v1 transport-protocol + // tokens for TCP over IPv4 and IPv6 respectively (net has no constants for + // these textual identifiers). + v1ProtoTCP4 = "TCP4" + v1ProtoTCP6 = "TCP6" ) func initVersion1() *Header { @@ -106,9 +112,9 @@ func parseVersion1(reader *bufio.Reader) (*Header, error) { // Read address family and protocol var transportProtocol AddressFamilyAndProtocol switch tokens[1] { - case "TCP4": + case v1ProtoTCP4: transportProtocol = TCPv4 - case "TCP6": + case v1ProtoTCP6: transportProtocol = TCPv6 case "UNKNOWN": transportProtocol = UNSPEC // doesn't exist in v1 but fits UNKNOWN @@ -170,9 +176,9 @@ func (header *Header) formatVersion1() ([]byte, error) { var proto string switch header.TransportProtocol { case TCPv4: - proto = "TCP4" + proto = v1ProtoTCP4 case TCPv6: - proto = "TCP6" + proto = v1ProtoTCP6 default: // Unknown connection (short form) return []byte("PROXY UNKNOWN" + crlf), nil @@ -184,16 +190,28 @@ func (header *Header) formatVersion1() ([]byte, error) { return nil, ErrInvalidAddress } - sourceIP, destIP := sourceAddr.IP, destAddr.IP + // netip.Addr (not net.IP) is used here so String() honors the address family + // declared by TransportProtocol. AddrFromSlice reports ok=false when the slice + // is nil (e.g. To4() on an IPv6-only address), which the guard below rejects. + var sourceIP, destIP netip.Addr switch header.TransportProtocol { case TCPv4: - sourceIP = sourceIP.To4() - destIP = destIP.To4() + sourceIP, sourceOK = netip.AddrFromSlice(sourceAddr.IP.To4()) + destIP, destOK = netip.AddrFromSlice(destAddr.IP.To4()) case TCPv6: - sourceIP = sourceIP.To16() - destIP = destIP.To16() + // Use netip.Addr instead of net.IP to guarantee an Is6() address; i.e. a + // v4-mapped IP in a TCP6 header serializes as ::ffff:1.2.3.4 instead of + // net.IP.String()'s collapsed 1.2.3.4. + sourceIP, sourceOK = netip.AddrFromSlice(sourceAddr.IP.To16()) + destIP, destOK = netip.AddrFromSlice(destAddr.IP.To16()) + default: + // Unreachable today: the proto switch at the top of this function already + // returns for anything other than TCPv4/TCPv6. Kept so a future protocol + // can't fall through with zero-value IPs while sourceOK/destOK still hold + // from the type assertion above. + return nil, ErrInvalidAddress } - if sourceIP == nil || destIP == nil { + if !sourceOK || !destOK { return nil, ErrInvalidAddress } diff --git a/vendor/github.com/pires/go-proxyproto/v2.go b/vendor/github.com/pires/go-proxyproto/v2.go index 432bcc583f..f47d164a9f 100644 --- a/vendor/github.com/pires/go-proxyproto/v2.go +++ b/vendor/github.com/pires/go-proxyproto/v2.go @@ -148,9 +148,9 @@ func parseVersion2(reader *bufio.Reader) (header *Header, err error) { return nil, fmt.Errorf("%w: %w", ErrInvalidAddress, err) } - network := "unix" + network := networkUnix if header.TransportProtocol.IsDatagram() { - network = "unixgram" + network = networkUnixgram } header.SourceAddr = &net.UnixAddr{ diff --git a/vendor/github.com/shoenig/go-m1cpu/cpu.go b/vendor/github.com/shoenig/go-m1cpu/cpu.go index 971bee764c..382c004921 100644 --- a/vendor/github.com/shoenig/go-m1cpu/cpu.go +++ b/vendor/github.com/shoenig/go-m1cpu/cpu.go @@ -144,10 +144,17 @@ package m1cpu // return global_brand; // } import "C" -import "fmt" +import ( + "fmt" + "sync" +) -func init() { - C.initialize() +var initOnce sync.Once + +func ensureInitialized() { + initOnce.Do(func() { + C.initialize() + }) } // IsAppleSilicon returns true on this platform. @@ -157,31 +164,37 @@ func IsAppleSilicon() bool { // PCoreHZ returns the max frequency in Hertz of the P-Core of an Apple Silicon CPU. func PCoreHz() uint64 { + ensureInitialized() return toHz(uint64(C.pCoreClock())) } // ECoreHZ returns the max frequency in Hertz of the E-Core of an Apple Silicon CPU. func ECoreHz() uint64 { + ensureInitialized() return toHz(uint64(C.eCoreClock())) } // PCoreGHz returns the max frequency in Gigahertz of the P-Core of an Apple Silicon CPU. func PCoreGHz() float64 { + ensureInitialized() return toGhz(uint64(C.pCoreClock())) } // ECoreGHz returns the max frequency in Gigahertz of the E-Core of an Apple Silicon CPU. func ECoreGHz() float64 { + ensureInitialized() return toGhz(uint64(C.eCoreClock())) } // PCoreCount returns the number of physical P (performance) cores. func PCoreCount() int { + ensureInitialized() return int(C.pCoreCount()) } // ECoreCount returns the number of physical E (efficiency) cores. func ECoreCount() int { + ensureInitialized() return int(C.eCoreCount()) } @@ -192,6 +205,7 @@ func ECoreCount() int { // - L1 data cache // - L2 cache func PCoreCache() (int, int, int) { + ensureInitialized() return int(C.pCoreL1InstCacheSize()), int(C.pCoreL1DataCacheSize()), int(C.pCoreL2CacheSize()) @@ -204,6 +218,7 @@ func PCoreCache() (int, int, int) { // - L1 data cache // - L2 cache func ECoreCache() (int, int, int) { + ensureInitialized() return int(C.eCoreL1InstCacheSize()), int(C.eCoreL1DataCacheSize()), int(C.eCoreL2CacheSize()) @@ -211,6 +226,7 @@ func ECoreCache() (int, int, int) { // ModelName returns the model name of the CPU. func ModelName() string { + ensureInitialized() return C.GoString(C.modelName()) } diff --git a/vendor/go.starlark.net/starlark/int.go b/vendor/go.starlark.net/starlark/int.go index 31f594b4d4..36b8a517ea 100644 --- a/vendor/go.starlark.net/starlark/int.go +++ b/vendor/go.starlark.net/starlark/int.go @@ -377,7 +377,8 @@ func AsInt(x Value, ptr any) error { return fmt.Errorf("got %s, want int", x.Type()) } - bits := reflect.TypeOf(ptr).Elem().Size() * 8 + ptrt := reflect.TypeOf(ptr) + bits := ptrt.Elem().Size() * 8 switch ptr.(type) { case *int, *int8, *int16, *int32, *int64: i, ok := xint.Int64() @@ -417,7 +418,8 @@ func AsInt(x Value, ptr any) error { *ptr = uintptr(i) } default: - panic(fmt.Sprintf("invalid argument type: %T", ptr)) + // Avoid %T, as it would cause *ptr to escape. + panic(fmt.Sprintf("invalid argument type: %s", ptrt)) } return nil } diff --git a/vendor/go.starlark.net/starlark/library.go b/vendor/go.starlark.net/starlark/library.go index 0640b3e0a3..bad18aff9a 100644 --- a/vendor/go.starlark.net/starlark/library.go +++ b/vendor/go.starlark.net/starlark/library.go @@ -178,7 +178,7 @@ func builtinAttrNames(methods map[string]*Builtin) []string { // https://github.com/google/starlark-go/blob/master/doc/spec.md#abs func abs(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var x Value - if err := UnpackPositionalArgs("abs", args, kwargs, 1, &x); err != nil { + if err := unpackPositionalArgsNoEscape("abs", args, kwargs, 1, &x); err != nil { return nil, err } switch x := x.(type) { @@ -197,7 +197,7 @@ func abs(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) // https://github.com/google/starlark-go/blob/master/doc/spec.md#all func all(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var iterable Iterable - if err := UnpackPositionalArgs("all", args, kwargs, 1, &iterable); err != nil { + if err := unpackPositionalArgsNoEscape("all", args, kwargs, 1, &iterable); err != nil { return nil, err } iter := iterable.Iterate() @@ -214,7 +214,7 @@ func all(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) // https://github.com/google/starlark-go/blob/master/doc/spec.md#any func any_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var iterable Iterable - if err := UnpackPositionalArgs("any", args, kwargs, 1, &iterable); err != nil { + if err := unpackPositionalArgsNoEscape("any", args, kwargs, 1, &iterable); err != nil { return nil, err } iter := iterable.Iterate() @@ -231,7 +231,7 @@ func any_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) // https://github.com/google/starlark-go/blob/master/doc/spec.md#bool func bool_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var x Value = False - if err := UnpackPositionalArgs("bool", args, kwargs, 0, &x); err != nil { + if err := unpackPositionalArgsNoEscape("bool", args, kwargs, 0, &x); err != nil { return nil, err } return x.Truth(), nil @@ -334,7 +334,7 @@ func dir(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) func enumerate(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var iterable Iterable var start int - if err := UnpackPositionalArgs("enumerate", args, kwargs, 1, &iterable, &start); err != nil { + if err := unpackPositionalArgsNoEscape("enumerate", args, kwargs, 1, &iterable, &start); err != nil { return nil, err } @@ -456,7 +456,7 @@ var ( func getattr(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var object, dflt Value var name string - if err := UnpackPositionalArgs("getattr", args, kwargs, 2, &object, &name, &dflt); err != nil { + if err := unpackPositionalArgsNoEscape("getattr", args, kwargs, 2, &object, &name, &dflt); err != nil { return nil, err } if object, ok := object.(HasAttrs); ok { @@ -484,7 +484,7 @@ func getattr(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, err func hasattr(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var object Value var name string - if err := UnpackPositionalArgs("hasattr", args, kwargs, 2, &object, &name); err != nil { + if err := unpackPositionalArgsNoEscape("hasattr", args, kwargs, 2, &object, &name); err != nil { return nil, err } if object, ok := object.(HasAttrs); ok { @@ -507,7 +507,7 @@ func hasattr(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, err // https://github.com/google/starlark-go/blob/master/doc/spec.md#hash func hash(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var x Value - if err := UnpackPositionalArgs("hash", args, kwargs, 1, &x); err != nil { + if err := unpackPositionalArgsNoEscape("hash", args, kwargs, 1, &x); err != nil { return nil, err } @@ -665,7 +665,7 @@ func parseInt(s string, base int) Value { // https://github.com/google/starlark-go/blob/master/doc/spec.md#len func len_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var x Value - if err := UnpackPositionalArgs("len", args, kwargs, 1, &x); err != nil { + if err := unpackPositionalArgsNoEscape("len", args, kwargs, 1, &x); err != nil { return nil, err } len := Len(x) @@ -678,7 +678,7 @@ func len_(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) // https://github.com/google/starlark-go/blob/master/doc/spec.md#list func list(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var iterable Iterable - if err := UnpackPositionalArgs("list", args, kwargs, 0, &iterable); err != nil { + if err := unpackPositionalArgsNoEscape("list", args, kwargs, 0, &iterable); err != nil { return nil, err } var elems []Value @@ -827,7 +827,7 @@ func print(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error func range_(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var start, stop, step int step = 1 - if err := UnpackPositionalArgs("range", args, kwargs, 1, &start, &stop, &step); err != nil { + if err := unpackPositionalArgsNoEscape("range", args, kwargs, 1, &start, &stop, &step); err != nil { return nil, err } @@ -966,7 +966,7 @@ func (*rangeIterator) Done() {} // https://github.com/google/starlark-go/blob/master/doc/spec.md#repr func repr(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var x Value - if err := UnpackPositionalArgs("repr", args, kwargs, 1, &x); err != nil { + if err := unpackPositionalArgsNoEscape("repr", args, kwargs, 1, &x); err != nil { return nil, err } return String(x.String()), nil @@ -975,7 +975,7 @@ func repr(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) // https://github.com/google/starlark-go/blob/master/doc/spec.md#reversed func reversed(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var iterable Iterable - if err := UnpackPositionalArgs("reversed", args, kwargs, 1, &iterable); err != nil { + if err := unpackPositionalArgsNoEscape("reversed", args, kwargs, 1, &iterable); err != nil { return nil, err } iter := iterable.Iterate() @@ -998,7 +998,7 @@ func reversed(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, er // https://github.com/google/starlark-go/blob/master/doc/spec.md#set func set(thread *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var iterable Iterable - if err := UnpackPositionalArgs("set", args, kwargs, 0, &iterable); err != nil { + if err := unpackPositionalArgsNoEscape("set", args, kwargs, 0, &iterable); err != nil { return nil, err } set := new(Set) @@ -1123,7 +1123,7 @@ func utf8Transcode(s string) string { // https://github.com/google/starlark-go/blob/master/doc/spec.md#tuple func tuple(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var iterable Iterable - if err := UnpackPositionalArgs("tuple", args, kwargs, 0, &iterable); err != nil { + if err := unpackPositionalArgsNoEscape("tuple", args, kwargs, 0, &iterable); err != nil { return nil, err } if len(args) == 0 { @@ -1212,7 +1212,7 @@ func zip(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error) // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·get func dict_get(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var key, dflt Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &key, &dflt); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &key, &dflt); err != nil { return nil, err } if v, ok, err := b.Receiver().(*Dict).Get(key); err != nil { @@ -1257,7 +1257,7 @@ func dict_keys(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·pop func dict_pop(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var k, d Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &k, &d); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &k, &d); err != nil { return nil, err } if v, found, err := b.Receiver().(*Dict).Delete(k); err != nil { @@ -1290,7 +1290,7 @@ func dict_popitem(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, err // https://github.com/google/starlark-go/blob/master/doc/spec.md#dict·setdefault func dict_setdefault(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var key, dflt Value = nil, None - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &key, &dflt); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &key, &dflt); err != nil { return nil, err } dict := b.Receiver().(*Dict) @@ -1332,7 +1332,7 @@ func dict_values(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, erro // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·append func list_append(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var object Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &object); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &object); err != nil { return nil, err } recv := b.Receiver().(*List) @@ -1358,7 +1358,7 @@ func list_clear(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error func list_extend(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { recv := b.Receiver().(*List) var iterable Iterable - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &iterable); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &iterable); err != nil { return nil, err } if err := recv.checkMutable("extend"); err != nil { @@ -1371,7 +1371,7 @@ func list_extend(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, erro // https://github.com/google/starlark-go/blob/master/doc/spec.md#list·index func list_index(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var value, start_, end_ Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &value, &start_, &end_); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &value, &start_, &end_); err != nil { return nil, err } @@ -1396,7 +1396,7 @@ func list_insert(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, erro recv := b.Receiver().(*List) var index int var object Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 2, &index, &object); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 2, &index, &object); err != nil { return nil, err } if err := recv.checkMutable("insert into"); err != nil { @@ -1425,7 +1425,7 @@ func list_insert(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, erro func list_remove(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { recv := b.Receiver().(*List) var value Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &value); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &value); err != nil { return nil, err } if err := recv.checkMutable("remove from"); err != nil { @@ -1448,7 +1448,7 @@ func list_pop(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) list := recv.(*List) n := list.Len() i := n - 1 - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &i); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &i); err != nil { return nil, err } origI := i @@ -1543,7 +1543,7 @@ func (*bytesIterator) Done() {} func string_count(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var sub string var start_, end_ Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &sub, &start_, &end_); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &sub, &start_, &end_); err != nil { return nil, err } @@ -1853,7 +1853,7 @@ func string_index(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, err func string_join(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { recv := string(b.Receiver().(String)) var iterable Iterable - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &iterable); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &iterable); err != nil { return nil, err } iter := iterable.Iterate() @@ -1885,7 +1885,7 @@ func string_lower(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, err func string_partition(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { recv := string(b.Receiver().(String)) var sep string - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &sep); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &sep); err != nil { return nil, err } if sep == "" { @@ -1915,7 +1915,7 @@ func string_partition(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, func string_removefix(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { recv := string(b.Receiver().(String)) var fix string - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &fix); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &fix); err != nil { return nil, err } if b.name[len("remove")] == 'p' { @@ -1931,7 +1931,7 @@ func string_replace(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, e recv := string(b.Receiver().(String)) var old, new string count := -1 - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 2, &old, &new, &count); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 2, &old, &new, &count); err != nil { return nil, err } return String(strings.Replace(recv, old, new, count)), nil @@ -1952,7 +1952,7 @@ func string_rindex(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, er func string_startswith(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var x Value var start, end Value = None, None - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &x, &start, &end); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &x, &start, &end); err != nil { return nil, err } @@ -1996,7 +1996,7 @@ func string_startswith(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·rstrip func string_strip(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var chars string - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &chars); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &chars); err != nil { return nil, err } recv := string(b.Receiver().(String)) @@ -2064,7 +2064,7 @@ func string_split(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, err recv := string(b.Receiver().(String)) var sep_ Value maxsplit := -1 - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &sep_, &maxsplit); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &sep_, &maxsplit); err != nil { return nil, err } @@ -2165,7 +2165,7 @@ func splitspace(s string, max int) []string { // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·splitlines func string_splitlines(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var keepends bool - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &keepends); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &keepends); err != nil { return nil, err } var lines []string @@ -2190,7 +2190,7 @@ func string_splitlines(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·add. func set_add(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var elem Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &elem); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &elem); err != nil { return nil, err } recv := b.Receiver().(*Set) @@ -2228,7 +2228,7 @@ func set_clear(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) func set_difference(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { // TODO: support multiple others: s.difference(*others) var other Iterable - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &other); err != nil { return nil, err } iter := other.Iterate() @@ -2244,7 +2244,7 @@ func set_difference(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, e func set_intersection(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { // TODO: support multiple others: s.difference(*others) var other Iterable - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &other); err != nil { return nil, err } iter := other.Iterate() @@ -2259,7 +2259,7 @@ func set_intersection(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, // https://github.com/google/starlark-go/blob/master/doc/spec.md#set_issubset. func set_issubset(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var other Iterable - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &other); err != nil { return nil, err } iter := other.Iterate() @@ -2274,7 +2274,7 @@ func set_issubset(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, err // https://github.com/google/starlark-go/blob/master/doc/spec.md#set_issuperset. func set_issuperset(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var other Iterable - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &other); err != nil { return nil, err } iter := other.Iterate() @@ -2289,7 +2289,7 @@ func set_issuperset(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, e // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·discard. func set_discard(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var k Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &k); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &k); err != nil { return nil, err } recv := b.Receiver().(*Set) @@ -2329,7 +2329,7 @@ func set_pop(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·remove. func set_remove(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var k Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &k); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &k); err != nil { return nil, err } if found, err := b.Receiver().(*Set).Delete(k); err != nil { @@ -2343,7 +2343,7 @@ func set_remove(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error // https://github.com/google/starlark-go/blob/master/doc/spec.md#set·symmetric_difference. func set_symmetric_difference(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { var other Iterable - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 0, &other); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 0, &other); err != nil { return nil, err } iter := other.Iterate() @@ -2376,7 +2376,7 @@ func set_update(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error func string_find_impl(b *Builtin, args Tuple, kwargs []Tuple, allowError, last bool) (Value, error) { var sub string var start_, end_ Value - if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &sub, &start_, &end_); err != nil { + if err := unpackPositionalArgsNoEscape(b.Name(), args, kwargs, 1, &sub, &start_, &end_); err != nil { return nil, err } diff --git a/vendor/go.starlark.net/starlark/unpack.go b/vendor/go.starlark.net/starlark/unpack.go index 11dd855e3b..2ca01536e0 100644 --- a/vendor/go.starlark.net/starlark/unpack.go +++ b/vendor/go.starlark.net/starlark/unpack.go @@ -8,6 +8,7 @@ import ( "log" "reflect" "strings" + "unsafe" "go.starlark.net/internal/spell" ) @@ -190,10 +191,35 @@ kwloop: // // See UnpackArgs for general comments. func UnpackPositionalArgs(fnname string, args Tuple, kwargs []Tuple, min int, vars ...any) error { + if err := checkPositionalArgs(fnname, args, kwargs, min, len(vars)); err != nil { + return err + } + for i, arg := range args { + if err := UnpackArg(arg, vars[i]); err != nil { + return fmt.Errorf("%s: for parameter %d: %s", fnname, i+1, err) + } + } + return nil +} + +// unpackPositionalArgsNoEscape is an optimized version of [UnpackPositionalArgs]. +// However, it panics if any vars[i] pointer value implements Unpacker. +func unpackPositionalArgsNoEscape(fnname string, args Tuple, kwargs []Tuple, min int, vars ...any) error { + if err := checkPositionalArgs(fnname, args, kwargs, min, len(vars)); err != nil { + return err + } + for i, arg := range args { + if err := unpackArgNoEscape(arg, vars[i]); err != nil { + return fmt.Errorf("%s: for parameter %d: %s", fnname, i+1, err) + } + } + return nil +} + +func checkPositionalArgs(fnname string, args Tuple, kwargs []Tuple, min, max int) error { if len(kwargs) > 0 { return fmt.Errorf("%s: unexpected keyword arguments", fnname) } - max := len(vars) if len(args) < min { var atleast string if min < max { @@ -208,11 +234,6 @@ func UnpackPositionalArgs(fnname string, args Tuple, kwargs []Tuple, min int, va } return fmt.Errorf("%s: got %d arguments, want %s%d", fnname, len(args), atmost, max) } - for i, arg := range args { - if err := UnpackArg(arg, vars[i]); err != nil { - return fmt.Errorf("%s: for parameter %d: %s", fnname, i+1, err) - } - } return nil } @@ -224,10 +245,21 @@ func UnpackPositionalArgs(fnname string, args Tuple, kwargs []Tuple, min int, va // [UnpackPositionalArgs] to unpack a sequence of positional and/or // keyword arguments. func UnpackArg(v Value, ptr any) error { + if ptr, ok := ptr.(Unpacker); ok { + return ptr.Unpack(v) // (causes *ptr to escape) + } + return unpackArgNoEscape(v, ptr) +} + +// unpackArgNoEscape is an optimized version of [UnpackArg]. +// However, it panics if ptr implements Unpacker. +func unpackArgNoEscape(v Value, ptr any) error { + // Caution: do not let *ptr escape, + // e.g. via reflection or dynamic calls. + // There is a test of this invariant. + // On failure, don't clobber *ptr. switch ptr := ptr.(type) { - case Unpacker: - return ptr.Unpack(v) case *Value: *ptr = v case *string: @@ -277,19 +309,22 @@ func UnpackArg(v Value, ptr any) error { *ptr = it default: // v must have type *V, where V is some subtype of starlark.Value. - ptrv := reflect.ValueOf(ptr) - if ptrv.Kind() != reflect.Pointer { - log.Panicf("internal error: not a pointer: %T", ptr) + ptrt := reflect.TypeOf(ptr) + if _, ok := ptr.(Unpacker); ok { + log.Panicf("unpackArgNoEscape does not support %s (Unpacker); use UnpackArg instead", ptrt) } - paramVar := ptrv.Elem() - if !reflect.TypeOf(v).AssignableTo(paramVar.Type()) { + if ptrt.Kind() != reflect.Pointer { + log.Panicf("internal error: not a pointer: %s", ptrt) + } + paramVarType := ptrt.Elem() + if !reflect.TypeOf(v).AssignableTo(paramVarType) { // The value is not assignable to the variable. // Detect a possible bug in the Go program that called Unpack: // If the variable *ptr is not a subtype of Value, // no value of v can possibly work. - if !paramVar.Type().AssignableTo(reflect.TypeFor[Value]()) { - log.Panicf("pointer element type does not implement Value: %T", ptr) + if !paramVarType.AssignableTo(reflect.TypeFor[Value]()) { + log.Panicf("pointer element type does not implement Value: %s", ptrt) } // Report Starlark dynamic type error. @@ -304,18 +339,22 @@ func UnpackArg(v Value, ptr any) error { // recover. // Default to Go reflect.Type name - paramType := paramVar.Type().String() + paramType := paramVarType.String() - // Attempt to call Value.Type method. + // Attempt to call Value.Type method on the zero + // value of the variable. func() { defer func() { recover() }() - if typer, _ := paramVar.Interface().(interface{ Type() string }); typer != nil { - paramType = typer.Type() + + if v, _ := reflect.Zero(paramVarType).Interface().(Value); v != nil { + paramType = v.Type() } }() return fmt.Errorf("got %s, want %s", v.Type(), paramType) } - paramVar.Set(reflect.ValueOf(v)) + + // assign *ptr = v + reflectSetElem(ptr, reflect.ValueOf(v)) } return nil } @@ -362,3 +401,34 @@ func (is *intset) len() int { } return len(is.large) } + +// reflectSetElem is equivalent to reflect.ValueOf(ptr).Elem().Set(v) +// but does not let *ptr escape. +// +// ptr must be a non-nil pointer to a variable to which v may be assigned. +func reflectSetElem(ptr any, v reflect.Value) { + typ := reflect.TypeOf(ptr) + if typ.Kind() != reflect.Pointer { + panic("reflect: call of SetElem on non-pointer") + } + type eface struct{ typ, data unsafe.Pointer } + p := noescape((*eface)(unsafe.Pointer(&ptr)).data) + reflect.NewAt(typ.Elem(), p).Elem().Set(v) +} + +// -- copied verbatim from abi.NoEscape -- + +// noescape hides the pointer p from escape analysis, preventing it +// from escaping to the heap. It compiles down to nothing. +// +// WARNING: This is very subtle to use correctly. The caller must +// ensure that it's truly safe for p to not escape to the heap by +// maintaining runtime pointer invariants (for example, that globals +// and the heap may not generally point into a stack). +// +//go:nosplit +//go:nocheckptr +func noescape(p unsafe.Pointer) unsafe.Pointer { + x := uintptr(p) + return unsafe.Pointer(x ^ 0) +} diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go index 326888ae35..7e3dbaad26 100644 --- a/vendor/google.golang.org/grpc/balancer/balancer.go +++ b/vendor/google.golang.org/grpc/balancer/balancer.go @@ -60,7 +60,7 @@ func Register(b Builder) { if !envconfig.CaseSensitiveBalancerRegistries { name = strings.ToLower(name) if name != b.Name() { - logger.Warningf("Balancer registered with name %q. grpc-go will be switching to case sensitive balancer registries soon. After 2 releases, we will enable the env var by default.", b.Name()) + logger.Warningf("Balancer registered with name %q. grpc-go has switched to case sensitive balancer registries. GRPC_GO_EXPERIMENTAL_CASE_SENSITIVE_BALANCER_REGISTRIES env variable will be removed in release v1.82.0", b.Name()) } } m[name] = b @@ -85,7 +85,7 @@ func Get(name string) Builder { if !envconfig.CaseSensitiveBalancerRegistries { lowerName := strings.ToLower(name) if lowerName != name { - logger.Warningf("Balancer retrieved for name %q. grpc-go will be switching to case sensitive balancer registries soon. After 2 releases, we will enable the env var by default.", name) + logger.Warningf("Balancer retrieved for name %q. grpc-go has switched to case sensitive balancer registries. GRPC_GO_EXPERIMENTAL_CASE_SENSITIVE_BALANCER_REGISTRIES env variable will be removed in release v1.82.0", name) } name = lowerName } diff --git a/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go index 518a69d573..d48bc304c2 100644 --- a/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go +++ b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go @@ -35,9 +35,9 @@ import ( "google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer/pickfirst/internal" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/experimental/balancer/weight" expstats "google.golang.org/grpc/experimental/stats" "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/internal/balancer/weight" "google.golang.org/grpc/internal/envconfig" internalgrpclog "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/pretty" diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go index 4ec5f9cd09..3af08e1ab9 100644 --- a/vendor/google.golang.org/grpc/dialoptions.go +++ b/vendor/google.golang.org/grpc/dialoptions.go @@ -173,10 +173,8 @@ func newJoinDialOption(opts ...DialOption) DialOption { // If this option is set to true every connection will release the buffer after // flushing the data on the wire. // -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a -// later release. +// Deprecated: shared write buffer is enabled by default. WithSharedWriteBuffer +// will be removed in a future release. func WithSharedWriteBuffer(val bool) DialOption { return newFuncDialOption(func(o *dialOptions) { o.copts.SharedWriteBuffer = val @@ -229,6 +227,14 @@ func WithInitialConnWindowSize(s int32) DialOption { // WithStaticStreamWindowSize returns a DialOption which sets the initial // stream window size to the value provided and disables dynamic flow control. +// +// Note that this also disables dynamic flow control for the connection, +// falling back to a default static connection-level window of 64KB. To +// use a larger connection-level window, you must also use the +// [WithStaticConnWindowSize] DialOption. +// +// Most users should not configure static flow control windows unless +// operating in a memory-constrained environment. func WithStaticStreamWindowSize(s int32) DialOption { return newFuncDialOption(func(o *dialOptions) { o.copts.InitialWindowSize = s @@ -239,6 +245,14 @@ func WithStaticStreamWindowSize(s int32) DialOption { // WithStaticConnWindowSize returns a DialOption which sets the initial // connection window size to the value provided and disables dynamic flow // control. +// +// Note that this also disables dynamic flow control for individual streams, +// falling back to a default static connection-level window of 64KB. To +// explicitly configure the stream-level window size, you must also use the +// [WithStaticStreamWindowSize] DialOption. +// +// Most users should not configure static flow control windows unless +// operating in a memory-constrained environment. func WithStaticConnWindowSize(s int32) DialOption { return newFuncDialOption(func(o *dialOptions) { o.copts.InitialConnWindowSize = s diff --git a/vendor/google.golang.org/grpc/encoding/encoding.go b/vendor/google.golang.org/grpc/encoding/encoding.go index 296f38c3a8..bfa8b268fe 100644 --- a/vendor/google.golang.org/grpc/encoding/encoding.go +++ b/vendor/google.golang.org/grpc/encoding/encoding.go @@ -66,6 +66,9 @@ type Compressor interface { // Decompress reads data from r, decompresses it, and provides the // uncompressed data via the returned io.Reader. If an error occurs while // initializing the decompressor, that error is returned instead. + // + // The returned io.Reader may optionally implement io.ReadCloser, and if it + // does, gRPC will call Close() exactly once. Decompress(r io.Reader) (io.Reader, error) // Name is the name of the compression codec and is used to set the content // coding header. The result must be static; the result cannot change diff --git a/vendor/google.golang.org/grpc/internal/balancer/weight/weight.go b/vendor/google.golang.org/grpc/experimental/balancer/weight/weight.go similarity index 71% rename from vendor/google.golang.org/grpc/internal/balancer/weight/weight.go rename to vendor/google.golang.org/grpc/experimental/balancer/weight/weight.go index 11beb07d14..beab9e07c9 100644 --- a/vendor/google.golang.org/grpc/internal/balancer/weight/weight.go +++ b/vendor/google.golang.org/grpc/experimental/balancer/weight/weight.go @@ -16,23 +16,23 @@ * */ -// Package weight contains utilities to manage endpoint weights. Weights are -// used by LB policies such as ringhash to distribute load across multiple -// endpoints. +// Package weight contains utilities to manage endpoint weights. +// Weights may be used by LB policies to distribute load across +// multiple endpoints. +// +// # Experimental +// +// Notice: All APIs in this package are EXPERIMENTAL and may be changed +// or removed in a later release. package weight -import ( - "fmt" - - "google.golang.org/grpc/resolver" -) +import "google.golang.org/grpc/resolver" // attributeKey is the type used as the key to store EndpointInfo in the // Attributes field of resolver.Endpoint. type attributeKey struct{} -// EndpointInfo will be stored in the Attributes field of Endpoints in order to -// use the ringhash balancer. +// EndpointInfo will be stored in the Attributes field of Endpoints. type EndpointInfo struct { Weight uint32 } @@ -43,22 +43,16 @@ func (a EndpointInfo) Equal(o any) bool { return ok && oa.Weight == a.Weight } -// Set returns a copy of endpoint in which the Attributes field is updated with -// EndpointInfo. +// Set returns a copy of endpoint in which the Attributes field is +// updated with EndpointInfo. func Set(endpoint resolver.Endpoint, epInfo EndpointInfo) resolver.Endpoint { endpoint.Attributes = endpoint.Attributes.WithValue(attributeKey{}, epInfo) return endpoint } -// String returns a human-readable representation of EndpointInfo. -// This method is intended for logging, testing, and debugging purposes only. -// Do not rely on the output format, as it is not guaranteed to remain stable. -func (a EndpointInfo) String() string { - return fmt.Sprintf("Weight: %d", a.Weight) -} - -// FromEndpoint returns the EndpointInfo stored in the Attributes field of an -// endpoint. It returns an empty EndpointInfo if attribute is not found. +// FromEndpoint returns the EndpointInfo stored in the Attributes +// field of an endpoint. It returns an empty EndpointInfo if attribute +// is not found. func FromEndpoint(endpoint resolver.Endpoint) EndpointInfo { v := endpoint.Attributes.Value(attributeKey{}) ei, _ := v.(EndpointInfo) diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go index 8ca87a57a2..ba05b65d5b 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go @@ -59,6 +59,15 @@ var ( // unconditionally. XDSEndpointHashKeyBackwardCompat = boolFromEnv("GRPC_XDS_ENDPOINT_HASH_KEY_BACKWARD_COMPAT", false) + // LabelServerGoroutines controls setting [runtime/pprof.Labels] on the + // goroutines spawned by [grpc.Server] type. + // For now, this is limited to the goroutines spawned to handle incoming + // requests on the server. + // Set "GRPC_GO_SERVER_GOROUTINE_LABELS" to "grpc.method=true" to + // enable this grpc.method label, or "all" to enable all valid labels. + // This variable is a bit-field. + LabelServerGoroutines = goroutineLabelsFromEnv("GRPC_GO_SERVER_GOROUTINE_LABELS", 0) + // RingHashSetRequestHashKey is set if the ring hash balancer can get the // request hash header by setting the "requestHashHeader" field, according // to gRFC A76. It can be disabled by setting the environment variable @@ -78,12 +87,12 @@ var ( EnableDefaultPortForProxyTarget = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_DEFAULT_PORT_FOR_PROXY_TARGET", true) // CaseSensitiveBalancerRegistries is set if the balancer registry should be - // case-sensitive. This is disabled by default, but can be enabled by setting + // case-sensitive. This is enabled by default, but can be disabled by setting // the env variable "GRPC_GO_EXPERIMENTAL_CASE_SENSITIVE_BALANCER_REGISTRIES" - // to "true". + // to "false". // - // TODO: After 2 releases, we will enable the env var by default. - CaseSensitiveBalancerRegistries = boolFromEnv("GRPC_GO_EXPERIMENTAL_CASE_SENSITIVE_BALANCER_REGISTRIES", false) + // This env varible will be removed in release v1.82.0. + CaseSensitiveBalancerRegistries = boolFromEnv("GRPC_GO_EXPERIMENTAL_CASE_SENSITIVE_BALANCER_REGISTRIES", true) // XDSAuthorityRewrite indicates whether xDS authority rewriting is enabled. // This feature is defined in gRFC A81 and is enabled by setting the @@ -104,22 +113,6 @@ var ( // to "false". XDSRecoverPanicInResourceParsing = boolFromEnv("GRPC_GO_EXPERIMENTAL_XDS_RESOURCE_PANIC_RECOVERY", true) - // DisableStrictPathChecking indicates whether strict path checking is - // disabled. This feature can be disabled by setting the environment - // variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING to "true". - // - // When strict path checking is enabled, gRPC will reject requests with - // paths that do not conform to the gRPC over HTTP/2 specification found at - // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md. - // - // When disabled, gRPC will allow paths that do not contain a leading slash. - // Enabling strict path checking is recommended for security reasons, as it - // prevents potential path traversal vulnerabilities. - // - // A future release will remove this environment variable, enabling strict - // path checking behavior unconditionally. - DisableStrictPathChecking = boolFromEnv("GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING", false) - // EnablePriorityLBChildPolicyCache controls whether the priority balancer // should cache child balancers that are removed from the LB policy config, // for a period of 15 minutes. This is disabled by default, but can be @@ -127,6 +120,18 @@ var ( // GRPC_EXPERIMENTAL_ENABLE_PRIORITY_LB_CHILD_POLICY_CACHE to true. EnablePriorityLBChildPolicyCache = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_PRIORITY_LB_CHILD_POLICY_CACHE", false) + // Enable8KBDefaultHeaderListSize indicates that default maximum header list + // size is restricted to 8KB. This is disabled by default, but can be enabled + // by setting the environment variable + // "GRPC_GO_EXPERIMENTAL_ENABLE_8KB_DEFAULT_HEADER_LIST_SIZE" to "true". + // When disabled, the default maximum header list size of 16MB is used. + // + // When enabled, RPCs with a total size of headers exceeding 8KB will fail + // unless explicitly configured otherwise by the user. + // + // TODO: In release v1.82.0, env var will be enabled by default. + Enable8KBDefaultHeaderListSize = boolFromEnv("GRPC_GO_EXPERIMENTAL_ENABLE_8KB_DEFAULT_HEADER_LIST_SIZE", false) + // EnableHTTPFramerReadBufferPooling enables the use of the // readyreader.Reader interface to perform non-memory-pinning reads, // provided the underlying net.Conn supports it. This reduces memory usage @@ -160,3 +165,52 @@ func uint64FromEnv(envVar string, def, min, max uint64) uint64 { } return v } + +// GoroutineLabels is a bitfield indicating which goroutine labels are enabled. +type GoroutineLabels uint16 + +func goroutineLabelsFromEnv(envVar string, def GoroutineLabels) GoroutineLabels { + val := def + v := os.Getenv(envVar) + if strings.EqualFold(v, "all") { + return AllGoroutineLabels + } else if strings.EqualFold(v, "none") { + return 0 + } + for s := range strings.SplitSeq(v, ",") { + s = strings.TrimSpace(s) + if len(s) == 0 { + continue + } + pre, post, ok := strings.Cut(s, "=") + if !ok { + // no equals sign + continue + } + post = strings.TrimSpace(post) + pre = strings.TrimSpace(pre) + bitDesignator := GoroutineLabels(0) + switch { + case strings.EqualFold(pre, "grpc.method"): + bitDesignator = GoroutineLabelServerMethod + default: + continue + } + if strings.EqualFold(post, "true") { + val |= bitDesignator + } else if strings.EqualFold(post, "false") { + val &^= bitDesignator + } + } + return val +} + +const ( + // GoroutineLabelServerMethod sets the grpc.method label on new + // server-side gRPC streams. + GoroutineLabelServerMethod GoroutineLabels = 1 << iota +) + +// AllGoroutineLabels is an or'd together bitfield of all valid GoroutineLabels +// constant values (above). +const AllGoroutineLabels = GoroutineLabelServerMethod diff --git a/vendor/google.golang.org/grpc/internal/envconfig/xds.go b/vendor/google.golang.org/grpc/internal/envconfig/xds.go index 333d8a0b06..a2312f8eac 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/xds.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/xds.go @@ -89,4 +89,14 @@ var ( // filtered and prefix-propagated to the LRS server. For more details, see: // https://github.com/grpc/proposal/blob/master/A85-lrs-custom-metrics-changes.md XDSORCAToLRSPropEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_ORCA_LRS_PROPAGATION", false) + + // XDSClientExtProcEnabled indicates whether ExtProc filter is enabled on + // the client side. For more details, see: + // https://github.com/grpc/proposal/blob/master/A93-xds-ext-proc.md + XDSClientExtProcEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_EXT_PROC_ON_CLIENT", false) + + // GCPAuthenticationFilterEnabled enables the xDS GCP Authentication + // filter. For more details, see: + // https://github.com/grpc/proposal/blob/master/A83-xds-gcp-authn-filter.md + GCPAuthenticationFilterEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER", false) ) diff --git a/vendor/google.golang.org/grpc/internal/grpcutil/encode_duration.go b/vendor/google.golang.org/grpc/internal/grpcutil/encode_duration.go index b25b0baec3..1cc43fc6b8 100644 --- a/vendor/google.golang.org/grpc/internal/grpcutil/encode_duration.go +++ b/vendor/google.golang.org/grpc/internal/grpcutil/encode_duration.go @@ -39,7 +39,6 @@ func div(d, r time.Duration) int64 { // // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests func EncodeDuration(t time.Duration) string { - // TODO: This is simplistic and not bandwidth efficient. Improve it. if t <= 0 { return "0n" } diff --git a/vendor/google.golang.org/grpc/internal/resolver/config_selector.go b/vendor/google.golang.org/grpc/internal/resolver/config_selector.go index 3db62ccad2..6320e9b576 100644 --- a/vendor/google.golang.org/grpc/internal/resolver/config_selector.go +++ b/vendor/google.golang.org/grpc/internal/resolver/config_selector.go @@ -106,14 +106,24 @@ type ClientStream interface { // ClientInterceptor is an interceptor for gRPC client streams. type ClientInterceptor interface { - // NewStream produces a ClientStream for an RPC which may optionally use - // the provided function to produce a stream for delegation. Note: - // RPCInfo.Context should not be used (will be nil). + // NewStream creates a ClientStream for an RPC. // - // done is invoked when the RPC is finished using its connection, or could - // not be assigned a connection. RPC operations may still occur on - // ClientStream after done is called, since the interceptor is invoked by - // application-layer operations. done must never be nil when called. + // Implementations must delegate stream creation to the provided newStream + // function. To intercept or override stream behavior, implementations + // may wrap the ClientStream returned by the delegate. + // + // Note: RPCInfo.Context is currently unused and will be nil. + // + // The done function is invoked when the RPC has finished using its + // underlying connection or if a connection could not be assigned. Because + // interceptors operate at the application layer, RPC operations may + // continue on the ClientStream even after done has been called. The + // caller must ensure done is non-nil. + // + // To ensure RPC completion notifications propagate through the entire + // interceptor chain, implementations must ensure that the done function + // passed to the delegate newStream invokes the done function passed to + // NewStream. NewStream(ctx context.Context, ri RPCInfo, done func(), newStream func(ctx context.Context, done func()) (ClientStream, error)) (ClientStream, error) // Close closes the interceptor. Once called, no new calls to NewStream are // accepted. Ongoing calls to NewStream are allowed to complete. diff --git a/vendor/google.golang.org/grpc/internal/stats/labels.go b/vendor/google.golang.org/grpc/internal/stats/labels.go index fd33af51ae..5ea898cb53 100644 --- a/vendor/google.golang.org/grpc/internal/stats/labels.go +++ b/vendor/google.golang.org/grpc/internal/stats/labels.go @@ -19,24 +19,56 @@ // Package stats provides internal stats related functionality. package stats -import "context" +import ( + "context" + "maps" +) -// Labels are the labels for metrics. -type Labels struct { - // TelemetryLabels are the telemetry labels to record. - TelemetryLabels map[string]string +// LabelCallback is a function that is executed when telemetry +// label keys are updated. +type LabelCallback func(map[string]string) +type telemetryLabelCallbackKey struct{} + +// UpdateLabels executes registered telemetry callbacks with the update labels. Labels +// are copied before being processed by any callbacks to ensure mutations are not +// shared among derived contexts. +// +// It is the responsibility of the registrant to handle conflicts or label resets. +func UpdateLabels(ctx context.Context, update map[string]string) { + executeTelemetryLabelCallbacks(ctx, update) } -type labelsKey struct{} +// RegisterTelemetryLabelCallback registers a callback function that is executed whenever +// telemetry labels are updated. +func RegisterTelemetryLabelCallback(ctx context.Context, callback LabelCallback) context.Context { + if callback == nil { + return ctx + } + + callbacks, ok := ctx.Value(telemetryLabelCallbackKey{}).([]LabelCallback) + if !ok { + return context.WithValue(ctx, telemetryLabelCallbackKey{}, []LabelCallback{callback}) + } + return context.WithValue(ctx, telemetryLabelCallbackKey{}, append(append([]LabelCallback(nil), callbacks...), callback)) -// GetLabels returns the Labels stored in the context, or nil if there is one. -func GetLabels(ctx context.Context) *Labels { - labels, _ := ctx.Value(labelsKey{}).(*Labels) - return labels } -// SetLabels sets the Labels in the context. -func SetLabels(ctx context.Context, labels *Labels) context.Context { - // could also append - return context.WithValue(ctx, labelsKey{}, labels) +// executeTelemetryLabelCallback runs the registered callbacks in the order they were +// registered on the context with the provided labels. If no callbacks are registered +// it does nothing. +// +// To ensure callbacks do not mutate the state of the provided label map it is copied +// before execution. +func executeTelemetryLabelCallbacks(ctx context.Context, labels map[string]string) { + callbacks, ok := ctx.Value(telemetryLabelCallbackKey{}).([]LabelCallback) + if !ok { + return + } + + labelsCopy := map[string]string{} + maps.Copy(labelsCopy, labels) + for _, callback := range callbacks { + callback(labelsCopy) + } + } diff --git a/vendor/google.golang.org/grpc/internal/transport/client_stream.go b/vendor/google.golang.org/grpc/internal/transport/client_stream.go index cd8152ef13..ad382b0fda 100644 --- a/vendor/google.golang.org/grpc/internal/transport/client_stream.go +++ b/vendor/google.golang.org/grpc/internal/transport/client_stream.go @@ -19,6 +19,7 @@ package transport import ( + "fmt" "sync/atomic" "golang.org/x/net/http2" @@ -28,6 +29,12 @@ import ( "google.golang.org/grpc/status" ) +// nonGRPCDataMaxLen is the maximum length of nonGRPCDataBuf. +// +// NOTE: If changed this value, you MUST update the corresponding test in: +// - /test/end2end_test.go:TestHTTPServerSendsNonGRPCHeaderSurfaceFurtherData +const nonGRPCDataMaxLen = 1024 + // ClientStream implements streaming functionality for a gRPC client. type ClientStream struct { Stream // Embed for common stream functionality. @@ -46,7 +53,11 @@ type ClientStream struct { // headerValid indicates whether a valid header was received. Only // meaningful after headerChan is closed (always call waitOnHeader() before // reading its value). - headerValid bool + headerValid bool + + nonGRPCStatus *status.Status // the initial status from the non-gRPC response header, finalized with collected data before closing. + nonGRPCDataBuf []byte // stores the data of a non-gRPC response. + noHeaders bool // set if the client never received headers (set only after the stream is done). headerChanClosed uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times. bytesReceived atomic.Bool // indicates whether any bytes have been received on this stream @@ -54,6 +65,29 @@ type ClientStream struct { statsHandler stats.Handler // nil for internal streams (e.g., health check, ORCA) where telemetry is not supported. } +func (s *ClientStream) startNonGRPCDataCollection(st *status.Status) { + s.nonGRPCStatus = st + s.nonGRPCDataBuf = make([]byte, 0, nonGRPCDataMaxLen) +} + +// finalizeNonGRPCStatus builds the terminal status by appending the collected +// response body to the original non-gRPC status message. +func (s *ClientStream) finalizeNonGRPCStatus() *status.Status { + msg := fmt.Sprintf("%s\ndata: %q", s.nonGRPCStatus.Message(), s.nonGRPCDataBuf) + return status.New(s.nonGRPCStatus.Code(), msg) +} + +// handleNonGRPCData collects non-gRPC body from the given data frame. +// It returns non-nil value when the stream should be closed with it. +func (s *ClientStream) handleNonGRPCData(f *parsedDataFrame) *status.Status { + n := min(f.data.Len(), nonGRPCDataMaxLen-len(s.nonGRPCDataBuf)) + s.nonGRPCDataBuf = append(s.nonGRPCDataBuf, f.data.ReadOnlyData()[0:n]...) + if len(s.nonGRPCDataBuf) >= nonGRPCDataMaxLen || f.StreamEnded() { + return s.finalizeNonGRPCStatus() + } + return nil +} + // Read reads an n byte message from the input stream. func (s *ClientStream) Read(n int) (mem.BufferSlice, error) { b, err := s.Stream.read(n) diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go index 7efa524785..c5a76b70ad 100644 --- a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go +++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go @@ -956,39 +956,16 @@ func (l *loopyWriter) processData() (bool, error) { // from data is copied to h to make as big as the maximum possible HTTP2 frame // size. - if len(dataItem.h) == 0 && reader.Remaining() == 0 { // Empty data frame - // Client sends out empty data frame with endStream = true - if err := l.framer.writeData(dataItem.streamID, dataItem.endStream, nil); err != nil { - return false, err - } - str.itl.dequeue() // remove the empty data item from stream - reader.Close() - if str.itl.isEmpty() { - str.state = empty - } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers. - if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil { - return false, err - } - if err := l.cleanupStreamHandler(trailer.cleanup); err != nil { - return false, err - } - } else { - l.activeStreams.enqueue(str) - } - return false, nil - } - + isEmpty := len(dataItem.h) == 0 && reader.Remaining() == 0 // Figure out the maximum size we can send maxSize := http2MaxFrameLen - if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota <= 0 { // stream-level flow control. + strQuota := int(l.oiws) - str.bytesOutStanding + if strQuota <= 0 && !isEmpty { // stream-level flow control. str.state = waitingOnStreamQuota return false, nil - } else if maxSize > strQuota { - maxSize = strQuota - } - if maxSize > int(l.sendQuota) { // connection-level flow control. - maxSize = int(l.sendQuota) } + maxSize = min(maxSize, max(strQuota, 0)) + maxSize = min(maxSize, int(l.sendQuota)) // connection-level flow control. // Compute how much of the header and data we can send within quota and max frame length hSize := min(maxSize, len(dataItem.h)) dSize := min(maxSize-hSize, reader.Remaining()) @@ -1039,19 +1016,23 @@ func (l *loopyWriter) processData() (bool, error) { reader.Close() str.itl.dequeue() } + return false, l.updateStreamAfterWrite(str) +} + +func (l *loopyWriter) updateStreamAfterWrite(str *outStream) error { if str.itl.isEmpty() { str.state = empty - } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // The next item is trailers. + } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers. if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil { - return false, err + return err } if err := l.cleanupStreamHandler(trailer.cleanup); err != nil { - return false, err + return err } } else if int(l.oiws)-str.bytesOutStanding <= 0 { // Ran out of stream quota. str.state = waitingOnStreamQuota } else { // Otherwise add it back to the list of active streams. l.activeStreams.enqueue(str) } - return false, nil + return nil } diff --git a/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go b/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go index 7cfbc9637b..98cef9ec2b 100644 --- a/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go +++ b/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go @@ -115,7 +115,6 @@ func (f *trInFlow) getSize() uint32 { return atomic.LoadUint32(&f.effectiveWindowSize) } -// TODO(mmukhi): Simplify this code. // inFlow deals with inbound flow control type inFlow struct { mu sync.Mutex @@ -174,14 +173,14 @@ func (f *inFlow) maybeAdjust(n uint32) uint32 { // onData is invoked when some data frame is received. It updates pendingData. func (f *inFlow) onData(n uint32) error { f.mu.Lock() + defer f.mu.Unlock() + f.pendingData += n if f.pendingData+f.pendingUpdate > f.limit+f.delta { limit := f.limit rcvd := f.pendingData + f.pendingUpdate - f.mu.Unlock() return fmt.Errorf("received %d-bytes data exceeding the limit %d bytes", rcvd, limit) } - f.mu.Unlock() return nil } @@ -189,8 +188,9 @@ func (f *inFlow) onData(n uint32) error { // to be sent to the peer. func (f *inFlow) onRead(n uint32) uint32 { f.mu.Lock() + defer f.mu.Unlock() + if f.pendingData == 0 { - f.mu.Unlock() return 0 } f.pendingData -= n @@ -205,9 +205,7 @@ func (f *inFlow) onRead(n uint32) uint32 { if f.pendingUpdate >= f.limit/4 { wu := f.pendingUpdate f.pendingUpdate = 0 - f.mu.Unlock() return wu } - f.mu.Unlock() return 0 } diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go index 7ab3422b8a..a8356c9adb 100644 --- a/vendor/google.golang.org/grpc/internal/transport/handler_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go @@ -479,8 +479,8 @@ func (ht *serverHandlerTransport) runStream() { func (ht *serverHandlerTransport) incrMsgRecv() {} -func (ht *serverHandlerTransport) Drain(string) { - panic("Drain() is not implemented") +func (ht *serverHandlerTransport) Drain(s string) { + ht.Close(errors.New(s)) } // mapRecvMsgError returns the non-nil err into the appropriate diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go index d6bc6a6cc7..133f5d7065 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go @@ -39,6 +39,7 @@ import ( "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/channelz" icredentials "google.golang.org/grpc/internal/credentials" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpcutil" @@ -318,7 +319,13 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts } writeBufSize := opts.WriteBufferSize readBufSize := opts.ReadBufferSize + // The default header list size is moving from 16MB to 8KB. The 8KB limit + // is only used if Enable8KBDefaultHeaderListSize is true; otherwise, the + // old 16MB default is used. User-specified options always take precedence. maxHeaderListSize := defaultClientMaxHeaderListSize + if envconfig.Enable8KBDefaultHeaderListSize { + maxHeaderListSize = upcomingDefaultHeaderListSize + } if opts.MaxHeaderListSize != nil { maxHeaderListSize = *opts.MaxHeaderListSize } @@ -879,8 +886,8 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr, handler s return false } } - if sz > int64(upcomingDefaultHeaderListSize) { - t.logger.Warningf("Header list size to send (%d bytes) is larger than the upcoming default limit (%d bytes). In a future release, this will be restricted to %d bytes.", sz, upcomingDefaultHeaderListSize, upcomingDefaultHeaderListSize) + if !envconfig.Enable8KBDefaultHeaderListSize && sz > int64(upcomingDefaultHeaderListSize) { + t.logger.Warningf("Header list size to send (%d bytes) is larger than the upcoming default limit (%d bytes). In release v1.82.0, GRPC_GO_EXPERIMENTAL_ENABLE_8KB_DEFAULT_HEADER_LIST_SIZE will be enabled by default, enforcing this limit.", sz, upcomingDefaultHeaderListSize) } return true } @@ -1224,6 +1231,23 @@ func (t *http2Client) handleData(f *parsedDataFrame) { t.closeStream(s, io.EOF, true, http2.ErrCodeFlowControl, status.New(codes.Internal, err.Error()), nil, false) return } + + if s.nonGRPCStatus != nil { + // The frame should be handled as a non-gRPC response body + st := s.handleNonGRPCData(f) + if st != nil { + t.closeStream(s, st.Err(), true, http2.ErrCodeProtocol, st, nil, true) + return + } + if w := s.fc.onRead(size); w > 0 { + t.controlBuf.put(&outgoingWindowUpdate{ + streamID: s.id, + increment: w, + }) + } + return + } + dataLen := f.data.Len() if f.Header().Flags.Has(http2.FlagDataPadded) { if w := s.fc.onRead(size - uint32(dataLen)); w > 0 { @@ -1468,6 +1492,17 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { return } + // If we are collecting non-gRPC response data and receive a trailing + // HEADERS frame with END_STREAM, finalize the buffered data and close + // the stream. + if s.nonGRPCStatus != nil { + if endStream { + st := s.finalizeNonGRPCStatus() + t.closeStream(s, st.Err(), true, http2.ErrCodeProtocol, st, nil, true) + } + return + } + var ( // If a gRPC Response-Headers has already been received, then it means // that the peer is speaking gRPC and we are in gRPC mode. @@ -1568,7 +1603,12 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { } se := status.New(grpcErrorCode, strings.Join(errs, "; ")) - t.closeStream(s, se.Err(), true, http2.ErrCodeProtocol, se, nil, endStream) + if endStream { + t.closeStream(s, se.Err(), true, http2.ErrCodeProtocol, se, nil, true) + return + } + + s.startNonGRPCDataCollection(se) return } diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go index 3a8c36e4f9..1acd44be4b 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go @@ -38,11 +38,13 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/grpc/internal" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/internal/pretty" istatus "google.golang.org/grpc/internal/status" "google.golang.org/grpc/internal/syscall" + transportinternal "google.golang.org/grpc/internal/transport/internal" "google.golang.org/grpc/mem" "google.golang.org/grpc/codes" @@ -165,7 +167,13 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, } writeBufSize := config.WriteBufferSize readBufSize := config.ReadBufferSize + // The default header list size is moving from 16MB to 8KB. The 8KB limit + // is only used if Enable8KBDefaultHeaderListSize is true; otherwise, the + // old 16MB default is used. User-specified options always take precedence. maxHeaderListSize := defaultServerMaxHeaderListSize + if envconfig.Enable8KBDefaultHeaderListSize { + maxHeaderListSize = upcomingDefaultHeaderListSize + } if config.MaxHeaderListSize != nil { maxHeaderListSize = *config.MaxHeaderListSize } @@ -948,8 +956,8 @@ func (t *http2Server) checkForHeaderListSize(hf []hpack.HeaderField) bool { return false } } - if sz > int64(upcomingDefaultHeaderListSize) { - t.logger.Warningf("Header list size to send (%d bytes) is larger than the upcoming default limit (%d bytes). In a future release, this will be restricted to %d bytes.", sz, upcomingDefaultHeaderListSize, upcomingDefaultHeaderListSize) + if !envconfig.Enable8KBDefaultHeaderListSize && sz > int64(upcomingDefaultHeaderListSize) { + t.logger.Warningf("Header list size to send (%d bytes) is larger than the upcoming default limit (%d bytes). In release v1.82.0, GRPC_GO_EXPERIMENTAL_ENABLE_8KB_DEFAULT_HEADER_LIST_SIZE will be enabled by default, enforcing this limit.", sz, upcomingDefaultHeaderListSize) } return true } @@ -1441,14 +1449,14 @@ func (t *http2Server) socketMetrics() *channelz.EphemeralSocketMetrics { func (t *http2Server) incrMsgSent() { if channelz.IsOn() { t.channelz.SocketMetrics.MessagesSent.Add(1) - t.channelz.SocketMetrics.LastMessageSentTimestamp.Add(1) + t.channelz.SocketMetrics.LastMessageSentTimestamp.Store(transportinternal.TimeNowFunc()) } } func (t *http2Server) incrMsgRecv() { if channelz.IsOn() { t.channelz.SocketMetrics.MessagesReceived.Add(1) - t.channelz.SocketMetrics.LastMessageReceivedTimestamp.Add(1) + t.channelz.SocketMetrics.LastMessageReceivedTimestamp.Store(transportinternal.TimeNowFunc()) } } diff --git a/vendor/google.golang.org/grpc/internal/grpcutil/regex.go b/vendor/google.golang.org/grpc/internal/transport/internal/internal.go similarity index 59% rename from vendor/google.golang.org/grpc/internal/grpcutil/regex.go rename to vendor/google.golang.org/grpc/internal/transport/internal/internal.go index 7a092b2b80..a7c7c7d5a8 100644 --- a/vendor/google.golang.org/grpc/internal/grpcutil/regex.go +++ b/vendor/google.golang.org/grpc/internal/transport/internal/internal.go @@ -1,6 +1,6 @@ /* * - * Copyright 2021 gRPC authors. + * Copyright 2026 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,16 +16,10 @@ * */ -package grpcutil +// Package internal contains functionality internal to the transport package. +package internal -import "regexp" - -// FullMatchWithRegex returns whether the full text matches the regex provided. -func FullMatchWithRegex(re *regexp.Regexp, text string) bool { - if len(text) == 0 { - return re.MatchString(text) - } - re.Longest() - rem := re.FindString(text) - return len(rem) == len(text) -} +// TimeNowFunc is a variable that can be set to override the default behavior of +// getting the current time in nanoseconds. It is used in transport code to set +// channelz timestamps, and is exposed here for testing purposes. +var TimeNowFunc func() int64 diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go index 1e224576e8..6dfae39849 100644 --- a/vendor/google.golang.org/grpc/internal/transport/transport.go +++ b/vendor/google.golang.org/grpc/internal/transport/transport.go @@ -35,6 +35,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/internal/channelz" + "google.golang.org/grpc/internal/transport/internal" "google.golang.org/grpc/keepalive" "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" @@ -46,6 +47,10 @@ import ( const logLevel = 2 +func init() { + internal.TimeNowFunc = func() int64 { return time.Now().UnixNano() } +} + // recvMsg represents the received msg from the transport. All transport // protocol specific info has been removed. type recvMsg struct { diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go index ee7f7dead1..52f4ea513d 100644 --- a/vendor/google.golang.org/grpc/rpc_util.go +++ b/vendor/google.golang.org/grpc/rpc_util.go @@ -128,6 +128,16 @@ func NewGZIPDecompressor() Decompressor { } func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) { + return d.doWithMaxSize(r, math.MaxInt64) +} + +// doWithMaxSize behaves like Do but caps the size of the decompressed +// payload at maxMessageSize+1 bytes. The Decompressor interface does not +// allow extra parameters, so callers inside the package type-assert to +// *gzipDecompressor to invoke this method directly. The +1 byte makes it +// possible for the caller to detect that the limit was exceeded and +// return ResourceExhausted instead of materializing an unbounded payload. +func (d *gzipDecompressor) doWithMaxSize(r io.Reader, maxMessageSize int64) ([]byte, error) { var z *gzip.Reader switch maybeZ := d.pool.Get().(type) { case nil: @@ -148,7 +158,11 @@ func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) { z.Close() d.pool.Put(z) }() - return io.ReadAll(z) + var src io.Reader = z + if maxMessageSize < math.MaxInt64 { + src = io.LimitReader(z, maxMessageSize+1) + } + return io.ReadAll(src) } func (d *gzipDecompressor) Type() string { @@ -830,15 +844,15 @@ func compress(in mem.BufferSlice, cp Compressor, compressor encoding.Compressor, if compressor != nil { z, err := compressor.Compress(w) if err != nil { - return nil, 0, wrapErr(err) + return nil, compressionNone, wrapErr(err) } for _, b := range in { if _, err := z.Write(b.ReadOnlyData()); err != nil { - return nil, 0, wrapErr(err) + return nil, compressionNone, wrapErr(err) } } if err := z.Close(); err != nil { - return nil, 0, wrapErr(err) + return nil, compressionNone, wrapErr(err) } } else { // This is obviously really inefficient since it fully materializes the data, but @@ -848,7 +862,7 @@ func compress(in mem.BufferSlice, cp Compressor, compressor encoding.Compressor, buf := in.MaterializeToBuffer(pool) defer buf.Free() if err := cp.Do(w, buf.ReadOnlyData()); err != nil { - return nil, 0, wrapErr(err) + return nil, compressionNone, wrapErr(err) } } return out, compressionMade, nil @@ -971,7 +985,20 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { if dc != nil { r := d.Reader() - uncompressed, err := dc.Do(r) + // For the built-in gzip decompressor, bound the decompressed output + // at maxReceiveMessageSize+1 so that a small but highly compressed + // payload (a "zip bomb") cannot expand to gigabytes in memory before + // the post-decompression size check below has a chance to fire. The + // Decompressor interface does not accept an extra size parameter, + // so we type-assert to invoke a size-aware helper. Third-party + // Decompressor implementations keep the original Do behavior. + var uncompressed []byte + var err error + if gd, ok := dc.(*gzipDecompressor); ok { + uncompressed, err = gd.doWithMaxSize(r, int64(maxReceiveMessageSize)) + } else { + uncompressed, err = dc.Do(r) + } if err != nil { r.Close() // ensure buffers are reused return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) @@ -989,6 +1016,9 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompress r.Close() // ensure buffers are reused return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the message: %v", err) } + if closer, ok := dcReader.(io.Closer); ok { + defer closer.Close() + } // Read at most one byte more than the limit from the decompressor. // Unless the limit is MaxInt64, in which case, that's impossible, so diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index 5229adf711..cf0a206719 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -28,6 +28,7 @@ import ( "net/http" "reflect" "runtime" + "runtime/pprof" "strings" "sync" "sync/atomic" @@ -150,8 +151,6 @@ type Server struct { serverWorkerChannel chan func() serverWorkerChannelClose func() - - strictPathCheckingLogEmitted atomic.Bool } type serverOptions struct { @@ -250,10 +249,8 @@ func newJoinServerOption(opts ...ServerOption) ServerOption { // If this option is set to true every connection will release the buffer after // flushing the data on the wire. // -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a -// later release. +// Deprecated: shared write buffer is enabled by default. SharedWriteBuffer +// will be removed in a future release. func SharedWriteBuffer(val bool) ServerOption { return newFuncServerOption(func(o *serverOptions) { o.sharedWriteBuffer = val @@ -302,6 +299,14 @@ func InitialConnWindowSize(s int32) ServerOption { // window size to the value provided and disables dynamic flow control. // The lower bound for window size is 64K and any value smaller than that // will be ignored. +// +// Note that this also disables dynamic flow control for the connection, +// falling back to a default static connection-level window of 64KB. To +// use a larger connection-level window, you must also use the +// [StaticConnWindowSize] ServerOption. +// +// Most users should not configure static flow control windows unless +// operating in a memory-constrained environment. func StaticStreamWindowSize(s int32) ServerOption { return newFuncServerOption(func(o *serverOptions) { o.initialWindowSize = s @@ -313,6 +318,14 @@ func StaticStreamWindowSize(s int32) ServerOption { // window size to the value provided and disables dynamic flow control. // The lower bound for window size is 64K and any value smaller than that // will be ignored. +// +// Note that this also disables dynamic flow control for individual streams, +// falling back to a default static connection-level window of 64KB. To +// explicitly configure the stream-level window size, you must also use the +// [StaticStreamWindowSize] ServerOption. +// +// Most users should not configure static flow control windows unless +// operating in a memory-constrained environment. func StaticConnWindowSize(s int32) ServerOption { return newFuncServerOption(func(o *serverOptions) { o.initialConnWindowSize = s @@ -1787,6 +1800,12 @@ func (s *Server) handleMalformedMethodName(stream *transport.ServerStream, ti *t func (s *Server) handleStream(t transport.ServerTransport, stream *transport.ServerStream) { ctx := stream.Context() ctx = contextWithServer(ctx, s) + if envconfig.LabelServerGoroutines&envconfig.GoroutineLabelServerMethod != 0 { + // This method always runs in its own goroutine, so we can set a + // goroutine label without needing to restore a previous context. + ctx = pprof.WithLabels(ctx, pprof.Labels("grpc.method", stream.Method())) + pprof.SetGoroutineLabels(ctx) + } var ti *traceInfo if EnableTracing { tr := newTrace("grpc.Recv."+methodFamily(stream.Method()), stream.Method()) @@ -1803,28 +1822,11 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Ser } } - sm := stream.Method() - if sm == "" { + sm, found := strings.CutPrefix(stream.Method(), "/") + if !found { s.handleMalformedMethodName(stream, ti) return } - if sm[0] != '/' { - // TODO(easwars): Add a link to the CVE in the below log messages once - // published. - if envconfig.DisableStrictPathChecking { - if old := s.strictPathCheckingLogEmitted.Swap(true); !old { - channelz.Warningf(logger, s.channelz, "grpc: Server.handleStream received malformed method name %q. Allowing it because the environment variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING is set to true, but this option will be removed in a future release.", sm) - } - } else { - if old := s.strictPathCheckingLogEmitted.Swap(true); !old { - channelz.Warningf(logger, s.channelz, "grpc: Server.handleStream rejected malformed method name %q. To temporarily allow such requests, set the environment variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING to true. Note that this is not recommended as it may allow requests to bypass security policies.", sm) - } - s.handleMalformedMethodName(stream, ti) - return - } - } else { - sm = sm[1:] - } pos := strings.LastIndex(sm, "/") if pos == -1 { s.handleMalformedMethodName(stream, ti) diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 3ccfe515f7..cf114ef4bc 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.81.1" +const Version = "1.82.0" diff --git a/vendor/modules.txt b/vendor/modules.txt index 8e0522661a..503c8ba393 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -481,8 +481,8 @@ github.com/google/uuid # github.com/gookit/color v1.6.1 ## explicit; go 1.18 github.com/gookit/color -# github.com/gopherjs/gopherjs v1.20.2 -## explicit; go 1.20 +# github.com/gopherjs/gopherjs v1.21.0 +## explicit; go 1.21 github.com/gopherjs/gopherjs/js # github.com/gorilla/securecookie v1.1.2 ## explicit; go 1.20 @@ -583,8 +583,8 @@ github.com/jinzhu/now # github.com/json-iterator/go v1.1.12 ## explicit; go 1.12 github.com/json-iterator/go -# github.com/klauspost/cpuid/v2 v2.3.0 -## explicit; go 1.22 +# github.com/klauspost/cpuid/v2 v2.4.0 +## explicit; go 1.24.0 github.com/klauspost/cpuid/v2 # github.com/klauspost/reedsolomon v1.14.1 ## explicit; go 1.24 @@ -623,7 +623,7 @@ github.com/lithammer/fuzzysearch/fuzzy # github.com/lucasb-eyer/go-colorful v1.4.0 ## explicit; go 1.12 github.com/lucasb-eyer/go-colorful -# github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e +# github.com/lufia/plan9stats v0.0.0-20260627054121-477a66015f15 ## explicit; go 1.21 github.com/lufia/plan9stats # github.com/mattn/go-colorable v0.1.15 @@ -687,7 +687,7 @@ github.com/orandin/lumberjackrus # github.com/oschwald/geoip2-golang/v2 v2.2.0 ## explicit; go 1.25.0 github.com/oschwald/geoip2-golang/v2 -# github.com/oschwald/maxminddb-golang/v2 v2.4.0 +# github.com/oschwald/maxminddb-golang/v2 v2.4.1 ## explicit; go 1.25.0 github.com/oschwald/maxminddb-golang/v2 github.com/oschwald/maxminddb-golang/v2/internal/decoder @@ -763,16 +763,16 @@ github.com/pion/mdns/v2 # github.com/pion/randutil v0.1.0 ## explicit; go 1.14 github.com/pion/randutil -# github.com/pion/rtcp v1.2.16 -## explicit; go 1.21 +# github.com/pion/rtcp v1.2.17 +## explicit; go 1.24.0 github.com/pion/rtcp -# github.com/pion/rtp v1.10.2 +# github.com/pion/rtp v1.10.3 ## explicit; go 1.24.0 github.com/pion/rtp github.com/pion/rtp/codecs github.com/pion/rtp/codecs/av1/obu github.com/pion/rtp/codecs/vp9 -# github.com/pion/sctp v1.10.2 +# github.com/pion/sctp v1.10.3 ## explicit; go 1.24.0 github.com/pion/sctp # github.com/pion/sdp/v3 v3.0.19 @@ -796,7 +796,7 @@ github.com/pion/transport/v4/reuseport github.com/pion/transport/v4/stdnet github.com/pion/transport/v4/utils/xor github.com/pion/transport/v4/vnet -# github.com/pion/turn/v5 v5.0.10 +# github.com/pion/turn/v5 v5.0.12 ## explicit; go 1.24.0 github.com/pion/turn/v5 github.com/pion/turn/v5/internal/allocation @@ -805,7 +805,7 @@ github.com/pion/turn/v5/internal/client github.com/pion/turn/v5/internal/ipnet github.com/pion/turn/v5/internal/proto github.com/pion/turn/v5/internal/server -# github.com/pion/webrtc/v4 v4.2.15 +# github.com/pion/webrtc/v4 v4.2.16 ## explicit; go 1.24.0 github.com/pion/webrtc/v4 github.com/pion/webrtc/v4/internal/fmtp @@ -813,8 +813,8 @@ github.com/pion/webrtc/v4/internal/mux github.com/pion/webrtc/v4/internal/util github.com/pion/webrtc/v4/pkg/media github.com/pion/webrtc/v4/pkg/rtcerr -# github.com/pires/go-proxyproto v0.12.0 -## explicit; go 1.25 +# github.com/pires/go-proxyproto v0.14.0 +## explicit; go 1.25.0 github.com/pires/go-proxyproto # github.com/pkg/errors v0.9.1 ## explicit @@ -898,7 +898,7 @@ github.com/shirou/gopsutil/v3/load github.com/shirou/gopsutil/v3/mem github.com/shirou/gopsutil/v3/net github.com/shirou/gopsutil/v3/process -# github.com/shoenig/go-m1cpu v0.2.1 +# github.com/shoenig/go-m1cpu v0.2.2 ## explicit; go 1.20 github.com/shoenig/go-m1cpu # github.com/shopspring/decimal v1.4.0 @@ -1197,7 +1197,7 @@ go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace/embedded go.opentelemetry.io/otel/trace/internal/telemetry go.opentelemetry.io/otel/trace/noop -# go.starlark.net v0.0.0-20260613233743-8ba36ccb83fb +# go.starlark.net v0.0.0-20260630144053-529d8e869a14 ## explicit; go 1.25.0 go.starlark.net/internal/compile go.starlark.net/internal/spell @@ -1318,12 +1318,12 @@ golang.zx2c4.com/wireguard/conn golang.zx2c4.com/wireguard/conn/winrio golang.zx2c4.com/wireguard/rwcancel golang.zx2c4.com/wireguard/tun -# google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 +# google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 ## explicit; go 1.25.0 -# google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d +# google.golang.org/genproto/googleapis/rpc v0.0.0-20260630182238-925bb5da69e7 ## explicit; go 1.25.0 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.81.1 +# google.golang.org/grpc v1.82.0 ## explicit; go 1.25.0 google.golang.org/grpc google.golang.org/grpc/attributes @@ -1344,13 +1344,13 @@ google.golang.org/grpc/credentials/insecure google.golang.org/grpc/encoding google.golang.org/grpc/encoding/internal google.golang.org/grpc/encoding/proto +google.golang.org/grpc/experimental/balancer/weight google.golang.org/grpc/experimental/stats google.golang.org/grpc/grpclog google.golang.org/grpc/grpclog/internal google.golang.org/grpc/internal google.golang.org/grpc/internal/backoff google.golang.org/grpc/internal/balancer/gracefulswitch -google.golang.org/grpc/internal/balancer/weight google.golang.org/grpc/internal/balancerload google.golang.org/grpc/internal/binarylog google.golang.org/grpc/internal/buffer @@ -1376,6 +1376,7 @@ google.golang.org/grpc/internal/stats google.golang.org/grpc/internal/status google.golang.org/grpc/internal/syscall google.golang.org/grpc/internal/transport +google.golang.org/grpc/internal/transport/internal google.golang.org/grpc/internal/transport/networktype google.golang.org/grpc/internal/transport/readyreader google.golang.org/grpc/keepalive