typhoeus 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/{CHANGELOG.markdown → CHANGELOG.md} +21 -12
  2. data/LICENSE +2 -0
  3. data/README.md +455 -0
  4. data/Rakefile +6 -26
  5. data/lib/typhoeus.rb +4 -6
  6. data/lib/typhoeus/curl.rb +453 -0
  7. data/lib/typhoeus/easy.rb +60 -358
  8. data/lib/typhoeus/easy/auth.rb +14 -0
  9. data/lib/typhoeus/easy/callbacks.rb +33 -0
  10. data/lib/typhoeus/easy/ffi_helper.rb +61 -0
  11. data/lib/typhoeus/easy/infos.rb +90 -0
  12. data/lib/typhoeus/easy/options.rb +115 -0
  13. data/lib/typhoeus/easy/proxy.rb +20 -0
  14. data/lib/typhoeus/easy/ssl.rb +82 -0
  15. data/lib/typhoeus/form.rb +30 -1
  16. data/lib/typhoeus/{normalized_header_hash.rb → header.rb} +2 -6
  17. data/lib/typhoeus/hydra.rb +9 -12
  18. data/lib/typhoeus/hydra_mock.rb +2 -2
  19. data/lib/typhoeus/multi.rb +118 -9
  20. data/lib/typhoeus/param_processor.rb +43 -0
  21. data/lib/typhoeus/request.rb +18 -21
  22. data/lib/typhoeus/response.rb +5 -4
  23. data/lib/typhoeus/utils.rb +14 -27
  24. data/lib/typhoeus/version.rb +1 -1
  25. metadata +155 -152
  26. data/Gemfile.lock +0 -37
  27. data/ext/typhoeus/.gitignore +0 -7
  28. data/ext/typhoeus/extconf.rb +0 -65
  29. data/ext/typhoeus/native.c +0 -12
  30. data/ext/typhoeus/native.h +0 -22
  31. data/ext/typhoeus/typhoeus_easy.c +0 -232
  32. data/ext/typhoeus/typhoeus_easy.h +0 -20
  33. data/ext/typhoeus/typhoeus_form.c +0 -59
  34. data/ext/typhoeus/typhoeus_form.h +0 -13
  35. data/ext/typhoeus/typhoeus_multi.c +0 -217
  36. data/ext/typhoeus/typhoeus_multi.h +0 -16
  37. data/lib/typhoeus/.gitignore +0 -1
  38. data/lib/typhoeus/service.rb +0 -20
  39. data/spec/fixtures/placeholder.gif +0 -0
  40. data/spec/fixtures/placeholder.txt +0 -1
  41. data/spec/fixtures/placeholder.ukn +0 -0
  42. data/spec/fixtures/result_set.xml +0 -60
  43. data/spec/servers/app.rb +0 -97
  44. data/spec/spec_helper.rb +0 -19
  45. data/spec/support/typhoeus_localhost_server.rb +0 -58
  46. data/spec/typhoeus/easy_spec.rb +0 -391
  47. data/spec/typhoeus/filter_spec.rb +0 -35
  48. data/spec/typhoeus/form_spec.rb +0 -117
  49. data/spec/typhoeus/hydra_mock_spec.rb +0 -300
  50. data/spec/typhoeus/hydra_spec.rb +0 -602
  51. data/spec/typhoeus/multi_spec.rb +0 -74
  52. data/spec/typhoeus/normalized_header_hash_spec.rb +0 -41
  53. data/spec/typhoeus/remote_method_spec.rb +0 -141
  54. data/spec/typhoeus/remote_proxy_object_spec.rb +0 -65
  55. data/spec/typhoeus/remote_spec.rb +0 -695
  56. data/spec/typhoeus/request_spec.rb +0 -387
  57. data/spec/typhoeus/response_spec.rb +0 -192
  58. data/spec/typhoeus/utils_spec.rb +0 -22
  59. data/typhoeus.gemspec +0 -33
