Ejemplo n.º 1
0
static int
testExternalGet ()
{
  struct MHD_Daemon *d;
  CURL *c;
  char buf[2048];
  struct CBC cbc;
  CURLM *multi;
  CURLMcode mret;
  fd_set rs;
  fd_set ws;
  fd_set es;
  MHD_socket maxsock;
#ifdef MHD_WINSOCK_SOCKETS
  int maxposixs; /* Max socket number unused on W32 */
#else  /* MHD_POSIX_SOCKETS */
#define maxposixs maxsock
#endif /* MHD_POSIX_SOCKETS */
  int running;
  struct CURLMsg *msg;
  time_t start;
  struct timeval tv;
  int i;
  MHD_socket fd;

  multi = NULL;
  cbc.buf = buf;
  cbc.size = 2048;
  cbc.pos = 0;
  d = MHD_start_daemon (MHD_USE_DEBUG,
                        11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
  if (d == NULL)
    return 256;
  c = setupCURL(&cbc);

  multi = curl_multi_init ();
  if (multi == NULL)
    {
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 512;
    }
  mret = curl_multi_add_handle (multi, c);
  if (mret != CURLM_OK)
    {
      curl_multi_cleanup (multi);
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 1024;
    }

  for (i = 0; i < 2; i++) {
    start = time (NULL);
    while ((time (NULL) - start < 5) && (multi != NULL))
      {
        maxsock = MHD_INVALID_SOCKET;
        maxposixs = -1;
        FD_ZERO (&rs);
        FD_ZERO (&ws);
        FD_ZERO (&es);
        curl_multi_perform (multi, &running);
        mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
        if (mret != CURLM_OK)
          {
            curl_multi_remove_handle (multi, c);
            curl_multi_cleanup (multi);
            curl_easy_cleanup (c);
            MHD_stop_daemon (d);
            return 2048;
          }
        if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock))
          {
            curl_multi_remove_handle (multi, c);
            curl_multi_cleanup (multi);
            curl_easy_cleanup (c);
            MHD_stop_daemon (d);
            return 4096;
          }
        tv.tv_sec = 0;
        tv.tv_usec = 1000;
        select (maxposixs + 1, &rs, &ws, &es, &tv);
        curl_multi_perform (multi, &running);
        if (running == 0)
          {
            msg = curl_multi_info_read (multi, &running);
            if (msg == NULL)
              break;
            if (msg->msg == CURLMSG_DONE)
              {
                if (i == 0 && msg->data.result != CURLE_OK)
                  printf ("%s failed at %s:%d: `%s'\n",
                          "curl_multi_perform",
                          __FILE__,
                          __LINE__, curl_easy_strerror (msg->data.result));
                else if (i == 1 && msg->data.result == CURLE_OK)
                  printf ("%s should have failed at %s:%d\n",
                          "curl_multi_perform",
                          __FILE__,
                          __LINE__);
                curl_multi_remove_handle (multi, c);
                curl_multi_cleanup (multi);
                curl_easy_cleanup (c);
                c = NULL;
                multi = NULL;
              }
          }
        MHD_run (d);
      }

      if (i == 0) {
        /* quiesce the daemon on the 1st iteration, so the 2nd should fail */
        fd = MHD_quiesce_daemon(d);
        if (MHD_INVALID_SOCKET == fd)
          {
            fprintf (stderr,
                     "MHD_quiesce_daemon failed.\n");
            curl_multi_remove_handle (multi, c);
            curl_multi_cleanup (multi);
            curl_easy_cleanup (c);
            MHD_stop_daemon (d);
            return 2;
          }
        c = setupCURL (&cbc);
        multi = curl_multi_init ();
        mret = curl_multi_add_handle (multi, c);
        if (mret != CURLM_OK)
        {
          curl_multi_remove_handle (multi, c);
          curl_multi_cleanup (multi);
          curl_easy_cleanup (c);
          MHD_stop_daemon (d);
          return 32768;
        }
      }
    }
  if (multi != NULL)
    {
      curl_multi_remove_handle (multi, c);
      curl_easy_cleanup (c);
      curl_multi_cleanup (multi);
    }
  MHD_stop_daemon (d);
  MHD_socket_close_ (fd);
  if (cbc.pos != strlen ("/hello_world"))
    return 8192;
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    return 16384;
  return 0;
}
Ejemplo n.º 2
0
/***************************************************************************
 * This function is still only for testing purposes. It makes a great way
 * to run the full test suite on the multi interface instead of the easy one.
 ***************************************************************************
 *
 * The *new* curl_easy_perform() is the external interface that performs a
 * transfer previously setup.
 *
 * Wrapper-function that: creates a multi handle, adds the easy handle to it,
 * runs curl_multi_perform() until the transfer is done, then detaches the
 * easy handle, destroys the multi handle and returns the easy handle's return
 * code. This will make everything internally use and assume multi interface.
 */
CURLcode curl_easy_perform(CURL *easy)
{
  CURLM *multi;
  CURLMcode mcode;
  CURLcode code = CURLE_OK;
  int still_running;
  struct timeval timeout;
  int rc;
  CURLMsg *msg;
  fd_set fdread;
  fd_set fdwrite;
  fd_set fdexcep;
  int maxfd;

  if(!easy)
    return CURLE_BAD_FUNCTION_ARGUMENT;

  multi = curl_multi_init();
  if(!multi)
    return CURLE_OUT_OF_MEMORY;

  mcode = curl_multi_add_handle(multi, easy);
  if(mcode) {
    curl_multi_cleanup(multi);
    if(mcode == CURLM_OUT_OF_MEMORY)
      return CURLE_OUT_OF_MEMORY;
    else
      return CURLE_FAILED_INIT;
  }

  /* we start some action by calling perform right away */

  do {
    while(CURLM_CALL_MULTI_PERFORM ==
          curl_multi_perform(multi, &still_running));

    if(!still_running)
      break;

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

    /* timeout once per second */
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    /* Old deprecated style: get file descriptors from the transfers */
    curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
    rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    /* The way is to extract the sockets and wait for them without using
       select. This whole alternative version should probably rather use the
       curl_multi_socket() approach. */

    if(rc == -1)
      /* select error */
      break;

    /* timeout or data to send/receive => loop! */
  } while(still_running);

  msg = curl_multi_info_read(multi, &rc);
  if(msg)
    code = msg->data.result;

  mcode = curl_multi_remove_handle(multi, easy);
  /* what to do if it fails? */

  mcode = curl_multi_cleanup(multi);
  /* what to do if it fails? */

  return code;
}
Ejemplo n.º 3
0
/*
 * Simply download two HTTP files!
 */
int main(int argc, char **argv)
{
  CURL *http_handle;
  CURL *http_handle2;
  CURLM *multi_handle;

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

  http_handle = curl_easy_init();
  http_handle2 = curl_easy_init();

  /* set options */
  curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");

  /* set options */
  curl_easy_setopt(http_handle2, CURLOPT_URL, "http://localhost/");

  /* init a multi stack */
  multi_handle = curl_multi_init();

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

  /* we start some action by calling perform right away */
  while(CURLM_CALL_MULTI_PERFORM ==
        curl_multi_perform(multi_handle, &still_running));

  while(still_running) {
    struct timeval timeout;
    int rc; /* select() return code */

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

    long curl_timeo = -1;

    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;

    curl_multi_timeout(multi_handle, &curl_timeo);
    if(curl_timeo >= 0) {
      timeout.tv_sec = curl_timeo / 1000;
      if(timeout.tv_sec > 1)
        timeout.tv_sec = 1;
      else
        timeout.tv_usec = (curl_timeo % 1000) * 1000;
    }

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

    /* In a real-world program you OF COURSE check the return code of the
       function calls.  On success, the value of maxfd is guaranteed to be
       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
       case of (maxfd == -1), we call select(0, ...), which is basically equal
       to sleep. */

    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    switch(rc) {
    case -1:
      /* select error */
      break;
    case 0:
    default:
      /* timeout or readable/writable sockets */
      while(CURLM_CALL_MULTI_PERFORM ==
            curl_multi_perform(multi_handle, &still_running));
      break;
    }
  }

  curl_multi_cleanup(multi_handle);

  curl_easy_cleanup(http_handle);
  curl_easy_cleanup(http_handle2);

  return 0;
}
Ejemplo n.º 4
0
int main(int argc, char *argv[])
{
  CURL *curl;

  CURLM *multi_handle;
  int still_running;

  struct curl_httppost *formpost=NULL;
  struct curl_httppost *lastptr=NULL;
  struct curl_slist *headerlist=NULL;
  static const char buf[] = "Expect:";

  /* Fill in the file upload field. This makes libcurl load data from  
     the given file name when curl_easy_perform() is called. */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, "sendfile",
               CURLFORM_FILE, "postit2.c",
               CURLFORM_END);

  /* Fill in the filename field */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, "filename",
               CURLFORM_COPYCONTENTS, "postit2.c",
               CURLFORM_END);

  /* Fill in the submit field too, even if this is rarely needed */
  curl_formadd(&formpost,
               &lastptr,
               CURLFORM_COPYNAME, "submit",
               CURLFORM_COPYCONTENTS, "send",
               CURLFORM_END);

  curl = curl_easy_init();
  multi_handle = curl_multi_init();

  /* initalize custom header list (stating that Expect: 100-continue is not
     wanted */
  headerlist = curl_slist_append(headerlist, buf);
  if(curl && multi_handle) {

    /* what URL that receives this POST */
    curl_easy_setopt(curl, CURLOPT_URL,
                     "http://www.fillinyoururl.com/upload.cgi");
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

    curl_multi_add_handle(multi_handle, curl);

    while(CURLM_CALL_MULTI_PERFORM ==
          curl_multi_perform(multi_handle, &still_running));

    while(still_running) {
      struct timeval timeout;
      int rc; /* select() return code */

      fd_set fdread;
      fd_set fdwrite;
      fd_set fdexcep;
      int maxfd;

      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 */
      curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

      /* In a real-world program you OF COURSE check the return code of the
         function calls, *and* you make sure that maxfd is bigger than -1
         so that the call to select() below makes sense! */

      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

      switch(rc) {
      case -1:
        /* select error */
        break;
      case 0:
        printf("timeout!\n");
      default:
        /* timeout or readable/writable sockets */
        printf("perform!\n");
        while(CURLM_CALL_MULTI_PERFORM ==
              curl_multi_perform(multi_handle, &still_running));
        printf("running: %d!\n", still_running);
        break;
      }
    }

    curl_multi_cleanup(multi_handle);

    /* always cleanup */
    curl_easy_cleanup(curl);

    /* then cleanup the formpost chain */
    curl_formfree(formpost);

    /* free slist */
    curl_slist_free_all (headerlist);
  }
  return 0;
}
Ejemplo n.º 5
0
// overloaded to additionally move data to/from the webserver
void LLHTTPAssetStorage::checkForTimeouts()
{
	CURLMcode mcode;
	LLAssetRequest *req;
	while ( (req = findNextRequest(mPendingDownloads, mRunningDownloads)) )
	{
		// Setup this curl download request
		// We need to generate a new request here
		// since the one in the list could go away
		char tmp_url[MAX_STRING]; /*Flawfinder: ignore*/
		char uuid_str[UUID_STR_LENGTH]; /*Flawfinder: ignore*/
		req->getUUID().toString(uuid_str);
		std::string base_url = getBaseURL(req->getUUID(), req->getType());
		snprintf(tmp_url, sizeof(tmp_url), "%s/%36s.%s", base_url.c_str() , uuid_str, LLAssetType::lookup(req->getType()));	/* Flawfinder: ignore */

		LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), 
										req->getType(), RT_DOWNLOAD, tmp_url, mCurlMultiHandle);
		new_req->mTmpUUID.generate();

		// Sets pending download flag internally
		new_req->setupCurlHandle();
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_FOLLOWLOCATION, TRUE);
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &curlDownCallback);
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEDATA, new_req->mCurlHandle);
	
		mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle);
		if (mcode > CURLM_OK)
		{
			// Failure.  Deleting the pending request will remove it from the running
			// queue, and push it to the end of the pending queue.
			new_req->cleanupCurlHandle();
			deletePendingRequest(RT_DOWNLOAD, new_req->getType(), new_req->getUUID());
			break;
		}
		else
		{
			llinfos << "Requesting " << new_req->mURLBuffer << llendl;
		}
	}

	while ( (req = findNextRequest(mPendingUploads, mRunningUploads)) )
	{
		// setup this curl upload request

		bool do_compress = req->getType() == LLAssetType::AT_OBJECT;

		char tmp_url[MAX_STRING];/*Flawfinder: ignore*/
		char uuid_str[UUID_STR_LENGTH];/*Flawfinder: ignore*/
		req->getUUID().toString(uuid_str);
		snprintf(tmp_url, sizeof(tmp_url), 					/* Flawfinder: ignore */
				do_compress ? "%s/%s.%s.gz" : "%s/%s.%s",
				mBaseURL.c_str(), uuid_str, LLAssetType::lookup(req->getType())); 

		LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), 
									req->getType(), RT_UPLOAD, tmp_url, mCurlMultiHandle);
		if (do_compress)
		{
			new_req->prepareCompressedUpload();
		}

		// Sets pending upload flag internally
		new_req->setupCurlHandle();
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_UPLOAD, 1);
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &nullOutputCallback);

		if (do_compress)
		{
			curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION,
					&LLHTTPAssetRequest::curlCompressedUploadCallback);
		}
		else
		{
			LLVFile file(mVFS, req->getUUID(), req->getType());
			curl_easy_setopt(new_req->mCurlHandle, CURLOPT_INFILESIZE, file.getSize());
			curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION,
					&curlUpCallback);
		}
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READDATA, new_req->mCurlHandle);
	
		mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle);
		if (mcode > CURLM_OK)
		{
			// Failure.  Deleting the pending request will remove it from the running
			// queue, and push it to the end of the pending queue.
			new_req->cleanupCurlHandle();
			deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID());
			break;
		}
		else
		{
			llinfos << "Requesting PUT " << new_req->mURLBuffer << llendl;
		}
		// Pending upload will have been flagged by the request
	}

	while ( (req = findNextRequest(mPendingLocalUploads, mRunningLocalUploads)) )
	{
		// setup this curl upload request
		LLVFile file(mVFS, req->getUUID(), req->getType());

		char tmp_url[MAX_STRING]; /*Flawfinder: ignore*/
		char uuid_str[UUID_STR_LENGTH]; /*Flawfinder: ignore*/
		req->getUUID().toString(uuid_str);
		
		// KLW - All temporary uploads are saved locally "http://localhost:12041/asset"
		snprintf(tmp_url, sizeof(tmp_url), "%s/%36s.%s", mLocalBaseURL.c_str(), uuid_str, LLAssetType::lookup(req->getType())); 	/* Flawfinder: ignore */

		LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), 
										req->getType(), RT_LOCALUPLOAD, tmp_url, mCurlMultiHandle);
		new_req->mRequestingAgentID = req->mRequestingAgentID;

		// Sets pending upload flag internally
		new_req->setupCurlHandle();
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_PUT, 1);
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_INFILESIZE, file.getSize());
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &nullOutputCallback);
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION, &curlUpCallback);
		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READDATA, new_req->mCurlHandle);
	
		mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle);
		if (mcode > CURLM_OK)
		{
			// Failure.  Deleting the pending request will remove it from the running
			// queue, and push it to the end of the pending queue.
			new_req->cleanupCurlHandle();
			deletePendingRequest(RT_LOCALUPLOAD, new_req->getType(), new_req->getUUID());
			break;
		}
		else
		{
			llinfos << "TAT: LLHTTPAssetStorage::checkForTimeouts() : pending local!"
				<< " Requesting PUT " << new_req->mURLBuffer << llendl;
		}
		// Pending upload will have been flagged by the request
	}
	S32 count = 0;
	int queue_length;
	do
	{
		mcode = curl_multi_perform(mCurlMultiHandle, &queue_length);
		count++;
	} while (mcode == CURLM_CALL_MULTI_PERFORM && (count < 5));

	CURLMsg *curl_msg;
	do
	{
		curl_msg = curl_multi_info_read(mCurlMultiHandle, &queue_length);
		if (curl_msg && curl_msg->msg == CURLMSG_DONE)
		{
			long curl_result = 0;
			S32 xfer_result = 0;

			LLHTTPAssetRequest *req = NULL;
			curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_PRIVATE, &req);
								
			curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_HTTP_CODE, &curl_result);
			if (RT_UPLOAD == req->mRequestType || RT_LOCALUPLOAD == req->mRequestType)
			{
				if (curl_msg->data.result == CURLE_OK && 
					(   curl_result == HTTP_OK 
					 || curl_result == HTTP_PUT_OK 
					 || curl_result == HTTP_NO_CONTENT))
				{
					llinfos << "Success uploading " << req->getUUID() << " to " << req->mURLBuffer << llendl;
					if (RT_LOCALUPLOAD == req->mRequestType)
					{
						addTempAssetData(req->getUUID(), req->mRequestingAgentID, mHostName);
					}
				}
				else if (curl_msg->data.result == CURLE_COULDNT_CONNECT ||
						curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
						curl_result == HTTP_SERVER_BAD_GATEWAY ||
						curl_result == HTTP_SERVER_TEMP_UNAVAILABLE)
				{
					llwarns << "Re-requesting upload for " << req->getUUID() << ".  Received upload error to " << req->mURLBuffer <<
						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl;
				}
				else
				{
					llwarns << "Failure uploading " << req->getUUID() << " to " << req->mURLBuffer <<
						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl;

					xfer_result = LL_ERR_ASSET_REQUEST_FAILED;
				}

				if (!(curl_msg->data.result == CURLE_COULDNT_CONNECT ||
						curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
						curl_result == HTTP_SERVER_BAD_GATEWAY ||
						curl_result == HTTP_SERVER_TEMP_UNAVAILABLE))
				{
					// shared upload finished callback
					// in the base class, this is called from processUploadComplete
					_callUploadCallbacks(req->getUUID(), req->getType(), (xfer_result == 0));
					// Pending upload flag will get cleared when the request is deleted
				}
			}
			else if (RT_DOWNLOAD == req->mRequestType)
			{
				if (curl_result == HTTP_OK && curl_msg->data.result == CURLE_OK)
				{
					if (req->mVFile && req->mVFile->getSize() > 0)
					{					
						llinfos << "Success downloading " << req->mURLBuffer << ", size " << req->mVFile->getSize() << llendl;

						req->mVFile->rename(req->getUUID(), req->getType());
					}
					else
					{
						// *TODO: if this actually indicates a bad asset on the server
						// (not certain at this point), then delete it
						llwarns << "Found " << req->mURLBuffer << " to be zero size" << llendl;
						xfer_result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
					}
				}
				else
				{
					// KLW - TAT See if an avatar owns this texture, and if so request re-upload.
					llwarns << "Failure downloading " << req->mURLBuffer << 
						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl;

					xfer_result = (curl_result == HTTP_MISSING) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;

					if (req->mVFile)
					{
						req->mVFile->remove();
					}
				}

				// call the static callback for transfer completion
				// this will cleanup all requests for this asset, including ours
				downloadCompleteCallback(
					xfer_result,
					req->getUUID(),
					req->getType(),
					(void *)req);
				// Pending download flag will get cleared when the request is deleted
			}
			else
			{
				// nothing, just axe this request
				// currently this can only mean an asset delete
			}

			// Deleting clears the pending upload/download flag if it's set and the request is transferring
			delete req;
			req = NULL;
		}

	} while (curl_msg && queue_length > 0);
	

	// Cleanup 
	// We want to bump to the back of the line any running uploads that have timed out.
	bumpTimedOutUploads();

	LLAssetStorage::checkForTimeouts();
}
Ejemplo n.º 6
0
/*
 * Simply download a HTTP file.
 */
int main(int argc, char **argv)
{
  CURL *http_handle;
  CURLM *multi_handle;

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

  http_handle = curl_easy_init();

  /* set the options (I left out a few, you'll get the point anyway) */
  curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");

  /* init a multi stack */
  multi_handle = curl_multi_init();

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

  /* we start some action by calling perform right away */
  while(CURLM_CALL_MULTI_PERFORM ==
        curl_multi_perform(multi_handle, &still_running));

  while(still_running) {
    struct timeval timeout;
    int rc; /* select() return code */

    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd;

    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 */
    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

    /* In a real-world program you OF COURSE check the return code of the
       function calls, *and* you make sure that maxfd is bigger than -1 so
       that the call to select() below makes sense! */

    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    switch(rc) {
    case -1:
      /* select error */
      still_running = 0;
      printf("select() returns error, this is badness\n");
      break;
    case 0:
    default:
      /* timeout or readable/writable sockets */
      while(CURLM_CALL_MULTI_PERFORM ==
            curl_multi_perform(multi_handle, &still_running));
      break;
    }
  }

  curl_multi_cleanup(multi_handle);

  curl_easy_cleanup(http_handle);

  return 0;
}
Ejemplo n.º 7
0
/**
 * Execute a command using Curl's multi interface
 * 
 * @param sdb the SimpleDB handle
 * @param cmd the command name
 * @param _params the parameters
 * @param next_token the next token (optional)
 * @param user_data the user data (optional)
 * @param user_data_2 the user data (optional)
 * @return the handle to the deferred call, or SDB_MULTI_ERROR on error 
 */
sdb_multi sdb_execute_multi(struct SDB* sdb, const char* cmd, struct sdb_params* _params, char* next_token, void* user_data, void* user_data_2)
{
	// Prepare the command execution
	
	struct sdb_params* params = sdb_params_alloc(_params->size + 8);
	if (SDB_FAILED(sdb_params_add(params, "Action", cmd))) return SDB_MULTI_ERROR;
	char timestamp[32]; sdb_timestamp(timestamp);
	if (SDB_FAILED(sdb_params_add(params, "Timestamp", timestamp))) return SDB_MULTI_ERROR;
	
	
	// Add the command parameters
	
	if (SDB_FAILED(sdb_params_add_all(params, _params))) return SDB_MULTI_ERROR;
	
	
	// Add the next token
	
	if (next_token != NULL) {
		if (SDB_FAILED(sdb_params_add(params, "NextToken", next_token))) return SDB_MULTI_ERROR;
	}
	
	
	// Add the required parameters
	
	if (SDB_FAILED(sdb_params_add_required(sdb, params))) return SDB_MULTI_ERROR;
	char* post = sdb_post(sdb, params);
	long postsize = strlen(post);
	sdb_params_free(params);
	
	
	// Allocate a multi-data structure
	
	struct sdb_multi_data* m = sdb_multi_alloc(sdb);
	assert(m);
	
	m->post = post;
	strncpy(m->command, cmd, SDB_LEN_COMMAND - 1);
	m->command[SDB_LEN_COMMAND - 1] = '\0';
	m->params = sdb_params_deep_copy(_params);
	m->user_data = user_data;
	m->user_data_2 = user_data_2;
	m->post_size = postsize;
	
	
	// Create a Curl handle and defer it
	
	sdb->rec.size = 0;
	curl_easy_setopt(m->curl, CURLOPT_URL, AWS_URL);
	curl_easy_setopt(m->curl, CURLOPT_WRITEDATA, &m->rec);
	curl_easy_setopt(m->curl, CURLOPT_POST, 1L);
	curl_easy_setopt(m->curl, CURLOPT_POSTFIELDS, post);
	CURLMcode cr = curl_multi_add_handle(sdb->curl_multi, m->curl);
	
	
	// Handle Curl errors
	
	if (cr != CURLM_OK) {
		sdb_multi_free_one(sdb, m);
		return SDB_MULTI_ERROR;
	}
	
	
	// Statistics (the size statistics would be updated when the response is received)
	
	sdb->stat.num_commands++;
	if (strncmp(cmd, "Put", 3) == 0) sdb->stat.num_puts++;
	
	
	return m->curl;
}
Ejemplo n.º 8
0
Archivo: lib575.c Proyecto: dims/curl
int test(char *URL)
{
    CURLMcode m;
    CURL *handle = NULL, *duphandle;
    CURLM *mhandle = NULL;
    int res = 0;
    int still_running = 0;

    if(curl_global_init(CURL_GLOBAL_ALL)) {
        fprintf(stderr, "curl_global_init() failed\n");
        goto test_cleanup;
    }

    handle = curl_easy_init();
    if(!handle) {
        res = CURLE_OUT_OF_MEMORY;
        goto test_cleanup;
    }

    test_setopt(handle, CURLOPT_URL, URL);
    test_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
    test_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;

    mhandle = curl_multi_init();
    if(!mhandle) {
        fprintf(stderr, "curl_multi_init() failed\n");
        goto test_cleanup;
    }

    curl_multi_add_handle(mhandle, handle);

    curl_multi_perform(mhandle, &still_running);

    while(still_running) {
        static struct timeval timeout = { /* 100 ms */
            0, 100000L
        };
        int rc;
        fd_set fdread;
        fd_set fdwrite;
        fd_set fdexcep;
        int max_fdset = -1;
        FD_ZERO(&fdread);
        FD_ZERO(&fdwrite);
        FD_ZERO(&fdexcep);

        m = curl_multi_fdset(mhandle, &fdread, &fdwrite, &fdexcep, &max_fdset);
        if(m != CURLM_OK) {
            fprintf(stderr, "curl_multi_fdset() error\n");
            goto test_cleanup;
        }
        /* We call select(max_fdset + 1, ...), specially in case of (maxfd == -1),
         * we call select(0, ...), which is basically equal to sleep. */
        rc = select(max_fdset + 1, &fdread, &fdwrite, &fdexcep, &timeout);
        if(rc == -1) {
            fprintf(stderr, "select() error\n");
            goto test_cleanup;
        }
        else {
            curl_multi_perform(mhandle, &still_running);
        }
    }

test_cleanup:
    if(mhandle)
        curl_multi_cleanup(mhandle);
    if(handle)
        curl_easy_cleanup(handle);
    curl_global_cleanup();
    return res;
}
Ejemplo n.º 9
0
void ConnectionManager::registerEasyHandle(CURL *easy) const {
	curl_multi_add_handle(_multi, easy);
}
Ejemplo n.º 10
0
int cetcd_multi_watch(cetcd_client *cli) {
    int           i, count;
    int           maxfd, left, added;
    long          timeout;
    long          backoff, backoff_max;
    fd_set        r, w, e;
    cetcd_array   *watchers;
    cetcd_watcher *watcher;
    CURLM         *mcurl;

    struct timeval tv;

    mcurl = curl_multi_init();
    watchers = &cli->watchers;
    count = cetcd_array_size(watchers);
    for (i = 0; i < count; ++i) {
        watcher = cetcd_array_get(watchers, i);
        curl_easy_setopt(watcher->curl, CURLOPT_PRIVATE, watcher);
        curl_multi_add_handle(mcurl, watcher->curl);
    }
    backoff = 100; /*100ms*/
    backoff_max = 1000; /*1 sec*/
    for(;;) {
        curl_multi_perform(mcurl, &left);
        if (left) {
            FD_ZERO(&r);
            FD_ZERO(&w);
            FD_ZERO(&e);
            curl_multi_fdset(mcurl, &r, &w, &e, &maxfd);
            curl_multi_timeout(mcurl, &timeout);
            if (timeout == -1) {
                timeout = 100; /*wait for 0.1 seconds*/
            }
            tv.tv_sec = timeout/1000;
            tv.tv_usec = (timeout%1000)*1000;

            /*TODO handle errors*/
            select(maxfd+1, &r, &w, &e, &tv);
        }
        added = cetcd_reap_watchers(cli, mcurl);
        if (added == 0 && left == 0) {
        /* It will call curl_multi_perform immediately if:
         * 1. left is 0
         * 2. a new attempt should be issued
         * It is expected to sleep a mount time between attempts.
         * So we fix this by increasing added counter only
         * when a new request should be issued.
         * When added is 0, maybe there are retring requests or nothing.
         * Either situations should wait before issuing the request.
         * */
            if (backoff < backoff_max) {
                backoff = 2 * backoff;
            } else {
                backoff = backoff_max;
            }
            tv.tv_sec = backoff/1000;
            tv.tv_usec = (backoff%1000) * 1000;
            select(1, 0, 0, 0, &tv);
        }
    }
    curl_multi_cleanup(mcurl);
    return count;
}
Ejemplo n.º 11
0
bool HTTPClient::Init(void* _ptr) {
	if(_ptr) {
		is_raise_error_multi_handle = true;
		code_multi = *(CURLMcode*)_ptr;
		return true;
	}
	if(is_raise_error_multi_handle)
		return true;
	
	//디비에서 URL이랑 매치되는 필드가져오기
	sqlite3* _db = NULL;
	char* _db_message = NULL;
	HTTP_DEBUG((sqlite3_open(HTTPManager::Share()->GetDBPath().c_str(), &_db)),
			   "sqlite 디비 열기에 실패하였습니다." << opened_file << "\nError Message:" << sqlite3_errmsg(_db) << "\n");
	std::string _query = "SELECT * FROM request WHERE url='" + request.url + "' LIMIT 1";
	HTTP_DEBUG((sqlite3_exec(_db, _query.c_str(), SQLMatchURLCallback, this, &_db_message)),
			   "sqllite 디비 검색에 실패하였습니다." << "\nError Message:" << _db_message);
	HTTP_DEBUG((sqlite3_close(_db)),
			   "sqlite 디비 닫기에 실패하였습니다." << "\nError Message:" << sqlite3_errmsg(_db) << "\n");
	
	if(db_id.length()) {
		if(db_expires > HTTP::CurrentTime()) {
			//저장된것 사용
			cache_type = HTTPResponse::CacheType_Expires;
		} else if(db_max_age > 0) {
			if(last_updated - db_last_updated < db_max_age) {
				//저장된것 사용
				cache_type = HTTPResponse::CacheType_Expires;
			} else {
				//연결(이후 Last-Modified로 캐쉬 체크)
				cache_type = HTTPResponse::CacheType_Last_Modified;
			}
		} else {
			//연결(이후 Last-Modified로 캐쉬 체크)
			cache_type = HTTPResponse::CacheType_Last_Modified;
		}
	} else {
		//처음 다운
		cache_type = HTTPResponse::CacheType_None;
	}
	
	if(!request.use_cache)
		cache_type = HTTPResponse::CacheType_None;
	
	//파일 준비
	ReadyFile();

#ifdef ANDROID_NDK
    if (is_https)
        return true;
#endif
    
	//연결이 필요한경우는 curl생성
	if(cache_type != HTTPResponse::CacheType_Expires)
		curl = curl_easy_init();
	
	if(curl) {
		curl_easy_setopt(curl, CURLOPT_URL, request.GetURL().c_str());
		
		ReadyHeader();
		ReadyBody();
		
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPClient::ReadBody);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
		curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, ReadHeader);
		curl_easy_setopt(curl, CURLOPT_WRITEHEADER, this);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
		
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, HTTPClient::Progress);
		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this);
		
		curl_multi_add_handle(HTTPManager::Share()->GetCURLMulti(), curl);
	}
	
	return true;
}
Ejemplo n.º 12
0
static int cetcd_reap_watchers(cetcd_client *cli, CURLM *mcurl) {
    int     added, ignore;
    CURLMsg *msg;
    CURL    *curl;
    cetcd_string url;
    cetcd_watcher *watcher;
    cetcd_response *resp;
    added = 0;
    while ((msg = curl_multi_info_read(mcurl, &ignore)) != NULL) {
        if (msg->msg == CURLMSG_DONE) {
            curl = msg->easy_handle;
            curl_easy_getinfo(curl, CURLINFO_PRIVATE, &watcher);

            resp = watcher->parser->resp;
            if (msg->data.result != CURLE_OK) {
                /*try next in round-robin ways*/
                /*FIXME There is a race condition if multiple watchers failed*/
                if (watcher->attempts) {
                    cli->picked = (cli->picked+1)%(cetcd_array_size(cli->addresses));
                    url = cetcd_watcher_build_url(cli, watcher);
                    curl_easy_setopt(watcher->curl, CURLOPT_URL, url);
                    sdsfree(url);
                    curl_multi_remove_handle(mcurl, curl);
                    curl_multi_add_handle(mcurl, curl);
                    /*++added;
                     *watcher->attempts --;
                     */
                    continue;
                } else {
                    resp->err = calloc(1, sizeof(cetcd_error));
                    resp->err->ecode = error_cluster_failed;
                    resp->err->message = sdsnew("cetcd_reap_watchers: all cluster servers failed.");
                }
            }
            if (watcher->callback) {
                watcher->callback(watcher->userdata, resp);
                if (resp->err) {
                    curl_multi_remove_handle(mcurl, curl);
                    cetcd_watcher_release(watcher);
                    break;
                }
                cetcd_response_release(resp);
                watcher->parser->resp = NULL; /*surpress it be freed again by cetcd_watcher_release*/
            }
            if (!watcher->once) {
                sdsclear(watcher->parser->buf);
                watcher->parser->st = 0;
                watcher->parser->resp = calloc(1, sizeof(cetcd_response));
                if (watcher->index) {
                    watcher->index ++;
                    url = cetcd_watcher_build_url(cli, watcher);
                    curl_easy_setopt(watcher->curl, CURLOPT_URL, url);
                    sdsfree(url);
                }
                curl_multi_remove_handle(mcurl, curl);
                curl_multi_add_handle(mcurl, curl);
                ++added;
                continue;
            }
            curl_multi_remove_handle(mcurl, curl);
            cetcd_watcher_release(watcher);
        }
    }
    return added;
}
Ejemplo n.º 13
0
bool HTTP::Request(const std::string & url, std::ostream & error_output)
{
	if (!multihandle)
	{
		error_output << "HTTP::Request: multihandle initialization failed" << std::endl;
		return false;
	}
    
	// Each single transfer is built up with an easy handle.
	CURL * easyhandle = curl_easy_init();
    
	if (easyhandle)
	{
		// Setup the appropriate options for the easy handle.
		curl_easy_setopt(easyhandle, CURLOPT_URL, url.c_str());
        
		// This function call will make this multi_handle control the specified easy_handle.
		// Furthermore, libcurl now initiates the connection associated with the specified easy_handle.
		CURLMcode result = curl_multi_add_handle(multihandle, easyhandle);
        
		if (result == CURLM_OK)
		{
			// Open the destination file for write.
			std::string filepart = ExtractFilenameFromUrl(url);
			if (filepart.empty())
			{
				error_output << "HTTP::Request: url \"" << url << "\" is invalid" << std::endl;
				curl_multi_remove_handle(multihandle, easyhandle);
				return false;
			}
            
			std::string filename = folder+"/"+filepart;
			FILE * file = fopen(filename.c_str(),"wb");
			if (!file)
			{
				error_output << "HTTP::Request: unable to open \"" << filename << "\" for writing" << std::endl;
				curl_multi_remove_handle(multihandle, easyhandle);
				return false;
			}
            
			// Setup file writing.
			curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);
			curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, file);
            
			// Begin tracking the easyhandle.
			REQUEST requestinfo(url,file);
			requestinfo.progress_callback_data.http = this;
			requestinfo.progress_callback_data.easyhandle = easyhandle;
			easyhandles.insert(std::make_pair(easyhandle,requestinfo));
			requests.insert(std::make_pair(url,HTTPINFO()));
            
			// Setup the progress callback.
			curl_easy_setopt(easyhandle, CURLOPT_NOPROGRESS, 0);
			curl_easy_setopt(easyhandle, CURLOPT_PROGRESSFUNCTION, ProgressCallback);
			curl_easy_setopt(easyhandle, CURLOPT_PROGRESSDATA, &(easyhandles.find(easyhandle)->second.progress_callback_data));
            
			return true;
		}
		else
		{
			// Tell the multihandle to forget the handle.
			curl_multi_remove_handle(multihandle, easyhandle);

			error_output << "HTTP::Request: CURL is unable to request URL \"" << url << "\"" << std::endl;
			return false;
		}
	}
	else
	{
		error_output << "HTTP::Request: easyhandle initialization failed" << std::endl;
		return false;
	}
}
Ejemplo n.º 14
0
static DWORD WINAPI vdf_threadfunc(LPVOID _unused) {
#else
static void *vdf_threadfunc(void *_unused) {
#endif
	while(1) {
		if(vdf_transport_start(trans) == 0) {
			while(vdf_transport_process(trans) == 0);
		} else {
			printf("Retrying NBD connect...\n");
			sleep(2);
		}
	}
	return 0;
}

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

	if(argc != 3) {
		fprintf(stderr, "Usage: %s <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");
	paused = stopped = 1;

	curl_multi = curl_multi_init();
//	curl_multi_add_handle(curl_multi, curl_handle);

	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;
	paused = stopped = 1;

	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[1], argv[2]);
	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
#ifdef _WIN32
	if(CreateThread(NULL, 0, vdf_threadfunc, NULL, 0, &tid) == NULL) {
		perror("CreateThread");
		return 1;
	}
#else
	if(pthread_create(&thd, NULL, vdf_threadfunc, NULL) == -1) {
		perror("pthread_create");
		return 1;
	}
#endif

	while(fgets(line, LINE_MAX, stdin) != NULL) {
		if((p = strchr(line, '\r')) != NULL)
			*p = 0;
		if((p = strchr(line, '\n')) != NULL)
			*p = 0;
		switch(line[0]) {
			case '>':
				paused = 1;
				if(line[1] != 0) {
					if(!stopped)
						curl_multi_remove_handle(curl_multi, curl_handle);
					stopped = 0;
					printf("Open URL: '%s'\n", line + 1);
					curl_easy_setopt(curl_handle, CURLOPT_URL, line + 1);
					curl_multi_add_handle(curl_multi, curl_handle);
				} else {
					if(stopped)
						continue;
					printf("Resume\n");
				}
				paused = stopped = 0;
				break;
			case '!':
				printf("Stop\n");
				stopped = paused = 1;
				sleep(200);
				bend = bstart = 0;
				curl_multi_remove_handle(curl_multi, curl_handle);
				break;
			case '#':
				printf("Pause\n");
				paused = 1;
				break;
		}
	}
	return 0;
}
Ejemplo n.º 15
0
int wswcurl_perform()
{
	int ret = 0;
	wswcurl_req *r, *next;

	if (!curlmulti) return 0;

	// process requests in FIFO manner

	// check for timed out requests and requests that need to be paused
	r = http_requests_hnode;
	while( r )
	{
		next = r->prev;

		if (r->status == WSTATUS_QUEUED) {
			// queued
			if (curlmulti_num_handles < WMAXMULTIHANDLES) {
				if (curl_multi_add_handle(curlmulti, r->curl)) {
					CURLDBG(("OOPS: CURL MULTI ADD HANDLE FAIL!!!"));
				}
				r->status = WSTATUS_STARTED;
				r->last_action = wswcurl_now();
				curlmulti_num_handles++;
			}
			else {
				// stay in queue
			}
		}

		// handle pauses for synchronous requests
		if( r->status == WSTATUS_STARTED && !r->callback_read ) {
			if( r->rxreceived >= r->rxreturned + WMAXBUFFERING ) {
				wswcurl_pause( r );
			}
		}

		// handle timeouts
		if( r->status == WSTATUS_STARTED ) {
			time_t now = wswcurl_now();

			if( r->paused ) {
				// paused
				r->last_action = now;
			} else if( r->timeout && ( r->last_action + r->timeout <= now ) ) {
				// timed out
				r->respcode = -1;
				r->status = -CURLE_OPERATION_TIMEDOUT;
				if( r->callback_done ) {
					r->callback_done( r, r->status, r->customp );
				}
			}
		}

		r = next;
	}

	//CURLDBG(("CURL BEFORE MULTI_PERFORM\n"));
	while ( curl_multi_perform(curlmulti, &ret) == CURLM_CALL_MULTI_PERFORM) {
		CURLDBG(("   CURL MULTI LOOP\n"));
	}
	ret += wswcurl_checkmsg();
	//CURLDBG(("CURL after checkmsg\n"));
	return ret;
}
Ejemplo n.º 16
0
Archivo: lib564.c Proyecto: dims/curl
int test(char *URL)
{
  int res = 0;
  CURL *curl;
  int running;
  char done=FALSE;
  CURLM *m = NULL;
  struct timeval ml_start;
  struct timeval mp_start;
  char ml_timedout = FALSE;
  char mp_timedout = FALSE;

  if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
    fprintf(stderr, "curl_global_init() failed\n");
    return TEST_ERR_MAJOR_BAD;
  }

  if ((curl = curl_easy_init()) == NULL) {
    fprintf(stderr, "curl_easy_init() failed\n");
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  test_setopt(curl, CURLOPT_URL, URL);
  test_setopt(curl, CURLOPT_VERBOSE, 1);
  test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
  test_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);

  if ((m = curl_multi_init()) == NULL) {
    fprintf(stderr, "curl_multi_init() failed\n");
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  if ((res = (int)curl_multi_add_handle(m, curl)) != CURLM_OK) {
    fprintf(stderr, "curl_multi_add_handle() failed, "
            "with code %d\n", res);
    curl_multi_cleanup(m);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return TEST_ERR_MAJOR_BAD;
  }

  ml_timedout = FALSE;
  ml_start = tutil_tvnow();

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

  while (!done) {
    fd_set rd, wr, exc;
    int max_fd;
    struct timeval interval;

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

    if (tutil_tvdiff(tutil_tvnow(), ml_start) >
        MAIN_LOOP_HANG_TIMEOUT) {
      ml_timedout = TRUE;
      break;
    }
    mp_timedout = FALSE;
    mp_start = tutil_tvnow();

    res = (int)curl_multi_perform(m, &running);
    if (tutil_tvdiff(tutil_tvnow(), mp_start) >
        MULTI_PERFORM_HANG_TIMEOUT) {
      mp_timedout = TRUE;
      break;
    }
    if (running <= 0) {
      done = TRUE; /* bail out */
      break;
    }

    if (res != CURLM_OK) {
      fprintf(stderr, "not okay???\n");
      break;
    }

    FD_ZERO(&rd);
    FD_ZERO(&wr);
    FD_ZERO(&exc);
    max_fd = 0;

    if (curl_multi_fdset(m, &rd, &wr, &exc, &max_fd) != CURLM_OK) {
      fprintf(stderr, "unexpected failured of fdset.\n");
      res = 189;
      break;
    }

    if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) {
      fprintf(stderr, "bad select??\n");
      res = 195;
      break;
    }
  }

  if (ml_timedout || mp_timedout) {
    if (ml_timedout) fprintf(stderr, "ml_timedout\n");
    if (mp_timedout) fprintf(stderr, "mp_timedout\n");
    fprintf(stderr, "ABORTING TEST, since it seems "
            "that it would have run forever.\n");
    res = TEST_ERR_RUNS_FOREVER;
  }

test_cleanup:

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

  return res;
}
Ejemplo n.º 17
0
static void handler (zsock_t *pipe, void *args) {
    curl_global_init(CURL_GLOBAL_ALL);
    CURLM *multi = curl_multi_init ();
    CURLSH *share = curl_share_init ();
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);

    long verbose = (*(bool *) args) ? 1L : 0L;
    long timeout = 30;
    CURLMcode code;

    SOCKET pipefd = zsock_fd (pipe);
    struct curl_waitfd waitfd = {pipefd, CURL_WAIT_POLLIN};

    //  List to hold pending curl handles, in case we are destroy the client
    //  while request are inprogress
    zlistx_t *pending_handles = zlistx_new ();
    zlistx_set_destructor (pending_handles, (zlistx_destructor_fn *) curl_destructor);

    zsock_signal (pipe, 0);

    bool terminated = false;
    while (!terminated) {
        int events = zsock_events (pipe);
        if ((events & ZMQ_POLLIN) == 0) {
            code = curl_multi_wait (multi, &waitfd, 1, 1000, NULL);
            assert (code == CURLM_OK);
        }

        events = zsock_events (pipe);
        if (events & ZMQ_POLLIN) {
            char* command = zstr_recv (pipe);
            if (!command)
                break;          //  Interrupted

            //  All actors must handle $TERM in this way
            if (streq (command, "$TERM"))
                terminated = true;
            else if (streq (command, "GET")) {
                char *url;
                zlistx_t *headers;
                void *userp;
                int rc = zsock_recv (pipe, "slp", &url, &headers, &userp);
                assert (rc == 0);

                zchunk_t *data = zchunk_new (NULL, 100);
                assert (data);
                struct curl_slist *curl_headers = zlistx_to_slist (headers);
                CURL *curl = curl_easy_init ();
                zlistx_add_end (pending_handles, curl);
                http_request *request = (http_request *) zmalloc (sizeof (http_request));
                assert (request);
                request->userp = userp;
                request->curl = curl;
                request->data = data;
                request->headers = curl_headers;

                curl_easy_setopt (curl, CURLOPT_SHARE, share);
                curl_easy_setopt (curl, CURLOPT_TIMEOUT, timeout);
                curl_easy_setopt (curl, CURLOPT_VERBOSE, verbose);
                curl_easy_setopt (curl, CURLOPT_HTTPHEADER, curl_headers);
                curl_easy_setopt (curl, CURLOPT_URL, url);
                curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data);
                curl_easy_setopt (curl, CURLOPT_WRITEDATA, data);
                curl_easy_setopt (curl, CURLOPT_PRIVATE, request);

                code = curl_multi_add_handle (multi, curl);
                assert (code == CURLM_OK);
                zlistx_destroy (&headers);
                zstr_free (&url);
           }
           else {
               puts ("E: invalid message to actor");
               assert (false);
           }
           zstr_free (&command);
        }

        int still_running;
        code = curl_multi_perform (multi, &still_running);
        assert (code == CURLM_OK);

        int msgq = 0;
        struct CURLMsg *msg = curl_multi_info_read(multi, &msgq);

        while (msg) {
            if(msg->msg == CURLMSG_DONE) {
                CURL *curl = msg->easy_handle;
                http_request *request;
                curl_easy_getinfo(curl, CURLINFO_PRIVATE, &request);

                long response_code_long;
                curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response_code_long);
                int response_code = (int)response_code_long;

                int rc = zsock_send (pipe, "icp", response_code, request->data, request->userp);
                assert (rc == 0);

                curl_multi_remove_handle (multi, curl);

                //  Remove curl from the pending handles and delete it
                void *handle = zlistx_find (pending_handles, curl);
                assert (handle);
                rc = zlistx_delete (pending_handles, handle);
                assert (rc == 0);
            }

            msg = curl_multi_info_read(multi, &msgq);
        }
    }

    zlistx_destroy (&pending_handles);
    curl_share_cleanup (share);
    curl_multi_cleanup (multi);
    curl_global_cleanup ();
}
Ejemplo n.º 18
0
/*
 * Upload all files over HTTP/2, using the same physical connection!
 */
int main(int argc, char **argv)
{
  struct input trans[NUM_HANDLES];
  CURLM *multi_handle;
  int i;
  int still_running = 0; /* keep number of running handles */
  const char *filename = "index.html";
  int num_transfers;

  if(argc > 1) {
    /* if given a number, do that many transfers */
    num_transfers = atoi(argv[1]);

    if(!num_transfers || (num_transfers > NUM_HANDLES))
      num_transfers = 3; /* a suitable low default */

    if(argc > 2)
      /* if given a file name, upload this! */
      filename = argv[2];
  }
  else
    num_transfers = 3;

  /* init a multi stack */
  multi_handle = curl_multi_init();

  for(i = 0; i<num_transfers; i++) {
    setup(&trans[i], i, filename);

    /* add the individual transfer */
    curl_multi_add_handle(multi_handle, trans[i].hnd);
  }

  curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);

  /* We do HTTP/2 so let's stick to one connection per host */
  curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 1L);

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

  while(still_running) {
    struct timeval timeout;
    int rc; /* select() return code */
    CURLMcode mc; /* curl_multi_fdset() return code */

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

    long curl_timeo = -1;

    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;

    curl_multi_timeout(multi_handle, &curl_timeo);
    if(curl_timeo >= 0) {
      timeout.tv_sec = curl_timeo / 1000;
      if(timeout.tv_sec > 1)
        timeout.tv_sec = 1;
      else
        timeout.tv_usec = (curl_timeo % 1000) * 1000;
    }

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

    if(mc != CURLM_OK) {
      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
      break;
    }

    /* On success the value of maxfd is guaranteed to be >= -1. We call
       select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
       no fds ready yet so we call select(0, ...) --or Sleep() on Windows--
       to sleep 100ms, which is the minimum suggested value in the
       curl_multi_fdset() doc. */

    if(maxfd == -1) {
#ifdef _WIN32
      Sleep(100);
      rc = 0;
#else
      /* Portable sleep for platforms other than Windows. */
      struct timeval wait = { 0, 100 * 1000 }; /* 100ms */
      rc = select(0, NULL, NULL, NULL, &wait);
#endif
    }
    else {
      /* Note that on some platforms 'timeout' may be modified by select().
         If you need access to the original value save a copy beforehand. */
      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
    }

    switch(rc) {
    case -1:
      /* select error */
      break;
    case 0:
    default:
      /* timeout or readable/writable sockets */
      curl_multi_perform(multi_handle, &still_running);
      break;
    }
  }

  curl_multi_cleanup(multi_handle);

  for(i = 0; i<num_transfers; i++) {
    curl_multi_remove_handle(multi_handle, trans[i].hnd);
    curl_easy_cleanup(trans[i].hnd);
  }

  return 0;
}
Ejemplo n.º 19
0
static int
testExternalPut ()
{
  struct MHD_Daemon *d;
  CURL *c;
  char buf[2048];
  struct CBC cbc;
  CURLM *multi;
  CURLMcode mret;
  fd_set rs;
  fd_set ws;
  fd_set es;
  int max;
  int running;
  time_t start;
  struct timeval tv;
  unsigned int pos = 0;
  int done_flag = 0;
  int i;

  multi = NULL;
  cbc.buf = buf;
  cbc.size = 2048;
  cbc.pos = 0;
  d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_ERROR_LOG */ ,
                        11080,
                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
  if (d == NULL)
    return 256;
  multi = curl_multi_init ();
  if (multi == NULL)
    {
      MHD_stop_daemon (d);
      return 512;
    }
  zzuf_socat_start ();
  for (i = 0; i < LOOP_COUNT; i++)
    {
      fprintf (stderr, ".");

      c = curl_easy_init ();
      curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11081/hello_world");
      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
      curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
      curl_easy_setopt (c, CURLOPT_READDATA, &pos);
      curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
      curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
      curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
      if (oneone)
        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
      else
        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
      /* NOTE: use of CONNECTTIMEOUT without also
       *   setting NOSIGNAL results in really weird
       *   crashes on my system! */
      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);



      mret = curl_multi_add_handle (multi, c);
      if (mret != CURLM_OK)
        {
          curl_multi_cleanup (multi);
          curl_easy_cleanup (c);
          zzuf_socat_stop ();
          MHD_stop_daemon (d);
          return 1024;
        }
      start = time (NULL);
      while ((time (NULL) - start < 5) && (c != NULL))
        {
          max = 0;
          FD_ZERO (&rs);
          FD_ZERO (&ws);
          FD_ZERO (&es);
          curl_multi_perform (multi, &running);
          mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
          if (mret != CURLM_OK)
            {
              curl_multi_remove_handle (multi, c);
              curl_multi_cleanup (multi);
              curl_easy_cleanup (c);
              zzuf_socat_stop ();
              MHD_stop_daemon (d);
              return 2048;
            }
          if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
            {
              curl_multi_remove_handle (multi, c);
              curl_multi_cleanup (multi);
              curl_easy_cleanup (c);
              zzuf_socat_stop ();
              MHD_stop_daemon (d);
              return 4096;
            }
          tv.tv_sec = 0;
          tv.tv_usec = 1000;
          select (max + 1, &rs, &ws, &es, &tv);
          curl_multi_perform (multi, &running);
          if (running == 0)
            {
              curl_multi_info_read (multi, &running);
              curl_multi_remove_handle (multi, c);
              curl_easy_cleanup (c);
              c = NULL;
            }
          MHD_run (d);
        }
      if (c != NULL)
        {
          curl_multi_remove_handle (multi, c);
          curl_easy_cleanup (c);
        }
    }
  fprintf (stderr, "\n");
  curl_multi_cleanup (multi);
  zzuf_socat_stop ();
  MHD_stop_daemon (d);
  return 0;
}
Ejemplo n.º 20
0
int test(char *URL)
{
  CURLM *cm = NULL;
  CURLSH *sh = NULL;
  CURL *ch = NULL;
  int unfinished;

  cm = curl_multi_init();
  if(!cm)
    return 1;
  sh = curl_share_init();
  if(!sh)
    goto cleanup;

  curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
  curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);

  ch = curl_easy_init();
  if(!ch)
    goto cleanup;

  curl_easy_setopt(ch, CURLOPT_SHARE, sh);
  curl_easy_setopt(ch, CURLOPT_URL, URL);
  curl_easy_setopt(ch, CURLOPT_COOKIEFILE, "log/cookies1905");
  curl_easy_setopt(ch, CURLOPT_COOKIEJAR, "log/cookies1905");

  curl_multi_add_handle(cm, ch);

  unfinished = 1;
  while(unfinished) {
    int MAX = 0;
    long max_tout;
    fd_set R, W, E;
    struct timeval timeout;

    FD_ZERO(&R);
    FD_ZERO(&W);
    FD_ZERO(&E);
    curl_multi_perform(cm, &unfinished);

    curl_multi_fdset(cm, &R, &W, &E, &MAX);
    curl_multi_timeout(cm, &max_tout);

    if(max_tout > 0) {
      timeout.tv_sec = max_tout / 1000;
      timeout.tv_usec = (max_tout % 1000) * 1000;
    }
    else {
      timeout.tv_sec = 0;
      timeout.tv_usec = 1000;
    }

    select(MAX + 1, &R, &W, &E, &timeout);
  }

  curl_easy_setopt(ch, CURLOPT_COOKIELIST, "FLUSH");
  curl_easy_setopt(ch, CURLOPT_SHARE, NULL);

  curl_multi_remove_handle(cm, ch);
  cleanup:
  curl_easy_cleanup(ch);
  curl_share_cleanup(sh);
  curl_multi_cleanup(cm);

  return 0;
}
Ejemplo n.º 21
0
int test( char *URL ) {
	CURL *c;
	CURLM *m;

	curl_global_init( CURL_GLOBAL_ALL );
	c = curl_easy_init();
	curl_easy_setopt( c, CURLOPT_PROXY, arg2 ); /* set in first.c */
	curl_easy_setopt( c, CURLOPT_URL, URL );
	curl_easy_setopt( c, CURLOPT_USERPWD, "test:ing" );
	curl_easy_setopt( c, CURLOPT_PROXYUSERPWD, "test:ing" );
	curl_easy_setopt( c, CURLOPT_HTTPPROXYTUNNEL, 1 );
	curl_easy_setopt( c, CURLOPT_HEADER, 1 );

	{
		CURLMcode res;
		int running;
		char done = FALSE;

		m = curl_multi_init();

		res = curl_multi_add_handle( m, c );

		while ( !done ) {
			fd_set rd, wr, exc;
			int max_fd;
			struct timeval interval;

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

			while ( res == CURLM_CALL_MULTI_PERFORM ) {
				res = curl_multi_perform( m, &running );
				if ( running <= 0 ) {
					done = TRUE;
					break;
				}
			}
			if ( done ) {
				break;
			}

			if ( res != CURLM_OK ) {
				fprintf( stderr, "not okay???\n" );
				break;
			}

			FD_ZERO( &rd );
			FD_ZERO( &wr );
			FD_ZERO( &exc );
			max_fd = 0;

			if ( curl_multi_fdset( m, &rd, &wr, &exc, &max_fd ) != CURLM_OK ) {
				fprintf( stderr, "unexpected failured of fdset.\n" );
				return 89;
			}

			if ( select( max_fd + 1, &rd, &wr, &exc, &interval ) == -1 ) {
				fprintf( stderr, "bad select??\n" );
				return 95;
			}

			res = CURLM_CALL_MULTI_PERFORM;
		}
	}
	curl_multi_remove_handle( m, c );
	curl_easy_cleanup( c );
	curl_multi_cleanup( m );

	return CURLE_OK;
}
int main(int argc, char **argv)
{
	int c;
	int num_handle = 4;
	int img = 1;
	bool received_all_fragments = false;
	bool * received_fragments = calloc(N, sizeof(bool));
	
	bool * tempBoolCheck = calloc(N, sizeof(bool));

	while ((c = getopt (argc, argv, "t:i:")) != -1) {
		switch (c) {
		case 't':
			num_handle = strtoul(optarg, NULL, 10);
			if (num_handle == 0) {
				printf("%s: option requires an argument > 0 -- 't'\n", argv[0]);
				return -1;
			}
			break;
		case 'i':
			img = strtoul(optarg, NULL, 10);
			if (img == 0) {
				printf("%s: option requires an argument > 0 -- 'i'\n", argv[0]);
				return -1;
			}
			break;
		default:
			return -1;
		}
	}


	png_structp png_ptr[num_handle];
	png_infop info_ptr[num_handle];

	png_byte * output_buffer = calloc(WIDTH*HEIGHT*4, sizeof(png_byte));

  //Lock for pthread
  // pthread_mutex_init(&lock, NULL);
   pthread_mutex_init(&lock_hd, NULL);
  // pthread_mutex_init(&lock_read_cb, NULL);

	char * url = malloc(sizeof(char)*strlen(BASE_URL)+4*5);
	char * url_2 = malloc(sizeof(char)*strlen(BASE_URL_2)+4*5);
	char * url_3 = malloc(sizeof(char)*strlen(BASE_URL_3)+4*5);
	
	png_bytep input_buffer[num_handle];

	struct bufdata bd[num_handle];
	struct headerdata hd[num_handle];
	for(int i = 0; i< num_handle; i++)
	{
		input_buffer[i] = malloc(sizeof(png_byte)*BUF_SIZE);
		bd[i].buf = input_buffer[i];
		hd[i].received_fragments = received_fragments;
	}
	// request appropriate URL
	sprintf(url, BASE_URL, img);
	sprintf(url_2, BASE_URL_2, img);
	sprintf(url_3, BASE_URL_3, img);
	printf("requesting URL %s\n", url);

	CURL *handles[num_handle];
	CURLM *multi_handle;
	CURLcode res = 0;
	int running_handles;
	
	CURLMsg *msg; /* for picking up messages with the transfer status */
	int msgs_left; /* how many messages are left */
	
	for (int i = 0; i < num_handle; i++)
	{
		handles[i] = curl_easy_init();
		if(!handles[i])
		{
			abort_("[main] could not initialize curl");
		}
		curl_easy_setopt(handles[i], CURLOPT_WRITEFUNCTION, write_cb);
		curl_easy_setopt(handles[i], CURLOPT_WRITEDATA, &(bd[i]));
		curl_easy_setopt(handles[i], CURLOPT_HEADERDATA, &hd[i]);
		curl_easy_setopt(handles[i], CURLOPT_HEADERFUNCTION, header_cb);
		if(i%3 == 0)
		{
			curl_easy_setopt(handles[i], CURLOPT_URL, url);
		}
		else if(i%3 == 1)
		{
			curl_easy_setopt(handles[i], CURLOPT_URL, url_2);
		}
		else
		{
			curl_easy_setopt(handles[i], CURLOPT_URL, url_3);
		}
		
		//keep pointer to array index
		//curl_easy_setopt(handles[i], CURLOPT_PRIVATE, url);
		// reset input buffer
		bd[i].len = bd[i].pos = 0; bd[i].max_size = BUF_SIZE;
	}



	/* init a multi stack */
	multi_handle = curl_multi_init();
	/* add the individual transfers */
	for (int i = 0; i < num_handle; i++)
	{
		curl_multi_add_handle(multi_handle, handles[i]);
	}
		

		// do curl request; check for errors
		// res = curl_easy_perform(curl);
		// if(res != CURLE_OK)
		// abort_("[main] curl_easy_perform() failed: %s\n",
		// curl_easy_strerror(res));
		

		//curl_multi_perform(multi_handle, &running_handles);
		
		do
		{
			int numfds=0;
			res = curl_multi_wait(multi_handle, NULL, 0, MAX_WAIT_MSECS, &numfds);
			if(res != CURLM_OK) {
				fprintf(stderr, "error: curl_multi_wait() returned %d\n", res);
				return EXIT_FAILURE;
			}
			curl_multi_perform(multi_handle, &running_handles);
 #ifdef _DEBUG_1_
	//printf("\n## numfds: %d, num_handle: %d\n", numfds, num_handle);
	fflush(stdout);
#endif
/* If the amount of running_handles is changed from the previous call (or is less than the amount of easy handles you've added to the multi handle), you know that there is one or more transfers less "running". You can then call curl_multi_info_read to get information about each individual completed transfer, and that returned info includes CURLcode and more. If an added handle fails very quickly, it may never be counted as a running_handle.*/
			if(running_handles < num_handle)
			{
#ifdef _DEBUG_1_
	printf("\nIn IF:, running_handles: %d\n", running_handles);
	fflush(stdout);
#endif
		
				while((msg = curl_multi_info_read(multi_handle, &msgs_left)))
				{
					
#ifdef _DEBUG_1_
	printf("\nmsgs_left:%d\n", msgs_left);
	fflush(stdout);
#endif
					if (msg->msg == CURLMSG_DONE)
					{
						CURL* replaceHandle = msg->easy_handle;
						
												
						curl_multi_remove_handle(multi_handle, replaceHandle);
						curl_multi_add_handle(multi_handle, replaceHandle);
						
						
						int iBdIndex = -1;
						for (int i = 0; i < num_handle; i++)
						{
							if (handles[i] == replaceHandle)
							{
								iBdIndex = i;
#ifdef _DEBUG_1_
	printf("\nfound handle, i:%d", i);
	fflush(stdout);
#endif
								break;
							}
						}
						
						
						res = msg->data.result;
						if(res != CURLE_OK)
						{
#ifdef _DEBUG_1_
	printf("\nContinued in the while loop, res is %d", res);
	fflush(stdout);
#endif
							continue;
							//abort_("[main] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
						}
//check for dup

								// if (received_fragments[hd[iBdIndex].n])
								// {
// #ifdef _DEBUG_1_
		// printf("\nContinued in the while loop, dup for %d", hd[iBdIndex].n);
		// fflush(stdout);
// #endif
									// continue;
								// }
						
						
	//pthread_mutex_lock(&lock);
						png_ptr[iBdIndex] = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
						if (!png_ptr[iBdIndex])
						{
							abort_("[main] png_create_read_struct failed");
						}
  // Write to the shared resource .
						
						// read PNG (as downloaded from network) and copy it to output buffer
#ifdef _DEBUG_1_
	printf("\nindex: %d, bd->pos: %d, bd->len: %d, hd.n: %d\n",iBdIndex, bd[iBdIndex].pos, bd[iBdIndex].len,hd[iBdIndex].n);
	fflush(stdout);
#endif

						png_bytep* row_pointers = read_png_file(png_ptr[iBdIndex], &info_ptr[iBdIndex], &bd[iBdIndex]);
						paint_destination(png_ptr[iBdIndex], row_pointers, hd[iBdIndex].n*BUF_WIDTH, 0, output_buffer);
						// reset input buffer
						bd[iBdIndex].len = bd[iBdIndex].pos = 0; bd[iBdIndex].max_size = BUF_SIZE;

						//bd[1].len = bd[1].pos = 0; bd[1].max_size = BUF_SIZE;
						// free allocated memory
						for (int y=0; y<BUF_HEIGHT; y++)
						{
							free(row_pointers[y]);
						}
						free(row_pointers);
						png_destroy_read_struct(&png_ptr[iBdIndex], &info_ptr[iBdIndex], NULL);

						// check for unreceived fragments
						received_all_fragments = true;
						for (int i = 0; i < N; i++)
						{
							if (!received_fragments[i])
							{
								received_all_fragments = false;
							}
						}
						
						//tempBoolCheck
						tempBoolCheck[hd[iBdIndex].n]=true;
						for(int i = 0; i < N; i++)
						{
							if(!tempBoolCheck[i])
							{
								received_all_fragments=false;
							}
						}
	//pthread_mutex_unlock(&lock);
					}
					else
					{
						//Error, replace the handle
						#ifdef _DEBUG_1_
	printf("\nError, replace the handle\n");
	fflush(stdout);
#endif
						CURL* replaceHandle = msg->easy_handle;
						curl_multi_remove_handle(multi_handle, replaceHandle);
						curl_multi_add_handle(multi_handle, replaceHandle);
						for (int i = 0; i < num_handle; i++)
						{
							if (handles[i] == replaceHandle)
							{
								bd[i].len = bd[i].pos = 0; bd[i].max_size = BUF_SIZE;
								break;
							}
						}
					}
					//break;
				}
			}

		} while(!received_all_fragments);
		
	free(url);
	free(url_2);
	free(url_3);
	//free(input_buffer);
	

	//curl_easy_cleanup(curl);
	curl_multi_cleanup(multi_handle);
	/* Free the CURL handles */
	for (int i=0; i<num_handle; i++)
	{
		free(input_buffer[i]);
		curl_easy_cleanup(handles[i]);
	}

	// now, write the array back to disk using write_png_file
	png_bytep * output_row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * HEIGHT);

	for (int i = 0; i < HEIGHT; i++)
		output_row_pointers[i] = &output_buffer[i*WIDTH*4];

	write_png_file("output.png", output_row_pointers);
	free(output_row_pointers);
	free(output_buffer);
	free(received_fragments);
	
	  //destory lock
  	// pthread_mutex_destroy(&lock);
	 pthread_mutex_destroy(&lock_hd);
	// pthread_mutex_destroy(&lock_read_cb);

	return 0;
}
Ejemplo n.º 23
0
// blocking asset fetch which bypasses the VFS
// this is a very limited function for use by the simstate loader and other one-offs
S32 LLHTTPAssetStorage::getURLToFile(const LLUUID& uuid, LLAssetType::EType asset_type, const LLString &url, const char *filename, progress_callback callback, void *userdata)
{
	// *NOTE: There is no guarantee that the uuid and the asset_type match
	// - not that it matters. - Doug
	lldebugs << "LLHTTPAssetStorage::getURLToFile() - " << url << llendl;

	FILE *fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/
	if (! fp)
	{
		llwarns << "Failed to open " << filename << " for writing" << llendl;
		return LL_ERR_ASSET_REQUEST_FAILED;
	}

	// make sure we use the normal curl setup, even though we don't really need a request object
	LLHTTPAssetRequest req(this, uuid, asset_type, RT_DOWNLOAD, url.c_str(), mCurlMultiHandle);
	req.mFP = fp;
	
	req.setupCurlHandle();
	curl_easy_setopt(req.mCurlHandle, CURLOPT_FOLLOWLOCATION, TRUE);
	curl_easy_setopt(req.mCurlHandle, CURLOPT_WRITEFUNCTION, &curlFileDownCallback);
	curl_easy_setopt(req.mCurlHandle, CURLOPT_WRITEDATA, req.mCurlHandle);

	curl_multi_add_handle(mCurlMultiHandle, req.mCurlHandle);
	llinfos << "Requesting as file " << req.mURLBuffer << llendl;

	// braindead curl loop
	int queue_length;
	CURLMsg *curl_msg;
	LLTimer timeout;
	timeout.setTimerExpirySec(GET_URL_TO_FILE_TIMEOUT);
	bool success = false;
	S32 xfer_result = 0;
	do
	{
		curl_multi_perform(mCurlMultiHandle, &queue_length);
		curl_msg = curl_multi_info_read(mCurlMultiHandle, &queue_length);

		if (callback)
		{
			callback(userdata);
		}

		if ( curl_msg && (CURLMSG_DONE == curl_msg->msg) )
		{
			success = true;
		}
		else if (timeout.hasExpired())
		{
			llwarns << "Request for " << url << " has timed out." << llendl;
			success = false;
			xfer_result = LL_ERR_ASSET_REQUEST_FAILED;
			break;
		}
	} while (!success);

	if (success)
	{
		long curl_result = 0;
		curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_HTTP_CODE, &curl_result);
		
		if (curl_result == HTTP_OK && curl_msg->data.result == CURLE_OK)
		{
			S32 size = ftell(req.mFP);
			if (size > 0)
			{
				// everything seems to be in order
				llinfos << "Success downloading " << req.mURLBuffer << " to file, size " << size << llendl;
			}
			else
			{
				llwarns << "Found " << req.mURLBuffer << " to be zero size" << llendl;
				xfer_result = LL_ERR_ASSET_REQUEST_FAILED;
			}
		}
		else
		{
			xfer_result = curl_result == HTTP_MISSING ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
			llinfos << "Failure downloading " << req.mURLBuffer << 
				" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl;
		}
	}

	fclose(fp);
	if (xfer_result)
	{
		LLFile::remove(filename);
	}
	return xfer_result;
}
Ejemplo n.º 24
0
static int
testExternalGet ()
{
  struct MHD_Daemon *d;
  CURL *c;
  char buf[2048];
  struct CBC cbc;
  CURLM *multi;
  CURLMcode mret;
  fd_set rs;
  fd_set ws;
  fd_set es;
  MHD_socket maxsock;
#ifdef MHD_WINSOCK_SOCKETS
  int maxposixs; /* Max socket number unused on W32 */
#else  /* MHD_POSIX_SOCKETS */
#define maxposixs maxsock
#endif /* MHD_POSIX_SOCKETS */
  int running;
  struct CURLMsg *msg;
  time_t start;
  struct timeval tv;

  multi = NULL;
  cbc.buf = buf;
  cbc.size = 2048;
  cbc.pos = 0;
  d = MHD_start_daemon (MHD_USE_ERROR_LOG,
                        21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
  if (d == NULL)
    return 256;
  c = curl_easy_init ();
  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:21080/hello_world");
  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
  if (oneone)
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  else
    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
  /* NOTE: use of CONNECTTIMEOUT without also
     setting NOSIGNAL results in really weird
     crashes on my system! */
  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);


  multi = curl_multi_init ();
  if (multi == NULL)
    {
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 512;
    }
  mret = curl_multi_add_handle (multi, c);
  if (mret != CURLM_OK)
    {
      curl_multi_cleanup (multi);
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 1024;
    }
  start = time (NULL);
  while ((time (NULL) - start < 5) && (multi != NULL))
    {
      maxsock = MHD_INVALID_SOCKET;
      maxposixs = -1;
      FD_ZERO (&rs);
      FD_ZERO (&ws);
      FD_ZERO (&es);
      curl_multi_perform (multi, &running);
      mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
      if (mret != CURLM_OK)
        {
          curl_multi_remove_handle (multi, c);
          curl_multi_cleanup (multi);
          curl_easy_cleanup (c);
          MHD_stop_daemon (d);
          return 2048;
        }
      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock))
        {
          curl_multi_remove_handle (multi, c);
          curl_multi_cleanup (multi);
          curl_easy_cleanup (c);
          MHD_stop_daemon (d);
          return 4096;
        }
      tv.tv_sec = 0;
      tv.tv_usec = 1000;
      if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv))
        {
          if (EINTR != errno)
            abort ();
        }
      curl_multi_perform (multi, &running);
      if (running == 0)
        {
          msg = curl_multi_info_read (multi, &running);
          if (msg == NULL)
            break;
          if (msg->msg == CURLMSG_DONE)
            {
              if (msg->data.result != CURLE_OK)
                printf ("%s failed at %s:%d: `%s'\n",
                        "curl_multi_perform",
                        __FILE__,
                        __LINE__, curl_easy_strerror (msg->data.result));
              curl_multi_remove_handle (multi, c);
              curl_multi_cleanup (multi);
              curl_easy_cleanup (c);
              c = NULL;
              multi = NULL;
            }
        }
      MHD_run (d);
    }
  if (multi != NULL)
    {
      curl_multi_remove_handle (multi, c);
      curl_easy_cleanup (c);
      curl_multi_cleanup (multi);
    }
  MHD_stop_daemon (d);
  if (cbc.pos != strlen ("/hello_world"))
    return 8192;
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    return 16384;
  return 0;
}
Ejemplo n.º 25
0
int main(void)
{
  CURL *curl;
  CURLM *mcurl;
  int still_running = 1;
  struct timeval mp_start;

  curl_global_init(CURL_GLOBAL_DEFAULT);

  curl = curl_easy_init();
  if(!curl)
    return 1;

  mcurl = curl_multi_init();
  if(!mcurl)
    return 2;

  /* Set username and password */
  curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
  curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret");

  /* This will fetch message 1 from the user's inbox */
  curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com/INBOX/;UID=1");

  /* Tell the multi stack about our easy handle */
  curl_multi_add_handle(mcurl, curl);

  /* Record the start time which we can use later */
  mp_start = tvnow();

  /* We start some action by calling perform right away */
  curl_multi_perform(mcurl, &still_running);

  while(still_running) {
    struct timeval timeout;
    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd = -1;
    int rc;
    CURLMcode mc; /* curl_multi_fdset() return code */

    long curl_timeo = -1;

    /* Initialise the file descriptors */
    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;

    curl_multi_timeout(mcurl, &curl_timeo);
    if(curl_timeo >= 0) {
      timeout.tv_sec = curl_timeo / 1000;
      if(timeout.tv_sec > 1)
        timeout.tv_sec = 1;
      else
        timeout.tv_usec = (curl_timeo % 1000) * 1000;
    }

    /* get file descriptors from the transfers */
    mc = curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);

    if(mc != CURLM_OK)
    {
      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
      break;
    }

    /* On success the value of maxfd is guaranteed to be >= -1. We call
       select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
       no fds ready yet so we call select(0, ...) --or Sleep() on Windows--
       to sleep 100ms, which is the minimum suggested value in the
       curl_multi_fdset() doc. */

    if(maxfd == -1) {
#ifdef _WIN32
      Sleep(100);
      rc = 0;
#else
      /* Portable sleep for platforms other than Windows. */
      struct timeval wait = { 0, 100 * 1000 }; /* 100ms */
      rc = select(0, NULL, NULL, NULL, &wait);
#endif
    }
    else {
      /* Note that on some platforms 'timeout' may be modified by select().
         If you need access to the original value save a copy beforehand. */
      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
    }

    if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
      fprintf(stderr,
              "ABORTING: Since it seems that we would have run forever.\n");
      break;
    }

    switch(rc) {
    case -1:  /* select error */
      break;
    case 0:   /* timeout */
    default:  /* action */
      curl_multi_perform(mcurl, &still_running);
      break;
    }
  }

  /* Always cleanup */
  curl_multi_remove_handle(mcurl, curl);
  curl_multi_cleanup(mcurl);
  curl_easy_cleanup(curl);
  curl_global_cleanup();

  return 0;
}
Ejemplo n.º 26
0
static void
addTask( void * vtask )
{
    struct tr_web_task * task = vtask;
    const tr_session * session = task->session;

    if( ( session == NULL ) || ( session->web == NULL ) )
        return;

    if( !task->resolved_host )
    {
        dbgmsg( "couldn't resolve host for \"%s\"... task failed", task->url );
        task_finish( task, 0 );
    }
    else
    {
        CURL * e = curl_easy_init( );
        struct tr_web * web = session->web;
        const int timeout = getTimeoutFromURL( task->url );
        const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL;
        const char * user_agent = TR_NAME "/" SHORT_VERSION_STRING;

        /* insert the resolved host into the URL s.t. curl's DNS won't block
         * even if -- like on most OSes -- it wasn't built with C-Ares :(
         * "http://www.craptrackular.org/announce?key=val&key2=..." becomes
         * "http://127.0.0.1/announce?key=val&key2=..." */
        {
            char * host;
            struct evbuffer * buf = evbuffer_new( );
            char * pch = strstr( task->url, task->host );
            char * tail = pch + strlen( task->host );
            evbuffer_add( buf, task->url, pch - task->url );
            evbuffer_add_printf( buf, "%s", task->resolved_host );
            evbuffer_add_printf( buf, "%s", tail );
            task->resolved_url = tr_strndup( EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
            dbgmsg( "old url: \"%s\" -- new url: \"%s\"", task->url, task->resolved_url );
            evbuffer_free( buf );

            /* Manually add a Host: argument that refers to the true URL */
            if( ( ( task->port <= 0 ) ) ||
                ( ( task->port == 80 ) && !strncmp( task->url, "http://", 7 ) ) ||
                ( ( task->port == 443 ) && !strncmp( task->url, "https://", 8 ) ) )
                host = tr_strdup_printf( "Host: %s", task->host );
            else
                host = tr_strdup_printf( "Host: %s:%d", task->host, task->port );

            task->slist = curl_slist_append( NULL, host );
            task->slist = curl_slist_append( task->slist, "Accept:" );
            curl_easy_setopt( e, CURLOPT_HTTPHEADER, task->slist );
            tr_free( host );
        }

        dbgmsg( "adding task #%lu [%s]", task->tag, task->resolved_url ? task->resolved_url : task->url );

        if( !task->range && session->isProxyEnabled ) {
            curl_easy_setopt( e, CURLOPT_PROXY, session->proxy );
            curl_easy_setopt( e, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
            curl_easy_setopt( e, CURLOPT_PROXYPORT, session->proxyPort );
            curl_easy_setopt( e, CURLOPT_PROXYTYPE,
                                      getCurlProxyType( session->proxyType ) );
        }
        if( !task->range && session->isProxyAuthEnabled ) {
            char * str = tr_strdup_printf( "%s:%s", session->proxyUsername,
                                                    session->proxyPassword );
            curl_easy_setopt( e, CURLOPT_PROXYUSERPWD, str );
            tr_free( str );
        }

        task->easy = e;
        task->multi = web->multi;

        /* use our own timeout instead of CURLOPT_TIMEOUT because the latter
         * doesn't play nicely with curl_multi.  See curl bug #2501457 */
        task->timer_event_isSet = TRUE;
        evtimer_set( &task->timer_event, task_timeout_cb, task );
        tr_timerAdd( &task->timer_event, timeout, 0 );

        curl_easy_setopt( e, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
        curl_easy_setopt( e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction );
        curl_easy_setopt( e, CURLOPT_SOCKOPTDATA, task );
        curl_easy_setopt( e, CURLOPT_WRITEDATA, task );
        curl_easy_setopt( e, CURLOPT_WRITEFUNCTION, writeFunc );
        curl_easy_setopt( e, CURLOPT_DNS_CACHE_TIMEOUT, MIN_DNS_CACHE_TIME );
        curl_easy_setopt( e, CURLOPT_FOLLOWLOCATION, 1L );
        curl_easy_setopt( e, CURLOPT_AUTOREFERER, 1L );
        curl_easy_setopt( e, CURLOPT_FORBID_REUSE, 1L );
        curl_easy_setopt( e, CURLOPT_MAXREDIRS, -1L );
        curl_easy_setopt( e, CURLOPT_PRIVATE, task );
        curl_easy_setopt( e, CURLOPT_SSL_VERIFYHOST, 0L );
        curl_easy_setopt( e, CURLOPT_SSL_VERIFYPEER, 0L );
        curl_easy_setopt( e, CURLOPT_URL, task->resolved_url ? task->resolved_url : task->url );
        curl_easy_setopt( e, CURLOPT_USERAGENT, user_agent );
        curl_easy_setopt( e, CURLOPT_VERBOSE, verbose );
        if( web->haveAddr )
            curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( &web->addr ) );
        if( task->range )
            curl_easy_setopt( e, CURLOPT_RANGE, task->range );

        if( curl_multi_add_handle( web->multi, e ) == CURLM_OK )
            ++web->taskCount;
    }
}
Ejemplo n.º 27
0
/*
 * Simply download a HTTP file.
 */
int main(void)
{
  CURL *http_handle;
  CURLM *multi_handle;

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

  curl_global_init(CURL_GLOBAL_DEFAULT);

  http_handle = curl_easy_init();

  /* set the options (I left out a few, you'll get the point anyway) */
  curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.example.com/");

  /* init a multi stack */
  multi_handle = curl_multi_init();

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

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

  do {
    struct timeval timeout;
    int rc; /* select() return code */

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

    long curl_timeo = -1;

    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;

    curl_multi_timeout(multi_handle, &curl_timeo);
    if(curl_timeo >= 0) {
      timeout.tv_sec = curl_timeo / 1000;
      if(timeout.tv_sec > 1)
        timeout.tv_sec = 1;
      else
        timeout.tv_usec = (curl_timeo % 1000) * 1000;
    }

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

    /* In a real-world program you OF COURSE check the return code of the
       function calls.  On success, the value of maxfd is guaranteed to be
       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
       case of (maxfd == -1), we call select(0, ...), which is basically equal
       to sleep. */

    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    switch(rc) {
    case -1:
      /* select error */
      still_running = 0;
      printf("select() returns error, this is badness\n");
      break;
    case 0:
    default:
      /* timeout or readable/writable sockets */
      curl_multi_perform(multi_handle, &still_running);
      break;
    }
  } while(still_running);

  curl_multi_remove_handle(multi_handle, http_handle);

  curl_easy_cleanup(http_handle);

  curl_multi_cleanup(multi_handle);

  curl_global_cleanup();

  return 0;
}
Ejemplo n.º 28
0
static CURLcode dohprobe(struct Curl_easy *data,
                         struct dnsprobe *p, DNStype dnstype,
                         const char *host,
                         const char *url, CURLM *multi,
                         struct curl_slist *headers)
{
  struct Curl_easy *doh = NULL;
  char *nurl = NULL;
  CURLcode result = CURLE_OK;
  timediff_t timeout_ms;
  DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
                         &p->dohlen);
  if(d) {
    failf(data, "Failed to encode DOH packet [%d]\n", d);
    return CURLE_OUT_OF_MEMORY;
  }

  p->dnstype = dnstype;
  p->serverdoh.memory = NULL;
  /* the memory will be grown as needed by realloc in the doh_write_cb
     function */
  p->serverdoh.size = 0;

  /* Note: this is code for sending the DoH request with GET but there's still
     no logic that actually enables this. We should either add that ability or
     yank out the GET code. Discuss! */
  if(data->set.doh_get) {
    char *b64;
    size_t b64len;
    result = Curl_base64url_encode(data, (char *)p->dohbuffer, p->dohlen,
                                   &b64, &b64len);
    if(result)
      goto error;
    nurl = aprintf("%s?dns=%s", url, b64);
    free(b64);
    if(!nurl) {
      result = CURLE_OUT_OF_MEMORY;
      goto error;
    }
    url = nurl;
  }

  timeout_ms = Curl_timeleft(data, NULL, TRUE);

  /* Curl_open() is the internal version of curl_easy_init() */
  result = Curl_open(&doh);
  if(!result) {
    /* pass in the struct pointer via a local variable to please coverity and
       the gcc typecheck helpers */
    struct dohresponse *resp = &p->serverdoh;
    ERROR_CHECK_SETOPT(CURLOPT_URL, url);
    ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
    ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
    if(!data->set.doh_get) {
      ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer);
      ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
    }
    ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
#ifdef USE_NGHTTP2
    ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
#endif
#ifndef CURLDEBUG
    /* enforce HTTPS if not debug */
    ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
#endif
    ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
    ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
    doh->set.fmultidone = Curl_doh_done;
    doh->set.dohfor = data; /* identify for which transfer this is done */
    p->easy = doh;

    /* add this transfer to the multi handle */
    if(curl_multi_add_handle(multi, doh))
      goto error;
  }
  else
    goto error;
  free(nurl);
  return CURLE_OK;

  error:
  free(nurl);
  Curl_close(doh);
  return result;
}
Ejemplo n.º 29
0
int main(void)
{
   CURL *curl;
   CURLM *mcurl;
   int still_running = 1;
   struct timeval mp_start;
   char mp_timedout = 0;
   struct WriteThis pooh;
   struct curl_slist* rcpt_list = NULL;

   pooh.counter = 0;

   curl_global_init(CURL_GLOBAL_DEFAULT);

   curl = curl_easy_init();
   if(!curl)
     return 1;

   mcurl = curl_multi_init();
   if(!mcurl)
     return 2;

   rcpt_list = curl_slist_append(rcpt_list, RECEPIENT);
   /* more addresses can be added here
      rcpt_list = curl_slist_append(rcpt_list, "*****@*****.**");
   */

   curl_easy_setopt(curl, CURLOPT_URL, "smtp://" SMTPSERVER SMTPPORT);
   curl_easy_setopt(curl, CURLOPT_USERNAME, USERNAME);
   curl_easy_setopt(curl, CURLOPT_PASSWORD, PASSWORD);
   curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
   curl_easy_setopt(curl, CURLOPT_MAIL_FROM, MAILFROM);
   curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpt_list);
   curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
   curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER,0);
   curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
   curl_easy_setopt(curl, CURLOPT_READDATA, &pooh);
   curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
   curl_easy_setopt(curl, CURLOPT_SSLVERSION, 0);
   curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0);
   curl_multi_add_handle(mcurl, curl);

   mp_timedout = 0;
   mp_start = tvnow();

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

  while(still_running) {
    struct timeval timeout;
    int rc; /* select() return code */

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

    long curl_timeo = -1;

    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;

    curl_multi_timeout(mcurl, &curl_timeo);
    if(curl_timeo >= 0) {
      timeout.tv_sec = curl_timeo / 1000;
      if(timeout.tv_sec > 1)
        timeout.tv_sec = 1;
      else
        timeout.tv_usec = (curl_timeo % 1000) * 1000;
    }

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

    /* In a real-world program you OF COURSE check the return code of the
       function calls.  On success, the value of maxfd is guaranteed to be
       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
       case of (maxfd == -1), we call select(0, ...), which is basically equal
       to sleep. */

    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    if (tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
      fprintf(stderr, "ABORTING TEST, since it seems "
              "that it would have run forever.\n");
      break;
    }

    switch(rc) {
    case -1:
      /* select error */
      break;
    case 0: /* timeout */
    default: /* action */
      curl_multi_perform(mcurl, &still_running);
      break;
    }
  }

  curl_slist_free_all(rcpt_list);
  curl_multi_remove_handle(mcurl, curl);
  curl_multi_cleanup(mcurl);
  curl_easy_cleanup(curl);
  curl_global_cleanup();
  return 0;
}
Ejemplo n.º 30
0
static void
tr_webThreadFunc( void * vsession )
{
    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->cookie_filename = tr_buildPath( session->configDir, "cookies.txt", NULL );

    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(( task = tr_list_pop_front( &web->tasks )))
        {
            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 );

        /* 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 );
                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 );
                curl_easy_cleanup( e );
/*fprintf( stderr, "removing a completed task.. taskCount is now %d (response code: %d, response len: %d)\n", taskCount, (int)task->code, (int)evbuffer_get_length(task->response) );*/
                tr_runInEventThread( task->session, task_finish_func, task );
                --taskCount;
            }
        }

#if 0
{
tr_list * l;
for( l=web->tasks; l!=NULL; l=l->next )
    fprintf( stderr, "still pending: %s\n", ((struct tr_web_task*)l->data)->url );
}
fprintf( stderr, "loop is ending... web is closing\n" );
#endif
    }

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

    /* cleanup */
    curl_multi_cleanup( multi );
    tr_lockFree( web->taskLock );
    tr_free( web->cookie_filename );
    tr_free( web );
    session->web = NULL;
}