cool.io 1.0.0 → 1.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 (83) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yaml +54 -0
  3. data/.gitignore +30 -0
  4. data/.rspec +3 -0
  5. data/{CHANGES → CHANGES.md} +175 -79
  6. data/{README.markdown → README.md} +43 -49
  7. data/Rakefile +44 -69
  8. data/appveyor.yml +18 -0
  9. data/cool.io.gemspec +18 -131
  10. data/examples/callbacked_echo_server.rb +24 -0
  11. data/ext/cool.io/buffer.c +781 -0
  12. data/ext/cool.io/cool.io.h +13 -0
  13. data/ext/cool.io/cool.io_ext.c +1 -0
  14. data/ext/cool.io/ev_wrap.h +4 -2
  15. data/ext/cool.io/extconf.rb +27 -16
  16. data/ext/cool.io/iowatcher.c +17 -8
  17. data/ext/cool.io/loop.c +36 -84
  18. data/ext/cool.io/stat_watcher.c +103 -25
  19. data/ext/cool.io/timer_watcher.c +3 -3
  20. data/ext/cool.io/utils.c +5 -0
  21. data/ext/cool.io/watcher.h +1 -1
  22. data/ext/libev/Changes +152 -3
  23. data/ext/libev/LICENSE +2 -1
  24. data/ext/libev/README +8 -8
  25. data/ext/libev/ev.c +1719 -348
  26. data/ext/libev/ev.h +146 -118
  27. data/ext/libev/ev_epoll.c +71 -20
  28. data/ext/libev/ev_kqueue.c +36 -16
  29. data/ext/libev/ev_poll.c +14 -11
  30. data/ext/libev/ev_port.c +43 -18
  31. data/ext/libev/ev_select.c +82 -25
  32. data/ext/libev/ev_vars.h +28 -21
  33. data/ext/libev/ev_win32.c +19 -10
  34. data/ext/libev/ev_wrap.h +166 -152
  35. data/ext/libev/test_libev_win32.c +1 -1
  36. data/gems.rb +9 -0
  37. data/lib/cool.io/async_watcher.rb +1 -1
  38. data/lib/cool.io/custom_require.rb +9 -0
  39. data/lib/cool.io/dns_resolver.rb +30 -22
  40. data/lib/cool.io/dsl.rb +32 -28
  41. data/lib/cool.io/io.rb +55 -35
  42. data/lib/cool.io/iowatcher.rb +1 -1
  43. data/lib/cool.io/listener.rb +35 -17
  44. data/lib/cool.io/loop.rb +17 -25
  45. data/lib/cool.io/meta.rb +6 -5
  46. data/lib/cool.io/server.rb +5 -4
  47. data/lib/cool.io/socket.rb +41 -30
  48. data/lib/cool.io/timer_watcher.rb +1 -1
  49. data/lib/cool.io/version.rb +7 -0
  50. data/lib/cool.io.rb +11 -10
  51. data/lib/coolio.rb +1 -1
  52. data/libev_ruby_gil.diff +175 -0
  53. data/libev_win_select.diff +130 -0
  54. data/spec/async_watcher_spec.rb +5 -5
  55. data/spec/dns_spec.rb +27 -8
  56. data/spec/iobuffer_spec.rb +147 -0
  57. data/spec/spec_helper.rb +15 -1
  58. data/spec/stat_watcher_spec.rb +81 -0
  59. data/spec/tcp_server_spec.rb +225 -0
  60. data/spec/tcp_socket_spec.rb +185 -0
  61. data/spec/timer_watcher_spec.rb +23 -19
  62. data/spec/udp_socket_spec.rb +58 -0
  63. data/spec/unix_listener_spec.rb +8 -8
  64. data/spec/unix_server_spec.rb +10 -8
  65. metadata +109 -112
  66. data/VERSION +0 -1
  67. data/examples/httpclient.rb +0 -38
  68. data/ext/http11_client/.gitignore +0 -5
  69. data/ext/http11_client/LICENSE +0 -31
  70. data/ext/http11_client/ext_help.h +0 -14
  71. data/ext/http11_client/extconf.rb +0 -6
  72. data/ext/http11_client/http11_client.c +0 -300
  73. data/ext/http11_client/http11_parser.c +0 -403
  74. data/ext/http11_client/http11_parser.h +0 -48
  75. data/ext/http11_client/http11_parser.rl +0 -173
  76. data/lib/cool.io/eventmachine.rb +0 -234
  77. data/lib/cool.io/http_client.rb +0 -419
  78. data/lib/rev.rb +0 -4
  79. data/spec/possible_tests/schedules_other_threads.rb +0 -48
  80. data/spec/possible_tests/test_on_resolve_failed.rb +0 -9
  81. data/spec/possible_tests/test_resolves.rb +0 -27
  82. data/spec/possible_tests/test_write_during_resolve.rb +0 -27
  83. data/spec/possible_tests/works_straight.rb +0 -71
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e56b06dac89092ba3fb69d7705788b4aecb51a205075b47afa6b8ff946f8bfa6
4
+ data.tar.gz: d9ff9ac907b8eb86d3158d893acdcc0f64c58985ae2ccfeeafbcc9c2a5e366a4
5
+ SHA512:
6
+ metadata.gz: b9d3c85e07f9f439c86be0572d4c455a429fbb2b8fd5b1cbdb87cd0fdca1c629060515074751eecb92357b365edf05c8b0cc79ce63ca4d6188e4eeca903cf95e
7
+ data.tar.gz: 942c188b705d59f6aa0c9d028d87b17722f9cba55c317cfb1be8f7548562c68e1467c8ec5664297cbb575fd1f6997875311d1a35d76efb772c4f50c87c20aa94
@@ -0,0 +1,54 @@
1
+ name: Test
2
+
3
+ on: [push, pull_request]
4
+
5
+ permissions:
6
+ contents: read
7
+
8
+ env:
9
+ CONSOLE_OUTPUT: XTerm
10
+
11
+ jobs:
12
+ test:
13
+ name: ${{matrix.ruby}} on ${{matrix.os}}
14
+ runs-on: ${{matrix.os}}-latest
15
+ continue-on-error: ${{matrix.experimental}}
16
+
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os:
21
+ - ubuntu
22
+ - macos
23
+ - windows
24
+
25
+ ruby:
26
+ - "3.0"
27
+ - "3.1"
28
+ - "3.2"
29
+ - "3.3"
30
+ - "head"
31
+
32
+ experimental: [false]
33
+
34
+ # include:
35
+ # - os: ubuntu
36
+ # ruby: truffleruby
37
+ # experimental: true
38
+ # - os: ubuntu
39
+ # ruby: jruby
40
+ # experimental: true
41
+ # - os: ubuntu
42
+ # ruby: head
43
+ # experimental: true
44
+
45
+ steps:
46
+ - uses: actions/checkout@v3
47
+ - uses: ruby/setup-ruby@v1
48
+ with:
49
+ ruby-version: ${{matrix.ruby}}
50
+ bundler-cache: true
51
+
52
+ - name: Run tests
53
+ timeout-minutes: 2
54
+ run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,30 @@
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
+ tmp
21
+
22
+ ## RUBINIUS
23
+ *.rbc
24
+
25
+ ## PROJECT::SPECIFIC
26
+ conftest.dSYM
27
+
28
+ *.lock
29
+ gems.locked
30
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format documentation
3
+ --backtrace
@@ -1,205 +1,301 @@
1
- 1.0.0:
1
+ 1.7.1
2
+ -----
3
+
4
+ * Set fallback local loopback address by default for Windows environment
5
+
6
+ 1.7.0
7
+ -----
8
+
9
+ * Fix extension build failure for ruby3
10
+
11
+ 1.6.1
12
+ -----
13
+
14
+ * Fix warning for recent compilers
15
+
16
+ 1.6.0
17
+ -----
18
+
19
+ * Add ruby 2.6/2.7 to windows gem
20
+ * Drop ruby 2.1/2.2/2.3 from windows gem
21
+
22
+ 1.5.4
23
+ -----
24
+
25
+ * Add ruby 2.5 to windows gem
26
+
27
+ 1.5.3
28
+ -----
29
+
30
+ * Fix invalid IOWatcher's rb_funcall that causes ArgumentError with ruby 2.5 and clang
31
+
32
+ 1.5.2
33
+ -----
34
+
35
+ * Fix invalid TimerWatcher's rb_funcall that causes ArgumentError with ruby 2.5 and clang
36
+
37
+ 1.5.1
38
+ -----
39
+
40
+ * Don't raise an exception when peername failed
41
+
42
+ 1.5.0
43
+ -----
44
+
45
+ * Update libev to 4.24
46
+
47
+ 1.4.6
48
+ -----
49
+
50
+ * Add ruby 2.4.0 to windows binary gem
51
+
52
+ 1.4.5
53
+ -----
54
+
55
+ * Increase FD_SETSIZE to 1024 on Windows
56
+
57
+ 1.4.4
58
+ -----
59
+
60
+ * Suppress lots of warnings
61
+
62
+ 1.4.3
63
+ -----
64
+
65
+ * Use accept instead of accept_nonblock on Windows to avoid thundering held problem
66
+ * Fix compilation error on Solaris and Ruby 2.3.0
67
+
68
+ 1.4.2
69
+ -----
70
+
71
+ * Add unexpected object info to attach exception message
72
+
73
+ 1.4.1
74
+ -----
75
+
76
+ * Use SleepEx instead of Sleep for better fix of process hung problem on windows environment
77
+ * Use rake-compiler-dock for cross compilation
78
+
79
+ 1.4.0
80
+ -----
81
+
82
+ * Update libev to 4.20
83
+ * Sleep in timeout instead of select on Windows
84
+
85
+ 1.3.1
86
+ -----
87
+
88
+ * Fix several bugs for JRuby support enhancement
89
+ * Fix deadlock bug on Windows environment
90
+ * Use RSpec3
91
+
92
+ 1.3.0
93
+ -----
94
+
95
+ * Block evaluation doesn't change self for keeping consistency with Ruby block
96
+ * Remove EventMachine emulation module
97
+ * Remove HttpClient
98
+ * DSL syntax is no longer available by default. Need to require 'cool.io/dsl' in user code
99
+ * Update libev to 4.19
100
+
101
+ 1.2.4
102
+ -----
103
+
104
+ * Fix a bug that #close for unconnected Socket doesn't detach all watchers (#33)
105
+ * Remove 1.8 support code
106
+ * Use standard library instead of own hosts list (#34)
107
+
108
+ 1.2.3
109
+ -----
110
+
111
+ * Fix CPU consuming issue on Windows.
112
+
113
+ 1.2.2
114
+ -----
115
+
116
+ * Add timeout option to Loop#run and Loop#run_once. Default by nil
117
+ * Support Ruby 2.2.0
118
+
119
+ 1.2.1
120
+ -----
121
+
122
+ * Release the GIL when libev polls (#24)
123
+ * Add Listener#listen method to change backlog size
124
+
125
+ 1.2.0
126
+ -----
127
+
128
+ * Support Windows environment via cross compilation
129
+ * Include iobuffer library
130
+ * Update to libev 4.15
131
+ * Remove Ruby 1.8 support
132
+
133
+ 1.1.0
134
+ -----
135
+
136
+ * Switch from Jeweler to Bundler for the gem boilerplate
137
+ * Fix firing of Coolio::HttpClient#on_request_complete (#15)
138
+ * Fix failure to resolve Init_cool symbol on win32 mingw (#14)
139
+ * Fix closing /etc/hosts in the DNS resolver (#12)
140
+ * Refactor StatWatcher to pass pervious and current path state ala Node.js
141
+ * spec:valgrind Rake task to run specs under valgrind
142
+ * Use rake-compiler to build cool.io
143
+ * Upgrade to libev 4.04
144
+
145
+ 1.0.0
146
+ -----
2
147
 
3
148
  * Fancy new DSL
4
149
 
5
- 0.9.0:
150
+ 0.9.0
151
+ -----
6
152
 
7
153
  * Rename the project to cool.io
8
-
9
154
  * Bump the version all the way to 0.9! Hell yeah! 1.0 soon!
10
-
11
155
  * Rename the main module from Rev to Coolio, with deprecation warnings for Rev
12
-
13
156
  * Use Jeweler to manage the gem
14
-
15
157
  * Update to RSpec 2.0
16
-
17
158
  * Update to libev 4.01
18
-
19
159
  * Initial Rubinius support
20
160
 
21
- 0.3.2:
161
+ 0.3.2
162
+ -----
22
163
 
23
164
  * Perform a blocking system call if we're the only thread running (1.8 only)
24
-
25
165
  * Run in non-blocking mode if we're the only thread in the process (1.8 only)
26
-
27
166
  * Make Rev::Loop#run_nonblock signal-safe
28
-
29
167
  * Fix spurious firing of Rev::AsyncWatchers
30
168
 
31
- 0.3.1:
169
+ 0.3.1
170
+ -----
32
171
 
33
172
  * Configurable intervals for Rev::StatWatcher
34
-
35
173
  * Fix broken version number :(
36
-
37
174
  * Removed warning about spuriously readable sockets from Rev::Listener
38
-
39
175
  * Rev::Listener ignores ECONNABORTED from accept_nonblock
40
-
41
176
  * Document rationale for EAGAIN/ECONNABORTED handling in Rev::Listener
42
177
 
43
- 0.3.0:
178
+ 0.3.0
179
+ -----
44
180
 
45
181
  * Add Rev::StatWatcher to monitor filesystem changes
46
-
47
182
  * Add Rev::Listener#fileno for accessing the underlying file descriptor
48
-
49
183
  * Support for creating Rev::Listeners from existing TCPServers/UNIXServers
50
-
51
184
  * Upgrade to libev 3.8
52
-
53
185
  * Simplified code loading
54
-
55
186
  * Pull in iobuffer gem and change outstanding uses of Rev::Buffer to IO::Buffer
56
-
57
187
  * Fix memory leaks resulting from strange semantics of Ruby's xrealloc
58
-
59
188
  * Rev::UNIXServer: use path instead of the first argument
60
-
61
189
  * Rev::Server-based classes can build off ::*Server objects
62
190
 
63
- 0.2.4:
191
+ 0.2.4
192
+ -----
64
193
 
65
194
  * Ugh, botched my first release from the git repo. Oh well. Try, try again.
66
195
 
67
- 0.2.3:
196
+ 0.2.3
197
+ -----
68
198
 
69
199
  * Initial Windows support
70
-
71
200
  * Initial Ruby 1.8.7 and 1.9.1 support
72
-
73
201
  * Upgrade to libev 3.52
74
-
75
202
  * Add checks for sys/resource.h and don't allow getting/setting maxfds if it
76
203
  isn't present
77
204
 
78
- 0.2.2:
205
+ 0.2.2
206
+ -----
79
207
 
80
208
  * Correct a pointer arithmetic error in the buffering code that could result
81
209
  in data corruption.
82
-
83
210
  * Upgrade to libev 3.41
84
-
85
211
  * Relax HTTP/1.1 reponse parser to allow the "reason" portion of the response
86
212
  header to be omitted
87
213
 
88
- 0.2.1:
214
+ 0.2.1
215
+ -----
89
216
 
90
217
  * Upgrade to libev 3.31
91
-
92
218
  * Rev::Loop#run_once and Rev::Loop#run_nonblock now return the number of events
93
219
  received when they were running
94
-
95
220
  * Remove inheritence relationship between Rev::IO and Rev::IOWatcher
96
-
97
221
  * Loosen HTTP/1.1 response parser to accept a common malformation in HTTP/1.1
98
222
  chunk headers
99
-
100
223
  * Add underscore prefix to instance variables to avoid conflicts in subclasses
101
-
102
224
  * Remove Rev::SSLServer until it can be made more useful
103
225
 
104
- 0.2.0:
226
+ 0.2.0
227
+ -----
105
228
 
106
229
  * Initial Ruby 1.8.6 support
107
-
108
230
  * Omit Rev::LIBEV_VERSION constant
109
-
110
231
  * Catch Errno::ECONNRESET when writing to sockets
111
-
112
232
  * SSL support via Rev::SSL, with a small C extension subclassing Ruby's
113
233
  OpenSSL::SSL::SSLSocket allowing for non-blocking SSL handshakes
114
-
115
234
  * Initial Rev::Utils implementation with #ncpus and methods to query and
116
235
  change the maximum number of file descriptors for the current process.
117
-
118
236
  * Initial Rev::AsyncWatcher implementation for cross-thread signaling
119
-
120
237
  * Handle unspecified Content-Length when encoding is identity in HttpClient
121
-
122
238
  * Fix bug in HttpClient processing zero Content-Length
123
-
124
239
  * Get rid of method_missing stuff in Rev::HttpClient
125
-
126
240
  * Have Rev::HttpClient close the connection on error
127
-
128
241
  * Allow Rev::TCPSocket#on_connect to be private when accepting connections
129
242
  from a Rev::TCPServer
130
243
 
131
- 0.1.4:
244
+ 0.1.4
245
+ -----
132
246
 
133
247
  * Calibrate Rev::TimerWatchers against ev_time() and ev_now() when the watcher
134
248
  is attached to the loop to ensure that the timeout interval is correct.
135
-
136
249
  * Add check to ensure that a Rev::Loop cannot be run from within a callback
137
-
138
250
  * Store Rev::Loop.default in a Thread-specific instance variable
139
-
140
251
  * Upgrade libev to 0.3.0
141
-
142
252
  * Rename BufferedIO to IO
143
-
144
253
  * Fixed bug in BufferedIO#write_output_buffer causing it to spin endlessly on
145
254
  an empty buffer.
146
-
147
255
  * Added has_active_watchers? to Rev::Loop to check for active watchers
148
256
 
149
- 0.1.3:
257
+ 0.1.3
258
+ -----
150
259
 
151
260
  * Fixed bug in Rev::Buffer read_from and write_to: now rb_sys_fail on failed
152
261
  reads/writes.
153
-
154
262
  * Change Rev::Buffer memory pools to purge on a periodic interval, rather than
155
263
  whenever the GC marks the object.
156
-
157
264
  * Fix bug in tracking the active watcher count. Factor shared watcher behavior
158
265
  from rev_watcher.h to rev_watcher.c.
159
266
 
160
- 0.1.2:
267
+ 0.1.2
268
+ -----
161
269
 
162
270
  * Commit initial specs
163
-
164
271
  * Improve RDoc for the library
165
-
166
272
  * Eliminate "zero copy" writes as they bypass the event loop
167
-
168
273
  * Added Rev::Buffer C extension to provide high speed buffered writes
169
-
170
274
  * Implement Rev::TCPSocket#peeraddr to improve compatibility with Ruby sockets
171
-
172
275
  * Added Rev::Listener.close for clean shutdown of a listener
173
-
174
276
  * Rev::Loop.default used to call ev_loop_default() (in C). However, this
175
277
  registers signal handlers which conflict with Ruby's own. Now the behavior
176
278
  has been changed to return a thread-local singleton of Rev::Loop.
177
-
178
279
  * Creating a new Rev::TCPListener will disable reverse lookups in BasicSocket
179
-
180
280
  * Made backlog for Rev::TCPListener user-definable
181
-
182
281
  * Rev::TCPSocket now implements an on_resolve_failed callback for failed DNS
183
282
  resolution. By default it's aliased to on_connect_failed.
184
-
185
283
  * Changed event_callbacks to use instance_exec rather than passing the
186
284
  watcher object as an argument. Documented use of defining an event
187
285
  callback as a block
188
-
189
286
  * Subsecond precision for Rev::TimerWatchers
190
287
 
191
- 0.1.1:
288
+ 0.1.1
289
+ -----
192
290
 
193
291
  * Added Rev::HttpClient, an asynchronous HTTP/1.1 client written on top of
194
292
  the Rev::TCPSocket class
195
-
196
293
  * Imported HTTP response parser from the RFuzz project
197
-
198
294
  * Added exception handling for Errno::ECONNRESET and Errno::EAGAIN
199
-
200
295
  * Fixed bugs in buffered writer which resulted in exceptions if all data
201
296
  couldn't be written with a nonblocking write.
202
297
 
203
- 0.1.0:
298
+ 0.1.0
299
+ -----
204
300
 
205
- * Initial public release
301
+ * Initial public release
@@ -1,8 +1,6 @@
1
1
  Cool.io
2
2
  =======
3
3
 
4
- [http://coolio.github.com](http://coolio.github.com)
5
-
6
4
  Cool.io is an event library for Ruby, built on the libev event library which
7
5
  provides a cross-platform interface to high performance system calls . This
8
6
  includes the epoll system call for Linux, the kqueue system call for BSDs and
@@ -14,14 +12,9 @@ applications.
14
12
 
15
13
  You can include Cool.io in your programs with:
16
14
 
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)
15
+ ```ruby
16
+ require 'cool.io'
17
+ ```
25
18
 
26
19
  Anatomy
27
20
  -------
@@ -92,37 +85,36 @@ core socket classes are also provided. Among these are:
92
85
  Cool.io::TCPSocket (or any subclass you wish to provide) whenever an incoming
93
86
  connection is received.
94
87
 
95
- * Cool.io::HttpClient - An HTTP/1.1 client with support for chunked encoding
96
- and streaming response processing through asynchronous callbacks.
97
-
98
88
  Example Program
99
89
  ---------------
100
90
 
101
91
  Cool.io provides a Sinatra-like DSL for authoring event-driven programs:
102
92
 
103
- require 'rubygems'
104
- require 'cool.io'
93
+ ```ruby
94
+ require 'cool.io'
95
+ require 'cool.io/dsl'
105
96
 
106
- ADDR = '127.0.0.1'
107
- PORT = 4321
97
+ ADDR = '127.0.0.1'
98
+ PORT = 4321
108
99
 
109
- cool.io.connection :echo_server_connection do
110
- on_connect do
111
- puts "#{remote_addr}:#{remote_port} connected"
112
- end
100
+ cool.io.connection :echo_server_connection do
101
+ on_connect do
102
+ puts "#{remote_addr}:#{remote_port} connected"
103
+ end
113
104
 
114
- on_close do
115
- puts "#{remote_addr}:#{remote_port} disconnected"
116
- end
105
+ on_close do
106
+ puts "#{remote_addr}:#{remote_port} disconnected"
107
+ end
117
108
 
118
- on_read do |data|
119
- write data
120
- end
121
- end
109
+ on_read do |data|
110
+ write data
111
+ end
112
+ end
122
113
 
123
- puts "Echo server listening on #{ADDR}:#{PORT}"
124
- cool.io.server ADDR, PORT, :echo_server_connection
125
- cool.io.run
114
+ puts "Echo server listening on #{ADDR}:#{PORT}"
115
+ cool.io.server ADDR, PORT, :echo_server_connection
116
+ cool.io.run
117
+ ```
126
118
 
127
119
  This creates a new connection class called :echo_server_connection and defines
128
120
  a set of callbacks for when various events occur.
@@ -140,29 +132,31 @@ Using Cool.io subclasses directly
140
132
  Below is an example of how to write an echo server using a subclass instead of
141
133
  the DSL:
142
134
 
143
- require 'cool.io'
144
- HOST = 'localhost'
145
- PORT = 4321
135
+ ```ruby
136
+ require 'cool.io'
137
+ HOST = 'localhost'
138
+ PORT = 4321
146
139
 
147
- class EchoServerConnection < Cool.io::TCPSocket
148
- def on_connect
149
- puts "#{remote_addr}:#{remote_port} connected"
150
- end
140
+ class EchoServerConnection < Cool.io::TCPSocket
141
+ def on_connect
142
+ puts "#{remote_addr}:#{remote_port} connected"
143
+ end
151
144
 
152
- def on_close
153
- puts "#{remote_addr}:#{remote_port} disconnected"
154
- end
145
+ def on_close
146
+ puts "#{remote_addr}:#{remote_port} disconnected"
147
+ end
155
148
 
156
- def on_read(data)
157
- write data
158
- end
159
- end
149
+ def on_read(data)
150
+ write data
151
+ end
152
+ end
160
153
 
161
- server = Cool.io::TCPServer.new(HOST, PORT, EchoServerConnection)
162
- server.attach(Cool.io::Loop.default)
154
+ server = Cool.io::TCPServer.new(HOST, PORT, EchoServerConnection)
155
+ server.attach(Cool.io::Loop.default)
163
156
 
164
- puts "Echo server listening on #{HOST}:#{PORT}"
165
- Cool.io::Loop.default.run
157
+ puts "Echo server listening on #{HOST}:#{PORT}"
158
+ Cool.io::Loop.default.run
159
+ ```
166
160
 
167
161
  Here a new observer type (EchoServerConnection) is made by subclassing an
168
162
  existing one and adding new implementations to existing event handlers.