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

Basic Rednet relay/forwarding/remote file server/gps host program

Started by ChunLing, 22 October 2012 - 08:47 PM
ChunLing #1
Posted 22 October 2012 - 10:47 PM
Hmm…no gps tag. Ah well. Anyway, I like remote controlled turtles. But there is a problem…if you put the control terminal where you can easily get at it, then you have limited rednet range. So, I set up a program that lets the gps node running it do a few other things than respond to pings. Here is a current version.
Spoiler
local tArgs = { ... }
local function opnmdm()
	for i,v in pairs(rs.getSides()) do	
		if peripheral.getType(v) == "modem" then
			if not rednet.isOpen(v) then rednet.open(v) end
		return true end
	end
return false end
local dmnlst,rlylst,hstID,sndr,mssg,dstnc,cmnd,prm1,xclst = {},{},os.computerID(),tonumber(tArgs[5])
local hstfnc = {
PING = function() rednet.send(sndr,textutils.serialize({xPos,yPos,zPos})) end,
access = function(acsdx) if dmnlst[sndr] then
	local tp = {acsdx:match("(%S+)%s*(%S+)%s*(.*)")}
	tp[4] = tonumber(tp[2])
	if tp[1] == "add" then tp[5] = true elseif tp[1] ~= "ban" then acsdx = nil end
	if tp[3] == "dmnlst" then tp[6] = dmnlst elseif tp[3] == "xclst" then
		if not xclst then xclst = {} end tp[6] = xclst
	else acsdx = nil end
	if tp[4] and acsdx then tp[6][tp[4]] = tp[5]
	tp[7] = fs.open(tp[3],"w") tp[7].writeLine(textutils.serialize(tp[6])) tp[7].close()
	else rednet.send(sndr,"Usage 'access add/ban ID dmnlst/xclst'") end
end end,
bcst = function(bmssg) if dmnlst[sndr] then
	if bmssg then rednet.send(nil,bmssg) end
end end,
del = function(flnm) if dmnlst[sndr] then
	flnm = flnm:match("%S+")
	if fs.exists(flnm) and not flnm == "/" then fs.delete(flnm) rednet.send(sndr,flnm.." deleted")
	else rednet.send(sndr,"File not found") end
end end,
dir = function(flnm)
	flnm = flnm:match("%S+")
	local tdir = fs.list(flnm)
	for i = 1,#tdir do rednet.send(sndr,tdir[i]) end
end,
drp = function()
	local rID = rlylst[sndr]
	rlylst[sndr],rlylst[rID] = nil
	local hndl = fs.open("rlylst","w")
	hndl.write(textutils.serialize(rlylst)) hndl.close()
	rednet.send(sndr,"Relay to ID"..rID.." dropped")
end,
fwd = function(frwd)
	local rID,fmssg = frwd:match("(%d+)%s*(.*)$")
	rID = tonumber(rID)
	if rID and fmssg then rednet.send(rID,fmssg) end
end,
hsts = function() if dmnlst[sndr] then
	local ndx,hstlst = 0,{}
	rednet.broadcast("PING")
	repeat ndx = ndx+1
		hstlst[ndx] = {rednet.receive(0.5)}
	until not hstlst[ndx][1]
	rednet.send(sndr,textutils.serialize(hstlst))
end end,
reboot = function() if dmnlst[sndr] then shell.run("reboot") end end,
rly = function(rlyID)
	local rID = tonumber(rlyID)
	rlylst[sndr],rlylst[rID] = rID,sndr
	local hndl = fs.open("rlylst","w")
	hndl.write(textutils.serialize(rlylst)) hndl.close()
	rednet.send(sndr,"Relaying to ID"..rlylst[sndr])
end,
rcvfl = function(flnm) if dmnlst[sndr] then
	local tp = {flnm:match("(%S+)%s*(.*)")}
	 tp[3] = fs.open(tp[1],"w") if tp[3] then tp[3].write(tp[2]) tp[3].close()
	rednet.send(sndr,tp[1].." Updated")
	else rednet.send(sndr,"File is Read Only") end
end end,
srvfl = function(flnm)
	flnm = flnm:match("%S+")
	local hndl = fs.open(flnm,"r")
	if hndl then rednet.send(sndr,hndl.readAll()) hndl.close()
	else rednet.send(sndr,"File not found") end
end,
}

