-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathclient_view.go
67 lines (59 loc) · 2.03 KB
/
client_view.go
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
package editor
import (
"cms.csesoc.unsw.edu.au/editor/OT/operations"
"github.com/gorilla/websocket"
)
// clientView is the embodiment of all data relating to a clientView connection
// it is mostly managed by the documentServer
// quick sidenote:
// since sendOp and sendAcknowledgement are bounded we can actually deadlock the system
// by filling them up :P, the documentServer avoids this with a little hack, it spins a goroutine
// to publish updates from the clientView within the pipe
type clientView struct {
socket *websocket.Conn
sendOp chan operations.Operation
sendAcknowledgement chan empty
sendTerminateSignal chan empty
}
func newClient(socket *websocket.Conn) *clientView {
return &clientView{
socket: socket,
sendOp: make(chan operations.Operation),
sendAcknowledgement: make(chan empty),
sendTerminateSignal: make(chan empty),
}
}
// run starts the client's spinny loop
// in this loop the clientView listens for updates and pushes
// them down the websocket, it also pulls stuff up the websocket
// the documentServer will use the appropriate channels to communicate
// updates to the client, namely: sendOp and sendAcknowledgement
func (c *clientView) run(serverPipe pipe, signalDeparturePipe alertLeaving) {
for {
select {
case <-c.sendOp:
// push the operation down the websocket
// send an acknowledgement
break
case <-c.sendAcknowledgement:
// push the acknowledgement down the websocket
break
case <-c.sendTerminateSignal:
// looks like we've been told to terminate by the documentServer
// propagate this to the client and close this connection
c.socket.Close()
return
default:
if _, msg, err := c.socket.ReadMessage(); err == nil {
// push the update to the documentServer
if request, err := operations.ParseOperation(string(msg)); err == nil {
serverPipe(request)
}
} else {
// todo: push a terminate signal to the client, also tell the server we're leaving
signalDeparturePipe()
c.socket.Close()
}
}
}
}