mirror of
				https://github.com/LDDestroier/CC/
				synced 2025-10-31 15:32:59 +00:00 
			
		
		
		
	Create skynet
Skynet created by Gollark.
This commit is contained in:
		
							
								
								
									
										704
									
								
								netrequire/skynet
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										704
									
								
								netrequire/skynet
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,704 @@ | |||||||
|  | -- Skynet was created by Gollark | ||||||
|  | -- This version was modified to include CBOR in the same file | ||||||
|  |  | ||||||
|  | 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 | ||||||
		Reference in New Issue
	
	Block a user
	 LDDestroier
					LDDestroier