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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
package server
import (
"io"
objectid "codeberg.org/lindenii/furgit/object/id"
"codeberg.org/lindenii/furgit/protocol/pktline"
"codeberg.org/lindenii/furgit/protocol/sideband64k"
)
// 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()
}
// FlushIO flushes buffered transport output without emitting pkt-line frames.
func (session *Session) FlushIO() error {
if session.useSideBand {
return session.sideband.FlushIO()
}
return session.enc.FlushIO()
}
// 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)
}
// PrimaryDataWriter returns one chunking writer for primary output bytes.
//
// When side-band-64k is enabled, writes are chunked into band-1 sideband
// frames. Otherwise writes are chunked into direct pkt-line data frames.
func (session *Session) PrimaryDataWriter() io.Writer {
if session.useSideBand {
return sideband64k.NewChunkWriter(session.sideband, sideband64k.BandData)
}
return pktline.NewChunkWriter(session.enc)
}
|