@@ -1,7 +0,0 @@
1
- conftest.dSYM/*
2
- conftest.dSYM
3
- mkmf.log
4
- *.o
5
- native.bundle
6
- Makefile
7
- *.bundle
@@ -1,65 +0,0 @@
1
- ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
2
-
3
- # :stopdoc:
4
-
5
- require 'mkmf'
6
-
7
- ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
8
- specified_curl = ARGV[0] =~ /^--with-curl/ ? ARGV[0].split("=")[1] : nil
9
- LIBDIR = specified_curl ? "#{specified_curl}/lib": Config::CONFIG['libdir']
10
- INCLUDEDIR = specified_curl ? "#{specified_curl}/include" : Config::CONFIG['includedir']
11
-
12
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'macruby'
13
- $LIBRUBYARG_STATIC.gsub!(/-static/, '')
14
- end
15
-
16
- $CFLAGS << " #{ENV["CFLAGS"]}"
17
- if Config::CONFIG['target_os'] == 'mingw32'
18
- $CFLAGS << " -DXP_WIN -DXP_WIN32 -DUSE_INCLUDED_VASPRINTF"
19
- elsif Config::CONFIG['target_os'] == 'solaris2'
20
- $CFLAGS << " -DUSE_INCLUDED_VASPRINTF"
21
- else
22
- $CFLAGS << " -g -DXP_UNIX"
23
- end
24
-
25
- use_macports = !(defined?(RUBY_ENGINE) && RUBY_ENGINE != 'ruby')
26
- $LIBPATH << "/opt/local/lib" if use_macports
27
-
28
- $CFLAGS << " -O3 -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline"
29
-
30
- if Config::CONFIG['target_os'] == 'mingw32'
31
- header = File.join(ROOT, 'cross', 'curl-7.19.4.win32', 'include')
32
- unless find_header('curl/curl.h', header)
33
- abort "need libcurl"
34
- end
35
- else
36
- HEADER_DIRS = [
37
- File.join(INCLUDEDIR, "curl"),
38
- INCLUDEDIR,
39
- '/usr/include/curl',
40
- '/usr/local/include/curl'
41
- ]
42
-
43
- [
44
- '/opt/local/include/curl',
45
- '/opt/local/include',
46
- ].each { |x| HEADER_DIRS.unshift(x) } if use_macports
47
-
48
- unless find_header('curl/curl.h', *HEADER_DIRS)
49
- abort "need libcurl"
50
- end
51
- end
52
-
53
- if Config::CONFIG['target_os'] == 'mingw32'
54
- find_library('curl', 'curl_easy_init',
55
- File.join(ROOT, 'cross', 'curl-7.19.4.win32', 'bin'))
56
- else
57
- find_library('curl', 'curl_easy_init',
58
- LIBDIR,
59
- '/opt/local/lib',
60
- '/usr/local/lib',
61
- '/usr/lib'
62
- )
63
- end
64
-
65
- create_makefile("typhoeus/native")
@@ -1,12 +0,0 @@
1
- #include <native.h>
2
-
3
- VALUE mTyphoeus;
4
-
5
- void Init_native()
6
- {
7
- mTyphoeus = rb_const_get(rb_cObject, rb_intern("Typhoeus"));
8
-
9
- init_typhoeus_easy();
10
- init_typhoeus_multi();
11
- init_typhoeus_form();
12
- }
@@ -1,22 +0,0 @@
1
- #ifndef TYPHOEUS_NATIVE
2
- #define TYPHOEUS_NATIVE
3
-
4
- #include <ruby.h>
5
- #include <curl/curl.h>
6
- #include <curl/easy.h>
7
- #include <curl/multi.h>
8
-
9
- void Init_native();
10
- extern VALUE mTyphoeus;
11
- extern void init_typhoeus_easy();
12
- extern void init_typhoeus_multi();
13
- extern void init_typhoeus_form();
14
-
15
- #endif
16
-
17
- #ifndef RSTRING_PTR
18
-
19
- #define RSTRING_PTR(s) (RSTRING(s)->ptr)
20
- #define RSTRING_LEN(s) (RSTRING(s)->len)
21
-
22
- #endif
@@ -1,232 +0,0 @@
1
- #include <typhoeus_easy.h>
2
-
3
- static VALUE idAppend;
4
- VALUE cTyphoeusEasy;
5
-
6
- static void dealloc(CurlEasy *curl_easy) {
7
- if (curl_easy->request_chunk != NULL) {
8
- free(curl_easy->request_chunk);
9
- }
10
-
11
- if (curl_easy->headers != NULL) {
12
- curl_slist_free_all(curl_easy->headers);
13
- }
14
-
15
- curl_easy_cleanup(curl_easy->curl);
16
-
17
- free(curl_easy);
18
- }
19
-
20
- static VALUE easy_setopt_string(VALUE self, VALUE opt_name, VALUE parameter) {
21
- CurlEasy *curl_easy;
22
- Data_Get_Struct(self, CurlEasy, curl_easy);
23
-
24
- CURLoption opt = NUM2LONG(opt_name);
25
- curl_easy_setopt(curl_easy->curl, opt, StringValuePtr(parameter));
26
- return opt_name;
27
- }
28
-
29
- static VALUE easy_setopt_form(VALUE self, VALUE opt_name, VALUE parameter) {
30
- CurlEasy *curl_easy;
31
- CurlForm *curl_form;
32
- Data_Get_Struct(self, CurlEasy, curl_easy);
33
- Data_Get_Struct(parameter, CurlForm, curl_form);
34
-
35
- CURLoption opt = NUM2LONG(opt_name);
36
- curl_easy_setopt(curl_easy->curl, opt, curl_form->first);
37
- return opt_name;
38
- }
39
-
40
- static VALUE easy_setopt_long(VALUE self, VALUE opt_name, VALUE parameter) {
41
- CurlEasy *curl_easy;
42
- Data_Get_Struct(self, CurlEasy, curl_easy);
43
-
44
- CURLoption opt = NUM2LONG(opt_name);
45
- curl_easy_setopt(curl_easy->curl, opt, NUM2LONG(parameter));
46
- return opt_name;
47
- }
48
-
49
- static VALUE easy_getinfo_string(VALUE self, VALUE info) {
50
- char *info_string;
51
- CurlEasy *curl_easy;
52
- Data_Get_Struct(self, CurlEasy, curl_easy);
53
-
54
- CURLoption opt = NUM2LONG(info);
55
- curl_easy_getinfo(curl_easy->curl, opt, &info_string);
56
-
57
- return rb_str_new2(info_string);
58
- }
59
-
60
- static VALUE easy_getinfo_long(VALUE self, VALUE info) {
61
- long info_long;
62
- CurlEasy *curl_easy;
63
- Data_Get_Struct(self, CurlEasy, curl_easy);
64
-
65
- CURLoption opt = NUM2LONG(info);
66
- curl_easy_getinfo(curl_easy->curl, opt, &info_long);
67
-
68
- return LONG2NUM(info_long);
69
- }
70
-
71
- static VALUE easy_getinfo_double(VALUE self, VALUE info) {
72
- double info_double = 0;
73
- CurlEasy *curl_easy;
74
- Data_Get_Struct(self, CurlEasy, curl_easy);
75
-
76
- CURLoption opt = NUM2LONG(info);
77
- curl_easy_getinfo(curl_easy->curl, opt, &info_double);
78
-
79
- return rb_float_new(info_double);
80
- }
81
-
82
- static VALUE easy_perform(VALUE self) {
83
- CurlEasy *curl_easy;
84
- CURLcode return_code;
85
- Data_Get_Struct(self, CurlEasy, curl_easy);
86
- return_code = curl_easy_perform(curl_easy->curl);
87
- rb_iv_set(self, "@curl_return_code", INT2FIX(return_code));
88
-
89
- return Qnil;
90
- }
91
-
92
- static size_t write_data_handler(char *stream, size_t size, size_t nmemb, VALUE val) {
93
- long stream_size = (long)(size * nmemb);
94
- rb_funcall(val, idAppend, 1, rb_str_new(stream, stream_size));
95
- return size * nmemb;
96
- }
97
-
98
- static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *data) {
99
- size_t realsize = size * nmemb;
100
- RequestChunk *mem = (RequestChunk *)data;
101
-
102
- if (realsize > mem->size - mem->read) {
103
- realsize = mem->size - mem->read;
104
- }
105
-
106
- if (realsize != 0) {
107
- memcpy(ptr, &(mem->memory[mem->read]), realsize);
108
- mem->read += realsize;
109
- }
110
-
111
- return realsize;
112
- }
113
-
114
- static void set_response_handlers(VALUE easy, CURL *curl) {
115
- rb_iv_set(easy, "@response_body", rb_str_new2(""));
116
- rb_iv_set(easy, "@response_header", rb_str_new2(""));
117
-
118
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&write_data_handler);
119
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, rb_iv_get(easy, "@response_body"));
120
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&write_data_handler);
121
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, rb_iv_get(easy, "@response_header"));
122
- }
123
-
124
- static VALUE easy_reset(VALUE self) {
125
- CurlEasy *curl_easy;
126
- Data_Get_Struct(self, CurlEasy, curl_easy);
127
-
128
- if (curl_easy->request_chunk != NULL) {
129
- free(curl_easy->request_chunk);
130
- curl_easy->request_chunk = NULL;
131
- }
132
-
133
- if (curl_easy->headers != NULL) {
134
- curl_slist_free_all(curl_easy->headers);
135
- curl_easy->headers = NULL;
136
- }
137
-
138
- curl_easy_reset(curl_easy->curl);
139
-
140
- set_response_handlers(self, curl_easy->curl);
141
-
142
- return Qnil;
143
- }
144
-
145
- static VALUE easy_add_header(VALUE self, VALUE header) {
146
- CurlEasy *curl_easy;
147
- Data_Get_Struct(self, CurlEasy, curl_easy);
148
-
149
- curl_easy->headers = curl_slist_append(curl_easy->headers, RSTRING_PTR(header));
150
- return header;
151
- }
152
-
153
- static VALUE easy_set_headers(VALUE self) {
154
- CurlEasy *curl_easy;
155
- Data_Get_Struct(self, CurlEasy, curl_easy);
156
-
157
- curl_easy_setopt(curl_easy->curl, CURLOPT_HTTPHEADER, curl_easy->headers);
158
-
159
- return Qnil;
160
- }
161
-
162
- static VALUE easy_set_request_body(VALUE self, VALUE data, VALUE content_length_header) {
163
- CurlEasy *curl_easy;
164
- Data_Get_Struct(self, CurlEasy, curl_easy);
165
-
166
- curl_easy->request_chunk = ALLOC(RequestChunk);
167
- curl_easy->request_chunk->size = RSTRING_LEN(data);
168
- curl_easy->request_chunk->memory = StringValuePtr(data);
169
- curl_easy->request_chunk->read = 0;
170
-
171
- curl_easy_setopt(curl_easy->curl, CURLOPT_READFUNCTION, (curl_read_callback)read_callback);
172
- curl_easy_setopt(curl_easy->curl, CURLOPT_READDATA, curl_easy->request_chunk);
173
- curl_easy_setopt(curl_easy->curl, CURLOPT_INFILESIZE, RSTRING_LEN(data));
174
-
175
- return Qnil;
176
- }
177
-
178
- static VALUE easy_escape(VALUE self, VALUE data, VALUE length) {
179
- CurlEasy *curl_easy;
180
- Data_Get_Struct(self, CurlEasy, curl_easy);
181
-
182
- return rb_str_new2(curl_easy_escape(curl_easy->curl, StringValuePtr(data), (int)NUM2INT(length)));
183
- }
184
-
185
- static VALUE version(VALUE self) {
186
- return rb_str_new2(curl_version());
187
- }
188
-
189
- static VALUE new(int argc, VALUE *argv, VALUE klass) {
190
- CURL *curl = curl_easy_init();
191
- CurlEasy *curl_easy = ALLOC(CurlEasy);
192
- curl_easy->curl = curl;
193
- curl_easy->headers = NULL;
194
- curl_easy->request_chunk = NULL;
195
- VALUE easy = Data_Wrap_Struct(cTyphoeusEasy, 0, dealloc, curl_easy);
196
-
197
- set_response_handlers(easy, curl);
198
-
199
- rb_obj_call_init(easy, argc, argv);
200
-
201
- return easy;
202
- }
203
-
204
- static VALUE curl_error_message(VALUE self) {
205
- VALUE return_code = rb_iv_get(self, "@curl_return_code");
206
- if (return_code == Qnil)
207
- return Qnil;
208
- else {
209
- CURLcode rc = (CURLcode)FIX2INT(return_code);
210
- return rb_str_new2(curl_easy_strerror(rc));
211
- }
212
- }
213
-
214
- void init_typhoeus_easy() {
215
- VALUE klass = cTyphoeusEasy = rb_define_class_under(mTyphoeus, "Easy", rb_cObject);
216
- idAppend = rb_intern("<<");
217
- rb_define_singleton_method(klass, "new", new, -1);
218
- rb_define_method(klass, "curl_error_message", curl_error_message, 0);
219
- rb_define_private_method(klass, "easy_setopt_string", easy_setopt_string, 2);
220
- rb_define_private_method(klass, "easy_setopt_form", easy_setopt_form, 2);
221
- rb_define_private_method(klass, "easy_setopt_long", easy_setopt_long, 2);
222
- rb_define_private_method(klass, "easy_getinfo_string", easy_getinfo_string, 1);
223
- rb_define_private_method(klass, "easy_getinfo_long", easy_getinfo_long, 1);
224
- rb_define_private_method(klass, "easy_getinfo_double", easy_getinfo_double, 1);
225
- rb_define_private_method(klass, "easy_perform", easy_perform, 0);
226
- rb_define_private_method(klass, "easy_reset", easy_reset, 0);
227
- rb_define_private_method(klass, "easy_set_request_body", easy_set_request_body, 1);
228
- rb_define_private_method(klass, "easy_set_headers", easy_set_headers, 0);
229
- rb_define_private_method(klass, "easy_add_header", easy_add_header, 1);
230
- rb_define_private_method(klass, "easy_escape", easy_escape, 2);
231
- rb_define_private_method(klass, "version", version, 0);
232
- }
@@ -1,20 +0,0 @@
1
- #ifndef TYPHOEUS_EASY
2
- #define TYPHOEUS_EASY
3
-
4
- #include <native.h>
5
- #include <typhoeus_form.h>
6
-
7
- void init_typhoeus_easy();
8
- typedef struct {
9
- const char *memory;
10
- int size;
11
- int read;
12
- } RequestChunk;
13
-
14
- typedef struct {
15
- RequestChunk *request_chunk;
16
- CURL *curl;
17
- struct curl_slist *headers;
18
- } CurlEasy;
19
-
20
- #endif
@@ -1,59 +0,0 @@
1
- #include <typhoeus_form.h>
2
-
3
- VALUE cTyphoeusForm;
4
-
5
- static void dealloc(CurlForm *curl_form) {
6
- curl_formfree(curl_form->first);
7
- free(curl_form);
8
- }
9
-
10
- static VALUE formadd_file(VALUE self,
11
- VALUE name,
12
- VALUE filename,
13
- VALUE content_type,
14
- VALUE path) {
15
- CurlForm *curl_form;
16
- Data_Get_Struct(self, CurlForm, curl_form);
17
-
18
- return INT2NUM((long) curl_formadd(&curl_form->first, &curl_form->last,
19
- CURLFORM_COPYNAME, RSTRING_PTR(name),
20
- CURLFORM_NAMELENGTH, (long)RSTRING_LEN(name),
21
- CURLFORM_FILENAME, RSTRING_PTR(filename),
22
- CURLFORM_CONTENTTYPE, RSTRING_PTR(content_type),
23
- CURLFORM_FILE, RSTRING_PTR(path),
24
- CURLFORM_END
25
- ));
26
- }
27
-
28
- static VALUE formadd_param(VALUE self, VALUE name, VALUE value) {
29
- CurlForm *curl_form;
30
- Data_Get_Struct(self, CurlForm, curl_form);
31
-
32
- return INT2NUM((long)curl_formadd(&curl_form->first, &curl_form->last,
33
- CURLFORM_COPYNAME, RSTRING_PTR(name),
34
- CURLFORM_NAMELENGTH, (long)RSTRING_LEN(name),
35
- CURLFORM_COPYCONTENTS, RSTRING_PTR(value),
36
- CURLFORM_CONTENTSLENGTH, (long)RSTRING_LEN(value),
37
- CURLFORM_END
38
- ));
39
- }
40
-
41
- static VALUE new(int argc, VALUE *argv, VALUE klass) {
42
- CurlForm *curl_form = ALLOC(CurlForm);
43
- curl_form->first = NULL;
44
- curl_form->last = NULL;
45
-
46
- VALUE form = Data_Wrap_Struct(cTyphoeusForm, 0, dealloc, curl_form);
47
-
48
- rb_obj_call_init(form, argc, argv);
49
-
50
- return form;
51
- }
52
-
53
- void init_typhoeus_form() {
54
- VALUE klass = cTyphoeusForm = rb_define_class_under(mTyphoeus, "Form", rb_cObject);
55
-
56
- rb_define_singleton_method(klass, "new", new, -1);
57
- rb_define_private_method(klass, "formadd_file", formadd_file, 4);
58
- rb_define_private_method(klass, "formadd_param", formadd_param, 2);
59
- }
@@ -1,13 +0,0 @@
1
- #ifndef TYPHOEUS_FORM
2
- #define TYPHOEUS_FORM
3
-
4
- #include <native.h>
5
-
6
- typedef struct {
7
- struct curl_httppost *first;
8
- struct curl_httppost *last;
9
- } CurlForm;
10
-
11
- void init_typhoeus_form();
12
-
13
- #endif
@@ -1,217 +0,0 @@
1
- /* Make sure select() works with >1024 file handles open. */
2
- #include <sys/types.h>
3
- #undef __FD_SETSIZE
4
- #define __FD_SETSIZE 524288
5
-
6
- #include <typhoeus_multi.h>
7
- #include <errno.h>
8
-
9
- static void multi_read_info(VALUE self, CURLM *multi_handle);
10
-
11
- static void dealloc(CurlMulti *curl_multi) {
12
- curl_multi_cleanup(curl_multi->multi);
13
- free(curl_multi);
14
- }
15
-
16
- static VALUE multi_add_handle(VALUE self, VALUE easy) {
17
- CurlEasy *curl_easy;
18
- Data_Get_Struct(easy, CurlEasy, curl_easy);
19
- CurlMulti *curl_multi;
20
- Data_Get_Struct(self, CurlMulti, curl_multi);
21
- CURLMcode mcode;
22
-
23
- mcode = curl_multi_add_handle(curl_multi->multi, curl_easy->curl);
24
- if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
25
- rb_raise(rb_eRuntimeError, "An error occured adding the handle: %d: %s", mcode, curl_multi_strerror(mcode));
26
- }
27
-
28
- curl_easy_setopt(curl_easy->curl, CURLOPT_PRIVATE, easy);
29
- curl_multi->active++;
30
-
31
- VALUE easy_handles = rb_iv_get(self, "@easy_handles");
32
- rb_ary_push(easy_handles, easy);
33
-
34
- if (mcode == CURLM_CALL_MULTI_PERFORM) {
35
- curl_multi_perform(curl_multi->multi, &(curl_multi->running));
36
- }
37
- //
38
- // if (curl_multi->running) {
39
- // printf("call read_info on add<br/>");
40
- // multi_read_info(self, curl_multi->multi);
41
- // }
42
-
43
- return easy;
44
- }
45
-
46
- static VALUE multi_remove_handle(VALUE self, VALUE easy) {
47
- CurlEasy *curl_easy;
48
- Data_Get_Struct(easy, CurlEasy, curl_easy);
49
- CurlMulti *curl_multi;
50
- Data_Get_Struct(self, CurlMulti, curl_multi);
51
-
52
- curl_multi->active--;
53
- curl_multi_remove_handle(curl_multi->multi, curl_easy->curl);
54
-
55
- VALUE easy_handles = rb_iv_get(self, "@easy_handles");
56
- rb_ary_delete(easy_handles, easy);
57
-
58
- return easy;
59
- }
60
-
61
- static void multi_read_info(VALUE self, CURLM *multi_handle) {
62
- int msgs_left, result;
63
- CURLMsg *msg;
64
- CURLcode ecode;
65
- CURL *easy_handle;
66
- VALUE easy;
67
-
68
- /* check for finished easy handles and remove from the multi handle */
69
- while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
70
-
71
- if (msg->msg != CURLMSG_DONE) {
72
- continue;
73
- }
74
-
75
- easy_handle = msg->easy_handle;
76
- result = msg->data.result;
77
- if (easy_handle) {
78
- ecode = curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, &easy);
79
- if (ecode != 0) {
80
- rb_raise(rb_eRuntimeError, "error getting easy object: %d: %s", ecode, curl_easy_strerror(ecode));
81
- }
82
-
83
- long response_code = -1;
84
- curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &response_code);
85
-
86
- multi_remove_handle(self, easy);
87
- rb_iv_set(easy, "@curl_return_code", INT2FIX(result));
88
-
89
- if (result != 0) {
90
- rb_funcall(easy, rb_intern("failure"), 0);
91
- }
92
- else if ((response_code >= 200 && response_code < 300) || response_code == 0) {
93
- rb_funcall(easy, rb_intern("success"), 0);
94
- }
95
- else {
96
- rb_funcall(easy, rb_intern("failure"), 0);
97
- }
98
- }
99
- }
100
- }
101
-
102
- /* called by multi_perform and fire_and_forget */
103
- static void rb_curl_multi_run(VALUE self, CURLM *multi_handle, int *still_running) {
104
- CURLMcode mcode;
105
-
106
- do {
107
- mcode = curl_multi_perform(multi_handle, still_running);
108
- } while (mcode == CURLM_CALL_MULTI_PERFORM);
109
-
110
- if (mcode != CURLM_OK) {
111
- rb_raise(rb_eRuntimeError, "an error occured while running perform: %d: %s", mcode, curl_multi_strerror(mcode));
112
- }
113
-
114
- multi_read_info( self, multi_handle );
115
- }
116
-
117
- static VALUE fire_and_forget(VALUE self) {
118
- CurlMulti *curl_multi;
119
- Data_Get_Struct(self, CurlMulti, curl_multi);
120
- rb_curl_multi_run( self, curl_multi->multi, &(curl_multi->running) );
121
-
122
- return Qnil;
123
- }
124
-
125
- static VALUE multi_perform(VALUE self) {
126
- CURLMcode mcode;
127
- CurlMulti *curl_multi;
128
- int maxfd, rc;
129
- fd_set fdread, fdwrite, fdexcep;
130
-
131
- long timeout;
132
- struct timeval tv = {0, 0};
133
-
134
- Data_Get_Struct(self, CurlMulti, curl_multi);
135
-
136
- rb_curl_multi_run( self, curl_multi->multi, &(curl_multi->running) );
137
- while(curl_multi->running) {
138
- FD_ZERO(&fdread);
139
- FD_ZERO(&fdwrite);
140
- FD_ZERO(&fdexcep);
141
-
142
- /* get the curl suggested time out */
143
- mcode = curl_multi_timeout(curl_multi->multi, &timeout);
144
- if (mcode != CURLM_OK) {
145
- rb_raise(rb_eRuntimeError, "an error occured getting the timeout: %d: %s", mcode, curl_multi_strerror(mcode));
146
- }
147
-
148
- if (timeout == 0) { /* no delay */
149
- rb_curl_multi_run( self, curl_multi->multi, &(curl_multi->running) );
150
- continue;
151
- }
152
- else if (timeout < 0) {
153
- timeout = 1;
154
- }
155
-
156
- tv.tv_sec = timeout / 1000;
157
- tv.tv_usec = (timeout * 1000) % 1000000;
158
-
159
- /* load the fd sets from the multi handle */
160
- mcode = curl_multi_fdset(curl_multi->multi, &fdread, &fdwrite, &fdexcep, &maxfd);
161
- if (mcode != CURLM_OK) {
162
- rb_raise(rb_eRuntimeError, "an error occured getting the fdset: %d: %s", mcode, curl_multi_strerror(mcode));
163
- }
164
-
165
- rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
166
- if (rc < 0) {
167
- rb_raise(rb_eRuntimeError, "error on thread select: %d", errno);
168
- }
169
- rb_curl_multi_run( self, curl_multi->multi, &(curl_multi->running) );
170
-
171
- }
172
-
173
- return Qnil;
174
- }
175
-
176
- static VALUE active_handle_count(VALUE self) {
177
- CurlMulti *curl_multi;
178
- Data_Get_Struct(self, CurlMulti, curl_multi);
179
-
180
- return INT2FIX(curl_multi->active);
181
- }
182
-
183
- static VALUE multi_cleanup(VALUE self) {
184
- CurlMulti *curl_multi;
185
- Data_Get_Struct(self, CurlMulti, curl_multi);
186
-
187
- curl_multi_cleanup(curl_multi->multi);
188
- curl_multi->active = 0;
189
- curl_multi->running = 0;
190
-
191
- return Qnil;
192
- }
193
-
194
- static VALUE new(int argc, VALUE *argv, VALUE klass) {
195
- CurlMulti *curl_multi = ALLOC(CurlMulti);
196
- curl_multi->multi = curl_multi_init();
197
- curl_multi->active = 0;
198
- curl_multi->running = 0;
199
-
200
- VALUE multi = Data_Wrap_Struct(cTyphoeusMulti, 0, dealloc, curl_multi);
201
-
202
- rb_obj_call_init(multi, argc, argv);
203
-
204
- return multi;
205
- }
206
-
207
- void init_typhoeus_multi() {
208
- VALUE klass = cTyphoeusMulti = rb_define_class_under(mTyphoeus, "Multi", rb_cObject);
209
-
210
- rb_define_singleton_method(klass, "new", new, -1);
211
- rb_define_private_method(klass, "multi_add_handle", multi_add_handle, 1);
212
- rb_define_private_method(klass, "multi_remove_handle", multi_remove_handle, 1);
213
- rb_define_private_method(klass, "multi_perform", multi_perform, 0);
214
- rb_define_private_method(klass, "multi_cleanup", multi_cleanup, 0);
215
- rb_define_private_method(klass, "active_handle_count", active_handle_count, 0);
216
- rb_define_method(klass, "fire_and_forget", fire_and_forget, 0);
217
- }