Esempio n. 1
0
/*
 * call-seq:
 * multi = Curl::Multi.new
 * easy1 = Curl::Easy.new('url')
 * easy2 = Curl::Easy.new('url')
 *
 * multi.add(easy1)
 * multi.add(easy2)
 *
 * multi.perform do
 *  # while idle other code my execute here
 * end
 *
 * Run multi handles, looping selecting when data can be transfered
 */
static VALUE ruby_curl_multi_perform(VALUE self) {
  CURLMcode mcode;
  ruby_curl_multi *rbcm;
  int maxfd, rc;
  fd_set fdread, fdwrite, fdexcep;

  long timeout;
  struct timeval tv = {0, 0};

  Data_Get_Struct(self, ruby_curl_multi, rbcm);
  //rb_gc_mark(self);

  rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );

  while(rbcm->running) { 
    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);

    /* load the fd sets from the multi handle */
    mcode = curl_multi_fdset(rbcm->handle, &fdread, &fdwrite, &fdexcep, &maxfd);
    if (mcode != CURLM_OK) {
      raise_curl_multi_error_exception(mcode);
    }

    /* get the curl suggested time out */
    mcode = curl_multi_timeout(rbcm->handle, &timeout);
    if (mcode != CURLM_OK) {
      raise_curl_multi_error_exception(mcode);
    }

    if (timeout == 0) { /* no delay */
      rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
      continue;
    }
    else if (timeout == -1) {
      timeout = 1; /* You must not wait too long 
                     (more than a few seconds perhaps) before 
                     you call curl_multi_perform() again */
    }

    if (rb_block_given_p()) {
      rb_yield(self);
    }
 
    tv.tv_sec = timeout / 1000;
    tv.tv_usec = (timeout * 1000) % 1000000;

    rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
    if (rc < 0) {
      rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
    }

    rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );

  }

  return Qnil;
}
Esempio n. 2
0
/*
 * call-seq:
 * multi = Curl::Multi.new
 * easy = Curl::Easy.new('url')
 *
 * multi.add(easy)
 *
 * Add an easy handle to the multi stack
 */
VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
  CURLMcode mcode;
  ruby_curl_easy *rbce;
  ruby_curl_multi *rbcm;

  Data_Get_Struct(self, ruby_curl_multi, rbcm);
  Data_Get_Struct(easy, ruby_curl_easy, rbce);

  /* setup the easy handle */
  ruby_curl_easy_setup( rbce );

  mcode = curl_multi_add_handle(rbcm->handle, rbce->curl);
  if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
    raise_curl_multi_error_exception(mcode);
  }

  rbcm->active++;

  /* Increase the running count, so that the perform loop keeps running.
   * If this number is not correct, the next call to curl_multi_perform will correct it. */
  rbcm->running++;

  rb_hash_aset( rbcm->requests, easy, easy );

  rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );

  return self;
}
Esempio n. 3
0
/*
 * call-seq:
 * multi = Curl::Multi.new
 * easy1 = Curl::Easy.new('url')
 * easy2 = Curl::Easy.new('url')
 *
 * multi.add(easy1)
 * multi.add(easy2)
 *
 * multi.perform do
 *  # while idle other code my execute here
 * end
 *
 * Run multi handles, looping selecting when data can be transfered
 */
VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
  CURLMcode mcode;
  ruby_curl_multi *rbcm;
  int maxfd, rc;
  fd_set fdread, fdwrite, fdexcep;
#ifdef _WIN32
  fd_set crt_fdread, crt_fdwrite, crt_fdexcep;
#endif

  long timeout_milliseconds;
  struct timeval tv = {0, 0};
  VALUE block = Qnil;

  rb_scan_args(argc, argv, "0&", &block);

  Data_Get_Struct(self, ruby_curl_multi, rbcm);

  timeout_milliseconds = cCurlMutiDefaulttimeout;

  rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
 
  do {
    while (rbcm->running) {

#ifdef HAVE_CURL_MULTI_TIMEOUT
      /* get the curl suggested time out */
      mcode = curl_multi_timeout(rbcm->handle, &timeout_milliseconds);
      if (mcode != CURLM_OK) {
        raise_curl_multi_error_exception(mcode);
      }
#else
      /* libcurl doesn't have a timeout method defined, initialize to -1 we'll pick up the default later */
      timeout_milliseconds = -1;
#endif

      if (timeout_milliseconds == 0) { /* no delay */
        rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
        continue;
      }
      else if (timeout_milliseconds < 0) {
        timeout_milliseconds = cCurlMutiDefaulttimeout; /* libcurl doesn't know how long to wait, use a default timeout */
      }

      if (timeout_milliseconds > cCurlMutiDefaulttimeout) {
        timeout_milliseconds = cCurlMutiDefaulttimeout; /* buggy versions libcurl sometimes reports huge timeouts... let's cap it */
      }

      tv.tv_sec  = 0; /* never wait longer than 1 second */
      tv.tv_usec = (int)(timeout_milliseconds * 1000); /* XXX: int is the right type for OSX, what about linux? */

      if (timeout_milliseconds == 0) { /* no delay */
        rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
        continue;
      }

      if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self);  }

      FD_ZERO(&fdread);
      FD_ZERO(&fdwrite);
      FD_ZERO(&fdexcep);
      /* load the fd sets from the multi handle */
      mcode = curl_multi_fdset(rbcm->handle, &fdread, &fdwrite, &fdexcep, &maxfd);
      if (mcode != CURLM_OK) {
        raise_curl_multi_error_exception(mcode);
      }

#ifdef _WIN32
      create_crt_fd(&fdread, &crt_fdread);
      create_crt_fd(&fdwrite, &crt_fdwrite);
      create_crt_fd(&fdexcep, &crt_fdexcep);
#endif

      rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);

#ifdef _WIN32
      cleanup_crt_fd(&fdread, &crt_fdread);
      cleanup_crt_fd(&fdwrite, &crt_fdwrite);
      cleanup_crt_fd(&fdexcep, &crt_fdexcep);
#endif

      switch(rc) {
      case -1:
        rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
        break;
      case 0:
        rb_curl_multi_read_info( self, rbcm->handle );
        if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self);  }
      default: 
        rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
        break;
      }
    }
    rb_curl_multi_read_info( self, rbcm->handle );
    if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self);  }
  } while( rbcm->running );
    
  return Qtrue;
}
Esempio n. 4
0
/*
 * call-seq:
 * multi = Curl::Multi.new
 * easy1 = Curl::Easy.new('url')
 * easy2 = Curl::Easy.new('url')
 *
 * multi.add(easy1)
 * multi.add(easy2)
 *
 * multi.perform do
 *  # while idle other code my execute here
 * end
 *
 * Run multi handles, looping selecting when data can be transfered
 */
VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
  CURLMcode mcode;
  ruby_curl_multi *rbcm;
  int maxfd, rc;
  fd_set fdread, fdwrite, fdexcep;

  long timeout_milliseconds;
  struct timeval tv = {0, 0};
  VALUE block = Qnil;

  rb_scan_args(argc, argv, "0&", &block);

  Data_Get_Struct(self, ruby_curl_multi, rbcm);

  rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );

  while(rbcm->running) {
    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);

    /* load the fd sets from the multi handle */
    mcode = curl_multi_fdset(rbcm->handle, &fdread, &fdwrite, &fdexcep, &maxfd);
    if (mcode != CURLM_OK) {
      raise_curl_multi_error_exception(mcode);
    }

#ifdef HAVE_CURL_MULTI_TIMEOUT
    /* get the curl suggested time out */
    mcode = curl_multi_timeout(rbcm->handle, &timeout_milliseconds);
    if (mcode != CURLM_OK) {
      raise_curl_multi_error_exception(mcode);
    }
#else
    /* libcurl doesn't have a timeout method defined... make a wild guess */
    timeout_milliseconds = -1;
#endif
    //printf("libcurl says wait: %ld ms or %ld s\n", timeout_milliseconds, timeout_milliseconds/1000);

    if (timeout_milliseconds == 0) { /* no delay */
      rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
      continue;
    }
    else if(timeout_milliseconds < 0) {
      timeout_milliseconds = 500; /* wait half a second, libcurl doesn't know how long to wait */
    }
#ifdef __APPLE_CC__
    if(timeout_milliseconds > 1000) {
      timeout_milliseconds = 1000; /* apple libcurl sometimes reports huge timeouts... let's cap it */
    }
#endif

    tv.tv_sec = timeout_milliseconds / 1000; // convert milliseconds to seconds
    tv.tv_usec = (timeout_milliseconds % 1000) * 1000; // get the remainder of milliseconds and convert to micro seconds

    rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
    switch(rc) {
    case -1:
      rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
      break;
    case 0:
      if (block != Qnil) {
        rb_funcall(block, rb_intern("call"), 1, self); 
      }
//      if (rb_block_given_p()) {
//        rb_yield(self);
//      }
    default: 
      rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
      break;
    }

  }

  return Qtrue;
}