-
-
Save EliterScripts/3fd2be3193ea4366d3cf7a601590245b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require('love.system') | |
require('love.timer') | |
require('love.math') | |
do | |
local json = require("engine/json/json") | |
local networkOutChannel = love.thread.getChannel( "network-server-thread" ) | |
local globalKillChannel = love.thread.getChannel( "global-kill-thread" ) | |
local printOutChannel = love.thread.getChannel( "printed-output" ) | |
local receiveClientData = love.thread.getChannel("receieve-client-data") | |
local sendClientData = love.thread.getChannel("send-client-data") | |
local running = true | |
function printDebug(...) | |
--if(wait ~= false)then | |
-- printOutChannel:supply({type = debugType, message = message}) | |
--else | |
printOutChannel:push({...}) | |
--end | |
end | |
function safePrintDebug(...) | |
local Args = {...} | |
return pcall(function() | |
printDebug(unpack(Args)) | |
end) | |
end | |
local function killMyself() | |
running = false | |
end | |
local function checkKillChannel() | |
local value = globalKillChannel:peek() | |
if(value == "command-line-user-input")then | |
globalKillChannel:pop() | |
killMyself() | |
elseif(value == "*")then | |
killMyself() | |
end | |
end | |
local function sendReceivedClientData(client, localAddress, localPort, sent_data, isPartial) | |
local json_encoded = "" | |
local stat, err = pcall(function() | |
local remoteAddress, remotePort = client:getpeername() | |
json_encoded = json.encode( | |
{ | |
["remoteAddress"] = remoteAddress, | |
["remotePort"] = remotePort, | |
["localAddress"] = localAddress, | |
["localPort"] = localPort, | |
["type"] = "received_data", | |
["message"] = sent_data, | |
["isPartial"] = isPartial, | |
["time"] = love.timer.getTime() | |
} | |
) | |
end) | |
if(stat == false)then | |
printDebug("Error: networkThread: receivedClientData: error while compiling JSON string:" .. err) | |
return false | |
else | |
receiveClientData:push(json_encoded) | |
return true | |
end | |
end | |
local function sendClientDisconnect(remoteAddress, remotePort, server) | |
local json_encoded = "" | |
local stat, err = pcall(function() | |
local localAddress, localPort = server:getsockname() | |
json_encoded = json.encode( | |
{ | |
["remoteAddress"] = remoteAddress, | |
["remotePort"] = remotePort, | |
["localAddress"] = localAddress, | |
["localPort"] = localPort, | |
["type"] = "meta", | |
["message"] = "disconnect", | |
["time"] = love.timer.getTime() | |
} | |
) | |
end) | |
if(stat == false)then | |
printDebug("Error: networkThread: sendClientDisconnect: error while compiling JSON string:" .. err) | |
return false | |
else | |
receiveClientData:push(json_encoded) | |
return true | |
end | |
end | |
local function sendClientConnect(client, localAddress, localPort) | |
local json_encoded = "" | |
local stat, err = pcall(function() | |
local remoteAddress, remotePort = client:getpeername() | |
json_encoded = json.encode( | |
{ | |
["remoteAddress"] = remoteAddress, | |
["remotePort"] = remotePort, | |
["localAddress"] = localAddress, | |
["localPort"] = localPort, | |
["type"] = "meta", | |
["message"] = "connect", | |
["time"] = love.timer.getTime() | |
} | |
) | |
end) | |
if(stat == false)then | |
printDebug("Error: networkThread: sendClientConnect: error while compiling JSON string:" .. err) | |
return false | |
else | |
receiveClientData:push(json_encoded) | |
return true | |
end | |
end | |
local function receiveSendClientData(client, server) | |
local rawMessage = sendClientData:peek() | |
if(rawMessage == nil)then | |
sendClientData:pop() | |
return true | |
end | |
--print(rawMessage) | |
local stat, err = pcall(function() | |
local currentRemoteAddress, currentRemotePort = client:getpeername() | |
local currentLocalAddress, currentLocalPort = server:getsockname() | |
local decoded_json = json.decode(rawMessage) | |
local remoteAddress = decoded_json["remoteAddress"] | |
local remotePort = decoded_json["remotePort"] | |
local localAddress = decoded_json["localAddress"] | |
local localPort = decoded_json["localPort"] | |
local receiveType = decoded_json["type"] | |
local message = decoded_json["message"] | |
if(currentRemoteAddress == remoteAddress)and | |
(currentRemotePort == remotePort)and | |
(currentLocalPort == localPort)and | |
(currentLocalAddress == localAddress)then | |
sendClientData:pop() | |
if(receiveType == "meta")then | |
if(message == "close")then | |
printDebug( | |
string.format( | |
"Info: dropping client %s:%s on %s:%s...", | |
currentRemoteAddress, currentRemotePort, currentLocalAddress, currentLocalPort | |
) | |
) | |
client:close() | |
return true, "closed" | |
end | |
elseif(receiveType == "send_data")then | |
print("sending...") | |
print(client:send(message)) | |
return true, "sent" | |
end | |
else | |
return false, "wrong_one" | |
end | |
end) | |
if(stat == false)then | |
printDebug("Error: networkThread: receiveSendClientData: " .. err) | |
end | |
end | |
while(running)do | |
checkKillChannel() | |
local socket = nil; | |
local server = nil; | |
local bound_port = nil; | |
local clients = {} | |
local localAddress; | |
local localPort; | |
local stat, err = pcall(function() | |
-- load namespace | |
socket = require("socket") | |
-- create a TCP socket and bind it to the local host, at any port | |
server = assert(socket.bind("*", 11055)) | |
-- find out which port the OS chose for us | |
local localAddress, localPort = server:getsockname() | |
bound_port = localPort | |
server:settimeout(0.2) | |
server:setoption('keepalive', true) | |
-- print a message informing what's up | |
printDebug("Please telnet to localhost on port " .. localPort) | |
-- loop forever waiting for clients | |
while(true)do | |
-- wait for a connection from any client | |
local client; | |
while(true)do | |
client = server:accept() | |
if(client ~= nil)then | |
client:settimeout(0.2) | |
client:setoption('keepalive', true) | |
local remoteAddress, remotePort = client:getpeername() | |
sendClientConnect(client, localAddress, localPort) | |
table.insert(clients, { | |
remoteAddress = remoteAddress, remotePort = remotePort, client = client, | |
localAddress = localAddress, localPort = localPort | |
}) | |
else | |
for k, v in pairs(clients)do | |
local client = v.client | |
if(client ~= nil)then | |
local stat, code = receiveSendClientData(client, server) | |
if(code == "closed")then | |
client:close() | |
--local stat, err = pcall(function() | |
while(true)do | |
local rawMessage = sendClientData:peek() | |
if(rawMessage == nil)then break end | |
local json_decoded = json.decode(rawMessage) | |
local localAddress = json_decoded["localAddress"] | |
local localPort = json_decoded["localPort"] | |
local remoteAddress = json_decoded["remoteAddress"] | |
local remotePort = json_decoded["remotePort"] | |
if(remoteAddress == v["remoteAddress"])and | |
(remotePort == v["remotePort"])and | |
(localPort == v["localPort"])and | |
(localAddress == v["localAddress"])then | |
sendClientData:pop() | |
else | |
break | |
end | |
end | |
--end) | |
table.remove(clients, k) | |
else | |
local full_data, s_status, partial_data = client:receive() | |
if(s_status == "closed")then | |
sendClientDisconnect(v.remoteAddress, v.remotePort, server) | |
client:close() | |
--local stat, err = pcall(function() | |
while(true)do | |
local rawMessage = sendClientData:peek() | |
if(rawMessage == nil)then break end | |
local json_decoded = json.decode(rawMessage) | |
local localAddress = json_decoded["localAddress"] | |
local localPort = json_decoded["localPort"] | |
local remoteAddress = json_decoded["remoteAddress"] | |
local remotePort = json_decoded["remotePort"] | |
if(remoteAddress == v["remoteAddress"])and | |
(remotePort == v["remotePort"])and | |
(localPort == v["localPort"])and | |
(localAddress == v["localAddress"])then | |
sendClientData:pop() | |
else | |
break | |
end | |
end | |
--end) | |
table.remove(clients, k) | |
else | |
local isPartial; | |
if(partial_data ~= nil)then | |
isPartial = true | |
end | |
if(full_data ~= nil)then | |
isPartial = false | |
end | |
sendReceivedClientData(client, localAddress, localPort, full_data or partial_data, isPartial) | |
end | |
end | |
end | |
end | |
end | |
end | |
--[[local client_host, client_port = client:getsockname() | |
local client_addr = client_host .. ":" .. client_port | |
-- make sure we don't block waiting for this client's line | |
printDebug("accepted connection. (" .. client_addr .. ")") | |
client:setoption('keepalive', true) | |
client:settimeout(0.2) | |
printDebug("connection timed out. (" .. client_addr .. ")") | |
-- receive the line | |
local line, err = client:receive() | |
-- if there was no error, send it back to the client | |
if not err then | |
client:send("RE: " .. line .. "\n") | |
printDebug("RECEIVE: " .. line .. "(" .. client_addr .. ")") | |
end | |
-- done with client, close the object | |
--client:close()]]-- | |
end | |
end) | |
if(stat == false)then | |
pcall(function() | |
printDebug("Error: " .. err) | |
end) | |
--attempts to close TCP socket, if exists. | |
local stat1, err1 = pcall(function() | |
safePrintDebug("Info: Attempting to close potential server port from safe mode...") | |
local stat2, err2 = pcall(function() | |
if(server == nil)then | |
safePrintDebug("Info: server object does not exist.") | |
else | |
safePrintDebug("Info: Attempting to close server object...") | |
server:close() | |
safePrintDebug("Info: Successfully closed server object.") | |
end | |
end) | |
if(stat2 == false )then | |
safePrintDebug("Error: there was a problem while attempting to close server object: " .. err2) | |
end | |
end) | |
if(stat1 == false)then | |
pcall(function() | |
printDebug("Error: there was an error while attempting to close potential port: " .. err) | |
end) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment