diff --git a/libnetwork.lua b/libnetwork.lua index 672cc37..0ba9076 100644 --- a/libnetwork.lua +++ b/libnetwork.lua @@ -9,184 +9,193 @@ close=function(port):bool } --]] -local netcard=require("localNetcard") +local netcard = require("localNetcard") +local event = require("event") +local uuid = require("uuid") +require("vector") -- Check Netcard -if(netcard.broadcast==nil or - netcard.send==nil or - netcard.open==nil or - netcard.isOpen==nil or - netcard.close==nil) then +if + (netcard.broadcast == nil or netcard.send == nil or netcard.open == nil or netcard.isOpen == nil or + netcard.close == nil) + then print("Error: netcard invalid.") end -local sker= -- Socket Kernel Table - { - fdset= -- Store information of sockets - { - --[[ - status : string ="Ready" "Connected" "Closed" - remote_hwport : int - remote_cookie : string - --]] - } - } +local sker = { + -- Socket Kernel Table + fdset = {} -- Store information of sockets +} -local arpker={} -- ARP Kernel Table +local arpker = {} -- ARP Kernel Table +local tcp_syn = string.pack("iii", 1, 1, 1) +local tcp_synack = string.pack("iii", 1, 1, 3) +local tcp_ack = string.pack("iii", 1, 1, 2) +local arp_broadcast = string.pack("iii", 1, 0, 0) +local arp_quest = string.pack("iii", 1, 0, 1) +local dhcp_quest = string.pack("iii", 0, 0, 1) +local dhcp_ack = string.pack("iii", 0, 0, 2) +local trans_data = string.pack("iii", 1, 2, 1) +local trans_ack = string.pack("iii", 1, 2, 2) function _findFirstAvaliableSocket() - local i=0 - while ( sker.fdset[i] ~= nil ) do i=i+1 end + local i = 0 + while (sker.fdset[i] ~= nil) do + i = i + 1 + end return i end function _doCreateSocket(sfd) - if(sker.fdset[sfd]~=nil) then return false,"sfd invalid" + if (sker.fdset[sfd] ~= nil) then + return false, "sfd invalid" else - sker.fdset[sfd]= - { - status="Ready" - } - return true,"Success" + sker.fdset[sfd] = { + status = "Ready", + -- remote_cookie + -- local_cookie + sendBus = Vector.new(), + recvBus = Vector.new() + } + return true, "Success" end end function _getSocketStatus(sfd) - if(sker.fdset[sfd]==nil) then return nil + if (sker.fdset[sfd] == nil) then + return nil else return sker.fdset[sfd].status end end -function _setSocketStatus(sfd,status,...) - if(sker.fdset[sfd]==nil) then return false +function _setSocketStatus(sfd, status, ...) + if (sker.fdset[sfd] == nil) then + return false else - sker.fdset[sfd].status=status - if(status=="Connected") then - sker.fdset[sfd].remote_hwport=arg[1] + sker.fdset[sfd].status = status + if (status == "Connected") then + sker.fdset[sfd].remote_cookie = arg[1] end return true end end function _isPortValid(port) - return port>0 and port<65536 + return port > 0 and port < 65536 end -function _doConnect(sfd,remote_uuid,port) -- Connect to port 10 of a remote device with virtual port +function _generateNewCookie() -- Generate a new cookie + return uuid.next() +end + +function _doConnect(sfd, remote_uuid, port) -- Connect to port 10 of a remote device with virtual port -- Send SYN package (1,1,1) - local syn=string.pack("iii",1,1,1) - if(not netcard.send(remote_uuid,10,syn,port)) then - return -1,"Network error" + local syn = tcp_syn + if (not netcard.send(remote_uuid, 10, syn, port)) then + return -1, "Network error" end -- Wait 1.5 seconds for SYN+ACK (1,1,3) - local e,remote_hwport,remote_cookie=event.pull(1.5,"net_synack") - if(e==nil) then - return -2,"Connection timed out" + local e, remote_cookie = event.pull(1.5, "net_synack") + if (e == nil) then + return -2, "Connection timed out" end --- Send ACK package (1,1,2) - local ack=string.pack("iii",1,1,2) - if(not netcard.send(remote_uuid,port,ack)) then - return -1,"Network error" + local ack = tcp_ack + local newcookie = _generateNewCookie() + -- Update FDSet Cookie + sker.fdset[sfd].remote_cookie = remote_cookie + sker.fdset[sfd].local_cookie = newcookie + if (not netcard.send(remote_uuid, 10, ack, remote_cookie, newcookie)) then + return -1, "Network error" end -- Connection established - return 0,"Success",remote_hwport + return 0, "Success", remote_cookie end function _isInArpCache(tag) -- Check ARP Check Table with tag for uuid - if(arpker[tag]~=nil) then - return true,arpker[tag].uuid + if (arpker[tag] ~= nil) then + return true, arpker[tag].uuid else return false end end -function _generateARPQuest(tag) -- Generate a ARP quest - local s=string.pack("iiii",1,0,1,string.length(tag)) - s=s..tag - return s -end - -function _doArpBroadcastQuery(tag) -- Broadcast ARP quest to hardware port 9 (arp) - if(netcard.broadcast(9,tag)) then return true,"Success" - else return false,"Netcard error" -end - -function socket() -- Allocate a new socket - local idx=_findFirstAvaliableSocket() - local ret,emsg=_doCreateSocket(idx) - if(not ret) then - return -1,emsg +function _doArpBroadcastQuery(header, tag) -- Broadcast ARP quest to hardware port 9 (arp) + if (netcard.broadcast(9, header, tag)) then + return true, "Success" else - return ret,emsg + return false, "Netcard error" end end -function connect(sfd,remote_tag,port) -- Connect to a remote device - if(_getSocketStatus(sfd)~="Ready") then - return -1,"Socket not ready" - elseif(not _isPortValid(port)) then - return -2,"Port Invalid" +function socket() -- Allocate a new socket + local idx = _findFirstAvaliableSocket() + local ret, emsg = _doCreateSocket(idx) + if (not ret) then + return -1, emsg + else + return ret, emsg + end +end + +function connect(sfd, remote_tag, port) -- Connect to a remote device + if (_getSocketStatus(sfd) ~= "Ready") then + return -1, "Socket not ready" + elseif (not _isPortValid(port)) then + return -2, "Port Invalid" else -- Try to resolve remote_tag to remote_uuid - local remote_uuid=do_arp_query(remote_tag) - if(remote_uuid == nil) then - return -3,"Tag can not be resolved into uuid" + local remote_uuid = do_arp_query(remote_tag) + if (remote_uuid == nil) then + return -3, "Tag can not be resolved into uuid" else - local eret,emsg,remote_hwport,remote_cookie=_doConnect(sfd,remote_uuid,port) - if(eret==0) then - _setSocketStatus(sfd,"Connected",remote_hwport,remote_cookie) - return 0,"Success" + local eret, emsg, remote_cookie = _doConnect(sfd, remote_uuid, port) + if (eret == 0) then + _setSocketStatus(sfd, "Connected", remote_cookie) + return 0, "Success" else - return eret,emsg + return eret, emsg end end end end -function bind(sfd,port) -- Bind socket at specific port - +function bind(sfd, port) -- Bind socket at specific port end -function listen(sfd,sz) -- Set size of queue for waiting connections - +function listen(sfd, sz) -- Set size of queue for waiting connections end function accept(sfd) -- Accept Connection - end -function send(sfd,...) -- Standard Network I/O - +function send(sfd, ...) -- Standard Network I/O end function recv(sfd) -- Standard Network I/O - end function shutdown(sfd) -- Close Socket - end function close(sfd) -- Close Socket - -end - -function do_dhcp_client() -- Connect to DHCP Server and try to get a tag. - end function do_arp_query(tag) -- ARP: Query uuid with tag, might send arp-request - local ret,uuid=_isInArpCache(tag) - if(ret) then return uuid + local ret, uuid = _isInArpCache(tag) + if (ret) then + return uuid else - local quest=_generateARPQuest(tag) - for i=1,3,1 do - if(_doArpBroadcastQuery(quest)) then - local e,etag,euuid=event.pull(0.5,"net_newarp") - if(e~=nil) then return euuid end + local questHeader = _generateARPQuestHeader() + for i = 1, 3, 1 do + if (_doArpBroadcastQuery(questHeader, tag)) then + local e, etag, euuid = event.pull(0.5, "net_newarp") + if (e ~= nil and etag == tag) then + return euuid + end end end return nil -- Failed to query arp in 3 tries. @@ -194,41 +203,84 @@ function do_arp_query(tag) -- ARP: Query uuid with tag, might send arp-request end function run_arp() -- Start ARP Services in background -event.listen("modem_message", -function(_event,_receiver,sender,_port,_distance,...) -if(_port==9) then -if(arg[1]==string.pack("iii",1,0,0) and arg[2]~=nil) then -- Received an ARP Broadcast -if(arpker[arg[2]]==nil) then -arpker[arg[2]]=sender -event.push("net_newarp",arg[2],sender) -elseif(arpker[arg[2]]~=sender) then -arpker[arg[2]]=sender -event.push("net_arpchanged",arg[2],sender) -end -- arpker check -elseif(arg[1]==string.pack("iii",1,0,1) and arg[2]~=nil) then -- Received an ARP Quest Broadcast -//todo -end -- arg1 and arg2 check -end -- port check -end) -- callback -end + event.listen( + "modem_message", + function(_event, _receiver, sender, _port, _distance, ...) + if (_port == 9) then + if (arg[1] == arp_broadcast and arg[2] ~= nil) then + -- Received an ARP Broadcast + if (arpker[arg[2]] == nil) then + arpker[arg[2]] = sender + event.push("net_newarp", arg[2], sender) + elseif (arpker[arg[2]] ~= sender) then + arpker[arg[2]] = sender + event.push("net_arpchanged", arg[2], sender) + end -- arpker check + elseif (arg[1] == arp_quest and arg[2] ~= nil and arg[2] == arpker.thisDevice) then + -- Received an ARP Quest Broadcast and it points this device + netcard.send(sender, 9, arp_broadcast, arg[2]) + end -- arg1 and arg2 check + end -- port check + end + ) -- callback + netcard.open(9) +end function run_dhcp_client() -- Start DHCP Client in background - + local finished = false + event.listen( + "modem_message", + function(_event, _receiver, sender, port, _distance, ...) + if (port == 8 and arg[1] == dhcp_ack) then + -- Receive DHCP Answer + arpker.thisDevice = arg[2] + -- Close Local Port + network.close(7) + -- Change flag to stop running + finished = true + -- Unregister this callback + return false + end + end + ) + network.open(7) + while not finished do + network.broadcast(8, dhcp_quest) + os.sleep(1) + end end function run_tcp() -- Start TCP Services in background -event.listen("modem_message", -function(_event,_receiver,sender,_port,_distance...) -if(_port==10) then -if(arg[1]==string.pack("iii",1,1,1)) then --SYN -event.push("net_newsyn",sender,arg[2]) + event.listen( + "modem_message", + function(_event, _receiver, sender, port, _distance, ...) + if (port == 10) then + if (arg[1] == tcp_syn) then --SYN + event.push("net_newsyn", sender, arg[2]) + end + elseif (port == 11) then + if (arg[1] == tcp_synack) then --SYN/ACK + event.push("net_newsynack", sender) + end + end + end + ) + event.listen( + "modem_message", + function(_event, _receiver, sender, port, _distance, ...) + if (port == 12) then + if (arg[1] == trans_data and arg[2] ~= nil) then + -- Find cookie and push data + for k, t in pairs(sker.fdset) do + if (t.local_cookie == arg[2]) then + t.recvBus.push_back(arg[3]) + break + end + end + end + end + end + ) + netcard.open(10) + netcard.open(11) end -elseif(_port==11) then -if(arg[1]==string.pack("iii",1,1,3)) then --SYN/ACK -event.push("net_newsynack",sender) -end -end -end) -netcard.open(10) -netcard.open(11) -end \ No newline at end of file