main ece7682

client.go RawHistoryFolder

1package sessionwire
2
3import (
4	"errors"
5	"time"
6
7	"google.golang.org/protobuf/proto"
8
9	"github.com/bnema/vev/internal/ports"
10	"github.com/bnema/vev/internal/protocol"
11	"github.com/bnema/vev/internal/protocol/wire"
12)
13
14type clientConnection struct {
15	handshake
16}
17
18var _ ports.ClientConnection = (*clientConnection)(nil)
19
20// NewClientConnection wraps one raw client connection incarnation. The
21// preamble runs lazily on first use, bounded by the handshake deadline
22// started here.
23func NewClientConnection(raw wire.Transport) ports.ClientConnection {
24	if raw == nil {
25		return nil
26	}
27	return &clientConnection{handshake: newHandshake(raw, time.Now().Add(protocol.HandshakeTimeout))}
28}
29
30func (c *clientConnection) ensurePreamble() error {
31	return c.handshake.ensurePreamble(runProtoClientPreamble)
32}
33
34func (c *clientConnection) SendClient(message protocol.ClientMessage) error {
35	if err := c.ensurePreamble(); err != nil {
36		return err
37	}
38	envelope, err := encodeProtoClient(message)
39	if err != nil {
40		return err
41	}
42	raw, err := proto.Marshal(envelope)
43	if err != nil {
44		return err
45	}
46	if err := checkCategoryCeiling(raw, clientEnvelopeCategory(raw), c.limits().maxReceiveEnvelopeBytes); err != nil {
47		return err
48	}
49	return c.raw.Send(wire.Envelope{Payload: raw})
50}
51
52func (c *clientConnection) ReceiveServer() (protocol.ServerMessage, error) {
53	if err := c.ensurePreamble(); err != nil {
54		return nil, err
55	}
56	envelope, err := c.raw.Recv()
57	if err != nil {
58		return nil, err
59	}
60	limits := c.limits()
61	message, decodeErr := decodeServerEnvelopeWithin(envelope.Payload, limits.maxReceiveEnvelopeBytes, limits.outputDataLimit)
62	if decodeErr == nil {
63		return message, nil
64	}
65	return nil, decodeErr
66}
67
68func (c *clientConnection) Capabilities() protocol.ConnectionCapabilities {
69	return rawCapabilities(c.raw, c.limits().outputDataLimit)
70}
71
72func (c *clientConnection) LinkState() ports.LinkState         { return rawLinkState(c.raw) }
73func (c *clientConnection) LinkEvents() <-chan ports.LinkEvent { return rawLinkEvents(c.raw) }
74func (c *clientConnection) Close() error                       { return c.raw.Close() }
75
76// DecodeServerEnvelope unwraps one scanned server envelope payload into
77// its semantic message for hidden one-shot carriages.
78func DecodeServerEnvelope(payload []byte) (protocol.ServerMessage, error) {
79	return decodeServerEnvelope(payload)
80}
81
82func decodeServerEnvelope(payload []byte) (protocol.ServerMessage, error) {
83	return decodeServerEnvelopeWithin(payload, wire.AbsoluteEnvelopeLimit, uint64(protocol.MaxOutputDataLen))
84}
85
86// decodeServerEnvelopeWithin unwraps one server envelope under the
87// negotiated receive ceilings: the serialized envelope must fit
88// maxReceiveEnvelopeBytes and any Output must declare uncompressed data at
89// or below outputDataLimit. The one-shot exported decoder uses the absolute
90// ceilings because no preamble was negotiated there.
91func decodeServerEnvelopeWithin(payload []byte, envelopeLimit, outputDataLimit uint64) (protocol.ServerMessage, error) {
92	envelope := &wire.ServerEnvelope{}
93	if err := checkCategoryCeiling(payload, serverEnvelopeCategory(payload), envelopeLimit); err != nil {
94		return nil, classifyEnvelopeError(err, envelope)
95	}
96	if err := wire.ScanEnvelope(envelope, payload); err != nil {
97		return nil, classifyEnvelopeError(err, envelope)
98	}
99	if err := (proto.UnmarshalOptions{DiscardUnknown: false}.Unmarshal(payload, envelope)); err != nil {
100		return nil, &protocol.DecodeFailure{Category: protocol.DecodeMalformed, Err: err}
101	}
102	if err := checkOutputDataCeiling(envelope, outputDataLimit); err != nil {
103		return nil, &protocol.DecodeFailure{Category: protocol.DecodeMalformed, Err: err}
104	}
105	message, err := decodeProtoServer(envelope)
106	if err != nil {
107		return nil, classifyEnvelopeError(err, envelope)
108	}
109	return message, nil
110}
111
112func classifyEnvelopeError(err error, _ *wire.ServerEnvelope) *protocol.DecodeFailure {
113	failure := &protocol.DecodeFailure{Category: protocol.DecodeMalformed, Err: err}
114	if errors.Is(err, wire.ErrScanUnknown) {
115		failure.Category = protocol.DecodeUnknownType
116	} else if errors.Is(err, ErrWrongDirection) {
117		failure.Category = protocol.DecodeWrongDirection
118	}
119	return failure
120}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close