Exemplo n.º 1
0
static int do_one_request(CURLM *m, char *URL, char *resolve)
{
  CURL *curls;
  struct curl_slist *resolve_list = NULL;
  int still_running;
  int res = 0;
  CURLMsg *msg;
  int msgs_left;

  resolve_list = curl_slist_append(resolve_list, resolve);

  easy_init(curls);

  easy_setopt(curls, CURLOPT_URL, URL);
  easy_setopt(curls, CURLOPT_RESOLVE, resolve_list);
  easy_setopt(curls, CURLOPT_DEBUGFUNCTION, debug_callback);
  easy_setopt(curls, CURLOPT_VERBOSE, 1);
  easy_setopt(curls, CURLOPT_DNS_CACHE_TIMEOUT, DNS_TIMEOUT);

  multi_add_handle(m, curls);
  multi_perform(m, &still_running);

  abort_on_test_timeout();

  while(still_running) {
    struct timeval timeout;
    fd_set fdread, fdwrite, fdexcep;
    int maxfd = -99;

    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);

    abort_on_test_timeout();
    multi_perform(m, &still_running);

    abort_on_test_timeout();
  }

  do {
    msg = curl_multi_info_read(m, &msgs_left);
    if(msg && msg->msg == CURLMSG_DONE && msg->easy_handle == curls) {
      res = msg->data.result;
      break;
    }
  } while(msg);

test_cleanup:

  curl_multi_remove_handle(m, curls);
  curl_easy_cleanup(curls);
  curl_slist_free_all(resolve_list);

  return res;
}
Exemplo n.º 2
0
void flush_internal_buffer(churl_context* context)
{
	churl_buffer* context_buffer = context->upload_buffer;
	if (context_buffer->top == 0)
		return;

	while((context->curl_still_running != 0) &&
		  ((context_buffer->top - context_buffer->bot) > 0))
	{
		/*
		 * Allow canceling a query while waiting for input from remote service
		 */
		CHECK_FOR_INTERRUPTS();

		multi_perform(context);
	}

	if ((context->curl_still_running == 0) &&
		((context_buffer->top - context_buffer->bot) > 0))
		elog(ERROR, "failed sending to remote component %s", get_dest_address(context->curl_handle));

	check_response(context);

	context_buffer->top = 0;
	context_buffer->bot = 0;
}
Exemplo n.º 3
0
int test(char *URL)
{
    int stillRunning;
    CURLM* multiHandle = NULL;
    CURL* curl = NULL;
    int res = 0;

    global_init(CURL_GLOBAL_ALL);

    multi_init(multiHandle);

    easy_init(curl);

    easy_setopt(curl, CURLOPT_USERPWD, libtest_arg2);
    easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
    easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");

    easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    easy_setopt(curl, CURLOPT_URL, URL);
    easy_setopt(curl, CURLOPT_INFILESIZE, (long)5);

    multi_add_handle(multiHandle, curl);

    /* this tests if removing an easy handle immediately after multi
       perform has been called succeeds or not. */

    fprintf(stderr, "curl_multi_perform()...\n");

    multi_perform(multiHandle, &stillRunning);

    fprintf(stderr, "curl_multi_perform() succeeded\n");

    fprintf(stderr, "curl_multi_remove_handle()...\n");
    res = (int) curl_multi_remove_handle(multiHandle, curl);
    if(res)
        fprintf(stderr, "curl_multi_remove_handle() failed, "
                "with code %d\n", res);
    else
        fprintf(stderr, "curl_multi_remove_handle() succeeded\n");

test_cleanup:

    /* undocumented cleanup sequence - type UB */

    curl_easy_cleanup(curl);
    curl_multi_cleanup(multiHandle);
    curl_global_cleanup();

    return res;
}
Exemplo n.º 4
0
/*
 * Fills internal buffer up to want bytes.
 * returns when size reached or transfer ended
 */
int fill_internal_buffer(churl_context* context, int want)
{
    fd_set 	fdread;
    fd_set 	fdwrite;
    fd_set 	fdexcep;
    int 	maxfd;
    struct 	timeval timeout;
    int 	nfds, curl_error;

    /* attempt to fill buffer */
	while (context->curl_still_running &&
		   ((context->download_buffer->top - context->download_buffer->bot) < want))
    {
        FD_ZERO(&fdread);
        FD_ZERO(&fdwrite);
        FD_ZERO(&fdexcep);

        /*
         * Allow canceling a query while waiting for input from remote service
         */
        CHECK_FOR_INTERRUPTS();

        /* set a suitable timeout to fail on */
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;

        /* get file descriptors from the transfers */
        if (CURLE_OK != (curl_error = curl_multi_fdset(context->multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd)))
			elog(ERROR, "internal error: curl_multi_fdset failed (%d - %s)",
						curl_error, curl_easy_strerror(curl_error));

		if (maxfd <= 0)
		{
			context->curl_still_running = 0;
			break;
		}

        if (-1 == (nfds = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout)))
		{
			if (errno == EINTR || errno == EAGAIN)
				continue;
			elog(ERROR, "internal error: select failed on curl_multi_fdset (maxfd %d) (%d - %s)",
				 maxfd, errno, strerror(errno));
		}

		if (nfds > 0)
			multi_perform(context);
    }

    return 0;
}
Exemplo n.º 5
0
/*
 * Let libcurl finish the upload by
 * calling perform repeatedly
 */
void finish_upload(churl_context* context)
{
	if (!context->multi_handle)
		return;

	flush_internal_buffer(context);

	/* allow read_callback to say 'all done'
	 * by returning a zero thus ending the connection
	 */
	while(context->curl_still_running != 0)
		multi_perform(context);

	check_response(context);
}
Exemplo n.º 6
0
/*
 * Setups the libcurl multi API
 */
