File: mirror.go

package info (click to toggle)
incus 6.0.4-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 23,864 kB
  • sloc: sh: 16,015; ansic: 3,121; python: 456; makefile: 321; ruby: 51; sql: 50; lisp: 6
file content (68 lines) | stat: -rw-r--r-- 1,658 bytes parent folder | download | duplicates (6)
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
package ws

import (
	"io"

	"github.com/gorilla/websocket"

	"github.com/lxc/incus/v6/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 error, chan error) {
	chRead := MirrorRead(conn, rwc)
	chWrite := MirrorWrite(conn, rwc)

	return chRead, chWrite
}

// MirrorRead is a uni-directional mirror which replicates an io.Reader to a websocket.
func MirrorRead(conn *websocket.Conn, rc io.Reader) chan error {
	chDone := make(chan error, 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() {
		_, err := io.Copy(connRWC, rc)

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

		// Send write barrier.
		connRWC.Close()

		chDone <- err
		close(chDone)
	}()

	return chDone
}

// MirrorWrite is a uni-directional mirror which replicates a websocket to an io.Writer.
func MirrorWrite(conn *websocket.Conn, wc io.Writer) chan error {
	chDone := make(chan error, 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() {
		_, err := io.Copy(wc, connRWC)

		logger.Debug("Websocket: Stopped write mirror", logger.Ctx{"address": conn.RemoteAddr().String(), "err": err})
		chDone <- err
		close(chDone)
	}()

	return chDone
}