aboutsummaryrefslogtreecommitdiff
path: root/protocol/v0v1/server/session.go
blob: b27ad8cd03de94f14d1c3aec66f2f4a5759d552e (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package server

import (
	"io"

	"codeberg.org/lindenii/furgit/format/pktline"
	"codeberg.org/lindenii/furgit/format/sideband64k"
	"codeberg.org/lindenii/furgit/objectid"
)

// Options configures one server-side v0/v1 session.
type Options struct {
	// Version selects protocol v0 or v1 framing.
	Version Version
	// Algorithm is the repository object ID algorithm for this session.
	Algorithm objectid.Algorithm
}

// Session is one stateful server-side v0/v1 server protocol session.
type Session struct {
	dec         *pktline.Decoder
	enc         *pktline.Encoder
	sideband    *sideband64k.Encoder
	opts        Options
	useSideBand bool
}

// NewSession creates one v0/v1 server session over r and w.
func NewSession(r io.Reader, w pktline.WriteFlusher, opts Options) *Session {
	return &Session{
		dec:      pktline.NewDecoder(r, pktline.ReadOptions{}),
		enc:      pktline.NewEncoder(w),
		sideband: sideband64k.NewEncoder(w),
		opts:     opts,
	}
}

// Algorithm returns the session object ID algorithm.
func (session *Session) Algorithm() objectid.Algorithm {
	return session.opts.Algorithm
}

// ReadFrame reads one low-level pkt-line frame from the session input.
func (session *Session) ReadFrame() (Frame, error) {
	return session.dec.ReadFrame()
}

// EnableSideBand64K enables side-band-64k output framing for subsequent data,
// progress, error, and flush writes.
func (session *Session) EnableSideBand64K() {
	session.useSideBand = true
}

// WriteData writes one primary output packet.
func (session *Session) WriteData(p []byte) error {
	if session.useSideBand {
		return session.sideband.WriteData(p)
	}

	return session.enc.WriteData(p)
}

// WriteProgress writes one progress packet.
func (session *Session) WriteProgress(p []byte) error {
	if !session.useSideBand {
		return ErrSideBandNotEnabled
	}

	return session.sideband.WriteProgress(p)
}

// WriteError writes one fatal error packet.
func (session *Session) WriteError(p []byte) error {
	if !session.useSideBand {
		return ErrSideBandNotEnabled
	}

	return session.sideband.WriteError(p)
}

// WriteFlush writes one trailing flush packet.
func (session *Session) WriteFlush() error {
	if session.useSideBand {
		return session.sideband.WriteFlush()
	}

	return session.enc.WriteFlush()
}

// ProgressWriter returns one chunking writer for sideband progress output.
//
// When side-band-64k was not negotiated, writes are discarded.
func (session *Session) ProgressWriter() io.Writer {
	if !session.useSideBand {
		return io.Discard
	}

	return sideband64k.NewChunkWriter(session.sideband, sideband64k.BandProgress)
}

// ErrorWriter returns one chunking writer for sideband error output.
//
// When side-band-64k was not negotiated, writes are discarded.
func (session *Session) ErrorWriter() io.Writer {
	if !session.useSideBand {
		return io.Discard
	}

	return sideband64k.NewChunkWriter(session.sideband, sideband64k.BandError)
}