sshserver

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package sshserver provides a pure-Go SSH server for Vision/3 BBS. It wraps gliderlabs/ssh (which itself wraps golang.org/x/crypto/ssh) and adds BBS-specific features like legacy algorithm support for retro terminal clients (SyncTERM, NetRunner) and read-interruptible sessions for clean door program I/O cancellation.

Index

Constants

This section is empty.

Variables

View Source
var ErrReadInterrupted = fmt.Errorf("read interrupted")

ErrReadInterrupted is returned by BBSSession.Read when a read interrupt fires.

Functions

func Cleanup

func Cleanup()

Cleanup is a no-op retained for API compatibility (was used to call ssh_finalize in the old C libssh implementation).

Types

type BBSSession

type BBSSession struct {
	ssh.Session
	// contains filtered or unexported fields
}

BBSSession wraps a gliderlabs ssh.Session with SetReadInterrupt support. Use WrapSession to create one.

Design invariant: at most ONE goroutine reads from the underlying ssh.Session at any time. When a read is interrupted, the orphaned goroutine reference is kept in orphanCh so the next Read() call waits for it to finish before issuing a new read. This prevents two concurrent readers from racing for bytes and silently eating keypresses.

func WrapSession

func WrapSession(s ssh.Session) *BBSSession

WrapSession wraps a gliderlabs ssh.Session to add BBS-specific features (currently: SetReadInterrupt for clean door I/O cancellation).

func (*BBSSession) Read

func (s *BBSSession) Read(p []byte) (int, error)

Read reads from the underlying SSH channel. If a read interrupt is set and fires before data arrives, ErrReadInterrupted is returned.

When an interrupted Read() leaves an orphaned goroutine blocked on the underlying session, the next Read() call waits for that goroutine to finish first. This guarantees only one reader is active at a time and prevents keypresses from being silently consumed by a stale goroutine.

func (*BBSSession) SetReadInterrupt

func (s *BBSSession) SetReadInterrupt(ch <-chan struct{})

SetReadInterrupt registers a channel that, when closed, causes any blocked Read() to return ErrReadInterrupted without consuming data. Pass nil to clear the interrupt.

type Config

type Config struct {
	HostKeyPath                string
	Host                       string
	Port                       int
	LegacySSHAlgorithms        bool
	SessionHandler             func(ssh.Session)
	PasswordHandler            func(ctx ssh.Context, password string) bool
	KeyboardInteractiveHandler func(ctx ssh.Context, challenger gossh.KeyboardInteractiveChallenge) bool
	Version                    string // SSH server banner version (default: "Vision3")
}

Config holds SSH server configuration.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server wraps a gliderlabs/ssh server.

func NewServer

func NewServer(cfg Config) (*Server, error)

NewServer creates and configures a new SSH server.

func (*Server) Close

func (s *Server) Close() error

Close shuts down the server and all active connections.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe binds to the configured address and serves SSH connections. It blocks until the server is closed.

func (*Server) Serve

func (s *Server) Serve(l net.Listener) error

Serve starts serving on an existing listener. Blocks until closed.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL