foxbat 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/em/connection.rb CHANGED
@@ -17,6 +17,14 @@ module EventMachine
17
17
  @netty_handler.write(data)
18
18
  end
19
19
 
20
+ def broadcast(data)
21
+ @netty_handler.write(data, true)
22
+ end
23
+
24
+ def send_file_data(path)
25
+ @netty_handler.send_file(path)
26
+ end
27
+
20
28
  def post_init; end
21
29
 
22
30
  def unbind; end
@@ -28,11 +36,7 @@ module EventMachine
28
36
  end
29
37
 
30
38
  def close_connection(after_writing=false)
31
- if after_writing
32
- @close_scheduled = true
33
- else
34
- @netty_handler.close
35
- end
39
+ @netty_handler.close
36
40
  end
37
41
 
38
42
  def close_connection_after_writing
@@ -44,7 +48,7 @@ module EventMachine
44
48
  end
45
49
 
46
50
  def comm_inactivity_timeout=(seconds)
47
- # todo
51
+ @netty_handler.set_read_timeout(seconds)
48
52
  end
49
53
 
50
54
  end
@@ -0,0 +1,210 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 16 Jul 2006
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+
26
+ module EventMachine
27
+ module Deferrable
28
+ autoload :Pool, 'em/deferrable/pool'
29
+
30
+ # Specify a block to be executed if and when the Deferrable object receives
31
+ # a status of :succeeded. See #set_deferred_status for more information.
32
+ #
33
+ # Calling this method on a Deferrable object whose status is not yet known
34
+ # will cause the callback block to be stored on an internal list.
35
+ # If you call this method on a Deferrable whose status is :succeeded, the
36
+ # block will be executed immediately, receiving the parameters given to the
37
+ # prior #set_deferred_status call.
38
+ #
39
+ #--
40
+ # If there is no status, add a callback to an internal list.
41
+ # If status is succeeded, execute the callback immediately.
42
+ # If status is failed, do nothing.
43
+ #
44
+ def callback &block
45
+ return unless block
46
+ @deferred_status ||= :unknown
47
+ if @deferred_status == :succeeded
48
+ block.call(*@deferred_args)
49
+ elsif @deferred_status != :failed
50
+ @callbacks ||= []
51
+ @callbacks.unshift block # << block
52
+ end
53
+ self
54
+ end
55
+
56
+ # Cancels an outstanding callback to &block if any. Undoes the action of #callback.
57
+ #
58
+ def cancel_callback block
59
+ @callbacks ||= []
60
+ @callbacks.delete block
61
+ end
62
+
63
+ # Specify a block to be executed if and when the Deferrable object receives
64
+ # a status of :failed. See #set_deferred_status for more information.
65
+ #--
66
+ # If there is no status, add an errback to an internal list.
67
+ # If status is failed, execute the errback immediately.
68
+ # If status is succeeded, do nothing.
69
+ #
70
+ def errback &block
71
+ return unless block
72
+ @deferred_status ||= :unknown
73
+ if @deferred_status == :failed
74
+ block.call(*@deferred_args)
75
+ elsif @deferred_status != :succeeded
76
+ @errbacks ||= []
77
+ @errbacks.unshift block # << block
78
+ end
79
+ self
80
+ end
81
+
82
+ # Cancels an outstanding errback to &block if any. Undoes the action of #errback.
83
+ #
84
+ def cancel_errback block
85
+ @errbacks ||= []
86
+ @errbacks.delete block
87
+ end
88
+
89
+ # Sets the "disposition" (status) of the Deferrable object. See also the large set of
90
+ # sugarings for this method.
91
+ # Note that if you call this method without arguments,
92
+ # no arguments will be passed to the callback/errback.
93
+ # If the user has coded these with arguments, then the
94
+ # user code will throw an argument exception.
95
+ # Implementors of deferrable classes <b>must</b>
96
+ # document the arguments they will supply to user callbacks.
97
+ #
98
+ # OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
99
+ # on the INSIDE of a callback. This is very useful when a previously-registered
100
+ # callback wants to change the parameters that will be passed to subsequently-registered
101
+ # ones.
102
+ #
103
+ # You may give either :succeeded or :failed as the status argument.
104
+ #
105
+ # If you pass :succeeded, then all of the blocks passed to the object using the #callback
106
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
107
+ # passed to the object using #errback will be discarded.
108
+ #
109
+ # If you pass :failed, then all of the blocks passed to the object using the #errback
110
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
111
+ # passed to the object using # callback will be discarded.
112
+ #
113
+ # If you pass any arguments to #set_deferred_status in addition to the status argument,
114
+ # they will be passed as arguments to any callbacks or errbacks that are executed.
115
+ # It's your responsibility to ensure that the argument lists specified in your callbacks and
116
+ # errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
117
+ # an ArgumentError.
118
+ #
119
+ #--
120
+ # We're shifting callbacks off and discarding them as we execute them.
121
+ # This is valid because by definition callbacks are executed no more than
122
+ # once. It also has the magic effect of permitting recursive calls, which
123
+ # means that a callback can call #set_deferred_status and change the parameters
124
+ # that will be sent to subsequent callbacks down the chain.
125
+ #
126
+ # Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
127
+ # by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
128
+ # versions.
129
+ #
130
+ # Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
131
+ # handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
132
+ # which only allows status to be set once. Prior to making this change, it was possible
133
+ # to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
134
+ # triggering its errbacks! That is clearly undesirable, but it's just as undesirable
135
+ # to raise an exception is status is set more than once on a Deferrable. The latter
136
+ # behavior would invalidate the idiom of resetting arguments by setting status from
137
+ # within a callback or errback, but more seriously it would cause spurious errors
138
+ # if a Deferrable was timed out and then an attempt was made to succeed it. See the
139
+ # comments under the new method #timeout.
140
+ #
141
+ def set_deferred_status status, *args
142
+ cancel_timeout
143
+ @errbacks ||= nil
144
+ @callbacks ||= nil
145
+ @deferred_status = status
146
+ @deferred_args = args
147
+ case @deferred_status
148
+ when :succeeded
149
+ if @callbacks
150
+ while cb = @callbacks.pop
151
+ cb.call(*@deferred_args)
152
+ end
153
+ end
154
+ @errbacks.clear if @errbacks
155
+ when :failed
156
+ if @errbacks
157
+ while eb = @errbacks.pop
158
+ eb.call(*@deferred_args)
159
+ end
160
+ end
161
+ @callbacks.clear if @callbacks
162
+ end
163
+ end
164
+
165
+
166
+ # Setting a timeout on a Deferrable causes it to go into the failed state after
167
+ # the Timeout expires (passing no arguments to the object's errbacks).
168
+ # Setting the status at any time prior to a call to the expiration of the timeout
169
+ # will cause the timer to be cancelled.
170
+ def timeout seconds, *args
171
+ cancel_timeout
172
+ me = self
173
+ @deferred_timeout = EventMachine::Timer.new(seconds) {me.fail(*args)}
174
+ self
175
+ end
176
+
177
+ # Cancels an outstanding timeout if any. Undoes the action of #timeout.
178
+ #
179
+ def cancel_timeout
180
+ @deferred_timeout ||= nil
181
+ if @deferred_timeout
182
+ @deferred_timeout.cancel
183
+ @deferred_timeout = nil
184
+ end
185
+ end
186
+
187
+
188
+ # Sugar for set_deferred_status(:succeeded, ...)
189
+ #
190
+ def succeed *args
191
+ set_deferred_status :succeeded, *args
192
+ end
193
+ alias set_deferred_success succeed
194
+
195
+ # Sugar for set_deferred_status(:failed, ...)
196
+ #
197
+ def fail *args
198
+ set_deferred_status :failed, *args
199
+ end
200
+ alias set_deferred_failure fail
201
+ end
202
+
203
+
204
+ # DefaultDeferrable is an otherwise empty class that includes Deferrable.
205
+ # This is very useful when you just need to return a Deferrable object
206
+ # as a way of communicating deferred status to some other part of a program.
207
+ class DefaultDeferrable
208
+ include Deferrable
209
+ end
210
+ end
data/lib/eventmachine.rb CHANGED
@@ -1,10 +1,13 @@
1
1
  import java.lang.Long
2
2
  import java.util.concurrent.Executors
3
3
  import java.util.concurrent.TimeUnit
4
+ import org.jboss.netty.util.HashedWheelTimer
5
+
6
+ require 'foxbat/future'
4
7
 
5
8
  module EventMachine
6
9
 
7
- def self.start_server host, port=nil, handler=nil, *args, &block
10
+ def self.start_server(host, port=nil, handler=nil, *args, &block)
8
11
  s = Foxbat::Server.new(host, port, handler, args.first || {}, &block)
9
12
 
10
13
  @@servers ||= []
@@ -13,6 +16,11 @@ module EventMachine
13
16
  s.start(@@threadpool)
14
17
  end
15
18
 
19
+ def self.connect(host, port=nil, handler=nil, *args, &block)
20
+ c = Foxbat::Client.new(host, port, handler, args.first || {}, &block)
21
+ c.start(@@threadpool)
22
+ end
23
+
16
24
  # We're on the JVM- this does nothing!
17
25
  def self.epoll; end
18
26
  def self.kqueue; end
@@ -20,24 +28,37 @@ module EventMachine
20
28
  def self.run(blk=nil, tail=nil, &block)
21
29
  @alive = true
22
30
  @@threadpool = Executors.newCachedThreadPool
31
+ @@timer = HashedWheelTimer.new
23
32
 
24
33
  block.call
25
34
 
26
35
  @@threadpool.awaitTermination(Long::MAX_VALUE, TimeUnit::SECONDS)
27
36
  end
28
37
 
38
+ def self.add_timer(*args, &block)
39
+ timeout = args.shift
40
+ callable = args.shift || block
41
+ task = lambda { |t| callable.call }
42
+ @@timer.newTimeout(task, timeout, TimeUnit::SECONDS)
43
+ end
44
+
29
45
  def self.stop
30
46
  @@servers.each { |s| s.stop }
31
47
  @@threadpool.shutdown
48
+ @@timer.stop
32
49
  end
33
50
 
34
- def self.executor
35
- @@threadpool
51
+ def self.defer(op, callback)
52
+ Foxbat::Future.schedule(op, callback, @@threadpool)
36
53
  end
37
54
 
38
55
  def self.reactor_running?
39
56
  @alive
40
57
  end
41
58
 
59
+ def self.connection_count
60
+ @@servers.map { |s| s.connection_count }.reduce(:+)
61
+ end
62
+
42
63
  end
43
64
 
@@ -0,0 +1,29 @@
1
+ import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory
2
+ import org.jboss.netty.bootstrap.ClientBootstrap
3
+
4
+ module Foxbat
5
+
6
+ class Client
7
+
8
+ def initialize(host, port, klass, options, &block)
9
+ if options[:secure]
10
+ @context = Security.setup_ssl_client_context
11
+ end
12
+
13
+ @group = DefaultChannelGroup.new
14
+ @address = InetSocketAddress.new(host, port)
15
+ @pipeline = Pipeline.new(klass, @group, true, options, @context, &block)
16
+ end
17
+
18
+ def start(threadpool)
19
+ factory = NioClientSocketChannelFactory.new(threadpool, threadpool)
20
+ @bootstrap = ClientBootstrap.new(factory)
21
+ @bootstrap.setPipelineFactory(@pipeline)
22
+ @bootstrap.setOption("child.tcpNoDelay", true)
23
+ @bootstrap.setOption("child.keepAlive", true)
24
+ @bootstrap.connect(@address)
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,15 @@
1
+ import com.google.common.util.concurrent.ListenableFutureTask
2
+
3
+ module Foxbat
4
+
5
+ class Future
6
+
7
+ def self.schedule(op, cb, executor)
8
+ future = ListenableFutureTask.create(op)
9
+ future.addListener(cb, executor)
10
+ executor.submit(future)
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ import java.net.InetSocketAddress
2
+ import org.jboss.netty.channel.group.DefaultChannelGroup
3
+ require_relative 'pipeline'
4
+ require_relative 'security'
5
+
6
+ module Foxbat
7
+
8
+ class GenericConnection
9
+
10
+
11
+
12
+ def start; end
13
+ end
14
+
15
+ end
@@ -0,0 +1,104 @@
1
+ import org.jboss.netty.handler.codec.http.HttpRequestDecoder
2
+ import org.jboss.netty.handler.codec.http.HttpResponseEncoder
3
+ import org.jboss.netty.handler.codec.http.HttpContentCompressor
4
+ import org.jboss.netty.channel.Channels
5
+ import org.jboss.netty.channel.ChannelPipelineFactory
6
+ import org.jboss.netty.buffer.ChannelBuffers
7
+ import org.jboss.netty.handler.codec.http.DefaultHttpResponse
8
+ import org.jboss.netty.handler.codec.http.HttpResponseStatus
9
+ import org.jboss.netty.handler.codec.http.HttpVersion
10
+ import org.jboss.netty.handler.codec.http.HttpHeaders
11
+
12
+ require_relative 'server'
13
+
14
+ module Foxbat
15
+
16
+ class WebPipeline
17
+ include ChannelPipelineFactory
18
+
19
+ HANDLER = "handler"
20
+ ENCODER = "encoder"
21
+ DECODER = "decoder"
22
+ DEFLATER = "deflater"
23
+
24
+ def initialize(app)
25
+ @app = app
26
+ @handler = ReadTimeoutHandler.new(EM.timer, 10)
27
+ end
28
+
29
+ def getPipeline
30
+ pipeline = Channels.pipeline
31
+ pipeline.addLast(DECODER, HttpRequestDecoder.new)
32
+ pipeline.addLast(ENCODER, HttpResponseEncoder.new)
33
+ pipeline.addLast(DEFLATER, HttpContentCompressor.new)
34
+ pipeline.addLast(HANDLER, WebHandler.new(@app))
35
+ pipeline
36
+ end
37
+ end
38
+
39
+ class WebHandler < SimpleChannelUpstreamHandler
40
+
41
+ def initialize(app)
42
+ super()
43
+ @app = app
44
+ end
45
+
46
+ def messageReceived(ctx, e)
47
+ req = e.getMessage
48
+ env = to_rack(req)
49
+ val = @app.call(env)
50
+
51
+ resp = to_netty(val)
52
+ future = e.getChannel.write(resp)
53
+
54
+ listener = Object.new
55
+ def listener.operationComplete(f)
56
+ f.getChannel.close
57
+ end
58
+
59
+ future.addListener(listener)
60
+ end
61
+
62
+ private
63
+
64
+ def to_rack(req)
65
+ env = {}
66
+ env['REQUEST_METHOD'] = req.getMethod.toString
67
+
68
+ req.getHeaders.each do |h|
69
+ header = "HTTP_" + h.getKey.upcase.gsub("-", "_")
70
+ env[header] = h.getValue
71
+ end
72
+ env
73
+ end
74
+
75
+ CODES = {200 => HttpResponseStatus::OK}
76
+
77
+ def to_netty(resp)
78
+ code, headers, content = resp
79
+
80
+ netty_response = DefaultHttpResponse.new(HttpVersion::HTTP_1_1, CODES[code])
81
+ headers.each do |k,v|
82
+ netty_response.setHeader(k, v)
83
+ end
84
+
85
+ content = content.to_java_bytes if content.is_a?(String)
86
+ buf = ChannelBuffers.copiedBuffer(content)
87
+ netty_response.setContent(buf)
88
+ netty_response.setHeader('Content-Length', buf.writerIndex)
89
+ netty_response.setHeader('Server', 'Foxbat')
90
+ netty_response
91
+ end
92
+ end
93
+
94
+ class HttpServer < Server
95
+
96
+ def initialize(host, port, klass, options, &block)
97
+ super(host, port, klass, options, &block)
98
+ @pipeline.releaseExternalResources
99
+ @pipeline = WebPipeline.new(block)
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -1,5 +1,7 @@
1
+ import java.io.RandomAccessFile
1
2
  import java.nio.ByteBuffer
2
3
  import org.jboss.netty.buffer.ChannelBuffers
4
+ import org.jboss.netty.channel.DefaultFileRegion
3
5
  import org.jboss.netty.channel.SimpleChannelUpstreamHandler
4
6
 
5
7
  module Foxbat
@@ -13,21 +15,37 @@ module Foxbat
13
15
  super()
14
16
  end
15
17
 
16
- def write(data)
18
+ def write(data, broadcast=false)
17
19
  data = data.to_java_bytes if data.is_a?(String)
18
20
  buf = ChannelBuffers.copiedBuffer(data)
19
- @channel.write(buf)
21
+
22
+ recipient = broadcast ? @group : @channel
23
+ recipient.write(buf)
24
+ end
25
+
26
+ def send_file(path)
27
+ file_channel = RandomAccessFile.new(path, 'r').getChannel
28
+ region = DefaultFileRegion.new(file_channel, 0, file_channel.size, true)
29
+ @channel.write(region)
20
30
  end
21
31
 
22
32
  def close
23
33
  @channel.close
24
34
  end
25
35
 
36
+ def set_read_timeout(seconds)
37
+
38
+ end
39
+
26
40
  private
27
41
 
28
42
  def channelOpen(ctx, e)
29
43
  @group.add(e.getChannel)
