api/internal/browser/vnc_proxy.go (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
package browser import ( "api/internal/database" "context" "fmt" "net" "github.com/coder/websocket" ) type VNCProxy struct { session *database.BrowserSession } func NewVNCProxy(session *database.BrowserSession) *VNCProxy { return &VNCProxy{ session: session, } } func (p *VNCProxy) ServeWebSocket(ctx context.Context, ws *websocket.Conn) error { // Connect to VNC server vncConn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", p.session.VNCPort)) if err != nil { return fmt.Errorf("failed to connect to VNC server: %w", err) } defer vncConn.Close() // Create channels for error handling errChan := make(chan error, 2) // Forward WebSocket -> VNC go func() { for { messageType, data, err := ws.Read(ctx) if err != nil { errChan <- err return } if messageType == websocket.MessageBinary { _, err = vncConn.Write(data) if err != nil { errChan <- err return } } } }() // Forward VNC -> WebSocket go func() { buffer := make([]byte, 4096) for { n, err := vncConn.Read(buffer) if err != nil { errChan <- err return } err = ws.Write(ctx, websocket.MessageBinary, buffer[:n]) if err != nil { errChan <- err return } } }() // Wait for any errors return <-errChan } |