main
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}