cool.io 1.2.3-x86-mingw32 → 1.4.1-x86-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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.travis.yml +3 -3
- data/CHANGES.md +35 -0
- data/README.md +1 -3
- data/Rakefile +11 -13
- data/cool.io.gemspec +3 -2
- data/examples/callbacked_echo_server.rb +24 -0
- data/ext/cool.io/extconf.rb +8 -24
- data/ext/cool.io/loop.c +1 -1
- data/ext/iobuffer/iobuffer.c +2 -0
- data/ext/libev/Changes +123 -4
- data/ext/libev/LICENSE +2 -1
- data/ext/libev/README +8 -8
- data/ext/libev/ev.c +313 -144
- data/ext/libev/ev.h +18 -10
- data/ext/libev/ev_epoll.c +4 -1
- data/ext/libev/ev_kqueue.c +1 -1
- data/ext/libev/ev_select.c +3 -4
- data/ext/libev/ev_vars.h +3 -2
- data/ext/libev/ev_win32.c +1 -1
- data/ext/libev/win_select.patch +115 -0
- data/lib/cool.io.rb +6 -4
- data/lib/cool.io/dns_resolver.rb +4 -10
- data/lib/cool.io/dsl.rb +6 -2
- data/lib/cool.io/io.rb +36 -16
- data/lib/cool.io/loop.rb +3 -11
- data/lib/cool.io/meta.rb +2 -2
- data/lib/cool.io/version.rb +4 -2
- data/spec/async_watcher_spec.rb +5 -5
- data/spec/dns_spec.rb +11 -7
- data/spec/iobuffer_spec.rb +147 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/stat_watcher_spec.rb +3 -3
- data/spec/tcp_server_spec.rb +98 -5
- data/spec/tcp_socket_spec.rb +185 -0
- data/spec/timer_watcher_spec.rb +23 -19
- data/spec/udp_socket_spec.rb +58 -0
- data/spec/unix_listener_spec.rb +7 -7
- data/spec/unix_server_spec.rb +7 -7
- metadata +83 -103
- data/examples/httpclient.rb +0 -38
- data/ext/http11_client/.gitignore +0 -5
- data/ext/http11_client/LICENSE +0 -31
- data/ext/http11_client/ext_help.h +0 -14
- data/ext/http11_client/extconf.rb +0 -6
- data/ext/http11_client/http11_client.c +0 -300
- data/ext/http11_client/http11_parser.c +0 -403
- data/ext/http11_client/http11_parser.h +0 -48
- data/ext/http11_client/http11_parser.rl +0 -173
- data/lib/cool.io/eventmachine.rb +0 -234
- data/lib/cool.io/http_client.rb +0 -427
@@ -1,48 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright (c) 2005 Zed A. Shaw
|
3
|
-
* You can redistribute it and/or modify it under the same terms as Ruby.
|
4
|
-
*/
|
5
|
-
|
6
|
-
#ifndef http11_parser_h
|
7
|
-
#define http11_parser_h
|
8
|
-
|
9
|
-
#include <sys/types.h>
|
10
|
-
|
11
|
-
#if defined(_WIN32)
|
12
|
-
#include <stddef.h>
|
13
|
-
#endif
|
14
|
-
|
15
|
-
typedef void (*element_cb)(void *data, const char *at, size_t length);
|
16
|
-
typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen);
|
17
|
-
|
18
|
-
typedef struct httpclient_parser {
|
19
|
-
int cs;
|
20
|
-
size_t body_start;
|
21
|
-
int content_len;
|
22
|
-
size_t nread;
|
23
|
-
size_t mark;
|
24
|
-
size_t field_start;
|
25
|
-
size_t field_len;
|
26
|
-
|
27
|
-
void *data;
|
28
|
-
|
29
|
-
field_cb http_field;
|
30
|
-
element_cb reason_phrase;
|
31
|
-
element_cb status_code;
|
32
|
-
element_cb chunk_size;
|
33
|
-
element_cb http_version;
|
34
|
-
element_cb header_done;
|
35
|
-
element_cb last_chunk;
|
36
|
-
|
37
|
-
|
38
|
-
} httpclient_parser;
|
39
|
-
|
40
|
-
int httpclient_parser_init(httpclient_parser *parser);
|
41
|
-
int httpclient_parser_finish(httpclient_parser *parser);
|
42
|
-
size_t httpclient_parser_execute(httpclient_parser *parser, const char *data, size_t len, size_t off);
|
43
|
-
int httpclient_parser_has_error(httpclient_parser *parser);
|
44
|
-
int httpclient_parser_is_finished(httpclient_parser *parser);
|
45
|
-
|
46
|
-
#define httpclient_parser_nread(parser) (parser)->nread
|
47
|
-
|
48
|
-
#endif
|
@@ -1,173 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright (c) 2005 Zed A. Shaw
|
3
|
-
* You can redistribute it and/or modify it under the same terms as Ruby.
|
4
|
-
*/
|
5
|
-
|
6
|
-
#include "http11_parser.h"
|
7
|
-
#include <stdio.h>
|
8
|
-
#include <assert.h>
|
9
|
-
#include <stdlib.h>
|
10
|
-
#include <ctype.h>
|
11
|
-
#include <string.h>
|
12
|
-
|
13
|
-
#define LEN(AT, FPC) (FPC - buffer - parser->AT)
|
14
|
-
#define MARK(M,FPC) (parser->M = (FPC) - buffer)
|
15
|
-
#define PTR_TO(F) (buffer + parser->F)
|
16
|
-
#define L(M) fprintf(stderr, "" # M "\n");
|
17
|
-
|
18
|
-
|
19
|
-
/** machine **/
|
20
|
-
%%{
|
21
|
-
machine httpclient_parser;
|
22
|
-
|
23
|
-
action mark {MARK(mark, fpc); }
|
24
|
-
|
25
|
-
action start_field { MARK(field_start, fpc); }
|
26
|
-
|
27
|
-
action write_field {
|
28
|
-
parser->field_len = LEN(field_start, fpc);
|
29
|
-
}
|
30
|
-
|
31
|
-
action start_value { MARK(mark, fpc); }
|
32
|
-
|
33
|
-
action write_value {
|
34
|
-
parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
|
35
|
-
}
|
36
|
-
|
37
|
-
action reason_phrase {
|
38
|
-
parser->reason_phrase(parser->data, PTR_TO(mark), LEN(mark, fpc));
|
39
|
-
}
|
40
|
-
|
41
|
-
action status_code {
|
42
|
-
parser->status_code(parser->data, PTR_TO(mark), LEN(mark, fpc));
|
43
|
-
}
|
44
|
-
|
45
|
-
action http_version {
|
46
|
-
parser->http_version(parser->data, PTR_TO(mark), LEN(mark, fpc));
|
47
|
-
}
|
48
|
-
|
49
|
-
action chunk_size {
|
50
|
-
parser->chunk_size(parser->data, PTR_TO(mark), LEN(mark, fpc));
|
51
|
-
}
|
52
|
-
|
53
|
-
action last_chunk {
|
54
|
-
parser->last_chunk(parser->data, NULL, 0);
|
55
|
-
}
|
56
|
-
|
57
|
-
action done {
|
58
|
-
parser->body_start = fpc - buffer + 1;
|
59
|
-
if(parser->header_done != NULL)
|
60
|
-
parser->header_done(parser->data, fpc + 1, pe - fpc - 1);
|
61
|
-
fbreak;
|
62
|
-
}
|
63
|
-
|
64
|
-
# line endings
|
65
|
-
CRLF = "\r\n";
|
66
|
-
|
67
|
-
# character types
|
68
|
-
CTL = (cntrl | 127);
|
69
|
-
tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
|
70
|
-
|
71
|
-
# elements
|
72
|
-
token = (ascii -- (CTL | tspecials));
|
73
|
-
|
74
|
-
Reason_Phrase = (any -- CRLF)* >mark %reason_phrase;
|
75
|
-
Status_Code = digit{3} >mark %status_code;
|
76
|
-
http_number = (digit+ "." digit+) ;
|
77
|
-
HTTP_Version = ("HTTP/" http_number) >mark %http_version ;
|
78
|
-
Status_Line = HTTP_Version " " Status_Code " "? Reason_Phrase :> CRLF;
|
79
|
-
|
80
|
-
field_name = token+ >start_field %write_field;
|
81
|
-
field_value = any* >start_value %write_value;
|
82
|
-
message_header = field_name ":" " "* field_value :> CRLF;
|
83
|
-
|
84
|
-
Response = Status_Line (message_header)* (CRLF @done);
|
85
|
-
|
86
|
-
chunk_ext_val = token+;
|
87
|
-
chunk_ext_name = token+;
|
88
|
-
chunk_extension = (";" chunk_ext_name >start_field %write_field %start_value ("=" chunk_ext_val >start_value)? %write_value )*;
|
89
|
-
last_chunk = "0"? chunk_extension :> (CRLF @last_chunk @done);
|
90
|
-
chunk_size = xdigit+;
|
91
|
-
chunk = chunk_size >mark %chunk_size chunk_extension space* :> (CRLF @done);
|
92
|
-
Chunked_Header = (chunk | last_chunk);
|
93
|
-
|
94
|
-
main := Response | Chunked_Header;
|
95
|
-
}%%
|
96
|
-
|
97
|
-
/** Data **/
|
98
|
-
%% write data;
|
99
|
-
|
100
|
-
int httpclient_parser_init(httpclient_parser *parser) {
|
101
|
-
int cs = 0;
|
102
|
-
%% write init;
|
103
|
-
parser->cs = cs;
|
104
|
-
parser->body_start = 0;
|
105
|
-
parser->content_len = 0;
|
106
|
-
parser->mark = 0;
|
107
|
-
parser->nread = 0;
|
108
|
-
parser->field_len = 0;
|
109
|
-
parser->field_start = 0;
|
110
|
-
|
111
|
-
return(1);
|
112
|
-
}
|
113
|
-
|
114
|
-
|
115
|
-
/** exec **/
|
116
|
-
size_t httpclient_parser_execute(httpclient_parser *parser, const char *buffer, size_t len, size_t off) {
|
117
|
-
const char *p, *pe;
|
118
|
-
int cs = parser->cs;
|
119
|
-
|
120
|
-
assert(off <= len && "offset past end of buffer");
|
121
|
-
|
122
|
-
p = buffer+off;
|
123
|
-
pe = buffer+len;
|
124
|
-
|
125
|
-
assert(*pe == '\0' && "pointer does not end on NUL");
|
126
|
-
assert(pe - p == len - off && "pointers aren't same distance");
|
127
|
-
|
128
|
-
|
129
|
-
%% write exec;
|
130
|
-
|
131
|
-
parser->cs = cs;
|
132
|
-
parser->nread += p - (buffer + off);
|
133
|
-
|
134
|
-
assert(p <= pe && "buffer overflow after parsing execute");
|
135
|
-
assert(parser->nread <= len && "nread longer than length");
|
136
|
-
assert(parser->body_start <= len && "body starts after buffer end");
|
137
|
-
assert(parser->mark < len && "mark is after buffer end");
|
138
|
-
assert(parser->field_len <= len && "field has length longer than whole buffer");
|
139
|
-
assert(parser->field_start < len && "field starts after buffer end");
|
140
|
-
|
141
|
-
if(parser->body_start) {
|
142
|
-
/* final \r\n combo encountered so stop right here */
|
143
|
-
%%write eof;
|
144
|
-
parser->nread++;
|
145
|
-
}
|
146
|
-
|
147
|
-
return(parser->nread);
|
148
|
-
}
|
149
|
-
|
150
|
-
int httpclient_parser_finish(httpclient_parser *parser)
|
151
|
-
{
|
152
|
-
int cs = parser->cs;
|
153
|
-
|
154
|
-
%%write eof;
|
155
|
-
|
156
|
-
parser->cs = cs;
|
157
|
-
|
158
|
-
if (httpclient_parser_has_error(parser) ) {
|
159
|
-
return -1;
|
160
|
-
} else if (httpclient_parser_is_finished(parser) ) {
|
161
|
-
return 1;
|
162
|
-
} else {
|
163
|
-
return 0;
|
164
|
-
}
|
165
|
-
}
|
166
|
-
|
167
|
-
int httpclient_parser_has_error(httpclient_parser *parser) {
|
168
|
-
return parser->cs == httpclient_parser_error;
|
169
|
-
}
|
170
|
-
|
171
|
-
int httpclient_parser_is_finished(httpclient_parser *parser) {
|
172
|
-
return parser->cs == httpclient_parser_first_final;
|
173
|
-
}
|
data/lib/cool.io/eventmachine.rb
DELETED
@@ -1,234 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (C)2007-10 Tony Arcieri, Roger Pack
|
3
|
-
# You can redistribute this under the terms of the Ruby license
|
4
|
-
# See file LICENSE for details
|
5
|
-
#++
|
6
|
-
|
7
|
-
require 'cool.io'
|
8
|
-
|
9
|
-
# EventMachine emulation for Cool.io:
|
10
|
-
#
|
11
|
-
# require 'coolio/eventmachine'
|
12
|
-
#
|
13
|
-
# Drawbacks: slightly slower than EM.
|
14
|
-
# Benefits: timers are more accurate using libev than using EM
|
15
|
-
# TODO: some things like connection timeouts aren't implemented yet
|
16
|
-
# DONE: timers and normal socket functions are implemented.
|
17
|
-
module EventMachine
|
18
|
-
class << self
|
19
|
-
# Start the Reactor loop
|
20
|
-
def run
|
21
|
-
yield if block_given?
|
22
|
-
Coolio::Loop.default.run
|
23
|
-
end
|
24
|
-
|
25
|
-
# Stop the Reactor loop
|
26
|
-
def stop_event_loop
|
27
|
-
Coolio::Loop.default.stop
|
28
|
-
end
|
29
|
-
|
30
|
-
class OneShotEMTimer < Coolio::TimerWatcher
|
31
|
-
def setup(proc)
|
32
|
-
@proc = proc
|
33
|
-
end
|
34
|
-
|
35
|
-
def on_timer
|
36
|
-
@proc.call
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# ltodo: use Coolio's PeriodicTimer to wrap EM's two similar to it
|
41
|
-
# todo: close all connections on 'stop', I believe
|
42
|
-
|
43
|
-
def add_timer(interval, proc = nil, &block)
|
44
|
-
block ||= proc
|
45
|
-
t = OneShotEMTimer.new(interval, false) # non repeating
|
46
|
-
t.setup(block)
|
47
|
-
|
48
|
-
# fire 'er off ltodo: do we keep track of these timers in memory?
|
49
|
-
t.attach(Coolio::Loop.default)
|
50
|
-
t
|
51
|
-
end
|
52
|
-
|
53
|
-
def cancel_timer(t)
|
54
|
-
# guess there's a case where EM you can say 'cancel' but it's already fired?
|
55
|
-
# kind of odd but it happens
|
56
|
-
t.detach if t.attached?
|
57
|
-
end
|
58
|
-
|
59
|
-
def set_comm_inactivity_timeout(*args); end # TODO
|
60
|
-
|
61
|
-
# Make an outgoing connection
|
62
|
-
def connect(addr, port, handler = Connection, *args, &block)
|
63
|
-
block = args.pop if Proc === args[-1]
|
64
|
-
|
65
|
-
# make sure we're a 'real' class here
|
66
|
-
klass = if (handler and handler.is_a?(Class))
|
67
|
-
handler
|
68
|
-
else
|
69
|
-
Class.new( Connection ) {handler and include handler}
|
70
|
-
end
|
71
|
-
|
72
|
-
wrapped_child = CallsBackToEM.connect(addr, port, *args) # ltodo: args? what? they're used? also TODOC TODO FIX
|
73
|
-
conn = klass.new(wrapped_child) # ltodo [?] addr, port, *args)
|
74
|
-
wrapped_child.attach(Coolio::Loop.default) # necessary
|
75
|
-
conn.heres_your_socket(wrapped_child)
|
76
|
-
wrapped_child.call_back_to_this(conn) # calls post_init for us
|
77
|
-
yield conn if block_given?
|
78
|
-
end
|
79
|
-
|
80
|
-
# Start a TCP server on the given address and port
|
81
|
-
def start_server(addr, port, handler = Connection, *args, &block)
|
82
|
-
# make sure we're a 'real' class here
|
83
|
-
klass = if (handler and handler.is_a?(Class))
|
84
|
-
handler
|
85
|
-
else
|
86
|
-
Class.new( Connection ) {handler and include handler}
|
87
|
-
end
|
88
|
-
|
89
|
-
server = Coolio::TCPServer.new(addr, port, CallsBackToEM, *args) do |wrapped_child|
|
90
|
-
conn = klass.new(wrapped_child)
|
91
|
-
conn.heres_your_socket(wrapped_child) # ideally NOT have this :)
|
92
|
-
wrapped_child.call_back_to_this(conn)
|
93
|
-
block.call(conn) if block
|
94
|
-
end
|
95
|
-
|
96
|
-
server.attach(Coolio::Loop.default)
|
97
|
-
end
|
98
|
-
|
99
|
-
def stop_server(server)
|
100
|
-
server.close
|
101
|
-
end
|
102
|
-
|
103
|
-
# Set the maximum number of descriptors available to this process
|
104
|
-
def set_descriptor_table_size(nfds)
|
105
|
-
Coolio::Utils.maxfds = nfds
|
106
|
-
end
|
107
|
-
|
108
|
-
# Compatibility noop. Handled automatically by libev
|
109
|
-
def epoll; end
|
110
|
-
|
111
|
-
# Compatibility noop. Handled automatically by libev
|
112
|
-
def kqueue; end
|
113
|
-
end
|
114
|
-
|
115
|
-
class CallsBackToEM < Coolio::TCPSocket
|
116
|
-
class ConnectTimer < Coolio::TimerWatcher
|
117
|
-
attr_accessor :parent
|
118
|
-
def on_timer
|
119
|
-
@parent.connection_has_timed_out
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def call_back_to_this parent
|
124
|
-
@call_back_to_this = parent
|
125
|
-
parent.post_init
|
126
|
-
end
|
127
|
-
|
128
|
-
def on_connect
|
129
|
-
# @connection_timer.detach if @connection_timer
|
130
|
-
# won't need that anymore :) -- with server connecteds we don't have it, anyway
|
131
|
-
|
132
|
-
# TODO should server accepted's call this? They don't currently
|
133
|
-
# [and can't, since on_connect gets called basically in the initializer--needs some code love for that to happen :)
|
134
|
-
@call_back_to_this.connection_completed if @call_back_to_this
|
135
|
-
end
|
136
|
-
|
137
|
-
def connection_has_timed_out
|
138
|
-
return if closed?
|
139
|
-
|
140
|
-
# wonder if this works when you're within a half-connected phase.
|
141
|
-
# I think it does. What about TCP state?
|
142
|
-
close unless closed?
|
143
|
-
@call_back_to_this.unbind
|
144
|
-
end
|
145
|
-
|
146
|
-
def on_write_complete
|
147
|
-
close if @should_close_after_writing
|
148
|
-
end
|
149
|
-
|
150
|
-
def should_close_after_writing
|
151
|
-
@should_close_after_writing = true;
|
152
|
-
end
|
153
|
-
|
154
|
-
def on_close
|
155
|
-
@call_back_to_this.unbind # about the same ltodo check if they ARE the same here
|
156
|
-
end
|
157
|
-
|
158
|
-
def on_resolve_failed
|
159
|
-
fail
|
160
|
-
end
|
161
|
-
|
162
|
-
def on_connect_failed
|
163
|
-
fail
|
164
|
-
end
|
165
|
-
|
166
|
-
def on_read(data)
|
167
|
-
@call_back_to_this.receive_data data
|
168
|
-
end
|
169
|
-
|
170
|
-
def fail
|
171
|
-
#@connection_timer.detch if @connection_timer
|
172
|
-
@call_back_to_this.unbind
|
173
|
-
end
|
174
|
-
|
175
|
-
def self.connect(*args)
|
176
|
-
a = super *args
|
177
|
-
# the connect timer currently kills TCPServer classes. I'm not sure why.
|
178
|
-
#@connection_timer = ConnectTimer.new(14) # needs to be at least higher than 12 :)
|
179
|
-
#@connection_timer.parent = a
|
180
|
-
#@connection_timer.attach(Coolio::Loop.default)
|
181
|
-
a
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
class Connection
|
186
|
-
def self.new(*args)
|
187
|
-
allocate#.instance_eval do
|
188
|
-
# initialize *args
|
189
|
-
#end
|
190
|
-
end
|
191
|
-
|
192
|
-
# we will need to call 'their functions' appropriately -- the commented out ones, here
|
193
|
-
#
|
194
|
-
# Callback fired when connection is created
|
195
|
-
def post_init
|
196
|
-
# I thought we were 'overriding' EM's existing methods, here.
|
197
|
-
# Huh? Why do we have to define these then?
|
198
|
-
end
|
199
|
-
|
200
|
-
# Callback fired when connection is closed
|
201
|
-
def unbind; end
|
202
|
-
|
203
|
-
# Callback fired when data is received
|
204
|
-
# def receive_data(data); end
|
205
|
-
def heres_your_socket(instantiated_coolio_socket)
|
206
|
-
instantiated_coolio_socket.call_back_to_this self
|
207
|
-
@wrapped_coolio = instantiated_coolio_socket
|
208
|
-
end
|
209
|
-
|
210
|
-
# Send data to the current connection -- called by them
|
211
|
-
def send_data(data)
|
212
|
-
@wrapped_coolio.write data
|
213
|
-
end
|
214
|
-
|
215
|
-
# Close the connection, optionally after writing
|
216
|
-
def close_connection(after_writing = false)
|
217
|
-
return close_connection_after_writing if after_writing
|
218
|
-
@wrapped_coolio.close
|
219
|
-
end
|
220
|
-
|
221
|
-
# Close the connection after all data has been written
|
222
|
-
def close_connection_after_writing
|
223
|
-
@wrapped_coolio.output_buffer_size.zero? ? @wrapped_coolio.close : @wrapped_coolio.should_close_after_writing
|
224
|
-
end
|
225
|
-
|
226
|
-
def get_peername
|
227
|
-
family, port, host_name, host_ip = @wrapped_coolio.peeraddr
|
228
|
-
Socket.pack_sockaddr_in(port, host_ip) # pack it up :)
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
# Shortcut constant
|
234
|
-
EM = EventMachine
|