This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Jahmaican's profile picture

rFTP - Rednet File Transfer Protocol

Started by Jahmaican, 02 September 2012 - 01:51 AM
Jahmaican #1
Posted 02 September 2012 - 03:51 AM


Hello again! I'm totally aware that once again I made a program that already exists in many forms, but I felt like making it my way, completely by myself. This is a complete (and user-friendly!) solution for sending files between computers using wireless modems.

Obviously the program must be present on both computers to work. It consists of two parts - sending and receiving. These are pretty self-explanatory, just notice that receiving mode on destination device has to be activated BEFORE you start sending a file.

Ad rem. As usual, first you need my little api that goes to api/devices:

function find(name,prior)
  local sides = {
  "top";
  "front";
  "left";
  "right";
  "back";
  "bottom" }

  if prior==nil then
	p=1
  else
	p=prior
  end

  for n=1,6 do
	if peripheral.getType(sides[n])==name then
	  if p==1 then
		return sides[n]
	  else
		p=p-1
	  end
	end
  end
  return "none"
end

And the program. I believe you don't have to modify ANYTHING in the code - yeah, it's that good. Sorry I gave up on comments this time, but it's almost 5 AM :)/>/>

os.loadAPI("api/devices")

-- GLOBAL VARIABLES --
local ver="1.1"
local id=os.getComputerID()
local wifi
local dest
local sfile
local sender
local dcat
local dfile
local dpath
-- /GLOBAL VARIABLES --

function Main()
  Clear()
  write("Initializing")
  textutils.slowWrite(".....nn")
 
  wifi=devices.find("modem")
  if wifi~="none" then
    print("Wireless device found!")
    write("Opening connection")
    textutils.slowWrite(".....nn")
    rednet.open(wifi)
    print("Done!")
    sleep(1)
    Menu()
  else
    print("Wireless device not found!nConnect a device and try again!")
    return 0
  end
end

function Menu()
  Clear()
  print("Your ID: "..id.."n")
  print("t1. Send file")
  print("t2. Receive file")
  print("t0. Exit")

  local event,p1=os.pullEvent("key")
    if p1==2 then
	  SendMenu()
    elseif p1==3 then
	  DownMenu()
    elseif p1==11 then
   	 term.clear()
        term.setCursorPos(1,1)
        print("Thanks for using rFTP!")
        rednet.close(wifi)
        return 0
    else
	  Menu()
    end
end  

function SendMenu()
  Clear()
  print("Enter destination ID (not label):")
  dest=tonumber(read())
  print("File to send: ")
  sfile=read()
  write("nChecking file")
  textutils.slowWrite(".....")
  if fs.exists(sfile)==true then
    write(" File OK!n")
  else
    print("nFile not found! Any key to continue...")
    os.pullEvent("key")
    Menu()
  end
  print("Estabilishing connection")
  rednet.send(dest,"@rftpstart")
  rednet.send(dest,sfile)
  print("Waiting for device #"..dest.." to respond...n[Press SPACE to cancel]")
  Waiting()
end

function Waiting()
  while true do
    local event,p1,p2=os.pullEvent()

    if (event=="rednet_message") and (p2=="@rftpagree") then
        print("File accepted by #"..dest.."n")
        sleep(1)
        Transfer()
        break
    elseif (event=="rednet_message") and (p2=="@rftpdeny") then
        print("#"..dest.." denied connection! Any key to continue...")
        os.pullEvent("key")
        Menu()
        break
    elseif (event=="key") and (p1==57) then
        Menu()
        break
    end
  end
end

function Transfer()
    local plik=fs.open(sfile,"r")
    local tresc=plik.readAll()
    rednet.send(dest,tresc)
    sleep(0.3)
    rednet.send(dest,"@rftpend")
    plik.close()
    print("Transfer complete! Any key to continue...")
    os.pullEvent("key")
    Menu()
end
    
function DownMenu()
    Clear()
    print("Your ID: "..id.."n")
    print("Waiting for an oncoming file...n[Press SPACE to cancel]")
    local event,p1,p2
    repeat
    event,p1,p2=os.pullEvent()
    until ((event=="rednet_message") and (p2=="@rftpstart")) or ((event=="key") and (p1==57))
    if (event=="rednet_message") and (p2=="@rftpstart") then
        sender=p1
        event,p1,p2=os.pullEvent("rednet_message")
        print("Device "..p1.." want to send you a file: "..p2..". Accept? [y/N]")
        local event,pp1=os.pullEvent("key")
        if (pp1==20) or (pp1==21) then
            Download()
        else
            rednet.send(p1,"@rftpdeny")
            Menu()
        end
    elseif (event=="key") and (p1==57) then
        Menu()
    end
end

function Download()
    Clear()
    
    print("Select the folder: [default: dl]")
    dcat=read()
    if dcat=="" then
        dcat="dl"
    end
    fs.makeDir(dcat)
    
    print("Select filename:")
    dfile=read()
    
    dpath=fs.combine(dcat,dfile)
    
    if fs.exists(dpath)==false then
        SaveFile()
    else
        print("File already exists! Try again? [y/N]")
        local event,p1=os.pullEvent("key")
        if (p1==20) or (p1==21) then
            Download()
        else
            rednet.send(p1,"@rftpdeny")
            Menu()
        end
    end
end

function SaveFile()
    local plik=fs.open(dpath,"w")
    rednet.send(p1,"@rftpagree")
    local event,p1,p2
    repeat
        event,p1,p2=os.pullEvent("rednet_message")
    until p1==sender
    if p2~="@rftpend" then
        plik.write(p2)
    end
    os.startTimer(10)
    while true do
        local event,p1,p2=os.pullEvent()
        if event=="rednet_message" and p1==sender and p2=="@rftpend" then
            write("nTransfer completed! ")
            break
        elseif event=="timer" then
            write("nTimed out! Check the file. ")
            break
        end
    end
    plik.close()
    print("Any key to continue...")
    os.pullEvent("key")
    Menu()
end

function Clear()
  term.clear()
  term.setCursorPos(1,1)
  print("rFTP v"..ver.."nby Jahmaicann~~~~~~~~~~~~n")
end

Main()

Just remember this is an early release and although I did my best (like making sure that other wireless devices won't interfere the transfer process), some minor bugs could still occur. Please let me know if you find anything like that.

Edit: Updated to 1.1
Edited on 24 September 2012 - 10:20 AM
UMayBleed #2
Posted 28 September 2012 - 02:47 PM
Nice, i made a FTP client and server application as well as a domain server, so the server could have something like http://bleedplace.ca but the server must be hosted, and have a domain, since it looks up the domain, then the domain server returns the computer id to the client and it uses it for connecting. It took me forever.
Brodur #3
Posted 15 August 2014 - 03:42 PM
Is there a way to use this with wired modems? As well, can we load the Api from the main directory for ease of use on a multiplayer server, rom/apis/devices is off limits on most.
Lyqyd #4
Posted 15 August 2014 - 05:37 PM
You'd just need to name the API "devices" and load it up with os.loadAPI("/devices") or whatever path you put it in. There's no need to have it in rom. As far as I can tell, there's nothing in it that would prevent it from working over a wired network.
Brodur #5
Posted 15 August 2014 - 06:18 PM
Thanks for that, it solved my problems.