cool.io 1.4.1-x64-mingw32

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +29 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGES.md +229 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +20 -0
  8. data/README.md +166 -0
  9. data/Rakefile +79 -0
  10. data/cool.io.gemspec +29 -0
  11. data/examples/callbacked_echo_server.rb +24 -0
  12. data/examples/dslified_echo_client.rb +34 -0
  13. data/examples/dslified_echo_server.rb +24 -0
  14. data/examples/echo_client.rb +38 -0
  15. data/examples/echo_server.rb +27 -0
  16. data/examples/google.rb +9 -0
  17. data/ext/cool.io/.gitignore +5 -0
  18. data/ext/cool.io/cool.io.h +59 -0
  19. data/ext/cool.io/cool.io_ext.c +25 -0
  20. data/ext/cool.io/ev_wrap.h +10 -0
  21. data/ext/cool.io/extconf.rb +61 -0
  22. data/ext/cool.io/iowatcher.c +189 -0
  23. data/ext/cool.io/libev.c +8 -0
  24. data/ext/cool.io/loop.c +261 -0
  25. data/ext/cool.io/stat_watcher.c +269 -0
  26. data/ext/cool.io/timer_watcher.c +219 -0
  27. data/ext/cool.io/utils.c +122 -0
  28. data/ext/cool.io/watcher.c +264 -0
  29. data/ext/cool.io/watcher.h +71 -0
  30. data/ext/iobuffer/extconf.rb +9 -0
  31. data/ext/iobuffer/iobuffer.c +767 -0
  32. data/ext/libev/Changes +507 -0
  33. data/ext/libev/LICENSE +37 -0
  34. data/ext/libev/README +58 -0
  35. data/ext/libev/README.embed +3 -0
  36. data/ext/libev/ev.c +5054 -0
  37. data/ext/libev/ev.h +853 -0
  38. data/ext/libev/ev_epoll.c +282 -0
  39. data/ext/libev/ev_kqueue.c +214 -0
  40. data/ext/libev/ev_poll.c +148 -0
  41. data/ext/libev/ev_port.c +185 -0
  42. data/ext/libev/ev_select.c +362 -0
  43. data/ext/libev/ev_vars.h +204 -0
  44. data/ext/libev/ev_win32.c +163 -0
  45. data/ext/libev/ev_wrap.h +200 -0
  46. data/ext/libev/ruby_gil.patch +97 -0
  47. data/ext/libev/test_libev_win32.c +123 -0
  48. data/ext/libev/win_select.patch +115 -0
  49. data/lib/.gitignore +2 -0
  50. data/lib/cool.io.rb +34 -0
  51. data/lib/cool.io/async_watcher.rb +43 -0
  52. data/lib/cool.io/custom_require.rb +9 -0
  53. data/lib/cool.io/dns_resolver.rb +219 -0
  54. data/lib/cool.io/dsl.rb +139 -0
  55. data/lib/cool.io/io.rb +194 -0
  56. data/lib/cool.io/iowatcher.rb +17 -0
  57. data/lib/cool.io/listener.rb +99 -0
  58. data/lib/cool.io/loop.rb +122 -0
  59. data/lib/cool.io/meta.rb +49 -0
  60. data/lib/cool.io/server.rb +75 -0
  61. data/lib/cool.io/socket.rb +230 -0
  62. data/lib/cool.io/timer_watcher.rb +17 -0
  63. data/lib/cool.io/version.rb +7 -0
  64. data/lib/coolio.rb +2 -0
  65. data/spec/async_watcher_spec.rb +57 -0
  66. data/spec/dns_spec.rb +43 -0
  67. data/spec/iobuffer_spec.rb +147 -0
  68. data/spec/spec_helper.rb +19 -0
  69. data/spec/stat_watcher_spec.rb +77 -0
  70. data/spec/tcp_server_spec.rb +225 -0
  71. data/spec/tcp_socket_spec.rb +185 -0
  72. data/spec/timer_watcher_spec.rb +59 -0
  73. data/spec/udp_socket_spec.rb +58 -0
  74. data/spec/unix_listener_spec.rb +25 -0
  75. data/spec/unix_server_spec.rb +27 -0
  76. metadata +182 -0
