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

need help with a mainframe

Started by JamiePhonic, 07 January 2013 - 05:32 AM
JamiePhonic #1
Posted 07 January 2013 - 06:32 AM
so, i'm running a Tekkit server for me and a few friends and we decided we wanted a way to control some things on the server from computers. for example, we have a factory and a fortress an wanted a way to control machines in the factory from a terminal in the fortress. so i wrote the code an it actually worked (after a lot of testing)
but we have now decided to generate a new map and use world edit to port some of the bigger buildings over, (namely the factory and fortress) because the old map was getting a little cramped.

so, here is my problem. all the buildings have been now spaced so far a part from the "central server" that i need to make a booster station to get all the terminals to connect to it. i don't really want to split the code up again into individual "areas" and so far my attempts at a booster/relay station have sort of failed, and this is why i'm here.

the code has 4 main parts:

The main server part; handles password checking and command execution.

The client part; handles the (very basic) UI and some status display parts. consists of 5 user accounts each of which grants access to manage a different facility, the admin account allows management of everything_

The booster station part: handles boosting commands (system will not work without at least 1 of these present)

The status screen part; handles displaying system status in each area (we have a big building with all the status screens in it to see whats going on everywhere at a glance. updates once every 10 seconds or so)
GopherAtl #2
Posted 07 January 2013 - 06:58 AM
a simple mission-specific relay station is pretty easy, a program something like this would work…


rednet.open(whateversidemodemson)

while true do
  local _, id, msg, dst = os.pullEvent("rednet_message")
  --parse the message
  local targetID, targetMsg = string.match(msg,"^(%d+)|(.*)$")
  --if we got values...
  if targetID and targetMsg then
    --...relay the message
    rednet.send(tonumber(targetID), targetMsg)
    print("relayed msg '"..targetMsg.."' from "..id.." to "..targetID)
  end 
end

then you would just send messages through the relay like this:


--replace <relayID> with the id of the computer running the relay program
--and <targetID> with the id of the computer you want it to send the message to

rednet.send(<relayID>,"<targetID>|any message here")
JamiePhonic #3
Posted 07 January 2013 - 07:32 AM
a simple mission-specific relay station is pretty easy, a program something like this would work…


rednet.open(whateversidemodemson)

while true do
  local _, id, msg, dst = os.pullEvent("rednet_message")
  --parse the message
  local targetID, targetMsg = string.match(msg,"^(%d+)|(.*)$")
  --if we got values...
  if targetID and targetMsg then
	--...relay the message
	rednet.send(tonumber(targetID), targetMsg)
	print("relayed msg '"..targetMsg.."' from "..id.." to "..targetID)
  end
end

then you would just send messages through the relay like this:


--replace <relayID> with the id of the computer running the relay program
--and <targetID> with the id of the computer you want it to send the message to

rednet.send(<relayID>,"<targetID>|any message here")
i had trued something like that, thing is, there's 2 way communication between server and client.
e.g. client sends a request, for example, "quarry"
the server receives this and executes the appropriate action and replies to the client with an acknowledgment that the action has been performed. in this case, quarry on or off and displays it no screen. its trying to get it to:

