qws
Version:
An HTML5 Web Sockets Server Module
138 lines (120 loc) • 3.17 kB
text/coffeescript
os = require 'options-stream'
zlib = require 'zlib'
{EventEmitter} = require 'events'
{unpack, inflate, Frame} = require './frame'
class Message extends EventEmitter
constructor : (, options)->
# http can only be use one time
= os {
deflate : true
min_deflate_length : 32
close_timeout : 100
}, options
frame = null
{ socket } = @
= zlib.createInflateRaw chunkSize : 128 * 1024
socket.on 'data', (chunk)=>
# first chunk
# if frame is null
while chunk and chunk.length
[frame, chunk] = unpack chunk, frame
# 2+ chunks
# else
# [frame, buf] = unpack chunk, frame
# if done
if frame.done
# decompress
inflate frame, , (err, f) =>
return 'error', err if err
# emit event
f
# reset frame
frame = null
socket.on 'error', (err)=>
'error', err
socket.on 'close', =>
'close'
write : (data, opcode, mask, cb) ->
# mask
if typeof mask is 'function'
cb = mask
mask = null
# opcode
switch typeof opcode
when 'function'
cb = opcode
opcode = null
when 'boolean'
mask = opcode
opcode = null
# text frame as defalut
opcode ?= 'text'
# no mask as defalut
mask ?= false
# data is frame
# if data instanceof Frame
# frame = data
# else
frame = new Frame
data : data
opcode : opcode
fin : true
mask : mask
minDeflateLength : .min_deflate_length
# pack
frame.pack .deflate, (err, bin) =>
if err
cb err if cb
return
# write
.write bin
cb null if cb
return
ping : (cb)->
'', 'ping', false, cb
return
pong : (cb)->
'', 'pong', false, cb
return
continue : (cb)->
'', 'continue', false, cb
return
writeRaw : (bin) ->
.write bin
end : (data, opcode, mask)->
if data?
data, opcode, mask, =>
else
return
close : ->
closed = false
'', 'close', false, =>
.on 'close', (err)=>
clearTimeout timer
closed = true
'closed', err
timer = setTimeout =>
return if closed
.end()
, .close_timeout
onFrame : (frame) ->
switch frame.opcode
when 'text' then 'message', frame.data.toString(), @
when 'binary' then 'message', frame.data, @
when 'ping' then 'ping'
when 'pong' then 'pong'
when 'close'
.end()
'close'
when 'continue' then 'continue'
# else 'control', frame.opcode
return
reset : (options) ->
= os , options
= options.cb
errorHandle : (msg) ->
msg if msg
exports.Message = Message