websocket-client 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.dirname(__FILE__) + '/../lib'
4
+
5
+ require 'websocket_client'
6
+
7
+ ## Create a disconnected client
8
+ client = WebSocketClient.create( 'ws://localhost:8081/websockets/' )
9
+
10
+ ## Set up the message handler before connecting
11
+ client.on_message do |msg|
12
+ puts "received #{msg}"
13
+ end
14
+
15
+ ## Connect
16
+ client.connect()
17
+
18
+ ## Use the connected client
19
+ puts "sending"
20
+ client.send( "HOWDY-1" )
21
+ client.send( "HOWDY-2" )
22
+ client.send( "HOWDY-3" )
23
+ sleep(1)
24
+
25
+ ## Explicit disconncet
26
+ client.disconnect
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.dirname(__FILE__) + '/../lib'
4
+
5
+ require 'websocket_client'
6
+
7
+ ## Create a disconnected client
8
+ WebSocketClient.create( 'ws://localhost:8081/websockets/' ) do |client|
9
+
10
+ ## Set up the message handler before connecting
11
+ client.on_message do |msg|
12
+ puts "received #{msg}"
13
+ end
14
+
15
+ ## Connect
16
+ client.connect() do |client|
17
+
18
+ ## Use the connected client
19
+ puts "sending"
20
+ client.send( "HOWDY-1" )
21
+ client.send( "HOWDY-2" )
22
+ client.send( "HOWDY-3" )
23
+ sleep(1)
24
+ end
25
+
26
+ ## Disconnected
27
+ end
@@ -0,0 +1,111 @@
1
+ require 'socket'
2
+ require 'uri'
3
+ require 'websocket_client/ietf_00'
4
+
5
+
6
+ module WebSocketClient
7
+
8
+ DEFAULT_HANDSHAKE = Ietf00
9
+
10
+ class DebugSocket
11
+ def initialize(socket)
12
+ @socket = socket
13
+ end
14
+
15
+ def method_missing(method, *args)
16
+ puts "> #{method}(#{args.join( ', ')})"
17
+ @socket.__send__( method, *args )
18
+ end
19
+ end
20
+
21
+ def self.create(uri,handshake_class=WebSocketClient::DEFAULT_HANDSHAKE,&block)
22
+ Client.new(uri, handshake_class, &block)
23
+ end
24
+
25
+ class Client
26
+ attr_reader :uri
27
+
28
+ def initialize(uri,handshake_class=WebSocketClient::DEFAULT_HANDSHAKE, &block)
29
+ @handshake_class = handshake_class
30
+ @socket = nil
31
+ @on_message_handler = nil
32
+ @handler_thread = nil
33
+ @close_state = nil
34
+ case ( uri )
35
+ when String
36
+ @uri = URI.parse( uri )
37
+ else
38
+ @uri = uri
39
+ end
40
+ block.call( self ) if block
41
+ end
42
+
43
+ def connect(&block)
44
+ @socket = TCPSocket.open(uri.host, uri.port)
45
+ @handshake = @handshake_class.new( uri, @socket )
46
+
47
+ start_handler
48
+
49
+ if ( block )
50
+ begin
51
+ block.call( self )
52
+ ensure
53
+ disconnect()
54
+ end
55
+ end
56
+ end
57
+
58
+ def disconnect
59
+ @socket.puts 0xFF
60
+ @socket.putc 0x00
61
+ @close_state = :requested
62
+ end
63
+
64
+ def send(msg)
65
+ @socket.print @handshake.encode_text_message( msg )
66
+ @socket.flush
67
+ end
68
+
69
+ def wait_forever()
70
+ @handler_thread.join
71
+ end
72
+
73
+ def on_message(msg=nil,&block)
74
+ if ( block )
75
+ @on_message_handler = block
76
+ else
77
+ @on_message_handler.call( msg ) if @on_message_handler
78
+ end
79
+ end
80
+
81
+ def start_handler
82
+ @handler_thread = Thread.new(@socket) do |socket|
83
+ msg = ''
84
+ while ( ! socket.eof? )
85
+ c = socket.getc
86
+ if ( c == 0x00 )
87
+ if ( @close_state == :half_closed )
88
+ socket.close
89
+ break;
90
+ else
91
+ msg = ''
92
+ end
93
+ elsif ( c == 0xFF )
94
+ if ( @close_state == :requested )
95
+ @close_state = :half_closed
96
+ else
97
+ on_message( msg )
98
+ end
99
+ else
100
+ if ( @close_state != nil )
101
+ @close_state = nil
102
+ end
103
+ msg << c
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ end
110
+ end
111
+
@@ -0,0 +1,90 @@
1
+ require 'socket'
2
+ require 'uri'
3
+ require 'digest/md5'
4
+
5
+ module WebSocketClient
6
+
7
+ class Ietf00
8
+
9
+ def initialize(uri, socket)
10
+ @socket = socket
11
+ key1, key2, key3, solution = generate_keys()
12
+
13
+ @socket.puts "GET #{uri.path} HTTP/1.1"
14
+ @socket.puts "Host: #{uri.host}"
15
+ @socket.puts "Connection: upgrade"
16
+ @socket.puts "Upgrade: websocket"
17
+ @socket.puts "Origin: http://#{uri.host}/"
18
+ @socket.puts "Sec-WebSocket-Version: 8"
19
+ @socket.puts "Sec-WebSocket-Key1: #{key1}"
20
+ @socket.puts "Sec-WebSocket-Key2: #{key2}"
21
+ @socket.puts ""
22
+ @socket.print key3
23
+ @socket.puts ""
24
+ @socket.flush
25
+
26
+ while ( ! @socket.eof? )
27
+ line = @socket.gets
28
+ break if ( line.strip == '' )
29
+ end
30
+ challenge = @socket.read( 16 )
31
+ if ( challenge == solution )
32
+ puts "success!"
33
+ end
34
+ #dump 'solution', solution
35
+ #dump 'challenge', challenge
36
+ end
37
+
38
+ def encode_text_message(msg)
39
+ @socket.putc 0x00
40
+ @socket.print msg
41
+ @socket.putc 0xFF
42
+ @socket.flush
43
+ end
44
+
45
+ def generate_keys()
46
+ key1 = generate_header_key
47
+ key2 = generate_header_key
48
+ key3 = generate_content_key
49
+ [ key1, key2, key3, solve( key1, key2, key3 ) ]
50
+ end
51
+
52
+ def solve(key1, key2, key3)
53
+ int1 = solve_header_key( key1 )
54
+ int2 = solve_header_key( key2 )
55
+ input = int1.to_s + int2.to_s + key3
56
+ Digest::MD5.digest( input )
57
+ end
58
+
59
+ def solve_header_key(key)
60
+ key_digits = key.strip.gsub( /[^0-9]/, '').to_i
61
+ key_spaces = key.strip.gsub( /[^ ]/, '').size
62
+ solution = key_digits / key_spaces
63
+ solution
64
+ end
65
+
66
+ def generate_header_key
67
+ key = ''
68
+ 1.upto(32) do
69
+ key << rand(90) + 32
70
+ end
71
+ 1.upto( rand(10) + 2 ) do
72
+ key[rand(key.size-1)+1,1] = ' '
73
+ end
74
+ 1.upto( rand(10) + 2 ) do
75
+ key[rand(key.size-1)+1,1] = rand(9).to_s
76
+ end
77
+ key
78
+ end
79
+
80
+ def generate_content_key
81
+ key = []
82
+ 'tacobob1'.each_byte do |byte|
83
+ key << byte
84
+ end
85
+ key.pack('cccccccc')
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -0,0 +1,2 @@
1
+
2
+ require 'websocket_client/client'
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: websocket-client
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - The TorqueBox Team
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-10 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description:
22
+ email: team@torquebox.org
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/websocket_client/client.rb
31
+ - lib/websocket_client/ietf_00.rb
32
+ - lib/websocket_client.rb
33
+ - examples/simple.rb
34
+ - examples/with_block.rb
35
+ homepage:
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ hash: 3
49
+ segments:
50
+ - 0
51
+ version: "0"
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.7.1
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Pure ruby WebSocket client
68
+ test_files: []
69
+