Skip to content

Instantly share code, notes, and snippets.

@AmariNoa
Created July 13, 2022 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AmariNoa/236d22fedc17c044743c4aa0f91b5b66 to your computer and use it in GitHub Desktop.
Save AmariNoa/236d22fedc17c044743c4aa0f91b5b66 to your computer and use it in GitHub Desktop.
File server and client for ComputerCraft
-- FileClient
-- Ver. 0.1
-- Include external lib
dofile("/lib/amari/string/StringUtil.lua")
local REDNET_SIDE = "left"
local REDNET_PROTOCOL_MASTER = "MasterServer"
local REDNET_PROTOCOL_FILE = "FileServer"
local function ParseCommand(str, pattern)
local start, tail = string.find(str, pattern)
local cmd = (start ~= nil) and string.sub(str, 1, start - 1) or str
local data = (start ~= nil) and string.sub(str, tail + 1, string.len(str)) or nil
return cmd, data
end
local computerId = os.getComputerID()
print("ComputerId = "..computerId)
rednet.open(REDNET_SIDE)
local isOpen = rednet.isOpen(REDNET_SIDE)
if not isOpen then
print("Rednet open failed.")
return
end
local masterServerId = 0
rednet.broadcast("GetServerId", REDNET_PROTOCOL_MASTER)
while true do
local sender, receive, protocol = rednet.receive(REDNET_PROTOCOL_MASTER)
if sender == nil then
-- Time out
print("MasterServer not found.")
return
end
local starts = "response:"..string.lower("GetServerId")
print("Receive: "..receive)
print("Starts: "..starts)
if string.startsWith(receive, starts) then
-- Master response
masterServerId = tonumber(string.split(receive, ":")[4])
break
end
end
local fileServerId = 0
rednet.send(masterServerId, "GetServerId", REDNET_PROTOCOL_FILE)
while true do
local sender, receive, protocol = rednet.receive(REDNET_PROTOCOL_MASTER)
if sender == nil then
-- Time out
print("FileServer not found.")
return
end
if string.startsWith(receive, "response:"..string.lower("GetServerId")) then
-- Master response
fileServerId = tonumber(string.split(receive, ":")[4])
break
end
end
local dir = ""
while true do
dir = read()
if string.lower(dir) == "download" then
break
elseif string.lower(dir) == "upload" then
break
end
print("Invalid argument. (Download or Upload)")
end
term.write("Enter file path >> ")
local filePath = read()
if string.lower(dir) == "download" then
local cmd = "Download:"..filePath
rednet.send(fileServerId, cmd, REDNET_PROTOCOL_FILE)
while true do
local sender, receive = rednet.receive(REDNET_PROTOCOL_FILE, 5)
if sender == nil then
print("Failed to connet to server.")
return
end
if receive.startsWith(receive, "response:"..string.lower("Download")) then
-- "response", "Download:result:data"
local rcvCmd, receive = ParseCommand(receive, ":")
-- "Download", "result:data"
rcvCmd, receive = ParseCommand(receive, ":")
-- "result", "data"
if rcvCmd == false then
print("Server error: "..receive)
return
end
print("** File received **")
print("FilePath: "..filePath)
local fileHandle = fs.open(filePath, "w")
if fileHandle then
fileHandle.write(receive)
fileHandle.close()
else
print("File cannot open.")
end
break
end
end
elseif string.lower(dir) == "upload" then
local fileHandle = fs.open(filePath, "r")
if fileHandle then
local cmd = "Upload:"..filePath..":"..fileHandle.readAll()
rednet.send(fileServerId, cmd, REDNET_PROTOCOL_FILE)
else
print("File cannot open.")
end
rednet.close(REDNET_SIDE)
else
print("Invalid command")
return
end
-- FileServer
-- Ver. 0.1
-- Include external lib
dofile("/lib/amari/string/StringUtil.lua")
local REDNET_SIDE = "back"
local REDNET_PROTOCOL_MASTER = "MasterServer"
local REDNET_PROTOCOL = "FileServer"
local function ParseCommand(str, pattern)
local start, tail = string.find(str, pattern)
local cmd = (start ~= nil) and string.sub(str, 1, start - 1) or str
local data = (start ~= nil) and string.sub(str, tail + 1, string.len(str)) or nil
return cmd, data
end
local stopServer = false
local function readConsoleThread()
local input = ""
while (not stopServer) do
term.write(">> ")
input = read()
-- TODO Add console command here
if string.lower(input) == "stop" then
stopServer = true
print("Stopping server...")
else
print("Unknown command: "..input)
end
end
end
local function serverThread()
local isOpen = true
local sender, receive, protocol
while isOpen do
sender, receive, protocol = rednet.receive(3)
if (sender ~= nil) and (receive ~= nil) then
-- Message received
-- local cmdSplit = string.split(receive, ":")
local cmd, tempReceive = ParseCommand(receive, ":")
cmd = string.lower(cmd)
print("Cmd: "..cmd)
-- print("Data: "..tempReceive)
-- Execute command
local result = false
local data = "Unknown command"
-- Add command
if cmd == string.lower("Upload") then
-- TODO Upload :: Add version
-- Upload:filePath:fileData
local filePath, tempReceive = ParseCommand(tempReceive, ":")
print("** Upload command received **")
print("FilePath: "..filePath)
local fileHandle = fs.open(filePath, "w")
if fileHandle then
fileHandle.write(tempReceive)
fileHandle.close()
result = true
data = "Success"
else
result = false
data = "Failed to open file"
end
elseif cmd == string.lower("Download") then
-- TODO Download :: Add version
-- Download:filePath
local filePath = tempReceive
print("** Download command received **")
print("FilePath: "..filePath)
local fileHandle = fs.open(filePath, "r")
if fileHandle then
result = true
data = fileHandle.readAll()
fileHandle.close()
else
result = false
data = "Failed to open file"
end
end
-- Message format => response:cmdName:result:data
local sendMsg = "response:"..cmd..":"..tostring(result)..":"..data
rednet.send(sender, sendMsg, REDNET_PROTOCOL)
end
if stopServer == true then
break
end
isOpen = rednet.isOpen(REDNET_SIDE)
if not isOpen then
break
end
end
end
-- Script main
local computerId = os.getComputerID()
print("ComputerId = "..computerId)
rednet.open(REDNET_SIDE)
local isOpen = rednet.isOpen(REDNET_SIDE)
if not isOpen then
print("Rednet open failed.")
return
end
print("FileServer started.")
print("Sending server id...")
rednet.broadcast("SetServerId:"..computerId, REDNET_PROTOCOL)
-- TODO delete
while true do
local sender, receive, protocol = rednet.receive(REDNET_PROTOCOL_MASTER, 5)
if receive == nil then
print("Connection time out.")
break
end
print("** Receive **")
print("Sender: "..sender)
print("Message: "..receive)
print("Protocol: "..protocol)
if string.startsWith(receive, "response") then
break
end
end
parallel.waitForAll(readConsoleThread, serverThread)
rednet.close(REDNET_SIZE)
print("FileServer stopped.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment