Class: EventMachine::RTMP::Handshake

Inherits:
ConnectionDelegate show all
Defined in:
lib/em-rtmp/handshake.rb

Constant Summary collapse

HANDSHAKE_VERSION =

The RTMP handshake involes each party sending 3 packets of data.

Client Server


0x03 -> 1536 random bytes (a) ->

                 <- 0x03
<- 1536 random bytes (b)

b ->

<- a

The handshake is completed by verifying that the response received matches the challenge string, with the notable exception that the first 4 bytes may be used for timestamping and can be different, and the second 4 bytes must all be zero.

0x03
HANDSHAKE_LENGTH =
1536

Instance Attribute Summary

Attributes inherited from ConnectionDelegate

#state

Instance Method Summary collapse

Methods inherited from ConnectionDelegate

#bytes_waiting, #change_state, #initialize, #read, #write

Methods included from IOHelpers

#read_bitfield, #read_double_be, #read_int29, #read_safe, #read_uint16_be, #read_uint24_be, #read_uint32_be, #read_uint32_le, #read_uint8, #write_bitfield, #write_double_be, #write_int29, #write_uint16_be, #write_uint24_be, #write_uint32_be, #write_uint32_le, #write_uint8

Constructor Details

This class inherits a constructor from EventMachine::RTMP::ConnectionDelegate

Instance Method Details

#buffer_changedObject

Handles a change to the buffer state

Returns a symbol indicating our state



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/em-rtmp/handshake.rb', line 29

def buffer_changed
  Logger.debug "#{state} #{bytes_waiting}"
  case state
  when :challenge_issued
    if bytes_waiting >= (1 + HANDSHAKE_LENGTH)
      handle_server_challenge
    end
  when :challenge_received
    if bytes_waiting >= HANDSHAKE_LENGTH
      handle_server_response
    end
  else
    raise HandshakeError, "Reached unexpected state"
  end

  state
end

#handle_server_challengeObject

Receives the server version byte and reissues it to the stream

Returns a state update



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/em-rtmp/handshake.rb', line 64

def handle_server_challenge
  Logger.debug "handling server challenge"

  server_version = read_uint8
  unless server_version == HANDSHAKE_VERSION
    raise HandshakeError, "Expected version byte to be 0x03"
  end

  server_challenge = read(HANDSHAKE_LENGTH)
  write server_challenge
  change_state :challenge_received
end

#handle_server_responseObject

Reads the server response to our challenge to authenticate peer

Returns a state update



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/em-rtmp/handshake.rb', line 80

def handle_server_response
  Logger.debug "handling client response"

  server_response = read(HANDSHAKE_LENGTH)
  unless server_response == @client_challenge
    raise HandshakeError, "Expected server to return client challenge"
  end

  Logger.debug "handshake complete"
  change_state :handshake_complete
end

#issue_challengeObject

Send the version byte followed by our challenge

Returns a state update



50
51
52
53
54
55
56
57
58
59
# File 'lib/em-rtmp/handshake.rb', line 50

def issue_challenge
  Logger.debug "issuing client challenge"

  @client_challenge = "\x00\x00\x00\x00\x00\x00\x00\x00" + (8...HANDSHAKE_LENGTH).map{rand(255)}.pack('C*')

  write_uint8 HANDSHAKE_VERSION
  write @client_challenge

  change_state :challenge_issued
end