Module: Curl

Defined in:
lib/rhack.rb,
lib/rhack/curl/itt.rb,
lib/rhack/curl/easy.rb,
lib/rhack/curl/multi.rb,
lib/rhack/curl/global.rb,
lib/rhack/curl/response.rb,
lib/rhack/curl/post_field.rb,
ext/curb/curb.c,
ext/curb-original/curb.c

Defined Under Namespace

Modules: Err Classes: Easy, Multi, PostField, Response, Upload

Constant Summary collapse

L =
RHACK::L
CURB_VERSION =
rb_str_new2(CURB_VERSION)
VERSION =
curlver
CURL_VERSION =
curlver
VERNUM =
curlvernum
CURL_VERNUM =
curlvernum
LONG_VERSION =
curllongver
CURL_LONG_VERSION =
curllongver
CURLINFO_TEXT =

Passed to on_debug handler to indicate that the data is informational text.

INT2FIX(CURLINFO_TEXT)
CURLINFO_HEADER_IN =

Passed to on_debug handler to indicate that the data is header (or header-like) data received from the peer.

INT2FIX(CURLINFO_HEADER_IN)
CURLINFO_HEADER_OUT =

Passed to on_debug handler to indicate that the data is header (or header-like) data sent to the peer.

INT2FIX(CURLINFO_HEADER_OUT)
CURLINFO_DATA_IN =

Passed to on_debug handler to indicate that the data is protocol data received from the peer.

INT2FIX(CURLINFO_DATA_IN)
CURLINFO_DATA_OUT =

Passed to on_debug handler to indicate that the data is protocol data sent to the peer.

INT2FIX(CURLINFO_DATA_OUT)
CURL_MULTICWD =
INT2FIX(CURLFTPMETHOD_MULTICWD)
CURL_NOCWD =
INT2FIX(CURLFTPMETHOD_NOCWD)
CURL_SINGLECWD =
INT2FIX(CURLFTPMETHOD_SINGLECWD)
CURLPROXY_HTTP =
INT2FIX(-1)
CURL_SSLVERSION_DEFAULT =
INT2FIX(-1)
CURL_SSLVERSION_TLSv1 =
INT2FIX(-1)
CURL_SSLVERSION_SSLv2 =
INT2FIX(-1)
CURL_SSLVERSION_SSLv3 =
INT2FIX(-1)
CURL_USESSL_CONTROL =
INT2FIX(-1)
CURL_USESSL_NONE =
INT2FIX(-1)
CURL_USESSL_TRY =
INT2FIX(-1)
CURL_USESSL_ALL =
INT2FIX(-1)
CURLPROXY_SOCKS4 =
INT2FIX(-2)
CURLPROXY_SOCKS5 =
INT2FIX(-2)
CURLAUTH_BASIC =
INT2FIX(0)
CURLAUTH_DIGEST =
INT2FIX(0)
CURLAUTH_GSSNEGOTIATE =
INT2FIX(0)
CURLAUTH_NTLM =
INT2FIX(0)
CURLAUTH_ANYSAFE =
INT2FIX(0)
CURLAUTH_ANY =
INT2FIX(0)
HTTP_1_1 =
LONG2NUM(CURL_HTTP_VERSION_1_1)
HTTP_1_0 =
LONG2NUM(CURL_HTTP_VERSION_1_0)
HTTP_NONE =
LONG2NUM(CURL_HTTP_VERSION_NONE)
@@carier =
Curl::Multi.new

Class Method Summary collapse

Class Method Details

.asyncdns?Boolean

Returns true if the installed libcurl was built with support for asynchronous name lookups, which allows more exact timeouts (even on Windows) and less blocking when using the multi interface. For libcurl versions < 7.10.7, always returns false.

Returns:

  • (Boolean)


128
129
130
131
132
133
134
135
# File 'ext/curb/curb.c', line 128

static VALUE ruby_curl_asyncdns_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_ASYNCHDNS
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_ASYNCHDNS) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.conv?Boolean

Returns true if the installed libcurl was built with support for character conversions. For libcurl versions < 7.15.4, always returns false.

Returns:

  • (Boolean)


213
214
215
216
217
218
219
220
# File 'ext/curb/curb.c', line 213

static VALUE ruby_curl_conv_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_CONV
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_CONV) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.debug?Boolean

Returns true if the installed libcurl was built with extra debug capabilities built-in. For libcurl versions < 7.10.6, always returns false.

Returns:

  • (Boolean)


110
111
112
113
114
115
116
117
# File 'ext/curb/curb.c', line 110

static VALUE ruby_curl_debug_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_DEBUG
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_DEBUG) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.execute(unless_allready = false) ⇒ Object Also known as: run



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/rhack/curl/global.rb', line 5

def execute(unless_allready=false)
  #if unless_allready and status
  #  return L.log "Carier allready executing"
  #end
  if @@carier_thread and s = @@carier_thread.status
    L.log "Carier Thread allready started and has status #{s}"
  else
    if s = status(false) then L.warn s end
    L.log(@@carier_thread ? "Resetting Carier thread" : "Setting Carier thread up")
    @@carier_thread = thread {
      error = nil
      begin
        yield if block_given?
      rescue => error
        nil
      end
      loop {
        begin
          # with true argument (idle) it would break only if there is no requests to perform
          # and still carier thread is joined
          break unless @@carier.perform true
          L.log "All requests have been performed; idling..."
        rescue => error
          L.log "Catched #{error.class.name} in Carier Thread"
          break
          # but ruby mystically crashes if next sequence occur:
          # Multi performs and can't see any requests so entering idle mode
          # we add some requests and multi load them
          # one of requests' callbacks raises error in *main* thread
          # so we can't allow any raises here, instead, keep them in 'wait' section
        end
      } unless error
      L.log "Nothing to perform; recalling..."
      error
    }
    # until main thread has sleep a bit, $CarierThread will have status "run", 
    # no matter whether it's idling or performing requests
    sleep 0.001
  end
end

.gssnegotiate?Boolean

Returns true if the installed libcurl supports HTTP GSS-Negotiate. For libcurl versions < 7.10.6, always returns false.

Returns:

  • (Boolean)


93
94
95
96
97
98
99
100
# File 'ext/curb/curb.c', line 93

static VALUE ruby_curl_gssnegotiate_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_GSSNEGOTIATE
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_GSSNEGOTIATE) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.idn?Boolean

Returns true if the installed libcurl was built with support for IDNA, domain names with international letters. For libcurl versions < 7.12.0, always returns false.

Returns:

  • (Boolean)


178
179
180
181
182
183
184
185
# File 'ext/curb/curb.c', line 178

static VALUE ruby_curl_idn_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_IDN
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_IDN) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.ipv6?Boolean

Returns true if the installed libcurl supports IPv6.

Returns:

  • (Boolean)


21
22
23
24
# File 'ext/curb/curb.c', line 21

static VALUE ruby_curl_ipv6_q(VALUE mod) {
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_IPV6) ? Qtrue : Qfalse);
}

.ITTObject

Run proc in Multi’s thread processing callbacks at this moment



4
5
6
7
8
# File 'lib/rhack/curl/itt.rb', line 4

def ITT
  res = nil
  RHACK::Scout('file://').loadGet(__FILE__) {|c| res = yield}
  loop {if res then break res else sleep 0.01 end}
end

.kerberos4?Boolean

Returns true if the installed libcurl supports Kerberos4 authentication with FTP connections.

Returns:

  • (Boolean)


33
34
35
36
# File 'ext/curb/curb.c', line 33

static VALUE ruby_curl_kerberos4_q(VALUE mod) {
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_KERBEROS4) ? Qtrue : Qfalse);
}

.largefile?Boolean

Returns true if the installed libcurl was built with support for large files. For libcurl versions < 7.11.1, always returns false.

Returns:

  • (Boolean)


161
162
163
164
165
166
167
168
# File 'ext/curb/curb.c', line 161

static VALUE ruby_curl_largefile_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_LARGEFILE
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_LARGEFILE) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.libz?Boolean

Returns true if the installed libcurl supports HTTP deflate using libz. For libcurl versions < 7.10, always returns false.

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
# File 'ext/curb/curb.c', line 61

static VALUE ruby_curl_libz_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_LIBZ
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_LIBZ) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.ntlm?Boolean

Returns true if the installed libcurl supports HTTP NTLM. For libcurl versions < 7.10.6, always returns false.

Returns:

  • (Boolean)


77
78
79
80
81
82
83
84
# File 'ext/curb/curb.c', line 77

static VALUE ruby_curl_ntlm_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_NTLM
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_NTLM) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.recallObject Also known as: stop



104
105
106
107
108
109
110
111
112
113
# File 'lib/rhack/curl/global.rb', line 104

def recall
  L.debug caller
  if @@carier_thread
    L.log "Recalling Carier thread"
    @@carier_thread.kill
    sleep 1
  else
    L.log "No thread to recall"
  end
end

.recall!Object Also known as: stop!



116
117
118
119
120
121
122
123
124
125
# File 'lib/rhack/curl/global.rb', line 116

def recall!
  if @@carier_thread
    L.warn "Recalling thread and resetting Carier!!!"
    @@carier_thread.kill
    @@carier_thread = nil
    reset_carier!
  else
    L.log "No thread to recall!"
  end
end

.resetObject Also known as: reload



135
136
137
138
# File 'lib/rhack/curl/global.rb', line 135

def reset
  recall
  execute
end

.reset!Object Also known as: reload!



141
142
143
144
# File 'lib/rhack/curl/global.rb', line 141

def reset!
  recall!
  execute
end

.reset_carier!Object



128
129
130
131
132
133
# File 'lib/rhack/curl/global.rb', line 128

def reset_carier!
  @@carier.clear!
  @@carier = Multi.new
  carier.pipeline = true
  #GC.start
end

.spnego?Boolean

Returns true if the installed libcurl was built with support for SPNEGO authentication (Simple and Protected GSS-API Negotiation Mechanism, defined in RFC 2478). For libcurl versions < 7.10.8, always returns false.

Returns:

  • (Boolean)


145
146
147
148
149
150
151
152
# File 'ext/curb/curb.c', line 145

static VALUE ruby_curl_spnego_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_SPNEGO
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_SPNEGO) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.ssl?Boolean

Returns true if the installed libcurl supports SSL connections. For libcurl versions < 7.10, always returns false.

Returns:

  • (Boolean)


45
46
47
48
49
50
51
52
# File 'ext/curb/curb.c', line 45

static VALUE ruby_curl_ssl_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_SSL
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_SSL) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.sspi?Boolean

Returns true if the installed libcurl was built with support for SSPI. This is only available on Windows and makes libcurl use Windows-provided functions for NTLM authentication. It also allows libcurl to use the current user and the current user’s password without the app having to pass them on. For libcurl versions < 7.13.2, always returns false.

Returns:

  • (Boolean)


197
198
199
200
201
202
203
204
# File 'ext/curb/curb.c', line 197

static VALUE ruby_curl_sspi_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_SSPI
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_SSPI) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}

.status(raise_error = true) ⇒ Object Also known as: st



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/rhack/curl/global.rb', line 147

def status(raise_error=true)
  if @@carier_thread and (s = @@carier_thread.status)
    L.log "Carier Thread responding with status #{s}"
    s
  elsif @@carier_thread
    begin
      # status = nil
      error = @@carier_thread.value
    rescue => error
      L.warn "Carier Thread has raised an exception"
      if raise_error
        recall!
        raise error
      else
        L.log "Carier Thread has catched #{error.inspect}"
        error
      end
    else
      # status = false
      L.log "Carier Thread has exited without an exception"
    end
  else
    L.log "There is no Carier Thread atm"
  end
end

.waitObject



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rhack/curl/global.rb', line 47

def wait
  if @@carier_thread and @@carier_thread.status
    unless within = Thread.current == @@carier_thread
      # We can't set `perform' timeout lesser than 1 second in the curl binding
      # because in that case thread status would always be "run"
      # so here we wait for exactly 1 sec
      sleep 1 
    end
    # Also, if thread do Kernel.sleep, it would skip Curl.wait here
    if !@@carier.sheduled and (@@carier_thread.status == 'sleep' or within && @@carier.reqs.empty?)
      L.log "No shedule to wait"
    else
      this_thread = within ? 'it\'s thread' : Thread.main == Thread.current ? 'main thread' : 'thread '+Thread.current.object_id
      L.log "Waiting for Carier to complete in #{this_thread}"
      begin
        L.log { "Trying to change Curl.joined #@@joined -> true from #{this_thread}" }
        if within 
          L.log "calling this from one of callbacks to wait for the rest to complete"
          begin
            @@carier.perform
          rescue RuntimeError => e
            L.warn [e, e.message]
            L.info "@@carier @@carier.sheduled @@carier_thread @@carier_thread.status", binding
            L.warn "Failed to run Multi#perform: nothing to perform"
          end
        else 
          @@joined = true
          @@carier_thread.join
        end
      rescue (defined?(IRB) ? IRB::Abort : NilClass)
        recall!
        L.info "Carier Thread recalled by a keyboard"
      ensure
        L.log "trying to change Curl.joined #@@joined -> false from #{this_thread}"
        if !within
          @@joined = false
          # using Curl#execute from different threads may cause problems here when you don't control input,
          # for example, in a daemonized ruby process
          # just do not get $CarierThread joined from non-main thread
          if @@carier_thread and e = @@carier_thread.value
            # this will raise thread-safely in main thread
            # in case of unrescued error in CarierThread
            L.log(([e.message]+RMTools.format_trace(e.backtrace))*"\n")
            recall!
            raise e 
          end
          execute
        end
      end
    end
  else
    L < "No thread to wait. I guess I should create one"
    execute
    wait
  end
end