ollie/fs/handlers_session.go

192 lines
4.4 KiB
Go

package fs
import (
"fmt"
"os"
"strings"
"ollie/bypass"
"ollie/session"
)
func readSessionIdx(_ HandlerCtx) ([]byte, error) {
return session.BuildIndex(), nil
}
func readAgentIdx(ctx HandlerCtx) ([]byte, error) {
return session.BuildAgentIndex(ctx.Session.Core), nil
}
func requestSessionNew(_ HandlerCtx, data []byte) ([]byte, error) {
args := strings.Fields(string(data))
name := ""
remote := ""
for _, arg := range args {
if k, v, ok := strings.Cut(arg, "="); ok {
switch k {
case "name":
name = v
case "remote":
remote = v
}
}
}
sess, err := session.CreateEmpty(name, remote)
if err != nil {
return nil, err
}
return []byte(sess.Name() + "\n"), nil
}
// sessionBindings returns bindings for all sessions.
// The Blueprint pattern clones the structure and binds ctx.Session.
func sessionBindings(ctx HandlerCtx) ([]Binding, error) {
rs := ctx.RootState
sessions := session.Sessions()
out := make([]Binding, 0, len(sessions))
for name, sess := range sessions {
// Get or create cached SessionNode wrapper
node := rs.GetOrCreateNode(sess)
n := name // capture
out = append(out, Binding{
Name: sess.Name(),
Aliases: []string{sess.ID},
UID: sess.Uname,
GID: "agent",
Applier: func(c HandlerCtx) HandlerCtx {
c.Context = node.Ctx()
c.Session = node
c.Remove = func() {
session.Kill(n)
rs.RemoveNode(n)
}
c.Rename = func(newName string) error {
if err := session.Rename(n, newName); err != nil {
return err
}
rs.RenameNode(n, newName)
return nil
}
return c
},
Remove: func() {
session.Kill(n)
rs.RemoveNode(n)
},
Rename: func(newName string) error {
if err := session.Rename(n, newName); err != nil {
return err
}
rs.RenameNode(n, newName)
return nil
},
})
}
return out, nil
}
func readSessionEnv(ctx HandlerCtx) ([]byte, error) {
s := ctx.Session
var sb strings.Builder
fmt.Fprintf(&sb, "OLLIE_SESSION_ID=%s\n", s.ID())
for _, e := range os.Environ() {
if strings.HasPrefix(e, "OLLIE_") && !strings.HasPrefix(e, "OLLIE_SESSION_ID=") {
sb.WriteString(e)
sb.WriteByte('\n')
}
}
return []byte(sb.String()), nil
}
func readSessionPaused(ctx HandlerCtx) ([]byte, error) {
if ctx.Session.IsPaused() {
return []byte("true\n"), nil
}
return []byte("false\n"), nil
}
func readSessionConnected(ctx HandlerCtx) ([]byte, error) {
if ctx.Session.IsConnected() {
return []byte("true\n"), nil
}
return []byte("false\n"), nil
}
func requestSessionCtl(ctx HandlerCtx, data []byte) ([]byte, error) {
return rdwrDispatch(sessionCtlHandlers)(ctx, data)
}
var sessionCtlHandlers = map[string]rdwrHandler{
"kill": func(ctx HandlerCtx, _ []string) ([]byte, error) {
ctx.Remove()
return []byte("ok\n"), nil
},
".": func(ctx HandlerCtx, _ []string) ([]byte, error) {
ctx.Remove()
return []byte("ok\n"), nil
},
"save": func(ctx HandlerCtx, _ []string) ([]byte, error) {
if ctx.Session.Core != nil {
ctx.Session.Core.Save()
}
return []byte("ok\n"), nil
},
"invalidate": func(ctx HandlerCtx, _ []string) ([]byte, error) {
ctx.Session.InvalidateModelsCache()
return []byte("ok\n"), nil
},
"pause": func(ctx HandlerCtx, _ []string) ([]byte, error) {
if err := ctx.Session.Pause(); err != nil {
return nil, err
}
return []byte("ok\n"), nil
},
"resume": func(ctx HandlerCtx, _ []string) ([]byte, error) {
if err := ctx.Session.Resume(); err != nil {
return nil, err
}
return []byte("ok\n"), nil
},
}
func readSessionName(ctx HandlerCtx) ([]byte, error) {
return []byte(ctx.Session.Name() + "\n"), nil
}
func writeSessionName(ctx HandlerCtx, data []byte) error {
newName := strings.TrimSpace(string(data))
if newName == "" {
return nil
}
oldName := ctx.Session.Name()
if newName != oldName {
return ctx.Rename(newName)
}
return nil
}
func readSessionID(ctx HandlerCtx) ([]byte, error) {
return []byte(ctx.Session.ID() + "\n"), nil
}
func readSessionBypass(ctx HandlerCtx) ([]byte, error) {
if ctx.Bypass == nil {
return nil, fmt.Errorf("bypass broker not available")
}
p := ctx.Bypass.SessionPolicy(ctx.Session.ID())
return p.Marshal()
}
func writeSessionBypass(ctx HandlerCtx, data []byte) error {
if ctx.Bypass == nil {
return fmt.Errorf("bypass broker not available")
}
var p bypass.Policy
if err := bypass.ParsePolicy(data, &p); err != nil {
return err
}
ctx.Bypass.SetSessionPolicy(ctx.Session.ID(), p)
return nil
}