cool.io 1.2.0-x86-mswin32-60

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 (79) hide show
  1. data/.gitignore +26 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +5 -0
  4. data/CHANGES.md +177 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +20 -0
  7. data/README.md +172 -0
  8. data/Rakefile +81 -0
  9. data/cool.io.gemspec +28 -0
  10. data/examples/dslified_echo_client.rb +34 -0
  11. data/examples/dslified_echo_server.rb +24 -0
  12. data/examples/echo_client.rb +38 -0
  13. data/examples/echo_server.rb +27 -0
  14. data/examples/google.rb +9 -0
  15. data/examples/httpclient.rb +38 -0
  16. data/ext/cool.io/.gitignore +5 -0
  17. data/ext/cool.io/cool.io.h +58 -0
  18. data/ext/cool.io/cool.io_ext.c +25 -0
  19. data/ext/cool.io/ev_wrap.h +8 -0
  20. data/ext/cool.io/extconf.rb +73 -0
  21. data/ext/cool.io/iowatcher.c +189 -0
  22. data/ext/cool.io/libev.c +8 -0
  23. data/ext/cool.io/loop.c +301 -0
  24. data/ext/cool.io/stat_watcher.c +269 -0
  25. data/ext/cool.io/timer_watcher.c +219 -0
  26. data/ext/cool.io/utils.c +122 -0
  27. data/ext/cool.io/watcher.c +264 -0
  28. data/ext/cool.io/watcher.h +71 -0
  29. data/ext/http11_client/.gitignore +5 -0
  30. data/ext/http11_client/LICENSE +31 -0
  31. data/ext/http11_client/ext_help.h +14 -0
  32. data/ext/http11_client/extconf.rb +6 -0
  33. data/ext/http11_client/http11_client.c +300 -0
  34. data/ext/http11_client/http11_parser.c +403 -0
  35. data/ext/http11_client/http11_parser.h +48 -0
  36. data/ext/http11_client/http11_parser.rl +173 -0
  37. data/ext/iobuffer/extconf.rb +9 -0
  38. data/ext/iobuffer/iobuffer.c +765 -0
  39. data/ext/libev/Changes +388 -0
  40. data/ext/libev/LICENSE +36 -0
  41. data/ext/libev/README +58 -0
  42. data/ext/libev/README.embed +3 -0
  43. data/ext/libev/ev.c +4803 -0
  44. data/ext/libev/ev.h +845 -0
  45. data/ext/libev/ev_epoll.c +279 -0
  46. data/ext/libev/ev_kqueue.c +214 -0
  47. data/ext/libev/ev_poll.c +148 -0
  48. data/ext/libev/ev_port.c +185 -0
  49. data/ext/libev/ev_select.c +314 -0
  50. data/ext/libev/ev_vars.h +203 -0
  51. data/ext/libev/ev_win32.c +163 -0
  52. data/ext/libev/ev_wrap.h +200 -0
  53. data/ext/libev/test_libev_win32.c +123 -0
  54. data/lib/.gitignore +2 -0
  55. data/lib/cool.io.rb +32 -0
  56. data/lib/cool.io/async_watcher.rb +43 -0
  57. data/lib/cool.io/custom_require.rb +9 -0
  58. data/lib/cool.io/dns_resolver.rb +225 -0
  59. data/lib/cool.io/dsl.rb +135 -0
  60. data/lib/cool.io/eventmachine.rb +234 -0
  61. data/lib/cool.io/http_client.rb +427 -0
  62. data/lib/cool.io/io.rb +174 -0
  63. data/lib/cool.io/iowatcher.rb +17 -0
  64. data/lib/cool.io/listener.rb +93 -0
  65. data/lib/cool.io/loop.rb +130 -0
  66. data/lib/cool.io/meta.rb +49 -0
  67. data/lib/cool.io/server.rb +74 -0
  68. data/lib/cool.io/socket.rb +230 -0
  69. data/lib/cool.io/timer_watcher.rb +17 -0
  70. data/lib/cool.io/version.rb +5 -0
  71. data/lib/coolio.rb +2 -0
  72. data/spec/async_watcher_spec.rb +57 -0
  73. data/spec/dns_spec.rb +39 -0
  74. data/spec/spec_helper.rb +12 -0
  75. data/spec/stat_watcher_spec.rb +77 -0
  76. data/spec/timer_watcher_spec.rb +55 -0
  77. data/spec/unix_listener_spec.rb +25 -0
  78. data/spec/unix_server_spec.rb +25 -0
  79. metadata +200 -0
