ollie/toolsrv/server9p.go

102 lines
2.2 KiB
Go

// server9p.go - State management for 9P toolsrv
package toolsrv
import (
"crypto/rand"
"encoding/hex"
"fmt"
"runtime"
"sync"
"ollie/fsedsl"
)
// Server9P holds the state for the 9P tool server.
type Server9P struct {
mu sync.RWMutex
secret string // set on first auth, verified on subsequent
token string // session token returned after auth
registry *Registry // tool registry
sessID string // session ID for registry scoping
yolo bool // skip sandbox
// Process management
fs *FS9P
}
// NewServer9P creates a new 9P tool server.
func NewServer9P() *Server9P {
return &Server9P{
fs: NewFS9P(""), // cwd set per-agent
}
}
// SetRegistry configures the tool registry and session ID.
func (s *Server9P) SetRegistry(r *Registry, sessID string) {
s.mu.Lock()
s.registry = r
s.sessID = sessID
s.fs.SetRegistry(r, sessID)
s.mu.Unlock()
}
// SetYolo enables/disables sandbox bypass.
func (s *Server9P) SetYolo(yolo bool) {
s.mu.Lock()
s.yolo = yolo
s.fs.SetYolo(yolo)
s.mu.Unlock()
}
// Authenticate handles secret verification.
// First call sets the secret; subsequent calls must match it.
// Returns (token, nil) on success, ("", error) on failure.
func (s *Server9P) Authenticate(clientSecret string) (string, error) {
s.mu.Lock()
defer s.mu.Unlock()
if s.secret == "" {
// First auth - set the secret
s.secret = clientSecret
s.token = randomToken()
return s.token, nil
}
// Subsequent auth - verify secret
if clientSecret != s.secret {
return "", fmt.Errorf("authentication failed")
}
return s.token, nil
}
// Token returns the current session token (empty if not authenticated).
func (s *Server9P) Token() string {
s.mu.RLock()
defer s.mu.RUnlock()
return s.token
}
// HostInfo returns platform info as key=value lines.
func (s *Server9P) HostInfo() string {
return fmt.Sprintf("platform=%s\narch=%s\n", runtime.GOOS, runtime.GOARCH)
}
// FS returns the underlying filesystem state.
func (s *Server9P) FS() *FS9P {
return s.fs
}
// BuildTree creates the fsedsl tree for this server.
func (s *Server9P) BuildTree() *fsedsl.Tree {
ctx := ToolsrvCtx{Server: s}
return fsedsl.BuildTree(ToolsrvSpec(), ctx)
}
func randomToken() string {
b := make([]byte, 16)
rand.Read(b)
return hex.EncodeToString(b)
}