cool.io 0.9.0

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