websocket-client 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+