OpenComputers Von Neumann Machine Programs
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.

194 lines
4.8 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. local async = require("async")
  2. local computer = require("computer")
  3. local component = require("component")
  4. local coroutine = require("coroutine")
  5. local dns = require("dns")
  6. local serial = require("serialization")
  7. local table = require("table")
  8. local string = require("string")
  9. local modem = component.proxy(component.list("modem")())
  10. local args = {...}
  11. -- Take some existing modem functions and data
  12. local net = {
  13. addr = modem.address,
  14. type = modem.type,
  15. open = modem.open,
  16. isOpen = modem.isOpen,
  17. close = modem.close,
  18. isWireless = modem.isWireless,
  19. maxPacketSize = modem.maxPacketSize,
  20. }
  21. -- Used to determine if a string is a proper uuid
  22. function isUUID(s)
  23. local pattern = {8,4,4,4,12}
  24. local t = split(s, "-")
  25. for i, v in ipairs(t) do
  26. if #v ~= pattern[i] or tonumber(v, 16) == nil then
  27. return false
  28. end
  29. end
  30. return true
  31. end
  32. -- Resolve addresses if they aren't UUIDs
  33. function checkAddr(addr)
  34. if not isUUID(addr) then
  35. return dns.query(addr)
  36. end
  37. return addr
  38. end
  39. -- Close all ports
  40. function net.closeAll()
  41. for i = 1, 65535 do
  42. net.close(i)
  43. end
  44. end
  45. -- Strength getter and setter
  46. function net.strength(n)
  47. if n ~= nil then
  48. modem.setStrength(n)
  49. else
  50. return modem.getStrength()
  51. end
  52. end
  53. -- Wake mesage getter and setter
  54. function net.wakeMsg(msg, fuzzy)
  55. if msg ~= nil then
  56. modem.setWakeMessage(msg, fuzzy)
  57. else
  58. return modem.getWakeMessage()
  59. end
  60. end
  61. -- Send network packets
  62. -- Auto serializes data for you
  63. function net.send(addr, port, ...)
  64. addr = checkAddr(addr)
  65. local arg = table.pack(...)
  66. for k, v in ipairs(arg) do
  67. -- Only serialize tables
  68. if type(v) == "table" then
  69. arg[k] = serial.serialize(v)
  70. end
  71. end
  72. modem.send(addr, port, table.unpack(arg))
  73. end
  74. -- Broadcast network packets
  75. -- Auto serializes data for you
  76. function net.broadcast(port, ...)
  77. local arg = table.pack(...)
  78. for k, v in ipairs(arg) do
  79. -- Only serialize tables
  80. if type(v) == "table" then
  81. arg[k] = serial.serialize(v)
  82. end
  83. end
  84. modem.broadcast(port, table.unpack(arg))
  85. end
  86. -- Custom function to receive network packets
  87. -- Can specify a port and or address for simple filtering
  88. -- Can also supply a filter function in addition to simple filtering
  89. -- If port supplied, default action is to open the port for you
  90. -- If nonblocking, uses coroutine.yield() do be prepared to handle that
  91. function net.recv(t)
  92. local pkt = {}
  93. local tmp = {}
  94. -- This allows default and keyword args
  95. if t ~= nil then
  96. setmetatable(t,{__index={
  97. port = nil,
  98. addr = nil,
  99. fuzzy = false,
  100. timeout = nil,
  101. filter = nil,
  102. open = true,
  103. }})
  104. local port, addr, timeout, filter, open =
  105. t[1] or t.port,
  106. t[2] or t.addr,
  107. t[3] or t.timeout,
  108. t[4] or t.filter,
  109. t[5] or t.open
  110. if addr ~= nil then
  111. addr = checkAddr(addr)
  112. end
  113. -- Automatically open port to listen on
  114. -- NOTE: Only works on a single port, if the filter function listens on
  115. -- multiple you'll have to do that manually
  116. if open and net ~= nil then net.open(port) end
  117. ----------------
  118. -- Basic filter function used to call user defined filter functions
  119. function f(name, ...)
  120. -- Get rid of all non modem messages
  121. if name ~= "modem_message" then return false end
  122. local arg = {...}
  123. local resAddress, resPort = arg[2], arg[3]
  124. -- Check port is good
  125. if port ~= nil and resPort ~= port then
  126. return false
  127. end
  128. -- Check addr is good
  129. if resAddr ~= nil and resAddr == addr then
  130. return false
  131. end
  132. -- Do further filtering
  133. if filter ~= nil then
  134. return filter(name, ...)
  135. else
  136. return true
  137. end
  138. end
  139. ----------------
  140. if timeout ~= nil then
  141. tmp = {async.pullFiltered(timeout, f)}
  142. else
  143. tmp = {async.pullFiltered(f)}
  144. end
  145. end
  146. -- Check for non-packets
  147. if #tmp == 0 then
  148. return nil, "timeout"
  149. elseif tmp[1] == "interrupted" then
  150. return nil, "interrupted"
  151. end
  152. -- Create basis of packet
  153. pkt.laddr, pkt.raddr, pkt.port, pkt.distance, pkt.msg = tmp[2], tmp[3], tmp[4], tmp[5], tmp[6]
  154. local data = {}
  155. for i = 6, #tmp do
  156. -- Unserialize any serialized data
  157. if type(tmp[i]) == "string" then
  158. status, res = pcall(serial.unserialize, tmp[i])
  159. if status and res == nil then data[i-5] = tmp[i] else data[i-5] = res end
  160. else
  161. data[i-5] = tmp[i]
  162. end
  163. end
  164. pkt.data = data
  165. return pkt
  166. end
  167. -- wget -f http://localhost:8080/lib/net.lua /usr/lib/net.lua
  168. -- wget -f http://mc.bashed.rocks:13699/lib/net.lua /usr/lib/net.lua
  169. return net