30
44
  end
45
+
46
+ def channelClosed(ctx, e)
47
+ @group.remove(e.getChannel)
48
+ end
31
49
 
32
50
  def channelConnected(ctx, e)
33
51
  @pipeline = ctx.getPipeline
@@ -10,9 +10,19 @@ module Foxbat
10
10
  class Pipeline
11
11
  include ChannelPipelineFactory
12
12
 
13
- def initialize(handler, group, options={}, ssl_context=nil, &block)
13
+ HANDLER = "handler"
14
+ SSL_HANDLER = "ssl"
15
+
16
+ def initialize(handler, group, client, options={}, ssl_context=nil, &block)
14
17
  @options = options
15
18
  @handler = handler
19
+ @client_mode = client
20
+
21
+ if handler.class == Module
22
+ @handler = Class.new(EM::Connection)
23
+ @handler.send(:include, handler)
24
+ end
25
+
16
26
  @group = group
17
27
  @block = block
18
28
  @context = ssl_context
@@ -21,18 +31,19 @@ module Foxbat
21
31
  def getPipeline
22
32
  pipeline = Channels.pipeline
23
33
  if @context
24
- engine = Security.create_ssl_engine(@context)
25
- pipeline.addLast("ssl", SslHandler.new(engine))
34
+ engine = Security.create_ssl_engine(@context, @client_mode)
35
+ pipeline.addLast(SSL_HANDLER, SslHandler.new(engine))
26
36
  end
37
+
27
38
  h = @handler.new(@options)
28
39
  @block.call(h) if @block
29
40
  connection = NettyConnection.new(h, @group)
30
- pipeline.addLast("handler", connection)
41
+ pipeline.addLast(HANDLER, connection)
31
42
  pipeline
32
43
  end
33
44
 
34
45
  def releaseExternalResources
35
- p 'cleaning up factory...'
46
+ # todo
36
47
  end
37
48
  end
38
49
 
@@ -24,8 +24,9 @@ module Foxbat
24
24
  end
