first before i get into the problem at hand, im not too familiar with timers and modem_messages with the os.pullevent(). im not entirely sure if a modem_message will still trigger if the computer is going through a current process.
problem trying to solve:
i am trying to create dynamic rednet sucurity with the modem api, i know a computer can only have 128 maximum channels (or ports i call them) open at the same time, so i figure that a server can listen on a certain channel as a public channel for clients to connect to. channels 1 - 128 would be public and channels 129 - 65535 would be private channels for interacting with servers.
problem i ran into:
i think i am getting the timing wrong but my test client is pinging on the test server, but the client isnt showing the response the server should have sent. im not sure how long i should wait between the transmit and reply and a little longer of a wait for a timer so if nothing happens the timer will fire and the client will continue on to other public ports.
i have both programs here and a screenshot of 1 run on the client program to the server.
tell me what yall think and test it out
P.S. im not giving out my encoding and decoding port functions due for the security purpose of this build.
test server code
Spoiler
-- rednet security server
local serverProperties = {publicPort = 10}
local privatePorts = {}
MODEM = peripheral.wrap("top")
MODEM.open(serverProperties.publicPort)
print("opened: "..serverProperties.publicPort)
while true do
local ev = { os.pullEvent() }
if ev[1] == "modem_message" then
os.sleep(0.2)
local iC = ev[3]
local rC = ev[4]
local pkg = textutils.unserialize(ev[5])
if type(pkg) == "table" then -- verify if its a table
if pkg.cid ~= nil then -- pkg must have a cid
privatePorts[pkg.cid] = {status = nil, name = pkg.name, port = nil}
if pkg.protocol == "_ping" then
privatePorts[pkg.cid].status = 1
MODEM.transmit(rC,serverProperties.publicPort,"_pong")
print("pinged from "..pkg.cid)
elseif pkg.protocol == "whoareyou?" and privatePorts[pkg.cid].status == 1 then
privatePorts[pkg.cid].status = 2
MODEM.transmit(rC,serverProperties.publicPort,"bankSer")
elseif pkg.protocol == "connectionRequest" and privatePorts[pkg.cid].status == 2 then
local gPort = RNGen() --RANDOM NUMBER GENERATOR TAKEN OUT
local packet = encodePort(gPort) --ENCODE PORT TAKEN OUT
privatePorts[pkg.cid].status = 3
privatePorts[pkg.cid].port = gPort
MODEM.open(gPort)
print("opened: "..gPort)
print("for cid: "..privatePorts[pkg.cid].status)
print("encoded at: "..textutils.serialize(packet))
MODEM.transmit(rC,serverProperties.publicPort,textutils.serialize(packet))
elseif pkg.protocol == "connectionVerify" and privatePorts[pkg.cid].status == 3 then
privatePorts[pkg.cid].status = "successful"
MODEM.transmit(rC,rC,"connectionEstablished")
else -- if pkg.protocol doesnt exist or doesnt match
MODEM.transmit(rC,serverProperties.publicPort,"invalid protocol")
print("invalid protocol")
end
else -- if pkg.cid is nil
MODEM.transmit(rC,serverProperties.publicPort,"invalid Credentials")
print("invalid Credentials")
end
else -- if pkg is a string
MODEM.transmit(rC,serverProperties.publicPort,"invalid packet")
print("invalid packet..")
end
elseif ev[1] == "key" then
end
os.sleep(0.1)
end
test client code
Spoiler
-- rednet security client
MODEM = peripheral.wrap("top")
-- lets find the server
local serverFound = false
local connected = false
local targetServ = "bankSer"
local count = 1
local status = 1
local credentials = {cid = os.getComputerID(), name = os.getComputerLabel(), protocol = nil}
print("Searching..")
while not serverFound and count < 16 do -- 120 public ports
MODEM.open(count)
print("opened: "..count)
if status == 1 then
credentials.protocol = "_ping"
status = 2
MODEM.transmit(count,count,textutils.serialize(credentials))
elseif status == 2 then
credentials.protocol = "whoareyou?"
MODEM.transmit(count,count,textutils.serialize(credentials))
elseif status == 3 then
credentials.protocol = "connectionRequest"
MODEM.transmit(count,count,textutils.serialize(credentials))
elseif status == 4 then
credentials.protocol = "connectionVerify"
MODEM.transmit(privatePort,privatePort,textutils.serialize(credentials))
end
credentials.protocol = nil
local T = os.startTimer(0.3)
local ev = { os.pullEvent() }
if ev[1] == "modem_message" then
local iC = ev[3]
local rC = ev[4]
local pkg = textutils.unserialize(ev[5])
if pkg == "_pong" then
serverFound = true
print("PINGED!")
end
end
count = count + 1
os.sleep(0.1)
end
print("Search ended")
the reason i put a status variable there for each computer id is i am making several steps to connect to the server, the client doesnt know what channel the server is listening on, so what the client does is i want it to scan each channel (most all the public channels [1-128]) and try and find the server its looking for. and the server keeps track of credentials that every connection needs, with is a table of the computerID computerName (if available), the status of the connection process and the port number assigned to that computer.
im not sure if i need to keep track of status of the connection, i mainly put it in there to make it hack proof and have a computer follow a specific format to connecting to the server without skipping a step.
this is the thought process i have drawn out of how i want the dynamic connection to work
so the client sends out pings for a server reply, if no rely go on to next channel and ping again.
once there is a pong, the client then asks "whoareyou?" so the server can reply with a unique id of what purpose that server does.
if the unique id isnt what the client wants then it will continue on the next channel.
if it is the right server then the client asks permission to connect
the server then encodes a port over rednet and sends it back to the client opening that private port
the client then decodes the port received by the server and closes all ports and opens the private port
last the client then sends a "connectionVerify" to see if it decoded the correct port from the server, and if so the server replies with "connectionEstablished"
and all the important information i am printing to the screen, im just not seeing the pong return from the server on the client that sent the ping. for testing i reduced the scan down to 15 channels and i should see a pong on the client on channel 10 but i dont, so thats why i am coming to the forums to see if i had a timing issue, or if i need to run the parallel api to try and solve this issue. i mainly think its a timing issue but im gunna keep tinkering with it and illl still listen on your guys' input like always
ok so after tinkering around alot, i have a proof of concept dynamically creating private ports on certain computer ids. expanding on the idea of hashing everything broadcasted on the public channels yes, but i did have timing issues, i learned today that i can sleep(0) to yield just long enough that a modem_message isnt triggered when i was sending a reply. code is very rough but im gunns work on it and place the beta builds in my pastebin. again i took out the RNG and encode and decode functions due to security. but here is a few screen shots and some data of the two programs i made, now i need to implement this on my banking system im creating.
-- rednet security client
MODEM = peripheral.wrap("top")
local decodePort = function(TAB)
-- TAKEN OUT
end
-- lets find the server
local serverFound = false
local connected = false
local targetServ = "bankSer"
local targetPort = nil
local count = 8
local status = 1
local credentials = {cid = os.getComputerID(), name = os.getComputerLabel(), protocol = nil}
print("Searching..")
while not serverFound and count < 13 do -- 120 public ports
MODEM.open(count)
print("opened: "..count)
if status == 1 then
credentials.protocol = "_ping"
MODEM.transmit(count,count,textutils.serialize(credentials))
local T = os.startTimer(0.5)
os.sleep(0)
local ev = { os.pullEvent() }
if ev[1] == "modem_message" then
local iC = ev[3]
local rC = ev[4]
local str = ev[5]
if str == "_pong" then
status = 2
print("PINGED!")
end
os.sleep(0)
if status == 2 then
credentials.protocol = "whoareyou?"
MODEM.transmit(count,count,textutils.serialize(credentials))
local T = os.startTimer(0.4)
os.sleep(0)
local ev = { os.pullEvent() }
if ev[1] == "modem_message" then
local iC = ev[3]
local rC = ev[4]
local str = ev[5]
if str == targetServ then
status = 3
serverFound = true
targetPort = count
print("Found Target Server, Requesting to Connect")
end
end
end
end
end
credentials.protocol = nil
count = count + 1
os.sleep(0.4)
end
print("Search ended, trying to connect")
local attempts = 0
while serverFound and not connected and attempts < 3 do
if status == 3 then
credentials.protocol = "connectionRequest"
MODEM.transmit(targetPort,targetPort,textutils.serialize(credentials))
local T = os.startTimer(0.4)
os.sleep(0)
local ev = { os.pullEvent() }
if ev[1] == "modem_message" then
local iC = ev[3]
local rC = ev[4]
local pkg = textutils.unserialize(ev[5])
targetPort = tonumber(decodePort(pkg))
print(targetPort)
connected = true
end
end
attempts = attempts + 1
end
print("ENDOF program")
-- rednet security server
local serverProperties = {publicPort = 10, serverType = "bankSer"}
local privatePorts = {}
MODEM = peripheral.wrap("top")
MODEM.open(serverProperties.publicPort)
print("opened: "..serverProperties.publicPort)
local RNGen = function()
-- TAKEN OUT
end
local encodePort = function(RNG)
-- TAKEN OUT
end
local decodePort = function(TAB)
-- TAKEN OUT
end
while true do
local ev = { os.pullEvent() }
if ev[1] == "modem_message" then
local iC = ev[3]
local rC = ev[4]
local pkg = textutils.unserialize(ev[5])
if type(pkg) == "table" then -- verify if its a table
if pkg.cid ~= nil then -- pkg must have a cid -computer id-
if privatePorts[pkg.cid] == nil then -- if cid isnt in memory create a slot
privatePorts[pkg.cid] = {name = pkg.name, port = 0}
end
os.sleep(0)
if pkg.protocol == "_ping" then
MODEM.transmit(rC,serverProperties.publicPort,"_pong")
print("pinged from "..pkg.cid)
elseif pkg.protocol == "whoareyou?" then
MODEM.transmit(rC,serverProperties.publicPort,serverProperties.serverType)
print("send Server ID to "..pkg.cid)
elseif pkg.protocol == "connectionRequest" then
local gPort = RNGen()
local packet = encodePort(gPort)
privatePorts[pkg.cid].port = gPort
MODEM.open(gPort)
print(" opened: "..gPort)
print(" for cid: "..pkg.cid)
print(" encoded at: "..textutils.serialize(packet))
MODEM.transmit(rC,serverProperties.publicPort,textutils.serialize(packet))
elseif pkg.protocol == "connectionVerify" then
MODEM.transmit(rC,rC,"connectionEstablished")
else -- if pkg.protocol doesnt exist or doesnt match
MODEM.transmit(rC,serverProperties.publicPort,"error: invalid protocol")
print("invalid protocol")
end
else -- if pkg.cid is nil
MODEM.transmit(rC,serverProperties.publicPort,"error: invalid Credentials")
print("invalid Credentials")
end
else -- if pkg is a string
MODEM.transmit(rC,serverProperties.publicPort,"error: invalid packet")
print("invalid packet..")
end
os.sleep(0)
elseif ev[1] == "key" then
print(textutils.serialize(privatePorts))
os.sleep(1.5)
end
end
and a picture of a monitor listening to all the events happening