Advertisement
horsemeat

ComputerCraft Router

Nov 5th, 2016
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.30 KB | None | 0 0
  1. --Computer Craft Router Application
  2. --By snipy67/Horsemeat
  3. --V1.0
  4. BROADCAST_PORT = 2
  5.  
  6. --Layer 1
  7. lowLevelListeners = {}
  8. routerComputerId = 0
  9.  
  10. function detectModem()
  11.     return peripheral.find("modem")
  12. end
  13. function lowLevelMessageSplit(message)
  14.     local tab = {}
  15.     local current = ""
  16.     for i = 1, #message, 1 do
  17.         if message:sub(i,i) == ':' then
  18.             table.insert(tab,current)
  19.             current = ""
  20.         else
  21.             current = current .. message:sub(i,i)
  22.         end
  23.     end
  24.     if #current > 0 then
  25.         table.insert(tab,current)
  26.     end
  27.     return tab
  28. end
  29.  
  30. function lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  31.     for k, v in pairs(lowLevelListeners) do
  32.         if v.message == tab[1] then
  33.             if verbose then
  34.                 print("function " .. v.message .. "found")
  35.             end
  36.             if v.func ~= nil then
  37.                 local t = {}
  38.                 t.message = tab[1]
  39.                 t.senderId = tab[2]
  40.                 t.reciverId = tab[3]
  41.                 t.data = tab[4]
  42.                 v.func(t)
  43.                 if t.data ~= nil then
  44.                     local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2] .. ":".. t.data;
  45.                     modem.transmit(port,port,responseText)
  46.                 else
  47.                     local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2]
  48.                     modem.transmit(port,port,responseText)
  49.                 end
  50.             else
  51.                 local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2]
  52.                 modem.transmit(port,port,responseText)
  53.             end
  54.             return true
  55.         else
  56.             if verbose then
  57.                 print("v.message:" .. v.message .. " != tab[1]:"..tab[1])
  58.             end
  59.         end
  60.     end
  61.     return false
  62. end
  63.  
  64. function lowLevelListener(modem,port,verbose)
  65.     while true do
  66.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()--listens for a actions
  67.         if event == "modem_message" then--gets the message
  68.             if senderChannel == port then
  69.                 if verbose then
  70.                     print("message recived: " .. message)
  71.                 end
  72.                 local tab = lowLevelMessageSplit(message)
  73.                 if #tab > 2 then
  74.                     if verbose then
  75.                         print("There is more then 2 arguments in the message")
  76.                     end
  77.                     if tonumber(tab[3]) == os.getComputerID() then
  78.                         if verbose then
  79.                             print("id matches")
  80.                         end
  81.                         lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  82.                     elseif tonumber(tab[3]) == -1 then
  83.                         if verbose then
  84.                             print("broadcast")
  85.                         end
  86.                         lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  87.                     end
  88.                 elseif #tab == 2 then
  89.                     lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  90.                 end
  91.             end
  92.         end
  93.     end
  94. end
  95.  
  96. function lowLevelRequest(modem,request,port,maxTimeOut,timeBetweenResend,numberOfResendsBeforeTimeOut,id,data,verbose)
  97.     local str = ""
  98.     if id ~= nil and id ~= -1 then
  99.         str = request .. ":" .. os.getComputerID() .. ":" .. id -- adds the computer id and the id of the reciver
  100.     else
  101.         str = request .. ":" .. os.getComputerID() .. ":" .. -1-- adds the computer id to the requests
  102.     end
  103.    
  104.     if data ~= nil then
  105.         str = str .. ":" .. data
  106.     end
  107.    
  108.     modem.transmit(port,port,str);--transmits the request
  109.     local responseText = request .. "~response"--creates text on how a response will look like
  110.     local count = 0--count is to keep track of how many times the request timed out
  111.     local timer = -1
  112.     if timeBetweenResend > 0 and numberOfResendsBeforeTimeOut > 0 then
  113.         timer = os.startTimer(timeBetweenResend) -- to keep track of the number of seconds before a time out
  114.     end
  115.     local atLeastOne = false--this determines if atleast one computer recived the request
  116.     local timeOutTimer
  117.     if maxTimeOut > 0 then
  118.         timeOutTimer = os.startTimer(maxTimeOut)--this timer is the number of seconds it should wait for return requests
  119.     end
  120.     local all = {} -- this is all the data that will be returned
  121.     all.package = {}--this is where the data from each request is stored
  122.     while true do
  123.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()--listens for a actions
  124.         if event == "timer" then--check if the timer is up
  125.             local timerId = modemSide; --modemSide is the timerid when timer event is called (prevents confusion)
  126.             if timerId == timer then--checks if the timer is the timer that handels resends
  127.                 if atLeastOne == false then--checks if there are no records recovered
  128.                     if count ~= numberOfResendsBeforeTimeOut then--check to make sure the count is not at the timeout stage
  129.                         modem.transmit(port,port,str);--transmits the request again
  130.                         count = count + 1 -- adds one to the #of time outs
  131.                         timer = os.startTimer(timeBetweenResend)--resets the timer
  132.                         if verbose then
  133.                             print("Message Transmission failed resending...")
  134.                         end
  135.                     else
  136.                         if verbose then
  137.                             print("Message Transmission failed")
  138.                         end
  139.                         all.sucess = false
  140.                         return all
  141.                     end
  142.                 end
  143.             elseif timerId == timeOutTimer then--this is the maximum amount of time it was going to wait and not it's going to return the data
  144.                 if atLeastone == false then
  145.                     all.sucess = false
  146.                 else
  147.                     all.sucess = true
  148.                 end
  149.                 return all
  150.             end
  151.         elseif event == "modem_message" then--gets the message
  152.             if senderChannel == port then
  153.                 local tab = lowLevelMessageSplit(message)
  154.                 if verbose then
  155.                     print("Modem message: " .. message)
  156.                 end
  157.                 if tab[1] == responseText then
  158.                     if tonumber(tab[3]) == os.getComputerID() then
  159.                         local p = {}
  160.                         p.sucess = true
  161.                         p.tab = tab
  162.                         atLeastOne = true
  163.                         table.insert(all.package,p)
  164.                         if verbose then
  165.                             print("This computer: " .. tab[3] .. ". Request response recived from " .. tab[2])
  166.                         end
  167.                         if timeOutTimer == -1 then
  168.                             all.sucess = true
  169.                             return all;
  170.                         end
  171.                     end
  172.                 end
  173.             end
  174.         end
  175.     end
  176. end
  177.  
  178. MAX_TIME_OUT = 0.8
  179. TIME_BETWEEN_RESENDS = 0.2
  180. NUMBER_OF_RESENDS = 4
  181. VERBOSE = false
  182.  
  183. --easy to use methods
  184. --> the low level lowLevelListener returns true if atleast 1 tramission has been valid and in this case only 1 transmision
  185. function basicListener(modem)
  186.     return lowLevelListener(modem,BROADCAST_PORT,VERBOSE)--this will never finish, it will listen forever
  187. end
  188.  
  189. -->Low level request return
  190. --.sucess
  191. --.package[instance].sucess = true
  192. --.package[instance].tab = tab
  193. function basicBroadcast(modem,request)
  194.    
  195.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,nil,nil,VERBOSE)--A broadcast request which will conenct to everyone
  196. end
  197.  
  198. function basicRequest(modem,request,computer)
  199.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,computer,nil,VERBOSE)-- a message for a certian computer
  200. end
  201.  
  202. function basicBroadcastWithData(modem,request,data)
  203.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,nil,data,VERBOSE)-- this a a broadcast with data
  204. end
  205.  
  206. function basicRequestWithData(modem,request,computer,data)
  207.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,computer,data,VERBOSE) -- this is a message for a certian computer with data
  208. end
  209.  
  210. function addActionListener(message,func)
  211.     --function parameters required (data)
  212.     --.message -- the message that was transmitted
  213.     --.senderId -- the sender of the message
  214.     --.reciverId -- the reciver of the message
  215.     --.data -- the data that might have been passed along
  216.     local tab = {}
  217.     tab.message = message
  218.     tab.func = func
  219.     table.insert(lowLevelListeners,tab)
  220.     return #lowLevelListeners
  221. end
  222.  
  223. function removeActionListener(index)
  224.     table.remove(lowLevelListeners,index)
  225. end
  226. --End Of Layer 1
  227.  
  228. --Routeing layer
  229. portsTaken = {}
  230. computerId = {}
  231.  
  232. function openBroadcastNode(modem)
  233.     portsTaken[BROADCAST_PORT] = true
  234.     modem.open(BROADCAST_PORT)
  235. end
  236.  
  237. function portInit(modem)
  238.     for i = 1, 128, 1 do
  239.         portsTaken[i] = false
  240.         if modem.isOpen(i) then
  241.             modem.close(i)
  242.         end
  243.     end
  244. end
  245.  
  246. function findEmptyPort(modem)
  247.     for i = 1,128, 1 do
  248.         if portsTaken[i] == false then
  249.             return i
  250.         end
  251.     end
  252.     return -1
  253. end
  254.  
  255. function routerServer(modem)
  256.     portInit(modem)
  257.     openBroadcastNode(modem)
  258.     local requestRoute = function(data)
  259.         local port = findEmptyPort(modem)
  260.         computerId[port] = data.senderId
  261.         portsTaken[port] = true
  262.         data.data = tostring(port)
  263.         print("Port Found: " .. port)
  264.     end
  265.     addActionListener("addport",requestRoute)
  266.     local deleteRoute = function(data)
  267.         local port = tonumber(data.data)
  268.         if port ~= nil or port ~= -1 then
  269.             if data.senderId == computerId[port] then
  270.                 computerId[data.senderId] = -1
  271.                 portsTaken[port] = false
  272.                 data.data = "true"
  273.                 print("Port Deleted: " .. port)
  274.             else
  275.                 data.data = "false"
  276.             end
  277.         end    
  278.     end
  279.     addActionListener("removeport",deleteRoute)
  280.     addActionListener("ping",nil)
  281.     basicListener(modem)
  282. end
  283.  
  284. function deletePort(modem,port)
  285.     local d = basicBroadcastWithData(modem,"removeport",tostring(port))
  286.     for k, v in pairs(d.package) do
  287.         if #v.tab > 3 then
  288.             local state = v.tab[4]
  289.             if state ~=nil then
  290.                 if state == "true" then
  291.                     return true
  292.                 else
  293.                     return false
  294.                 end
  295.             end
  296.         end
  297.     end
  298.     print("router error")
  299.     return false
  300. end
  301.  
  302. function getRouterPort(modem)
  303.     local d = basicRequest(modem,"addport",routerComputerId)
  304.     for k, v in pairs(d.package) do
  305.         if #v.tab > 3 then
  306.             local p = v.tab[4]
  307.             if p ~= nil and p ~= "" then
  308.                 return tonumber(p)
  309.             end
  310.         end
  311.     end
  312.     print("router error")
  313.     return -1
  314. end
  315.  
  316. function routerInit(modem)
  317.     portInit(modem)
  318.     openBroadcastNode(modem)
  319.     local d = basicBroadcast(modem,"ping")
  320.     if d.sucess then
  321.         if #d.package > 0 then
  322.             local id = -1
  323.             for k, v in pairs(d.package) do
  324.                 if id == -1 or id == tonumber(v.tab[2]) then
  325.                     id = tonumber(v.tab[2])
  326.                     if id ~= -1 and id < 128 then
  327.                         routerComputerId = id
  328.                         return true
  329.                     end
  330.                 else
  331.                     print("Too many routers")
  332.                     return false
  333.                 end
  334.             end
  335.             print("unknown router Error")
  336.             return false
  337.         elseif #d.package == 0 then
  338.             print("No Routers detected")
  339.             return false
  340.         else
  341.             return false
  342.         end
  343.     else
  344.         print("Router not found")
  345.         return false
  346.     end
  347. end
  348. --End of routeing layer
  349. function runServer()
  350.     local modem = detectModem()
  351.     routerServer(modem)
  352. end
  353.  
  354. function runClient()
  355.     local modem = detectModem()
  356.     if routerInit(modem) then
  357.         local port = getRouterPort(modem)
  358.         print("retrived Port: " .. port)
  359.         os.sleep(2)
  360.         deletePort(modem,port)
  361.     else
  362.         print("error to init router")
  363.     end
  364. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement