main pico / pkg / tunkit / web-handler.go
Eric Bower  ·  2026-10-01
 1package tunkit
 2
 3import (
 4	"fmt"
 5	"log/slog"
 6	"net"
 7	"os"
 8
 9	"github.com/picosh/pico/pkg/pssh"
10)
11
12type ctxAddressKey struct{}
13
14func getAddressCtx(ctx *pssh.SSHServerConnSession) (string, error) {
15	address, ok := ctx.Value(ctxAddressKey{}).(string)
16	if address == "" || !ok {
17		return address, fmt.Errorf("address not set on `*pssh.SSHServerConnSession()` for connection")
18	}
19	return address, nil
20}
21func setAddressCtx(ctx *pssh.SSHServerConnSession, address string) {
22	ctx.SetValue(ctxAddressKey{}, address)
23}
24
25type WebTunnelHandler struct {
26	HttpHandler HttpHandlerFn
27	Logger      *slog.Logger
28}
29
30func (wt *WebTunnelHandler) GetLogger() *slog.Logger {
31	return wt.Logger
32}
33
34func (wt *WebTunnelHandler) GetHttpHandler() HttpHandlerFn {
35	return wt.HttpHandler
36}
37
38func (wt *WebTunnelHandler) Close(ctx *pssh.SSHServerConnSession) error {
39	listener, err := getListenerCtx(ctx)
40	if err != nil {
41		return err
42	}
43
44	if listener != nil {
45		_ = listener.Close()
46		setListenerCtx(ctx, nil)
47	}
48
49	return nil
50}
51
52func (wt *WebTunnelHandler) CreateListener(ctx *pssh.SSHServerConnSession) (net.Listener, error) {
53	tempFile, err := os.CreateTemp("", "")
54	if err != nil {
55		return nil, err
56	}
57
58	err = tempFile.Close()
59	if err != nil {
60		return nil, err
61	}
62	address := tempFile.Name()
63	err = os.Remove(address)
64	if err != nil {
65		return nil, err
66	}
67
68	connListener, err := net.Listen("unix", address)
69	if err != nil {
70		return nil, err
71	}
72	setAddressCtx(ctx, address)
73	setListenerCtx(ctx, connListener)
74
75	return connListener, nil
76}
77
78func (wt *WebTunnelHandler) CreateConn(ctx *pssh.SSHServerConnSession) (net.Conn, error) {
79	_, err := httpServe(wt, ctx, wt.GetLogger())
80	if err != nil {
81		wt.GetLogger().Info("unable to create listener", "err", err)
82		return nil, err
83	}
84
85	address, err := getAddressCtx(ctx)
86	if err != nil {
87		return nil, err
88	}
89
90	return net.Dial("unix", address)
91}