void setup_multi_handle(churl_context* context)
{
	int curl_error;

	/* Create multi handle on first use */
	if (!context->multi_handle)
		if (!(context->multi_handle = curl_multi_init()))
			elog(ERROR, "internal error: curl_multi_init failed");

	/* add the easy handle to the multi handle */
	/* don't blame me, blame libcurl */
	if (CURLM_OK != (curl_error = curl_multi_add_handle(context->multi_handle, context->curl_handle)))
		if (CURLM_CALL_MULTI_PERFORM != curl_error)
			elog(ERROR, "internal error: curl_multi_add_handle failed (%d - %s)",
				 curl_error, curl_easy_strerror(curl_error));

	multi_perform(context);
}
Exemplo n.º 7
0
int test(char *URL)
{
  int res = 0;
  CURL *curl = NULL;
  int counter=0;
  CURLM *m = NULL;
  int running=1;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  easy_init(curl);

  easy_setopt(curl, CURLOPT_URL, URL);
  easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  easy_setopt(curl, CURLOPT_HEADER, 1L);

  /* read the POST data from a callback */
  easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback);
  easy_setopt(curl, CURLOPT_IOCTLDATA, &counter);
  easy_setopt(curl, CURLOPT_READFUNCTION, readcallback);
  easy_setopt(curl, CURLOPT_READDATA, &counter);
  /* We CANNOT do the POST fine without setting the size (or choose chunked)! */
  easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(UPLOADTHIS));

  easy_setopt(curl, CURLOPT_POST, 1L);
#ifdef CURL_DOES_CONVERSIONS
  /* Convert the POST data to ASCII. */
  easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1L);
#endif
  easy_setopt(curl, CURLOPT_PROXY, libtest_arg2);
  easy_setopt(curl, CURLOPT_PROXYUSERPWD, libtest_arg3);
  easy_setopt(curl, CURLOPT_PROXYAUTH,
                   (long) (CURLAUTH_NTLM | CURLAUTH_DIGEST | CURLAUTH_BASIC) );

  multi_init(m);

  multi_add_handle(m, curl);

  while (running) {
    struct timeval timeout;
    fd_set fdread, fdwrite, fdexcep;
    int maxfd = -99;

    timeout.tv_sec = 0;
    timeout.tv_usec = 100000L; /* 100 ms */

    multi_perform(m, &running);

    abort_on_test_timeout();

#ifdef TPF
    sleep(1); /* avoid ctl-10 dump */
#endif

    if(!running)
      break; /* done */

    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);

    multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    abort_on_test_timeout();
  }

test_cleanup:

  /* proper cleanup sequence - type PA */

  curl_multi_remove_handle(m, curl);
  curl_multi_cleanup(m);
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return res;
}
Exemplo n.º 8
0
int test(char *URL)
{
  int res = 0;
  CURL *curl = NULL;
  int running;
  CURLM *m = NULL;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  easy_init(curl);

  easy_setopt(curl, CURLOPT_URL, URL);
  easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  easy_setopt(curl, CURLOPT_PROXY, libtest_arg2);
  easy_setopt(curl, CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4);

  multi_init(m);

  multi_add_handle(m, curl);

  fprintf(stderr, "Start at URL 0\n");

  for(;;) {
    struct timeval interval;
    fd_set rd, wr, exc;
    int maxfd = -99;

    interval.tv_sec = 1;
    interval.tv_usec = 0;

    multi_perform(m, &running);

    abort_on_test_timeout();

    if(!running)
      break; /* done */

    FD_ZERO(&rd);
    FD_ZERO(&wr);
    FD_ZERO(&exc);

    multi_fdset(m, &rd, &wr, &exc, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd + 1, &rd, &wr, &exc, &interval);

    abort_on_test_timeout();
  }

test_cleanup:

  /* undocumented cleanup sequence - type UB */

  curl_easy_cleanup(curl);
  curl_multi_cleanup(m);
  curl_global_cleanup();

  return res;
}
Exemplo n.º 9
0
Arquivo: lib591.c Projeto: 2px/curl
int test(char *URL)
{
  CURL *easy = NULL;
  CURLM *multi = NULL;
  int res = 0;
  int running;
  int msgs_left;
  CURLMsg *msg;
  FILE *upload = NULL;
  int error;

  start_test_timing();

  upload = fopen(libtest_arg3, "rb");
  if(!upload) {
    error = ERRNO;
    fprintf(stderr, "fopen() failed with error: %d (%s)\n",
            error, strerror(error));
    fprintf(stderr, "Error opening file: (%s)\n", libtest_arg3);
    return TEST_ERR_FOPEN;
  }

  res_global_init(CURL_GLOBAL_ALL);
  if(res) {
    fclose(upload);
    return res;
  }

  easy_init(easy);

  /* go verbose */
  easy_setopt(easy, CURLOPT_VERBOSE, 1L);

  /* specify target */
  easy_setopt(easy, CURLOPT_URL, URL);

  /* enable uploading */
  easy_setopt(easy, CURLOPT_UPLOAD, 1L);

  /* data pointer for the file read function */
  easy_setopt(easy, CURLOPT_READDATA, upload);

  /* use active mode FTP */
  easy_setopt(easy, CURLOPT_FTPPORT, "-");

  /* server connection timeout */
  easy_setopt(easy, CURLOPT_ACCEPTTIMEOUT_MS,
              strtol(libtest_arg2, NULL, 10)*1000);

  multi_init(multi);

  multi_add_handle(multi, easy);

  for(;;) {
    struct timeval interval;
    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    long timeout = -99;
    int maxfd = -99;

    multi_perform(multi, &running);

    abort_on_test_timeout();

    if(!running)
      break; /* done */

    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);

    multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    multi_timeout(multi, &timeout);

    /* At this point, timeout is guaranteed to be greater or equal than -1. */

    if(timeout != -1L) {
      int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
      interval.tv_sec = itimeout/1000;
      interval.tv_usec = (itimeout%1000)*1000;
    }
    else {
      interval.tv_sec = 0;
      interval.tv_usec = 100000L; /* 100 ms */
    }

    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);

    abort_on_test_timeout();
  }

  msg = curl_multi_info_read(multi, &msgs_left);
  if(msg)
    res = msg->data.result;

test_cleanup:

  /* undocumented cleanup sequence - type UA */

  curl_multi_cleanup(multi);
  curl_easy_cleanup(easy);
  curl_global_cleanup();

  /* close the local file */
  fclose(upload);

  return res;
}
Exemplo n.º 10
0
int test(char *url)
{
    CURLM *multi = NULL;
    int running;
    int i, j;
    int num_handles = 0;
    enum HandleState state = ReadyForNewHandle;
    size_t urllen = strlen(url) + 4 + 1;
    char* full_url = malloc(urllen);

    start_test_timing();

    if(!full_url) {
        fprintf(stderr, "Not enough memory for full url\n");
        return TEST_ERR_MAJOR_BAD;
    }

    for(i = 0; i < MAX_EASY_HANDLES; ++i) {
        easy[i] = NULL;
        sockets[i] = CURL_SOCKET_BAD;
    }

    res_global_init(CURL_GLOBAL_ALL);
    if(res) {
        free(full_url);
        return res;
    }

    multi_init(multi);

#ifdef USE_PIPELINING
    multi_setopt(multi, CURLMOPT_PIPELINING, 1L);
    multi_setopt(multi, CURLMOPT_MAX_HOST_CONNECTIONS, 5L);
    multi_setopt(multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, 10L);
#endif

    for(;;) {
        struct timeval interval;
        fd_set fdread;
        fd_set fdwrite;
        fd_set fdexcep;
        long timeout = -99;
        int maxfd = -99;
        bool found_new_socket = FALSE;

        /* Start a new handle if we aren't at the max */
        if(state == ReadyForNewHandle) {
            easy_init(easy[num_handles]);

            if(num_handles % 3 == 2) {
                snprintf(full_url, urllen, "%s0200", url);
                easy_setopt(easy[num_handles], CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
            }
            else {
                snprintf(full_url, urllen, "%s0100", url);
                easy_setopt(easy[num_handles], CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            }
            easy_setopt(easy[num_handles], CURLOPT_FRESH_CONNECT, 1L);
            easy_setopt(easy[num_handles], CURLOPT_URL, full_url);
            easy_setopt(easy[num_handles], CURLOPT_VERBOSE, 1L);
            easy_setopt(easy[num_handles], CURLOPT_HTTPGET, 1L);
            easy_setopt(easy[num_handles], CURLOPT_USERPWD, "testuser:testpass");
            easy_setopt(easy[num_handles], CURLOPT_WRITEFUNCTION, callback);
            easy_setopt(easy[num_handles], CURLOPT_WRITEDATA, easy + num_handles);
            easy_setopt(easy[num_handles], CURLOPT_HEADER, 1L);

            multi_add_handle(multi, easy[num_handles]);
            num_handles += 1;
            state = NeedSocketForNewHandle;
        }

        multi_perform(multi, &running);

        abort_on_test_timeout();

        if(!running && state == NoMoreHandles)
            break; /* done */

        FD_ZERO(&fdread);
        FD_ZERO(&fdwrite);
        FD_ZERO(&fdexcep);

        multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);

        /* At this point, maxfd is guaranteed to be greater or equal than -1. */

        /* Any socket which is new in fdread is associated with the new handle */
        for(i = 0; i <= maxfd; ++i) {
            bool socket_exists = FALSE;
            curl_socket_t curfd = (curl_socket_t)i;

            if(!FD_ISSET(curfd, &fdread)) {
                continue;
            }

            /* Check if this socket was already detected for an earlier handle (or
               for this handle, num_handles-1, in the callback */
            for(j = 0; j < num_handles; ++j) {
                if(sockets[j] == curfd) {
                    socket_exists = TRUE;
                    break;
                }
            }
            if(socket_exists) {
                continue;
            }

            if(found_new_socket || state != NeedSocketForNewHandle) {
                fprintf(stderr, "Unexpected new socket\n");
                res = TEST_ERR_MAJOR_BAD;
                goto test_cleanup;
            }

            /* Now we know the socket is for the most recent handle, num_handles-1 */
            if(sockets[num_handles-1] != CURL_SOCKET_BAD) {
                /* A socket for this handle was already detected in the callback; if it
                   matched socket_exists should be true and we would never get here */
                assert(curfd != sockets[num_handles-1]);
                fprintf(stderr, "Handle %d wrote to socket %d then detected on %d\n",
                        num_handles-1, (int)sockets[num_handles-1], (int)curfd);
                res = TEST_ERR_MAJOR_BAD;
                goto test_cleanup;
            }
            else {
                sockets[num_handles-1] = curfd;
                found_new_socket = TRUE;
                /* continue to make sure there's only one new handle */
            }
        }

        if(state == NeedSocketForNewHandle) {
            if(maxfd != -1 && !found_new_socket) {
                fprintf(stderr, "Warning: socket did not open immediately for new "
                        "handle (trying again)\n");
                continue;
            }
            state = num_handles < MAX_EASY_HANDLES ? ReadyForNewHandle
                    : NoMoreHandles;
        }

        multi_timeout(multi, &timeout);

        /* At this point, timeout is guaranteed to be greater or equal than -1. */

        fprintf(stderr, "%s:%d num_handles %d timeout %ld\n",
                __FILE__, __LINE__, num_handles, timeout);

        if(timeout != -1L) {
            int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
            interval.tv_sec = itimeout/1000;
            interval.tv_usec = (itimeout%1000)*1000;
        }
        else {
            interval.tv_sec = TEST_HANG_TIMEOUT/1000+1;
            interval.tv_usec = 0;

            /* if there's no timeout and we get here on the last handle, we may
               already have read the last part of the stream so waiting makes no
               sense */
            if(!running && num_handles == MAX_EASY_HANDLES) {
                break;
            }
        }

        select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);

        abort_on_test_timeout();
    }

test_cleanup:

    /* proper cleanup sequence - type PB */

    for(i = 0; i < MAX_EASY_HANDLES; i++) {
        curl_multi_remove_handle(multi, easy[i]);
        curl_easy_cleanup(easy[i]);
    }

    curl_multi_cleanup(multi);
    curl_global_cleanup();

    free(full_url);

    return res;
}
Exemplo n.º 11
0
int test(char *URL)
{
  CURL* curls = NULL;
  CURLM* multi = NULL;
  int still_running;
  int i = TEST_ERR_FAILURE;
  int res = 0;
  CURLMsg *msg;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  multi_init(multi);

  easy_init(curls);

  easy_setopt(curls, CURLOPT_URL, URL);
  easy_setopt(curls, CURLOPT_HEADER, 1L);

  multi_add_handle(multi, curls);

  multi_perform(multi, &still_running);

  abort_on_test_timeout();

  while(still_running) {
    int num;
    res = curl_multi_wait(multi, NULL, 0, TEST_HANG_TIMEOUT, &num);
    if (res != CURLM_OK) {
      printf("curl_multi_wait() returned %d\n", res);
      res = TEST_ERR_MAJOR_BAD;
      goto test_cleanup;
    }

    abort_on_test_timeout();

    multi_perform(multi, &still_running);

    abort_on_test_timeout();
  }

  msg = curl_multi_info_read(multi, &still_running);
  if(msg)
    /* this should now contain a result code from the easy handle,
       get it */
    i = msg->data.result;

test_cleanup:

  /* undocumented cleanup sequence - type UA */

  curl_multi_cleanup(multi);
  curl_easy_cleanup(curls);
  curl_global_cleanup();

  if(res)
    i = res;

  return i; /* return the final return code */
}
Exemplo n.º 12
0
Arquivo: lib507.c Projeto: 2px/curl
int test(char *URL)
{
  CURL* curls = NULL;
  CURLM* multi = NULL;
  int still_running;
  int i = -1;
  int res = 0;
  CURLMsg *msg;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  multi_init(multi);

  easy_init(curls);

  easy_setopt(curls, CURLOPT_URL, URL);
  easy_setopt(curls, CURLOPT_HEADER, 1L);

  multi_add_handle(multi, curls);

  multi_perform(multi, &still_running);

  abort_on_test_timeout();

  while(still_running) {
    struct timeval timeout;
    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd = -99;

    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    abort_on_test_timeout();

    multi_perform(multi, &still_running);

    abort_on_test_timeout();
  }

  msg = curl_multi_info_read(multi, &still_running);
  if(msg)
    /* this should now contain a result code from the easy handle,
       get it */
    i = msg->data.result;

test_cleanup:

  /* undocumented cleanup sequence - type UA */

  curl_multi_cleanup(multi);
  curl_easy_cleanup(curls);
  curl_global_cleanup();

  if(res)
    i = res;

  return i; /* return the final return code */
}
Exemplo n.º 13
0
int test(char *URL)
{
  int res = 0;
  CURL *curl[NUM_HANDLES];
  int running;
  CURLM *m = NULL;
  int current = 0;
  int i;

  for(i=0; i < NUM_HANDLES; i++)
    curl[i] = NULL;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  /* get NUM_HANDLES easy handles */
  for(i=0; i < NUM_HANDLES; i++) {
    easy_init(curl[i]);
    /* specify target */
    easy_setopt(curl[i], CURLOPT_URL, URL);
    /* go verbose */
    easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
  }

  multi_init(m);

  multi_add_handle(m, curl[current]);

  fprintf(stderr, "Start at URL 0\n");

  for(;;) {
    struct timeval interval;
    fd_set rd, wr, exc;
    int maxfd = -99;

    interval.tv_sec = 1;
    interval.tv_usec = 0;

    multi_perform(m, &running);

    abort_on_test_timeout();

    if(!running) {
#ifdef LIB527
      /* NOTE: this code does not remove the handle from the multi handle
         here, which would be the nice, sane and documented way of working.
         This however tests that the API survives this abuse gracefully. */
      curl_easy_cleanup(curl[current]);
      curl[current] = NULL;
#endif
      if(++current < NUM_HANDLES) {
        fprintf(stderr, "Advancing to URL %d\n", current);
#ifdef LIB532
        /* first remove the only handle we use */
        curl_multi_remove_handle(m, curl[0]);

        /* make us re-use the same handle all the time, and try resetting
           the handle first too */
        curl_easy_reset(curl[0]);
        easy_setopt(curl[0], CURLOPT_URL, URL);
        /* go verbose */
        easy_setopt(curl[0], CURLOPT_VERBOSE, 1L);

        /* re-add it */
        multi_add_handle(m, curl[0]);
#else
        multi_add_handle(m, curl[current]);
#endif
      }
      else {
        break; /* done */
      }
    }

    FD_ZERO(&rd);
    FD_ZERO(&wr);
    FD_ZERO(&exc);

    multi_fdset(m, &rd, &wr, &exc, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd+1, &rd, &wr, &exc, &interval);

    abort_on_test_timeout();
  }

test_cleanup:

#if defined(LIB526)

  /* test 526 and 528 */
  /* proper cleanup sequence - type PB */

  for(i=0; i < NUM_HANDLES; i++) {
    curl_multi_remove_handle(m, curl[i]);
    curl_easy_cleanup(curl[i]);
  }
  curl_multi_cleanup(m);
  curl_global_cleanup();

#elif defined(LIB527)

  /* test 527 */

  /* Upon non-failure test flow the easy's have already been cleanup'ed. In
     case there is a failure we arrive here with easy's that have not been
     cleanup'ed yet, in this case we have to cleanup them or otherwise these
     will be leaked, let's use undocumented cleanup sequence - type UB */

  if(res)
    for(i=0; i < NUM_HANDLES; i++)
      curl_easy_cleanup(curl[i]);

  curl_multi_cleanup(m);
  curl_global_cleanup();

#elif defined(LIB532)

  /* test 532 */
  /* undocumented cleanup sequence - type UB */

  for(i=0; i < NUM_HANDLES; i++)
    curl_easy_cleanup(curl[i]);
  curl_multi_cleanup(m);
  curl_global_cleanup();

#endif

  return res;
}
Exemplo n.º 14
0
int test(char *URL)
{
  int res = 0;
  CURL *curl[NUM_HANDLES];
  int running;
  CURLM *m = NULL;
  int i;
  char target_url[256];
  char dnsentry[256];
  struct curl_slist *slist = NULL;
  char *port = libtest_arg3;
  char *address = libtest_arg2;

  (void)URL;

  /* Create fake DNS entries for serverX.example.com for all handles */
  for(i=0; i < NUM_HANDLES; i++) {
    sprintf(dnsentry, "server%d.example.com:%s:%s", i + 1, port, address);
    printf("%s\n", dnsentry);
    slist = curl_slist_append(slist, dnsentry);
  }

  for(i=0; i < NUM_HANDLES; i++)
    curl[i] = NULL;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  multi_init(m);

  multi_setopt(m, CURLMOPT_MAXCONNECTS, 3);

  /* get NUM_HANDLES easy handles */
  for(i=0; i < NUM_HANDLES; i++) {
    /* get an easy handle */
    easy_init(curl[i]);
    /* specify target */
    sprintf(target_url, "http://server%d.example.com:%s/path/1506%04i",
            i + 1, port, i + 1);
    target_url[sizeof(target_url) - 1] = '\0';
    easy_setopt(curl[i], CURLOPT_URL, target_url);
    /* go verbose */
    easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
    /* include headers */
    easy_setopt(curl[i], CURLOPT_HEADER, 1L);

    easy_setopt(curl[i], CURLOPT_RESOLVE, slist);
  }

  fprintf(stderr, "Start at URL 0\n");

  for(i=0; i < NUM_HANDLES; i++) {
    /* add handle to multi */
    multi_add_handle(m, curl[i]);

    for(;;) {
      struct timeval interval;
      fd_set rd, wr, exc;
      int maxfd = -99;

      interval.tv_sec = 1;
      interval.tv_usec = 0;

      multi_perform(m, &running);

      abort_on_test_timeout();

      if(!running)
        break; /* done */

      FD_ZERO(&rd);
      FD_ZERO(&wr);
      FD_ZERO(&exc);

      multi_fdset(m, &rd, &wr, &exc, &maxfd);

      /* At this point, maxfd is guaranteed to be greater or equal than -1. */

      select_test(maxfd+1, &rd, &wr, &exc, &interval);

      abort_on_test_timeout();
    }
  }

test_cleanup:

  /* proper cleanup sequence - type PB */

  for(i=0; i < NUM_HANDLES; i++) {
    curl_multi_remove_handle(m, curl[i]);
    curl_easy_cleanup(curl[i]);
  }

  curl_slist_free_all(slist);

  curl_multi_cleanup(m);
  curl_global_cleanup();

  return res;
}
Exemplo n.º 15
0
int test(char *URL)
{
  CURL* easy = NULL;
  CURLM* multi = NULL;
  int still_running;
  int res = 0;

  char redirect[160];

  /* DNS cache injection */
  struct curl_slist *dns_cache_list;

  sprintf(redirect, "google.com:%s:%s", libtest_arg2, libtest_arg3);

  start_test_timing();

  dns_cache_list = curl_slist_append(NULL, redirect);
  if(!dns_cache_list) {
    fprintf(stderr, "curl_slist_append() failed\n");
    return TEST_ERR_MAJOR_BAD;
  }

  res_global_init(CURL_GLOBAL_ALL);
  if(res) {
    curl_slist_free_all(dns_cache_list);
    return res;
  }

  easy_init(easy);

  easy_setopt(easy, CURLOPT_URL, URL);
  easy_setopt(easy, CURLOPT_HEADER, 1L);
  easy_setopt(easy, CURLOPT_RESOLVE, dns_cache_list);

  multi_init(multi);

  multi_add_handle(multi, easy);

  multi_perform(multi, &still_running);

  abort_on_test_timeout();

  while(still_running) {
    struct timeval timeout;
    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd = -99;

    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    abort_on_test_timeout();

    multi_perform(multi, &still_running);

    abort_on_test_timeout();
  }

test_cleanup:

#ifdef LIB1502
  /* undocumented cleanup sequence - type UA */
  curl_multi_cleanup(multi);
  curl_easy_cleanup(easy);
  curl_global_cleanup();
#endif

#ifdef LIB1503
  /* proper cleanup sequence - type PA */
  curl_multi_remove_handle(multi, easy);
  curl_multi_cleanup(multi);
  curl_easy_cleanup(easy);
  curl_global_cleanup();
#endif

#ifdef LIB1504
  /* undocumented cleanup sequence - type UB */
  curl_easy_cleanup(easy);
  curl_multi_cleanup(multi);
  curl_global_cleanup();
#endif

#ifdef LIB1505
  /* proper cleanup sequence - type PB */
  curl_multi_remove_handle(multi, easy);
  curl_easy_cleanup(easy);
  curl_multi_cleanup(multi);
  curl_global_cleanup();
#endif

  curl_slist_free_all(dns_cache_list);

  return res;
}
Exemplo n.º 16
0
/*
 * Source code in here hugely as reported in bug report 651464 by
 * Christopher R. Palmer.
 *
 * Use multi interface to get document over proxy with bad port number.
 * This caused the interface to "hang" in libcurl 7.10.2.
 */
int test(char *URL)
{
  CURL *c = NULL;
  int res = 0;
  CURLM *m = NULL;
  fd_set rd, wr, exc;
  int running;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  easy_init(c);

  /* The point here is that there must not be anything running on the given
     proxy port */
  if (libtest_arg2)
    easy_setopt(c, CURLOPT_PROXY, libtest_arg2);
  easy_setopt(c, CURLOPT_URL, URL);
  easy_setopt(c, CURLOPT_VERBOSE, 1L);

  multi_init(m);

  multi_add_handle(m, c);

  for(;;) {
    struct timeval interval;
    int maxfd = -99;

    interval.tv_sec = 1;
    interval.tv_usec = 0;

    fprintf(stderr, "curl_multi_perform()\n");

    multi_perform(m, &running);

    abort_on_test_timeout();

    if(!running) {
      /* This is where this code is expected to reach */
      int numleft;
      CURLMsg *msg = curl_multi_info_read(m, &numleft);
      fprintf(stderr, "Expected: not running\n");
      if(msg && !numleft)
        res = TEST_ERR_SUCCESS; /* this is where we should be */
      else
        res = TEST_ERR_FAILURE; /* not correct */
      break; /* done */
    }
    fprintf(stderr, "running == %d\n", running);

    FD_ZERO(&rd);
    FD_ZERO(&wr);
    FD_ZERO(&exc);

    fprintf(stderr, "curl_multi_fdset()\n");

    multi_fdset(m, &rd, &wr, &exc, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd+1, &rd, &wr, &exc, &interval);

    abort_on_test_timeout();
  }

test_cleanup:

  /* proper cleanup sequence - type PA */

  curl_multi_remove_handle(m, c);
  curl_multi_cleanup(m);
  curl_easy_cleanup(c);
  curl_global_cleanup();

  return res;
}
Exemplo n.º 17
0
int test(char *URL)
{
    CURL *handle = NULL;
    CURLM *mhandle = NULL;
    int res = 0;
    int still_running = 0;

    start_test_timing();

    global_init(CURL_GLOBAL_ALL);

    easy_init(handle);

    easy_setopt(handle, CURLOPT_URL, URL);
    easy_setopt(handle, CURLOPT_VERBOSE, 1L);

    multi_init(mhandle);

    multi_add_handle(mhandle, handle);

    multi_perform(mhandle, &still_running);

    abort_on_test_timeout();

    while(still_running) {
        struct timeval timeout;
        fd_set fdread;
        fd_set fdwrite;
        fd_set fdexcep;
        int maxfd = -99;
        struct timeval before;
        struct timeval after;
        int e;

        timeout.tv_sec = 0;
        timeout.tv_usec = 100000L; /* 100 ms */

        FD_ZERO(&fdread);
        FD_ZERO(&fdwrite);
        FD_ZERO(&fdexcep);

        multi_fdset(mhandle, &fdread, &fdwrite, &fdexcep, &maxfd);

        /* At this point, maxfd is guaranteed to be greater or equal than -1. */

        select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

        abort_on_test_timeout();

        fprintf(stderr, "ping\n");
        before = tutil_tvnow();

        multi_perform(mhandle, &still_running);

        abort_on_test_timeout();

        after = tutil_tvnow();
        e = elapsed(&before, &after);
        fprintf(stderr, "pong = %d\n", e);

        if(e > MAX_BLOCKED_TIME_US) {
            res = 100;
            break;
        }
    }

test_cleanup:

    /* undocumented cleanup sequence - type UA */

    curl_multi_cleanup(mhandle);
    curl_easy_cleanup(handle);
    curl_global_cleanup();

    return res;
}
Exemplo n.º 18
0
int test(char *URL)
{
  CURL *easy = NULL;
  CURLM *multi = NULL;
  int res = 0;
  int running;
  int msgs_left;
  int phase;
  CURLMsg *msg;

  start_test_timing();

  res_global_init(CURL_GLOBAL_ALL);
  if(res) {
    return res;
  }

  easy_init(easy);

  multi_init(multi);

  for (phase = CONNECT_ONLY_PHASE; phase < LAST_PHASE; ++phase) {
    /* go verbose */
    easy_setopt(easy, CURLOPT_VERBOSE, 1L);

    /* specify target */
    easy_setopt(easy, CURLOPT_URL, URL);

    /* enable 'CONNECT_ONLY' option when in connect phase */
    if (phase == CONNECT_ONLY_PHASE)
      easy_setopt(easy, CURLOPT_CONNECT_ONLY, 1L);

    /* enable 'NOBODY' option to send 'QUIT' command in quit phase */
    if (phase == QUIT_PHASE) {
      easy_setopt(easy, CURLOPT_CONNECT_ONLY, 0L);
      easy_setopt(easy, CURLOPT_NOBODY, 1L);
      easy_setopt(easy, CURLOPT_FORBID_REUSE, 1L);
    }

    multi_add_handle(multi, easy);

    for(;;) {
      struct timeval interval;
      fd_set fdread;
      fd_set fdwrite;
      fd_set fdexcep;
      long timeout = -99;
      int maxfd = -99;

      multi_perform(multi, &running);

      abort_on_test_timeout();

      if(!running)
        break; /* done */

      FD_ZERO(&fdread);
      FD_ZERO(&fdwrite);
      FD_ZERO(&fdexcep);

      multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);

      /* At this point, maxfd is guaranteed to be greater or equal than -1. */

      multi_timeout(multi, &timeout);

      /* At this point, timeout is guaranteed to be greater or equal than -1. */

      if(timeout != -1L) {
        int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
        interval.tv_sec = itimeout/1000;
        interval.tv_usec = (itimeout%1000)*1000;
      }
      else {
        interval.tv_sec = TEST_HANG_TIMEOUT/1000+1;
        interval.tv_usec = 0;
      }

      select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);

      abort_on_test_timeout();
    }

    msg = curl_multi_info_read(multi, &msgs_left);
    if(msg)
      res = msg->data.result;

    multi_remove_handle(multi, easy);
  }

test_cleanup:

  /* undocumented cleanup sequence - type UA */

  curl_multi_cleanup(multi);
  curl_easy_cleanup(easy);
  curl_global_cleanup();

  return res;
}
Exemplo n.º 19
0
int test(char *URL)
{
  int res = 0;
  CURL *curl = NULL;
  int running;
  CURLM *m = NULL;
  int current = 0;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  easy_init(curl);

  easy_setopt(curl, CURLOPT_URL, URL);
  easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  easy_setopt(curl, CURLOPT_FAILONERROR, 1L);

  multi_init(m);

  multi_add_handle(m, curl);

  fprintf(stderr, "Start at URL 0\n");

  for(;;) {
    struct timeval interval;
    fd_set rd, wr, exc;
    int maxfd = -99;

    interval.tv_sec = 1;
    interval.tv_usec = 0;

    multi_perform(m, &running);

    abort_on_test_timeout();

    if(!running) {
      if(!current++) {
        fprintf(stderr, "Advancing to URL 1\n");
        /* remove the handle we use */
        curl_multi_remove_handle(m, curl);

        /* make us re-use the same handle all the time, and try resetting
           the handle first too */
        curl_easy_reset(curl);
        easy_setopt(curl, CURLOPT_URL, libtest_arg2);
        easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        easy_setopt(curl, CURLOPT_FAILONERROR, 1L);

        /* re-add it */
        multi_add_handle(m, curl);
      }
      else
        break; /* done */
    }

    FD_ZERO(&rd);
    FD_ZERO(&wr);
    FD_ZERO(&exc);

    multi_fdset(m, &rd, &wr, &exc, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd + 1, &rd, &wr, &exc, &interval);

    abort_on_test_timeout();
  }

test_cleanup:

  /* undocumented cleanup sequence - type UB */

  curl_easy_cleanup(curl);
  curl_multi_cleanup(m);
  curl_global_cleanup();

  return res;
}
Exemplo n.º 20
0
int test(char *URL)
{
  CURL *c = NULL;
  CURLM *m = NULL;
  int res = 0;
  int running;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  easy_init(c);

  easy_setopt(c, CURLOPT_PROXY, libtest_arg2); /* set in first.c */
  easy_setopt(c, CURLOPT_URL, URL);
  easy_setopt(c, CURLOPT_USERPWD, "test:ing");
  easy_setopt(c, CURLOPT_PROXYUSERPWD, "test:ing");
  easy_setopt(c, CURLOPT_HTTPPROXYTUNNEL, 1L);
  easy_setopt(c, CURLOPT_HEADER, 1L);
  easy_setopt(c, CURLOPT_VERBOSE, 1L);

  multi_init(m);

  multi_add_handle(m, c);

  for(;;) {
    struct timeval interval;
    fd_set rd, wr, exc;
    int maxfd = -99;

    interval.tv_sec = 1;
    interval.tv_usec = 0;

    multi_perform(m, &running);

    abort_on_test_timeout();

    if(!running)
      break; /* done */

    FD_ZERO(&rd);
    FD_ZERO(&wr);
    FD_ZERO(&exc);

    multi_fdset(m, &rd, &wr, &exc, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd + 1, &rd, &wr, &exc, &interval);

    abort_on_test_timeout();
  }

test_cleanup:

  /* proper cleanup sequence - type PA */

  curl_multi_remove_handle(m, c);
  curl_multi_cleanup(m);
  curl_easy_cleanup(c);
  curl_global_cleanup();

  return res;
}
int test(char *URL)
{
  int res = 0;
  CURL *curl = NULL;
  FILE *hd_src = NULL;
  int hd;
  struct_stat file_info;
  CURLM *m = NULL;
  int running;

  start_test_timing();

  if(!libtest_arg2) {
#ifdef LIB529
    /* test 529 */
    fprintf(stderr, "Usage: lib529 [url] [uploadfile]\n");
#else
    /* test 525 */
    fprintf(stderr, "Usage: lib525 [url] [uploadfile]\n");
#endif
    return TEST_ERR_USAGE;
  }

  hd_src = fopen(libtest_arg2, "rb");
  if(NULL == hd_src) {
    fprintf(stderr, "fopen failed with error: %d (%s)\n",
            errno, strerror(errno));
    fprintf(stderr, "Error opening file: (%s)\n", libtest_arg2);
    return TEST_ERR_FOPEN;
  }

  /* get the file size of the local file */
  hd = fstat(fileno(hd_src), &file_info);
  if(hd == -1) {
    /* can't open file, bail out */
    fprintf(stderr, "fstat() failed with error: %d (%s)\n",
            errno, strerror(errno));
    fprintf(stderr, "ERROR: cannot open file (%s)\n", libtest_arg2);
    fclose(hd_src);
    return TEST_ERR_FSTAT;
  }

  res_global_init(CURL_GLOBAL_ALL);
  if(res) {
    fclose(hd_src);
    return res;
  }

  easy_init(curl);

  /* enable uploading */
  easy_setopt(curl, CURLOPT_UPLOAD, 1L);

  /* specify target */
  easy_setopt(curl, CURLOPT_URL, URL);

  /* go verbose */
  easy_setopt(curl, CURLOPT_VERBOSE, 1L);

  /* use active FTP */
  easy_setopt(curl, CURLOPT_FTPPORT, "-");

  /* now specify which file to upload */
  easy_setopt(curl, CURLOPT_READDATA, hd_src);

  /* NOTE: if you want this code to work on Windows with libcurl as a DLL, you
     MUST also provide a read callback with CURLOPT_READFUNCTION. Failing to
     do so will give you a crash since a DLL may not use the variable's memory
     when passed in to it from an app like this. */

  /* Set the size of the file to upload (optional).  If you give a *_LARGE
     option you MUST make sure that the type of the passed-in argument is a
     curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must
     make sure that to pass in a type 'long' argument. */
  easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);

  multi_init(m);

  multi_add_handle(m, curl);

  for(;;) {
    struct timeval interval;
    fd_set rd, wr, exc;
    int maxfd = -99;

    interval.tv_sec = 1;
    interval.tv_usec = 0;

    multi_perform(m, &running);

    abort_on_test_timeout();

    if(!running)
      break; /* done */

    FD_ZERO(&rd);
    FD_ZERO(&wr);
    FD_ZERO(&exc);

    multi_fdset(m, &rd, &wr, &exc, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd+1, &rd, &wr, &exc, &interval);

    abort_on_test_timeout();
  }

test_cleanup:

#ifdef LIB529
  /* test 529 */
  /* proper cleanup sequence - type PA */
  curl_multi_remove_handle(m, curl);
  curl_multi_cleanup(m);
  curl_easy_cleanup(curl);
  curl_global_cleanup();
#else
  /* test 525 */
  /* proper cleanup sequence - type PB */
  curl_multi_remove_handle(m, curl);
  curl_easy_cleanup(curl);
  curl_multi_cleanup(m);
  curl_global_cleanup();
#endif

  /* close the local file */
  fclose(hd_src);

  return res;
}
Exemplo n.º 22
0
int test(char *URL)
{
  CURL *handle = NULL;
  CURL *duphandle = NULL;
  CURLM *mhandle = NULL;
  int res = 0;
  int still_running = 0;

  start_test_timing();

  global_init(CURL_GLOBAL_ALL);

  easy_init(handle);

  easy_setopt(handle, CURLOPT_URL, URL);
  easy_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
  easy_setopt(handle, CURLOPT_VERBOSE, 1L);

  res = curl_easy_perform(handle);
  if(res)
    goto test_cleanup;

  res = curl_easy_perform(handle);
  if(res)
    goto test_cleanup;

  duphandle = curl_easy_duphandle(handle);
  if(!duphandle)
    goto test_cleanup;
  curl_easy_cleanup(handle);
  handle = duphandle;

  multi_init(mhandle);

  multi_add_handle(mhandle, handle);

  multi_perform(mhandle, &still_running);

  abort_on_test_timeout();

  while(still_running) {
    struct timeval timeout;
    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd = -99;

    timeout.tv_sec = 0;
    timeout.tv_usec = 100000L; /* 100 ms */

    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);

    multi_fdset(mhandle, &fdread, &fdwrite, &fdexcep, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);

    abort_on_test_timeout();

    multi_perform(mhandle, &still_running);

    abort_on_test_timeout();
  }

test_cleanup:

  /* undocumented cleanup sequence - type UA */

  curl_multi_cleanup(mhandle);
  curl_easy_cleanup(handle);
  curl_global_cleanup();

  return res;
}
Exemplo n.º 23
0
/*
 * Simply download a HTTPS file!
 *
 * This test was added after the HTTPS-using-multi-interface with OpenSSL
 * regression of 7.19.1 to hopefully prevent this embarassing mistake from
 * appearing again... Unfortunately the bug wasn't triggered by this test,
 * which presumably is because the connect to a local server is too
 * fast/different compared to the real/distant servers we saw the bug happen
 * with.
 */
int test(char *URL)
{
  CURL *http_handle = NULL;
  CURLM *multi_handle = NULL;
  int res = 0;

  int still_running; /* keep number of running handles */

  start_test_timing();

  /*
  ** curl_global_init called indirectly from curl_easy_init.
  */

  easy_init(http_handle);

  /* set options */
  easy_setopt(http_handle, CURLOPT_URL, URL);
  easy_setopt(http_handle, CURLOPT_HEADER, 1L);
  easy_setopt(http_handle, CURLOPT_SSL_VERIFYPEER, 0L);
  easy_setopt(http_handle, CURLOPT_SSL_VERIFYHOST, 0L);

  /* init a multi stack */
  multi_init(multi_handle);

  /* add the individual transfers */
  multi_add_handle(multi_handle, http_handle);

  /* we start some action by calling perform right away */
  multi_perform(multi_handle, &still_running);

  abort_on_test_timeout();

  while(still_running) {
    struct timeval timeout;

    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd = -99;

    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);

    /* set a suitable timeout to play around with */
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    /* get file descriptors from the transfers */
    multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

    /* At this point, maxfd is guaranteed to be greater or equal than -1. */

    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    abort_on_test_timeout();

    /* timeout or readable/writable sockets */
    multi_perform(multi_handle, &still_running);

    abort_on_test_timeout();
  }

test_cleanup:

  /* undocumented cleanup sequence - type UA */

  curl_multi_cleanup(multi_handle);
  curl_easy_cleanup(http_handle);
  curl_global_cleanup();

  return res;
}