mirror of
				https://github.com/LDDestroier/CC/
				synced 2025-10-31 07:22:59 +00:00 
			
		
		
		
	Update skynet.lua
This commit is contained in:
		| @@ -1,704 +1,4 @@ | ||||
| -- Skynet was created by Gollark | ||||
| -- This version was modified to include CBOR in the same file | ||||
| https://github.com/LDDestroier/CC/raw/master/API/skynet.lua | ||||
|  | ||||
| local CBOR = (function() | ||||
| 	-- Concise Binary Object Representation (CBOR) | ||||
| 	-- RFC 7049 | ||||
|  | ||||
| 	local function softreq(pkg, field) | ||||
| 		local ok, mod = pcall(require, pkg); | ||||
| 		if not ok then return end | ||||
| 		if field then return mod[field]; end | ||||
| 		return mod; | ||||
| 	end | ||||
| 	local dostring = function (s) | ||||
| 		local ok, f = pcall(loadstring or load, s); -- luacheck: read globals loadstring | ||||
| 		if ok and f then return f(); end | ||||
| 	end | ||||
|  | ||||
| 	local setmetatable, getmetatable = setmetatable, getmetatable; | ||||
| 	local dbg_getmetatable | ||||
| 	if debug then dbg_getmetatable = debug.getmetatable else dbg_getmetatable = getmetatable end | ||||
| 	local assert = assert; | ||||
| 	local error = error; | ||||
| 	local type = type; | ||||
| 	local pairs = pairs; | ||||
| 	local ipairs = ipairs; | ||||
| 	local tostring = tostring; | ||||
| 	local s_char = string.char; | ||||
| 	local t_concat = table.concat; | ||||
| 	local t_sort = table.sort; | ||||
| 	local m_floor = math.floor; | ||||
| 	local m_abs = math.abs; | ||||
| 	local m_huge = math.huge; | ||||
| 	local m_max = math.max; | ||||
| 	local maxint = math.maxinteger or 9007199254740992; | ||||
| 	local minint = math.mininteger or -9007199254740992; | ||||
| 	local NaN = 0/0; | ||||
| 	local m_frexp = math.frexp; | ||||
| 	local m_ldexp = math.ldexp or function (x, exp) return x * 2.0 ^ exp; end; | ||||
| 	local m_type = math.type or function (n) return n % 1 == 0 and n <= maxint and n >= minint and "integer" or "float" end; | ||||
| 	local s_pack = string.pack or softreq("struct", "pack"); | ||||
| 	local s_unpack = string.unpack or softreq("struct", "unpack"); | ||||
| 	local b_rshift = softreq("bit32", "rshift") or softreq("bit", "rshift") or | ||||
| 		dostring "return function(a,b) return a >> b end" or | ||||
| 		function (a, b) return m_max(0, m_floor(a / (2 ^ b))); end; | ||||
|  | ||||
| 	-- sanity check | ||||
| 	if s_pack and s_pack(">I2", 0) ~= "\0\0" then | ||||
| 		s_pack = nil; | ||||
| 	end | ||||
| 	if s_unpack and s_unpack(">I2", "\1\2\3\4") ~= 0x102 then | ||||
| 		s_unpack = nil; | ||||
| 	end | ||||
|  | ||||
| 	local _ENV = nil; -- luacheck: ignore 211 | ||||
|  | ||||
| 	local encoder = {}; | ||||
|  | ||||
| 	local function encode(obj, opts) | ||||
| 		return encoder[type(obj)](obj, opts); | ||||
| 	end | ||||
|  | ||||
| 	-- Major types 0, 1 and length encoding for others | ||||
| 	local function integer(num, m) | ||||
| 		if m == 0 and num < 0 then | ||||
| 			-- negative integer, major type 1 | ||||
| 			num, m = - num - 1, 32; | ||||
| 		end | ||||
| 		if num < 24 then | ||||
| 			return s_char(m + num); | ||||
| 		elseif num < 2 ^ 8 then | ||||
| 			return s_char(m + 24, num); | ||||
| 		elseif num < 2 ^ 16 then | ||||
| 			return s_char(m + 25, b_rshift(num, 8), num % 0x100); | ||||
| 		elseif num < 2 ^ 32 then | ||||
| 			return s_char(m + 26, | ||||
| 				b_rshift(num, 24) % 0x100, | ||||
| 				b_rshift(num, 16) % 0x100, | ||||
| 				b_rshift(num, 8) % 0x100, | ||||
| 				num % 0x100); | ||||
| 		elseif num < 2 ^ 64 then | ||||
| 			local high = m_floor(num / 2 ^ 32); | ||||
| 			num = num % 2 ^ 32; | ||||
| 			return s_char(m + 27, | ||||
| 				b_rshift(high, 24) % 0x100, | ||||
| 				b_rshift(high, 16) % 0x100, | ||||
| 				b_rshift(high, 8) % 0x100, | ||||
| 				high % 0x100, | ||||
| 				b_rshift(num, 24) % 0x100, | ||||
| 				b_rshift(num, 16) % 0x100, | ||||
| 				b_rshift(num, 8) % 0x100, | ||||
| 				num % 0x100); | ||||
| 		end | ||||
| 		error "int too large"; | ||||
| 	end | ||||
|  | ||||
| 	if s_pack then | ||||
| 		function integer(num, m) | ||||
| 			local fmt; | ||||
| 			m = m or 0; | ||||
| 			if num < 24 then | ||||
| 				fmt, m = ">B", m + num; | ||||
| 			elseif num < 256 then | ||||
| 				fmt, m = ">BB", m + 24; | ||||
| 			elseif num < 65536 then | ||||
| 				fmt, m = ">BI2", m + 25; | ||||
| 			elseif num < 4294967296 then | ||||
| 				fmt, m = ">BI4", m + 26; | ||||
| 			else | ||||
| 				fmt, m = ">BI8", m + 27; | ||||
| 			end | ||||
| 			return s_pack(fmt, m, num); | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local simple_mt = {}; | ||||
| 	function simple_mt:__tostring() return self.name or ("simple(%d)"):format(self.value); end | ||||
| 	function simple_mt:__tocbor() return self.cbor or integer(self.value, 224); end | ||||
|  | ||||
| 	local function simple(value, name, cbor) | ||||
| 		assert(value >= 0 and value <= 255, "bad argument #1 to 'simple' (integer in range 0..255 expected)"); | ||||
| 		return setmetatable({ value = value, name = name, cbor = cbor }, simple_mt); | ||||
| 	end | ||||
|  | ||||
| 	local tagged_mt = {}; | ||||
| 	function tagged_mt:__tostring() return ("%d(%s)"):format(self.tag, tostring(self.value)); end | ||||
| 	function tagged_mt:__tocbor() return integer(self.tag, 192) .. encode(self.value); end | ||||
|  | ||||
| 	local function tagged(tag, value) | ||||
| 		assert(tag >= 0, "bad argument #1 to 'tagged' (positive integer expected)"); | ||||
| 		return setmetatable({ tag = tag, value = value }, tagged_mt); | ||||
| 	end | ||||
|  | ||||
| 	local null = simple(22, "null"); -- explicit null | ||||
| 	local undefined = simple(23, "undefined"); -- undefined or nil | ||||
| 	local BREAK = simple(31, "break", "\255"); | ||||
|  | ||||
| 	-- Number types dispatch | ||||
| 	function encoder.number(num) | ||||
| 		return encoder[m_type(num)](num); | ||||
| 	end | ||||
|  | ||||
| 	-- Major types 0, 1 | ||||
| 	function encoder.integer(num) | ||||
| 		if num < 0 then | ||||
| 			return integer(-1 - num, 32); | ||||
| 		end | ||||
| 		return integer(num, 0); | ||||
| 	end | ||||
|  | ||||
| 	-- Major type 7 | ||||
| 	function encoder.float(num) | ||||
| 		if num ~= num then -- NaN shortcut | ||||
| 			return "\251\127\255\255\255\255\255\255\255"; | ||||
| 		end | ||||
| 		local sign = (num > 0 or 1 / num > 0) and 0 or 1; | ||||
| 		num = m_abs(num) | ||||
| 		if num == m_huge then | ||||
| 			return s_char(251, sign * 128 + 128 - 1) .. "\240\0\0\0\0\0\0"; | ||||
| 		end | ||||
| 		local fraction, exponent = m_frexp(num) | ||||
| 		if fraction == 0 then | ||||
| 			return s_char(251, sign * 128) .. "\0\0\0\0\0\0\0"; | ||||
| 		end | ||||
| 		fraction = fraction * 2; | ||||
| 		exponent = exponent + 1024 - 2; | ||||
| 		if exponent <= 0 then | ||||
| 			fraction = fraction * 2 ^ (exponent - 1) | ||||
| 			exponent = 0; | ||||
| 		else | ||||
| 			fraction = fraction - 1; | ||||
| 		end | ||||
| 		return s_char(251, | ||||
| 			sign * 2 ^ 7 + m_floor(exponent / 2 ^ 4) % 2 ^ 7, | ||||
| 			exponent % 2 ^ 4 * 2 ^ 4 + | ||||
| 			m_floor(fraction * 2 ^ 4 % 0x100), | ||||
| 			m_floor(fraction * 2 ^ 12 % 0x100), | ||||
| 			m_floor(fraction * 2 ^ 20 % 0x100), | ||||
| 			m_floor(fraction * 2 ^ 28 % 0x100), | ||||
| 			m_floor(fraction * 2 ^ 36 % 0x100), | ||||
| 			m_floor(fraction * 2 ^ 44 % 0x100), | ||||
| 			m_floor(fraction * 2 ^ 52 % 0x100) | ||||
| 		) | ||||
| 	end | ||||
|  | ||||
| 	if s_pack then | ||||
| 		function encoder.float(num) | ||||
| 			return s_pack(">Bd", 251, num); | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
|  | ||||
| 	-- Major type 2 - byte strings | ||||
| 	function encoder.bytestring(s) | ||||
| 		return integer(#s, 64) .. s; | ||||
| 	end | ||||
|  | ||||
| 	-- Major type 3 - UTF-8 strings | ||||
| 	function encoder.utf8string(s) | ||||
| 		return integer(#s, 96) .. s; | ||||
| 	end | ||||
|  | ||||
| 	function encoder.string(s) | ||||
| 		if s:match "^[\0-\127]*$" then -- If string is entirely ASCII characters, then treat it as a UTF-8 string | ||||
| 			return encoder.utf8string(s) | ||||
| 		else | ||||
| 			return encoder.bytestring(s) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	function encoder.boolean(bool) | ||||
| 		return bool and "\245" or "\244"; | ||||
| 	end | ||||
|  | ||||
| 	encoder["nil"] = function() return "\246"; end | ||||
|  | ||||
| 	function encoder.userdata(ud, opts) | ||||
| 		local mt = dbg_getmetatable(ud); | ||||
| 		if mt then | ||||
| 			local encode_ud = opts and opts[mt] or mt.__tocbor; | ||||
| 			if encode_ud then | ||||
| 				return encode_ud(ud, opts); | ||||
| 			end | ||||
| 		end | ||||
| 		error "can't encode userdata"; | ||||
| 	end | ||||
|  | ||||
| 	function encoder.table(t, opts) | ||||
| 		local mt = getmetatable(t); | ||||
| 		if mt then | ||||
| 			local encode_t = opts and opts[mt] or mt.__tocbor; | ||||
| 			if encode_t then | ||||
| 				return encode_t(t, opts); | ||||
| 			end | ||||
| 		end | ||||
| 		-- the table is encoded as an array iff when we iterate over it, | ||||
| 		-- we see succesive integer keys starting from 1.  The lua | ||||
| 		-- language doesn't actually guarantee that this will be the case | ||||
| 		-- when we iterate over a table with successive integer keys, but | ||||
| 		-- due an implementation detail in PUC Rio Lua, this is what we | ||||
| 		-- usually observe.  See the Lua manual regarding the # (length) | ||||
| 		-- operator.  In the case that this does not happen, we will fall | ||||
| 		-- back to a map with integer keys, which becomes a bit larger. | ||||
| 		local array, map, i, p = { integer(#t, 128) }, { "\191" }, 1, 2; | ||||
| 		local is_array = true; | ||||
| 		for k, v in pairs(t) do | ||||
| 			is_array = is_array and i == k; | ||||
| 			i = i + 1; | ||||
|  | ||||
| 			local encoded_v = encode(v, opts); | ||||
| 			array[i] = encoded_v; | ||||
|  | ||||
| 			map[p], p = encode(k, opts), p + 1; | ||||
| 			map[p], p = encoded_v, p + 1; | ||||
| 		end | ||||
| 		-- map[p] = "\255"; | ||||
| 		map[1] = integer(i - 1, 160); | ||||
| 		return t_concat(is_array and array or map); | ||||
| 	end | ||||
|  | ||||
| 	-- Array or dict-only encoders, which can be set as __tocbor metamethod | ||||
| 	function encoder.array(t, opts) | ||||
| 		local array = { }; | ||||
| 		for i, v in ipairs(t) do | ||||
| 			array[i] = encode(v, opts); | ||||
| 		end | ||||
| 		return integer(#array, 128) .. t_concat(array); | ||||
| 	end | ||||
|  | ||||
| 	function encoder.map(t, opts) | ||||
| 		local map, p, len = { "\191" }, 2, 0; | ||||
| 		for k, v in pairs(t) do | ||||
| 			map[p], p = encode(k, opts), p + 1; | ||||
| 			map[p], p = encode(v, opts), p + 1; | ||||
| 			len = len + 1; | ||||
| 		end | ||||
| 		-- map[p] = "\255"; | ||||
| 		map[1] = integer(len, 160); | ||||
| 		return t_concat(map); | ||||
| 	end | ||||
| 	encoder.dict = encoder.map; -- COMPAT | ||||
|  | ||||
| 	function encoder.ordered_map(t, opts) | ||||
| 		local map = {}; | ||||
| 		if not t[1] then -- no predefined order | ||||
| 			local i = 0; | ||||
| 			for k in pairs(t) do | ||||
| 				i = i + 1; | ||||
| 				map[i] = k; | ||||
| 			end | ||||
| 			t_sort(map); | ||||
| 		end | ||||
| 		for i, k in ipairs(t[1] and t or map) do | ||||
| 			map[i] = encode(k, opts) .. encode(t[k], opts); | ||||
| 		end | ||||
| 		return integer(#map, 160) .. t_concat(map); | ||||
| 	end | ||||
|  | ||||
| 	encoder["function"] = function () | ||||
| 		error "can't encode function"; | ||||
| 	end | ||||
|  | ||||
| 	-- Decoder | ||||
| 	-- Reads from a file-handle like object | ||||
| 	local function read_bytes(fh, len) | ||||
| 		return fh:read(len); | ||||
| 	end | ||||
|  | ||||
| 	local function read_byte(fh) | ||||
| 		return fh:read(1):byte(); | ||||
| 	end | ||||
|  | ||||
| 	local function read_length(fh, mintyp) | ||||
| 		if mintyp < 24 then | ||||
| 			return mintyp; | ||||
| 		elseif mintyp < 28 then | ||||
| 			local out = 0; | ||||
| 			for _ = 1, 2 ^ (mintyp - 24) do | ||||
| 				out = out * 256 + read_byte(fh); | ||||
| 			end | ||||
| 			return out; | ||||
| 		else | ||||
| 			error "invalid length"; | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local decoder = {}; | ||||
|  | ||||
| 	local function read_type(fh) | ||||
| 		local byte = read_byte(fh); | ||||
| 		return b_rshift(byte, 5), byte % 32; | ||||
| 	end | ||||
|  | ||||
| 	local function read_object(fh, opts) | ||||
| 		local typ, mintyp = read_type(fh); | ||||
| 		return decoder[typ](fh, mintyp, opts); | ||||
| 	end | ||||
|  | ||||
| 	local function read_integer(fh, mintyp) | ||||
| 		return read_length(fh, mintyp); | ||||
| 	end | ||||
|  | ||||
| 	local function read_negative_integer(fh, mintyp) | ||||
| 		return -1 - read_length(fh, mintyp); | ||||
| 	end | ||||
|  | ||||
| 	local function read_string(fh, mintyp) | ||||
| 		if mintyp ~= 31 then | ||||
| 			return read_bytes(fh, read_length(fh, mintyp)); | ||||
| 		end | ||||
| 		local out = {}; | ||||
| 		local i = 1; | ||||
| 		local v = read_object(fh); | ||||
| 		while v ~= BREAK do | ||||
| 			out[i], i = v, i + 1; | ||||
| 			v = read_object(fh); | ||||
| 		end | ||||
| 		return t_concat(out); | ||||
| 	end | ||||
|  | ||||
| 	local function read_unicode_string(fh, mintyp) | ||||
| 		return read_string(fh, mintyp); | ||||
| 	end | ||||
|  | ||||
| 	local function read_array(fh, mintyp, opts) | ||||
| 		local out = {}; | ||||
| 		if mintyp == 31 then | ||||
| 			local i = 1; | ||||
| 			local v = read_object(fh, opts); | ||||
| 			while v ~= BREAK do | ||||
| 				out[i], i = v, i + 1; | ||||
| 				v = read_object(fh, opts); | ||||
| 			end | ||||
| 		else | ||||
| 			local len = read_length(fh, mintyp); | ||||
| 			for i = 1, len do | ||||
| 				out[i] = read_object(fh, opts); | ||||
| 			end | ||||
| 		end | ||||
| 		return out; | ||||
| 	end | ||||
|  | ||||
| 	local function read_map(fh, mintyp, opts) | ||||
| 		local out = {}; | ||||
| 		local k; | ||||
| 		if mintyp == 31 then | ||||
| 			local i = 1; | ||||
| 			k = read_object(fh, opts); | ||||
| 			while k ~= BREAK do | ||||
| 				out[k], i = read_object(fh, opts), i + 1; | ||||
| 				k = read_object(fh, opts); | ||||
| 			end | ||||
| 		else | ||||
| 			local len = read_length(fh, mintyp); | ||||
| 			for _ = 1, len do | ||||
| 				k = read_object(fh, opts); | ||||
| 				out[k] = read_object(fh, opts); | ||||
| 			end | ||||
| 		end | ||||
| 		return out; | ||||
| 	end | ||||
|  | ||||
| 	local tagged_decoders = {}; | ||||
|  | ||||
| 	local function read_semantic(fh, mintyp, opts) | ||||
| 		local tag = read_length(fh, mintyp); | ||||
| 		local value = read_object(fh, opts); | ||||
| 		local postproc = opts and opts[tag] or tagged_decoders[tag]; | ||||
| 		if postproc then | ||||
| 			return postproc(value); | ||||
| 		end | ||||
| 		return tagged(tag, value); | ||||
| 	end | ||||
|  | ||||
| 	local function read_half_float(fh) | ||||
| 		local exponent = read_byte(fh); | ||||
| 		local fraction = read_byte(fh); | ||||
| 		local sign = exponent < 128 and 1 or -1; -- sign is highest bit | ||||
|  | ||||
| 		fraction = fraction + (exponent * 256) % 1024; -- copy two(?) bits from exponent to fraction | ||||
| 		exponent = b_rshift(exponent, 2) % 32; -- remove sign bit and two low bits from fraction; | ||||
|  | ||||
| 		if exponent == 0 then | ||||
| 			return sign * m_ldexp(fraction, -24); | ||||
| 		elseif exponent ~= 31 then | ||||
| 			return sign * m_ldexp(fraction + 1024, exponent - 25); | ||||
| 		elseif fraction == 0 then | ||||
| 			return sign * m_huge; | ||||
| 		else | ||||
| 			return NaN; | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local function read_float(fh) | ||||
| 		local exponent = read_byte(fh); | ||||
| 		local fraction = read_byte(fh); | ||||
| 		local sign = exponent < 128 and 1 or -1; -- sign is highest bit | ||||
| 		exponent = exponent * 2 % 256 + b_rshift(fraction, 7); | ||||
| 		fraction = fraction % 128; | ||||
| 		fraction = fraction * 256 + read_byte(fh); | ||||
| 		fraction = fraction * 256 + read_byte(fh); | ||||
|  | ||||
| 		if exponent == 0 then | ||||
| 			return sign * m_ldexp(exponent, -149); | ||||
| 		elseif exponent ~= 0xff then | ||||
| 			return sign * m_ldexp(fraction + 2 ^ 23, exponent - 150); | ||||
| 		elseif fraction == 0 then | ||||
| 			return sign * m_huge; | ||||
| 		else | ||||
| 			return NaN; | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local function read_double(fh) | ||||
| 		local exponent = read_byte(fh); | ||||
| 		local fraction = read_byte(fh); | ||||
| 		local sign = exponent < 128 and 1 or -1; -- sign is highest bit | ||||
|  | ||||
| 		exponent = exponent %  128 * 16 + b_rshift(fraction, 4); | ||||
| 		fraction = fraction % 16; | ||||
| 		fraction = fraction * 256 + read_byte(fh); | ||||
| 		fraction = fraction * 256 + read_byte(fh); | ||||
| 		fraction = fraction * 256 + read_byte(fh); | ||||
| 		fraction = fraction * 256 + read_byte(fh); | ||||
| 		fraction = fraction * 256 + read_byte(fh); | ||||
| 		fraction = fraction * 256 + read_byte(fh); | ||||
|  | ||||
| 		if exponent == 0 then | ||||
| 			return sign * m_ldexp(exponent, -149); | ||||
| 		elseif exponent ~= 0xff then | ||||
| 			return sign * m_ldexp(fraction + 2 ^ 52, exponent - 1075); | ||||
| 		elseif fraction == 0 then | ||||
| 			return sign * m_huge; | ||||
| 		else | ||||
| 			return NaN; | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
|  | ||||
| 	if s_unpack then | ||||
| 		function read_float(fh) return s_unpack(">f", read_bytes(fh, 4)) end | ||||
| 		function read_double(fh) return s_unpack(">d", read_bytes(fh, 8)) end | ||||
| 	end | ||||
|  | ||||
| 	local function read_simple(fh, value, opts) | ||||
| 		if value == 24 then | ||||
| 			value = read_byte(fh); | ||||
| 		end | ||||
| 		if value == 20 then | ||||
| 			return false; | ||||
| 		elseif value == 21 then | ||||
| 			return true; | ||||
| 		elseif value == 22 then | ||||
| 			return null; | ||||
| 		elseif value == 23 then | ||||
| 			return undefined; | ||||
| 		elseif value == 25 then | ||||
| 			return read_half_float(fh); | ||||
| 		elseif value == 26 then | ||||
| 			return read_float(fh); | ||||
| 		elseif value == 27 then | ||||
| 			return read_double(fh); | ||||
| 		elseif value == 31 then | ||||
| 			return BREAK; | ||||
| 		end | ||||
| 		if opts and opts.simple then | ||||
| 			return opts.simple(value); | ||||
| 		end | ||||
| 		return simple(value); | ||||
| 	end | ||||
|  | ||||
| 	decoder[0] = read_integer; | ||||
| 	decoder[1] = read_negative_integer; | ||||
| 	decoder[2] = read_string; | ||||
| 	decoder[3] = read_unicode_string; | ||||
| 	decoder[4] = read_array; | ||||
| 	decoder[5] = read_map; | ||||
| 	decoder[6] = read_semantic; | ||||
| 	decoder[7] = read_simple; | ||||
|  | ||||
| 	-- opts.more(n) -> want more data | ||||
| 	-- opts.simple -> decode simple value | ||||
| 	-- opts[int] -> tagged decoder | ||||
| 	local function decode(s, opts) | ||||
| 		local fh = {}; | ||||
| 		local pos = 1; | ||||
|  | ||||
| 		local more; | ||||
| 		if type(opts) == "function" then | ||||
| 			more = opts; | ||||
| 		elseif type(opts) == "table" then | ||||
| 			more = opts.more; | ||||
| 		elseif opts ~= nil then | ||||
| 			error(("bad argument #2 to 'decode' (function or table expected, got %s)"):format(type(opts))); | ||||
| 		end | ||||
| 		if type(more) ~= "function" then | ||||
| 			function more() | ||||
| 				error "input too short"; | ||||
| 			end | ||||
| 		end | ||||
|  | ||||
| 		function fh:read(bytes) | ||||
| 			local ret = s:sub(pos, pos + bytes - 1); | ||||
| 			if #ret < bytes then | ||||
| 				ret = more(bytes - #ret, fh, opts); | ||||
| 				if ret then self:write(ret); end | ||||
| 				return self:read(bytes); | ||||
| 			end | ||||
| 			pos = pos + bytes; | ||||
| 			return ret; | ||||
| 		end | ||||
|  | ||||
| 		function fh:write(bytes) -- luacheck: no self | ||||
| 			s = s .. bytes; | ||||
| 			if pos > 256 then | ||||
| 				s = s:sub(pos + 1); | ||||
| 				pos = 1; | ||||
| 			end | ||||
| 			return #bytes; | ||||
| 		end | ||||
|  | ||||
| 		return read_object(fh, opts); | ||||
| 	end | ||||
|  | ||||
| 	return { | ||||
| 		-- en-/decoder functions | ||||
| 		encode = encode; | ||||
| 		decode = decode; | ||||
| 		decode_file = read_object; | ||||
|  | ||||
| 		-- tables of per-type en-/decoders | ||||
| 		type_encoders = encoder; | ||||
| 		type_decoders = decoder; | ||||
|  | ||||
| 		-- special treatment for tagged values | ||||
| 		tagged_decoders = tagged_decoders; | ||||
|  | ||||
| 		-- constructors for annotated types | ||||
| 		simple = simple; | ||||
| 		tagged = tagged; | ||||
|  | ||||
| 		-- pre-defined simple values | ||||
| 		null = null; | ||||
| 		undefined = undefined; | ||||
| 	}; | ||||
| end)() | ||||
|  | ||||
| local skynet = { | ||||
| 	server = "wss://osmarks.tk/skynet2/connect/", | ||||
| 	socket = nil, | ||||
| 	open_channels = {}, | ||||
| 	CBOR = CBOR | ||||
| } | ||||
|  | ||||
| function skynet.connect(force) | ||||
| 	if not skynet.socket or force then | ||||
| 		-- If we already have a socket and are throwing it away, close old one. | ||||
| 		if skynet.socket then skynet.socket.close() end | ||||
| 		local sock = http.websocket(skynet.server) | ||||
| 		if not sock then error "Skynet server unavailable, broken or running newer protocol version." end | ||||
| 		skynet.socket = sock | ||||
| 		 | ||||
| 		for _, c in pairs(skynet.open_channels) do | ||||
| 			skynet.open(c)	 | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function skynet.disconnect() | ||||
| 	if skynet.socket then skynet.socket.close() end | ||||
| end | ||||
|  | ||||
| local function value_in_table(t, v) | ||||
| 	for k, tv in pairs(t) do if tv == v then return true, k end end | ||||
| 	return false | ||||
| end | ||||
|  | ||||
| local function send_raw(data, tries) | ||||
| 	local tries = tries or 0 | ||||
| 	skynet.connect() | ||||
| 	local ok, err = pcall(skynet.socket.send, CBOR.encode(data), true) -- send in binary mode | ||||
| 	if not ok then | ||||
| 		if tries > 0 then sleep(tries) end | ||||
| 		if tries > 5 then error("Max reconnection attempts exceeded. " .. err) end | ||||
| 		pcall(skynet.connect, true) -- attempt to force reconnect | ||||
| 		send_raw(data, tries + 1) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- Opens the given channel | ||||
| function skynet.open(channel) | ||||
| 	-- Don't send unnecessary channel-open messages | ||||
| 	if not value_in_table(skynet.open_channels, channel) then | ||||
| 		send_raw { | ||||
| 			"open", | ||||
| 			channel | ||||
| 		} | ||||
| 		table.insert(skynet.open_channels, channel) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local function recv_one(filter) | ||||
| 	skynet.connect() | ||||
| 	while true do | ||||
| 		local contents = skynet.socket.receive() | ||||
| 		local result = CBOR.decode(contents) | ||||
| 		if type(result) == "table" then | ||||
| 			if result[1] == "error" then error(result[2] .. ": " .. result[3]) end | ||||
| 			if filter(result) then | ||||
| 				return result | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local function recv_message(channel) | ||||
| 	local m = recv_one(function(msg) | ||||
| 		return msg[1] == "message" and (channel == nil or msg[2].channel == channel) | ||||
| 	end) | ||||
| 	return m[2].channel, m[2].message, m[2] | ||||
| end | ||||
|  | ||||
| function skynet.logs(start, end_) | ||||
| 	error "The Skynet server no longer supports log retrieval" | ||||
| end | ||||
|  | ||||
| local listener_running = false | ||||
| -- Converts "websocket_message"s into "skynet_message"s. | ||||
| function skynet.listen(force_run) | ||||
| 	local function run() | ||||
| 		while true do | ||||
| 			os.queueEvent("skynet_message", recv_message())	 | ||||
| 		end | ||||
| 	end | ||||
| 	if not listener_running or force_run then | ||||
| 		local ok, err = pcall(run) | ||||
| 		listener_running = false | ||||
| 		if not ok then | ||||
| 			error(err) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- Receives one message on given channel | ||||
| -- Will open channel if it is not already open | ||||
| -- Returns the channel, message, and full message object | ||||
| function skynet.receive(channel) | ||||
| 	if channel then skynet.open(channel) end | ||||
| 	return recv_message(channel) | ||||
| end | ||||
|  | ||||
| -- Send given data on given channel | ||||
| -- Can accept a third argument - an object of extra metadata to send | ||||
| function skynet.send(channel, data, full) | ||||
| 	local obj = full or {} | ||||
| 	obj.message = data | ||||
| 	obj.channel = channel | ||||
| 	send_raw { | ||||
| 		"message", | ||||
| 		obj | ||||
| 	} | ||||
| end | ||||
|  | ||||
| return skynet | ||||
| Skynet is originally made by Gollark, and is a modem-like communications API that uses websockets for inter-server use. | ||||
| This version of Skynet has the CBOR API bundled. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 LDDestroier
					LDDestroier