Sha256: 40dd9d16541677d4c69b3062fc1608acd241cf2be41ace25e6db07b4c3abdbb1

Contents?: true

Size: 1.89 KB

Versions: 1

Compression:

Stored size: 1.89 KB

Contents

require 'digest/md5'

module EventMachine
  module WebSocket
    module Handshake76
      def handshake
        challenge_response = solve_challenge(
          request['Sec-WebSocket-Key1'],
          request['Sec-WebSocket-Key2'],
          request['Third-Key']
        )

        location  = "#{request['Host'].scheme}://#{request['Host'].host}"
        location << ":#{request['Host'].port}" if request['Host'].port
        location << request['Path']

        upgrade =  "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
        upgrade << "Upgrade: WebSocket\r\n"
        upgrade << "Connection: Upgrade\r\n"
        upgrade << "Sec-WebSocket-Location: #{location}\r\n"
        upgrade << "Sec-WebSocket-Origin: #{request['Origin']}\r\n"
        if protocol = request['Sec-WebSocket-Protocol']
          validate_protocol!(protocol)
          upgrade << "Sec-WebSocket-Protocol: #{protocol}\r\n"
        end
        upgrade << "\r\n"
        upgrade << challenge_response

        debug [:upgrade_headers, upgrade]

        return upgrade
      end

      private

      def solve_challenge(first, second, third)
        # Refer to 5.2 4-9 of the draft 76
        sum = [(extract_nums(first) / count_spaces(first))].pack("N*") +
          [(extract_nums(second) / count_spaces(second))].pack("N*") +
          third
        Digest::MD5.digest(sum)
      end

      def extract_nums(string)
        string.scan(/[0-9]/).join.to_i
      end

      def count_spaces(string)
        spaces = string.scan(/ /).size
        # As per 5.2.5, abort the connection if spaces are zero.
        raise HandshakeError, "Websocket Key1 or Key2 does not contain spaces - this is a symptom of a cross-protocol attack" if spaces == 0
        return spaces
      end

      def validate_protocol!(protocol)
        raise HandshakeError, "Invalid WebSocket-Protocol: empty" if protocol.empty?
        # TODO: Validate characters
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
em-websocket-0.2.0 lib/em-websocket/handshake76.rb