if opnmdm() then
	xPos,yPos,zPos = gps.locate(2,true )
	if tArgs[1] == "host" then
		if not xPos then xPos,yPos,zPos = tArgs[2],tArgs[3],tArgs[4]
			local itr8 = 0
			while not (xPos and yPos and zPos) do
				write("Enter x coordinate: ") xPos = tonumber(read())
				write("Enter y coordinate: ") yPos = tonumber(read())
				write("Enter z coordinate: ") zPos = tonumber(read())
				itr8 = itr8+1
				if itr8 > 3 then print("Invalid input") return false end
			end
		end
		print("GPS/Relay Node position "..xPos..","..yPos..","..zPos)
		local hndl = fs.open("startup","w")
		hndl.writeLine("shell.run("rnhst","host","..xPos..","..yPos..","..zPos..")")
		hndl.close()
		if sndr then hndl,xclst,dmnlst = fs.open("xclst","w"),{[sndr] = true},{[sndr] = true}
			hndl.writeLine(textutils.serialize(xclst)) hndl.close()
		elseif fs.exists("xclst") then hndl = fs.open("xclst","r")
			xclst = textutils.unserialize(hndl.readAll()) hndl.close()
		end
		if fs.exists("rlylst") then hndl = fs.open("rlylst","r")
			rlylst = textutils.unserialize(hndl.readAll()) hndl.close()
		end
		if fs.exists("dmnlst") then hndl = fs.open("dmnlst","r")
			dmnlst = textutils.unserialize(hndl.readAll()) hndl.close()
		else hndl = fs.open("dmnlst","w") hndl.writeLine(textutils.serialize(dmnlst)) hndl.close()end
		repeat sndr,mssg,dstnc = rednet.receive()
			if rlylst[hstID] then rednet.send(rlylst[hstID],sndr..":"..mssg) end
			if xclst and not xclst[sndr] then cmnd = "none" else
				cmnd,prm1 = mssg:match("^(%S+)%s*(.*)")
				if prm1 == "" then prm1 = "/" end
				if hstfnc[cmnd] then hstfnc[cmnd](prm1) end
			end
			if rlylst[sndr] and not hstfnc[cmnd] then rednet.send(rlylst[sndr],mssg) end
		until not hstID
	return true end
else print("could not open modem") return false
end
Basically, this supports some additional functions that can be activated by sending it a rednet message. We have good old "PING", which sends back a message giving the (nominal) position of the host, so that gps.locate calls can use it to find their position. We add "bcst [message to broadcast]" which should rebroadcast "[message to broadcast]", or whatever other message you put in there. Also "rly ID" where ID is the number ID of a computer/turtle you want to relay messges to/from, and "drp" which drops the current relay (right now, you can only have one relay from a given ID through a given node, that might change but for now its enough for my needs). We also have the "fwd ID [message to forward]" command, which takes the "[message to forward]" and forwards it to ID. This should work with multiple forwards, so you can write something like "fwd 10 fwd 11 fwd 12 fwd 13 Hi there!". But I haven't fully tested it. For functionality, we have the "hsts" command, which orders the node to issue a ping and collect all the responses it gets in a table, which it then sends back to the command issuer. This could be useful in some ways. The "reboot" function, you guessed it, reboots the node. This can be useful, but it may be removed in later versions. "rcvfl [filename]" opens the node to receive a message and and save it under "[filename]", the message body is requested in a followup message (I should probably change this so that the filebody is included after "[filename]" in the command message, we'll see). "srvfl [filename]" does the exact opposite, it sends the file "[filename]" to the requester.

The program takes the same command line parameters as the existing gps program, with the addition of a single extra parameter (explained later). However, it differs in that it prefers consistency with an existing gps system and will override the provided parameters if it gets a valid location calculation based on pinging the area. Once it has established its posltion, it saves a startup file so that if it reboots it will have the old position to start from. It also saves the table of relays, and an optional table (which is initially filled with the ID in the aforementioned extra parameter) that restricts access to the functions (including "PING") to an explicit list of authorized IDs. Eventually, I may add a second list that restricts access to the bcst, hsts, rcvfl, and reboot commands (since these can be used to give away the node's position to untrusted rednet ID's or totally take over the relay node).

Feedback is much appreciated, particularly finding bugs. I am already planning to eventually add the "administrator" authorization level and to make it possible to have more than one relay per ID through a given node (there is already a special case when the relay ID is set to the ID of the node, it relays all received messages to the requesting ID).

Okay, fixed now. And now it should be a bit better.

Pastebin link for rnhst. Bugfix. Newest update. Added new commands: access, del, dir, and endhst. The rcvfl and srvfl commands have been renamed to flrcv and flsrv to avoid conflict with the clfn turtle versions (the conflict was originally planned, but deemed pointless on further consideration).
Edited on 22 January 2013 - 06:14 AM
ChunLing #2
Posted 22 October 2012 - 11:29 PM
Blarg, it's not working right now. Why me? It was working fine before, and then I went and broke it!
ChunLing #3
Posted 24 October 2012 - 02:34 AM
Pastebin link added. Development will continue as bugs/deficiencies are discovered.
ChunLing #4
Posted 24 October 2012 - 03:41 AM
Bugfix.

I have a question. Right now there is a listening post mode (if an allowed ID sets up a relay to the rnhst node's own ID, all messages received by the node are forwarded to that ID, regardless of other relays in effect). However, I currently have the logic set so that a relay can be established to a disallowed ID. I'm thinking that this is redundant and a bit dangerous, as you can already send to disallowed IDs with the fwd (or bcst) command, and you can monitor messages from disallowed IDs with listening post mode. On the other hand, if an allowed ID sets a relay to a disallowed ID (or if permissions are revoked), currently nothing cleans those up automatically. So…what should be done in that case? Should relays to disallowed IDs be allowed at all? Should a change in the allowed ID list trigger a purge of the relay list? Or should things stay as they are now?
Tiin57 #5
Posted 24 October 2012 - 10:09 PM
I would think you'd be above such a trolololol, ChunLing.
Cruor #6
Posted 24 October 2012 - 10:11 PM
Please refrain from using a EULA that is basicly made to troll.
ChunLing #7
Posted 25 October 2012 - 12:23 AM
Ah, com'on! You guys are trashing my EULA without posting bug reports, what's up with that?
ChunLing #8
Posted 25 October 2012 - 05:28 AM
Well, since no one wants to trash my program's bugs, I'll focus on adding a few extra functions. Then there's sure to be tasty bugs to hunt.

I'm thinking that, while it's currently possible for an admin to do pretty much anything by using rcvfl to alter the startup file and restarting, it would be good to have an easier way to do certain things, like editing dmnlst and xclst and deleting files. So I'm thinking of basically two new functions, something like "access ID add/ban admin/exclusive" and "delete filename". The access function would add or ban an ID to/from the dmnlst or xclst. And of course delete would do just that to the named file (with a warning if you were trying to delete dmnlst).

Any thoughts?
ChunLing #9
Posted 26 October 2012 - 10:16 AM
Okay, new functions: access, del, and dir. Usage: "access add/ban ID dmnlst/xclst", "del filepath", and "dir path". The access command adds or removes a computerID from the dmnlst (that controls remote administrative access to the node) and the xclst, which controls basic access (removal of the xclst makes normal access unrestricted for non-admin things). The other two commands are basic file delete and directory listing.

As always, bug reports are sought. Usability is also a concern with the new commands, they've been added in the interests of easier remote administration, after all. The "access" and "del" commands are supposed to be available only to administrators, if you see them working for computerID's that haven't been added to the dmnlst, that's a bug, so report it!
SilverSatin #10
Posted 22 January 2013 - 06:59 AM
hold on i just gotta reformat your original post cause its hard to read without adding necessary spaces. ( no insult or offense meant by that )
——————————————————————————————————————————————————————————————

SpoilerBasically, this supports some additional functions that can be activated by sending it a rednet message.

1. We have good old "PING", which sends back a message giving the (nominal) position of the host, so that gps.locate calls can use it to find their position.

2. We add "bcst [message to broadcast]" which should rebroadcast "[message to broadcast]", or whatever other message you put in there.

3. Also "rly ID" where ID is the number ID of a computer/turtle you want to relay messges to/from,

4. and "drp" which drops the current relay (right now, you can only have one relay from a given ID through a given node, that might change but for now its enough for my needs).

5. We also have the "fwd ID [message to forward]" command, which takes the "[message to forward]" and forwards it to ID. This should work with multiple forwards, so you can write something like "fwd 10 fwd 11 fwd 12 fwd 13 Hi there!".
But I haven't fully tested it.


For functionality,
6. we have the "hsts" command, which orders the node to issue a ping and collect all the responses it gets in a table, which it then sends back to the command issuer.
This could be useful in some ways.

7.The "reboot" function, you guessed it, reboots the node. This can be useful, but it may be removed in later versions.

8. "rcvfl [filename]" opens the node to receive a message and and save it under "[filename]", the message body is requested in a followup message (I should probably change this so that the filebody is included after "[filename]" in the command message, we'll see).

9. "srvfl [filename]" does the exact opposite, it sends the file "[filename]" to the requester.

The program takes the same command line parameters as the existing gps program, with the addition of a single extra parameter (explained later). However, it differs in that it prefers consistency with an existing gps system and will override the provided parameters if it gets a valid location calculation based on pinging the area.

Once it has established its posltion, it saves a startup file so that if it reboots it will have the old position to start from. It also saves the table of relays, and an optional table (which is initially filled with the ID in the aforementioned extra parameter) that restricts access to the functions (including "PING") to an explicit list of authorized IDs.

Eventually, I may add a second list that restricts access to the bcst, hsts, rcvfl, and reboot commands (since these can be used to give away the node's position to untrusted rednet ID's or totally take over the relay node).

Feedback is much appreciated, particularly finding bugs. I am already planning to eventually add the "administrator" authorization level and to make it possible to have more than one relay per ID through a given node (there is already a special case when the relay ID is set to the ID of the node, it relays all received messages to the requesting ID).


Okay, fixed now. And now it should be a bit better.

————————————————————————————————————————————————————————————-
Also Bugfix. Newest update <- link does not work and its a little confusing to know what is the latest version the one posted in the spoiler of the one on paste bit maybe adding version numbers would be less confusing :D/>

Now my real post about this code. i dont understand it…
i removed the GPS part as thats something i dont need i kept the Relay part and forwarding but i cant get it to work.

I start up a server computer on one side of a 16x16 area
then i put this relay in the middle i entered (relay is the name of the program)
relay rly 21
all it did was create a 'dmnlst' file containing just "{}" without the quotes. and that was it…
then i thought i should just go ahead and make a client on the other side of the area and try to send a message TO the relay so it can send it to the server and get a respond back…

didnt work.

then i tried
relay host

which got a loop going but its not responding to incomming signals i dont know whats going on…. i think i broke the code when removing the GPS part. :P/> oh well, nice code and by the style of it YOUR A PRO! :D/>
Skullblade #11
Posted 22 January 2013 - 07:23 AM
you just gotta reformat his original post SO bad that you bumped a 3 month old post…….*head+table=bang*
ChunLing #12
Posted 22 January 2013 - 07:52 AM
Yeah…the first link is to the final pastebin, there were several temporary pastes as the program was being developed. I used date format since tracking a project version was a little beyond what suited this.

Okay, the basic command line usage is "relay host [x] [y] [z] [DM]", where x, y, and z are coordinates and DM is the computer ID of the computer that has administrative access (which is always remote, the program is designed for putting relay nodes up at the world height limit, where non-remote access is presumed to be irrelevant). Just to be clear, all interaction with the node is supposed to be by rednet, not just administrative functions.

I should rewrite the program to be more robust in terms of making sure that you have an admin ID set (either by command line or by dmnlst file). I should also probably remove the "host" parameter, I did that solely for the sake of maintaining as much similarity to the setup of a standard GPS host as possible, it really serves no other purpose.

You can remove/add functions from the hstfnc table without breaking the overall program, though some of them are pretty essential to controlling the thing. But if you're not setting a DM at startup you don't have access to the control functions anyway. You can only use dir, drp, flsrv, fwd, and rly if you are not sending from a computerID contained in the dmnlst. These functions are still used remotely, by sending rednet messages like "rly 23" (establish a two-way relay between the sender and computerID 23) to the relay node.