cool.io 0.9.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.
Files changed (73) hide show
  1. data/.gitignore +25 -0
  2. data/CHANGES +199 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +4 -0
  5. data/Rakefile +98 -0
  6. data/VERSION +1 -0
  7. data/examples/echo_client.rb +38 -0
  8. data/examples/echo_server.rb +27 -0
  9. data/examples/google.rb +9 -0
  10. data/examples/httpclient.rb +38 -0
  11. data/ext/cool.io/.gitignore +5 -0
  12. data/ext/cool.io/cool.io.h +58 -0
  13. data/ext/cool.io/cool.io_ext.c +25 -0
  14. data/ext/cool.io/ev_wrap.h +8 -0
  15. data/ext/cool.io/extconf.rb +69 -0
  16. data/ext/cool.io/iowatcher.c +189 -0
  17. data/ext/cool.io/libev.c +8 -0
  18. data/ext/cool.io/loop.c +303 -0
  19. data/ext/cool.io/stat_watcher.c +191 -0
  20. data/ext/cool.io/timer_watcher.c +219 -0
  21. data/ext/cool.io/utils.c +122 -0
  22. data/ext/cool.io/watcher.c +264 -0
  23. data/ext/cool.io/watcher.h +71 -0
  24. data/ext/http11_client/.gitignore +5 -0
  25. data/ext/http11_client/ext_help.h +14 -0
  26. data/ext/http11_client/extconf.rb +6 -0
  27. data/ext/http11_client/http11_client.c +300 -0
  28. data/ext/http11_client/http11_parser.c +403 -0
  29. data/ext/http11_client/http11_parser.h +48 -0
  30. data/ext/http11_client/http11_parser.rl +173 -0
  31. data/ext/libev/Changes +364 -0
  32. data/ext/libev/LICENSE +36 -0
  33. data/ext/libev/README +58 -0
  34. data/ext/libev/README.embed +3 -0
  35. data/ext/libev/ev.c +3867 -0
  36. data/ext/libev/ev.h +826 -0
  37. data/ext/libev/ev_epoll.c +234 -0
  38. data/ext/libev/ev_kqueue.c +198 -0
  39. data/ext/libev/ev_poll.c +148 -0
  40. data/ext/libev/ev_port.c +164 -0
  41. data/ext/libev/ev_select.c +307 -0
  42. data/ext/libev/ev_vars.h +197 -0
  43. data/ext/libev/ev_win32.c +153 -0
  44. data/ext/libev/ev_wrap.h +186 -0
  45. data/ext/libev/test_libev_win32.c +123 -0
  46. data/ext/libev/update_ev_wrap +19 -0
  47. data/lib/.gitignore +2 -0
  48. data/lib/cool.io.rb +30 -0
  49. data/lib/cool.io/async_watcher.rb +43 -0
  50. data/lib/cool.io/dns_resolver.rb +220 -0
  51. data/lib/cool.io/eventmachine.rb +234 -0
  52. data/lib/cool.io/http_client.rb +419 -0
  53. data/lib/cool.io/io.rb +174 -0
  54. data/lib/cool.io/iowatcher.rb +17 -0
  55. data/lib/cool.io/listener.rb +93 -0
  56. data/lib/cool.io/loop.rb +130 -0
  57. data/lib/cool.io/meta.rb +49 -0
  58. data/lib/cool.io/server.rb +74 -0
  59. data/lib/cool.io/socket.rb +224 -0
  60. data/lib/cool.io/timer_watcher.rb +17 -0
  61. data/lib/coolio.rb +2 -0
  62. data/lib/rev.rb +4 -0
  63. data/spec/async_watcher_spec.rb +57 -0
  64. data/spec/possible_tests/schedules_other_threads.rb +48 -0
  65. data/spec/possible_tests/test_on_resolve_failed.rb +9 -0
  66. data/spec/possible_tests/test_resolves.rb +27 -0
  67. data/spec/possible_tests/test_write_during_resolve.rb +27 -0
  68. data/spec/possible_tests/works_straight.rb +71 -0
  69. data/spec/spec_helper.rb +5 -0
  70. data/spec/timer_watcher_spec.rb +55 -0
  71. data/spec/unix_listener_spec.rb +25 -0
  72. data/spec/unix_server_spec.rb +25 -0
  73. metadata +184 -0
