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.

163 line
3.8KB

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