1. receive from the client and sent it to the server (id is constant so that's easy)
2. receive the reply from the server and get it to send it to the computer called the action.
the send and receives are broken up with sleeps so the client has time to receive the first reply before the server sends the second (in the case of the status monitors.)
GopherAtl #4
Posted 07 January 2013 - 07:42 AM
so? the relay I posted works both ways, and for any number of computers, you just have to modify them all to send through the relay. If you put the relay at very high altitude, it'll have more range and can cover a pretty sizable area in all directions with just the one, and the delay added by this shouldn't be more than a couple of ticks.
JamiePhonic #5
Posted 07 January 2013 - 07:50 AM
have a look at the client code, the server code and the relay code, the client WILL NOT operate with out a relay. it just says "couldn't connect to a local relay server" (line 241 down in the client code is the server ping code. it checks if a relay server is present and if so, continues with execution, else it shuts down.)

ill give the code a shot anyway and report back.
ChunLing #6
Posted 07 January 2013 - 09:36 PM
I don't know why you're parsing the message, just have a table of relays, and when a message comes into the relay, if the id corresponds to an index in the relay table, then send the message on to the value associated with that relay. Like this:
local relayList = {[10]=5,[5]=10,[12]=7,[7]=12,[33]=4,[4]=33,}
repeat sndr,mssg,dstnc = rednet.receive()
    if rlylst[sndr] then rednet.send(rlylst[sndr],mssg) end
until rlylst[sndr] and mssg == "Terminate Relay Hosting"
This provides immediate two way relay between computers according to their table entries. It is terminated by a message from any computer on the relay list.
JamiePhonic #7
Posted 08 January 2013 - 03:42 AM
I don't know why you're parsing the message, just have a table of relays, and when a message comes into the relay, if the id corresponds to an index in the relay table, then send the message on to the value associated with that relay. Like this:
local relayList = {[10]=5,[5]=10,[12]=7,[7]=12,[33]=4,[4]=33,}
repeat sndr,mssg,dstnc = rednet.receive()
	if rlylst[sndr] then rednet.send(rlylst[sndr],mssg) end
until rlylst[sndr] and mssg == "Terminate Relay Hosting"
This provides immediate two way relay between computers according to their table entries. It is terminated by a message from any computer on the relay list.
the thing is, the client uses a type of secure connection where it broadcasts a check message which the relay responds to, the relays id is then kept in a global variable so that the computer will only send messages to the relay and the relay will only send it to the server, it uses send instead of broadcast for things like password verification, the user enter a password and its sent through the relay to the server with rednet.send, the server reply's true or false depending on weather the password was right.

what i need is this: all clients will broadcast a message to check if a relay is available. the first relay to reply will become that computers default. all messages sent and received will use the id of the relay to send messages because there may be more than 1 relay in range. the relay will only ever send and receive messages from id 0, the main control server.
i would also like to some how add this code into it. this opens a file called users that lists the id's of all computers that are allowed to connect and checks the computers id against the list. if the ID isn't in the list, the command is ignored.

rednet.open("left")
while true do
print("--------------------------------------------")
print("Waiting for message...")
id, msg, dist = rednet.receive()
print("Message ".. msg .." received from ".. id ..", authenticating...")

continue = false
users = fs.open("users", "r")
while true do
  line = users.readLine()
  if not line then
   print("User ID ".. id .." authentication failed.")
   continue = false
   break
  elseif line == tostring(id) then
   print("User ID ".. id .." authentication succeeded.")
   continue = true
   break
  end
end
users.close()

if continue then
  command = {}
  for match in string.gmatch(msg, "[^ \t]+") do
	table.insert( command, match )
  end

  if command[1] == "reboot" then
   print("Rebooting...")
   sleep(1)
   os.reboot()
  
  elseif command[1] == "authuser" then
   print("Authenticating user ID ".. id)
   users = fs.open("users", "r")
   while true do
	line = users.readLine()
	if not line then
	 print("User ID ".. id .." authentication failed.")
	 rednet.send(id, "false")
	 break
	elseif line == tostring(id) then
	 print("User ID ".. id .." authentication succeeded.")
	 rednet.send(id, "true")
  break
	end
   end
   users.close()
ChunLing #8
Posted 08 January 2013 - 07:15 AM
Um…you might be misinterpreting how you can access a global variable. It's available to all programs run in the shell environment of a given computer, it's not available to any other computers.

Anyway, my sample code was pulled from my rnhst program, which suits my needs even though it only handles one recipient per sender at a time (you can have multiple senders per recipient, if you don't drop them with the correct node command, but I like this and so I rarely drop relays…I liked it so much that I added a way to make it so that a given computer can receive all messages received by the node).

The thing is that rednet is (currently) secure enough that a simple relay works just fine and is fairly transparent, so it doesn't require extensive adaptation of code to work with it.
JamiePhonic #9
Posted 08 January 2013 - 08:41 AM
Um…you might be misinterpreting how you can access a global variable. It's available to all programs run in the shell environment of a given computer, it's not available to any other computers.
i know that, i want each computer to find a relay and store its ID so only that relay will be used because there may be more than 1 relay in range. of any given computer

Edit: its ok, i figured it out using the code i wrote myself