File: mirror.go

package info (click to toggle)
lxd 5.0.2%2Bgit20231211.1364ae4-9
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 25,632 kB
  • sloc: sh: 14,272; ansic: 3,112; python: 432; makefile: 265; ruby: 51; sql: 50; javascript: 9; lisp: 6
file content (66 lines) | stat: -rw-r--r-- 1,645 bytes parent folder | download
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
package ws

import (
	"io"

	"github.com/gorilla/websocket"

	"github.com/canonical/lxd/shared/logger"
)

// Mirror takes a websocket and replicates all read/write to a ReadWriteCloser.
// Returns channels indicating when reads and writes are finished (respectively).
func Mirror(conn *websocket.Conn, rwc io.ReadWriteCloser) (chan struct{}, chan struct{}) {
	chRead := MirrorRead(conn, rwc)
	chWrite := MirrorWrite(conn, rwc)

	return chRead, chWrite
}

// MirrorRead is a uni-directional mirror which replicates an io.ReadCloser to a websocket.
func MirrorRead(conn *websocket.Conn, rc io.ReadCloser) chan struct{} {
	chDone := make(chan struct{}, 1)
	if rc == nil {
		close(chDone)
		return chDone
	}

	logger.Debug("Websocket: Started read mirror", logger.Ctx{"address": conn.RemoteAddr().String()})

	connRWC := NewWrapper(conn)

	go func() {
		defer close(chDone)

		_, _ = io.Copy(connRWC, rc)

		logger.Debug("Websocket: Stopped read mirror", logger.Ctx{"address": conn.RemoteAddr().String()})

		// Send write barrier.
		connRWC.Close()
	}()

	return chDone
}

// MirrorWrite is a uni-directional mirror which replicates a websocket to an io.WriteCloser.
func MirrorWrite(conn *websocket.Conn, wc io.WriteCloser) chan struct{} {
	chDone := make(chan struct{}, 1)
	if wc == nil {
		close(chDone)
		return chDone
	}

	logger.Debug("Websocket: Started write mirror", logger.Ctx{"address": conn.RemoteAddr().String()})

	connRWC := NewWrapper(conn)

	go func() {
		defer close(chDone)
		_, _ = io.Copy(wc, connRWC)

		logger.Debug("Websocket: Stopped write mirror", logger.Ctx{"address": conn.RemoteAddr().String()})
	}()

	return chDone
}