Skip to content

Instantly share code, notes, and snippets.

@ezmobius
Created February 5, 2011 04:33
Show Gist options
  • Save ezmobius/812206 to your computer and use it in GitHub Desktop.
Save ezmobius/812206 to your computer and use it in GitHub Desktop.
MSG = /^MSG\s+(\S+)\s+(\S+)\s+((\S+)\s+)?(\d+)$/i #:nodoc:
OK = /^\+OK/i #:nodoc:
ERR = /^-ERR\s+('.+')?/i #:nodoc:
PING = /^PING/i #:nodoc:
PONG = /^PONG/i #:nodoc:
INFO = /^INFO\s+(.+)/i #:nodoc:
# Responses
CR_LF = ("\r\n".freeze) #:nodoc:
CR_LF_SIZE = (CR_LF.bytesize) #:nodoc:
PING_REQUEST = ("PING#{CR_LF}".freeze) #:nodoc:
PONG_RESPONSE = ("PONG#{CR_LF}".freeze) #:nodoc:
EMPTY_MSG = (''.freeze) #:nodoc:
def receive_data(data) #:nodoc:
(@buf ||= '') << data
while (@buf && [email protected]?)
if (@needed && @buf.bytesize >= @needed + CR_LF_SIZE)
payload = @buf.slice(0, @needed)
on_msg(@sub, @sid, @reply, payload)
@buf = @buf.slice((@needed + CR_LF_SIZE), @buf.bytesize)
@sub = @sid = @reply = @needed = nil
elsif @buf =~ /^(.*)\r\n/ # Process a control line
@buf = $'
op = $1
case op
when MSG
@sub, @sid, @reply, @needed = $1, $2.to_i, $4, $5.to_i
when OK # No-op right now
when ERR
@err_cb = proc { raise Error, "Error received from server :#{$1}."} unless user_err_cb?
err_cb.call($1)
when PING
send_command(PONG_RESPONSE)
when PONG
cb = @pongs.shift
cb.call if cb
when INFO
process_info($1)
end
else # Waiting for additional data
return
end
end
end
-- Protocol metatable
local protocol_mt = {
msg = re.new([[(MSG)\s+(\S+)\s+(\S+)\s+((\S+)\s+)?(\d+)]], 'i'),
ok = re.new([[(\+OK)]], 'i'),
err = re.new([[(-ERR)\s+('.+')?]], 'i'),
ping = re.new("(PING)", 'i'),
pong = re.new("(PONG)", 'i'),
info = re.new([[(INFO)\s+(.+)]], 'i'),
ctrl_line = re.new([[(.*)\r\n]], 'i'),
cr_lf = "\r\n",
cr_lf_size = bytesize("\r\n"),
ping_request = "PING" .. '\r\n',
pong_request = "PONG" .. '\r\n',
empty_msg = '',
}
local buf = ""
local eom = nil
local ops = nil
local op = nil
local _ = nil
local payload = nil
local needed = nil
function process_data(data)
buf = buf .. data
print("my buf:\n" .. buf)
while buf and string.len(buf) > 0 do
-- print('---------------')
--print(buf)
-- local _, eom, ops = proto.ctrl_line:tfind(buf, 1)
-- local buf_lst = make_list(buf)
-- local res = buf_lst:slice(eom, bytesize(buf))
-- buf = make_string(res)
-- print(buf)
-- print('---------------')
if needed then
if bytesize(buf) >= (needed + proto.cr_lf_size) then
print('in msg if')
local buf_list = make_list(buf)
payload = buf_list:slice(0, needed)
on_msg(sub, sid, reply, make_string(payload))
buf_list = make_list(buf)
buf = buf_list:slice(bytesize(needed .. cr_lf_size), bytesize(buf))
buf = make_string(buf)
sub = nil
sid = nil
reply = nil
needed = nil
ops = nil
op = nil
end
elseif (_, eom, ops) = (re.new([[(.*)\r\n]], 'i')):tfind(buf, 1) then
local op = ops[1]
-- print(op)
if op == "MSG" then
local _, _, msg = proto.msg:tfind(buf, 1)
pretty.dump(msg)
sub, sid, reply, needed = msg[1], msg[2], msg[4], msg[5]
elseif op == "+OK" then
local _, _, ok = proto.ok:tfind(buf, 1)
-- no-op
return
elseif op == "-ERR" then
local _, _, err = proto.err:tfind(buf, 1)
print(err[1])
return
elseif op == "PING" then
local _, _, ping = proto.ping:tfind(buf, 1)
client.send(proto.pong_request)
return
elseif op == "PONG" then
local _, _, pong = proto.pong:tfind(buf, 1)
client.send(proto.ping_request)
return
elseif op == "INFO" then
local _, _, info = proto.info:tfind(buf, 1)
server_info = json.encode(info)
print('info:')
pretty.dump(server_info)
return
end
else
return
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment