Operating system for OpenComputers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
4.0KB

  1. local vcomponent = require "vcomponent"
  2. local serial = require "serialization"
  3. local component = require "component"
  4. local computer = require "computer"
  5. local event = require "event"
  6. local imt = require "interminitel"
  7. local cfg = {}
  8. cfg.peers = {}
  9. cfg.rtimer = 5
  10. cfg.katimer = 30
  11. local listeners = {}
  12. local timers = {}
  13. local proxies = {}
  14. local function loadcfg()
  15. local f = io.open("/boot/cfg/vtunnel.cfg","rb")
  16. if not f then return false end
  17. for k,v in pairs(serial.unserialize(f:read("*a")) or {}) do
  18. cfg[k] = v
  19. end
  20. f:close()
  21. end
  22. local function savecfg()
  23. local f = io.open("/boot/cfg/vtunnel.cfg","wb")
  24. if not f then
  25. print("Warning: unable to save configuration.")
  26. return false
  27. end
  28. f:write(serial.serialize(cfg))
  29. f:close()
  30. end
  31. local function createTunnel(host,port,addr,raddr)
  32. local proxy = {address=addr,buffer=""}
  33. function proxy.connect()
  34. if proxy.socket then
  35. proxy.socket.close()
  36. end
  37. proxy.socket = component.invoke(component.list("internet")(),"connect",host,port)
  38. local st = computer.uptime()
  39. repeat
  40. coroutine.yield()
  41. until proxy.socket.finishConnect() or computer.uptime() > st+5
  42. end
  43. function proxy.send(...)
  44. rt = 0
  45. while not proxy.socket.write(imt.encodePacket(...)) and rt < 10 do
  46. proxy.connect()
  47. rt = rt + 1
  48. end
  49. proxy.last = computer.uptime()
  50. end
  51. function proxy.read()
  52. local rb, r
  53. local rt = 0
  54. while true do
  55. rb,r = proxy.socket.read(4096)
  56. if rb or rt > 10 then break end
  57. if type(rb) == "nil" then
  58. proxy.connect()
  59. end
  60. rt = rt + 1
  61. end
  62. proxy.buffer = proxy.buffer .. rb
  63. while imt.decodePacket(proxy.buffer) do
  64. computer.pushSignal("modem_message",addr,raddr,0,0,imt.decodePacket(proxy.buffer))
  65. proxy.buffer = imt.getRemainder(proxy.buffer) or ""
  66. end
  67. if computer.uptime() > proxy.last + cfg.katimer then
  68. proxy.socket.write("\0\1\0")
  69. proxy.last = computer.uptime()
  70. end
  71. end
  72. function proxy.getWakeMessage()
  73. return false
  74. end
  75. proxy.setWakeMessage = proxy.getWakeMessage
  76. function proxy.maxPacketSize()
  77. return 8192
  78. end
  79. function proxy.getChannel()
  80. return host..":"..tostring(port)
  81. end
  82. proxy.connect()
  83. proxy.last = computer.uptime()
  84. return proxy, read
  85. end
  86. vt = {}
  87. function start()
  88. loadcfg()
  89. for k,v in pairs(cfg.peers) do
  90. print(string.format("Connecting to %s:%d",v.host,v.port))
  91. v.addr = v.addr or vcomponent.uuid()
  92. v.raddr = v.raddr or vcomponent.uuid()
  93. local px,tr = createTunnel(v.host, v.port, v.addr, v.raddr)
  94. vcomponent.register(v.addr, "tunnel", px)
  95. timers[v.addr] = tr
  96. proxies[v.addr] = px
  97. end
  98. for k,v in pairs(os.tasks()) do
  99. if os.taskInfo(v).name:match("minitel") then
  100. os.kill(v)
  101. end
  102. end
  103. end
  104. function vt.stop()
  105. for k,v in pairs(listeners) do
  106. event.ignore(v[1],v[2])
  107. end
  108. for k,v in pairs(timers) do
  109. event.cancel(v)
  110. end
  111. for k,v in pairs(proxies) do
  112. vcomponent.unregister(k)
  113. end
  114. end
  115. function vt.listpeers()
  116. for k,v in pairs(cfg.peers) do
  117. print(string.format("#%d (%s:%d)\n Local address: %s\n Remote address: %s",k,v.host,v.port,v.addr,v.raddr))
  118. end
  119. end
  120. function vt.addpeer(host,port)
  121. port = tonumber(port) or 4096
  122. local t = {}
  123. t.host = host
  124. t.port = port
  125. t.addr = vcomponent.uuid()
  126. t.raddr = vcomponent.uuid()
  127. cfg.peers[#cfg.peers+1] = t
  128. print(string.format("Added peer #%d (%s:%d) to the configuration.\nRestart to apply changes.",#cfg.peers,host,port))
  129. savecfg()
  130. end
  131. function vt.delpeer(n)
  132. n=tonumber(n)
  133. if not n then
  134. print("delpeer requires a number, representing the peer number, as an argument.")
  135. return false
  136. end
  137. local dp = table.remove(cfg.peers, n)
  138. savecfg()
  139. print(string.format("Removed peer %s:%d",dp.host, dp.port))
  140. end
  141. function vt.settimer(time)
  142. time = tonumber(time)
  143. if not time then
  144. print("Timer must be a number.")
  145. return false
  146. end
  147. cfg.rtime = time
  148. savecfg()
  149. end
  150. vt.start = start
  151. _G.libs.vtunnel = vt
  152. print(pcall(start))
  153. local last = computer.uptime()
  154. while true do
  155. local tE = {coroutine.yield()}
  156. if computer.uptime() > last + cfg.rtimer then
  157. for k,v in pairs(timers) do
  158. print(pcall(v))
  159. end
  160. last = computer.uptime()
  161. end
  162. end
  163. --[[
  164. _G.vtunnel = {}
  165. _G.vtunnel.start = start
  166. _G.vtunnel.delpeer = delpeer
  167. ]]