shooting_star 3.2.1 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +17 -2
- data/Manifest.txt +4 -0
- data/Rakefile +19 -1
- data/ext/asteroid.c +9 -2
- data/ext/asteroid.h +1 -0
- data/lib/shooting_star/channel.rb +9 -2
- data/lib/shooting_star/server.rb +74 -49
- data/lib/shooting_star/shooter.rb +3 -8
- data/lib/shooting_star/version.rb +3 -0
- data/lib/shooting_star.rb +27 -16
- data/test/ext/asteroid_test.rb +3 -8
- data/test/lib/shooting_star_test.rb +18 -19
- data/vendor/plugins/meteor_strike/generators/chat/templates/controller.rb +31 -11
- data/vendor/plugins/meteor_strike/generators/chat/templates/helper.rb +1 -1
- data/vendor/plugins/meteor_strike/generators/chat/templates/index.rhtml +13 -14
- data/vendor/plugins/meteor_strike/generators/meteor/templates/controller.rb +0 -6
- data/vendor/plugins/meteor_strike/generators/meteor/templates/meteor_strike.swf +0 -0
- data/vendor/plugins/meteor_strike/generators/meteor/templates/view.rhtml +2 -2
- data/vendor/plugins/meteor_strike/lib/meteor_strike/controller.rb +37 -0
- data/vendor/plugins/meteor_strike/lib/meteor_strike/helper.rb +8 -6
- data/vendor/plugins/meteor_strike/lib/meteor_strike.rb +4 -0
- data/vendor/plugins/meteor_strike/tasks/meteor_strike.rake +7 -0
- data/vendor/plugins/meteor_strike/views/xhr.rhtml +58 -47
- metadata +8 -4
data/History.txt
CHANGED
@@ -1,13 +1,28 @@
|
|
1
|
+
*** 3.2.2 / 2007-08-26
|
2
|
+
+ 3 major enhancements:
|
3
|
+
+ Profiling by RubyProf if CONFIG.profile.
|
4
|
+
+ Serialized event execution.
|
5
|
+
+ Separated type and phase on connection management.
|
6
|
+
+ 3 minor enhancements:
|
7
|
+
+ Added new task meteor_strike:update for updating plugin.
|
8
|
+
+ Refined a code of reconnection in flash client.
|
9
|
+
+ Updated chat generator.
|
10
|
+
+ 2 minor spec changes:
|
11
|
+
+ Added lib/version.rb.
|
12
|
+
+ Added :without_logging to shooting_star.yml
|
13
|
+
+ 1 minor bugfix:
|
14
|
+
+ Renamed helper module of a chat generator template.
|
15
|
+
|
1
16
|
*** 3.2.1 / 2007-08-09
|
2
|
-
+
|
17
|
+
+ 2 critical bugfixes:
|
3
18
|
+ Fixed a behaviour of xhr client initialization.
|
19
|
+
+ Fixed a behaviour of flash client initialization.
|
4
20
|
|
5
21
|
*** 3.2.0 / 2007-08-09
|
6
22
|
+ 3 major enhancements:
|
7
23
|
+ Automatic activation/deactivation of flash client.
|
8
24
|
+ Ported meteor_strike.swf from CS3 to mtasc.
|
9
25
|
+ Heart beat.
|
10
|
-
- Serialized event execution.
|
11
26
|
+ 7 minor enhancements:
|
12
27
|
+ shooting_star.yml is processed by ERB.
|
13
28
|
+ Updated implementation of observers.
|
data/Manifest.txt
CHANGED
@@ -4,6 +4,7 @@ README.txt
|
|
4
4
|
Rakefile
|
5
5
|
bin/shooting_star
|
6
6
|
lib/shooting_star.rb
|
7
|
+
lib/shooting_star/version.rb
|
7
8
|
lib/shooting_star/server.rb
|
8
9
|
lib/shooting_star/shooter.rb
|
9
10
|
lib/shooting_star/channel.rb
|
@@ -26,9 +27,12 @@ vendor/plugins/meteor_strike/lib
|
|
26
27
|
vendor/plugins/meteor_strike/lib/meteor_strike.rb
|
27
28
|
vendor/plugins/meteor_strike/lib/meteor_strike
|
28
29
|
vendor/plugins/meteor_strike/lib/meteor_strike/helper.rb
|
30
|
+
vendor/plugins/meteor_strike/lib/meteor_strike/controller.rb
|
29
31
|
vendor/plugins/meteor_strike/views
|
30
32
|
vendor/plugins/meteor_strike/views/xhr.rhtml
|
31
33
|
vendor/plugins/meteor_strike/views/flash.rhtml
|
34
|
+
vendor/plugins/meteor_strike/tasks
|
35
|
+
vendor/plugins/meteor_strike/tasks/meteor_strike.rake
|
32
36
|
vendor/plugins/meteor_strike/test
|
33
37
|
vendor/plugins/meteor_strike/test/meteor_strike_test.rb
|
34
38
|
vendor/plugins/meteor_strike/generators
|
data/Rakefile
CHANGED
@@ -10,9 +10,10 @@ namespace :gem do
|
|
10
10
|
|
11
11
|
$: << './lib'
|
12
12
|
$: << './ext'
|
13
|
-
require 'shooting_star'
|
13
|
+
require 'shooting_star/version'
|
14
14
|
|
15
15
|
Hoe.new('shooting_star', ShootingStar::VERSION) do |hoe|
|
16
|
+
|
16
17
|
hoe.author = 'Genki Takiuchi'
|
17
18
|
hoe.email = 'takiuchi@drecom.co.jp'
|
18
19
|
hoe.description = 'Comet server.'
|
@@ -69,3 +70,20 @@ file 'public/meteor_strike.swf' => 'as/meteor_strike.as' do
|
|
69
70
|
'-swf public/meteor_strike.swf',
|
70
71
|
'-main as/meteor_strike.as'].join(' ')
|
71
72
|
end
|
73
|
+
|
74
|
+
desc 'making ext'
|
75
|
+
task :ext => 'ext/asteroid.so'
|
76
|
+
|
77
|
+
file 'ext/asteroid.so' => 'ext/Makefile' do
|
78
|
+
cwd = `pwd`
|
79
|
+
cd 'ext/'
|
80
|
+
sh 'make'
|
81
|
+
cd cwd.chomp
|
82
|
+
end
|
83
|
+
|
84
|
+
file 'ext/Makefile' => 'ext/extconf.rb' do
|
85
|
+
cwd = `pwd`
|
86
|
+
cd 'ext/'
|
87
|
+
sh 'ruby extconf.rb'
|
88
|
+
cd cwd.chomp
|
89
|
+
end
|
data/ext/asteroid.c
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
#include <errno.h>
|
10
10
|
#include <sys/types.h>
|
11
11
|
#include <sys/socket.h>
|
12
|
+
#include <sys/time.h>
|
12
13
|
#include <netinet/in.h>
|
13
14
|
#include <arpa/inet.h>
|
14
15
|
#include "extconf.h"
|
@@ -21,7 +22,6 @@
|
|
21
22
|
* -------------------------------------------------------------------------- */
|
22
23
|
#ifdef HAVE_SYS_EVENT_H
|
23
24
|
#include <sys/event.h>
|
24
|
-
#include <sys/time.h>
|
25
25
|
typedef int asteroid_pollfd_t;
|
26
26
|
typedef struct kevent asteroid_poll_event_t;
|
27
27
|
#endif
|
@@ -137,6 +137,7 @@ void Init_asteroid(){
|
|
137
137
|
Asteroid = rb_define_module("Asteroid");
|
138
138
|
rb_define_singleton_method(Asteroid, "run", asteroid_s_run, 3);
|
139
139
|
rb_define_singleton_method(Asteroid, "stop", asteroid_s_stop, 0);
|
140
|
+
rb_define_singleton_method(Asteroid, "now", asteroid_s_now, 0);
|
140
141
|
rb_define_class_variable(Asteroid, "@@clients", clients = rb_hash_new());
|
141
142
|
}
|
142
143
|
|
@@ -204,12 +205,18 @@ static VALUE asteroid_s_stop(VALUE Self){
|
|
204
205
|
return Qnil;
|
205
206
|
}
|
206
207
|
|
208
|
+
static VALUE asteroid_s_now(VALUE Self){
|
209
|
+
struct timeval now;
|
210
|
+
gettimeofday(&now, NULL);
|
211
|
+
return rb_float_new(now.tv_sec + now.tv_usec/1000000.0);
|
212
|
+
}
|
213
|
+
|
207
214
|
static VALUE asteroid_server_send_data(VALUE Self, VALUE Data){
|
208
215
|
VALUE Fd = rb_iv_get(Self, "@fd");
|
209
216
|
int fd = FIX2INT(Fd), remain = RSTRING(Data)->len, len, trial = 100;
|
210
217
|
char *data = StringValuePtr(Data);
|
211
218
|
while(remain){
|
212
|
-
len = send(fd, data, remain, MSG_NOSIGNAL);
|
219
|
+
len = send(fd, data, remain, MSG_DONTWAIT|MSG_NOSIGNAL);
|
213
220
|
if(len == -1){
|
214
221
|
if(errno == EAGAIN && --trial){
|
215
222
|
rb_thread_schedule();
|
data/ext/asteroid.h
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
static VALUE asteroid_s_run(VALUE Self, VALUE Host, VALUE Port, VALUE Module);
|
2
2
|
static VALUE asteroid_s_stop(VALUE Self);
|
3
|
+
static VALUE asteroid_s_now(VALUE Self);
|
3
4
|
static VALUE asteroid_server_send_data(VALUE Self, VALUE Data);
|
4
5
|
static VALUE asteroid_server_write_and_close(VALUE Self);
|
@@ -10,16 +10,23 @@ module ShootingStar
|
|
10
10
|
@@channels[path] = self
|
11
11
|
end
|
12
12
|
|
13
|
+
# A message is sent to observers if params includes a :event key.
|
14
|
+
# If there are no observers, the message is sent to clients.
|
15
|
+
# Others are sent to clients.
|
13
16
|
def transmit(id, params)
|
17
|
+
need_event_handling = false
|
14
18
|
if event = params[:event]
|
15
19
|
observers = @@observers.has_key?(@path) ? @@observers[@path].dup : nil
|
16
20
|
observers.each do |name, obs|
|
17
21
|
begin obs.__send__(event, params) if obs.respond_to?(event)
|
18
22
|
rescue Exception; Channel.ignore(@path, name) end
|
19
23
|
end if observers
|
24
|
+
need_event_handling = observers.nil? || observers.empty?
|
20
25
|
end
|
21
|
-
|
22
|
-
|
26
|
+
if event.nil? || need_event_handling
|
27
|
+
@waiters.each do |signature, server|
|
28
|
+
server.commit if server.respond(id, params)
|
29
|
+
end
|
23
30
|
end
|
24
31
|
end
|
25
32
|
|
data/lib/shooting_star/server.rb
CHANGED
@@ -57,17 +57,19 @@ module ShootingStar
|
|
57
57
|
@channel_path ||= CGI.unescape(channel_path)
|
58
58
|
@query = "channel=#{channel_path}&sig=#{@signature}"
|
59
59
|
@type = @params['__t__']
|
60
|
+
@phase = @params['__p__']
|
60
61
|
# process verb
|
61
62
|
if !@type
|
62
|
-
|
63
|
+
make_xhr_connection(path)
|
63
64
|
else
|
64
65
|
prepare_channel(@channel_path)
|
65
66
|
@uid = @@uids[@signature] ||= @params['uid']
|
66
67
|
@tag = @@tags[@signature] ||=
|
67
68
|
(@params['tag'] || '').split(',').map{|i| CGI.unescape(i)}
|
68
|
-
|
69
|
+
unless @phase == 'reconnect'
|
70
|
+
make_flash_connection if @type == 'flash'
|
69
71
|
notify(:event => :enter, :uid => @uid, :tag => @tag)
|
70
|
-
log
|
72
|
+
log{"Connected: #{@uid}"}
|
71
73
|
end
|
72
74
|
@executing = @@executings[@signature] ||= Hash.new
|
73
75
|
@@servers[@signature] = self
|
@@ -76,7 +78,7 @@ module ShootingStar
|
|
76
78
|
rescue MethodNotAcceptable
|
77
79
|
write_and_close
|
78
80
|
rescue Exception => e
|
79
|
-
log
|
81
|
+
log{"ERROR: #{e.message}\n#{e.backtrace.join("\n")}\n#{data}"}
|
80
82
|
write_and_close
|
81
83
|
end
|
82
84
|
|
@@ -91,9 +93,9 @@ module ShootingStar
|
|
91
93
|
@@uids.delete(@signature)
|
92
94
|
@@tags.delete(@signature)
|
93
95
|
@@executings.delete(@signature)
|
94
|
-
log
|
96
|
+
log{"Disconnected: #{@uid}:#{@signature}"}
|
95
97
|
if Channel.cleanup(@channel_path)
|
96
|
-
log
|
98
|
+
log{"Channel closed: #{@channel_path}"}
|
97
99
|
end
|
98
100
|
end
|
99
101
|
|
@@ -113,24 +115,18 @@ module ShootingStar
|
|
113
115
|
return false if @unbound || !@waiting
|
114
116
|
@executing.each{|id, params| execute(id, params)}
|
115
117
|
return false if @execution.empty?
|
116
|
-
return false unless send_data(@type == '
|
118
|
+
return false unless send_data(@type == 'flash' ? "#{@execution}\0" :
|
117
119
|
"HTTP/1.1 200 OK\nContent-Type: text/javascript\n\n#{@execution}")
|
118
|
-
@committed_at =
|
120
|
+
@committed_at = Asteroid::now
|
119
121
|
@execution = ''
|
120
|
-
@executing
|
122
|
+
@executing.clear
|
121
123
|
@@executings.delete(@signature)
|
122
|
-
unless @type == '
|
124
|
+
unless @type == 'flash'
|
123
125
|
@waiting = nil
|
124
126
|
write_and_close
|
125
127
|
end
|
126
128
|
true
|
127
129
|
end
|
128
|
-
|
129
|
-
# noticed execution and remove the command from execution buffer.
|
130
|
-
def executed(id)
|
131
|
-
@executing = @@executings[@signature] ||= Hash.new
|
132
|
-
@executing.delete(id)
|
133
|
-
end
|
134
130
|
|
135
131
|
# update current status of servant.
|
136
132
|
def update(uid, tag)
|
@@ -140,7 +136,7 @@ module ShootingStar
|
|
140
136
|
@@tags[@signature] = @tag = tag
|
141
137
|
notify(:event => :enter, :uid => @uid, :tag => @tag)
|
142
138
|
end
|
143
|
-
log
|
139
|
+
log{"Update: #{@uid}:#{@tag.join(',')}"}
|
144
140
|
end
|
145
141
|
|
146
142
|
def uid; @@uids[@signature] end
|
@@ -152,31 +148,31 @@ module ShootingStar
|
|
152
148
|
end
|
153
149
|
|
154
150
|
private
|
155
|
-
def log(
|
151
|
+
def log(&block) ShootingStar::log(&block) end
|
156
152
|
|
157
153
|
# check session timeout
|
158
154
|
def session_timeout?
|
159
155
|
return true unless @committed_at
|
160
|
-
|
156
|
+
Asteroid::now - @committed_at > ShootingStar::CONFIG.session_timeout
|
161
157
|
end
|
162
158
|
|
163
159
|
# broadcast event to clients.
|
164
160
|
def notify(params = {})
|
165
161
|
return unless Channel[@channel_path]
|
166
162
|
event_id = ShootingStar::timestamp
|
167
|
-
log
|
163
|
+
log{"Event(#{event_id}): #{@channel_path}:#{params.inspect}"}
|
168
164
|
Channel[@channel_path].transmit("event-#{event_id}", params)
|
169
165
|
rescue Exception => e
|
170
|
-
log
|
166
|
+
log{"ERROR: #{e.message}\n#{e.backtrace.join("\n")}"}
|
171
167
|
end
|
172
168
|
|
173
169
|
# wait for commands or events until they occur. if they're already in
|
174
170
|
# the execution buffer, they'll be flushed and return on the spot.
|
175
171
|
def wait_for
|
176
172
|
@waiting = true
|
177
|
-
log
|
173
|
+
log{"Wait for: #{@channel_path}:#{@uid}:#{@tag.inspect}:#{@signature}"}
|
178
174
|
if prepare_channel(@channel_path).join(self)
|
179
|
-
log
|
175
|
+
log{"Flushed: #{@channel_path}:#{@uid}:#{@tag.inspect}:#{@signature}"}
|
180
176
|
end
|
181
177
|
end
|
182
178
|
|
@@ -184,41 +180,68 @@ module ShootingStar
|
|
184
180
|
def prepare_channel(channel_path)
|
185
181
|
unless Channel[channel_path]
|
186
182
|
Channel.new(channel_path)
|
187
|
-
log
|
183
|
+
log{"Channel opened: #{channel_path}"}
|
188
184
|
end
|
189
185
|
Channel[channel_path]
|
190
186
|
end
|
191
187
|
|
192
188
|
# add execution line to the buffer.
|
193
189
|
def execute(id, params)
|
194
|
-
sweep_timeout = ShootingStar::CONFIG.sweep_timeout
|
195
190
|
@executing[id] = params
|
196
191
|
query = @query.sub(%r[\&sig=\d+], '')
|
197
192
|
query += "&" + FormEncoder.encode(params) if params
|
198
|
-
@execution +=
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
var
|
205
|
-
|
206
|
-
|
207
|
-
|
193
|
+
@execution += "meteorStrike.execute(#{id.to_json},#{query.to_json});"
|
194
|
+
end
|
195
|
+
|
196
|
+
def executioner(initial_serial_id = 0)
|
197
|
+
sweep_timeout = ShootingStar::CONFIG.sweep_timeout
|
198
|
+
<<-"EOH"
|
199
|
+
var meteorStrike = window.meteorStrike || new Object;
|
200
|
+
meteorStrike.execute = function(id, query){
|
201
|
+
var channel = #{@channel_path.to_json};
|
202
|
+
var ms = meteorStrike[channel] = meteorStrike[channel] || new Object;
|
203
|
+
ms.serialId = ms.serialId || #{initial_serial_id};
|
204
|
+
var ms1 = document.getElementById('meteor-strike-1-form');
|
205
|
+
var box = ms1 ? ms1.parentNode : document.body;
|
206
|
+
var iframe = document.createElement('iframe');
|
207
|
+
var remove = function(){
|
208
|
+
if(iframe) box.removeChild(iframe);
|
209
|
+
iframe = null;
|
210
|
+
};
|
211
|
+
var timer = setTimeout(remove, #{sweep_timeout});
|
212
|
+
var ready = function(){
|
213
|
+
clearTimeout(timer);
|
214
|
+
setTimeout(remove, 0);
|
215
|
+
};
|
216
|
+
iframe.onload = ready;
|
217
|
+
iframe.onreadystatechange = function(){
|
218
|
+
if(this.readyState == 'complete') ready();
|
219
|
+
};
|
220
|
+
iframe.src = ['#{@params['execute']}/', id, '?', query,
|
221
|
+
'&__s__=', ms.serialId++].join('');
|
222
|
+
box.appendChild(iframe);
|
208
223
|
};
|
209
|
-
iframe.src = '#{@params['execute']}/#{id}?#{query}';
|
210
|
-
box.appendChild(iframe);
|
211
|
-
})();
|
212
224
|
EOH
|
213
225
|
end
|
214
226
|
|
215
|
-
# make client connect us.
|
216
|
-
def
|
227
|
+
# make flash client connect us.
|
228
|
+
def make_flash_connection
|
229
|
+
query = @query.sub(%r[\&sig=\d+], '')
|
230
|
+
query += "&" + FormEncoder.encode(:event => :init, :type => :flash)
|
231
|
+
event_id = MD5.new("event-init-flash-#{Asteroid::now}").to_s
|
232
|
+
send_data executioner + %Q{
|
233
|
+
meteorStrike.execute(#{event_id.to_json}, #{query.to_json});
|
234
|
+
} + "\0"
|
235
|
+
end
|
236
|
+
|
237
|
+
# make xhr client connect us.
|
238
|
+
def make_xhr_connection(path)
|
217
239
|
assets = URI.parse(@params['execute'])
|
218
240
|
assets.path = '/javascripts/prototype.js'
|
219
241
|
assets.query = assets.fragment = nil
|
220
|
-
query = @query.sub(%r[\&sig=\d+], '')
|
242
|
+
query = @query.sub(%r[\&sig=\d+], '') + '&__s__=0'
|
221
243
|
query += "&" + FormEncoder.encode(:event => :init, :type => :xhr)
|
244
|
+
event_id = MD5.new("event-init-xhr-#{Asteroid::now}").to_s
|
222
245
|
heartbeat = @params['heartbeat'].to_i
|
223
246
|
send_data "HTTP/1.1 200 OK\nContent-Type: text/html\n\n" +
|
224
247
|
<<-"EOH"
|
@@ -229,16 +252,18 @@ module ShootingStar
|
|
229
252
|
<script type="text/javascript" src="#{assets}"></script>
|
230
253
|
<script type="text/javascript">
|
231
254
|
//<![CDATA[
|
232
|
-
|
233
|
-
|
234
|
-
body
|
235
|
-
|
236
|
-
|
255
|
+
#{executioner(1)}
|
256
|
+
var connect = function(reconnect){
|
257
|
+
var body = $H(#{@params.to_json});
|
258
|
+
body.__t__ = 'xhr';
|
259
|
+
body.__p__ = reconnect ? 'reconnect' : 'connect';
|
260
|
+
var request = new Ajax.Request(#{path.to_json}, {evalScript: true,
|
261
|
+
onComplete: function(xhr){
|
237
262
|
setTimeout(function(){connect(true)},
|
238
263
|
xhr.getResponseHeader('Content-Type') ? 0 : 3000);
|
239
264
|
}, postBody: body.toQueryString()});
|
240
|
-
var disconnect = function()
|
241
|
-
|
265
|
+
var disconnect = function(){
|
266
|
+
request.options.onComplete = function(){};
|
242
267
|
request.transport.abort();
|
243
268
|
};
|
244
269
|
Event.observe(window, 'unload', disconnect);
|
@@ -249,7 +274,7 @@ module ShootingStar
|
|
249
274
|
setTimeout(function(){connect(false)}, 0);
|
250
275
|
//]]>
|
251
276
|
</script></head><body>
|
252
|
-
<iframe src="#{@params['execute']}
|
277
|
+
<iframe src="#{@params['execute']}/#{event_id}?#{query}"></iframe>
|
253
278
|
</body></html>
|
254
279
|
EOH
|
255
280
|
rescue Exception
|
@@ -6,7 +6,8 @@ module ShootingStar
|
|
6
6
|
# broadcast/multicast message
|
7
7
|
def shoot(channel_path, id, tag, options = {})
|
8
8
|
return unless Channel[channel_path]
|
9
|
-
|
9
|
+
tag ||= []
|
10
|
+
log{"Shot: #{channel_path}:#{id}:#{tag.join(',')}:#{options}"}
|
10
11
|
Channel[channel_path].transmit(id, options.merge(:tag => tag))
|
11
12
|
end
|
12
13
|
|
@@ -49,12 +50,6 @@ module ShootingStar
|
|
49
50
|
servers(channel_path, tag).map{|s| s.signature}
|
50
51
|
end
|
51
52
|
|
52
|
-
# notification entry point of message execution.
|
53
|
-
def executed(sig, id)
|
54
|
-
::ShootingStar::Server[sig].executed(id)
|
55
|
-
rescue Exception
|
56
|
-
end
|
57
|
-
|
58
53
|
# observe server side events
|
59
54
|
def observe(channel_path, observer)
|
60
55
|
Channel.observe(channel_path, observer)
|
@@ -62,7 +57,7 @@ module ShootingStar
|
|
62
57
|
end
|
63
58
|
|
64
59
|
private
|
65
|
-
def log(
|
60
|
+
def log(&block) ShootingStar::log(&block) end
|
66
61
|
|
67
62
|
def servers(channel_path, tag = nil)
|
68
63
|
return [] unless Channel[channel_path]
|
data/lib/shooting_star.rb
CHANGED
@@ -5,19 +5,19 @@ require 'yaml'
|
|
5
5
|
require 'ftools'
|
6
6
|
require 'fileutils'
|
7
7
|
require 'erb'
|
8
|
+
require 'shooting_star/version'
|
8
9
|
require 'shooting_star/config'
|
9
10
|
require 'shooting_star/shooter'
|
10
11
|
|
11
12
|
module ShootingStar
|
12
|
-
VERSION = '3.2.1'
|
13
13
|
CONFIG = Config.new(
|
14
14
|
:config => 'config/shooting_star.yml',
|
15
15
|
:pid_file => 'tmp/pids/shooting_star.pid',
|
16
16
|
:log_file => 'log/shooting_star.log',
|
17
17
|
:daemon => false,
|
18
18
|
:slient => false,
|
19
|
-
:session_timeout => 10,
|
20
|
-
:sweep_timeout =>
|
19
|
+
:session_timeout => 10.0,
|
20
|
+
:sweep_timeout => 30_000)
|
21
21
|
|
22
22
|
def self.configure(options = {})
|
23
23
|
if @log_file
|
@@ -35,6 +35,8 @@ module ShootingStar
|
|
35
35
|
@@shooter ||= DRb.start_service && DRbObject.new(nil, CONFIG.shooter.uri)
|
36
36
|
end
|
37
37
|
|
38
|
+
def self.timestamp; ("%.6f" % Asteroid::now).tr('.', '') end
|
39
|
+
|
38
40
|
# install config file and plugin
|
39
41
|
def self.init
|
40
42
|
base_dir = CONFIG.directory || FileUtils.pwd
|
@@ -63,13 +65,22 @@ module ShootingStar
|
|
63
65
|
|
64
66
|
def self.start(&block)
|
65
67
|
if File.exist?(CONFIG.pid_file)
|
66
|
-
|
67
|
-
|
68
|
+
begin
|
69
|
+
shooter.signature
|
70
|
+
log{'shooting_star is already running.'}
|
71
|
+
return
|
72
|
+
rescue Exception
|
73
|
+
log{'shooting_star seems having been shut down incorrectly.'}
|
74
|
+
end
|
68
75
|
end
|
69
76
|
if CONFIG.daemon
|
70
77
|
Signal.trap(:ALRM){exit} and sleep if fork
|
71
78
|
Process.setsid
|
72
79
|
end
|
80
|
+
if CONFIG.profile
|
81
|
+
require 'ruby-prof'
|
82
|
+
RubyProf.start
|
83
|
+
end
|
73
84
|
require 'shooting_star/shooter'
|
74
85
|
@@druby = DRb.start_service(CONFIG.shooter.uri, Shooter.new)
|
75
86
|
require 'shooting_star/server'
|
@@ -81,14 +92,17 @@ module ShootingStar
|
|
81
92
|
Signal.trap(:INT) do
|
82
93
|
Asteroid::stop
|
83
94
|
@@druby.stop_service
|
84
|
-
log
|
95
|
+
log{"shooting_star service stopped."}
|
85
96
|
File.rm_f(CONFIG.pid_file)
|
97
|
+
if CONFIG.profile
|
98
|
+
RubyProf::FlatPrinter.new(RubyProf.stop).print(STDOUT, 0)
|
99
|
+
end
|
86
100
|
end
|
87
101
|
Signal.trap(:EXIT) do
|
88
102
|
File.rm_f(CONFIG.pid_file)
|
89
103
|
@log_file.close if @log_file
|
90
104
|
end
|
91
|
-
log
|
105
|
+
log{"shooting_star service started."}
|
92
106
|
Process.kill(:ALRM, Process.ppid) rescue nil if CONFIG.daemon
|
93
107
|
block.call if block
|
94
108
|
end
|
@@ -102,7 +116,7 @@ module ShootingStar
|
|
102
116
|
end
|
103
117
|
Thread.pass while File.exist?(CONFIG.pid_file)
|
104
118
|
rescue Errno::ENOENT
|
105
|
-
log
|
119
|
+
log{"shooting_star service is not running."}
|
106
120
|
rescue Errno::ESRCH
|
107
121
|
File.unlink(CONFIG.pid_file)
|
108
122
|
ensure
|
@@ -135,16 +149,13 @@ module ShootingStar
|
|
135
149
|
puts "#{'-' * 79}\n%11d %s\n#{'-' * 79}" % [total_observers, 'TOTAL']
|
136
150
|
end
|
137
151
|
|
138
|
-
def self.timestamp
|
139
|
-
now = Time.now
|
140
|
-
"%d%06d" % [now.tv_sec, now.tv_usec]
|
141
|
-
end
|
142
|
-
|
143
152
|
private
|
144
|
-
def self.log(
|
145
|
-
|
153
|
+
def self.log(&block)
|
154
|
+
return if CONFIG.without_logging
|
155
|
+
message = block.call if block
|
156
|
+
puts(message) unless CONFIG.silent
|
146
157
|
@log_file ||= open(CONFIG.log_file, 'a')
|
147
|
-
@log_file.puts(
|
158
|
+
@log_file.puts(message) if @log_file
|
148
159
|
end
|
149
160
|
end
|
150
161
|
__END__
|
data/test/ext/asteroid_test.rb
CHANGED
@@ -20,14 +20,9 @@ end
|
|
20
20
|
|
21
21
|
class ShootingStarTest < Test::Unit::TestCase
|
22
22
|
def setup
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
Asteroid::run('127.0.0.1', 7124, Server) do
|
27
|
-
mutex.unlock
|
28
|
-
end
|
29
|
-
end
|
30
|
-
mutex.lock
|
23
|
+
flag = false
|
24
|
+
@thread = Thread.new{Asteroid::run('127.0.0.1', 7124, Server){flag = true}}
|
25
|
+
Thread.pass until flag
|
31
26
|
end
|
32
27
|
|
33
28
|
def teardown
|
@@ -19,10 +19,9 @@ class ShootingStarTest < Test::Unit::TestCase
|
|
19
19
|
:log_file => 'log/shooting_star.test.log',
|
20
20
|
:server => {:host => '127.0.0.1', :port => 8081},
|
21
21
|
:shooter => {:uri => 'druby://127.0.0.1:7124'}
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
mutex.lock
|
22
|
+
flag = false
|
23
|
+
@thread = Thread.new{ShootingStar.start{flag = true}}
|
24
|
+
Thread.pass until flag
|
26
25
|
@query = "sig=0123456789&execute=http://127.0.0.1:4001/meteor/strike"
|
27
26
|
@query2 = "sig=1123456789&execute=http://127.0.0.1:4001/meteor/strike"
|
28
27
|
end
|
@@ -49,19 +48,18 @@ class ShootingStarTest < Test::Unit::TestCase
|
|
49
48
|
assert_not_nil result.index('test\/channel')
|
50
49
|
client.close
|
51
50
|
|
52
|
-
|
53
|
-
mutex.lock
|
51
|
+
flag = false
|
54
52
|
Thread.new do
|
55
53
|
client = TCPSocket.open('127.0.0.1', 8081)
|
56
54
|
send(client, "POST", "test/channel", "#{@query}&__t__=c")
|
57
|
-
|
55
|
+
flag = true
|
58
56
|
end
|
59
|
-
|
57
|
+
Thread.pass until flag
|
60
58
|
shooter = DRbObject.new_with_uri('druby://127.0.0.1:7124')
|
61
59
|
assert_not_nil shooter
|
62
60
|
shooter.shoot("test/channel", 12, [])
|
63
61
|
assert_not_nil result = client.read
|
64
|
-
assert_not_nil result.index('
|
62
|
+
assert_not_nil result.index('meteorStrike.execute(12,')
|
65
63
|
end
|
66
64
|
|
67
65
|
def test_multi_user_communication
|
@@ -74,27 +72,28 @@ class ShootingStarTest < Test::Unit::TestCase
|
|
74
72
|
observer = TestObserver.new
|
75
73
|
assert_not_nil observer
|
76
74
|
shooter.observe('test/channel', observer)
|
77
|
-
|
78
|
-
mutex.lock
|
75
|
+
flag = false
|
79
76
|
assert_nil observer.params
|
80
77
|
Thread.new do
|
81
78
|
send(client1, "POST", "test/channel", "#{@query}&__t__=c")
|
82
|
-
|
79
|
+
flag = true
|
83
80
|
end
|
84
|
-
|
85
|
-
|
81
|
+
Thread.pass until flag
|
82
|
+
assert_not_nil observer.params
|
83
|
+
assert_equal :enter, observer.params[:event]
|
84
|
+
flag = false
|
86
85
|
Thread.new do
|
87
86
|
send(client2, "POST", "test/channel", "#{@query2}&__t__=c")
|
88
|
-
|
87
|
+
flag = true
|
89
88
|
end
|
90
|
-
|
89
|
+
Thread.pass until flag
|
91
90
|
assert_not_nil observer.params
|
92
91
|
assert_equal :enter, observer.params[:event]
|
93
|
-
assert_not_nil result1 = client1.read
|
94
|
-
assert_not_nil result1.index('meteor/strike/event-')
|
95
92
|
shooter.shoot("test/channel", 12, [])
|
93
|
+
assert_not_nil result1 = client1.read
|
94
|
+
assert_not_nil result1.index('meteorStrike.execute(12,')
|
96
95
|
assert_not_nil result2 = client2.read
|
97
|
-
assert_not_nil result2.index('
|
96
|
+
assert_not_nil result2.index('meteorStrike.execute(12,')
|
98
97
|
end
|
99
98
|
|
100
99
|
def test_xmlsocket_server
|
@@ -2,6 +2,7 @@ class <%= class_name %>Controller < ApplicationController
|
|
2
2
|
layout '<%= file_name %>', :only => :index
|
3
3
|
|
4
4
|
def index
|
5
|
+
session[:name] ||= 'guest'
|
5
6
|
@chats = <%= class_name %>.find(:all).reverse
|
6
7
|
end
|
7
8
|
|
@@ -9,24 +10,43 @@ class <%= class_name %>Controller < ApplicationController
|
|
9
10
|
@chat = <%= class_name %>.find(params[:id])
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
-
|
14
|
-
content = render_component_as_string :action => 'show', :id => @chat.id
|
15
|
-
javascript = render_to_string :update do |page|
|
16
|
-
page.insert_html :top, 'chat-list', content
|
17
|
-
end
|
18
|
-
Meteor.shoot '<%= file_name %>', javascript
|
13
|
+
def listen
|
14
|
+
session[:name] = params[:name]
|
19
15
|
render :update do |page|
|
20
|
-
page
|
21
|
-
|
16
|
+
page << <<-"EOH"
|
17
|
+
meteorStrike['<%= file_name %>'].update(#{session[:name].to_json});
|
18
|
+
EOH
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def talk
|
23
|
+
@chat = <%= class_name %>.new(
|
24
|
+
:name => session[:name], :message => params[:message])
|
25
|
+
if @chat.save
|
26
|
+
content = render_component_as_string :action => 'show', :id => @chat.id
|
27
|
+
javascript = render_to_string :update do |page|
|
28
|
+
page.insert_html :top, 'chat-list', content
|
29
|
+
end
|
30
|
+
Meteor.shoot '<%= file_name %>', javascript
|
31
|
+
render :update do |page|
|
32
|
+
page[:message].clear
|
33
|
+
page[:message].focus
|
34
|
+
end
|
35
|
+
else
|
36
|
+
render :nothing => true
|
22
37
|
end
|
23
38
|
end
|
24
39
|
|
25
|
-
def
|
40
|
+
def event
|
41
|
+
message = case params[:event]
|
42
|
+
when 'init'; "connection established by #{params[:type]}."
|
43
|
+
when 'enter'; "#{params[:uid]} joined."
|
44
|
+
when 'leave'; "#{params[:uid]} left."
|
45
|
+
end
|
26
46
|
@chat = <%= class_name %>.new(
|
27
47
|
:name => '(* system *)',
|
28
48
|
:created_at => Time.now,
|
29
|
-
:message =>
|
49
|
+
:message => message)
|
30
50
|
render :action => 'show'
|
31
51
|
end
|
32
52
|
end
|
@@ -1,2 +1,2 @@
|
|
1
|
-
module
|
1
|
+
module <%= class_name %>Helper
|
2
2
|
end
|
@@ -1,18 +1,17 @@
|
|
1
|
-
<%%
|
2
|
-
<%%=
|
1
|
+
<%% form_remote_tag(:url => {:action => 'listen'}) do |f| %>
|
2
|
+
<%%= text_field_tag :name, session[:name] %>
|
3
|
+
<%%= submit_tag 'Listen' %><br />
|
4
|
+
<%% end %>
|
5
|
+
<%% form_remote_tag(:url => {:action => 'talk'}) do |f| %>
|
6
|
+
<%%= text_field_tag :message %>
|
3
7
|
<%%= submit_tag 'Talk' %><br />
|
4
|
-
<%%= f.text_area :message, :rows => 3 %>
|
5
8
|
<%% end %>
|
6
9
|
<ul id="chat-list">
|
7
|
-
<%% for chat in @chats %>
|
8
|
-
|
9
|
-
<%% end %>
|
10
|
+
<%% for chat in @chats %>
|
11
|
+
<%%= render_component :action => 'show', :id => chat.id %>
|
12
|
+
<%% end %>
|
10
13
|
</ul>
|
11
|
-
<%%= meteor_strike '<%= file_name %>', :event => %Q{
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
insertion: Insertion.Top, parameters: {client_type: params.type}});
|
16
|
-
break;
|
17
|
-
}
|
18
|
-
} %>
|
14
|
+
<%%= meteor_strike '<%= file_name %>', :uid => session[:name], :event => %Q{
|
15
|
+
new Ajax.Updater('chat-list', #{url_for(:action => 'event').to_json}, {
|
16
|
+
insertion: Insertion.Top, parameters: params})}
|
17
|
+
%>
|
@@ -1,7 +1,6 @@
|
|
1
1
|
class MeteorController < ApplicationController
|
2
2
|
layout nil
|
3
3
|
caches_action :strike
|
4
|
-
after_filter :notify_execution, :only => [:strike]
|
5
4
|
|
6
5
|
def strike
|
7
6
|
@channel = params[:channel]
|
@@ -24,9 +23,4 @@ class MeteorController < ApplicationController
|
|
24
23
|
Meteor.shooter.sweep
|
25
24
|
render :nothing => true
|
26
25
|
end
|
27
|
-
|
28
|
-
private
|
29
|
-
def notify_execution
|
30
|
-
Meteor.shooter.executed(params[:sig], params[:id])
|
31
|
-
end
|
32
26
|
end
|
Binary file
|
@@ -9,8 +9,8 @@
|
|
9
9
|
var javascript = #{@javascript.to_json};
|
10
10
|
var execute = function(){
|
11
11
|
var ms = parent.parent.meteorStrike[channel];
|
12
|
-
if(ms) ms.
|
13
|
-
else setTimeout(
|
12
|
+
if(ms) ms.evaluate(javascript, #{params[:__s__]});
|
13
|
+
else setTimeout(evaluate, 0);
|
14
14
|
};
|
15
15
|
execute();
|
16
16
|
})();
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module MeteorStrike
|
2
|
+
module Controller
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
after_filter :meteor_strike
|
6
|
+
hide_action :meteor_strike
|
7
|
+
hide_action :install_meteor_strike
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def install_meteor_strike
|
12
|
+
if parent_controller
|
13
|
+
parent_controller.install_meteor_strike
|
14
|
+
else
|
15
|
+
@install_meteor_strike ||= 0
|
16
|
+
@install_meteor_strike += 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def meteor_strike
|
21
|
+
return unless @install_meteor_strike
|
22
|
+
result = <<-"EOH"
|
23
|
+
<script language="VBScript">
|
24
|
+
'<![CDATA[
|
25
|
+
On Error Resume Next
|
26
|
+
EOH
|
27
|
+
(1..@install_meteor_strike).each do |i|
|
28
|
+
result << <<-"EOH"
|
29
|
+
Sub meteor_strike_#{i}_FSCommand(ByVal command, ByVal args)
|
30
|
+
Call meteor_strike_#{i}_DoFSCommand(command, args)
|
31
|
+
End Sub
|
32
|
+
EOH
|
33
|
+
end
|
34
|
+
response.body.sub!(%r{</head>}i, "#{result}\n']]>\n</script></head>")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -18,7 +18,7 @@ module MeteorStrike
|
|
18
18
|
cc += 'post-check=0, pre-check=0'
|
19
19
|
controller.headers['Cache-Control'] = cc
|
20
20
|
end
|
21
|
-
@meteor_strike
|
21
|
+
@meteor_strike = controller.install_meteor_strike
|
22
22
|
config = Meteor::config
|
23
23
|
server = Meteor::server
|
24
24
|
shooting_star_uri = "#{server}/#{channel}"
|
@@ -27,17 +27,19 @@ module MeteorStrike
|
|
27
27
|
shooting_star_uri = [subdomain, shooting_star_uri].join('.')
|
28
28
|
end
|
29
29
|
uri = url_for(:only_path => false).split('/')[0..2].join('/')
|
30
|
-
uid = options[:uid] ?
|
30
|
+
uid = options[:uid] ? options[:uid].to_s : ''
|
31
|
+
escaped_uid = CGI.escape(uid)
|
31
32
|
tags = options[:tag] || []
|
32
33
|
tag = tags.map{|i| CGI.escape(i.to_s)}.join(',')
|
33
34
|
update_uri = "#{uri}/meteor/update"
|
34
|
-
|
35
|
+
now = Time.now
|
36
|
+
sig = "%d%06d" % [now.tv_sec, now.tv_usec]
|
35
37
|
iframe_id = "meteor-strike-#{@meteor_strike}"
|
36
38
|
host_port = (server.split(':') << '80')[0..1].join(':')
|
37
|
-
flash_vars = ["channel=#{channel}", "tag=#{tag}", "uid=#{
|
39
|
+
flash_vars = ["channel=#{channel}", "tag=#{tag}", "uid=#{escaped_uid}",
|
38
40
|
"sig=#{sig}", "base_uri=#{uri}", "server=#{host_port}",
|
39
|
-
"heartbeat=#{options[:heartbeat]}", "debug=#{options[:debug].to_json}"
|
40
|
-
|
41
|
+
"heartbeat=#{options[:heartbeat]}", "debug=#{options[:debug].to_json}",
|
42
|
+
"meteor_strike_id=#{@meteor_strike}"].join('&')
|
41
43
|
unless options[:noflash]
|
42
44
|
@flash_html = render :use_full_path => false,
|
43
45
|
:file => File.join(PLUGIN_ROOT, 'views/flash.rhtml'),
|
@@ -11,6 +11,7 @@
|
|
11
11
|
<input name="tag" /><input name="uid" /><input name="sig" />
|
12
12
|
<input name="heartbeat" value="<%= options[:heartbeat] %>" />
|
13
13
|
</form>
|
14
|
+
<div id="<%= iframe_id %>-flash"></div>
|
14
15
|
<%= javascript_tag %Q{
|
15
16
|
var meteorStrike = meteorStrike || $H();
|
16
17
|
meteorStrike.getFlashVersion = function(){
|
@@ -41,40 +42,53 @@
|
|
41
42
|
return $A(tags).uniq().map(encode).join(',');
|
42
43
|
};
|
43
44
|
var ms = meteorStrike[channel] = meteorStrike[channel] || new Object;
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
ms.getTags = function(){return TAGS};
|
46
|
+
ms.getUid = function(){return UID};
|
47
|
+
ms.executionQueue = {};
|
48
|
+
ms.executionCounter = 0;
|
49
|
+
ms.evaluate = function(js, serialId){
|
50
|
+
ms.executionQueue[serialId] = js;
|
51
|
+
if(serialId == ms.executionCounter){
|
52
|
+
while(js = ms.executionQueue[ms.executionCounter]){
|
53
|
+
eval(js);
|
54
|
+
delete ms.executionQueue[ms.executionCounter];
|
55
|
+
++ms.executionCounter;
|
52
56
|
}
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
channel: channel, uid: uid || UID,
|
58
|
-
tag: encodeTags(tags || TAGS), sig: #{sig.to_json}
|
59
|
-
}).toQueryString(), asynchronous: true});
|
60
|
-
UID = uid, TAGS = tags;
|
61
|
-
};
|
62
|
-
ms.tuneIn = function(tags){
|
63
|
-
ms.update(UID, TAGS.concat(tags || []).uniq());
|
64
|
-
};
|
65
|
-
ms.tuneOut = function(tags){
|
66
|
-
ms.update(UID, Array.prototype.without.apply(TAGS, tags));
|
67
|
-
};
|
68
|
-
ms.tuneInOut = function(tagsIn, tagsOut){
|
69
|
-
var tags = TAGS.concat(tagsIn || []).uniq();
|
70
|
-
ms.update(UID, Array.prototype.without.apply(tags, tagsOut));
|
71
|
-
};
|
72
|
-
ms.tuneOutIn = function(tagsOut, tagsIn){
|
73
|
-
var tags = Array.prototype.without.apply(TAGS, tagsOut);
|
74
|
-
ms.update(UID, tags.concat(tagsIn || []).uniq());
|
75
|
-
};
|
76
|
-
setTimeout(ms.connector = function(){
|
57
|
+
}
|
58
|
+
};
|
59
|
+
ms.event = function(params){
|
60
|
+
if(params.event == 'init'){
|
77
61
|
if(ms.connection) return;
|
62
|
+
if(ms.connecting && ms.connecting != params.type) return;
|
63
|
+
ms.connection = params.type;
|
64
|
+
}
|
65
|
+
(function(){#{options[:event]}})();
|
66
|
+
};
|
67
|
+
ms.update = function(uid, tags){
|
68
|
+
new Ajax.Request(#{update_uri.to_json}, {postBody: $H({
|
69
|
+
channel: channel, uid: uid || UID,
|
70
|
+
tag: encodeTags(tags || TAGS), sig: #{sig.to_json}
|
71
|
+
}).toQueryString(), asynchronous: true});
|
72
|
+
UID = uid, TAGS = tags;
|
73
|
+
};
|
74
|
+
ms.tuneIn = function(tags){
|
75
|
+
ms.update(UID, TAGS.concat(tags || []).uniq());
|
76
|
+
};
|
77
|
+
ms.tuneOut = function(tags){
|
78
|
+
ms.update(UID, Array.prototype.without.apply(TAGS, tags));
|
79
|
+
};
|
80
|
+
ms.tuneInOut = function(tagsIn, tagsOut){
|
81
|
+
var tags = TAGS.concat(tagsIn || []).uniq();
|
82
|
+
ms.update(UID, Array.prototype.without.apply(tags, tagsOut));
|
83
|
+
};
|
84
|
+
ms.tuneOutIn = function(tagsOut, tagsIn){
|
85
|
+
var tags = Array.prototype.without.apply(TAGS, tagsOut);
|
86
|
+
ms.update(UID, tags.concat(tagsIn || []).uniq());
|
87
|
+
};
|
88
|
+
Event.observe(window, 'load', function(){
|
89
|
+
setTimeout(ms.connector = function(){
|
90
|
+
if(ms.connection) return;
|
91
|
+
if(ms.connecting && ms.connecting != 'xhr') return;
|
78
92
|
var form = $("#{iframe_id}-form");
|
79
93
|
form.uid.value = #{uid.to_json};
|
80
94
|
form.tag.value = #{tag.to_json};
|
@@ -88,26 +102,23 @@
|
|
88
102
|
function meteor_strike_#{@meteor_strike}_DoFSCommand(command, args){
|
89
103
|
var ms = meteorStrike[#{channel.to_json}];
|
90
104
|
switch(command){
|
91
|
-
case 'execute':
|
105
|
+
case 'execute':
|
106
|
+
if(ms.connection == 'flash' || ms.connecting == 'flash') eval(args);
|
107
|
+
else if($('#{iframe_id}-flash')) Element.remove('#{iframe_id}-flash');
|
108
|
+
break;
|
92
109
|
case 'event':
|
93
|
-
|
110
|
+
switch(args){
|
111
|
+
case 'connect': // intercept xhr connection
|
112
|
+
ms.connecting = 'flash';
|
113
|
+
if(ms.connection != 'flash') ms.connection = null;
|
114
|
+
if($('#{iframe_id}')) Element.remove('#{iframe_id}');
|
115
|
+
break;
|
116
|
+
}
|
94
117
|
break;
|
95
118
|
}
|
96
119
|
}
|
97
|
-
if(navigator.appName && navigator.appName.indexOf("Microsoft") != -1 &&
|
98
|
-
navigator.userAgent.indexOf("Windows") != -1 &&
|
99
|
-
navigator.userAgent.indexOf("Windows 3.1") == -1){
|
100
|
-
document.write([
|
101
|
-
'<script language="VBScript"\\>',
|
102
|
-
'On Error Resume Next',
|
103
|
-
['Sub meteor_strike_', #{@meteor_strike},
|
104
|
-
'_FSCommand(ByVal command, ByVal args)'].join(''),
|
105
|
-
[' Call meteor_strike_', #{@meteor_strike},
|
106
|
-
'_DoFSCommand(command, args)'].join(''),
|
107
|
-
'End Sub', '</script\\>'].join(#{"\n".to_json}));
|
108
|
-
}
|
109
120
|
if(meteorStrike.getFlashVersion() >= 6){
|
110
|
-
|
121
|
+
$('#{iframe_id}-flash').innerHTML = #{@flash_html.to_json};
|
111
122
|
}
|
112
123
|
} %>
|
113
124
|
</div>
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.4
|
3
3
|
specification_version: 1
|
4
4
|
name: shooting_star
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 3.2.
|
7
|
-
date: 2007-08-
|
6
|
+
version: 3.2.2
|
7
|
+
date: 2007-08-30 00:00:00 +09:00
|
8
8
|
summary: Our goal is development of practical comet server which will be achieving over 100,000 simultaneous connections per host. On this purpose, we abandon portability and use system calls depending on particular OS such as epoll and kqueue.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- Rakefile
|
37
37
|
- bin/shooting_star
|
38
38
|
- lib/shooting_star.rb
|
39
|
+
- lib/shooting_star/version.rb
|
39
40
|
- lib/shooting_star/server.rb
|
40
41
|
- lib/shooting_star/shooter.rb
|
41
42
|
- lib/shooting_star/channel.rb
|
@@ -58,9 +59,12 @@ files:
|
|
58
59
|
- vendor/plugins/meteor_strike/lib/meteor_strike.rb
|
59
60
|
- vendor/plugins/meteor_strike/lib/meteor_strike
|
60
61
|
- vendor/plugins/meteor_strike/lib/meteor_strike/helper.rb
|
62
|
+
- vendor/plugins/meteor_strike/lib/meteor_strike/controller.rb
|
61
63
|
- vendor/plugins/meteor_strike/views
|
62
64
|
- vendor/plugins/meteor_strike/views/xhr.rhtml
|
63
65
|
- vendor/plugins/meteor_strike/views/flash.rhtml
|
66
|
+
- vendor/plugins/meteor_strike/tasks
|
67
|
+
- vendor/plugins/meteor_strike/tasks/meteor_strike.rake
|
64
68
|
- vendor/plugins/meteor_strike/test
|
65
69
|
- vendor/plugins/meteor_strike/test/meteor_strike_test.rb
|
66
70
|
- vendor/plugins/meteor_strike/generators
|
@@ -125,5 +129,5 @@ dependencies:
|
|
125
129
|
requirements:
|
126
130
|
- - ">="
|
127
131
|
- !ruby/object:Gem::Version
|
128
|
-
version: 1.
|
132
|
+
version: 1.3.0
|
129
133
|
version:
|