forked from sandia-minimega/minimega
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ufs.go
133 lines (105 loc) · 2.35 KB
/
ufs.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2015-2021 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain
// rights in this software.
package ron
import (
"errors"
"fmt"
log "minilog"
"net"
)
// ListenUFS starts a listener to connect to UFS running on the VM specified by
// the UUID. Returns the TCP port or an error.
func (s *Server) ListenUFS(uuid string) (int, error) {
s.clientLock.Lock()
defer s.clientLock.Unlock()
c, ok := s.clients[uuid]
if !ok {
return 0, fmt.Errorf("no such client: %v", uuid)
}
m := &Message{
Type: MESSAGE_UFS,
UUID: uuid,
UfsMode: UFS_OPEN,
}
if err := c.sendMessage(m); err != nil {
return 0, err
}
// Listen on random tcp port
l, err := net.Listen("tcp4", ":0")
if err != nil {
return 0, err
}
c.Lock()
defer c.Unlock()
c.ufsListener = l
addr := l.Addr().(*net.TCPAddr)
go func() {
defer l.Close()
log.Info("waiting for connections to ufs on %v", addr)
for {
conn, err := l.Accept()
if err != nil {
log.Error("accept failed: %v", err)
c.Lock()
defer c.Unlock()
c.ufsListener = nil
return
}
log.Info("new connection from %v", conn.RemoteAddr())
c.Lock()
c.ufsConn = conn
c.Unlock()
// blocks until connection is done
Trunk(conn, c.UUID, func(m *Message) error {
m.Type = MESSAGE_UFS
m.UfsMode = UFS_DATA
return c.sendMessage(m)
})
c.Lock()
c.ufsConn = nil
c.Unlock()
conn.Close()
m := &Message{
Type: MESSAGE_UFS,
UUID: uuid,
UfsMode: UFS_CLOSE,
}
if err := c.sendMessage(m); err != nil {
log.Error("unable to close: %v", err)
}
}
}()
return addr.Port, nil
}
func (s *Server) DisconnectUFS(uuid string) error {
s.clientLock.Lock()
defer s.clientLock.Unlock()
c, ok := s.clients[uuid]
if !ok {
return fmt.Errorf("no such client: %v", uuid)
}
c.Lock()
defer c.Unlock()
if c.ufsListener == nil {
return errors.New("ufs is not running")
}
m := &Message{
Type: MESSAGE_UFS,
UUID: uuid,
UfsMode: UFS_CLOSE,
}
if err := c.sendMessage(m); err != nil {
log.Error("unable to close: %v", err)
}
c.ufsListener.Close()
c.ufsListener = nil
if c.ufsConn != nil {
c.ufsConn.Close()
c.ufsConn = nil
}
return nil
}
func (c *client) ufsMessage(m *Message) {
c.ufsConn.Write(m.Tunnel)
}