@@ -0,0 +1,139 @@
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
128
+ Cool::IOThunk
129
+ end
130
+ end
131
+
132
+ module IOThunk
133
+ def self.io
134
+ Coolio::DSL
135
+ end
136
+ end
137
+ end
138
+
139
+ extend Cool::Coolness
@@ -0,0 +1,194 @@
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)
35
+ @_read_watcher.attach(loop)
36
+ schedule_write if !@_write_buffer.empty?
37
+ self
38
+ end
39
+
40
+ # Detach from the event loop
41
+ def detach
42
+ # TODO should these detect write buffers, as well?
43
+ @_read_watcher.detach
44
+ self
45
+ end
46
+
47
+ # Enable the watcher
48
+ def enable
49
+ @_read_watcher.enable
50
+ self
51
+ end
52
+
53
+ # Disable the watcher
54
+ def disable
55
+ @_read_watcher.disable
56
+ self
57
+ end
58
+
59
+ # Is the watcher attached?
60
+ def attached?
61
+ @_read_watcher.attached?
62
+ end
63
+
64
+ # Is the watcher enabled?
65
+ def enabled?
66
+ @_read_watcher.enabled?
67
+ end
68
+
69
+ # Obtain the event loop associated with this object
70
+ def evloop
71
+ @_read_watcher.evloop
72
+ end
73
+
74
+ #
75
+ # Callbacks for asynchronous events
76
+ #
77
+
78
+ # Called whenever the IO object receives data
79
+ def on_read(data); end
80
+ event_callback :on_read
81
+
82
+ # Called whenever a write completes and the output buffer is empty
83
+ def on_write_complete; end
84
+ event_callback :on_write_complete
85
+
86
+ # Called whenever the IO object hits EOF
87
+ def on_close; end
88
+ event_callback :on_close
89
+
90
+ #
91
+ # Write interface
92
+ #
93
+
94
+ # Write data in a buffered, non-blocking manner
95
+ def write(data)
96
+ @_write_buffer << data
97
+ schedule_write
98
+ data.size
99
+ end
100
+
101
+ # Close the IO stream
102
+ def close
103
+ detach if attached?
104
+ detach_write_watcher
105
+ @_io.close unless closed?
106
+
107
+ on_close
108
+ nil
109
+ end
110
+
111
+ # Is the IO object closed?
112
+ def closed?
113
+ @_io.nil? or @_io.closed?
114
+ end
115
+
116
+ #########
117
+ protected
118
+ #########
119
+
120
+ # Read from the input buffer and dispatch to on_read
121
+ def on_readable
122
+ begin
123
+ on_read @_io.read_nonblock(INPUT_SIZE)
124
+ rescue Errno::EAGAIN, Errno::EINTR
125
+ return
126
+
127
+ # SystemCallError catches Errno::ECONNRESET amongst others.
128
+ rescue SystemCallError, EOFError, IOError, SocketError
129
+ close
130
+ end
131
+ end
132
+
133
+ # Write the contents of the output buffer
134
+ def on_writable
135
+ begin
136
+ @_write_buffer.write_to(@_io)
137
+ rescue Errno::EINTR
138
+ return
139
+
140
+ # SystemCallError catches Errno::EPIPE & Errno::ECONNRESET amongst others.
141
+ rescue SystemCallError, IOError, SocketError
142
+ return close
143
+ end
144
+
145
+ if @_write_buffer.empty?
146
+ disable_write_watcher
147
+ on_write_complete
148
+ end
149
+ end
150
+
151
+ # Schedule a write to be performed when the IO object becomes writable
152
+ def schedule_write
153
+ return unless @_io # this would mean 'we are still pre DNS here'
154
+ return unless @_read_watcher.attached? # this would mean 'currently unattached' -- ie still pre DNS, or just plain not attached, which is ok
155
+ begin
156
+ enable_write_watcher
157
+ rescue IOError
158
+ end
159
+ end
160
+
161
+ def enable_write_watcher
162
+ if @_write_watcher.attached?
163
+ @_write_watcher.enable unless @_write_watcher.enabled?
164
+ else
165
+ @_write_watcher.attach(evloop)
166
+ end
167
+ end
168
+
169
+ def disable_write_watcher
170
+ @_write_watcher.disable if @_write_watcher and @_write_watcher.enabled?
171
+ end
172
+
173
+ def detach_write_watcher
174
+ @_write_watcher.detach if @_write_watcher and @_write_watcher.attached?
175
+ end
176
+
177
+ # Internal class implementing watchers used by Coolio::IO
178
+ class Watcher < IOWatcher
179
+ def initialize(ruby_io, coolio_io, flags)
180
+ @coolio_io = coolio_io
181
+ super(ruby_io, flags)
182
+ end
183
+
184
+ # Configure IOWatcher event callbacks to call the method passed to #initialize
185
+ def on_readable
186
+ @coolio_io.__send__(:on_readable)
187
+ end
188
+
189
+ def on_writable
190
+ @coolio_io.__send__(:on_writable)
191
+ end
192
+ end
193
+ end
194
+ 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,99 @@
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
+ def listen(backlog)
25
+ @listen_socket.listen(backlog)
26
+ end
27
+
28
+ # Close the listener
29
+ def close
30
+ detach if attached?
31
+ @listen_socket.close
32
+ end
33
+
34
+ # Called whenever the server receives a new connection
35
+ def on_connection(socket); end
36
+ event_callback :on_connection
37
+
38
+ #########
39
+ protected
40
+ #########
41
+
42
+ # Coolio callback for handling new connections
43
+ def on_readable
44
+ begin
45
+ on_connection @listen_socket.accept_nonblock
46
+ rescue Errno::EAGAIN, Errno::ECONNABORTED
47
+ # EAGAIN can be triggered here if the socket is shared between
48
+ # multiple processes and a thundering herd is woken up to accept
49
+ # one connection, only one process will get the connection and
50
+ # the others will be awoken.
51
+ # ECONNABORTED is documented in accept() manpages but modern TCP
52
+ # stacks with syncookies and/or accept()-filtering for DoS
53
+ # protection do not see it. In any case this error is harmless
54
+ # and we should instead spend our time with clients that follow
55
+ # through on connection attempts.
56
+ end
57
+ end
58
+ end
59
+
60
+ DEFAULT_BACKLOG = 1024
61
+
62
+ class TCPListener < Listener
63
+ # Create a new Coolio::TCPListener on the specified address and port.
64
+ # Accepts the following options:
65
+ #
66
+ # :backlog - Max size of the pending connection queue (default 1024)
67
+ # :reverse_lookup - Retain BasicSocket's reverse DNS functionality (default false)
68
+ #
69
+ # If the specified address is an TCPServer object, it will ignore
70
+ # the port and :backlog option and create a new Coolio::TCPListener out
71
+ # of the existing TCPServer object.
72
+ def initialize(addr, port = nil, options = {})
73
+ BasicSocket.do_not_reverse_lookup = true unless options[:reverse_lookup]
74
+ options[:backlog] ||= DEFAULT_BACKLOG
75
+
76
+ listen_socket = if ::TCPServer === addr
77
+ addr
78
+ else
79
+ raise ArgumentError, "port must be an integer" if nil == port
80
+ ::TCPServer.new(addr, port)
81
+ end
82
+ listen_socket.instance_eval { listen(options[:backlog]) }
83
+ super(listen_socket)
84
+ end
85
+ end
86
+
87
+ class UNIXListener < Listener
88
+ # Create a new Coolio::UNIXListener
89
+ #
90
+ # Accepts the same arguments as UNIXServer.new
91
+ # Optionally, it can also take anyn existing UNIXServer object
92
+ # and create a Coolio::UNIXListener out of it.
93
+ def initialize(*args)
94
+ s = ::UNIXServer === args.first ? args.first : ::UNIXServer.new(*args)
95
+ s.instance_eval { listen(DEFAULT_BACKLOG) }
96
+ super(s)
97
+ end
98
+ end
99
+ end