cool.io 0.9.0 → 1.0.0

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/CHANGES CHANGED
@@ -1,3 +1,7 @@
1
+ 1.0.0:
2
+
3
+ * Fancy new DSL
4
+
1
5
  0.9.0:
2
6
 
3
7
  * Rename the project to cool.io
@@ -12,6 +16,8 @@
12
16
 
13
17
  * Update to libev 4.01
14
18
 
19
+ * Initial Rubinius support
20
+
15
21
  0.3.2:
16
22
 
17
23
  * Perform a blocking system call if we're the only thread running (1.8 only)
@@ -1,4 +1,175 @@
1
1
  Cool.io
2
2
  =======
3
3
 
4
- This page intentionally left blank... for now
4
+ [http://coolio.github.com](http://coolio.github.com)
5
+
6
+ Cool.io is an event library for Ruby, built on the libev event library which
7
+ provides a cross-platform interface to high performance system calls . This
8
+ includes the epoll system call for Linux, the kqueue system call for BSDs and
9
+ OS X, and the completion ports interface for Solaris.
10
+
11
+ Cool.io also binds asynchronous wrappers to Ruby's core socket classes so you can
12
+ use them in conjunction with Cool.io to build asynchronous event-driven
13
+ applications.
14
+
15
+ You can include Cool.io in your programs with:
16
+
17
+ require 'rubygems'
18
+ require 'cool.io'
19
+
20
+ Questions? Sign up for the mailing list by emailing: [cool.io@librelist.com](mailto:cool.io@librelist.com)
21
+
22
+ The latest development code is available via github at:
23
+
24
+ [git://github.com/tarcieri/cool.io.git](git://github.com/tarcieri/cool.io.git)
25
+
26
+ Anatomy
27
+ -------
28
+
29
+ Cool.io builds on two core classes which bind to the libev API:
30
+
31
+ * Cool.io::Loop - This class represents an event loop which uses underlying high
32
+ performance system calls to wait for events.
33
+
34
+ * Cool.io::Watcher - This is the base class for event observers. Once you attach
35
+ an event observer to a loop and start running it, you will begin receiving
36
+ callbacks to particlar methods when events occur.
37
+
38
+ Watchers
39
+ --------
40
+
41
+ There are presently four types of watchers:
42
+
43
+ * Cool.io::IOWatcher - This class waits for an IO object to become readable,
44
+ writable, or both.
45
+
46
+ * Cool.io::TimerWatcher - This class waits for a specified duration then fires
47
+ an event. You can also configure it to fire an event at specified intervals.
48
+
49
+ * Cool.io::StatWatcher - Monitors files or directories for changes
50
+
51
+ * Cool.io::AsyncWatcher - Can be used to wake up a Cool.io::Loop running in a
52
+ different thread. This allows each thread to run a separate Cool.io::Loop and
53
+ for the different event loops to be able to signal each other.
54
+
55
+ Using Watchers
56
+ --------------
57
+
58
+ Watchers have five important methods:
59
+
60
+ * attach(loop) - This binds a watcher to the specified event loop. If the
61
+ watcher is already bound to a loop it will be detached first, then attached
62
+ to the new one.
63
+
64
+ * detach - This completely unbinds a watcher from an event loop.
65
+
66
+ * disable - This stops the watcher from receiving events but does not unbind
67
+ it from the loop. If you are trying to toggle a watcher on and off, it's
68
+ best to use this method (and enable) as it performs better than completely
69
+ removing the watcher from the event loop.
70
+
71
+ * enable - This re-enables a watcher which has been disabled in the past.
72
+ The watcher must still be bound to an event loop.
73
+
74
+ * evloop - This returns the Cool.io::Loop object which the watcher is currently
75
+ bound to.
76
+
77
+ Asynchronous Wrappers
78
+ ---------------------
79
+
80
+ Several classes which provide asynchronous event-driven wrappers for Ruby's
81
+ core socket classes are also provided. Among these are:
82
+
83
+ * Cool.io::TCPSocket - A buffered wrapper to core Ruby's Socket class for use with
84
+ TCP sockets. You can asynchronously create outgoing TCP connections using
85
+ its Cool.io::TCPSocket.connect method. Cool.io::TCPSocket provides write buffering
86
+ to ensure that writing never blocks, and has asynchronous callbacks for
87
+ several events, including when the connection is opened (or failed), when
88
+ data is received, when the write buffer has been written out completely,
89
+ and when the connection closes.
90
+
91
+ * Cool.io::TCPServer - A wrapper for TCPServer which creates new instances of
92
+ Cool.io::TCPSocket (or any subclass you wish to provide) whenever an incoming
93
+ connection is received.
94
+
95
+ * Cool.io::HttpClient - An HTTP/1.1 client with support for chunked encoding
96
+ and streaming response processing through asynchronous callbacks.
97
+
98
+ Example Program
99
+ ---------------
100
+
101
+ Cool.io provides a Sinatra-like DSL for authoring event-driven programs:
102
+
103
+ require 'rubygems'
104
+ require 'cool.io'
105
+
106
+ ADDR = '127.0.0.1'
107
+ PORT = 4321
108
+
109
+ cool.io.connection :echo_server_connection do
110
+ on_connect do
111
+ puts "#{remote_addr}:#{remote_port} connected"
112
+ end
113
+
114
+ on_close do
115
+ puts "#{remote_addr}:#{remote_port} disconnected"
116
+ end
117
+
118
+ on_read do |data|
119
+ write data
120
+ end
121
+ end
122
+
123
+ puts "Echo server listening on #{ADDR}:#{PORT}"
124
+ cool.io.server ADDR, PORT, :echo_server_connection
125
+ cool.io.run
126
+
127
+ This creates a new connection class called :echo_server_connection and defines
128
+ a set of callbacks for when various events occur.
129
+
130
+ We then create a new server on the given address and port. When this server
131
+ receives new connections, it will create new instances of the given connection
132
+ class for each connection.
133
+
134
+ Finally, we kick everything off with cool.io.run. Calling cool.io.run will
135
+ block, listening for events on our server.
136
+
137
+ Using Cool.io subclasses directly
138
+ ---------------------------------
139
+
140
+ Below is an example of how to write an echo server using a subclass instead of
141
+ the DSL:
142
+
143
+ require 'cool.io'
144
+ HOST = 'localhost'
145
+ PORT = 4321
146
+
147
+ class EchoServerConnection < Cool.io::TCPSocket
148
+ def on_connect
149
+ puts "#{remote_addr}:#{remote_port} connected"
150
+ end
151
+
152
+ def on_close
153
+ puts "#{remote_addr}:#{remote_port} disconnected"
154
+ end
155
+
156
+ def on_read(data)
157
+ write data
158
+ end
159
+ end
160
+
161
+ server = Cool.io::TCPServer.new(HOST, PORT, EchoServerConnection)
162
+ server.attach(Cool.io::Loop.default)
163
+
164
+ puts "Echo server listening on #{HOST}:#{PORT}"
165
+ Cool.io::Loop.default.run
166
+
167
+ Here a new observer type (EchoServerConnection) is made by subclassing an
168
+ existing one and adding new implementations to existing event handlers.
169
+
170
+ A new event loop is created, and a new Cool.io::TCPServer (whose base class is
171
+ Cool.io::Watcher) is created and attached to the event loop.
172
+
173
+ Once this is done, the event loop is started with event_loop.run. This method
174
+ will block until there are no active watchers for the loop or the loop is
175
+ stopped explicitly with event_loop.stop.
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ begin
12
12
  gem.homepage = "http://github.com/tarcieri/cool.io"
13
13
  gem.authors = ["Tony Arcieri"]
14
14
  gem.add_dependency "iobuffer", ">= 0.1.3"
15
- gem.add_development_dependency "rspec", "~> 2.0.0"
15
+ gem.add_development_dependency "rspec", ">= 2.1.0"
16
16
  gem.extensions = FileList["ext/**/extconf.rb"].to_a
17
17
 
18
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0
1
+ 1.0.0
@@ -0,0 +1,138 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cool.io}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tony Arcieri"]
12
+ s.date = %q{2010-12-13}
13
+ s.description = %q{A Ruby wrapper around the libev high performance event library}
14
+ s.email = %q{tony@medioh.com}
15
+ s.extensions = ["ext/cool.io/extconf.rb", "ext/http11_client/extconf.rb"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.markdown"
19
+ ]
20
+ s.files = [
21
+ "CHANGES",
22
+ "LICENSE",
23
+ "README.markdown",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "cool.io.gemspec",
27
+ "examples/dslified_echo_client.rb",
28
+ "examples/dslified_echo_server.rb",
29
+ "examples/echo_client.rb",
30
+ "examples/echo_server.rb",
31
+ "examples/google.rb",
32
+ "examples/httpclient.rb",
33
+ "ext/cool.io/.gitignore",
34
+ "ext/cool.io/cool.io.h",
35
+ "ext/cool.io/cool.io_ext.c",
36
+ "ext/cool.io/ev_wrap.h",
37
+ "ext/cool.io/extconf.rb",
38
+ "ext/cool.io/iowatcher.c",
39
+ "ext/cool.io/libev.c",
40
+ "ext/cool.io/loop.c",
41
+ "ext/cool.io/stat_watcher.c",
42
+ "ext/cool.io/timer_watcher.c",
43
+ "ext/cool.io/utils.c",
44
+ "ext/cool.io/watcher.c",
45
+ "ext/cool.io/watcher.h",
46
+ "ext/http11_client/.gitignore",
47
+ "ext/http11_client/LICENSE",
48
+ "ext/http11_client/ext_help.h",
49
+ "ext/http11_client/extconf.rb",
50
+ "ext/http11_client/http11_client.c",
51
+ "ext/http11_client/http11_parser.c",
52
+ "ext/http11_client/http11_parser.h",
53
+ "ext/http11_client/http11_parser.rl",
54
+ "ext/libev/Changes",
55
+ "ext/libev/LICENSE",
56
+ "ext/libev/README",
57
+ "ext/libev/README.embed",
58
+ "ext/libev/ev.c",
59
+ "ext/libev/ev.h",
60
+ "ext/libev/ev_epoll.c",
61
+ "ext/libev/ev_kqueue.c",
62
+ "ext/libev/ev_poll.c",
63
+ "ext/libev/ev_port.c",
64
+ "ext/libev/ev_select.c",
65
+ "ext/libev/ev_vars.h",
66
+ "ext/libev/ev_win32.c",
67
+ "ext/libev/ev_wrap.h",
68
+ "ext/libev/test_libev_win32.c",
69
+ "lib/.gitignore",
70
+ "lib/cool.io.rb",
71
+ "lib/cool.io/async_watcher.rb",
72
+ "lib/cool.io/dns_resolver.rb",
73
+ "lib/cool.io/dsl.rb",
74
+ "lib/cool.io/eventmachine.rb",
75
+ "lib/cool.io/http_client.rb",
76
+ "lib/cool.io/io.rb",
77
+ "lib/cool.io/iowatcher.rb",
78
+ "lib/cool.io/listener.rb",
79
+ "lib/cool.io/loop.rb",
80
+ "lib/cool.io/meta.rb",
81
+ "lib/cool.io/server.rb",
82
+ "lib/cool.io/socket.rb",
83
+ "lib/cool.io/timer_watcher.rb",
84
+ "lib/coolio.rb",
85
+ "lib/rev.rb",
86
+ "spec/async_watcher_spec.rb",
87
+ "spec/dns_spec.rb",
88
+ "spec/possible_tests/schedules_other_threads.rb",
89
+ "spec/possible_tests/test_on_resolve_failed.rb",
90
+ "spec/possible_tests/test_resolves.rb",
91
+ "spec/possible_tests/test_write_during_resolve.rb",
92
+ "spec/possible_tests/works_straight.rb",
93
+ "spec/spec_helper.rb",
94
+ "spec/timer_watcher_spec.rb",
95
+ "spec/unix_listener_spec.rb",
96
+ "spec/unix_server_spec.rb"
97
+ ]
98
+ s.homepage = %q{http://github.com/tarcieri/cool.io}
99
+ s.require_paths = ["lib"]
100
+ s.rubygems_version = %q{1.3.7}
101
+ s.summary = %q{The cool event framework for Ruby}
102
+ s.test_files = [
103
+ "examples/dslified_echo_client.rb",
104
+ "examples/dslified_echo_server.rb",
105
+ "examples/echo_client.rb",
106
+ "examples/echo_server.rb",
107
+ "examples/google.rb",
108
+ "examples/httpclient.rb",
109
+ "spec/async_watcher_spec.rb",
110
+ "spec/dns_spec.rb",
111
+ "spec/possible_tests/schedules_other_threads.rb",
112
+ "spec/possible_tests/test_on_resolve_failed.rb",
113
+ "spec/possible_tests/test_resolves.rb",
114
+ "spec/possible_tests/test_write_during_resolve.rb",
115
+ "spec/possible_tests/works_straight.rb",
116
+ "spec/spec_helper.rb",
117
+ "spec/timer_watcher_spec.rb",
118
+ "spec/unix_listener_spec.rb",
119
+ "spec/unix_server_spec.rb"
120
+ ]
121
+
122
+ if s.respond_to? :specification_version then
123
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
124
+ s.specification_version = 3
125
+
126
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
127
+ s.add_runtime_dependency(%q<iobuffer>, [">= 0.1.3"])
128
+ s.add_development_dependency(%q<rspec>, [">= 2.1.0"])
129
+ else
130
+ s.add_dependency(%q<iobuffer>, [">= 0.1.3"])
131
+ s.add_dependency(%q<rspec>, [">= 2.1.0"])
132
+ end
133
+ else
134
+ s.add_dependency(%q<iobuffer>, [">= 0.1.3"])
135
+ s.add_dependency(%q<rspec>, [">= 2.1.0"])
136
+ end
137
+ end
138
+
@@ -0,0 +1,34 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ ADDR = '127.0.0.1'
7
+ PORT = 4321
8
+
9
+ cool.io.connect ADDR, PORT do
10
+ on_connect do
11
+ puts "Connected to #{remote_host}:#{remote_port}"
12
+ write "bounce this back to me"
13
+ end
14
+
15
+ on_close do
16
+ puts "Disconnected from #{remote_host}:#{remote_port}"
17
+ end
18
+
19
+ on_read do |data|
20
+ puts "Got: #{data}"
21
+ close
22
+ end
23
+
24
+ on_resolve_failed do
25
+ puts "Error: Couldn't resolve #{remote_host}"
26
+ end
27
+
28
+ on_connect_failed do
29
+ puts "Error: Connection refused to #{remote_host}:#{remote_port}"
30
+ end
31
+ end
32
+
33
+ puts "Echo client connecting to #{ADDR}:#{PORT}..."
34
+ cool.io.run
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ ADDR = '127.0.0.1'
7
+ PORT = 4321
8
+
9
+ cool.io.server ADDR, PORT do
10
+ on_connect do
11
+ puts "#{remote_addr}:#{remote_port} connected"
12
+ end
13
+
14
+ on_close do
15
+ puts "#{remote_addr}:#{remote_port} disconnected"
16
+ end
17
+
18
+ on_read do |data|
19
+ write data
20
+ end
21
+ end
22
+
23
+ puts "Echo server listening on #{ADDR}:#{PORT}"
24
+ cool.io.run
@@ -6,7 +6,7 @@ require 'cool.io'
6
6
  ADDR = '127.0.0.1'
7
7
  PORT = 4321
8
8
 
9
- class ClientConnection < Coolio::TCPSocket
9
+ class ClientConnection < Cool.io::TCPSocket
10
10
  def on_connect
11
11
  puts "#{remote_addr}:#{remote_port} connected"
12
12
  write "bounce this back to me"
@@ -31,7 +31,7 @@ class ClientConnection < Coolio::TCPSocket
31
31
 
32
32
  end
33
33
 
34
- event_loop = Coolio::Loop.default
34
+ event_loop = Cool.io::Loop.default
35
35
  client = ClientConnection.connect(ADDR, PORT)
36
36
  client.attach(event_loop)
37
37
  puts "Echo client connecting to #{ADDR}:#{PORT}..."
@@ -6,7 +6,7 @@ require 'cool.io'
6
6
  ADDR = '127.0.0.1'
7
7
  PORT = 4321
8
8
 
9
- class EchoServerConnection < Coolio::TCPSocket
9
+ class EchoServerConnection < Cool.io::TCPSocket
10
10
  def on_connect
11
11
  puts "#{remote_addr}:#{remote_port} connected"
12
12
  end
@@ -20,8 +20,8 @@ class EchoServerConnection < Coolio::TCPSocket
20
20
  end
21
21
  end
22
22
 
23
- event_loop = Coolio::Loop.default
24
- Coolio::TCPServer.new(ADDR, PORT, EchoServerConnection).attach(event_loop)
23
+ event_loop = Cool.io::Loop.default
24
+ Cool.io::TCPServer.new(ADDR, PORT, EchoServerConnection).attach(event_loop)
25
25
 
26
26
  puts "Echo server listening on #{ADDR}:#{PORT}"
27
27
  event_loop.run
@@ -274,9 +274,7 @@ static VALUE Coolio_Loop_run_nonblock(VALUE self)
274
274
 
275
275
  assert(loop_data->ev_loop && !loop_data->events_received);
276
276
 
277
- TRAP_BEG;
278
277
  RUN_LOOP(loop_data, EVLOOP_NONBLOCK);
279
- TRAP_END;
280
278
  Coolio_Loop_dispatch_events(loop_data);
281
279
 
282
280
  nevents = INT2NUM(loop_data->events_received);
@@ -0,0 +1,31 @@
1
+ Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are
6
+ met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ * Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
16
+ of its contributors may be used to endorse or promote products
17
+ derived from this software without specific prior written
18
+ permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
24
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+
@@ -18,10 +18,12 @@ require "cool.io/dns_resolver"
18
18
  require "cool.io/socket"
19
19
  require "cool.io/server"
20
20
  require "cool.io/http_client"
21
+ require "cool.io/dsl"
21
22
 
22
23
  module Coolio
23
24
  VERSION = File.read(File.expand_path('../../VERSION', __FILE__)).strip
24
25
  def self.version; VERSION; end
26
+ def self.inspect; "Cool.io"; end
25
27
  end
26
28
 
27
29
  module Cool
@@ -0,0 +1,135 @@
1
+ #--
2
+ # Copyright (C)2010 Tony Arcieri
3
+ # You can redistribute this under the terms of the Ruby license
4
+ # See file LICENSE for details
5
+ #++
6
+
7
+ module Coolio
8
+ # A module we stash all the connections defined by the DSL under
9
+ module Connections; end
10
+
11
+ # A DSL for defining Cool.io connection types and servers
12
+ module DSL
13
+ # Define all methods on the metaclass
14
+ module_function
15
+
16
+ # Run the default Cool.io event loop
17
+ def run
18
+ Cool.io::Loop.default.run
19
+ end
20
+
21
+ # Connect to the given host and port using the given connection class
22
+ def connect(host, port, connection_name = nil, *initializer_args, &block)
23
+ if block_given?
24
+ initializer_args.unshift connection_name if connection_name
25
+
26
+ klass = Class.new Cool.io::TCPSocket
27
+ connection_builder = ConnectionBuilder.new klass
28
+ connection_builder.instance_eval &block
29
+ else
30
+ raise ArgumentError, "no connection name or block given" unless connection_name
31
+ klass = self[connection_name]
32
+ end
33
+
34
+ client = klass.connect host, port, *initializer_args
35
+ client.attach Cool.io::Loop.default
36
+ client
37
+ end
38
+
39
+ # Create a new Cool.io::TCPServer
40
+ def server(host, port, connection_name = nil, *initializer_args, &block)
41
+ if block_given?
42
+ initializer_args.unshift connection_name if connection_name
43
+
44
+ klass = Class.new Cool.io::TCPSocket
45
+ connection_builder = ConnectionBuilder.new klass
46
+ connection_builder.instance_eval &block
47
+ else
48
+ raise ArgumentError, "no connection name or block given" unless connection_name
49
+ klass = self[connection_name]
50
+ end
51
+
52
+ server = Cool.io::TCPServer.new host, port, klass, *initializer_args
53
+ server.attach Cool.io::Loop.default
54
+ server
55
+ end
56
+
57
+ # Create a new Cool.io::TCPSocket class
58
+ def connection(name, &block)
59
+ # Camelize class name
60
+ class_name = name.to_s.split('_').map { |s| s.capitalize }.join
61
+
62
+ connection = Class.new Cool.io::TCPSocket
63
+ connection_builder = ConnectionBuilder.new connection
64
+ connection_builder.instance_eval &block
65
+
66
+ Coolio::Connections.const_set class_name, connection
67
+ end
68
+
69
+ # Look up a connection class by its name
70
+ def [](connection_name)
71
+ class_name = connection_name.to_s.split('_').map { |s| s.capitalize }.join
72
+
73
+ begin
74
+ Coolio::Connections.const_get class_name
75
+ rescue NameError
76
+ raise NameError, "No connection type registered for #{connection_name.inspect}"
77
+ end
78
+ end
79
+
80
+ # Builder for Cool.io::TCPSocket classes
81
+ class ConnectionBuilder
82
+ def initialize(klass)
83
+ @klass = klass
84
+ end
85
+
86
+ # Declare an initialize function
87
+ def initializer(&action)
88
+ @klass.send :define_method, :initialize, &action
89
+ end
90
+
91
+ # Declare the on_connect callback
92
+ def on_connect(&action)
93
+ @klass.send :define_method, :on_connect, &action
94
+ end
95
+
96
+ # Declare a callback fired if we failed to connect
97
+ def on_connect_failed(&action)
98
+ @klass.send :define_method, :on_connect_failed, &action
99
+ end
100
+
101
+ # Declare a callback fired if DNS resolution failed
102
+ def on_resolve_failed(&action)
103
+ @klass.send :define_method, :on_resolve_failed, &action
104
+ end
105
+
106
+ # Declare the on_close callback
107
+ def on_close(&action)
108
+ @klass.send :define_method, :on_close, &action
109
+ end
110
+
111
+ # Declare the on_read callback
112
+ def on_read(&action)
113
+ @klass.send :define_method, :on_read, &action
114
+ end
115
+
116
+ # Declare the on_write_complete callback
117
+ def on_write_complete(&action)
118
+ @klass.send :define_method, :on_write_complete, &action
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ # The Cool module containing all our coolness
125
+ module Cool
126
+ module Coolness
127
+ def cool; Cool::IOThunk; end
128
+ end
129
+
130
+ module IOThunk
131
+ def self.io; Coolio::DSL; end
132
+ end
133
+ end
134
+
135
+ extend Cool::Coolness
@@ -39,10 +39,8 @@ module Coolio
39
39
  event_callback :on_connect_failed
40
40
 
41
41
  # Called if a hostname failed to resolve when connecting
42
- # Defaults to calling on_connect_failed
43
- def on_resolve_failed
44
- on_connect_failed
45
- end
42
+ # Defaults to calling on_connect_failed
43
+ alias_method :on_resolve_failed, :on_connect_failed
46
44
 
47
45
  #########
48
46
  protected
@@ -123,7 +121,7 @@ module Coolio
123
121
 
124
122
  # Called by precreate during asyncronous DNS resolution
125
123
  def preinitialize(addr, port, *args)
126
- @_write_buffer = ::IO::Buffer.new # allow for writing BEFORE the DNS has resolved
124
+ @_write_buffer = ::IO::Buffer.new # allow for writing BEFORE DNS has resolved
127
125
  @remote_host, @remote_addr, @remote_port = addr, addr, port
128
126
  @_resolver = TCPConnectResolver.new(self, addr, port, *args)
129
127
  end
@@ -137,7 +135,7 @@ module Coolio
137
135
 
138
136
  super
139
137
 
140
- @address_family, @remote_port, @remote_host, @remote_addr = socket.peeraddr
138
+ @address_family, @remote_port, @remote_host, @remote_addr = socket.peeraddr
141
139
  end
142
140
 
143
141
  def peeraddr
@@ -153,9 +151,9 @@ module Coolio
153
151
  @host, addr, @port = host, addr, port
154
152
  @address_family = nil
155
153
 
156
- @socket = super(family, ::Socket::SOCK_STREAM, 0)
154
+ super(family, ::Socket::SOCK_STREAM, 0)
157
155
  begin
158
- @socket.connect_nonblock(::Socket.sockaddr_in(port, addr))
156
+ connect_nonblock(::Socket.sockaddr_in(port, addr))
159
157
  rescue Errno::EINPROGRESS
160
158
  end
161
159
  end
@@ -0,0 +1,39 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ VALID_DOMAIN = "google.com"
4
+ INVALID_DOMAIN = "gibidigibigididibitidibigitibidigitidididi.com"
5
+
6
+ class ItWorked < StandardError; end
7
+ class WontResolve < StandardError; end
8
+
9
+ class ConnectorThingy < Cool.io::TCPSocket
10
+ def on_connect
11
+ raise ItWorked
12
+ end
13
+
14
+ def on_resolve_failed
15
+ raise WontResolve
16
+ end
17
+ end
18
+
19
+ describe "DNS" do
20
+ before :each do
21
+ @loop = Cool.io::Loop.new
22
+ end
23
+
24
+ it "connects to valid domains" do
25
+ ConnectorThingy.connect(VALID_DOMAIN, 80).attach(@loop)
26
+
27
+ proc do
28
+ @loop.run
29
+ end.should raise_error(ItWorked)
30
+ end
31
+
32
+ it "fires on_resolve_failed for invalid domains" do
33
+ ConnectorThingy.connect(INVALID_DOMAIN, 80).attach(@loop)
34
+
35
+ proc do
36
+ @loop.run
37
+ end.should raise_error(WontResolve)
38
+ end
39
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cool.io
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 9
9
9
  - 0
10
- version: 0.9.0
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tony Arcieri
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-06 00:00:00 -06:00
18
+ date: 2010-12-13 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -40,14 +40,14 @@ dependencies:
40
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ~>
43
+ - - ">="
44
44
  - !ruby/object:Gem::Version
45
- hash: 15
45
+ hash: 11
46
46
  segments:
47
47
  - 2
48
+ - 1
48
49
  - 0
49
- - 0
50
- version: 2.0.0
50
+ version: 2.1.0
51
51
  type: :development
52
52
  version_requirements: *id002
53
53
  description: A Ruby wrapper around the libev high performance event library
@@ -61,12 +61,14 @@ extra_rdoc_files:
61
61
  - LICENSE
62
62
  - README.markdown
63
63
  files:
64
- - .gitignore
65
64
  - CHANGES
66
65
  - LICENSE
67
66
  - README.markdown
68
67
  - Rakefile
69
68
  - VERSION
69
+ - cool.io.gemspec
70
+ - examples/dslified_echo_client.rb
71
+ - examples/dslified_echo_server.rb
70
72
  - examples/echo_client.rb
71
73
  - examples/echo_server.rb
72
74
  - examples/google.rb
@@ -85,6 +87,7 @@ files:
85
87
  - ext/cool.io/watcher.c
86
88
  - ext/cool.io/watcher.h
87
89
  - ext/http11_client/.gitignore
90
+ - ext/http11_client/LICENSE
88
91
  - ext/http11_client/ext_help.h
89
92
  - ext/http11_client/extconf.rb
90
93
  - ext/http11_client/http11_client.c
@@ -106,11 +109,11 @@ files:
106
109
  - ext/libev/ev_win32.c
107
110
  - ext/libev/ev_wrap.h
108
111
  - ext/libev/test_libev_win32.c
109
- - ext/libev/update_ev_wrap
110
112
  - lib/.gitignore
111
113
  - lib/cool.io.rb
112
114
  - lib/cool.io/async_watcher.rb
113
115
  - lib/cool.io/dns_resolver.rb
116
+ - lib/cool.io/dsl.rb
114
117
  - lib/cool.io/eventmachine.rb
115
118
  - lib/cool.io/http_client.rb
116
119
  - lib/cool.io/io.rb
@@ -124,6 +127,7 @@ files:
124
127
  - lib/coolio.rb
125
128
  - lib/rev.rb
126
129
  - spec/async_watcher_spec.rb
130
+ - spec/dns_spec.rb
127
131
  - spec/possible_tests/schedules_other_threads.rb
128
132
  - spec/possible_tests/test_on_resolve_failed.rb
129
133
  - spec/possible_tests/test_resolves.rb
@@ -138,8 +142,8 @@ homepage: http://github.com/tarcieri/cool.io
138
142
  licenses: []
139
143
 
140
144
  post_install_message:
141
- rdoc_options:
142
- - --charset=UTF-8
145
+ rdoc_options: []
146
+
143
147
  require_paths:
144
148
  - lib
145
149
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -168,17 +172,20 @@ signing_key:
168
172
  specification_version: 3
169
173
  summary: The cool event framework for Ruby
170
174
  test_files:
175
+ - examples/dslified_echo_client.rb
176
+ - examples/dslified_echo_server.rb
177
+ - examples/echo_client.rb
178
+ - examples/echo_server.rb
179
+ - examples/google.rb
180
+ - examples/httpclient.rb
171
181
  - spec/async_watcher_spec.rb
172
- - spec/spec_helper.rb
173
- - spec/timer_watcher_spec.rb
174
- - spec/unix_listener_spec.rb
175
- - spec/unix_server_spec.rb
182
+ - spec/dns_spec.rb
176
183
  - spec/possible_tests/schedules_other_threads.rb
177
184
  - spec/possible_tests/test_on_resolve_failed.rb
178
185
  - spec/possible_tests/test_resolves.rb
179
186
  - spec/possible_tests/test_write_during_resolve.rb
180
187
  - spec/possible_tests/works_straight.rb
181
- - examples/echo_client.rb
182
- - examples/echo_server.rb
183
- - examples/google.rb
184
- - examples/httpclient.rb
188
+ - spec/spec_helper.rb
189
+ - spec/timer_watcher_spec.rb
190
+ - spec/unix_listener_spec.rb
191
+ - spec/unix_server_spec.rb
data/.gitignore DELETED
@@ -1,25 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## RUBINIUS
22
- *.rbc
23
-
24
- ## PROJECT::SPECIFIC
25
- conftest.dSYM
@@ -1,19 +0,0 @@
1
- #!/bin/sh
2
-
3
- (
4
- echo '#define VAR(name,decl) name'
5
- echo '#define EV_GENWRAP 1'
6
- cat ev_vars.h
7
- ) | cc -E -o - - | perl -ne '
8
- while (<>) {
9
- push @syms, $1 if /(^\w+)/;
10
- }
11
- print "/* DO NOT EDIT, automatically generated by update_ev_wrap */\n",
12
- "#ifndef EV_WRAP_H\n",
13
- "#define EV_WRAP_H\n",
14
- (map "#define $_ ((loop)->$_)\n", @syms),
15
- "#else\n",
16
- "#undef EV_WRAP_H\n",
17
- (map "#undef $_\n", @syms),
18
- "#endif\n";
19
- ' >ev_wrap.h