sumdb

Imports

Imports #

"sync"
"sync/atomic"
"bytes"
"errors"
"fmt"
"strings"
"sync"
"sync/atomic"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/note"
"golang.org/x/mod/sumdb/tlog"
"bytes"
"context"
"net/http"
"os"
"strings"
"golang.org/x/mod/internal/lazyregexp"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/tlog"
"context"
"fmt"
"sync"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/note"
"golang.org/x/mod/sumdb/tlog"

Constants & Variables

ErrGONOSUMDB var #

ErrGONOSUMDB is returned by [Client.Lookup] for paths that match a pattern listed in the GONOSUMDB list (set by [Client.SetGONOSUMDB], usually from the environment variable).

var ErrGONOSUMDB = *ast.CallExpr

ErrSecurity var #

ErrSecurity is returned by [Client] operations that invoke Client.SecurityError.

var ErrSecurity = *ast.CallExpr

ErrWriteConflict var #

ErrWriteConflict signals a write conflict during Client.WriteConfig.

var ErrWriteConflict = *ast.CallExpr

ServerPaths var #

ServerPaths are the URL paths the Server can (and should) serve. Typically a server will do: srv := sumdb.NewServer(ops) for _, path := range sumdb.ServerPaths { http.Handle(path, srv) }

var ServerPaths = []string{...}

modVerRE var #

var modVerRE = *ast.CallExpr

msgFuture const #

const msgFuture

msgNow const #

const msgNow

msgPast const #

const msgPast = *ast.BinaryExpr

Type Aliases

testHashes type #

testHashes implements tlog.HashReader, reading from a slice.

type testHashes []tlog.Hash

Interfaces

ClientOps interface #

A ClientOps provides the external operations (file caching, HTTP fetches, and so on) needed by the [Client]. The methods must be safe for concurrent use by multiple goroutines.

type ClientOps interface {
ReadRemote(path string) ([]byte, error)
ReadConfig(file string) ([]byte, error)
WriteConfig(file string, old []byte, new []byte) error
ReadCache(file string) ([]byte, error)
WriteCache(file string, data []byte)
Log(msg string)
SecurityError(msg string)
}

ServerOps interface #

A ServerOps provides the external operations (underlying database access and so on) needed by the [Server].

type ServerOps interface {
Signed(ctx context.Context) ([]byte, error)
ReadRecords(ctx context.Context, id int64, n int64) ([][]byte, error)
Lookup(ctx context.Context, m module.Version) (int64, error)
ReadTileData(ctx context.Context, t tlog.Tile) ([]byte, error)
}

Structs

Client struct #

A Client is a client connection to a checksum database. All the methods are safe for simultaneous use by multiple goroutines.

type Client struct {
ops ClientOps
didLookup uint32
initOnce sync.Once
initErr error
name string
verifiers note.Verifiers
tileReader tileReader
tileHeight int
nosumdb string
record parCache
tileCache parCache
latestMu sync.Mutex
latest tlog.Tree
latestMsg []byte
tileSavedMu sync.Mutex
tileSaved map[tlog.Tile]bool
}

Server struct #

A Server is the checksum database HTTP server, which implements http.Handler and should be invoked to serve the paths listed in [ServerPaths].

type Server struct {
ops ServerOps
}

TestServer struct #

A TestServer is an in-memory implementation of [ServerOps] for testing.

type TestServer struct {
signer string
gosum func(path string, vers string) ([]byte, error)
mu sync.Mutex
hashes testHashes
records [][]byte
lookup map[string]int64
}

cacheEntry struct #

type cacheEntry struct {
done uint32
mu sync.Mutex
result interface{}
}

parCache struct #

parCache runs an action once per key and caches the result.

type parCache struct {
m sync.Map
}

tileReader struct #

tileReader is a *Client wrapper that implements tlog.TileReader. The separate type avoids exposing the ReadTiles and SaveTiles methods on Client itself.

type tileReader struct {
c *Client
}

Functions

Do method #

Do calls the function f if and only if Do is being called for the first time with this key. No call to Do with a given key returns until the one call to f returns. Do returns the value returned by the one call to f.

func (c *parCache) Do(key interface{}, f func() interface{}) interface{}

Get method #

Get returns the cached result associated with key. It returns nil if there is no such result. If the result for key is being computed, Get does not wait for the computation to finish.

func (c *parCache) Get(key interface{}) interface{}

Height method #

func (r *tileReader) Height() int

Lookup method #

Lookup returns the go.sum lines for the given module path and version. The version may end in a /go.mod suffix, in which case Lookup returns the go.sum lines for the module's go.mod-only hash.

func (c *Client) Lookup(path string, vers string) (lines []string, err error)

Lookup method #

