Example #1
0
size_t
Net::Request::Read(void *_buffer, size_t buffer_size, unsigned long timeout)
{
  assert(handle != NULL);

  const int timeout_ms = timeout == INFINITE ? -1 : timeout;

  Buffer::Range range;
  CURLMcode mcode = CURLM_CALL_MULTI_PERFORM;
  while (true) {
    range = buffer.Read();
    if (!range.IsEmpty())
      break;

    CURLcode code = session.InfoRead(handle);
    if (code != CURLE_AGAIN)
      return 0;

    if (mcode != CURLM_CALL_MULTI_PERFORM &&
        !session.Select(timeout_ms))
      return 0;

    CURLMcode mcode = session.Perform();
    if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM)
      return 0;
  }

  --buffer_size;
  if (buffer_size > range.length)
    buffer_size = range.length;

  uint8_t *p = (uint8_t *)_buffer;
  std::copy(range.data, range.data + buffer_size, p);
  p[buffer_size] = 0;

  buffer.Consume(buffer_size);
  curl_easy_pause(handle, CURLPAUSE_CONT);

  return buffer_size;
}
int
client_send (struct Session *s, struct HTTP_Message *msg)
{
  GNUNET_assert (s != NULL);
  GNUNET_CONTAINER_DLL_insert_tail (s->msg_head, s->msg_tail, msg);

  if (GNUNET_YES != exist_session(p, s))
  {
    GNUNET_break (0);
    return GNUNET_SYSERR;
  }
  if (s->client_put_paused == GNUNET_YES)
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
                     "Client: %p was suspended, unpausing\n", s->client_put);
    s->client_put_paused = GNUNET_NO;
    curl_easy_pause (s->client_put, CURLPAUSE_CONT);
  }
  client_schedule (s->plugin, GNUNET_YES);

  return GNUNET_OK;
}
 void requestBytes( size_t offset, size_t len )
 {
     switch (state_)
     {
     case 0: // requestInfo has not be called
         state_ = 3;
         perform();
         break;
     case 1: // requestInfo has been called but we are not blocked yet
         state_ = 3;
         break;
     case 2: // we are blocked 
         state_ = 3;
 #ifdef USE_CURL_PAUSE
         curl_easy_pause(cur_, CURLPAUSE_SEND_CONT);
 #endif
         break;
 #ifndef USE_CURL_PAUSE
     case 4: 
         state_ = 3;
         break;
 #endif
     }
 }
Example #4
0
extern "C" int32_t HttpNative_EasyUnpause(CURL* handle)
{
    return curl_easy_pause(handle, CURLPAUSE_CONT);
}
    // This is the writer call back function used by cur_  
    size_t writer_callback( void *ptr, size_t size, size_t nmemb)
    {
        dputils::StreamGuard guard(this);

        if (!client_)
            return 0;

        // What we will return  
        size_t result = 0;  
        size_t bytes = size * nmemb;
        switch (state_)
        {
        case 0: //  broken state;
            return 0;
        case 1: // unexpected, but let's recover
    #ifdef USE_CURL_PAUSE
            curl_easy_pause (cur_, CURLPAUSE_SEND);
            state_ = 2;
    #else
            state_ = 4;
    #endif
            append ((unsigned char *)ptr, bytes);
            if (client_)
            {
                client_->propertiesReady();
            }
            break;
        case 2:
            {
                //it's the first time after requestBytes was called
                append((unsigned char *)ptr, bytes);
                dp::Data data (saved_, saved_size_);
                state_ = 3;
                if (client_)
                {
                    size_t oldOffset = write_offset_;
                    write_offset_ += bytes;
                    client_->bytesReady(oldOffset, data, bytes == 0);
                }
            }
            break;
        case 3:
            {
                dp::Data data (static_cast<unsigned char *>(ptr), bytes);
                if (client_)
                {
                    size_t oldOffset = write_offset_;
                    write_offset_ += bytes;
                    client_->bytesReady(oldOffset, data, bytes == 0);
                }
            }
            break;

    #ifndef USE_CURL_PAUSE
        case 4:
            {
                append ((unsigned char *)ptr, bytes);
            }
            break;
    #endif
        }
        if (client_)
            result = bytes;

        return result;
    }
    size_t header_callback( void *ptr, size_t size, size_t nmemb)
    {
        dputils::StreamGuard guard(this);

        if (!client_)
            return 0;

        // What we will return  
        size_t result = 0;  
        size_t bytes = size * nmemb;

        if (state_ > 1)
            return  bytes;


        // we are not guaranteed that ptr is null-terminated
        char *buf = new char[bytes + 1];
        if (ptr != NULL && bytes != 0)
            ::memcpy (buf, ptr, bytes);
        buf[bytes] = (char)0;
        size_t len = ::strlen(buf);
        while (len > 0 && buf[len-1] <= ' ')
        {
            len--;
            buf[len] = 0;
        }

        if (len == 0)
        {
    #ifdef USE_CURL_PAUSE
            curl_easy_pause (cur_, CURLPAUSE_SEND);
            state_ = 2;
    #else
            state_ = 4;
    #endif
            if (client_)
            {
                client_->propertiesReady();
            }
        } 
        else
        {
            char * colon = ::strchr(buf, ':');
            if (colon)
            {
                *colon = (char)0;
                do
                {
                    ++colon;
                } while (*colon == ' ');

                int t = ::strlen(colon);

                if (client_)
                {
                    if (::strcmp(buf,  "Content-Length") == 0)
                    {
                        int len = ::atoi(colon);
                        if (len > 0)
                        {
                            client_->totalLengthReady(len);
                        }
                    }
                    else
                    {
                        client_->propertyReady(buf, colon);
                    }
                }
            }
        }

        delete[] buf;

        if (client_)
            result = bytes;

        return result;  
    }
