--------------------------------------------------------- --- ZedSocket library for ZD --------------------------------------------------------- local http = require("http") local json = require("./json.lua") local os = require("os") local math = require("math") local table = require("table") local qs = require('querystring') local WebSocket = require('luvit-websocket') return function(ZD) ZD.ZedSocket = function(port, wsOnly) local this = {} this.connectionHandlers = {} this.onConnection = function(t, func) if type(func) ~= "function" then return end table.insert(this.connectionHandlers, func) end this.clients = {} if(not wsOnly)then http.createServer(function (req, res) local tbl = { tostring(req.headers["accept-encoding"]), tostring(req.headers["accept-language"]), tostring(req.headers["connection"]), tostring(req.headers["cookie"]), tostring(req.headers["host"]), tostring(req.headers["user-agent"]) } local id = ZD.hashTable(tbl) local body = "" local url = ZD.parseURL(req.url) if url.path == "/connect" then local client = {} client.id = tostring(id) client.ip = req.socket._handle:getpeername().address client.uid = ZD.md5.sumhexa(client.ip .. client.id .. tostring(os.time()) .. tostring(math.random())) client.listener = {} client.packets = {} client.send = function(client, name, args) if type(args) == "table" then table.insert(client.packets, {packet = name, data = args}) end end client.on = function(client, event, cb) this.clients[client.uid].listener[event] = cb end this.clients[client.uid] = client for k,v in pairs(this.connectionHandlers) do v(client) end body = client.uid elseif url.path == "/get" then if url.get.id and this.clients[url.get.id] then local pack = {} local packets = {} for k,v in pairs(this.clients[url.get.id].packets) do table.insert(pack, v) end ZD.base64.encodeTable(pack, packets) this.clients[url.get.id].packets = {} body = json:encode(packets) end elseif url.path == "/send" then if url.get.id and this.clients[url.get.id] and url.get.data then local client = this.clients[url.get.id] local data = {} ZD.base64.decodeTable(json:decode(qs.urldecode(url.get.data)), data) if data.packet and type(client.listener[data.packet]) == "function" then client.listener[data.packet](data.data) end end elseif url.path == "/disconnect" then if url.get.id and this.clients[url.get.id] then if type(this.clients[url.get.id].listener["disconnect"]) == "function" then this.clients[url.get.id].listener["disconnect"]() end this.clients[url.get.id] = nil end end res:writeHead(200, { ["Content-Type"] = "text/plain", ["Access-Control-Allow-Origin"] = "*", ["Content-Length"] = #body }) res:finish(body) end):listen(port) end local WS = WebSocket.server(port + 1) WS:on('connect', function(sock) client = {} client.socket = sock client.socket.listener = {} client.ip = client.socket._handle:getpeername().address client.socket.uid = ZD.md5.sumhexa(client.ip .. tostring(os.time()) .. tostring(math.random())) client.send = function(client, name, args) if type(args) == "table" then local packet = {} ZD.base64.encodeTable({packet = tostring(name), data = args}, packet) client.socket:send(json:encode(packet)) end end client.on = function(client, event, cb) this.clients[client.socket.uid].socket.listener[event] = cb end this.clients[client.socket.uid] = client for k,v in pairs(this.connectionHandlers) do v(client) end end) WS:on('data', function(socket, message) local data = {} if message and #message > 3 then ZD.base64.decodeTable(json:decode(message), data) if data.packet and type(socket.listener[data.packet]) == "function" then socket.listener[data.packet](data.data) end end end) WS:on('disconnect', function(socket) if type(socket.listener) == "table" and type(socket.listener["disconnect"]) == "function" then socket.listener["disconnect"]() end this.clients[socket.uid] = nil end) return this end end