From bdb8b91e1ff4b6dec703d857484170bde1c61669 Mon Sep 17 00:00:00 2001 From: MrZ626 <1046101471@qq.com> Date: Fri, 12 Feb 2021 22:24:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86ws=E5=BA=93=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Zframework/websocket.lua | 210 ++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 111 deletions(-) diff --git a/Zframework/websocket.lua b/Zframework/websocket.lua index b32d0c69..17f78dc1 100644 --- a/Zframework/websocket.lua +++ b/Zframework/websocket.lua @@ -1,135 +1,123 @@ --[[ -websocket client pure lua implement for love2d -by flaribbit + websocket client pure lua implement for love2d + by flaribbit -usage: - local client = require("websocket").new() - client:connect("127.0.0.1", 5000) - client:settimeout(0) - client:send("hello from love2d") - print(client:read()) - client:close() + usage: + local client = require("websocket").new() + client:connect("127.0.0.1", 5000) + client:settimeout(0) + client:send("hello from love2d") + print(client:read()) + client:close() ]] +-- local debug_print=print local socket = require"socket" local bit = require"bit" -local band = bit.band -local bor = bit.bor -local bxor = bit.bxor -local shl = bit.lshift -local shr = bit.rshift - --- local log_debug = print -local log_debug = function()end -local b2s = function(b)return b and"true"or"false"end +local band, bor, bxor = bit.band, bit.bor, bit.bxor +local shl, shr = bit.lshift, bit.rshift local OPCODES = { - ["CONTINUE"]=0, - ["TEXT"] =1, - ["BINARY"] =2, - ["CLOSE"] =8, - ["PING"] =9, - ["PONG"] =10, + CONTINUE=0, + TEXT =1, + BINARY =2, + CLOSE =8, + PING =9, + PONG =10, } local _M = { - OPCODES = OPCODES, + OPCODES = OPCODES, } _M.__index = _M -_M.new = function() - local m = {} - setmetatable(m, _M) - return m +function _M.new() + local m = {} + setmetatable(m, _M) + return m end -_M.connect = function(self, host, port, path) - local socket = socket.tcp() - self.socket = socket - local res, err = socket:connect(host, port) - if res~=1 then - return res, err - end - log_debug("[handshake] connected") - -- WebSocket handshake - local seckey = "osT3F7mvlojIvf3/8uIsJQ==" - path = path or "/" - res, err = socket:send("GET "..path.." HTTP/1.1\r\nHost: "..host..":"..port.."\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: "..seckey.."\r\n\r\n") - repeat - res = socket:receive("*l") - until res=="" - log_debug("[handshake] succeed") +local seckey = "osT3F7mvlojIvf3/8uIsJQ==" +function _M.connect(self, host, port, path) + local SOCK = socket.tcp() + self.socket = SOCK + local res, err = SOCK:connect(host, port) + if res~=1 then return res, err end + -- debug_print("[handshake] connected") + + -- WebSocket handshake + res, err = SOCK:send("GET "..(path or"/").." HTTP/1.1\r\nHost: "..host..":"..port.."\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: "..seckey.."\r\n\r\n") + repeat res = SOCK:receive("*l") until res=="" + -- debug_print("[handshake] succeed") end -_M.send = function(self, message) - local socket = self.socket - local mask_key = {1, 14, 5, 14} - -- message type - socket:send(string.char(bor(0x80, OPCODES.BINARY))) - -- length - local length = #message - log_debug("[encode] message length: "..length) - if length>65535 then - socket:send(string.char(bor(127, 0x80), 0, 0, 0, 0, - band(shr(length, 24), 0xff), - band(shr(length, 16), 0xff), - band(shr(length, 8), 0xff), - band(length, 0xff))) - elseif length>125 then - socket:send(string.char(bor(126, 0x80), - band(shr(length, 8), 0xff), - band(length, 0xff))) - else - socket:send(string.char(bor(length, 0x80))) - end - log_debug("[encode] masking") - socket:send(string.char(unpack(mask_key))) - local msgbyte = {message:byte(1, length)} - for i = 1, length do - msgbyte[i] = bxor(msgbyte[i], mask_key[(i-1)%4+1]) - end - socket:send(string.char(unpack(msgbyte))) - log_debug("[encode] end") +function _M.send(self, message) + local SOCK = self.socket + local mask_key = {1, 14, 5, 14} + + -- message type + SOCK:send(string.char(bor(0x80, OPCODES.BINARY))) + + -- length + local length = #message + -- debug_print("[encode] message length: "..length) + if length>65535 then + SOCK:send(string.char(bor(127, 0x80), 0, 0, 0, 0, + band(shr(length, 24), 0xff), + band(shr(length, 16), 0xff), + band(shr(length, 8), 0xff), + band(length, 0xff))) + elseif length>125 then + SOCK:send(string.char(bor(126, 0x80), + band(shr(length, 8), 0xff), + band(length, 0xff))) + else + SOCK:send(string.char(bor(length, 0x80))) + end + -- debug_print("[encode] masking") + SOCK:send(string.char(unpack(mask_key))) + local msgbyte = {message:byte(1, length)} + for i = 1, length do + msgbyte[i] = bxor(msgbyte[i], mask_key[(i-1)%4+1]) + end + SOCK:send(string.char(unpack(msgbyte))) + -- debug_print("[encode] end") end -_M.read = function(self) - -- byte 0-1 - local socket = self.socket - local res, err = socket:receive(2) - if res==nil then - return res, err - end - local byte = res:byte() - local flag_FIN = byte>=0x80 - local OPCODE = band(byte, 0x0f) - byte = res:byte(2) - local flag_MASK = byte>=0x80 - log_debug("[decode] FIN="..b2s(flag_FIN)..", OPCODE="..OPCODE..", MASK="..b2s(flag_MASK)) - -- length - local length = band(byte, 0x7f) - if length==126 then - res = socket:receive(2) - local b1, b2 = res:byte(1, 2) - length = shl(b1, 8) + b2 - elseif length==127 then - res = socket:receive(8) - local b = {res:byte(1, 8)} - length = shl(b[5], 32) + shl(b[6], 24) + shl(b[7], 8) + b[8] - end - log_debug("[decode] message length: "..length) - -- data - res = socket:receive(length) - log_debug("[decode] string length: "..#res) - log_debug("[decode] end") - return res +function _M.read(self) + -- byte 0-1 + local SOCK = self.socket + local res, err = SOCK:receive(2) + if res==nil then return res, err end + + -- local flag_FIN = res:byte()>=0x80 + -- local OPCODE = band(res:byte(), 0x0f) + -- local flag_MASK = res:byte(2)>=0x80 + -- debug_print("[decode] FIN="..tostring(flag_FIN)..", OPCODE="..OPCODE..", MASK="..tostring(flag_MASK)) + + -- length + local byte = res:byte(2) + local length = band(byte, 0x7f) + if length==126 then + res = SOCK:receive(2) + local b1, b2 = res:byte(1, 2) + length = shl(b1, 8) + b2 + elseif length==127 then + res = SOCK:receive(8) + local b = {res:byte(1, 8)} + length = shl(b[5], 32) + shl(b[6], 24) + shl(b[7], 8) + b[8] + end + -- debug_print("[decode] message length: "..length) + + -- data + res = SOCK:receive(length) + -- debug_print("[decode] string length: "..#res) + -- debug_print("[decode] end") + return res end -_M.close = function(self) - self.socket:close() -end +function _M.close(self) self.socket:close() end -_M.settimeout = function(self, t) - self.socket:settimeout(t) -end +function _M.settimeout(self, t) self.socket:settimeout(t) end -return _M +return _M \ No newline at end of file