em-websocket-server 0.13 → 0.15
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.
- data/README.markdown +98 -38
- data/em-websocket-server.gemspec +17 -27
- data/lib/em-websocket-server.rb +15 -0
- data/lib/em-websocket-server/protocol/version76.rb +49 -0
- data/lib/em-websocket-server/request.rb +109 -0
- data/lib/em-websocket-server/server.rb +157 -0
- metadata +9 -21
- data/examples/chat.html +0 -37
- data/examples/chat.rb +0 -70
- data/examples/tictactoe/tictactoe.html +0 -51
- data/examples/tictactoe/tictactoe.js +0 -130
- data/examples/tictactoe/tictactoe.rb +0 -213
- data/examples/timesync.html +0 -29
- data/examples/timesync.rb +0 -37
- data/lib/web_socket.rb +0 -13
- data/lib/web_socket/client.rb +0 -71
- data/lib/web_socket/frame.rb +0 -20
- data/lib/web_socket/server.rb +0 -202
- data/lib/web_socket/util.rb +0 -55
metadata
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-websocket-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 17
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
7
|
+
- 15
|
8
|
+
version: "0.15"
|
10
9
|
platform: ruby
|
11
10
|
authors:
|
12
11
|
- Dan Simpson
|
@@ -14,7 +13,7 @@ autorequire:
|
|
14
13
|
bindir: bin
|
15
14
|
cert_chain: []
|
16
15
|
|
17
|
-
date:
|
16
|
+
date: 2010-08-30 00:00:00 -07:00
|
18
17
|
default_executable:
|
19
18
|
dependencies:
|
20
19
|
- !ruby/object:Gem::Dependency
|
@@ -25,12 +24,11 @@ dependencies:
|
|
25
24
|
requirements:
|
26
25
|
- - ">="
|
27
26
|
- !ruby/object:Gem::Version
|
28
|
-
hash: 39
|
29
27
|
segments:
|
30
28
|
- 0
|
31
29
|
- 12
|
32
|
-
-
|
33
|
-
version: 0.12.
|
30
|
+
- 10
|
31
|
+
version: 0.12.10
|
34
32
|
type: :runtime
|
35
33
|
version_requirements: *id001
|
36
34
|
description: An evented ruby websocket server built on top of EventMachine
|
@@ -44,18 +42,10 @@ extra_rdoc_files: []
|
|
44
42
|
files:
|
45
43
|
- README.markdown
|
46
44
|
- em-websocket-server.gemspec
|
47
|
-
-
|
48
|
-
-
|
49
|
-
-
|
50
|
-
-
|
51
|
-
- examples/tictactoe/tictactoe.html
|
52
|
-
- examples/tictactoe/tictactoe.js
|
53
|
-
- examples/tictactoe/tictactoe.rb
|
54
|
-
- lib/web_socket.rb
|
55
|
-
- lib/web_socket/client.rb
|
56
|
-
- lib/web_socket/server.rb
|
57
|
-
- lib/web_socket/frame.rb
|
58
|
-
- lib/web_socket/util.rb
|
45
|
+
- lib/em-websocket-server.rb
|
46
|
+
- lib/em-websocket-server/server.rb
|
47
|
+
- lib/em-websocket-server/request.rb
|
48
|
+
- lib/em-websocket-server/protocol/version76.rb
|
59
49
|
has_rdoc: true
|
60
50
|
homepage: http://github.com/dansimpson/em-websocket-server
|
61
51
|
licenses: []
|
@@ -70,7 +60,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
70
60
|
requirements:
|
71
61
|
- - ">="
|
72
62
|
- !ruby/object:Gem::Version
|
73
|
-
hash: 3
|
74
63
|
segments:
|
75
64
|
- 0
|
76
65
|
version: "0"
|
@@ -79,7 +68,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
68
|
requirements:
|
80
69
|
- - ">="
|
81
70
|
- !ruby/object:Gem::Version
|
82
|
-
hash: 3
|
83
71
|
segments:
|
84
72
|
- 0
|
85
73
|
version: "0"
|
data/examples/chat.html
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>em-websocket-server test</title>
|
5
|
-
</head>
|
6
|
-
<body>
|
7
|
-
|
8
|
-
|
9
|
-
<h1>em-websocket-server chat demo</h1>
|
10
|
-
<div id="chat">connecting....</div>
|
11
|
-
|
12
|
-
<script>
|
13
|
-
|
14
|
-
var webSocket = new WebSocket('ws://localhost:8000/time');
|
15
|
-
|
16
|
-
webSocket.onopen = function(event){
|
17
|
-
document.getElementById('chat').innerHTML = 'connected';
|
18
|
-
};
|
19
|
-
|
20
|
-
webSocket.onmessage = function(event){
|
21
|
-
document.getElementById('chat').innerHTML += "<br/>" + event.data;
|
22
|
-
};
|
23
|
-
|
24
|
-
webSocket.onclose = function(event){
|
25
|
-
document.getElementById('chat').innerHTML = 'socket closed';
|
26
|
-
};
|
27
|
-
|
28
|
-
document.getElementById('chatty').addEventListener("onkeypress", function() {
|
29
|
-
webSocket.send("test");
|
30
|
-
});
|
31
|
-
|
32
|
-
</script>
|
33
|
-
|
34
|
-
<a href="#" onclick="webSocket.send('test')">Send Test</a>
|
35
|
-
|
36
|
-
</body>
|
37
|
-
</html>
|
data/examples/chat.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'web_socket'
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
$chatroom = EM::Channel.new
|
8
|
-
$messages = 0
|
9
|
-
|
10
|
-
class ChatServer < WebSocket::Server
|
11
|
-
|
12
|
-
def on_connect
|
13
|
-
puts "Server -> Connect"
|
14
|
-
@sid = $chatroom.subscribe do |msg|
|
15
|
-
send_message msg
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def on_disconnect
|
20
|
-
puts "Server -> Handle Disconnect"
|
21
|
-
$chatroom.unsubscribe(@sid)
|
22
|
-
end
|
23
|
-
|
24
|
-
def on_receive msg
|
25
|
-
|
26
|
-
$messages += 1
|
27
|
-
if($messages % 100 == 0)
|
28
|
-
puts $messages
|
29
|
-
end
|
30
|
-
|
31
|
-
$chatroom.push(msg)
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
class ChatClient < WebSocket::Client
|
37
|
-
|
38
|
-
def initialize *args
|
39
|
-
super
|
40
|
-
end
|
41
|
-
|
42
|
-
def on_disconnect
|
43
|
-
puts "Client -> Disconnected"
|
44
|
-
end
|
45
|
-
|
46
|
-
def on_connect
|
47
|
-
|
48
|
-
EM.add_periodic_timer(rand() * 8, EM.Callback(self, :on_timer))
|
49
|
-
|
50
|
-
puts "Client -> connected"
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
def on_timer
|
55
|
-
send_message "x"
|
56
|
-
end
|
57
|
-
|
58
|
-
def on_receive msg
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
EM.kqueue
|
64
|
-
|
65
|
-
EM.run do
|
66
|
-
EM.start_server "0.0.0.0", 8000, ChatServer
|
67
|
-
5.times do
|
68
|
-
EM.connect "localhost", 8000, ChatClient
|
69
|
-
end
|
70
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
|
3
|
-
<html>
|
4
|
-
<head>
|
5
|
-
<title>Tic Tac Toe</title>
|
6
|
-
<meta name="author" content="Jordan Fowler (TheBreeze)">
|
7
|
-
|
8
|
-
<style type="text/css" media="screen">
|
9
|
-
#navigation ul {
|
10
|
-
list-style-type: none;
|
11
|
-
padding: 0;
|
12
|
-
margin: 25px 0px;
|
13
|
-
}
|
14
|
-
|
15
|
-
#navigation ul li {
|
16
|
-
display: inline;
|
17
|
-
padding: 0;
|
18
|
-
margin: 0;
|
19
|
-
margin-right: 10px;
|
20
|
-
}
|
21
|
-
|
22
|
-
#game-board .cell {
|
23
|
-
width: 100px;
|
24
|
-
height: 100px;
|
25
|
-
padding: 5px;
|
26
|
-
background: #000;
|
27
|
-
color: #FFF;
|
28
|
-
font-size: 100px;
|
29
|
-
text-align: center;
|
30
|
-
vertical-align: middle;
|
31
|
-
}
|
32
|
-
</style>
|
33
|
-
</head>
|
34
|
-
<body>
|
35
|
-
|
36
|
-
<h1>Tic Tac Toe</h1>
|
37
|
-
|
38
|
-
<div id="user-count"></div>
|
39
|
-
<div id="game-stats"></div>
|
40
|
-
<div id="status"></div>
|
41
|
-
|
42
|
-
<table id="game-board">
|
43
|
-
<tr><td id="cell-0-0" class="cell"></td><td id="cell-1-0" class="cell"></td><td id="cell-2-0" class="cell"></td></tr>
|
44
|
-
<tr><td id="cell-0-1" class="cell"></td><td id="cell-1-1" class="cell"></td><td id="cell-2-1" class="cell"></td></tr>
|
45
|
-
<tr><td id="cell-0-2" class="cell"></td><td id="cell-1-2" class="cell"></td><td id="cell-2-2" class="cell"></td></tr>
|
46
|
-
</table>
|
47
|
-
|
48
|
-
<script type="text/javascript" charset="utf-8" src="mootools-1.2.4-core-nc.js"></script>
|
49
|
-
<script type="text/javascript" charset="utf-8" src="tictactoe.js"></script>
|
50
|
-
</body>
|
51
|
-
</html>
|
@@ -1,130 +0,0 @@
|
|
1
|
-
// Author: Jordan Fowler (TheBreeze)
|
2
|
-
|
3
|
-
var TicTacToe = new Class({
|
4
|
-
wins: 0,
|
5
|
-
loses: 0,
|
6
|
-
draws: 0,
|
7
|
-
methodMap: {
|
8
|
-
'queued': 'onQueued',
|
9
|
-
'start': 'onStart',
|
10
|
-
'turn': 'onTurn',
|
11
|
-
'move': 'onMove',
|
12
|
-
'game_over': 'onGameOver',
|
13
|
-
'win': 'onWin',
|
14
|
-
'loss': 'onLoss',
|
15
|
-
'draw': 'onDraw',
|
16
|
-
'user_count': 'onUserCount'
|
17
|
-
},
|
18
|
-
|
19
|
-
initialize: function() {
|
20
|
-
if (TicTacToe.connection == null) {
|
21
|
-
TicTacToe.connection = new WebSocket('ws://localhost:8000/tictactoe');
|
22
|
-
};
|
23
|
-
|
24
|
-
TicTacToe.connection.onopen = this.join.bind(this);
|
25
|
-
TicTacToe.connection.onmessage = this.onMessage.bind(this);
|
26
|
-
TicTacToe.connection.onclose = this.onGameOver.bind(this);
|
27
|
-
|
28
|
-
this.setGameStats();
|
29
|
-
},
|
30
|
-
|
31
|
-
onMessage: function(event) {
|
32
|
-
var command = JSON.decode(event.data);
|
33
|
-
|
34
|
-
console.log('[RCV] ' + command.msg);
|
35
|
-
|
36
|
-
this[this.methodMap[command.msg]].call(this, command);
|
37
|
-
},
|
38
|
-
|
39
|
-
message: function(msg, options) {
|
40
|
-
var command = JSON.encode({msg: msg, data: options});
|
41
|
-
|
42
|
-
console.log('[SENT] ' + msg);
|
43
|
-
|
44
|
-
TicTacToe.connection.send(command);
|
45
|
-
},
|
46
|
-
|
47
|
-
setStatus: function(status) {
|
48
|
-
$('status').set('text', status);
|
49
|
-
},
|
50
|
-
|
51
|
-
setGameStats: function() {
|
52
|
-
$('game-stats').set('text', 'Wins: '+this.wins+' / Losses: '+this.wins+' / Draws: '+this.draws);
|
53
|
-
},
|
54
|
-
|
55
|
-
setUserCount: function(userCount) {
|
56
|
-
$('user-count').set('text', 'Number of players: ' + userCount);
|
57
|
-
},
|
58
|
-
|
59
|
-
join: function(event) {
|
60
|
-
this.message('join');
|
61
|
-
|
62
|
-
this.setStatus('Connecting you to a game...');
|
63
|
-
},
|
64
|
-
|
65
|
-
reset: function() {
|
66
|
-
$$('.cell').set('text', '');
|
67
|
-
|
68
|
-
this.join();
|
69
|
-
},
|
70
|
-
|
71
|
-
onQueued: function(command) {
|
72
|
-
this.setStatus('Waiting for another player...');
|
73
|
-
},
|
74
|
-
|
75
|
-
onStart: function(command) {
|
76
|
-
this.setStatus('Game found! Their turn first...');
|
77
|
-
},
|
78
|
-
|
79
|
-
onTurn: function(command) {
|
80
|
-
this.setStatus('Your turn...');
|
81
|
-
},
|
82
|
-
|
83
|
-
onMove: function(command) {
|
84
|
-
$('cell-'+command.data.x+'-'+command.data.y).set('text', command.key);
|
85
|
-
|
86
|
-
this.setStatus('Their turn...');
|
87
|
-
},
|
88
|
-
|
89
|
-
move: function(x, y) {
|
90
|
-
this.message('move', {x: x, y: y});
|
91
|
-
},
|
92
|
-
|
93
|
-
onGameOver: function(command) {
|
94
|
-
this.setStatus('Game over.');
|
95
|
-
this.setGameStats();
|
96
|
-
this.reset();
|
97
|
-
},
|
98
|
-
|
99
|
-
onWin: function(command) {
|
100
|
-
this.wins += 1;
|
101
|
-
this.setStatus('Game over. You win!');
|
102
|
-
this.setGameStats();
|
103
|
-
},
|
104
|
-
|
105
|
-
onLoss: function(command) {
|
106
|
-
this.losses += 1;
|
107
|
-
this.setStatus('Game over. You lose!');
|
108
|
-
this.setGameStats();
|
109
|
-
},
|
110
|
-
|
111
|
-
onDraw: function(command) {
|
112
|
-
this.draws += 1;
|
113
|
-
this.setStatus('Game over. It was a draw!');
|
114
|
-
this.setGameStats();
|
115
|
-
},
|
116
|
-
|
117
|
-
onUserCount: function(command) {
|
118
|
-
this.setUserCount(command.data);
|
119
|
-
}
|
120
|
-
});
|
121
|
-
|
122
|
-
$$('.cell').addEvent('click', function(event) {
|
123
|
-
try {
|
124
|
-
currentGame.move($(this).get('id').split('-')[1], $(this).get('id').split('-')[2]);
|
125
|
-
} catch(error) {
|
126
|
-
alert('Please wait while we connect you to a game...');
|
127
|
-
}
|
128
|
-
});
|
129
|
-
|
130
|
-
currentGame = new TicTacToe();
|
@@ -1,213 +0,0 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'web_socket'
|
5
|
-
require 'json'
|
6
|
-
require 'uuid'
|
7
|
-
require 'pp'
|
8
|
-
|
9
|
-
$games = {}
|
10
|
-
$waiting = nil
|
11
|
-
$status = nil
|
12
|
-
|
13
|
-
class StatusChannel < EM::Channel
|
14
|
-
|
15
|
-
def initialize
|
16
|
-
super
|
17
|
-
@count = 0
|
18
|
-
end
|
19
|
-
|
20
|
-
def increment
|
21
|
-
@count += 1
|
22
|
-
push @count
|
23
|
-
end
|
24
|
-
|
25
|
-
def decrement
|
26
|
-
@count -= 1
|
27
|
-
push @count
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class Game < EM::Channel
|
32
|
-
|
33
|
-
attr_accessor :id, :player1, :player2, :current, :grid
|
34
|
-
|
35
|
-
def initialize player1, player2
|
36
|
-
super()
|
37
|
-
@id = UUID.new
|
38
|
-
@player1 = player1
|
39
|
-
@player2 = player2
|
40
|
-
@grid = Matrix.diagonal(0,0,0)
|
41
|
-
end
|
42
|
-
|
43
|
-
def set_turn p
|
44
|
-
@current = p
|
45
|
-
@current.turn!
|
46
|
-
end
|
47
|
-
|
48
|
-
def start!
|
49
|
-
@current = nil
|
50
|
-
@player1.start!
|
51
|
-
@player2.start!
|
52
|
-
toggle
|
53
|
-
end
|
54
|
-
|
55
|
-
def move p, data
|
56
|
-
if @current == p
|
57
|
-
unless @matrix[data["x"].to_i][data["y"].to_i]
|
58
|
-
@matrix[data["x"].to_i][data["y"].to_i] = p.key
|
59
|
-
|
60
|
-
@player1.send_move(p.key, data)
|
61
|
-
@player2.send_move(p.key, data)
|
62
|
-
|
63
|
-
|
64
|
-
winner = has_winner?
|
65
|
-
full = full?
|
66
|
-
|
67
|
-
if winner || full
|
68
|
-
@player1.send_command("game_over")
|
69
|
-
@player2.send_command("game_over")
|
70
|
-
if winner
|
71
|
-
p.send_command("win")
|
72
|
-
opponent(p).send_command("loss")
|
73
|
-
else full?
|
74
|
-
@player1.send_command("draw")
|
75
|
-
@player2.send_command("draw")
|
76
|
-
end
|
77
|
-
else
|
78
|
-
toggle
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def full?
|
85
|
-
@matrix.each do |row|
|
86
|
-
row.each do |col|
|
87
|
-
return false unless col
|
88
|
-
end
|
89
|
-
end
|
90
|
-
return true
|
91
|
-
end
|
92
|
-
|
93
|
-
def has_winner?
|
94
|
-
return true if @matrix[1][1] && (@matrix[0][0] == @matrix[1][1]) && (@matrix[1][1] == @matrix[2][2])
|
95
|
-
return true if @matrix[1][1] && (@matrix[0][2] == @matrix[1][1]) && (@matrix[1][1] == @matrix[2][0])
|
96
|
-
@matrix.each do |row|
|
97
|
-
return true if row[1] && (row[0] == row[1]) && (row[1] == row[2])
|
98
|
-
end
|
99
|
-
return false
|
100
|
-
end
|
101
|
-
|
102
|
-
def opponent p
|
103
|
-
@player1 == p ? @player2 : @player1
|
104
|
-
end
|
105
|
-
|
106
|
-
def toggle
|
107
|
-
set_turn(@current == @player1 ? @player2 : @player1)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
class TickTackToeServer < WebSocket::Server
|
112
|
-
|
113
|
-
attr_accessor :game_id, :key, :status_key
|
114
|
-
|
115
|
-
def on_connect
|
116
|
-
@status_key = $status.subscribe do |c|
|
117
|
-
send_user_count c
|
118
|
-
end
|
119
|
-
$status.increment
|
120
|
-
end
|
121
|
-
|
122
|
-
def on_disconnect
|
123
|
-
$status.unsubscribe @status_key
|
124
|
-
$status.decrement
|
125
|
-
delete_game!
|
126
|
-
end
|
127
|
-
|
128
|
-
def on_receive data
|
129
|
-
|
130
|
-
begin
|
131
|
-
msg = JSON.parse(data)
|
132
|
-
rescue
|
133
|
-
send_command "error"
|
134
|
-
return
|
135
|
-
end
|
136
|
-
|
137
|
-
case msg["msg"]
|
138
|
-
when "join"
|
139
|
-
if $waiting.empty?
|
140
|
-
$waiting.push(self)
|
141
|
-
send_command "queued"
|
142
|
-
else
|
143
|
-
$waiting.pop do |opponent|
|
144
|
-
game = Game.new(self, opponent)
|
145
|
-
self.key = "X"
|
146
|
-
opponent.key = "O"
|
147
|
-
self.game_id = opponent.game_id = game.id
|
148
|
-
game.start!
|
149
|
-
$games[game_id] = game
|
150
|
-
end
|
151
|
-
end
|
152
|
-
when "move"
|
153
|
-
if game
|
154
|
-
game.move self, msg["data"]
|
155
|
-
|
156
|
-
else
|
157
|
-
log "Cannot move on a nil game!"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def delete_game!
|
163
|
-
if $games.key?(game_id)
|
164
|
-
$games.delete(game_id)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def game
|
169
|
-
$games[game_id]
|
170
|
-
end
|
171
|
-
|
172
|
-
def turn!
|
173
|
-
send_command "turn"
|
174
|
-
end
|
175
|
-
|
176
|
-
def game_over!
|
177
|
-
delete_game!
|
178
|
-
send_command "game_over"
|
179
|
-
end
|
180
|
-
|
181
|
-
def start!
|
182
|
-
send_command "start"
|
183
|
-
end
|
184
|
-
|
185
|
-
def send_move key, data
|
186
|
-
send_message({:msg => "move", :key => key, :data => data}.to_json)
|
187
|
-
end
|
188
|
-
|
189
|
-
def send_command cmd
|
190
|
-
send_message({:msg => cmd}.to_json)
|
191
|
-
end
|
192
|
-
|
193
|
-
def send_user_count count
|
194
|
-
send_message({:msg => :user_count, :data => count}.to_json)
|
195
|
-
end
|
196
|
-
|
197
|
-
|
198
|
-
def send_message msg
|
199
|
-
super msg
|
200
|
-
puts "Sent: #{msg}"
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
|
205
|
-
EM.epoll
|
206
|
-
EM.set_descriptor_table_size(10240)
|
207
|
-
|
208
|
-
EM.run do
|
209
|
-
$waiting = EM::Queue.new
|
210
|
-
$status = StatusChannel.new
|
211
|
-
|
212
|
-
EM.start_server "0.0.0.0", 8000, TickTackToeServer
|
213
|
-
end
|