main
Raw Download raw file
  1// Package cli provides CLI infrastructure for govnc.
  2package cli
  3
  4import (
  5	"net/http"
  6	"time"
  7
  8	"goVNC/pkg/proxy"
  9	"goVNC/pkg/rfb"
 10	"goVNC/pkg/transport"
 11	"goVNC/pkg/web"
 12)
 13
 14// Config holds all CLI configuration.
 15type Config struct {
 16	// Target WebSocket URL
 17	URL string
 18
 19	// Connection options
 20	Connection ConnectionConfig
 21
 22	// VNC session options
 23	VNC VNCConfig
 24
 25	// Input options
 26	Input InputConfig
 27
 28	// Clipboard options
 29	Clipboard ClipboardConfig
 30
 31	// Server mode options
 32	Server ServerConfig
 33
 34	// Output options
 35	Output OutputConfig
 36}
 37
 38// ConnectionConfig holds connection-related settings.
 39type ConnectionConfig struct {
 40	// Headers to send with the connection (repeatable).
 41	Headers http.Header
 42
 43	// Cookie string to send.
 44	Cookie string
 45
 46	// UserAgent to send.
 47	UserAgent string
 48
 49	// Proxy URL for upstream proxy.
 50	Proxy string
 51
 52	// ConnectTimeout for connection establishment.
 53	ConnectTimeout time.Duration
 54
 55	// Insecure skips TLS verification.
 56	Insecure bool
 57}
 58
 59// VNCConfig holds VNC-specific settings.
 60type VNCConfig struct {
 61	// User for VNC authentication (user:password format).
 62	User string
 63
 64	// Password for VNC authentication.
 65	Password string
 66
 67	// AuthNone forces no authentication.
 68	AuthNone bool
 69
 70	// Shared requests a shared session.
 71	Shared bool
 72
 73	// Exclusive requests an exclusive session.
 74	Exclusive bool
 75
 76	// Encodings to request.
 77	Encodings []int32
 78}
 79
 80// InputConfig holds input-related settings.
 81type InputConfig struct {
 82	// InputFile to read input from (- for stdin).
 83	InputFile string
 84
 85	// TypeText to type and exit.
 86	TypeText string
 87
 88	// KeyDelay between keystrokes in milliseconds.
 89	KeyDelay int
 90}
 91
 92// ClipboardConfig holds clipboard-related settings.
 93type ClipboardConfig struct {
 94	// ClipInDir to watch for outgoing clipboard files.
 95	ClipInDir string
 96
 97	// ClipOutDir to save incoming clipboard files.
 98	ClipOutDir string
 99
100	// ClipSend text to send to clipboard and exit.
101	ClipSend string
102}
103
104// ServerConfig holds server mode settings.
105type ServerConfig struct {
106	// HTTPAddr to start HTTP/WS server on.
107	HTTPAddr string
108
109	// ProxyMode for client sessions.
110	ProxyMode string
111
112	// MaxClients for concurrent WebSocket clients.
113	MaxClients int
114
115	// NoVNCPath for static noVNC files.
116	NoVNCPath string
117
118	// APIPrefix for API routes.
119	APIPrefix string
120
121	// CORSOrigin for CORS headers.
122	CORSOrigin string
123}
124
125// OutputConfig holds output-related settings.
126type OutputConfig struct {
127	// Verbose level (0-3).
128	Verbose int
129
130	// Silent suppresses output.
131	Silent bool
132
133	// OutputFile to write to.
134	OutputFile string
135}
136
137// DefaultConfig returns a Config with sensible defaults.
138func DefaultConfig() *Config {
139	return &Config{
140		Connection: ConnectionConfig{
141			Headers:        make(http.Header),
142			UserAgent:      "govnc/1.0",
143			ConnectTimeout: 30 * time.Second,
144		},
145		VNC: VNCConfig{
146			Shared:    true,
147			Encodings: rfb.DefaultEncodings(),
148		},
149		Server: ServerConfig{
150			HTTPAddr:   ":8080",
151			ProxyMode:  "shared",
152			MaxClients: 10,
153			APIPrefix:  "/api",
154			CORSOrigin: "*",
155		},
156	}
157}
158
159// ToDialOptions converts ConnectionConfig to transport.DialOptions.
160func (c *ConnectionConfig) ToDialOptions() *transport.DialOptions {
161	opts := transport.NewDialOptions()
162	opts.Headers = c.Headers.Clone()
163	if c.Cookie != "" {
164		opts.AddHeader("Cookie", c.Cookie)
165	}
166	if c.UserAgent != "" {
167		opts.AddHeader("User-Agent", c.UserAgent)
168	}
169	opts.Timeout = c.ConnectTimeout
170	opts.Proxy = c.Proxy
171	// TODO: Handle Insecure flag with TLS config
172	return opts
173}
174
175// ToHandshakeConfig converts VNCConfig to rfb.HandshakeConfig.
176func (c *VNCConfig) ToHandshakeConfig() *rfb.HandshakeConfig {
177	cfg := rfb.DefaultHandshakeConfig()
178
179	// Determine shared mode
180	if c.Exclusive {
181		cfg.SharedSession = false
182	} else if c.Shared {
183		cfg.SharedSession = true
184	}
185
186	// Set password if provided
187	if c.Password != "" {
188		cfg.Password = c.Password
189	}
190
191	// Add VNC auth if password is provided
192	if c.Password != "" && !c.AuthNone {
193		cfg.AllowedSecurityTypes = []rfb.SecurityType{
194			rfb.SecurityTypeNone,
195			rfb.SecurityTypeVNCAuth,
196		}
197	}
198
199	return cfg
200}
201
202// ToClientConfig converts VNCConfig to rfb.ClientConfig.
203func (c *VNCConfig) ToClientConfig() *rfb.ClientConfig {
204	cfg := rfb.DefaultClientConfig()
205	cfg.Handshake = c.ToHandshakeConfig()
206	if len(c.Encodings) > 0 {
207		cfg.Encodings = c.Encodings
208	}
209	return cfg
210}
211
212// ToServerConfig converts ServerConfig to web.ServerConfig.
213func (c *ServerConfig) ToServerConfig() *web.ServerConfig {
214	cfg := web.DefaultServerConfig()
215	if c.HTTPAddr != "" {
216		cfg.ListenAddr = c.HTTPAddr
217	}
218	if c.APIPrefix != "" {
219		cfg.APIPrefix = c.APIPrefix
220	}
221	if c.NoVNCPath != "" {
222		cfg.NoVNCPath = c.NoVNCPath
223	}
224	if c.CORSOrigin != "" {
225		cfg.CORSOrigin = c.CORSOrigin
226	}
227	if c.MaxClients > 0 {
228		cfg.MaxClients = c.MaxClients
229	}
230
231	switch c.ProxyMode {
232	case "isolated":
233		cfg.ProxyMode = proxy.IsolatedMode
234	default:
235		cfg.ProxyMode = proxy.SharedMode
236	}
237
238	return cfg
239}