data/lib/cool.io/io.rb ADDED
@@ -0,0 +1,174 @@
1
+ #--
2
+ # Copyright (C)2007-10 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 buffered I/O class witch fits into the Coolio Watcher framework.
9
+ # It provides both an observer which reads data as it's received
10
+ # from the wire and a buffered write watcher which stores data and writes
11
+ # it out each time the socket becomes writable.
12
+ #
13
+ # This class is primarily meant as a base class for other streams
14
+ # which need non-blocking writing, and is used to implement Coolio's
15
+ # Socket class and its associated subclasses.
16
+ class IO
17
+ extend Meta
18
+
19
+ # Maximum number of bytes to consume at once
20
+ INPUT_SIZE = 16384
21
+
22
+ def initialize(io)
23
+ @_io = io
24
+ @_write_buffer ||= ::IO::Buffer.new
25
+ @_read_watcher = Watcher.new(io, self, :r)
26
+ @_write_watcher = Watcher.new(io, self, :w)
27
+ end
28
+
29
+ #
30
+ # Watcher methods, delegated to @_read_watcher
31
+ #
32
+
33
+ # Attach to the event loop
34
+ def attach(loop); @_read_watcher.attach loop; schedule_write if !@_write_buffer.empty?; self; end
35
+
36
+ # Detach from the event loop
37
+ def detach; @_read_watcher.detach; self; end # TODO should these detect write buffers, as well?
38
+
39
+ # Enable the watcher
40
+ def enable; @_read_watcher.enable; self; end
41
+
42
+ # Disable the watcher
43
+ def disable; @_read_watcher.disable; self; end
44
+
45
+ # Is the watcher attached?
46
+ def attached?; @_read_watcher.attached?; end
47
+
48
+ # Is the watcher enabled?
49
+ def enabled?; @_read_watcher.enabled?; end
50
+
51
+ # Obtain the event loop associated with this object
52
+ def evloop; @_read_watcher.evloop; end
53
+
54
+ #
55
+ # Callbacks for asynchronous events
56
+ #
57
+
58
+ # Called whenever the IO object receives data
59
+ def on_read(data); end
60
+ event_callback :on_read
61
+
62
+ # Called whenever a write completes and the output buffer is empty
63
+ def on_write_complete; end
64
+ event_callback :on_write_complete
65
+
66
+ # Called whenever the IO object hits EOF
67
+ def on_close; end
68
+ event_callback :on_close
69
+
70
+ #
71
+ # Write interface
72
+ #
73
+
74
+ # Write data in a buffered, non-blocking manner
75
+ def write(data)
76
+ @_write_buffer << data
77
+ schedule_write
78
+ data.size
79
+ end
80
+
81
+ # Number of bytes are currently in the output buffer
82
+ def output_buffer_size
83
+ @_write_buffer.size
84
+ end
85
+
86
+ # Close the IO stream
87
+ def close
88
+ detach if attached?
89
+ detach_write_watcher
90
+ @_io.close unless @_io.closed?
91
+
92
+ on_close
93
+ nil
94
+ end
95
+
96
+ # Is the IO object closed?
97
+ def closed?
98
+ @_io.nil? or @_io.closed?
99
+ end
100
+
101
+ #########
102
+ protected
103
+ #########
104
+
105
+ # Read from the input buffer and dispatch to on_read
106
+ def on_readable
107
+ begin
108
+ on_read @_io.read_nonblock(INPUT_SIZE)
109
+ rescue Errno::EAGAIN, Errno::EINTR
110
+ return
111
+
112
+ # SystemCallError catches Errno::ECONNRESET amongst others.
113
+ rescue SystemCallError, EOFError, IOError, SocketError
114
+ close
115
+ end
116
+ end
117
+
118
+ # Write the contents of the output buffer
119
+ def on_writable
120
+ begin
121
+ @_write_buffer.write_to(@_io)
122
+ rescue Errno::EINTR
123
+ return
124
+
125
+ # SystemCallError catches Errno::EPIPE & Errno::ECONNRESET amongst others.
126
+ rescue SystemCallError, IOError, SocketError
127
+ return close
128
+ end
129
+
130
+ if @_write_buffer.empty?
131
+ disable_write_watcher
132
+ on_write_complete
133
+ end
134
+ end
135
+
136
+ # Schedule a write to be performed when the IO object becomes writable
137
+ def schedule_write
138
+ return unless @_io # this would mean 'we are still pre DNS here'
139
+ return unless attached? # this would mean 'currently unattached' -- ie still pre DNS, or just plain not attached, which is ok
140
+ begin
141
+ enable_write_watcher
142
+ rescue IOError
143
+ end
144
+ end
145
+
146
+ def enable_write_watcher
147
+ if @_write_watcher.attached?
148
+ @_write_watcher.enable unless @_write_watcher.enabled?
149
+ else
150
+ @_write_watcher.attach(evloop)
151
+ end
152
+ end
153
+
154
+ def disable_write_watcher
155
+ @_write_watcher.disable if @_write_watcher and @_write_watcher.enabled?
156
+ end
157
+
158
+ def detach_write_watcher
159
+ @_write_watcher.detach if @_write_watcher and @_write_watcher.attached?
160
+ end
161
+
162
+ # Internal class implementing watchers used by Coolio::IO
163
+ class Watcher < IOWatcher
164
+ def initialize(ruby_io, coolio_io, flags)
165
+ @coolio_io = coolio_io
166
+ super(ruby_io, flags)
167
+ end
168
+
169
+ # Configure IOWatcher event callbacks to call the method passed to #initialize
170
+ def on_readable; @coolio_io.__send__(:on_readable); end
171
+ def on_writable; @coolio_io.__send__(:on_writable); end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,17 @@
1
+ #--
2
+ # Copyright (C)2007-10 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
+ class IOWatcher
9
+ # The actual implementation of this class resides in the C extension
10
+ # Here we metaprogram proper event_callbacks for the callback methods
11
+ # These can take a block and store it to be called when the event
12
+ # is actually fired.
13
+
14
+ extend Meta
15
+ event_callback :on_readable, :on_writable
16
+ end
17
+ end
@@ -0,0 +1,93 @@
1
+ #--
2
+ # Copyright (C)2007-10 Tony Arcieri
3
+ # You can redistribute this under the terms of the Ruby license
4
+ # See file LICENSE for details
5
+ #++
6
+
7
+ require 'socket'
8
+
9
+ module Coolio
10
+ # Listeners wait for incoming connections. When a listener receives a
11
+ # connection it fires the on_connection event with the newly accepted
12
+ # socket as a parameter.
13
+ class Listener < IOWatcher
14
+ def initialize(listen_socket)
15
+ @listen_socket = listen_socket
16
+ super(@listen_socket)
17
+ end
18
+
19
+ # Returns an integer representing the underlying numeric file descriptor
20
+ def fileno
21
+ @listen_socket.fileno
22
+ end
23
+
24
+ # Close the listener
25
+ def close
26
+ detach if attached?
27
+ @listen_socket.close
28
+ end
29
+
30
+ # Called whenever the server receives a new connection
31
+ def on_connection(socket); end
32
+ event_callback :on_connection
33
+
34
+ #########
35
+ protected
36
+ #########
37
+
38
+ # Coolio callback for handling new connections
39
+ def on_readable
40
+ begin
41
+ on_connection @listen_socket.accept_nonblock
42
+ rescue Errno::EAGAIN, Errno::ECONNABORTED
43
+ # EAGAIN can be triggered here if the socket is shared between
44
+ # multiple processes and a thundering herd is woken up to accept
45
+ # one connection, only one process will get the connection and
46
+ # the others will be awoken.
47
+ # ECONNABORTED is documented in accept() manpages but modern TCP
48
+ # stacks with syncookies and/or accept()-filtering for DoS
49
+ # protection do not see it. In any case this error is harmless
50
+ # and we should instead spend our time with clients that follow
51
+ # through on connection attempts.
52
+ end
53
+ end
54
+ end
55
+
56
+ class TCPListener < Listener
57
+ DEFAULT_BACKLOG = 1024
58
+
59
+ # Create a new Coolio::TCPListener on the specified address and port.
60
+ # Accepts the following options:
61
+ #
62
+ # :backlog - Max size of the pending connection queue (default 1024)
63
+ # :reverse_lookup - Retain BasicSocket's reverse DNS functionality (default false)
64
+ #
65
+ # If the specified address is an TCPServer object, it will ignore
66
+ # the port and :backlog option and create a new Coolio::TCPListener out
67
+ # of the existing TCPServer object.
68
+ def initialize(addr, port = nil, options = {})
69
+ BasicSocket.do_not_reverse_lookup = true unless options[:reverse_lookup]
70
+ options[:backlog] ||= DEFAULT_BACKLOG
71
+
72
+ listen_socket = if ::TCPServer === addr
73
+ addr
74
+ else
75
+ raise ArgumentError, "port must be an integer" if nil == port
76
+ ::TCPServer.new(addr, port)
77
+ end
78
+ listen_socket.instance_eval { listen(options[:backlog]) }
79
+ super(listen_socket)
80
+ end
81
+ end
82
+
83
+ class UNIXListener < Listener
84
+ # Create a new Coolio::UNIXListener
85
+ #
86
+ # Accepts the same arguments as UNIXServer.new
87
+ # Optionally, it can also take anyn existing UNIXServer object
88
+ # and create a Coolio::UNIXListener out of it.
89
+ def initialize(*args)
90
+ super(::UNIXServer === args.first ? args.first : ::UNIXServer.new(*args))
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,130 @@
1
+ #--
2
+ # Copyright (C)2007-10 Tony Arcieri
3
+ # You can redistribute this under the terms of the Ruby license
4
+ # See file LICENSE for details
5
+ #++
6
+
7
+ require 'thread'
8
+
9
+ # Monkeypatch Thread to include a method for obtaining the default Coolio::Loop
10
+ class Thread
11
+ def _coolio_loop
12
+ @_coolio_loop ||= Coolio::Loop.new
13
+ end
14
+ end
15
+
16
+ module Coolio
17
+ class Loop
18
+ # In Ruby 1.9 we want a Coolio::Loop per thread, but Ruby 1.8 is unithreaded
19
+ if RUBY_VERSION >= "1.9.0"
20
+ # Retrieve the default event loop for the current thread
21
+ def self.default
22
+ Thread.current._coolio_loop
23
+ end
24
+ else
25
+ # Retrieve the default event loop
26
+ def self.default
27
+ @@_coolio_loop ||= Coolio::Loop.new
28
+ end
29
+ end
30
+
31
+ # Create a new Coolio::Loop
32
+ #
33
+ # Options:
34
+ #
35
+ # :skip_environment (boolean)
36
+ # Ignore the $LIBEV_FLAGS environment variable
37
+ #
38
+ # :fork_check (boolean)
39
+ # Enable autodetection of forks
40
+ #
41
+ # :backend
42
+ # Choose the default backend, one (or many in an array) of:
43
+ # :select (most platforms)
44
+ # :poll (most platforms except Windows)
45
+ # :epoll (Linux)
46
+ # :kqueue (BSD/Mac OS X)
47
+ # :port (Solaris 10)
48
+ #
49
+ def initialize(options = {})
50
+ @watchers = {}
51
+ @active_watchers = 0
52
+
53
+ flags = 0
54
+
55
+ options.each do |option, value|
56
+ case option
57
+ when :skip_environment
58
+ flags |= EVFLAG_NOEV if value
59
+ when :fork_check
60
+ flags |= EVFLAG_FORKCHECK if value
61
+ when :backend
62
+ value = [value] unless value.is_a? Array
63
+ value.each do |backend|
64
+ case backend
65
+ when :select then flags |= EVBACKEND_SELECT
66
+ when :poll then flags |= EVBACKEND_POLL
67
+ when :epoll then flags |= EVBACKEND_EPOLL
68
+ when :kqueue then flags |= EVBACKEND_KQUEUE
69
+ when :port then flags |= EVBACKEND_PORT
70
+ else raise ArgumentError, "no such backend: #{backend}"
71
+ end
72
+ end
73
+ else raise ArgumentError, "no such option: #{option}"
74
+ end
75
+ end
76
+
77
+ @loop = ev_loop_new(flags)
78
+ end
79
+
80
+ # Attach a watcher to the loop
81
+ def attach(watcher)
82
+ watcher.attach self
83
+ end
84
+
85
+ # Run the event loop and dispatch events back to Ruby. If there
86
+ # are no watchers associated with the event loop it will return
87
+ # immediately. Otherwise, run will continue blocking and making
88
+ # event callbacks to watchers until all watchers associated with
89
+ # the loop have been disabled or detached. The loop may be
90
+ # explicitly stopped by calling the stop method on the loop object.
91
+ def run
92
+ raise RuntimeError, "no watchers for this loop" if @watchers.empty?
93
+
94
+ @running = true
95
+ while @running and not @active_watchers.zero?
96
+ run_once
97
+ end
98
+ @running = false
99
+ end
100
+
101
+ # Stop the event loop if it's running
102
+ def stop
103
+ raise RuntimeError, "loop not running" unless @running
104
+ @running = false
105
+ end
106
+
107
+ # Does the loop have any active watchers?
108
+ def has_active_watchers?
109
+ @active_watchers > 0
110
+ end
111
+
112
+ # All watchers attached to the current loop
113
+ def watchers
114
+ @watchers.keys
115
+ end
116
+
117
+ #######
118
+ private
119
+ #######
120
+
121
+ EVFLAG_NOENV = 0x1000000 # do NOT consult environment
122
+ EVFLAG_FORKCHECK = 0x2000000 # check for a fork in each iteration
123
+
124
+ EVBACKEND_SELECT = 0x00000001 # supported about anywhere
125
+ EVBACKEND_POLL = 0x00000002 # !win
126
+ EVBACKEND_EPOLL = 0x00000004 # linux
127
+ EVBACKEND_KQUEUE = 0x00000008 # bsd
128
+ EVBACKEND_PORT = 0x00000020 # solaris 10
129
+ end
130
+ end
@@ -0,0 +1,49 @@
1
+ #--
2
+ # Copyright (C)2007-10 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
+ module Meta
9
+ # Use an alternate watcher with the attach/detach/enable/disable methods
10
+ # if it is presently assigned. This is useful if you are waiting for
11
+ # an event to occur before the current watcher can be used in earnest,
12
+ # such as making an outgoing TCP connection.
13
+ def watcher_delegate(proxy_var)
14
+ %w{attach detach enable disable}.each do |method|
15
+ module_eval <<-EOD
16
+ def #{method}(*args)
17
+ if defined? #{proxy_var} and #{proxy_var}
18
+ #{proxy_var}.#{method}(*args)
19
+ return self
20
+ end
21
+
22
+ super
23
+ end
24
+ EOD
25
+ end
26
+ end
27
+
28
+ # Define callbacks whose behavior can be changed on-the-fly per instance.
29
+ # This is done by giving a block to the callback method, which is captured
30
+ # as a proc and stored for later. If the method is called without a block,
31
+ # the stored block is executed if present, otherwise it's a noop.
32
+ def event_callback(*methods)
33
+ methods.each do |method|
34
+ module_eval <<-EOD
35
+ def #{method}(*args, &block)
36
+ if block
37
+ @#{method}_callback = block
38
+ return
39
+ end
40
+
41
+ if defined? @#{method}_callback and @#{method}_callback
42
+ instance_exec(*args, &@#{method}_callback)
43
+ end
44
+ end
45
+ EOD
46
+ end
47
+ end
48
+ end
49
+ end