Advertisement
ladyDia

Networked Terminal

Dec 8th, 2024 (edited)
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.21 KB | None | 0 0
  1. --Variables
  2. local networkDeviceSide = "left" --Change this to where network device is
  3. deviceType = "terminal"
  4. ipAddress =  {-1,-1,-1}
  5. routerID = -1 --The computer ID of the router, allowing for responses to be returned
  6. message = {}
  7. packet = {}
  8. localFunctions = {}
  9. logs = {} --Saves what would normally be printed to the console
  10. commandLog = {} --Saves all the run commands
  11. version = "1.2"
  12.  
  13. waitingForCommand = true
  14.  
  15. --[[
  16.     All data packets have a set structure made of four sections
  17.     First Section - IP Address of target system
  18.     Second Section - IP Address of sending system
  19.     Third Section - Type of packet being sent (what protocol does packet follow)
  20.     Fourth Section - The main data the packet is transporting
  21.  
  22.     For testing, the IP address will be the same as the device ID.
  23.     In the future this will be changed to allow for proper routing and
  24.     security measures.
  25.  
  26.     The protocol the packet follows is a string in all caps
  27.     (CDP,ERP,DRP,UPP,etc) to allow for universal understanding (and style)
  28.  
  29.     An IP address of 0 for the target system means that the packet is for
  30.     the router to work with. Trying to assign a different device this IP will fail
  31.     as the router will intercept all packets with that IP.
  32. --]]
  33.  
  34. local function printToLog(printed)
  35.     --Add a string to the log
  36.     table.insert(logs,printed)
  37. end
  38.  
  39. local function sendPacket (
  40.         targetIP, --table
  41.         protocol, --String
  42.         data --Any
  43. )
  44.     --[[
  45.         This function sends a packet to an IP address in the network.
  46.         Each packet needs to follow the rules of packet construction.
  47.         If the target IP is 0 then the packet will be sent to the default router.
  48.         If the sending IP is -1 then that means the IP hasn't been set yet
  49.         and will need to be to recieve packets from devices other than the router.
  50.     --]]
  51.     --Checking if there is a default router to send packet to, otherwise skip all code
  52.     if routerID == -1 then
  53.         printToLog("Default router not set")
  54.         goto skip
  55.     end
  56.     --Checking if packet components have the right data types, otherwise skip all code
  57.     if not (type(targetIP) == "table") or not (type(protocol) == "string") then
  58.         printToLog("Improperly formatted packet")
  59.         goto skip
  60.     end
  61.     --Packet construction
  62.     local packet = {
  63.         targetIP,
  64.         ipAddress,
  65.         protocol,
  66.         data
  67.     }
  68.     --Sending packet
  69.     printToLog(targetIP[1].."."..targetIP[2].."."..targetIP[3] .. " " .. ipAddress[1].."."..ipAddress[2].."."..ipAddress[3] .. " " .. protocol .. " " .. data)
  70.     rednet.send(routerID,packet)
  71.     ::skip::
  72. end
  73.  
  74.  local function responseRDP ()
  75.     --[[
  76.     Router Discovery Protocol
  77.     Used by a router to discover other routers and build up a internetwork routing table.
  78.     After recieving a routing table, start adding it to router routing table
  79.     Routing table info:
  80.     1 - IP of router
  81.     2 - ID of next hop
  82.     3 - IP of next hop? (for future tracert)
  83.     4 - Number of hops to IP (To find shortest route)
  84.    
  85.     Routers will not have themselves on their own routing tables
  86.     --]]
  87. end
  88.  
  89. local function responseCDP ()
  90.     --[[
  91.     Computer Discovery Protocol
  92.     Used by a router to discover devices on the network then assign them IP addresses
  93.     and set itself as the device's default router. Devices already with an IP and
  94.     default router do not respond to CDP packets to avoid confusion on the side of
  95.     the router.
  96.     --]]
  97.     --If the device already has an IP and assigned Router then skip all code
  98.     if not (ipAddress == -1)  and not (routerID == -1) then goto skip end
  99.     printToLog(routerID)
  100.     --Sets the device's default router to the device ID that sent the packet
  101.     routerID = message[1]
  102.     printToLog(routerID)
  103.     --Send CDP packet to router (IP 0) with the ID of the device
  104.     sendPacket({0,0,0},"CDP",os.getComputerID())
  105.     --An IP packet should be sent in the near future to this device to assign IP
  106.     ::skip::
  107. end
  108.  
  109. local function responseERP ()
  110.     --[[
  111.         Echo Request Protocol is used to see if an IP address is responding.
  112.         Sending an ERP packet will cause the device to send a return packet back to the
  113.         source device.
  114.     --]]
  115.     if packet[4] == "Ping" then
  116.         sendPacket(packet[2],"ERP","pong")
  117.     else
  118.         print("Response from "..packet[2][1].."."..packet[2][2].."."..packet[2][3])
  119.     end
  120. end
  121.  
  122. local function responseDRP ()
  123.     --Device Request Protocol
  124.     if type(packet[4]) == "table" then
  125.         for index = 1, #packet[4], 1 do
  126.             print(packet[4][index][1].." "..packet[4][index][2])
  127.         end
  128.     end
  129. end
  130.  
  131. local function responseUPP ()
  132.     --Unknown Packet Protocol
  133. end
  134.  
  135. local function responseIP ()
  136.     --[[
  137.     Internet Protocol
  138.     Used by router to give a device an IP address. Will only be accepted if the
  139.     router is the default router the device knows. If the default router is
  140.     unassigned then the IP packet is dropped. The data on the packet should
  141.     be a number.
  142.     --]]
  143.     --Checking if routerID is assigned
  144.     printToLog(routerID)
  145.     if routerID == -1 then goto skip end
  146.     --Checking if routerID is the same as the message sender
  147.     if not (routerID == message[1]) then goto skip end
  148.     --Setting the IP of the device to the one sent by the router
  149.     ipAddress = packet[4]
  150.    
  151.     --Sending IP packet with the device type to the router
  152.     sendPacket({0,0,0},"IP",deviceType)
  153.     ::skip::
  154. end
  155.  
  156. local function responseDP ()
  157.     --Data  Packet
  158.     if type(packet[4]) == "string" then
  159.         printToLog("DP packet: "..packet[4])
  160.     elseif type(packet[4]) == "table" then
  161.         local tempString = ""
  162.         for index = 1, #packet[4], 1 do
  163.             tempString = tempString .. packet[4][index]
  164.         end
  165.         printToLog("DP packet: "..tempString)
  166.     end    
  167. end
  168.  
  169. local function responseAP ()
  170.     --Acknowledgement Packet
  171. end
  172.  
  173. local function stripString(inputString, splitChar)
  174.     --[[
  175.         Takes in a string, removes all characters that match the
  176.         splitChar, and outputs a table of strings from where the
  177.         splitChar was.
  178.     --]]
  179.    
  180.     local outputTable = {}
  181.     local tempString = ""
  182.     if not type(inputString) == "string" then  
  183.         print("stripString: input not string")
  184.         goto skip
  185.     end
  186.     for index = 1, #inputString, 1 do
  187.         if string.sub(inputString,index,index) == splitChar then
  188.             table.insert(outputTable,tempString)
  189.             tempString = ""
  190.             goto continue
  191.         end
  192.         tempString = tempString .. string.sub(inputString,index,index)
  193.         ::continue::
  194.     end
  195.     table.insert(outputTable,tempString)
  196.     ::skip::
  197.     return outputTable
  198. end
  199.  
  200. local function commandLine()
  201.     --[[
  202.         The Command Line Interface allows a user to run commands on this
  203.         system. This can include sending pings to other systems, sending
  204.         custom packages to other systems, seeing rednet logs, etc.
  205.         Currently all commands are network based, but others may be made
  206.         later.
  207.     --]]
  208.     local command = read()
  209.     --print(command)
  210.     local commandTable = stripString(command," ")
  211.     command = table.remove(commandTable,1)
  212.     --Setting the command string to all uppercase
  213.     command = string.upper(command)
  214.     --print("command"..command)
  215.    
  216.     if localFunctions["command"..command] then
  217.         --If protocol exists
  218.         table.insert(commandLog,{command,commandTable})
  219.         localFunctions["command"..command](commandTable)
  220.         --table.insert(dataQueue,packet)
  221.     else  
  222.         print("Unrecognized command")
  223.     end
  224.     waitingForCommand = false
  225. end
  226.  
  227. local function commandPRINTLOGS (options)
  228.     --[[
  229.         Prints out the log to the console
  230.     --]]
  231.     for index = 1, #logs, 1 do
  232.         print(logs[index])
  233.     end
  234. end
  235.  
  236. local function commandPING (options)
  237.     --[[
  238.         Uses ERP/ICMP to send a ping message to target IP.
  239.     --]]
  240.     --print(#options)
  241.     tempIP = stripString(options[1],".")
  242.     if not (#tempIP  == 3) then goto skip end
  243.     options[1] = {tonumber(tempIP[1]),tonumber(tempIP[2]),tonumber(tempIP[3])}
  244.     if options then
  245.         --For right now, first option is just IP address for Ping
  246.         sendPacket(options[1],"ERP","Ping")
  247.     else
  248.         print([[
  249.             Weh
  250.         ]])
  251.     end
  252.     ::skip::
  253. end
  254.  
  255. local function commandIPCONFIG (options)
  256.     --[[
  257.         Prints all network related information
  258.     --]]
  259.     print("Device type: "..deviceType.."\n".."IP address: "..ipAddress[1].."."..ipAddress[2].."."..ipAddress[3].."\n".."Router ID: "..routerID)
  260. end
  261.  
  262. local function commandHELP (options)
  263.     print("Ping <IP address>, PrintLogs, IPconfig, Packet <TargetIP> <Protocol> <Data>")
  264. end
  265.  
  266. local function commandPACKET (options)
  267.     --Makes a custom packet to send to an IP
  268.     local tempIP = stripString(options[1],".")
  269.     local tempString = ""
  270.     if not (#options >= 3) then goto skip end
  271.     if not (#tempIP  == 3) then goto skip end
  272.     options[1] = {tonumber(tempIP[1]),tonumber(tempIP[2]),tonumber(tempIP[3])}
  273.     if not ((type(options[1]) == "table") and (type(options[2]) == "string")) then goto skip end
  274.     if not (options[1][1] < 0) then
  275.         if #options > 3 then
  276.             for index = 3, #options, 1 do
  277.                 tempString = tempString.." "..options[index]
  278.             end
  279.         else
  280.             tempString = options[3]
  281.         end
  282.         sendPacket(options[1],options[2],tempString)
  283.     else
  284.         rednet.broadcast({options[1],ipAddress,options[2],options[3]})
  285.     end
  286.     ::skip::
  287. end
  288.  
  289. local function responseNetwork()
  290.     while waitingForCommand do
  291.         --[[
  292.             Listens for rednet messages and runs responses
  293.         --]]
  294.         --printToLog("Ready to recieve message")
  295.         --Wait until rednet message recieved
  296.         message = {rednet.receive(1)}
  297.         --Pulling out the packet inside of the message
  298.         packet = (message[2])
  299.         if not packet then goto continue end
  300.         --Checking if packet is properly formatted, if it is not then drop packet and continue loop
  301.         if #packet < 4 then goto continue end
  302.         if packet[3] == "RDP" then goto continue end
  303.         if not (packet[3] == "CDP") then
  304.             printToLog("Packet Type: " .. packet[3])
  305.         end
  306.         if localFunctions["response"..packet[3]] then
  307.             --If protocol exists
  308.             if not (packet[3] == "CDP") then
  309.                 printToLog("Running response "..packet[3])
  310.             end
  311.             localFunctions["response"..packet[3]]()
  312.             --table.insert(dataQueue,packet)
  313.         else  
  314.             --Send UPP packet to source device if protocol is unknown
  315.             printToLog("Unknown")
  316.             sendPacket(packet[1],"UPP","Unknown Packet Type: "..packet[3])
  317.         end
  318.         --]]
  319.         ::continue::
  320.         --End of cycle upkeep
  321.         --Resetting last received message and packet back to their default states
  322.         message = {}
  323.         packet = {}
  324.     end
  325.     waitingForCommand = true
  326. end
  327.  
  328. function mainLoop ()
  329.     --This function runs continuously and allows the device to respond to requests and packets
  330.     while true do
  331.         parallel.waitForAll(responseNetwork,commandLine)
  332.     end
  333. end
  334.  
  335. --Finding all of the local functions and storing them
  336. index = 1
  337. while true do
  338.     key, data = debug.getlocal(1,index)
  339.     if not key then break end
  340.     --(key)
  341.     if type(data) == "function" then
  342.         if debug.getinfo(data, "S").what == "Lua" then
  343.             localFunctions[key] = data
  344.         end
  345.     end
  346.     index = index + 1
  347. end
  348.  
  349. --Turning on the network capabilities of the device
  350. peripheralNames = peripheral.getNames()
  351. for i = 1, #peripheralNames, 1 do
  352.     if peripheral.hasType(peripheralNames[i],"modem") then
  353.         rednet.open(peripheralNames[i])
  354.     end
  355. end
  356. --Calling the mainLoop to start program
  357. print("Starting Command Line Interface")
  358. print("Terminal version: "..version)
  359. print("To find out more about commands type: 'help'")
  360. mainLoop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement