· 6 years ago · Apr 11, 2020, 10:02 PM
1--[[
2- SRN v1.1.0
3- By TheQWERTYCoder
4- Modified by legomaster616
5-
6- Licensed under the GNU GPL.
7- You may copy this API as long as you...
8-
9- 1. License the copy under the GNU GPL
10- 2. Modify it in a way that changes the functionality (You can't make a copy that does the exact same thing)
11- 3. Tell the user that it is modified
12-
13- Thank you for reading!
14]]
15
16
17local localhost
18version = "1.1.0"
19
20function init(side, host)
21 api_path = settings.get("api.path")
22 if not api_path then
23 api_path = "."
24 end
25 rsa_path = api_path.."/rsa.lua"
26
27 if not fs.exists(rsa_path) then
28 error("rsa.lua not found! "..
29 "Please install to \""..api_path..
30 "\" or set api.path to correct path")
31 end
32 if not rsa then
33 os.loadAPI(rsa_path)
34 end
35 rednet.open(side) -- Make sure modem is open
36 localhost = host
37 rednet.host(
38 "SRNv"..version,
39 (
40 host or
41 os.computerLabel() or
42 tostring(os.computerID())
43 )
44 ) -- Enables srn connections
45end
46
47local function srnGetMsg(msg, host, timeout)
48 local id, data
49 local endtime = timeout and (
50 os.clock() + timeout
51 )
52
53 repeat
54 id, data = rednet.receive("SRNv"..version, 1)
55 until
56 (
57 data and data.host == host and data.msg == msg
58 ) or (
59 timeout and os.clock() == endtime
60 )
61 return id,data
62end
63
64local function srnSendMsg(host, msg, data)
65 local ID = rednet.lookup("SRNv"..version, host)
66 rednet.send(ID, {
67 msg = msg,
68 host = localhost,
69 data = data
70 }, "SRNv"..version)
71end
72
73local srncon = {}
74function connect(host)
75 local key = rsa.new()
76 srnSendMsg(host, "CONNECT", nil)
77 srnSendMsg(host, "PUBKEY", key.public)
78 local id, data = srnGetMsg("PUBKEY", host)
79 key.public = data.data
80 srncon[host] = {
81 id = id,
82 rsa = key,
83 send = function(msg)
84 srnSendMsg(
85 self.id,
86 "DATA",
87 self.rsa.encrypt(msg)
88 )
89 end
90 }
91end
92
93local function resolveCon(host)
94 local id,data = srnGetMsg("CONNECT",host)
95 srncon[data.host] = {
96 id = host,
97 rsa = rsa.new(),
98 send = function(msg)
99 srnSendMsg(
100 self.id,
101 "DATA",
102 self.rsa.encrypt(msg)
103 )
104 end
105 }
106 rednet.send(
107 id, {
108 msg="PUBKEY",
109 host=localhost,
110 data=key.public
111 },
112 "SRNv"..version
113 )
114 local id, data = srnGetMsg("PUBKEY",id)
115 srncon[data.host].rsa.public = data.data
116end
117
118function listen(host, timeout)
119 parallel.waitForAny(
120 function()
121 resolveCon(host)
122 end,
123 function()
124 local endtime = (
125 timeout and os.clock() + timeout
126 )
127 repeat coroutine.yield()
128 until (endtime and os.clock() >= endtime)
129 end
130 )
131end
132
133local function hostname(ID)
134 for k,v in srncon do
135 if v.id == ID then
136 return k
137 end
138 end
139 return id
140end
141
142function send(host, msg)
143 if not srncon[host] then
144 connect(host)
145 end
146 srncon[host].send(msg)
147end
148
149function receive(timeout)
150 listen(nil,timeout)
151 local id,data = srnGetMsg("DATA")
152 return srncon[data.host].rsa.decrypt(data.data)
153end