taf2-curb 0.2.8.0 → 0.3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -2
- data/Rakefile +5 -1
- data/ext/curb.h +7 -4
- data/ext/curb_easy.c +77 -34
- data/ext/curb_errors.c +11 -1
- data/ext/curb_multi.c +39 -16
- data/ext/curb_postfield.c +14 -4
- data/ext/extconf.rb +29 -2
- data/tests/helper.rb +50 -16
- data/tests/tc_curl_multi.rb +1 -1
- metadata +2 -3
data/README
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
* http://curb.rubyforge.org/
|
4
4
|
* http://rubyforge.org/projects/curb
|
5
|
-
* http://groups.google.com/group/curb---ruby-libcurl-bindings
|
6
5
|
* http://github.com/taf2/curb/tree/master
|
7
6
|
|
8
7
|
Curb (probably CUrl-RuBy or something) provides Ruby-language bindings for the
|
@@ -18,7 +17,7 @@ Ruby license. See the LICENSE file for the gory details.
|
|
18
17
|
|
19
18
|
=== You will need
|
20
19
|
|
21
|
-
* A working Ruby installation (1.8+, tested with 1.8.5)
|
20
|
+
* A working Ruby installation (1.8+, tested with 1.8.5, 1.8.6, 1.8.7, and 1.9.1)
|
22
21
|
* A working (lib)curl installation, with development stuff (7.5+, tested with 7.15)
|
23
22
|
* A sane build environment
|
24
23
|
|
data/Rakefile
CHANGED
@@ -78,7 +78,11 @@ end
|
|
78
78
|
# Test Tasks ---------------------------------------------------------
|
79
79
|
task :ta => :alltests
|
80
80
|
task :tu => :unittests
|
81
|
-
task :test => :unittests
|
81
|
+
task :test => [:rmpid,:unittests]
|
82
|
+
|
83
|
+
task :rmpid do
|
84
|
+
sh "rm -rf tests/server_lock-*"
|
85
|
+
end
|
82
86
|
|
83
87
|
if ENV['RELTEST']
|
84
88
|
announce "Release task testing - not running regression tests on alltests"
|
data/ext/curb.h
CHANGED
@@ -20,11 +20,11 @@
|
|
20
20
|
#include "curb_macros.h"
|
21
21
|
|
22
22
|
// These should be managed from the Rake 'release' task.
|
23
|
-
#define CURB_VERSION "0.
|
24
|
-
#define CURB_VER_NUM
|
23
|
+
#define CURB_VERSION "0.3.0.0"
|
24
|
+
#define CURB_VER_NUM 300
|
25
25
|
#define CURB_VER_MAJ 0
|
26
|
-
#define CURB_VER_MIN
|
27
|
-
#define CURB_VER_MIC
|
26
|
+
#define CURB_VER_MIN 3
|
27
|
+
#define CURB_VER_MIC 0
|
28
28
|
#define CURB_VER_PATCH 0
|
29
29
|
|
30
30
|
|
@@ -32,6 +32,9 @@
|
|
32
32
|
#ifndef RSTRING_LEN
|
33
33
|
#define RSTRING_LEN(x) RSTRING(x)->len
|
34
34
|
#endif
|
35
|
+
#ifndef RSTRING_PTR
|
36
|
+
#define RSTRING_PTR(x) RSTRING(x)->ptr
|
37
|
+
#endif
|
35
38
|
|
36
39
|
#ifdef HAVE_RUBY19_HASH
|
37
40
|
#define RHASH_LEN(hash) RHASH(hash)->ntbl->num_entries
|
data/ext/curb_easy.c
CHANGED
@@ -34,22 +34,41 @@ static size_t default_data_handler(char *stream,
|
|
34
34
|
rb_str_buf_cat(out, stream, size * nmemb);
|
35
35
|
return size * nmemb;
|
36
36
|
}
|
37
|
+
typedef struct _PutStream {
|
38
|
+
char *buffer;
|
39
|
+
size_t offset, len;
|
40
|
+
} PutStream;
|
37
41
|
|
38
42
|
// size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
|
39
|
-
static size_t read_data_handler(
|
43
|
+
static size_t read_data_handler(void *ptr,
|
40
44
|
size_t size,
|
41
45
|
size_t nmemb,
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
void *stream) {
|
47
|
+
|
48
|
+
PutStream *pstream = (PutStream*)stream;
|
49
|
+
size_t sent_bytes = (size * nmemb);
|
50
|
+
size_t remaining = pstream->len - pstream->offset;
|
51
|
+
|
52
|
+
// amount remaining is less then the buffer to send - can send it all
|
53
|
+
if( remaining < sent_bytes ) {
|
54
|
+
memcpy(ptr, pstream->buffer+pstream->offset, remaining);
|
55
|
+
sent_bytes = remaining;
|
56
|
+
pstream->offset += remaining;
|
57
|
+
}
|
58
|
+
else if( remaining > sent_bytes ) { // sent_bytes <= remaining - send what we can fit in the buffer(ptr)
|
59
|
+
memcpy(ptr, pstream->buffer+pstream->offset, sent_bytes);
|
60
|
+
pstream->offset += sent_bytes;
|
61
|
+
}
|
62
|
+
else { // they're equal
|
63
|
+
memcpy(ptr, pstream->buffer+pstream->offset, --sent_bytes);
|
64
|
+
pstream->offset += sent_bytes;
|
65
|
+
}
|
66
|
+
if (sent_bytes == 0) {
|
67
|
+
free(pstream);
|
68
|
+
}
|
51
69
|
|
52
|
-
|
70
|
+
//printf("sent_bytes: %ld of %ld\n", sent_bytes, remaining);
|
71
|
+
return sent_bytes;
|
53
72
|
}
|
54
73
|
|
55
74
|
static size_t proc_data_handler(char *stream,
|
@@ -119,6 +138,10 @@ void curl_easy_mark(ruby_curl_easy *rbce) {
|
|
119
138
|
rb_gc_mark(rbce->postdata_buffer);
|
120
139
|
rb_gc_mark(rbce->bodybuf);
|
121
140
|
rb_gc_mark(rbce->headerbuf);
|
141
|
+
|
142
|
+
if( rbce->self != Qnil ) {
|
143
|
+
rb_gc_mark(rbce->self);
|
144
|
+
}
|
122
145
|
}
|
123
146
|
|
124
147
|
void curl_easy_free(ruby_curl_easy *rbce) {
|
@@ -205,6 +228,8 @@ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
|
|
205
228
|
rbce->bodybuf = Qnil;
|
206
229
|
rbce->headerbuf = Qnil;
|
207
230
|
rbce->curl_headers = NULL;
|
231
|
+
|
232
|
+
rbce->self = Qnil;
|
208
233
|
|
209
234
|
new_curl = Data_Wrap_Struct(cCurlEasy, curl_easy_mark, curl_easy_free, rbce);
|
210
235
|
|
@@ -1367,7 +1392,7 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *hea
|
|
1367
1392
|
}
|
1368
1393
|
|
1369
1394
|
/* Setup HTTP headers if necessary */
|
1370
|
-
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); //
|
1395
|
+
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); // XXX: maybe we shouldn't be clearing this?
|
1371
1396
|
|
1372
1397
|
if (rbce->headers != Qnil) {
|
1373
1398
|
if ((rb_type(rbce->headers) == T_ARRAY) || (rb_type(rbce->headers) == T_HASH)) {
|
@@ -1403,8 +1428,8 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce, VALUE bodybuf, V
|
|
1403
1428
|
if (TYPE(bodybuf) == T_STRING) {
|
1404
1429
|
rbce->body_data = rb_str_to_str(bodybuf);
|
1405
1430
|
}
|
1406
|
-
else if (rb_respond_to(bodybuf, rb_intern("
|
1407
|
-
rbce->body_data = rb_funcall(bodybuf, rb_intern("
|
1431
|
+
else if (rb_respond_to(bodybuf, rb_intern("to_s"))) {
|
1432
|
+
rbce->body_data = rb_funcall(bodybuf, rb_intern("to_s"), 0);
|
1408
1433
|
}
|
1409
1434
|
else {
|
1410
1435
|
rbce->body_data = Qnil;
|
@@ -1417,8 +1442,8 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce, VALUE bodybuf, V
|
|
1417
1442
|
if (TYPE(headerbuf) == T_STRING) {
|
1418
1443
|
rbce->header_data = rb_str_to_str(headerbuf);
|
1419
1444
|
}
|
1420
|
-
else if (rb_respond_to(headerbuf, rb_intern("
|
1421
|
-
rbce->header_data = rb_funcall(headerbuf, rb_intern("
|
1445
|
+
else if (rb_respond_to(headerbuf, rb_intern("to_s"))) {
|
1446
|
+
rbce->header_data = rb_funcall(headerbuf, rb_intern("to_s"), 0);
|
1422
1447
|
}
|
1423
1448
|
else {
|
1424
1449
|
rbce->header_data = Qnil;
|
@@ -1488,26 +1513,34 @@ static VALUE handle_perform(VALUE self, ruby_curl_easy *rbce) {
|
|
1488
1513
|
FD_ZERO(&fdwrite);
|
1489
1514
|
FD_ZERO(&fdexcep);
|
1490
1515
|
|
1491
|
-
|
1492
|
-
timeout.tv_sec = 1;
|
1493
|
-
timeout.tv_usec = 0;
|
1516
|
+
//time_t timer = time(NULL);
|
1494
1517
|
/* get file descriptors from the transfers */
|
1495
1518
|
mcode = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
1496
1519
|
if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
|
1497
1520
|
raise_curl_multi_error_exception(mcode);
|
1498
1521
|
}
|
1499
1522
|
|
1523
|
+
/* set a suitable timeout to play around with - ruby seems to be greedy about this and won't necessarily yield so the timeout is small.. */
|
1524
|
+
timeout.tv_sec = 0.0;
|
1525
|
+
timeout.tv_usec = 100000.0;
|
1500
1526
|
rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
1501
1527
|
if (rc < 0) {
|
1502
1528
|
rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
|
1503
1529
|
}
|
1504
1530
|
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1531
|
+
if( rc >= 0 ) {
|
1532
|
+
switch(rc) {
|
1533
|
+
case 0:
|
1534
|
+
//printf("timeout(%.6f) :", difftime(time(NULL), timer) );
|
1535
|
+
default:
|
1536
|
+
//printf("readable/writable: %d\n", rc);
|
1537
|
+
/* timeout or readable/writable sockets */
|
1538
|
+
while(CURLM_CALL_MULTI_PERFORM == (mcode=curl_multi_perform(multi_handle, &still_running)) );
|
1539
|
+
break;
|
1540
|
+
}
|
1541
|
+
}
|
1542
|
+
else {
|
1543
|
+
// error
|
1511
1544
|
}
|
1512
1545
|
|
1513
1546
|
if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
|
@@ -1549,7 +1582,7 @@ static VALUE handle_perform(VALUE self, ruby_curl_easy *rbce) {
|
|
1549
1582
|
rb_funcall( rbce->success_proc, idCall, 1, self );
|
1550
1583
|
}
|
1551
1584
|
else if (rbce->failure_proc != Qnil &&
|
1552
|
-
(response_code >= 300 && response_code
|
1585
|
+
(response_code >= 300 && response_code <= 999)) {
|
1553
1586
|
rb_funcall( rbce->failure_proc, idCall, 1, self );
|
1554
1587
|
}
|
1555
1588
|
|
@@ -1723,21 +1756,31 @@ static VALUE ruby_curl_easy_perform_head(VALUE self) {
|
|
1723
1756
|
static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
|
1724
1757
|
ruby_curl_easy *rbce;
|
1725
1758
|
CURL *curl;
|
1726
|
-
|
1727
|
-
|
1759
|
+
|
1760
|
+
PutStream *pstream = (PutStream*)malloc(sizeof(PutStream));
|
1761
|
+
memset(pstream, 0, sizeof(PutStream));
|
1728
1762
|
|
1729
1763
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
1730
1764
|
curl = rbce->curl;
|
1731
1765
|
|
1732
|
-
|
1733
|
-
|
1766
|
+
pstream->len = RSTRING_LEN(data);
|
1767
|
+
pstream->buffer = StringValuePtr(data);
|
1768
|
+
|
1734
1769
|
|
1735
1770
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
|
1736
1771
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, (curl_read_callback)read_data_handler);
|
1737
|
-
curl_easy_setopt(curl, CURLOPT_READDATA,
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1772
|
+
curl_easy_setopt(curl, CURLOPT_READDATA, pstream);
|
1773
|
+
//printf("uploading %d bytes\n", pstream->len);
|
1774
|
+
curl_easy_setopt(curl, CURLOPT_INFILESIZE, pstream->len);
|
1775
|
+
|
1776
|
+
VALUE ret = handle_perform(self, rbce);
|
1777
|
+
/* cleanup */
|
1778
|
+
curl_easy_setopt(curl, CURLOPT_UPLOAD, 0);
|
1779
|
+
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
1780
|
+
curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
|
1781
|
+
curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0);
|
1782
|
+
|
1783
|
+
return ret;
|
1741
1784
|
}
|
1742
1785
|
|
1743
1786
|
/* =================== DATA FUNCS =============== */
|
data/ext/curb_errors.c
CHANGED
@@ -309,15 +309,21 @@ void raise_curl_easy_error_exception(CURLcode code) {
|
|
309
309
|
case CURLE_FTP_SSL_FAILED: /* 64 - Requested FTP SSL level failed */
|
310
310
|
exclz = eCurlErrFTPSSLFailed;
|
311
311
|
break;
|
312
|
+
#ifdef HAVE_CURLE_SEND_FAIL_REWIND
|
312
313
|
case CURLE_SEND_FAIL_REWIND: /* 65 - Sending the data requires a rewind that failed */
|
313
314
|
exclz = eCurlErrSendFailedRewind;
|
314
|
-
break;
|
315
|
+
break;
|
316
|
+
#endif
|
317
|
+
#ifdef HAVE_CURLE_SSL_ENGINE_INITFAILED
|
315
318
|
case CURLE_SSL_ENGINE_INITFAILED: /* 66 - failed to initialise ENGINE */
|
316
319
|
exclz = eCurlErrSSLEngineInitFailed;
|
317
320
|
break;
|
321
|
+
#endif
|
322
|
+
#ifdef HAVE_CURLE_LOGIN_DENIED
|
318
323
|
case CURLE_LOGIN_DENIED: /* 67 - user, password or similar was not accepted and we failed to login */
|
319
324
|
exclz = eCurlErrLoginDenied;
|
320
325
|
break;
|
326
|
+
#endif
|
321
327
|
|
322
328
|
// recent additions, may not be present in all supported versions
|
323
329
|
#ifdef HAVE_CURLE_TFTP_NOTFOUND
|
@@ -386,12 +392,16 @@ void raise_curl_multi_error_exception(CURLMcode code) {
|
|
386
392
|
case CURLM_INTERNAL_ERROR: /* 4 */
|
387
393
|
exclz = mCurlErrInternalError;
|
388
394
|
break;
|
395
|
+
#if HAVE_CURLM_BAD_SOCKET
|
389
396
|
case CURLM_BAD_SOCKET: /* 5 */
|
390
397
|
exclz = mCurlErrBadSocket;
|
391
398
|
break;
|
399
|
+
#endif
|
400
|
+
#if HAVE_CURLM_UNKNOWN_OPTION
|
392
401
|
case CURLM_UNKNOWN_OPTION: /* 6 */
|
393
402
|
exclz = mCurlErrUnknownOption;
|
394
403
|
break;
|
404
|
+
#endif
|
395
405
|
default:
|
396
406
|
exclz = eCurlErrError;
|
397
407
|
exmsg = "Unknown error result from libcurl";
|
data/ext/curb_multi.c
CHANGED
@@ -4,7 +4,13 @@
|
|
4
4
|
*
|
5
5
|
* $Id$
|
6
6
|
*/
|
7
|
+
|
8
|
+
#include "curb_config.h"
|
9
|
+
#ifdef HAVE_RUBY19_ST_H
|
10
|
+
#include <ruby/st.h>
|
11
|
+
#else
|
7
12
|
#include <st.h>
|
13
|
+
#endif
|
8
14
|
#include "curb_easy.h"
|
9
15
|
#include "curb_errors.h"
|
10
16
|
#include "curb_postfield.h"
|
@@ -41,12 +47,12 @@ static void curl_multi_flush_easy(VALUE key, VALUE easy, ruby_curl_multi *rbcm)
|
|
41
47
|
|
42
48
|
static void curl_multi_free(ruby_curl_multi *rbcm) {
|
43
49
|
//printf("hash entries: %d\n", RHASH(rbcm->requests)->tbl->num_entries );
|
44
|
-
if (RHASH_LEN(rbcm->requests) > 0) {
|
50
|
+
if (rbcm && RHASH_LEN(rbcm->requests) > 0) {
|
45
51
|
rb_hash_foreach( rbcm->requests, (int (*)())curl_multi_flush_easy, (VALUE)rbcm );
|
46
52
|
|
47
53
|
curl_multi_cleanup(rbcm->handle);
|
48
54
|
//rb_hash_clear(rbcm->requests)
|
49
|
-
rbcm->requests =
|
55
|
+
rbcm->requests = Qnil;
|
50
56
|
}
|
51
57
|
}
|
52
58
|
|
@@ -73,6 +79,24 @@ static VALUE ruby_curl_multi_new(VALUE self) {
|
|
73
79
|
return new_curlm;
|
74
80
|
}
|
75
81
|
|
82
|
+
/*
|
83
|
+
* call-seq:
|
84
|
+
* multi = Curl::Multi.new
|
85
|
+
* multi.max_connects = 800
|
86
|
+
*
|
87
|
+
* Set the max connections in the cache for a multi handle
|
88
|
+
*/
|
89
|
+
static VALUE ruby_curl_multi_max_connects(VALUE self, VALUE count) {
|
90
|
+
#ifdef HAVE_CURLMOPT_MAXCONNECTS
|
91
|
+
ruby_curl_multi *rbcm;
|
92
|
+
|
93
|
+
Data_Get_Struct(self, ruby_curl_multi, rbcm);
|
94
|
+
curl_multi_setopt(rbcm->handle, CURLMOPT_MAXCONNECTS, NUM2INT(count));
|
95
|
+
#endif
|
96
|
+
|
97
|
+
return self;
|
98
|
+
}
|
99
|
+
|
76
100
|
/*
|
77
101
|
* call-seq:
|
78
102
|
* multi = Curl::Multi.new
|
@@ -106,7 +130,7 @@ static VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
|
|
106
130
|
curl_multi_perform(rbcm->handle, &(rbcm->running));
|
107
131
|
}
|
108
132
|
|
109
|
-
rb_hash_aset( rbcm->requests,
|
133
|
+
rb_hash_aset( rbcm->requests, easy, easy );
|
110
134
|
// active should equal INT2FIX(RHASH(rbcm->requests)->tbl->num_entries)
|
111
135
|
|
112
136
|
if (rbcm->active > rbcm->running) {
|
@@ -135,8 +159,10 @@ static VALUE ruby_curl_multi_remove(VALUE self, VALUE easy) {
|
|
135
159
|
|
136
160
|
Data_Get_Struct(self, ruby_curl_multi, rbcm);
|
137
161
|
|
162
|
+
ruby_curl_easy *rbce;
|
163
|
+
Data_Get_Struct(easy, ruby_curl_easy, rbce);
|
164
|
+
|
138
165
|
rb_curl_multi_remove(rbcm,easy);
|
139
|
-
// active should equal INT2FIX(RHASH(rbcm->requests)->tbl->num_entries)
|
140
166
|
|
141
167
|
return self;
|
142
168
|
}
|
@@ -157,7 +183,12 @@ static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy) {
|
|
157
183
|
ruby_curl_easy_cleanup( easy, rbce, rbce->bodybuf, rbce->headerbuf, rbce->curl_headers );
|
158
184
|
rbce->headerbuf = Qnil;
|
159
185
|
rbce->bodybuf = Qnil;
|
160
|
-
|
186
|
+
|
187
|
+
// active should equal INT2FIX(RHASH(rbcm->requests)->tbl->num_entries)
|
188
|
+
VALUE r = rb_hash_delete( rbcm->requests, easy );
|
189
|
+
if( r != easy || r == Qnil ) {
|
190
|
+
fprintf(stderr, "Critical:: Unable to remove easy from requests\n");
|
191
|
+
}
|
161
192
|
}
|
162
193
|
|
163
194
|
static void rb_curl_multi_read_info(VALUE self, CURLM *multi_handle) {
|
@@ -166,7 +197,6 @@ static void rb_curl_multi_read_info(VALUE self, CURLM *multi_handle) {
|
|
166
197
|
CURLcode ecode;
|
167
198
|
CURL *easy_handle;
|
168
199
|
ruby_curl_easy *rbce = NULL;
|
169
|
-
// VALUE finished = rb_ary_new();
|
170
200
|
|
171
201
|
/* check for finished easy handles and remove from the multi handle */
|
172
202
|
while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
|
@@ -182,8 +212,6 @@ static void rb_curl_multi_read_info(VALUE self, CURLM *multi_handle) {
|
|
182
212
|
if (ecode != 0) {
|
183
213
|
raise_curl_easy_error_exception(ecode);
|
184
214
|
}
|
185
|
-
//printf( "finished: 0x%X\n", (long)rbce->self );
|
186
|
-
//rb_ary_push(finished, rbce->self);
|
187
215
|
ruby_curl_multi_remove( self, rbce->self );
|
188
216
|
|
189
217
|
if (rbce->complete_proc != Qnil) {
|
@@ -204,21 +232,15 @@ static void rb_curl_multi_read_info(VALUE self, CURLM *multi_handle) {
|
|
204
232
|
rb_funcall( rbce->success_proc, idCall, 1, rbce->self );
|
205
233
|
}
|
206
234
|
else if (rbce->failure_proc != Qnil &&
|
207
|
-
(response_code >= 300 && response_code
|
235
|
+
(response_code >= 300 && response_code <= 999)) {
|
208
236
|
rb_funcall( rbce->failure_proc, idCall, 1, rbce->self );
|
209
237
|
}
|
238
|
+
rbce->self = Qnil;
|
210
239
|
}
|
211
240
|
else {
|
212
241
|
//printf( "missing easy handle\n" );
|
213
242
|
}
|
214
243
|
}
|
215
|
-
|
216
|
-
/*
|
217
|
-
while (RARRAY(finished)->len > 0) {
|
218
|
-
//printf( "finished handle\n" );
|
219
|
-
ruby_curl_multi_remove( self, rb_ary_pop(finished) );
|
220
|
-
}
|
221
|
-
*/
|
222
244
|
}
|
223
245
|
|
224
246
|
/* called within ruby_curl_multi_perform */
|
@@ -321,6 +343,7 @@ void init_curb_multi() {
|
|
321
343
|
rb_define_singleton_method(cCurlMulti, "new", ruby_curl_multi_new, -1);
|
322
344
|
|
323
345
|
/* Instnace methods */
|
346
|
+
rb_define_method(cCurlMulti, "max_connects=", ruby_curl_multi_max_connects, 1);
|
324
347
|
rb_define_method(cCurlMulti, "add", ruby_curl_multi_add, 1);
|
325
348
|
rb_define_method(cCurlMulti, "remove", ruby_curl_multi_remove, 1);
|
326
349
|
rb_define_method(cCurlMulti, "perform", ruby_curl_multi_perform, 0);
|
data/ext/curb_postfield.c
CHANGED
@@ -429,9 +429,10 @@ static VALUE ruby_curl_postfield_to_str(VALUE self) {
|
|
429
429
|
|
430
430
|
if ((rbcpf->local_file == Qnil) && (rbcpf->remote_file == Qnil)) {
|
431
431
|
if (rbcpf->name != Qnil) {
|
432
|
-
|
432
|
+
|
433
|
+
char *tmpchrs = curl_escape(RSTRING_PTR(rbcpf->name), RSTRING_LEN(rbcpf->name));
|
433
434
|
|
434
|
-
if (
|
435
|
+
if (!tmpchrs) {
|
435
436
|
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name `%s'", tmpchrs);
|
436
437
|
} else {
|
437
438
|
VALUE tmpcontent = Qnil;
|
@@ -445,8 +446,17 @@ static VALUE ruby_curl_postfield_to_str(VALUE self) {
|
|
445
446
|
} else {
|
446
447
|
tmpcontent = rb_str_new2("");
|
447
448
|
}
|
448
|
-
|
449
|
-
|
449
|
+
if (TYPE(tmpcontent) != T_STRING) {
|
450
|
+
if (rb_respond_to(tmpcontent, rb_intern("to_s"))) {
|
451
|
+
tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
|
452
|
+
}
|
453
|
+
else {
|
454
|
+
rb_raise(rb_eRuntimeError, "postfield(%s) is not a string and does not respond_to to_s", RSTRING_PTR(escd_name) );
|
455
|
+
}
|
456
|
+
}
|
457
|
+
//fprintf(stderr, "encoding content: %ld - %s\n", RSTRING_LEN(tmpcontent), RSTRING_PTR(tmpcontent) );
|
458
|
+
tmpchrs = curl_escape(RSTRING_PTR(tmpcontent), RSTRING_LEN(tmpcontent));
|
459
|
+
if (!tmpchrs) {
|
450
460
|
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
|
451
461
|
} else {
|
452
462
|
VALUE escd_content = rb_str_new2(tmpchrs);
|
data/ext/extconf.rb
CHANGED
@@ -70,6 +70,17 @@ have_constant "curle_tftp_illegal"
|
|
70
70
|
have_constant "curle_tftp_unknownid"
|
71
71
|
have_constant "curle_tftp_exists"
|
72
72
|
have_constant "curle_tftp_nosuchuser"
|
73
|
+
# older versions of libcurl 7.12
|
74
|
+
have_constant "curle_send_fail_rewind"
|
75
|
+
have_constant "curle_ssl_engine_initfailed"
|
76
|
+
have_constant "curle_login_denied"
|
77
|
+
|
78
|
+
# older than 7.16.3
|
79
|
+
have_constant "curlmopt_maxconnects"
|
80
|
+
|
81
|
+
# centos 4.5 build of libcurl
|
82
|
+
have_constant "curlm_bad_socket"
|
83
|
+
have_constant "curlm_unknown_option"
|
73
84
|
|
74
85
|
if try_compile('int main() { return 0; }','-Wall')
|
75
86
|
$CFLAGS << ' -Wall'
|
@@ -77,7 +88,7 @@ end
|
|
77
88
|
|
78
89
|
# do some checking to detect ruby 1.8 hash.c vs ruby 1.9 hash.c
|
79
90
|
def test_for(name, const, src)
|
80
|
-
checking_for
|
91
|
+
checking_for name do
|
81
92
|
if try_compile(src,"#{$CFLAGS} #{$LIBS}")
|
82
93
|
define const
|
83
94
|
true
|
@@ -86,7 +97,7 @@ def test_for(name, const, src)
|
|
86
97
|
end
|
87
98
|
end
|
88
99
|
end
|
89
|
-
test_for("Ruby 1.9", "RUBY19_HASH", %{
|
100
|
+
test_for("Ruby 1.9 Hash", "RUBY19_HASH", %{
|
90
101
|
#include <ruby.h>
|
91
102
|
int main() {
|
92
103
|
VALUE hash = rb_hash_new();
|
@@ -96,6 +107,22 @@ test_for("Ruby 1.9", "RUBY19_HASH", %{
|
|
96
107
|
return 1;
|
97
108
|
}
|
98
109
|
})
|
110
|
+
test_for("Ruby 1.9 st.h", "RUBY19_ST_H", %{
|
111
|
+
#include <ruby.h>
|
112
|
+
#include <ruby/st.h>
|
113
|
+
int main() {
|
114
|
+
return 0;
|
115
|
+
}
|
116
|
+
})
|
117
|
+
|
118
|
+
test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
|
119
|
+
#include <curl/curl.h>
|
120
|
+
int main() {
|
121
|
+
CURL *easy = curl_easy_init();
|
122
|
+
curl_easy_escape(easy,"hello",5);
|
123
|
+
return 0;
|
124
|
+
}
|
125
|
+
})
|
99
126
|
|
100
127
|
create_header('curb_config.h')
|
101
128
|
create_makefile('curb_core')
|
data/tests/helper.rb
CHANGED
@@ -17,6 +17,12 @@ $TEST_URL = "file://#{URI.escape(File.expand_path(__FILE__).tr('\\','/').tr(':',
|
|
17
17
|
require 'thread'
|
18
18
|
require 'webrick'
|
19
19
|
|
20
|
+
# set this to true to avoid testing with multiple threads
|
21
|
+
# or to test with multiple threads set it to false
|
22
|
+
# this is important since, some code paths will change depending
|
23
|
+
# on the presence of multiple threads
|
24
|
+
TEST_SINGLE_THREADED=false
|
25
|
+
|
20
26
|
# keep webrick quiet
|
21
27
|
class ::WEBrick::HTTPServer
|
22
28
|
def access_log(config, req, res)
|
@@ -87,28 +93,56 @@ module TestServerMethods
|
|
87
93
|
def server_setup(port=9129,servlet=TestServlet)
|
88
94
|
@__port = port
|
89
95
|
if @server.nil? and !File.exist?(locked_file)
|
90
|
-
File.open(locked_file,'w') {|f| f << 'locked' }
|
91
|
-
|
92
|
-
# start up a webrick server for testing delete
|
93
|
-
@server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => File.expand_path(File.dirname(__FILE__))
|
94
|
-
|
95
|
-
@server.mount(servlet.path, servlet)
|
96
|
-
queue = Queue.new # synchronize the thread startup to the main thread
|
97
96
|
|
98
|
-
|
97
|
+
File.open(locked_file,'w') {|f| f << 'locked' }
|
98
|
+
if TEST_SINGLE_THREADED
|
99
|
+
rd, wr = IO.pipe
|
100
|
+
@__pid = fork do
|
101
|
+
rd.close
|
102
|
+
rd = nil
|
103
|
+
|
104
|
+
# start up a webrick server for testing delete
|
105
|
+
server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => File.expand_path(File.dirname(__FILE__))
|
106
|
+
|
107
|
+
server.mount(servlet.path, servlet)
|
108
|
+
trap("INT") { server.shutdown }
|
109
|
+
GC.start
|
110
|
+
wr.flush
|
111
|
+
wr.close
|
112
|
+
server.start
|
113
|
+
end
|
114
|
+
wr.close
|
115
|
+
rd.read
|
116
|
+
rd.close
|
117
|
+
else
|
118
|
+
# start up a webrick server for testing delete
|
119
|
+
@server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => File.expand_path(File.dirname(__FILE__))
|
120
|
+
|
121
|
+
@server.mount(servlet.path, servlet)
|
122
|
+
queue = Queue.new # synchronize the thread startup to the main thread
|
123
|
+
|
124
|
+
@test_thread = Thread.new { queue << 1; @server.start }
|
125
|
+
|
126
|
+
# wait for the queue
|
127
|
+
value = queue.pop
|
128
|
+
if !value
|
129
|
+
STDERR.puts "Failed to startup test server!"
|
130
|
+
exit(1)
|
131
|
+
end
|
99
132
|
|
100
|
-
# wait for the queue
|
101
|
-
value = queue.pop
|
102
|
-
if !value
|
103
|
-
STDERR.puts "Failed to startup test server!"
|
104
|
-
exit(1)
|
105
133
|
end
|
106
134
|
|
107
135
|
exit_code = lambda do
|
108
136
|
begin
|
109
|
-
|
110
|
-
|
111
|
-
|
137
|
+
if File.exist?(locked_file)
|
138
|
+
File.unlink locked_file
|
139
|
+
if TEST_SINGLE_THREADED
|
140
|
+
Process.kill 'INT', @__pid
|
141
|
+
else
|
142
|
+
@server.shutdown unless @server.nil?
|
143
|
+
end
|
144
|
+
end
|
145
|
+
#@server.shutdown unless @server.nil?
|
112
146
|
rescue Object => e
|
113
147
|
puts "Error #{__FILE__}:#{__LINE__}\n#{e.message}"
|
114
148
|
end
|
data/tests/tc_curl_multi.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: taf2-curb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ross Bamford
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-06-08 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -41,7 +41,6 @@ files:
|
|
41
41
|
- ext/curb_macros.h
|
42
42
|
- ext/curb.h
|
43
43
|
- ext/curb_postfield.h
|
44
|
-
- ext/curb_config.h
|
45
44
|
- ext/curb_multi.h
|
46
45
|
has_rdoc: true
|
47
46
|
homepage: http://curb.rubyforge.org/
|