data/.gitignore ADDED
@@ -0,0 +1,25 @@
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
data/CHANGES ADDED
@@ -0,0 +1,199 @@
1
+ 0.9.0:
2
+
3
+ * Rename the project to cool.io
4
+
5
+ * Bump the version all the way to 0.9! Hell yeah! 1.0 soon!
6
+
7
+ * Rename the main module from Rev to Coolio, with deprecation warnings for Rev
8
+
9
+ * Use Jeweler to manage the gem
10
+
11
+ * Update to RSpec 2.0
12
+
13
+ * Update to libev 4.01
14
+
15
+ 0.3.2:
16
+
17
+ * Perform a blocking system call if we're the only thread running (1.8 only)
18
+
19
+ * Run in non-blocking mode if we're the only thread in the process (1.8 only)
20
+
21
+ * Make Rev::Loop#run_nonblock signal-safe
22
+
23
+ * Fix spurious firing of Rev::AsyncWatchers
24
+
25
+ 0.3.1:
26
+
27
+ * Configurable intervals for Rev::StatWatcher
28
+
29
+ * Fix broken version number :(
30
+
31
+ * Removed warning about spuriously readable sockets from Rev::Listener
32
+
33
+ * Rev::Listener ignores ECONNABORTED from accept_nonblock
34
+
35
+ * Document rationale for EAGAIN/ECONNABORTED handling in Rev::Listener
36
+
37
+ 0.3.0:
38
+
39
+ * Add Rev::StatWatcher to monitor filesystem changes
40
+
41
+ * Add Rev::Listener#fileno for accessing the underlying file descriptor
42
+
43
+ * Support for creating Rev::Listeners from existing TCPServers/UNIXServers
44
+
45
+ * Upgrade to libev 3.8
46
+
47
+ * Simplified code loading
48
+
49
+ * Pull in iobuffer gem and change outstanding uses of Rev::Buffer to IO::Buffer
50
+
51
+ * Fix memory leaks resulting from strange semantics of Ruby's xrealloc
52
+
53
+ * Rev::UNIXServer: use path instead of the first argument
54
+
55
+ * Rev::Server-based classes can build off ::*Server objects
56
+
57
+ 0.2.4:
58
+
59
+ * Ugh, botched my first release from the git repo. Oh well. Try, try again.
60
+
61
+ 0.2.3:
62
+
63
+ * Initial Windows support
64
+
65
+ * Initial Ruby 1.8.7 and 1.9.1 support
66
+
67
+ * Upgrade to libev 3.52
68
+
69
+ * Add checks for sys/resource.h and don't allow getting/setting maxfds if it
70
+ isn't present
71
+
72
+ 0.2.2:
73
+
74
+ * Correct a pointer arithmetic error in the buffering code that could result
75
+ in data corruption.
76
+
77
+ * Upgrade to libev 3.41
78
+
79
+ * Relax HTTP/1.1 reponse parser to allow the "reason" portion of the response
80
+ header to be omitted
81
+
82
+ 0.2.1:
83
+
84
+ * Upgrade to libev 3.31
85
+
86
+ * Rev::Loop#run_once and Rev::Loop#run_nonblock now return the number of events
87
+ received when they were running
88
+
89
+ * Remove inheritence relationship between Rev::IO and Rev::IOWatcher
90
+
91
+ * Loosen HTTP/1.1 response parser to accept a common malformation in HTTP/1.1
92
+ chunk headers
93
+
94
+ * Add underscore prefix to instance variables to avoid conflicts in subclasses
95
+
96
+ * Remove Rev::SSLServer until it can be made more useful
97
+
98
+ 0.2.0:
99
+
100
+ * Initial Ruby 1.8.6 support
101
+
102
+ * Omit Rev::LIBEV_VERSION constant
103
+
104
+ * Catch Errno::ECONNRESET when writing to sockets
105
+
106
+ * SSL support via Rev::SSL, with a small C extension subclassing Ruby's
107
+ OpenSSL::SSL::SSLSocket allowing for non-blocking SSL handshakes
108
+
109
+ * Initial Rev::Utils implementation with #ncpus and methods to query and
110
+ change the maximum number of file descriptors for the current process.
111
+
112
+ * Initial Rev::AsyncWatcher implementation for cross-thread signaling
113
+
114
+ * Handle unspecified Content-Length when encoding is identity in HttpClient
115
+
116
+ * Fix bug in HttpClient processing zero Content-Length
117
+
118
+ * Get rid of method_missing stuff in Rev::HttpClient
119
+
120
+ * Have Rev::HttpClient close the connection on error
121
+
122
+ * Allow Rev::TCPSocket#on_connect to be private when accepting connections
123
+ from a Rev::TCPServer
124
+
125
+ 0.1.4:
126
+
127
+ * Calibrate Rev::TimerWatchers against ev_time() and ev_now() when the watcher
128
+ is attached to the loop to ensure that the timeout interval is correct.
129
+
130
+ * Add check to ensure that a Rev::Loop cannot be run from within a callback
131
+
132
+ * Store Rev::Loop.default in a Thread-specific instance variable
133
+
134
+ * Upgrade libev to 0.3.0
135
+
136
+ * Rename BufferedIO to IO
137
+
138
+ * Fixed bug in BufferedIO#write_output_buffer causing it to spin endlessly on
139
+ an empty buffer.
140
+
141
+ * Added has_active_watchers? to Rev::Loop to check for active watchers
142
+
143
+ 0.1.3:
144
+
145
+ * Fixed bug in Rev::Buffer read_from and write_to: now rb_sys_fail on failed
146
+ reads/writes.
147
+
148
+ * Change Rev::Buffer memory pools to purge on a periodic interval, rather than
149
+ whenever the GC marks the object.
150
+
151
+ * Fix bug in tracking the active watcher count. Factor shared watcher behavior
152
+ from rev_watcher.h to rev_watcher.c.
153
+
154
+ 0.1.2:
155
+
156
+ * Commit initial specs
157
+
158
+ * Improve RDoc for the library
159
+
160
+ * Eliminate "zero copy" writes as they bypass the event loop
161
+
162
+ * Added Rev::Buffer C extension to provide high speed buffered writes
163
+
164
+ * Implement Rev::TCPSocket#peeraddr to improve compatibility with Ruby sockets
165
+
166
+ * Added Rev::Listener.close for clean shutdown of a listener
167
+
168
+ * Rev::Loop.default used to call ev_loop_default() (in C). However, this
169
+ registers signal handlers which conflict with Ruby's own. Now the behavior
170
+ has been changed to return a thread-local singleton of Rev::Loop.
171
+
172
+ * Creating a new Rev::TCPListener will disable reverse lookups in BasicSocket
173
+
174
+ * Made backlog for Rev::TCPListener user-definable
175
+
176
+ * Rev::TCPSocket now implements an on_resolve_failed callback for failed DNS
177
+ resolution. By default it's aliased to on_connect_failed.
178
+
179
+ * Changed event_callbacks to use instance_exec rather than passing the
180
+ watcher object as an argument. Documented use of defining an event
181
+ callback as a block
182
+
183
+ * Subsecond precision for Rev::TimerWatchers
184
+
185
+ 0.1.1:
186
+
187
+ * Added Rev::HttpClient, an asynchronous HTTP/1.1 client written on top of
188
+ the Rev::TCPSocket class
189
+
190
+ * Imported HTTP response parser from the RFuzz project
191
+
192
+ * Added exception handling for Errno::ECONNRESET and Errno::EAGAIN
193
+
194
+ * Fixed bugs in buffered writer which resulted in exceptions if all data
195
+ couldn't be written with a nonblocking write.
196
+
197
+ 0.1.0:
198
+
199
+ * Initial public release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007-10 Tony Arcieri
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,4 @@
1
+ Cool.io
2
+ =======
3
+
4
+ This page intentionally left blank... for now
data/Rakefile ADDED
@@ -0,0 +1,98 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "cool.io"
9
+ gem.summary = "The cool event framework for Ruby"
10
+ gem.description = "A Ruby wrapper around the libev high performance event library"
11
+ gem.email = "tony@medioh.com"
12
+ gem.homepage = "http://github.com/tarcieri/cool.io"
13
+ gem.authors = ["Tony Arcieri"]
14
+ gem.add_dependency "iobuffer", ">= 0.1.3"
15
+ gem.add_development_dependency "rspec", "~> 2.0.0"
16
+ gem.extensions = FileList["ext/**/extconf.rb"].to_a
17
+
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ require 'rspec/core/rake_task'
26
+ RSpec::Core::RakeTask.new(:spec) do |spec|
27
+ spec.pattern = 'spec/**/*_spec.rb'
28
+ spec.rspec_opts = %w[-fs -c -b]
29
+ end
30
+
31
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
32
+ spec.pattern = 'spec/**/*_spec.rb'
33
+ spec.rcov = true
34
+ spec.rspec_opts = %w[-fs -c -b]
35
+ end
36
+
37
+ task :default => %w(compile spec)
38
+ task :spec => :check_dependencies
39
+
40
+ require 'rake/rdoctask'
41
+ Rake::RDocTask.new do |rdoc|
42
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "cool.io #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
49
+
50
+ def make(makedir)
51
+ Dir.chdir(makedir) { sh 'make' }
52
+ end
53
+
54
+ def extconf(dir)
55
+ Dir.chdir(dir) { ruby "extconf.rb" }
56
+ end
57
+
58
+ def setup_extension(dir, extension)
59
+ ext = "ext/#{dir}"
60
+ ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}"
61
+ ext_files = FileList[
62
+ "#{ext}/*.c",
63
+ "#{ext}/*.h",
64
+ "#{ext}/extconf.rb",
65
+ "#{ext}/Makefile",
66
+ ]
67
+
68
+ desc "Builds just the #{extension} extension"
69
+ task extension.to_sym => ["#{ext}/Makefile", ext_so ]
70
+
71
+ file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
72
+ extconf "#{ext}"
73
+ end
74
+
75
+ file ext_so => ext_files do
76
+ make "#{ext}"
77
+ cp ext_so, "lib"
78
+ end
79
+ end
80
+
81
+ setup_extension("cool.io", "cool.io_ext")
82
+ setup_extension("http11_client", "http11_client")
83
+
84
+ task :compile => %w(cool.io_ext http11_client)
85
+
86
+ # Rebuild parser Ragel
87
+ task :http11_parser do
88
+ Dir.chdir "ext/http11_client" do
89
+ target = "http11_parser.c"
90
+ File.unlink target if File.exist? target
91
+ sh "ragel http11_parser.rl | rlgen-cd -G2 -o #{target}"
92
+ raise "Failed to build C source" unless File.exist? target
93
+ end
94
+ end
95
+
96
+ CLEAN.include ["build/*", "**/*.o", "**/*.so", "**/*.a", "**/*.log", "pkg"]
97
+ CLEAN.include ["ext/**/Makefile", "lib/cool.io_ext.*", "lib/http11_client.*"]
98
+ CLEAN.include ["ext/**/*.#{Config::CONFIG["DLEXT"]}"]
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.9.0
@@ -0,0 +1,38 @@
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
+ class ClientConnection < Coolio::TCPSocket
10
+ def on_connect
11
+ puts "#{remote_addr}:#{remote_port} connected"
12
+ write "bounce this back to me"
13
+ end
14
+
15
+ def on_close
16
+ puts "#{remote_addr}:#{remote_port} disconnected"
17
+ end
18
+
19
+ def on_read(data)
20
+ print "got #{data}"
21
+ close
22
+ end
23
+
24
+ def on_resolve_failed
25
+ print "DNS resolve failed"
26
+ end
27
+
28
+ def on_connect_failed
29
+ print "connect failed, meaning our connection to their port was rejected"
30
+ end
31
+
32
+ end
33
+
34
+ event_loop = Coolio::Loop.default
35
+ client = ClientConnection.connect(ADDR, PORT)
36
+ client.attach(event_loop)
37
+ puts "Echo client connecting to #{ADDR}:#{PORT}..."
38
+ event_loop.run
@@ -0,0 +1,27 @@
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
+ class EchoServerConnection < Coolio::TCPSocket
10
+ def on_connect
11
+ puts "#{remote_addr}:#{remote_port} connected"
12
+ end
13
+
14
+ def on_close
15
+ puts "#{remote_addr}:#{remote_port} disconnected"
16
+ end
17
+
18
+ def on_read(data)
19
+ write data
20
+ end
21
+ end
22
+
23
+ event_loop = Coolio::Loop.default
24
+ Coolio::TCPServer.new(ADDR, PORT, EchoServerConnection).attach(event_loop)
25
+
26
+ puts "Echo server listening on #{ADDR}:#{PORT}"
27
+ event_loop.run
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ l = Coolio::Loop.default
7
+ c = Coolio::HttpClient.connect("www.google.com", 80).attach(l)
8
+ c.request('GET', '/search', :query => { :q => 'feces'})
9
+ l.run
@@ -0,0 +1,38 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ class MyHttpClient < Coolio::HttpClient
7
+ def on_connect
8
+ super
9
+ STDERR.puts "Connected to #{remote_host}:#{remote_port}"
10
+ end
11
+
12
+ def on_connect_failed
13
+ super
14
+ STDERR.puts "Connection failed"
15
+ end
16
+
17
+ def on_response_header(header)
18
+ STDERR.puts "Response: #{header.http_version} #{header.status} #{header.http_reason}"
19
+ end
20
+
21
+ def on_body_data(data)
22
+ STDOUT.write data
23
+ STDOUT.flush
24
+ end
25
+
26
+ def on_request_complete
27
+ STDERR.puts "Request complete!"
28
+ end
29
+
30
+ def on_error(reason)
31
+ STDERR.puts "Error: #{reason}"
32
+ end
33
+ end
34
+
35
+ l = Coolio::Loop.default
36
+ c = MyHttpClient.connect("www.google.com", 80).attach(l)
37
+ c.request('GET', '/search', :query => { :q => 'foobar' })
38
+ l.run