Class: ACIrb::EventChannel

Inherits:
Object
  • Object
show all
Defined in:
lib/events.rb

Overview

Event channel interface

Defined Under Namespace

Classes: ApicWebSocketRecvTimeout, WebSocketNoHandshake

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rest, _options = {}) ⇒ EventChannel

Returns a new instance of EventChannel.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/events.rb', line 21

def initialize(rest, _options = {})
  @rest = rest

  uri = URI.parse(@rest.baseurl)

  if uri.scheme == 'https'
    scheme = 'wss'
    secure = true
  else
    scheme = 'ws'
    secure = false
  end

  url = '%s://%s/socket%s' % [scheme, uri.host, rest.auth_cookie]

  @handshake = WebSocket::Handshake::Client.new(url: url)
  @frame = WebSocket::Frame::Incoming::Server.new(version: @handshake.version)

  @socket = TCPSocket.new(@handshake.host, uri.port)

  if secure
    puts 'connecting over secure websocket'
    ctx = OpenSSL::SSL::SSLContext.new

    ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE unless rest.verify

    ssl_sock = OpenSSL::SSL::SSLSocket.new(@socket, ctx)
    ssl_sock.sync_close = true
    ssl_sock.connect

    @transport_socket = @socket
    @socket = ssl_sock
  else
    @transport_socket = nil
  end

  @socket.write(@handshake.to_s)
  @socket.flush

  loop do
    data = @socket.getc
    next if data.nil?

    @handshake << data

    if @handshake.finished?
      fail @handshake.error.to_s unless @handshake.valid?
      @handshaked = true
      break
    end
  end
end

Instance Attribute Details

#restObject

Returns the value of attribute rest.



13
14
15
# File 'lib/events.rb', line 13

def rest
  @rest
end

Instance Method Details

#closeObject



118
119
120
# File 'lib/events.rb', line 118

def close
  @socket.close
end

#receive(timeout = nil) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/events.rb', line 86

def receive(timeout = nil)
  fail WebSocketNoHandshake unless @handshaked

  readable, writable, error = IO.select([@socket], nil, nil, timeout)
  if readable
    begin
      data = @socket.read_nonblock(1024)
    rescue Errno::EAGAIN, Errno::EWOULDBLOCK, (IO::WaitReadable if defined?(IO::WaitReadable)) => e
      puts '%s, retrying' % e
      retry
    end
  else
    fail ApicWebSocketRecvTimeout, 'Timeout for websocket read'
  end
  @frame << data

  messages = []
  while message = @frame.next
    if message.type === :ping
      send(message.data, :pong)
      return messages
    end
    messages << message.to_s
  end

  events = []
  messages.each do |msg|
    events += MoEvent.parse_event(self, msg.to_s)
  end
  events
end

#send(data, type = :text) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/events.rb', line 74

def send(data, type = :text)
  fail WebSocketNoHandshake unless @handshaked

  data = WebSocket::Frame::Outgoing::Client.new(
    version: @handshake.version,
    data: data,
    type: type
  ).to_s
  @socket.write data
  @socket.flush
end