Class: XRBP::WebSocket::Socket

Inherits:
Object
  • Object
show all
Defined in:
lib/xrbp/websocket/socket.rb

Overview

Low level wrapper around TCPSocket operations, providing mechanisms to negotiate base websocket connection.

Constant Summary collapse

DEFAULT_PORTS =
{:ws    => 80,
:http  => 80,
:wss   => 443,
:https => 443}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ Socket

Returns a new instance of Socket.



32
33
34
35
# File 'lib/xrbp/websocket/socket.rb', line 32

def initialize(client)
  @client      = client
  @pipe_broken = false
end

Instance Attribute Details

#clientObject

Returns the value of attribute client.



20
21
22
# File 'lib/xrbp/websocket/socket.rb', line 20

def client
  @client
end

#pipe_brokenObject (readonly)

Returns the value of attribute pipe_broken.



18
19
20
# File 'lib/xrbp/websocket/socket.rb', line 18

def pipe_broken
  @pipe_broken
end

Instance Method Details

#closeObject



75
76
77
# File 'lib/xrbp/websocket/socket.rb', line 75

def close
  socket.close if socket
end

#connectObject



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/xrbp/websocket/socket.rb', line 37

def connect
  uri = URI.parse client.url
  host = uri.host
  port = uri.port || DEFAULT_PORTS[uri.scheme.intern]

  @socket = TCPSocket.new(host, port)
  socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)

  init_ssl_socket if ['https', 'wss'].include? uri.scheme
  nil
end

#optionsObject



28
29
30
# File 'lib/xrbp/websocket/socket.rb', line 28

def options
  client.options
end

#read_next(dest) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/xrbp/websocket/socket.rb', line 105

def read_next(dest)
  begin
    read_sockets, _, _ = IO.select([socket], nil, nil, 0.1)

    if read_sockets && read_sockets[0]
      dest << socket.read_nonblock(1024)

      if socket.respond_to?(:pending) # SSLSocket
        dest << socket.read(socket.pending) while socket.pending > 0
      end
    end
  rescue IO::WaitReadable
    # No op

  rescue IO::WaitWritable
    IO.select(nil, [socket])
    retry
  end
end

#write(data) ⇒ Object



79
80
81
# File 'lib/xrbp/websocket/socket.rb', line 79

def write(data)
  socket.write data
end

#write_nonblock(data) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/xrbp/websocket/socket.rb', line 83

def write_nonblock(data)
  begin
    socket.write_nonblock(data)

  rescue IO::WaitReadable
    IO.select([socket]) # OpenSSL needs to read internally
    retry

  rescue IO::WaitWritable, Errno::EINTR
    IO.select(nil, [socket])
    retry

  rescue Errno::EPIPE => e
    @pipe_broken = true
    raise

  rescue OpenSSL::SSL::SSLError => e
    @pipe_broken = true
    raise
  end
end