-
Notifications
You must be signed in to change notification settings - Fork 1
/
vncd
179 lines (156 loc) · 4.3 KB
/
vncd
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
local args = {...}
local connections = {}
local nshAPI = {
connList = connections
}
nshAPI.getRemoteID = function()
return false
end
nshAPI.send = function(msg)
return false
end
nshAPI.receive = function(timeout)
return false
end
nshAPI.getClientCapabilities = function()
return false
end
nshAPI.getRemoteConnections = function()
local remotes = {}
for cNum, cInfo in pairs(nshAPI.connList) do
table.insert(remotes, cNum)
if cInfo.outbound then
table.insert(remotes, cInfo.outbound)
end
end
return remotes
end
nshAPI.packFile = function(path)
return false
end
nshAPI.unpackAndSaveFile = function(path, data)
return false
end
local packetConversion = {
query = "SQ",
response = "SR",
data = "SP",
close = "SC",
textTable = "TT",
event = "EV",
SQ = "query",
SR = "response",
SP = "data",
SC = "close",
TT = "textTable",
EV = "event",
}
local function openModem()
local modemFound = false
for _, side in ipairs(rs.getSides()) do
if peripheral.getType(side) == "modem" then
if not rednet.isOpen(side) then rednet.open(side) end
modemFound = true
break
end
end
return modemFound
end
local function send(id, pType, message)
if pType and message then
if term.current then
return rednet.send(id, packetConversion[pType]..":;"..message, "tror")
else
return rednet.send(id, packetConversion[pType]..":;"..message)
end
end
end
local function resumeThread(co, event)
if not co.filter or event[1] == co.filter then
co.filter = nil
local _old = term.redirect(co.target)
local passback = {coroutine.resume(co.thread, unpack(event))}
if _old then term.redirect(_old) else term.restore() end
if passback[1] and passback[2] then
co.filter = passback[2]
end
if coroutine.status(co.thread) == "dead" then
for cNum, cInfo in pairs(connections) do
send(cNum, "close", "disconnect")
end
connections = {}
end
if connections[conn] and conn ~= "localShell" and framebuffer then
for cNum, cInfo in pairs(connections) do
send(cNum, "textTable", textutils.serialize(co.target.buffer))
end
end
framebuffer.draw(co.target.buffer)
end
end
if not openModem() then error("No modem present!") end
local bufferDirs = {"/","/LyqydOS/","/usr/apis/","/disk/"}
if not framebuffer then
for i = 1, #bufferDirs do
if fs.exists(bufferDirs[i].."framebuffer") and os.loadAPI(bufferDirs[i].."framebuffer") then
break
end
end
end
if not framebuffer then
print("Couldn't find framebuffer API!")
return
end
term.clear()
term.setCursorPos(1,1)
local x, y = term.getSize()
local redirect = framebuffer.new(x, y, term.isColor())
local shellRoutine = coroutine.create(function() shell.run("/rom/programs/shell", unpack(args)) end)
local co = {thread = shellRoutine, target = redirect}
resumeThread(co, {})
_G.nsh = nshAPI
while coroutine.status(co.thread) ~= "dead" do
event = {os.pullEventRaw()}
if event[1] == "rednet_message" then
if packetConversion[string.sub(event[3], 1, 2)] then
--this is a packet meant for us.
conn = event[2]
packetType = packetConversion[string.sub(event[3], 1, 2)]
message = string.match(event[3], ";(.*)")
if connections[conn] and connections[conn].status == "open" then
if packetType == "event" then
local eventTable = textutils.unserialize(message)
resumeThread(co, eventTable)
elseif packetType == "query" then
connections[conn] = {status = "open"}
send(conn, "response", "OK")
send(conn, "textTable", textutils.serialize(co.target.buffer))
elseif packetType == "close" then
connections[conn] = nil
send(conn, "close", "disconnect")
--close connection
end
elseif packetType ~= "query" then
--usually, we would send a disconnect here, but this prevents one from hosting nsh and connecting to other computers. Pass these to all shells as well.
resumeThread(co, event)
else
--open new connection
connections[conn] = {status = "open"}
send(conn, "response", "OK")
send(conn, "textTable", textutils.serialize(co.target.buffer))
end
else
--rednet message, but not in the correct format, so pass to all shells.
resumeThread(co, event)
end
elseif event[1] == "terminate" then
break
else
--dispatch all other events to all shells
resumeThread(co, event)
end
end
for cNum, cInfo in pairs(connections) do
send(cNum, "close", "disconnect")
end
_G.nsh = nil