Advertisement
NonSequitur

wsclient.lua

Feb 1st, 2016
224
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 2.57 KB | None | 0 0
  1. package.loaded['websocket.bit'] = require'bit.numberlua'.bit
  2.  
  3. local sync = require'websocket.sync'
  4.  
  5. local Resumer = {}
  6. function Resumer.new(callback, thread)
  7.     return setmetatable({thread = thread, req = nil, data = '', callback = callback}, {__index = Resumer})
  8. end
  9.  
  10. function Resumer:resume(...)
  11.     return select(2, coroutine.resume(self.thread, ...))
  12. end
  13.  
  14. function Resumer:request(pattern)
  15.     self.req = pattern
  16. end
  17.  
  18. function Resumer:on_data(data)
  19.     self.data = self.data .. data
  20.     if self.req then
  21.         local vals
  22.         local ret, rest
  23.         if self.req == '*l' then
  24.             ret, rest = self.data:match('^(.-)\n(.+)$')
  25.             if not ret then
  26.                 ret, rest = self.data, ''
  27.             end
  28.  
  29.             if ret and coroutine.status(self.thread) ~= 'dead' then
  30.                 self.req = nil
  31.                 self.data = rest
  32.                 vals = {self:resume(ret)}
  33.             end
  34.         elseif type(self.req) == 'number' and coroutine.status(self.thread) ~= 'dead' then
  35.             if #self.data >= self.req then
  36.                 ret, rest = self.data:sub(1, self.req), self.data:sub(self.req + 1)
  37.                 self.req = nil
  38.                 self.data = rest
  39.                 vals = {self:resume(ret)}
  40.             end
  41.         end
  42.  
  43.         if vals and coroutine.status(self.thread) == 'dead' and self.callback then
  44.             self.callback(unpack(vals))
  45.         end
  46.     end
  47. end
  48.  
  49. local new = function(connect_callback, send_callback, receive_callback, close_callback)
  50.     local self = {}
  51.  
  52.     self.sock_connect = function(self, host, port)
  53.         self.sock = net.createConnection(net.TCP, 0)
  54.         self.sock:on("receive", function(sock, msg)
  55.             if self.resumer then
  56.                 self.resumer:on_data(msg)
  57.             end
  58.         end)
  59.        
  60.         self.sock:connect(port, host)
  61.     end
  62.  
  63.     self.sock_send = function(self, data)
  64.         return self.sock:send(data, send_callback)
  65.     end
  66.  
  67.     self.sock_receive = function(self, pattern, prefix)
  68.         if self.resumer then
  69.             self.resumer:request(pattern)
  70.             return coroutine.yield()
  71.         end
  72.     end
  73.  
  74.     self.sock_close = function(self)
  75.         self.sock:close()
  76.     end
  77.  
  78.     self = sync.extend(self)
  79.  
  80.     self.resumer = Resumer.new(
  81.         function(...)
  82.             connect_callback(...)
  83.  
  84.             local callback = function(...)
  85.                 receive_callback(...)
  86.                 self.resumer = Resumer.new(callback, coroutine.create(self.receive))
  87.                 self.resumer:resume(self)
  88.             end
  89.             self.resumer = Resumer.new(callback, coroutine.create(self.receive))
  90.             self.resumer:resume(self)
  91.         end,
  92.  
  93.         coroutine.create(self.connect)
  94.     )
  95.     self.connect = function(...)
  96.         self.resumer:resume(...)
  97.     end
  98.  
  99.     local close_resumer = Resumer.new(close_callback, coroutine.create(self.close))
  100.     self.close = function(...)
  101.         self.resumer = close_resumer
  102.         self.resumer:resume(...)
  103.     end
  104.  
  105.     return self
  106. end
  107.  
  108. return new
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement