taf2-curb 0.2.8.0 → 0.3.0.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.
- 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/
|