Class: EventMachine::WebSocketCodec::Handshake

Inherits:
Object
  • Object
show all
Defined in:
lib/em-ws-client/handshake.rb

Overview

Internal: Responsbile for generating the request and validating the response

Defined Under Namespace

Classes: HandshakeError

Constant Summary collapse

Status =
/^HTTP\/1.1 (\d+)/i.freeze
Header =
/^([^:]+):\s*(.+)$/i.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, origin = "em-ws-client") ⇒ Handshake

Returns a new instance of Handshake.



16
17
18
19
20
21
22
23
# File 'lib/em-ws-client/handshake.rb', line 16

def initialize uri, origin="em-ws-client"
  @uri = uri
  @origin = origin
  @buffer = ""
  @complete = false
  @valid = false
  @extra = ""
end

Instance Attribute Details

#extraObject

Returns the value of attribute extra.



14
15
16
# File 'lib/em-ws-client/handshake.rb', line 14

def extra
  @extra
end

Instance Method Details

#<<(data) ⇒ Object



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
# File 'lib/em-ws-client/handshake.rb', line 39

def << data
  @buffer << data

  if @buffer.index "\r\n\r\n"

    response, @extra = @buffer.split("\r\n\r\n", 2)

    lines = response.split "\r\n"

    if Status =~ lines.shift
      if $1.to_i != 101
        raise HandshakeError.new "Received code #{$1}"
      end
    end

    table = {}
    lines.each do |line|
      header = /^([^:]+):\s*(.+)$/.match(line)
      table[header[1].downcase.strip] = header[2].strip if header
    end

    @complete = true
    if table["sec-websocket-accept"] == response_key
      @valid = true
    else
      raise HandshakeError.new "Invalid Sec-Websocket-Accept"
    end
  end
end

#complete?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/em-ws-client/handshake.rb', line 69

def complete?
  @complete
end

#hostObject



77
78
79
# File 'lib/em-ws-client/handshake.rb', line 77

def host
  @uri.host + (@uri.port ? ":#{@uri.port}" : "")
end

#pathObject



81
82
83
# File 'lib/em-ws-client/handshake.rb', line 81

def path
  (@uri.path.empty? ? "/" : @uri.path) + (@uri.query ? "?#{@uri.query}" : "")
end

#requestObject



25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/em-ws-client/handshake.rb', line 25

def request
  headers = ["GET #{path} HTTP/1.1"]
  headers << "Connection: keep-alive, Upgrade"
  headers << "Host: #{host}"
  headers << "Sec-WebSocket-Key: #{request_key}"
  headers << "Sec-WebSocket-Version: 13"
  headers << "Origin: #{@origin}"
  headers << "Upgrade: websocket"
  headers << "User-Agent: em-ws-client"
  headers << "\r\n"

  headers.join "\r\n"
end

#request_keyObject

Build a unique request key to match against



86
87
88
# File 'lib/em-ws-client/handshake.rb', line 86

def request_key
  @request_key ||= SecureRandom::base64
end

#response_keyObject

Build the response key from the given request key for comparison with the response value.



92
93
94
# File 'lib/em-ws-client/handshake.rb', line 92

def response_key
  Base64.encode64(Digest::SHA1.digest("#{request_key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11")).chomp
end

#valid?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/em-ws-client/handshake.rb', line 73

def valid?
  @valid
end