CURLSHcode Mtacurl::share_setopt( CURLSHoption option, const char *val ) { if ( !m_pCurlShare ) m_pCurlShare = curl_share_init(); return curl_share_setopt( m_pCurlShare, option, val ); }
int l_share_init(lua_State *L) { l_share_userdata *share_userdata = l_share_newuserdata(L); if ((share_userdata->curlsh = curl_share_init()) == NULL) luaL_error(L, "something went wrong and you cannot use the other curl functions"); /* return userdata */ return 1; }
void adns::NewShareHndl() { RemoveShareHndl(); sharehndl = curl_share_init(); curl_share_setopt(sharehndl, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(sharehndl, CURLSHOPT_USERDATA, this); curl_share_setopt(sharehndl, CURLSHOPT_LOCKFUNC, adns_lock_function); curl_share_setopt(sharehndl, CURLSHOPT_UNLOCKFUNC, adns_unlock_function); }
BCResourceHandleManagerCURL::BCResourceHandleManagerCURL() : m_downloadTimer(this, &BCResourceHandleManagerCURL::downloadTimerCallback) , m_cookieJarFileName("/tmp/cookies-owb.txt") { curl_global_init(CURL_GLOBAL_ALL); m_curlMultiHandle = curl_multi_init(); m_curlShareHandle = curl_share_init(); curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); }
int FetcherManager::start() { Manager::start(); curl_global_init(CURL_GLOBAL_ALL); sh = curl_share_init(); curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(sh, CURLSHOPT_LOCKFUNC, lock_function); curl_share_setopt(sh, CURLSHOPT_UNLOCKFUNC, unlock_function); startCrawlerThread(); }
ResourceHandleManager::ResourceHandleManager() : m_downloadTimer(this, &ResourceHandleManager::downloadTimerCallback) , m_cookieJarFileName(0) { curl_global_init(CURL_GLOBAL_ALL); m_curlMultiHandle = curl_multi_init(); m_curlShareHandle = curl_share_init(); curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); }
void CurlEasy::SetShareHandle(void* curl_handle) { static void* share_handle = NULL; if (!share_handle) { share_handle = curl_share_init(); curl_share_setopt(share_handle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); } curl_easy_setopt(curl_handle, CURLOPT_SHARE, share_handle); curl_easy_setopt(curl_handle, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 5); }
/** * Initializes the input/output part of the * specified metha object **/ M_CODE lm_init_io(io_t *io, metha_t *m) { io->m = m; #ifdef WIN32 io->synchronous = 1; #endif if (io->synchronous) return M_OK; if (!(io->multi_h = curl_multi_init())) { LM_ERROR(m, "could not create CURL multi interface"); return M_FAILED; } if (!(io->share_h = curl_share_init())) { LM_ERROR(m, "could not create CURL share interface"); return M_ERROR; } if (pipe(io->msg_fd) != 0) { LM_ERROR(m, "pipe() failed: %s", strerror(errno)); return M_FAILED; } if (!(io->queue.pos = malloc(QUEUE_INIT_SIZE*sizeof(ioqp_t)))) return M_OUT_OF_MEM; io->queue.allocsz = QUEUE_INIT_SIZE; io->queue.size = 0; io->started = 0; pthread_mutex_init(&io->queue_mtx, 0); pthread_rwlock_init(&io->cookies_mtx, 0); pthread_rwlock_init(&io->dns_mtx, 0); pthread_rwlock_init(&io->share_mtx, 0); if (io->cookies) curl_share_setopt(io->share_h, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); curl_share_setopt(io->share_h, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(io->share_h, CURLSHOPT_LOCKFUNC, &lm_iothr_lock_shared_cb); curl_share_setopt(io->share_h, CURLSHOPT_UNLOCKFUNC, &lm_iothr_unlock_shared_cb); curl_share_setopt(io->share_h, CURLSHOPT_USERDATA, io); curl_multi_setopt(io->multi_h, CURLMOPT_SOCKETFUNCTION, &lm_iothr_socket_cb); curl_multi_setopt(io->multi_h, CURLMOPT_SOCKETDATA, io); curl_multi_setopt(io->multi_h, CURLMOPT_TIMERFUNCTION, &lm_iothr_set_timer_cb); curl_multi_setopt(io->multi_h, CURLMOPT_TIMERDATA, io); /*curl_multi_setopt(io->multi_h, CURLMOPT_PIPELINING, 1);*/ return M_OK; }
/* constructor */ PYCURL_INTERNAL CurlShareObject * do_share_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) { int res; CurlShareObject *self; #ifdef WITH_THREAD const curl_lock_function lock_cb = share_lock_callback; const curl_unlock_function unlock_cb = share_unlock_callback; #endif int *ptr; if (!PyArg_ParseTupleAndKeywords(args, kwds, "", empty_keywords)) { return NULL; } /* Allocate python curl-share object */ self = (CurlShareObject *) subtype->tp_alloc(subtype, 0); if (!self) { return NULL; } /* tp_alloc is expected to return zeroed memory */ for (ptr = (int *) &self->dict; ptr < (int *) (((char *) self) + sizeof(CurlShareObject)); ++ptr) assert(*ptr == 0); #ifdef WITH_THREAD self->lock = share_lock_new(); assert(self->lock != NULL); #endif /* Allocate libcurl share handle */ self->share_handle = curl_share_init(); if (self->share_handle == NULL) { Py_DECREF(self); PyErr_SetString(ErrorObject, "initializing curl-share failed"); return NULL; } #ifdef WITH_THREAD /* Set locking functions and data */ res = curl_share_setopt(self->share_handle, CURLSHOPT_LOCKFUNC, lock_cb); assert(res == CURLE_OK); res = curl_share_setopt(self->share_handle, CURLSHOPT_USERDATA, self); assert(res == CURLE_OK); res = curl_share_setopt(self->share_handle, CURLSHOPT_UNLOCKFUNC, unlock_cb); assert(res == CURLE_OK); #endif return self; }
CurlFtp::CurlFtp(QObject *parent) : QThread(parent) { CURLcode rc; CurlFtp::seq += 1; Q_ASSERT(::curl_global_inited >= 0); ::curl_global_init_mutex.lock(); if (::curl_global_inited == 0) { #if defined(Q_OS_WIN32) rc = curl_global_init(CURL_GLOBAL_WIN32 | CURL_GLOBAL_SSL); #endif // rc = curl_global_init(CURL_GLOBAL_ALL); rc = curl_global_init(CURL_GLOBAL_DEFAULT); Q_ASSERT(rc == 0); ::curl_global_inited = 1; } else { ::curl_global_inited += 1; } ::curl_global_init_mutex.unlock(); this->curl = curl_easy_init(); Q_ASSERT(this->curl != NULL); rc = curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, 1); // this app should used in multithread envirement // rc = curl_easy_setopt(this->curl, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_SINGLECWD); rc = curl_easy_setopt(this->curl, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_NOCWD); rc = curl_easy_setopt(this->curl, CURLOPT_FILETIME, 0); // if ftp put, this cmd error, the put will not exec #ifdef CURLOPT_WILDCARDMATCH // <= 7.19 problem rc = curl_easy_setopt(this->curl, CURLOPT_WILDCARDMATCH, 0); #endif // rc = curl_easy_setopt(this->curl, CURLOPT_DNS_USE_GLOBAL_CACHE, 0); // obslate OPT this->shareHandle = curl_share_init(); rc = curl_easy_setopt(this->curl, CURLOPT_SHARE, this->shareHandle); this->protoType = PROTO_FTP; rc = curl_easy_setopt(this->curl, CURLOPT_USE_SSL, CURLUSESSL_NONE); int qtype1 = qRegisterMetaType<QAbstractSocket::SocketError>("SocketError" ); int qtype2 = qRegisterMetaType<QAbstractSocket::SocketState>("SocketState" ); //// test QObject::connect(this, SIGNAL(runHere()), this, SLOT(nowarnRunDone())); QObject::connect(this, SIGNAL(finished()), this, SLOT(asynRunRetrDone())); }
void curl_load() { curl_global_init(CURL_GLOBAL_ALL); sem_init(&curl_share_sem, 0, 1); curl_share = curl_share_init(); if (curl_share_setopt(curl_share, CURLSHOPT_LOCKFUNC, curl_share_lock)) error("curl_share_setopt failed"); if (curl_share_setopt(curl_share, CURLSHOPT_UNLOCKFUNC, curl_share_unlock)) error("curl_share_setopt failed"); if (curl_share_setopt(curl_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS)) error("curl_share_setopt failed"); }
/** * @brief Called when creating a curl data structure that will be shared across different * http connections. DNS caching data is such data structure. * * @param curlShHandle: pointer to a CURLSH structure that will be instantiated by curl_share_init * * @return none **/ void libhttpcomm_curlShareInit(CURLSH *curlShHandle) { curlShHandle = curl_share_init(); if (curlShHandle != NULL) { if(curl_share_setopt(curlShHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS) != CURLSHE_OK) { SYSLOG_ERR("curl_easy_setopt CURLSHOPT_SHARE"); } }else { SYSLOG_ERR("curl_share_init"); } }
CurlHttpIO::CurlHttpIO() { curl_global_init(CURL_GLOBAL_DEFAULT); curlm = curl_multi_init(); curlsh = curl_share_init(); curl_share_setopt(curlsh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(curlsh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); contenttypejson = curl_slist_append(NULL, "Content-Type: application/json"); contenttypejson = curl_slist_append(contenttypejson, "Expect:"); contenttypebinary = curl_slist_append(NULL, "Content-Type: application/octet-stream"); contenttypebinary = curl_slist_append(contenttypebinary, "Expect:"); }
void NetworkModule::Initialize() { curl_global_init(CURL_GLOBAL_ALL); modulePath = GetPath(); this->networkBinding = new NetworkBinding(host); this->analyticsBinding = new AnalyticsBinding(); GlobalObject::GetInstance()->SetObject("Network", this->networkBinding); GlobalObject::GetInstance()->SetObject("Analytics", this->analyticsBinding); curlShareHandle = curl_share_init(); curl_share_setopt(curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); curl_share_setopt(curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(curlShareHandle, CURLSHOPT_LOCKFUNC, CurlLockCallback); curl_share_setopt(curlShareHandle, CURLSHOPT_UNLOCKFUNC, CurlUnlockCallback); }
//{ int lcurl_share_create(lua_State *L, int error_mode){ lcurl_share_t *p; lua_settop(L, 1); p = lutil_newudatap(L, lcurl_share_t, LCURL_SHARE); p->curl = curl_share_init(); p->err_mode = error_mode; if(!p->curl) return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_SHARE, CURLSHE_NOMEM); if(lua_type(L, 1) == LUA_TTABLE){ int ret = lcurl_utils_apply_options(L, 1, 2, 1, p->err_mode, LCURL_ERROR_SHARE, CURLSHE_BAD_OPTION); if(ret) return ret; assert(lua_gettop(L) == 2); } return 1; }
HTTPCURLContext::HTTPCURLContext(uv_loop_t *loop_) : HTTPContextBase(loop_), loop(loop_) { if (curl_global_init(CURL_GLOBAL_ALL)) { throw std::runtime_error("Could not init cURL"); } timeout = new uv_timer_t; timeout->data = this; uv_timer_init(loop, timeout); share = curl_share_init(); multi = curl_multi_init(); handleError(curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, handleSocket)); handleError(curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, this)); handleError(curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, startTimeout)); handleError(curl_multi_setopt(multi, CURLMOPT_TIMERDATA, this)); }
activemq(const std::string& user, const std::string& password, const std::string& url) : m_username(user), m_password(password), m_url(url), m_data_parse_callback(nullptr) { //register callback register_callback(); curl_global_init(CURL_GLOBAL_ALL); m_curl = curl_easy_init(); curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this); string user_pass = m_username + ":" + m_password; curl_easy_setopt(m_curl, CURLOPT_USERPWD, user_pass.c_str()); #ifdef DEBUG curl_easy_setopt(m_curl, CURLOPT_VERBOSE, 1); #endif //curl(m_download_url, "GET", filename, true); if (!share_handle) { share_handle = curl_share_init(); curl_share_setopt(share_handle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); } curl_easy_setopt(m_curl, CURLOPT_SHARE, share_handle); curl_easy_setopt(m_curl, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 5); }
bool HttpInit(IStorage *pStorage) { pStorage->GetBinaryPath("data/ca-ddnet.pem", CA_FILE_PATH, sizeof(CA_FILE_PATH)); if(curl_global_init(CURL_GLOBAL_DEFAULT)) { return true; } gs_Share = curl_share_init(); if(!gs_Share) { return true; } for(unsigned int i = 0; i < sizeof(gs_aLocks) / sizeof(gs_aLocks[0]); i++) { gs_aLocks[i] = lock_create(); } curl_share_setopt(gs_Share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(gs_Share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); curl_share_setopt(gs_Share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); curl_share_setopt(gs_Share, CURLSHOPT_LOCKFUNC, CurlLock); curl_share_setopt(gs_Share, CURLSHOPT_UNLOCKFUNC, CurlUnlock); return false; }
/* test function */ int test(char *URL) { int res; CURLSHcode scode; char *url; struct Tdata tdata; CURL *curl; CURLSH *share; struct curl_slist *headers; int i; struct userdata user; user.text = (char *)"Pigs in space"; user.counter = 0; printf( "GLOBAL_INIT\n" ); curl_global_init( CURL_GLOBAL_ALL ); /* prepare share */ printf( "SHARE_INIT\n" ); share = curl_share_init(); curl_share_setopt( share, CURLSHOPT_LOCKFUNC, lock); curl_share_setopt( share, CURLSHOPT_UNLOCKFUNC, unlock); curl_share_setopt( share, CURLSHOPT_USERDATA, &user); printf( "CURL_LOCK_DATA_COOKIE\n" ); curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); printf( "CURL_LOCK_DATA_DNS\n" ); curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); res = 0; /* start treads */ for (i=1; i<=THREADS; i++ ) { /* set thread data */ tdata.url = suburl( URL, i ); /* must be freed */ tdata.share = share; /* simulate thread, direct call of "thread" function */ printf( "*** run %d\n",i ); fire( &tdata ); free( tdata.url ); } /* fetch a another one and save cookies */ printf( "*** run %d\n", i ); curl = curl_easy_init(); url = suburl( URL, i ); headers = sethost( NULL ); curl_easy_setopt( curl, CURLOPT_HTTPHEADER, (void*)headers ); curl_easy_setopt( curl, CURLOPT_URL, url ); printf( "CURLOPT_SHARE\n" ); curl_easy_setopt( curl, CURLOPT_SHARE, share ); printf( "CURLOPT_COOKIEJAR\n" ); curl_easy_setopt( curl, CURLOPT_COOKIEJAR, JAR ); printf( "PERFORM\n" ); curl_easy_perform( curl ); /* try to free share, expect to fail because share is in use*/ printf( "try SHARE_CLEANUP...\n" ); scode = curl_share_cleanup( share ); if ( scode==CURLSHE_OK ) { fprintf(stderr, "curl_share_cleanup succeed but error expected\n"); share = NULL; } else { printf( "SHARE_CLEANUP failed, correct\n" ); } /* clean up last handle */ printf( "CLEANUP\n" ); curl_easy_cleanup( curl ); curl_slist_free_all( headers ); free(url); /* free share */ printf( "SHARE_CLEANUP\n" ); scode = curl_share_cleanup( share ); if ( scode!=CURLSHE_OK ) { fprintf(stderr, "curl_share_cleanup failed, code errno %d\n", scode); } printf( "GLOBAL_CLEANUP\n" ); curl_global_cleanup(); return res; }
/* test function */ int test(char *URL) { int res; CURLSHcode scode = CURLSHE_OK; char *url; struct Tdata tdata; CURL *curl; CURLSH *share; int i; struct userdata user; user.text = (char *)"Pigs in space"; user.counter = 0; printf( "GLOBAL_INIT\n" ); if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { fprintf(stderr, "curl_global_init() failed\n"); return TEST_ERR_MAJOR_BAD; } /* prepare share */ printf( "SHARE_INIT\n" ); if ((share = curl_share_init()) == NULL) { fprintf(stderr, "curl_share_init() failed\n"); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } if ( CURLSHE_OK == scode ) { printf( "CURLSHOPT_LOCKFUNC\n" ); scode = curl_share_setopt( share, CURLSHOPT_LOCKFUNC, my_lock); } if ( CURLSHE_OK == scode ) { printf( "CURLSHOPT_UNLOCKFUNC\n" ); scode = curl_share_setopt( share, CURLSHOPT_UNLOCKFUNC, my_unlock); } if ( CURLSHE_OK == scode ) { printf( "CURLSHOPT_USERDATA\n" ); scode = curl_share_setopt( share, CURLSHOPT_USERDATA, &user); } if ( CURLSHE_OK == scode ) { printf( "CURL_LOCK_DATA_SSL_SESSION\n" ); scode = curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); } if ( CURLSHE_OK != scode ) { fprintf(stderr, "curl_share_setopt() failed\n"); curl_share_cleanup(share); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } res = 0; /* start treads */ for (i=1; i<=THREADS; i++ ) { /* set thread data */ tdata.url = URL; tdata.share = share; /* simulate thread, direct call of "thread" function */ printf( "*** run %d\n",i ); fire( &tdata ); } /* fetch a another one */ printf( "*** run %d\n", i ); if ((curl = curl_easy_init()) == NULL) { fprintf(stderr, "curl_easy_init() failed\n"); curl_share_cleanup(share); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } url = URL; test_setopt( curl, CURLOPT_URL, url ); printf( "CURLOPT_SHARE\n" ); test_setopt( curl, CURLOPT_SHARE, share ); printf( "PERFORM\n" ); curl_easy_perform( curl ); /* try to free share, expect to fail because share is in use*/ printf( "try SHARE_CLEANUP...\n" ); scode = curl_share_cleanup( share ); if ( scode==CURLSHE_OK ) { fprintf(stderr, "curl_share_cleanup succeed but error expected\n"); share = NULL; } else { printf( "SHARE_CLEANUP failed, correct\n" ); } test_cleanup: /* clean up last handle */ printf( "CLEANUP\n" ); curl_easy_cleanup( curl ); /* free share */ printf( "SHARE_CLEANUP\n" ); scode = curl_share_cleanup( share ); if ( scode!=CURLSHE_OK ) fprintf(stderr, "curl_share_cleanup failed, code errno %d\n", (int)scode); printf( "GLOBAL_CLEANUP\n" ); curl_global_cleanup(); return res; }
QuviMedia::QuviMedia(std::wstring&& url) : QuviMediaInfo(std::move(url)) , m_curlsh(curl_share_init()) { assert(m_curlsh); // TODO: throw exception curl_share_setopt(m_curlsh, CURLSHOPT_LOCKFUNC, CurlShareLockFunction); curl_share_setopt(m_curlsh, CURLSHOPT_UNLOCKFUNC, CurlShareUnlockFunction); curl_share_setopt(m_curlsh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); curl_share_setopt(m_curlsh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(m_curlsh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); curl_share_setopt(m_curlsh, CURLSHOPT_USERDATA, &m_curlshLock); curl_easy_setopt(m_curl, CURLOPT_SHARE, m_curlsh); // TODO: ensure that cookies are properly inherited if (GetContentType() == "video/vnd.mpeg.dash.mpd") { std::string murl = GetMultibyteUrl(); if (murl.empty()) throw 1; // TODO: replace with some sensible exception std::unique_ptr<dash::IDASHManager> manager(CreateDashManager()); if (!manager) throw 1; // TODO: replace with some sensible exception std::unique_ptr<dash::mpd::IMPD> mpd(manager->Open(&murl[0])); if (!mpd) throw 1; // TODO: replace with some sensible exception const auto& period = mpd->GetPeriods().front(); for (const auto& adaptationSet : period->GetAdaptationSets()) { const auto& representation = adaptationSet->GetRepresentation().back(); enum class DashRepresentationType { Base, Template, List, }; auto determineType = [](const dash::mpd::IPeriod* period, const dash::mpd::IAdaptationSet* adaptationSet, const dash::mpd::IRepresentation* representation) -> DashRepresentationType { assert(representation && adaptationSet && period); if (representation->GetSegmentList()) return DashRepresentationType::List; if (representation->GetSegmentTemplate()) return DashRepresentationType::Template; if (representation->GetSegmentBase() || !representation->GetBaseURLs().empty()) return DashRepresentationType::Base; if (adaptationSet->GetSegmentList()) return DashRepresentationType::List; if (adaptationSet->GetSegmentTemplate()) return DashRepresentationType::Template; if (adaptationSet->GetSegmentBase()) return DashRepresentationType::Base; if (period->GetSegmentList()) return DashRepresentationType::List; if (period->GetSegmentTemplate()) return DashRepresentationType::Template; if (period->GetSegmentBase()) return DashRepresentationType::Base; throw 1; // TODO: replace with some sensible exception }; const DashRepresentationType type = determineType(period, adaptationSet, representation); if (type != DashRepresentationType::Base) // TODO: support other stream types throw 1; // TODO: replace with some sensible exception // TODO: support compound urls std::unique_ptr<dash::network::IChunk> chunk(representation->GetBaseURLs()[0]->ToMediaSegment({})); if (!chunk) throw 1; // TODO: replace with some sensible exception auto& uri = chunk->AbsoluteURI(); if (uri.empty()) throw 1; // TODO: replace with some sensible exception curl_easy_setopt(m_curl, CURLOPT_URL, &uri[0]); curl_easy_setopt(m_curl, CURLOPT_NOBODY, 1L); CURLcode cc = curl_easy_perform(m_curl); if (cc != CURLE_OK) throw 1; // TODO: replace with some sensible exception // TODO: use return codes long code = 0, proxycode = 0; curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &code); curl_easy_getinfo(m_curl, CURLINFO_HTTP_CONNECTCODE, &proxycode); double size = 0; curl_easy_getinfo(m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &size); curl_easy_setopt(m_curl, CURLOPT_HTTPGET, 1L); m_backends.emplace_back(std::make_unique<QuviSimpleStreamBackend>((uint64_t)size, m_curl, m_curlsh)); } } else { assert(m_backends.empty()); m_backends.emplace_back(std::make_unique<QuviSimpleStreamBackend>(GetContentLength(), m_curl, m_curlsh)); } }
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 (); }
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; }
/* test function */ int test(char *URL) { int res; CURLSHcode scode = CURLSHE_OK; CURLcode code = CURLE_OK; char *url = NULL; struct Tdata tdata; CURL *curl; CURLSH *share; struct curl_slist *headers = NULL; struct curl_slist *cookies = NULL; struct curl_slist *next_cookie = NULL; int i; struct userdata user; user.text = (char *)"Pigs in space"; user.counter = 0; printf("GLOBAL_INIT\n"); if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { fprintf(stderr, "curl_global_init() failed\n"); return TEST_ERR_MAJOR_BAD; } /* prepare share */ printf("SHARE_INIT\n"); if((share = curl_share_init()) == NULL) { fprintf(stderr, "curl_share_init() failed\n"); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } if(CURLSHE_OK == scode) { printf("CURLSHOPT_LOCKFUNC\n"); scode = curl_share_setopt(share, CURLSHOPT_LOCKFUNC, my_lock); } if(CURLSHE_OK == scode) { printf("CURLSHOPT_UNLOCKFUNC\n"); scode = curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, my_unlock); } if(CURLSHE_OK == scode) { printf("CURLSHOPT_USERDATA\n"); scode = curl_share_setopt(share, CURLSHOPT_USERDATA, &user); } if(CURLSHE_OK == scode) { printf("CURL_LOCK_DATA_COOKIE\n"); scode = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); } if(CURLSHE_OK == scode) { printf("CURL_LOCK_DATA_DNS\n"); scode = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); } if(CURLSHE_OK != scode) { fprintf(stderr, "curl_share_setopt() failed\n"); curl_share_cleanup(share); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } /* initial cookie manipulation */ if((curl = curl_easy_init()) == NULL) { fprintf(stderr, "curl_easy_init() failed\n"); curl_share_cleanup(share); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } printf("CURLOPT_SHARE\n"); test_setopt(curl, CURLOPT_SHARE, share); printf("CURLOPT_COOKIELIST injected_and_clobbered\n"); test_setopt(curl, CURLOPT_COOKIELIST, "Set-Cookie: injected_and_clobbered=yes; " "domain=host.foo.com; expires=Sat Feb 2 11:56:27 GMT 2030"); printf("CURLOPT_COOKIELIST ALL\n"); test_setopt(curl, CURLOPT_COOKIELIST, "ALL"); printf("CURLOPT_COOKIELIST session\n"); test_setopt(curl, CURLOPT_COOKIELIST, "Set-Cookie: session=elephants"); printf("CURLOPT_COOKIELIST injected\n"); test_setopt(curl, CURLOPT_COOKIELIST, "Set-Cookie: injected=yes; domain=host.foo.com; " "expires=Sat Feb 2 11:56:27 GMT 2030"); printf("CURLOPT_COOKIELIST SESS\n"); test_setopt(curl, CURLOPT_COOKIELIST, "SESS"); printf("CLEANUP\n"); curl_easy_cleanup(curl); res = 0; /* start treads */ for(i=1; i<=THREADS; i++) { /* set thread data */ tdata.url = suburl(URL, i); /* must be curl_free()d */ tdata.share = share; /* simulate thread, direct call of "thread" function */ printf("*** run %d\n",i); fire(&tdata); curl_free(tdata.url); } /* fetch a another one and save cookies */ printf("*** run %d\n", i); if((curl = curl_easy_init()) == NULL) { fprintf(stderr, "curl_easy_init() failed\n"); curl_share_cleanup(share); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } url = suburl(URL, i); headers = sethost(NULL); test_setopt(curl, CURLOPT_HTTPHEADER, headers); test_setopt(curl, CURLOPT_URL, url); printf("CURLOPT_SHARE\n"); test_setopt(curl, CURLOPT_SHARE, share); printf("CURLOPT_COOKIEJAR\n"); test_setopt(curl, CURLOPT_COOKIEJAR, JAR); printf("CURLOPT_COOKIELIST FLUSH\n"); test_setopt(curl, CURLOPT_COOKIELIST, "FLUSH"); printf("PERFORM\n"); curl_easy_perform(curl); printf("CLEANUP\n"); curl_easy_cleanup(curl); curl_free(url); curl_slist_free_all(headers); /* load cookies */ if((curl = curl_easy_init()) == NULL) { fprintf(stderr, "curl_easy_init() failed\n"); curl_share_cleanup(share); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } url = suburl(URL, i); headers = sethost(NULL); test_setopt(curl, CURLOPT_HTTPHEADER, headers); test_setopt(curl, CURLOPT_URL, url); printf("CURLOPT_SHARE\n"); test_setopt(curl, CURLOPT_SHARE, share); printf("CURLOPT_COOKIELIST ALL\n"); test_setopt(curl, CURLOPT_COOKIELIST, "ALL"); printf("CURLOPT_COOKIEJAR\n"); test_setopt(curl, CURLOPT_COOKIEFILE, JAR); printf("CURLOPT_COOKIELIST RELOAD\n"); test_setopt(curl, CURLOPT_COOKIELIST, "RELOAD"); code = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies); if(code != CURLE_OK) { fprintf(stderr, "curl_easy_getinfo() failed\n"); res = TEST_ERR_MAJOR_BAD; goto test_cleanup; } printf("loaded cookies:\n"); if(!cookies) { fprintf(stderr, " reloading cookies from '%s' failed\n", JAR); res = TEST_ERR_MAJOR_BAD; goto test_cleanup; } printf("-----------------\n"); next_cookie = cookies; while(next_cookie) { printf(" %s\n", next_cookie->data); next_cookie = next_cookie->next; } printf("-----------------\n"); curl_slist_free_all(cookies); /* try to free share, expect to fail because share is in use*/ printf("try SHARE_CLEANUP...\n"); scode = curl_share_cleanup(share); if(scode==CURLSHE_OK) { fprintf(stderr, "curl_share_cleanup succeed but error expected\n"); share = NULL; } else { printf("SHARE_CLEANUP failed, correct\n"); } test_cleanup: /* clean up last handle */ printf("CLEANUP\n"); curl_easy_cleanup(curl); curl_slist_free_all(headers); curl_free(url); /* free share */ printf("SHARE_CLEANUP\n"); scode = curl_share_cleanup(share); if(scode!=CURLSHE_OK) fprintf(stderr, "curl_share_cleanup failed, code errno %d\n", (int)scode); printf("GLOBAL_CLEANUP\n"); curl_global_cleanup(); return res; }
static VALUE ov_http_client_initialize(int argc, VALUE* argv, VALUE self) { VALUE opt; VALUE opts; long connections; long pipeline; ov_http_client_object* ptr; /* Get the pointer to the native object: */ ov_http_client_ptr(self, ptr); /* Check the number of arguments: */ if (argc > 1) { rb_raise(ov_error_class, "Expected at most one argument, 'opts', but received %d", argc); } opts = argc > 0? argv[0]: Qnil; if (NIL_P(opts)) { opts = rb_hash_new(); } else { Check_Type(opts, T_HASH); } /* Get the value of the 'ca_file' parameter: */ opt = rb_hash_aref(opts, CA_FILE_SYMBOL); if (NIL_P(opt)) { ptr->ca_file = NULL; } else { Check_Type(opt, T_STRING); ptr->ca_file = ov_string_dup(opt); } /* Get the value of the 'insecure' parameter: */ opt = rb_hash_aref(opts, INSECURE_SYMBOL); ptr->insecure = NIL_P(opt)? false: RTEST(opt); /* Get the value of the 'debug' parameter: */ opt = rb_hash_aref(opts, DEBUG_SYMBOL); ptr->debug = NIL_P(opt)? false: RTEST(opt); /* Get the value of the 'compress' parameter: */ opt = rb_hash_aref(opts, COMPRESS_SYMBOL); ptr->compress = NIL_P(opt)? true: RTEST(opt); /* Get the value of the 'timeout' parameter: */ opt = rb_hash_aref(opts, TIMEOUT_SYMBOL); if (NIL_P(opt)) { ptr->timeout = 0; } else { Check_Type(opt, T_FIXNUM); ptr->timeout = NUM2INT(opt); } /* Get the value of the 'connect_timeout' parameter: */ opt = rb_hash_aref(opts, CONNECT_TIMEOUT_SYMBOL); if (NIL_P(opt)) { ptr->connect_timeout = 0; } else { Check_Type(opt, T_FIXNUM); ptr->connect_timeout = NUM2INT(opt); } /* Get the value of the 'proxy_url' parameter: */ opt = rb_hash_aref(opts, PROXY_URL_SYMBOL); if (NIL_P(opt)) { ptr->proxy_url = NULL; } else { Check_Type(opt, T_STRING); ptr->proxy_url = ov_string_dup(opt); } /* Get the value of the 'proxy_username' parameter: */ opt = rb_hash_aref(opts, PROXY_USERNAME_SYMBOL); if (NIL_P(opt)) { ptr->proxy_username = NULL; } else { Check_Type(opt, T_STRING); ptr->proxy_username = ov_string_dup(opt); } /* Get the value of the 'proxy_password' parameter: */ opt = rb_hash_aref(opts, PROXY_PASSWORD_SYMBOL); if (NIL_P(opt)) { ptr->proxy_password = NULL; } else { Check_Type(opt, T_STRING); ptr->proxy_password = ov_string_dup(opt); } /* Get the value of the 'log' parameter: */ opt = rb_hash_aref(opts, LOG_SYMBOL); ptr->log = opt; /* Get the value of the 'pipeline' parameter: */ opt = rb_hash_aref(opts, PIPELINE_SYMBOL); if (NIL_P(opt)) { pipeline = 0; } else { Check_Type(opt, T_FIXNUM); pipeline = NUM2LONG(opt); } if (pipeline < 0) { rb_raise(rb_eArgError, "The maximum pipeline length can't be %ld, minimum is 0.", pipeline); } /* Get the value of the 'connections' parameter: */ opt = rb_hash_aref(opts, CONNECTIONS_SYMBOL); if (NIL_P(opt)) { connections = 1; } else { Check_Type(opt, T_FIXNUM); connections = NUM2LONG(opt); } if (connections < 1) { rb_raise(rb_eArgError, "The maximum number of connections can't be %ld, minimum is 1.", connections); } /* Get the value of the 'cookies' parameter. If it is a string it will be used as the path of the file where the cookies will be stored. If it is any other thing it will be treated as a boolean flag indicating if cookies should be enabled but not loaded/saved from/to any file. */ opt = rb_hash_aref(opts, COOKIES_SYMBOL); if (TYPE(opt) == T_STRING) { ptr->cookies = ov_string_dup(opt); } else if (RTEST(opt)) { ptr->cookies = ov_string_dup(rb_str_new2("")); } else { ptr->cookies = NULL; } /* Create the queue that contains requests that haven't been sent to libcurl yet: */ ptr->queue = rb_ary_new(); /* Create the hash that contains the transfers are pending an completed. Both use the identity of the request as key. */ ptr->completed = rb_funcall(rb_hash_new(), COMPARE_BY_IDENTITY_ID, 0); ptr->pending = rb_funcall(rb_hash_new(), COMPARE_BY_IDENTITY_ID, 0); /* Calculate the max number of requests that can be handled by libcurl simultaneously. For versions of libcurl newer than 7.30.0 the limit can be increased when using pipelining. For older versions it can't be increased because libcurl would create additional connections for the requests that can't be pipelined. */ ptr->limit = connections; if (pipeline > 0 && libcurl_version->version_num >= 0x071e00 /* 7.30.0 */) { ptr->limit *= pipeline; } /* Create the libcurl multi handle: */ ptr->handle = curl_multi_init(); if (ptr->handle == NULL) { rb_raise(ov_error_class, "Can't create libcurl multi object"); } /* Create the libcurl share handle in order to share cookie data: */ ptr->share = curl_share_init(); if (ptr->share == NULL) { rb_raise(ov_error_class, "Can't create libcurl share object"); } if (ptr->cookies != NULL) { curl_share_setopt(ptr->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); } /* Enable pipelining: */ if (pipeline > 0) { curl_multi_setopt(ptr->handle, CURLMOPT_PIPELINING, CURLPIPE_HTTP1); if (libcurl_version->version_num >= 0x071e00 /* 7.30.0 */) { curl_multi_setopt(ptr->handle, CURLMOPT_MAX_PIPELINE_LENGTH, pipeline); } else { ov_http_client_log_warn( ptr->log, "Can't set maximum pipeline length to %d, it isn't supported by libcurl %s. Upgrade to 7.30.0 or " "newer to avoid this issue.", pipeline, libcurl_version->version ); } } /* Set the max number of connections: */ if (connections > 0) { if (libcurl_version->version_num >= 0x071e00 /* 7.30.0 */) { curl_multi_setopt(ptr->handle, CURLMOPT_MAX_HOST_CONNECTIONS, connections); curl_multi_setopt(ptr->handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, connections); } else { ov_http_client_log_warn( ptr->log, "Can't set maximum number of connections to %d, it isn't supported by libcurl %s. Upgrade to 7.30.0 " "or newer to avoid this issue.", connections, libcurl_version->version ); } if (libcurl_version->version_num >= 0x070f03 /* 7.16.3 */) { curl_multi_setopt(ptr->handle, CURLMOPT_MAXCONNECTS, connections); } else { ov_http_client_log_warn( ptr->log, "Can't set total maximum connection cache size to %d, it isn't supported by libcurl %s. Upgrade to " "7.16.3 or newer to avoid this issue.", connections, libcurl_version->version ); } } return self; }