ref: 803089a76171db1dd5b891fb6dfa1b7e7f3d50d2
dir: /protocol/v0v1/server/session.go/
package server
import (
"io"
"codeberg.org/lindenii/furgit/objectid"
"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)
}