class Forward::Socket
Constants
- ACTIVITY_TIMEOUT
- HEART_BEAT_INTERVAL
- WATCH_INTERVAL
Public Class Methods
new(tunnel)
click to toggle source
# File lib/forward/socket.rb, line 8 def initialize(tunnel) @tunnel = tunnel @socket = Faye::WebSocket::Client.new(@tunnel.tunneler) @socket.on :open do |event| logger.debug '[socket] open' send(type: 'tunnel:identify', tunnelId: @tunnel.id) end @socket.on :message do |event| receive(event.data) end @socket.on :close do |event| logger.debug "[socket] close - code: #{event.code} reason: #{event.reason}" if @tunnel.open? exit_with_message "Your tunnel has been disconnected" else @tunnel.destroy { exit_with_error "Unable to open tunnel, please contact us at #{SUPPORT_EMAIL}" } end end @socket.on :error do |event| logger.debug "[socket] error #{event.inspect}" end end
Public Instance Methods
send(message, data = nil)
click to toggle source
# File lib/forward/socket.rb, line 34 def send(message, data = nil) @socket.send(pack(message, data)) end
Private Instance Methods
beat()
click to toggle source
# File lib/forward/socket.rb, line 86 def beat EM.add_periodic_timer(HEART_BEAT_INTERVAL) do logger.debug "[heartbeat] lub" send(type: 'heartbeat:lub') end end
pack(message, data = nil)
click to toggle source
# File lib/forward/socket.rb, line 105 def pack(message, data = nil) message = message.is_a?(String) ? message : message.to_json message.encode!('utf-16le') bytes = Array(message.bytesize).pack('v').bytes.to_a bytes += message.bytes.to_a bytes += data.bytes.to_a unless data.nil? bytes end
receive(data)
click to toggle source
# File lib/forward/socket.rb, line 40 def receive(data) message, data = unpack(data) logger.debug "[socket] #{message[:type]}" @tunnel.track_activity! if message[:type] == 'tunnel:ready' @tunnel.ready! beat watch return end if message[:type] == 'tunnel:notfound' logger.debug "[socket] tunnel not found" exit_with_message "Unable to open tunnel, please contact us at #{SUPPORT_EMAIL}" end if message[:type] == 'notification' puts message[:message] return end if message[:type] == 'request:start' logger.debug "[request] start #{message[:url]}" request = Request.new(@tunnel, message) @tunnel.requests[request.id] = request return end request = @tunnel.requests[message[:id]] return if request.nil? if message[:type] == 'request:data' logger.debug '[request] data' request << data end if message[:type] == 'request:end' logger.debug '[request] end' request.process end end
unpack(bytes)
click to toggle source
# File lib/forward/socket.rb, line 116 def unpack(bytes) bytes = bytes.pack('C*') message_size = bytes.unpack('v')[0] message = bytes.byteslice(2, message_size).force_encoding('utf-16le') binary_offset = 2 + message_size [JSON.parse(message, symbolize_names: true), bytes.byteslice(binary_offset..-1)] end
watch()
click to toggle source
# File lib/forward/socket.rb, line 93 def watch EM.add_periodic_timer(WATCH_INTERVAL) do logger.debug "[socket] checking activity" inactive_for = Time.now.to_i - @tunnel.last_active_at if inactive_for > ACTIVITY_TIMEOUT logger.debug "[socket] closing due to inactivity (heartbeats and requests)" @socket.close end end end