func (s *TestServer) Lookup(ctx context.Context, m module.Version) (int64, error)

NewClient function #

NewClient returns a new [Client] using the given [ClientOps].

func NewClient(ops ClientOps) *Client

NewServer function #

NewServer returns a new Server using the given operations.

func NewServer(ops ServerOps) *Server

NewTestServer function #

NewTestServer constructs a new [TestServer] that will sign its tree with the given signer key (see [golang.org/x/mod/sumdb/note]) and fetch new records as needed by calling gosum.

func NewTestServer(signer string, gosum func(path string, vers string) ([]byte, error)) *TestServer

ReadHashes method #

func (h testHashes) ReadHashes(indexes []int64) ([]tlog.Hash, error)

ReadRecords method #

func (s *TestServer) ReadRecords(ctx context.Context, id int64, n int64) ([][]byte, error)

ReadTileData method #

func (s *TestServer) ReadTileData(ctx context.Context, t tlog.Tile) ([]byte, error)

ReadTiles method #

ReadTiles reads and returns the requested tiles, either from the on-disk cache or the server.

func (r *tileReader) ReadTiles(tiles []tlog.Tile) ([][]byte, error)

SaveTiles method #

SaveTiles saves the now validated tiles.

func (r *tileReader) SaveTiles(tiles []tlog.Tile, data [][]byte)

ServeHTTP method #

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

SetGONOSUMDB method #

SetGONOSUMDB sets the list of comma-separated GONOSUMDB patterns for the Client. For any module path matching one of the patterns, [Client.Lookup] will return ErrGONOSUMDB. SetGONOSUMDB can be called at most once, and if so it must be called before the first call to Lookup.

func (c *Client) SetGONOSUMDB(list string)

SetTileHeight method #

SetTileHeight sets the tile height for the Client. Any call to SetTileHeight must happen before the first call to [Client.Lookup]. If SetTileHeight is not called, the Client defaults to tile height 8. SetTileHeight can be called at most once, and if so it must be called before the first call to Lookup.

func (c *Client) SetTileHeight(height int)

Signed method #

func (s *TestServer) Signed(ctx context.Context) ([]byte, error)

checkRecord method #

checkRecord checks that record #id's hash matches data.

func (c *Client) checkRecord(id int64, data []byte) error

checkTrees method #

checkTrees checks that older (from olderNote) is contained in newer (from newerNote). If an error occurs, such as malformed data or a network problem, checkTrees returns that error. If on the other hand checkTrees finds evidence of misbehavior, it prepares a detailed message and calls log.Fatal.

func (c *Client) checkTrees(older tlog.Tree, olderNote []byte, newer tlog.Tree, newerNote []byte) error

init method #

init initializes the client (if not already initialized) and returns any initialization error.

func (c *Client) init() error

initWork method #

initWork does the actual initialization work.

func (c *Client) initWork()

markTileSaved method #

markTileSaved records that tile is already present in the on-disk cache, so that a future SaveTiles for that tile can be ignored.

func (c *Client) markTileSaved(tile tlog.Tile)

mergeLatest method #

mergeLatest merges the tree head in msg with the Client's current latest tree head, ensuring the result is a consistent timeline. If the result is inconsistent, mergeLatest calls c.ops.SecurityError with a detailed security error message and then (only if c.ops.SecurityError does not exit the program) returns ErrSecurity. If the Client's current latest tree head moves forward, mergeLatest updates the underlying configuration file as well, taking care to merge any independent updates to that configuration.

func (c *Client) mergeLatest(msg []byte) error

mergeLatestMem method #

mergeLatestMem is like mergeLatest but is only concerned with updating the in-memory copy of the latest tree head (c.latest) not the configuration file. The when result explains when msg happened relative to our previous idea of c.latest: msgPast means msg was from before c.latest, msgNow means msg was exactly c.latest, and msgFuture means msg was from after c.latest, which has now been updated.

func (c *Client) mergeLatestMem(msg []byte) (when int, err error)

readTile method #

readTile reads a single tile, either from the on-disk cache or the server.

func (c *Client) readTile(tile tlog.Tile) ([]byte, error)

reportError function #

reportError reports err to w. If it's a not-found, the reported error is 404. Otherwise it is an internal server error. The caller must only call reportError in contexts where a not-found err should be reported as 404.

func reportError(w http.ResponseWriter, err error)

skip method #

func (c *Client) skip(target string) bool

tileCacheKey method #

tileCacheKey returns the cache key for the tile.

func (c *Client) tileCacheKey(tile tlog.Tile) string

tileRemotePath method #

tileRemotePath returns the remote path for the tile.

func (c *Client) tileRemotePath(tile tlog.Tile) string

Generated with Arrow