25
25
  fis.close
26
26
 
27
- kmf = KeyManagerFactory.getInstance('SunX509')
28
- tmf = TrustManagerFactory.getInstance('SunX509')
27
+ algorithm = KeyManagerFactory.getDefaultAlgorithm
28
+ kmf = KeyManagerFactory.getInstance(algorithm)
29
+ tmf = TrustManagerFactory.getInstance(algorithm)
29
30
 
30
31
  kmf.init(keystore, password)
31
32
  tmf.init(keystore)
@@ -43,10 +44,20 @@ module Foxbat
43
44
  context.init(kmf.getKeyManagers, tmf.getTrustManagers, nil)
44
45
  context
45
46
  end
46
-
47
- def self.create_ssl_engine(context)
48
- engine = context.createSSLEngine
49
- engine.setUseClientMode(false)
47
+
48
+ def self.setup_ssl_client_context
49
+ # keystore = KeyStore.getInstance(KeyStore.getDefaultType)
50
+ # context = SSLContext.getInstance('TLSv1')
51
+ # tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
52
+ # tmf.init(keystore)
53
+ # context.init(nil, nil, nil)
54
+ # context
55
+ SSLContext.getDefault
56
+ end
57
+
58
+ def self.create_ssl_engine(context, client=false)
59
+ context.createSSLEngine
60
+ engine.setUseClientMode(client)
50
61
  engine.setNeedClientAuth(false)
51
62
  engine
52
63
  end
data/lib/foxbat/server.rb CHANGED
@@ -3,12 +3,10 @@ import org.jboss.netty.channel.group.DefaultChannelGroup
3
3
  import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory
4
4
  import org.jboss.netty.bootstrap.ServerBootstrap
5
5
  require_relative 'pipeline'
6
- require_relative 'security'
7
6
 
8
7
  module Foxbat
9
8
 
10
9
  class Server
11
-
12
10
  def initialize(host, port, klass, options, &block)
13
11
  if options[:secure]
14
12
  @context = Security.setup_ssl_context(options[:keystore])
@@ -16,15 +14,21 @@ module Foxbat
16
14
 
17
15
  @group = DefaultChannelGroup.new
18
16
  @address = InetSocketAddress.new(host, port)
19
- @pipeline = Pipeline.new(klass, @group, options, @context, &block)
17
+ @pipeline = Pipeline.new(klass, @group, false, options, @context, &block)
20
18
  end
21
-
19
+
22
20
  def start(threadpool)
23
- @factory = NioServerSocketChannelFactory.new(threadpool, threadpool)
24
- @bootstrap = ServerBootstrap.new(@factory)
21
+ sp = java.util.concurrent.Executors.newSingleThreadExecutor
22
+ factory = NioServerSocketChannelFactory.new(sp, threadpool)
23
+ @bootstrap = ServerBootstrap.new(factory)
25
24
  @bootstrap.setPipelineFactory(@pipeline)
26
- @server_channel = @bootstrap.bind(@address)
27
- @group.add(@server_channel)
25
+ @bootstrap.setOption("child.tcpNoDelay", true)
26
+ server_channel = @bootstrap.bind(@address)
27
+ @group.add(server_channel)
28
+ end
29
+
30
+ def connection_count
31
+ @group.size - 1 # -1 to exclude the server's channel
28
32
  end
29
33
 
30
34
  def stop
@@ -1,3 +1,3 @@
1
1
  module Foxbat
2
- VERSION = '0.2.4'
2
+ VERSION = '0.2.5'
3
3
  end
data/lib/foxbat.rb CHANGED
@@ -1,45 +1,53 @@
1
1
  require 'java'
2
2
 
3
- NETTY_VERSION = '3.5.0.Final'
4
- JAR_SIZE = 1110903.0 # TODO: remove hard-coded jar size
5
-
6
- netty_jar = File.dirname(__FILE__) + "/netty-#{NETTY_VERSION}.jar"
3
+ unless Kernel.respond_to?(:require_relative)
4
+ module Kernel
5
+ def require_relative(path)
6
+ require File.join(File.dirname(caller[0]), path.to_str)
7
+ end
8
+ end
9
+ end
7
10
 