Example #7
0
CURLcode Mtacurl::pause( int bitmask )
{
	return curl_easy_pause(m_pCurl, bitmask);
}
Example #8
0
static void
tr_webThreadFunc (void * vsession)
{
  char * str;
  CURLM * multi;
  struct tr_web * web;
  int taskCount = 0;
  struct tr_web_task * task;
  tr_session * session = vsession;

  /* try to enable ssl for https support; but if that fails,
   * try a plain vanilla init */
  if (curl_global_init (CURL_GLOBAL_SSL))
    curl_global_init (0);

  web = tr_new0 (struct tr_web, 1);
  web->close_mode = ~0;
  web->taskLock = tr_lockNew ();
  web->tasks = NULL;
  web->curl_verbose = getenv ("TR_CURL_VERBOSE") != NULL;
  web->curl_ssl_verify = getenv ("TR_CURL_SSL_VERIFY") != NULL;
  web->curl_ca_bundle = getenv ("CURL_CA_BUNDLE");
  if (web->curl_ssl_verify)
    {
      tr_logAddNamedInfo ("web", "will verify tracker certs using envvar CURL_CA_BUNDLE: %s",
               web->curl_ca_bundle == NULL ? "none" : web->curl_ca_bundle);
      tr_logAddNamedInfo ("web", "NB: this only works if you built against libcurl with openssl or gnutls, NOT nss");
      tr_logAddNamedInfo ("web", "NB: invalid certs will show up as 'Could not connect to tracker' like many other errors");
    }

  str = tr_buildPath (session->configDir, "cookies.txt", NULL);
  if (tr_fileExists (str, NULL))
    web->cookie_filename = tr_strdup (str);
  tr_free (str);

  multi = curl_multi_init ();
  session->web = web;

  for (;;)
    {
      long msec;
      int unused;
      CURLMsg * msg;
      CURLMcode mcode;

      if (web->close_mode == TR_WEB_CLOSE_NOW)
        break;
      if ((web->close_mode == TR_WEB_CLOSE_WHEN_IDLE) && (web->tasks == NULL))
        break;

      /* add tasks from the queue */
      tr_lockLock (web->taskLock);
      while (web->tasks != NULL)
        {
          /* pop the task */
          task = web->tasks;
          web->tasks = task->next;
          task->next = NULL;

          dbgmsg ("adding task to curl: [%s]", task->url);
          curl_multi_add_handle (multi, createEasy (session, web, task));
          /*fprintf (stderr, "adding a task.. taskCount is now %d\n", taskCount);*/
          ++taskCount;
        }
      tr_lockUnlock (web->taskLock);

      /* unpause any paused curl handles */
      if (paused_easy_handles != NULL)
        {
          CURL * handle;
          tr_list * tmp;

          /* swap paused_easy_handles to prevent oscillation
             between writeFunc this while loop */
          tmp = paused_easy_handles;
          paused_easy_handles = NULL;

          while ((handle = tr_list_pop_front (&tmp)))
            curl_easy_pause (handle, CURLPAUSE_CONT);
        }

      /* maybe wait a little while before calling curl_multi_perform () */
      msec = 0;
      curl_multi_timeout (multi, &msec);
      if (msec < 0)
        msec = THREADFUNC_MAX_SLEEP_MSEC;
      if (session->isClosed)
        msec = 100; /* on shutdown, call perform () more frequently */
      if (msec > 0)
        {
          int usec;
          int max_fd;
          struct timeval t;
          fd_set r_fd_set, w_fd_set, c_fd_set;

          max_fd = 0;
          FD_ZERO (&r_fd_set);
          FD_ZERO (&w_fd_set);
          FD_ZERO (&c_fd_set);
          curl_multi_fdset (multi, &r_fd_set, &w_fd_set, &c_fd_set, &max_fd);

          if (msec > THREADFUNC_MAX_SLEEP_MSEC)
            msec = THREADFUNC_MAX_SLEEP_MSEC;

          usec = msec * 1000;
          t.tv_sec =  usec / 1000000;
          t.tv_usec = usec % 1000000;
          tr_select (max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t);
        }

      /* call curl_multi_perform () */
      do
        mcode = curl_multi_perform (multi, &unused);
      while (mcode == CURLM_CALL_MULTI_PERFORM);

      /* pump completed tasks from the multi */
      while ((msg = curl_multi_info_read (multi, &unused)))
        {
          if ((msg->msg == CURLMSG_DONE) && (msg->easy_handle != NULL))
            {
              double total_time;
              struct tr_web_task * task;
              long req_bytes_sent;
              CURL * e = msg->easy_handle;
              curl_easy_getinfo (e, CURLINFO_PRIVATE, (void*)&task);
              assert (e == task->curl_easy);
              curl_easy_getinfo (e, CURLINFO_RESPONSE_CODE, &task->code);
              curl_easy_getinfo (e, CURLINFO_REQUEST_SIZE, &req_bytes_sent);
              curl_easy_getinfo (e, CURLINFO_TOTAL_TIME, &total_time);
              task->did_connect = task->code>0 || req_bytes_sent>0;
              task->did_timeout = !task->code && (total_time >= task->timeout_secs);
              curl_multi_remove_handle (multi, e);
              tr_list_remove_data (&paused_easy_handles, e);
              curl_easy_cleanup (e);
              tr_runInEventThread (task->session, task_finish_func, task);
              --taskCount;
            }
        }
    }

  /* Discard any remaining tasks.
   * This is rare, but can happen on shutdown with unresponsive trackers. */
  while (web->tasks != NULL)
    {
      task = web->tasks;
      web->tasks = task->next;
      dbgmsg ("Discarding task \"%s\"", task->url);
      task_free (task);
    }

  /* cleanup */
  tr_list_free (&paused_easy_handles, NULL);
  curl_multi_cleanup (multi);
  tr_lockFree (web->taskLock);
  tr_free (web->cookie_filename);
  tr_free (web);
  session->web = NULL;
}
Example #9
0
size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
{
  size_t rc;
  struct OutStruct *outs = userdata;
  struct OperationConfig *config = outs->config;
  size_t bytes = sz * nmemb;
  bool is_tty = config->global->isatty;

  /*
   * Once that libcurl has called back tool_write_cb() the returned value
   * is checked against the amount that was intended to be written, if
   * it does not match then it fails with CURLE_WRITE_ERROR. So at this
   * point returning a value different from sz*nmemb indicates failure.
   */
  const size_t failure = bytes ? 0 : 1;

#ifdef DEBUGBUILD
  {
    char *tty = curlx_getenv("CURL_ISATTY");
    if(tty) {
      is_tty = TRUE;
      curl_free(tty);
    }
  }

  if(config->show_headers) {
    if(bytes > (size_t)CURL_MAX_HTTP_HEADER) {
      warnf(config->global, "Header data size exceeds single call write "
            "limit!\n");
      return failure;
    }
  }
  else {
    if(bytes > (size_t)CURL_MAX_WRITE_SIZE) {
      warnf(config->global, "Data size exceeds single call write limit!\n");
      return failure;
    }
  }

  {
    /* Some internal congruency checks on received OutStruct */
    bool check_fails = FALSE;
    if(outs->filename) {
      /* regular file */
      if(!*outs->filename)
        check_fails = TRUE;
      if(!outs->s_isreg)
        check_fails = TRUE;
      if(outs->fopened && !outs->stream)
        check_fails = TRUE;
      if(!outs->fopened && outs->stream)
        check_fails = TRUE;
      if(!outs->fopened && outs->bytes)
        check_fails = TRUE;
    }
    else {
      /* standard stream */
      if(!outs->stream || outs->s_isreg || outs->fopened)
        check_fails = TRUE;
      if(outs->alloc_filename || outs->is_cd_filename || outs->init)
        check_fails = TRUE;
    }
    if(check_fails) {
      warnf(config->global, "Invalid output struct data for write callback\n");
      return failure;
    }
  }
#endif

  if(!outs->stream && !tool_create_output_file(outs))
    return failure;

  if(is_tty && (outs->bytes < 2000) && !config->terminal_binary_ok) {
    /* binary output to terminal? */
    if(memchr(buffer, 0, bytes)) {
      warnf(config->global, "Binary output can mess up your terminal. "
            "Use \"--output -\" to tell curl to output it to your terminal "
            "anyway, or consider \"--output <FILE>\" to save to a file.\n");
      config->synthetic_error = ERR_BINARY_TERMINAL;
      return failure;
    }
  }

#ifdef _WIN32
  if(isatty(fileno(outs->stream))) {
    DWORD in_len = (DWORD)(sz * nmemb);
    wchar_t* wc_buf;
    DWORD wc_len;
    intptr_t fhnd;

    /* calculate buffer size for wide characters */
    wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len,  NULL, 0);
    wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
    if(!wc_buf)
      return failure;

    /* calculate buffer size for multi-byte characters */
    wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len, wc_buf, wc_len);
    if(!wc_len) {
      free(wc_buf);
      return failure;
    }

    fhnd = _get_osfhandle(fileno(outs->stream));

    if(!WriteConsoleW(
        (HANDLE) fhnd,
        wc_buf,
        wc_len,
        &wc_len,
        NULL)) {
      free(wc_buf);
      return failure;
    }
    free(wc_buf);
    rc = bytes;
  }
  else
#endif
    rc = fwrite(buffer, sz, nmemb, outs->stream);

  if(bytes == rc)
    /* we added this amount of data to the output */
    outs->bytes += bytes;

  if(config->readbusy) {
    config->readbusy = FALSE;
    curl_easy_pause(config->easy, CURLPAUSE_CONT);
  }

  if(config->nobuffer) {
    /* output buffering disabled */
    int res = fflush(outs->stream);
    if(res)
      return failure;
  }

  return rc;
}
Example #10
0
void ResourceHandleManager::initializeHandle(ResourceHandle* job)
{
    KURL kurl = job->request().url();

    // Remove any fragment part, otherwise curl will send it as part of the request.
    kurl.removeRef();

    ResourceHandleInternal* d = job->getInternal();
    String url = kurl.string();

    if (kurl.isLocalFile()) {
        String query = kurl.query();
        // Remove any query part sent to a local file.
        if (!query.isEmpty())
            url = url.left(url.find(query));
        // Determine the MIME type based on the path.
        d->m_response.setMimeType(MIMETypeRegistry::getMIMETypeForPath(url));
    }

    d->m_handle = curl_easy_init();

#if LIBCURL_VERSION_NUM > 0x071200
    if (d->m_defersLoading) {
        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL);
        // If we did not pause the handle, we would ASSERT in the
        // header callback. So just assert here.
        ASSERT(error == CURLE_OK);
    }
#endif
#ifndef NDEBUG
    if (getenv("DEBUG_CURL"))
        curl_easy_setopt(d->m_handle, CURLOPT_VERBOSE, 1);
#endif
    curl_easy_setopt(d->m_handle, CURLOPT_PRIVATE, job);
    curl_easy_setopt(d->m_handle, CURLOPT_ERRORBUFFER, m_curlErrorBuffer);
    curl_easy_setopt(d->m_handle, CURLOPT_WRITEFUNCTION, writeCallback);
    curl_easy_setopt(d->m_handle, CURLOPT_WRITEDATA, job);
    curl_easy_setopt(d->m_handle, CURLOPT_HEADERFUNCTION, headerCallback);
    curl_easy_setopt(d->m_handle, CURLOPT_WRITEHEADER, job);
    curl_easy_setopt(d->m_handle, CURLOPT_AUTOREFERER, 1);
    curl_easy_setopt(d->m_handle, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(d->m_handle, CURLOPT_MAXREDIRS, 10);
    curl_easy_setopt(d->m_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_easy_setopt(d->m_handle, CURLOPT_SHARE, m_curlShareHandle);
    curl_easy_setopt(d->m_handle, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 5); // 5 minutes
    // FIXME: Enable SSL verification when we have a way of shipping certs
    // and/or reporting SSL errors to the user.
    if (ignoreSSLErrors)
        curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYPEER, false);
    // enable gzip and deflate through Accept-Encoding:
    curl_easy_setopt(d->m_handle, CURLOPT_ENCODING, "");

    // url must remain valid through the request
    ASSERT(!d->m_url);

    // url is in ASCII so latin1() will only convert it to char* without character translation.
    d->m_url = strdup(url.latin1().data());
    curl_easy_setopt(d->m_handle, CURLOPT_URL, d->m_url);

    if (m_cookieJarFileName) {
        curl_easy_setopt(d->m_handle, CURLOPT_COOKIEFILE, m_cookieJarFileName);
        curl_easy_setopt(d->m_handle, CURLOPT_COOKIEJAR, m_cookieJarFileName);
    }

    struct curl_slist* headers = 0;
    if (job->request().httpHeaderFields().size() > 0) {
        HTTPHeaderMap customHeaders = job->request().httpHeaderFields();
        HTTPHeaderMap::const_iterator end = customHeaders.end();
        for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) {
            String key = it->first;
            String value = it->second;
            String headerString(key);
            headerString.append(": ");
            headerString.append(value);
            CString headerLatin1 = headerString.latin1();
            headers = curl_slist_append(headers, headerLatin1.data());
        }
    }

    if ("GET" == job->request().httpMethod())
        curl_easy_setopt(d->m_handle, CURLOPT_HTTPGET, TRUE);
    else if ("POST" == job->request().httpMethod())
        setupPOST(job, &headers);
    else if ("PUT" == job->request().httpMethod())
        setupPUT(job, &headers);
    else if ("HEAD" == job->request().httpMethod())
        curl_easy_setopt(d->m_handle, CURLOPT_NOBODY, TRUE);

    if (headers) {
        curl_easy_setopt(d->m_handle, CURLOPT_HTTPHEADER, headers);
        d->m_customHeaders = headers;
    }
}
Example #11
0
static DWORD WINAPI curl_threadfunc(LPVOID _unused) {
#else
static void *curl_threadfunc(void *_unused) {
#endif

	while(1) {
		if(will_overflow()) {
			curl_easy_pause(curl_handle, CURLPAUSE_ALL);
			do {
				printf(".");
				fflush(stdout);
				usleep(100000);
			} while(will_overflow());
			curl_easy_pause(curl_handle, CURLPAUSE_CONT);
		}
		if(curl_easy_perform(curl_handle) != CURLE_OK)
			sleep(2);
		printf("Retrying URL connect...\n");
	}
	return 0;
}

int main(int argc, char *argv[]) {
#ifdef _WIN32
	int tid;
#else
	pthread_t thd;
#endif

	if(argc != 4) {
		fprintf(stderr, "Usage: %s <stream_url> <nbd_addr> <nbd_port>\n", argv[0]);
		return 1;
	}

	curl_global_init(CURL_GLOBAL_ALL);
	curl_handle = curl_easy_init();
	curl_easy_setopt(curl_handle, CURLOPT_URL, argv[1]);
	curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, curl_cback);
	curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "vdf_stream");

	drv = vdf_drive_create(DRIVE_SIZE, DRIVE_FLAGS);
	if(drv == NULL) {
		perror("vdf_createdrive");
		return 1;
	}

	bps = vdf_drive_sectorsize(drv);
	filesize = (vdf_drive_dataclusters(drv) - 16) * vdf_drive_clustersize(drv);		/* leave a bit of room */

	bufflen = bps * BUFFCNT;
	buffer = malloc(bufflen);
	if(buffer == NULL) {
		perror("malloc");
		return 1;
	}
	bstart = bend = 0;
	writeoff = 0;

	fil = vdf_add_file_virt(vdf_drive_root(drv), TRACK_NAME, filesize, file_cback, NULL, 0);
	if(fil == NULL) {
		perror("vdf_add_file_virt");
		return 1;
	}

	trans = vdf_transport_open(VTD_NBD_CLI_STR, drv, NULL, argv[2], argv[3]);
	if(trans == NULL) {
		perror("vdf_transport_open");
		return 1;
	}

#ifdef _WIN32
	if(CreateThread(NULL, 0, curl_threadfunc, NULL, 0, &tid) == NULL) {
		perror("CreateThread");
		return 1;
	}
#else
	if(pthread_create(&thd, NULL, curl_threadfunc, NULL) == -1) {
		perror("pthread_create");
		return 1;
	}
#endif

//	vdf_dump_drive_info(drv, stdout);
//	vdf_dump_drive(drv, "stream.img");
//	return 0;

	while(1) {
		if(vdf_transport_start(trans) == 0) {
			while(vdf_transport_process(trans) == 0);
		} else {
			printf("Retrying NBD connect...\n");
			sleep(2);
		}
	}
}
Example #12
0
static off_t libcurl_seek(hFILE *fpv, off_t offset, int whence)
{
    hFILE_libcurl *fp = (hFILE_libcurl *) fpv;

    CURLcode err;
    CURLMcode errm;
    off_t origin, pos;

    switch (whence) {
    case SEEK_SET:
        origin = 0;
        break;
    case SEEK_CUR:
        errno = ENOSYS;
        return -1;
    case SEEK_END:
        if (fp->file_size < 0) { errno = ESPIPE; return -1; }
        origin = fp->file_size;
        break;
    default:
        errno = EINVAL;
        return -1;
    }

    // Check 0 <= origin+offset < fp->file_size carefully, avoiding overflow
    if ((offset < 0)? origin + offset < 0
                : (fp->file_size >= 0 && offset > fp->file_size - origin)) {
        errno = EINVAL;
        return -1;
    }

    pos = origin + offset;

    errm = curl_multi_remove_handle(curl.multi, fp->easy);
    if (errm != CURLM_OK) { errno = multi_errno(errm); return -1; }
    curl.nrunning--;

    // TODO If we seem to be doing random access, use CURLOPT_RANGE to do
    // limited reads (e.g. about a BAM block!) so seeking can reuse the
    // existing connection more often.

    if (pos <= 2147483647) err = curl_easy_setopt(fp->easy, CURLOPT_RESUME_FROM, (long) pos);
    else err = curl_easy_setopt(fp->easy, CURLOPT_RESUME_FROM_LARGE, (curl_off_t) pos);
    if (err != CURLE_OK) { errno = easy_errno(fp->easy, err); return -1; }

    fp->buffer.len = 0;
    fp->paused = fp->finished = 0;

    errm = curl_multi_add_handle(curl.multi, fp->easy);
    if (errm != CURLM_OK) { errno = multi_errno(errm); return -1; }
    curl.nrunning++;

    err = curl_easy_pause(fp->easy, CURLPAUSE_CONT);
    if (err != CURLE_OK) { errno = easy_errno(fp->easy, err); return -1; }

    while (! fp->paused && ! fp->finished)
        if (wait_perform() < 0) return -1;

    if (fp->finished && fp->final_result != CURLE_OK) {
        errno = easy_errno(fp->easy, fp->final_result);
        return -1;
    }

    return pos;
}
Example #13
0
CURLcode DllLibCurl::easy_pause(CURL_HANDLE* handle, int bitmask)
{
  return curl_easy_pause(handle, bitmask);
}
Example #14
0
int32_t HttpNative_EasyUnpause(CURL* handle)
{
    return (int32_t)(curl_easy_pause(handle, CURLPAUSE_CONT));
}
Example #15
0
	// This is the writer call back function used by m_curl  
	size_t writer_callback( void *ptr, size_t size, size_t nmemb)
	{
		dputils::StreamGuard guard(this);

		if (!m_client)
			return 0;

		// What we will return  
		size_t result = 0;  
		size_t bytes = size * nmemb;
		switch (m_state)
		{
		case 0: //  broken state;
			return 0;
		case 1: // unexpected, but let's recover
#ifdef USE_CURL_PAUSE
			curl_easy_pause (m_curl, CURLPAUSE_SEND);
			m_state = 2;
#else
			m_state = 4;
#endif
			append ((unsigned char *)ptr, bytes);
			if (m_client)
			{
				m_client->propertiesReady();
			}
			break;
		case 2:
			{
				//it's the first time after requestBytes was called
				append((unsigned char *)ptr, bytes);
				dp::Data data (m_saved, m_savedSize);
				m_state = 3;
				if (m_client)
				{
					size_t oldOffset = m_writeOffset;
					m_writeOffset += bytes;
					if( m_verbose )
						reportData( "in", oldOffset, data );
					m_client->bytesReady(oldOffset, data, bytes == 0);
				}
			}
			break;
		case 3:
			{
				dp::Data data (static_cast<unsigned char *>(ptr), bytes);
				if (m_client)
				{
					size_t oldOffset = m_writeOffset;
					m_writeOffset += bytes;
					if( m_verbose )
						reportData( "in", oldOffset, data );
					m_client->bytesReady(oldOffset, data, bytes == 0);
				}
			}
			break;

#ifndef USE_CURL_PAUSE
		case 4:
			{
				append ((unsigned char *)ptr, bytes);
			}
			break;
#endif
		}
		if (m_client)
			result = bytes;

		return result;  
	}
size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
{
  size_t rc;
  struct OutStruct *outs = userdata;
  struct Configurable *config = outs->config;

  /*
   * Once that libcurl has called back tool_write_cb() the returned value
   * is checked against the amount that was intended to be written, if
   * it does not match then it fails with CURLE_WRITE_ERROR. So at this
   * point returning a value different from sz*nmemb indicates failure.
   */
  const size_t failure = (sz * nmemb) ? 0 : 1;

  if(!config)
    return failure;

#ifdef DEBUGBUILD
  if(config->include_headers) {
    if(sz * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
      warnf(config, "Header data size exceeds single call write limit!\n");
      return failure;
    }
  }
  else {
    if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) {
      warnf(config, "Data size exceeds single call write limit!\n");
      return failure;
    }
  }

  {
    /* Some internal congruency checks on received OutStruct */
    bool check_fails = FALSE;
    if(outs->filename) {
      /* regular file */
      if(!*outs->filename)
        check_fails = TRUE;
      if(!outs->s_isreg)
        check_fails = TRUE;
      if(outs->fopened && !outs->stream)
        check_fails = TRUE;
      if(!outs->fopened && outs->stream)
        check_fails = TRUE;
      if(!outs->fopened && outs->bytes)
        check_fails = TRUE;
    }
    else {
      /* standard stream */
      if(!outs->stream || outs->s_isreg || outs->fopened)
        check_fails = TRUE;
      if(outs->alloc_filename || outs->init)
        check_fails = TRUE;
    }
    if(check_fails) {
      warnf(config, "Invalid output struct data for write callback\n");
      return failure;
    }
  }
#endif

  if(!outs->stream) {
    FILE *file;

    if(!outs->filename || !*outs->filename) {
      warnf(config, "Remote filename has no length!\n");
      return failure;
    }

    if(config->content_disposition) {
      /* don't overwrite existing files */
      file = fopen(outs->filename, "rb");
      if(file) {
        fclose(file);
        warnf(config, "Refusing to overwrite %s: %s\n", outs->filename,
              strerror(EEXIST));
        return failure;
      }
    }

    /* open file for writing */
    file = fopen(outs->filename, "wb");
    if(!file) {
      warnf(config, "Failed to create the file %s: %s\n", outs->filename,
            strerror(errno));
      return failure;
    }
    outs->s_isreg = TRUE;
    outs->fopened = TRUE;
    outs->stream = file;
    outs->bytes = 0;
    outs->init = 0;
  }

  rc = fwrite(buffer, sz, nmemb, outs->stream);

  if((sz * nmemb) == rc)
    /* we added this amount of data to the output */
    outs->bytes += (sz * nmemb);

  if(config->readbusy) {
    config->readbusy = FALSE;
    curl_easy_pause(config->easy, CURLPAUSE_CONT);
  }

  if(config->nobuffer) {
    /* output buffering disabled */
    int res = fflush(outs->stream);
    if(res)
      return failure;
  }

  return rc;
}
/**
 * Function that can be used by the transport service to transmit
 * a message using the plugin.   Note that in the case of a
 * peer disconnecting, the continuation MUST be called
 * prior to the disconnect notification itself.  This function
 * will be called with this peer's HELLO message to initiate
 * a fresh connection to another peer.
 *
 * @param cls closure
 * @param s which session must be used
 * @param msgbuf the message to transmit
 * @param msgbuf_size number of bytes in 'msgbuf'
 * @param priority how important is the message (most plugins will
 *                 ignore message priority and just FIFO)
 * @param to how long to wait at most for the transmission (does not
 *                require plugins to discard the message after the timeout,
 *                just advisory for the desired delay; most plugins will ignore
 *                this as well)
 * @param cont continuation to call once the message has
 *        been transmitted (or if the transport is ready
 *        for the next transmission call; or if the
 *        peer disconnected...); can be NULL
 * @param cont_cls closure for cont
 * @return number of bytes used (on the physical network, with overheads);
 *         -1 on hard errors (i.e. address invalid); 0 is a legal value
 *         and does NOT mean that the message was not transmitted (DV)
 */
static ssize_t
http_client_plugin_send (void *cls,
                         struct Session *s,
                         const char *msgbuf, size_t msgbuf_size,
                         unsigned int priority,
                         struct GNUNET_TIME_Relative to,
                         GNUNET_TRANSPORT_TransmitContinuation cont,
                         void *cont_cls)
{
  struct HTTP_Client_Plugin *plugin = cls;
  struct HTTP_Message *msg;
  char *stat_txt;

  GNUNET_assert (plugin != NULL);
  GNUNET_assert (s != NULL);

  /* lookup if session is really existing */
  if (GNUNET_YES != client_exist_session (plugin, s))
  {
    GNUNET_break (0);
    return GNUNET_SYSERR;
  }

  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
                   "Session %p/connection %p: Sending message with %u to peer `%s' \n",
                   s, s->client_put,
                   msgbuf_size, GNUNET_i2s (&s->target));

  /* create new message and schedule */
  msg = GNUNET_malloc (sizeof (struct HTTP_Message) + msgbuf_size);
  msg->next = NULL;
  msg->size = msgbuf_size;
  msg->pos = 0;
  msg->buf = (char *) &msg[1];
  msg->transmit_cont = cont;
  msg->transmit_cont_cls = cont_cls;
  memcpy (msg->buf, msgbuf, msgbuf_size);
  GNUNET_CONTAINER_DLL_insert_tail (s->msg_head, s->msg_tail, msg);

  GNUNET_asprintf (&stat_txt, "# bytes currently in %s_client buffers", plugin->protocol);
  GNUNET_STATISTICS_update (plugin->env->stats,
                            stat_txt, msgbuf_size, GNUNET_NO);

  GNUNET_free (stat_txt);

  if (GNUNET_YES == s->put_tmp_disconnecting)
  {
    /* PUT connection is currently getting disconnected */
    s->put_reconnect_required = GNUNET_YES;
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
                     "Session %p/connection %jp: currently disconnecting, reconnecting immediately\n",
                     s, s->client_put);
    return msgbuf_size;
  }
  else if (GNUNET_YES == s->put_paused)
  {
    /* PUT connection was paused, unpause */
    GNUNET_assert (s->put_disconnect_task != GNUNET_SCHEDULER_NO_TASK);
    GNUNET_SCHEDULER_cancel (s->put_disconnect_task);
    s->put_disconnect_task = GNUNET_SCHEDULER_NO_TASK;
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
                     "Session %p/connection %p: unpausing connection\n",
                     s, s->client_put);
    s->put_paused = GNUNET_NO;
    curl_easy_pause (s->client_put, CURLPAUSE_CONT);
  }
  else if (GNUNET_YES == s->put_tmp_disconnected)
  {
    /* PUT connection was disconnected, reconnect */
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
                     "Session %p: Reconnecting PUT connection\n",
                     s);
    s->put_tmp_disconnected = GNUNET_NO;
    GNUNET_break (s->client_put == NULL);
    if (GNUNET_SYSERR == client_connect_put (s))
    {
      return GNUNET_SYSERR;
    }
  }

  client_schedule (s->plugin, GNUNET_YES);
  client_reschedule_session_timeout (s);
  return msgbuf_size;
}