cool.io 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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