8
- if !File.exist?(netty_jar)
9
- puts "Couldn't find netty's JAR to load. Let's download it now."
11
+ def require_or_get(lib, version, ns)
12
+ jar = "#{lib}-#{version}.jar"
13
+ jarpath = File.dirname(__FILE__) + '/' + jar
14
+ if !File.exist?(jarpath)
15
+ puts "Couldn't find #{lib}, let's download it now."
10
16
 
11
- require 'net/http'
12
- f = open(netty_jar, 'w')
13
-
14
- Net::HTTP.start('search.maven.org') do |http|
15
-
16
- begin
17
- http.request_get("/remotecontent?filepath=io/netty/netty/#{NETTY_VERSION}/netty-#{NETTY_VERSION}.jar") do |resp|
18
- acc = 0
19
- resp.read_body do |segment|
20
- acc += segment.length
21
- percent = ((acc / JAR_SIZE) * 100).to_i
22
- print "Downloading netty #{NETTY_VERSION} from maven repository... [#{percent}%]\r"
23
- f.write(segment)
17
+ require 'net/http'
18
+ f = open(jarpath, 'w')
19
+
20
+ Net::HTTP.start('search.maven.org') do |http|
21
+
22
+ begin
23
+ http.request_get("/remotecontent?filepath=#{ns}/#{lib}/#{version}/#{jar}") do |resp|
24
+ puts "Downloading #{jar} from maven repository..."
25
+ resp.read_body do |segment|
26
+ f.write(segment)
27
+ end
28
+ puts "Done."
24
29
  end
25
- puts "\nDone. You shouldn't see me again :)"
30
+ ensure
31
+ f.close()
26
32
  end
27
- ensure
28
- f.close()
29
33
  end
30
34
  end
35
+
36
+ require jar
31
37
  end
32
38
 
33
- require 'netty-3.5.0.Final.jar'
39
+ require_or_get 'netty', '3.5.0.Final', 'io/netty'
40
+ require_or_get 'guava', '13.0.1', 'com/google/guava'
34
41
 
35
42
  require 'em/connection'
43
+ require 'em/deferrable'
36
44
  require 'em/periodic_timer'
37
45
  require 'em/timer'
46
+ require 'foxbat/client'
38
47
  require 'foxbat/server'
39
48
  require 'foxbat/version'
40
- require_relative 'eventmachine'
41
-
42
49
 
50
+ require_relative 'eventmachine'
43
51
 
44
52
  module EventMachine; end
45
53
 
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foxbat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-18 00:00:00.000000000 Z
12
+ date: 2012-11-12 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A drop-in replacement for EM, providing functionality missing from the
15
15
  Java port.
@@ -22,15 +22,21 @@ files:
22
22
  - lib/eventmachine.rb
23
23
  - lib/foxbat/barrier.rb
24
24
  - lib/foxbat/version.rb
25
+ - lib/foxbat/generic_connection.rb
26
+ - lib/foxbat/client.rb
25
27
  - lib/foxbat/server.rb
28
+ - lib/foxbat/http_server.rb
26
29
  - lib/foxbat/pipeline.rb
30
+ - lib/foxbat/future.rb
27
31
  - lib/foxbat/netty_connection.rb
28
32
  - lib/foxbat/security.rb
29
33
  - lib/netty-3.5.0.Final.jar
30
34
  - lib/foxbat.rb
31
35
  - lib/em/periodic_timer.rb
32
36
  - lib/em/timer.rb
37
+ - lib/em/deferrable.rb
33
38
  - lib/em/connection.rb
39
+ - lib/guava-13.0.1.jar
34
40
  homepage: http://github.com/m0wfo/foxbat
35
41
  licenses: []
36
42
  post_install_message: