static CURLMcode perform(CURLM * multi) { int handles; CURLMcode code; fd_set fdread, fdwrite, fdexcep; struct timeval mp_start; char mp_timedout = FALSE; mp_timedout = FALSE; mp_start = tutil_tvnow(); for (;;) { static struct timeval timeout = /* 100 ms */ { 0, 100000L }; int maxfd = -1; code = curl_multi_perform(multi, &handles); if (tutil_tvdiff(tutil_tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) { mp_timedout = TRUE; break; } if (handles <= 0) return CURLM_OK; switch (code) { case CURLM_OK: break; case CURLM_CALL_MULTI_PERFORM: continue; default: return code; } FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); curl_multi_fdset(multi, &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. */ if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) return (CURLMcode) ~CURLM_OK; } /* We only reach this point if (mp_timedout) */ if (mp_timedout) fprintf(stderr, "mp_timedout\n"); fprintf(stderr, "ABORTING TEST, since it seems " "that it would have run forever.\n"); return (CURLMcode) ~CURLM_OK; }
static void registerUnregisterFds() { int fd, fdMax; FD_ZERO(&curlSrc->fdRead); FD_ZERO(&curlSrc->fdWrite); FD_ZERO(&curlSrc->fdExc); curlSrc->fdMax = -1; /* What fds does libcurl want us to poll? */ curl_multi_fdset(curlSrc->multiHandle, &curlSrc->fdRead, &curlSrc->fdWrite, &curlSrc->fdExc, &curlSrc->fdMax); if ((curlSrc->fdMax < -1) || (curlSrc->fdMax > GLIBCURL_FDMAX)) { DEBUG_FAILURE(("registerUnregisterFds: fdMax=%d\n", curlSrc->fdMax)); } /*fprintf(stderr, "registerUnregisterFds: fdMax=%d\n", curlSrc->fdMax);*/ assert(curlSrc->fdMax >= -1 && curlSrc->fdMax <= GLIBCURL_FDMAX); fdMax = curlSrc->fdMax; if (fdMax < curlSrc->lastPollFdMax) fdMax = curlSrc->lastPollFdMax; /* Has the list of required events for any of the fds changed? */ for (fd = 0; fd <= fdMax; ++fd) { gushort events = 0; if (FD_ISSET(fd, &curlSrc->fdRead)) events |= GLIBCURL_READ; if (FD_ISSET(fd, &curlSrc->fdWrite)) events |= GLIBCURL_WRITE; if (FD_ISSET(fd, &curlSrc->fdExc)) events |= GLIBCURL_EXC; /* List of events unchanged => no (de)registering */ if (events == curlSrc->lastPollFd[fd].events) continue; DD((stdout, "registerUnregisterFds: fd %d: old events %x, " "new events %x\n", fd, curlSrc->lastPollFd[fd].events, events)); /* fd is already a lastPollFd, but event type has changed => do nothing. Due to the implementation of g_main_context_query(), the new event flags will be picked up automatically. */ if (events != 0 && curlSrc->lastPollFd[fd].events != 0) { curlSrc->lastPollFd[fd].events = events; continue; } curlSrc->lastPollFd[fd].events = events; /* Otherwise, (de)register as appropriate */ if (events == 0) { g_source_remove_poll(&curlSrc->source, &curlSrc->lastPollFd[fd]); curlSrc->lastPollFd[fd].revents = 0; D((stderr, "unregister fd %d\n", fd)); } else { g_source_add_poll(&curlSrc->source, &curlSrc->lastPollFd[fd]); D((stderr, "register fd %d\n", fd)); } } curlSrc->lastPollFdMax = curlSrc->fdMax; }
/* use to attempt to fill the read buffer up to requested number of bytes */ static int fill_buffer(URL_FILE *file,int want,int waittime) { fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd; struct timeval timeout; int rc; (void) waittime; /* only attempt to fill buffer if transactions still running and buffer * doesnt exceed required size already */ if((!file->still_running) || (file->buffer_pos > want)) return 0; /* attempt to fill buffer */ do { FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); /* set a suitable timeout to fail on */ timeout.tv_sec = 60; /* 1 minute */ timeout.tv_usec = 0; /* get file descriptors from the transfers */ curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); switch(rc) { case -1: /* select error */ break; case 0: break; default: /* timeout or readable/writable sockets */ /* note we *could* be more efficient and not wait for * CURLM_CALL_MULTI_PERFORM to clear here and check it on re-entry * but that gets messy */ while(curl_multi_perform(multi_handle, &file->still_running) == CURLM_CALL_MULTI_PERFORM); break; } } while(file->still_running && (file->buffer_pos < want)); return 1; }
static PyObject * do_multi_select(CurlMultiObject *self, PyObject *args) { int max_fd = -1, n; double timeout = -1.0; struct timeval tv, *tvp; CURLMcode res; if (!PyArg_ParseTuple(args, "d:select", &timeout)) { return NULL; } if (check_multi_state(self, 1 | 2, "select") != 0) { return NULL; } if (timeout < 0 || timeout >= 365 * 24 * 60 * 60) { PyErr_SetString(PyExc_OverflowError, "invalid timeout period"); return NULL; } else { long seconds = (long)timeout; timeout = timeout - (double)seconds; assert(timeout >= 0.0); assert(timeout < 1.0); tv.tv_sec = seconds; tv.tv_usec = (long)(timeout*1000000.0); tvp = &tv; } FD_ZERO(&self->read_fd_set); FD_ZERO(&self->write_fd_set); FD_ZERO(&self->exc_fd_set); res = curl_multi_fdset(self->multi_handle, &self->read_fd_set, &self->write_fd_set, &self->exc_fd_set, &max_fd); if (res != CURLM_OK) { CURLERROR_MSG("multi_fdset failed"); } if (max_fd < 0) { n = 0; } else { Py_BEGIN_ALLOW_THREADS n = select(max_fd + 1, &self->read_fd_set, &self->write_fd_set, &self->exc_fd_set, tvp); Py_END_ALLOW_THREADS /* info: like Python's socketmodule.c we do not raise an exception * if select() fails - we'll leave it to the actual libcurl * socket code to report any errors. */ } return PyInt_FromLong(n); }
static CURLcode cover_thumbnailer_load_perform (CoverThumbnailer *cover, CURL *curl_handle) { gint still_running; struct timeval timeout; fd_set fdread; fd_set fdwrite; fd_set fdexcep; gint rc = 0; gint maxfd; CURLcode code = CURLE_OK; CURLMsg *msg; do { /* start the action */ while (curl_multi_perform (cover->curl_multi, &still_running) == CURLM_CALL_MULTI_PERFORM); if (!still_running) break; /* timeout once per second */ timeout.tv_sec = 1; timeout.tv_usec = 0; FD_ZERO (&fdread); FD_ZERO (&fdwrite); FD_ZERO (&fdexcep); /* get file descriptors from the transfers */ curl_multi_fdset (cover->curl_multi, &fdread, &fdwrite, &fdexcep, &maxfd); rc = select (maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); /* select error */ if (rc == -1) break; } while (still_running); /* get return value */ msg = curl_multi_info_read (cover->curl_multi, &rc); if (msg != NULL) code = msg->data.result; /* cleanup */ curl_multi_remove_handle (cover->curl_multi, curl_handle); curl_easy_cleanup (curl_handle); return code; }
/******************************************************************************* * Function name - mget_url_smooth * * Description - Performs actual fetching of urls for a whole batch. Starts * with initial fetch by mperform_smooth () and further acts * using mperform_smooth () on select events * * Input - *bctx - pointer to the batch of contexts * * Return Code/Output - On Success - 0, on Error -1 ********************************************************************************/ static int mget_url_smooth (batch_context* bctx) { int max_timeout_msec = 1000; unsigned long now_time = get_tick_count (); int cycle_counter = 0; int still_running = 0; struct timeval timeout; mperform_smooth (bctx, &now_time, &still_running); while (max_timeout_msec > 0) { int rc, maxfd; fd_set fdread, fdwrite, fdexcep; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); timeout.tv_sec = 0; timeout.tv_usec = 250000; max_timeout_msec -= timeout.tv_sec*1000 + timeout.tv_usec * 0.001; curl_multi_fdset(bctx->multiple_handle, &fdread, &fdwrite, &fdexcep, &maxfd); //fprintf (stderr, "%s - Waiting for %d clients with seconds %f.\n", //name, still_running, max_timeout); rc = select (maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); switch(rc) { case -1: /* select error */ break; case 0: /* timeout */ now_time = get_tick_count (); default: /* timeout or readable/writable sockets */ mperform_smooth (bctx, &now_time, &still_running); break; } if (!(++cycle_counter % TIME_RECALCULATION_CYCLES_NUM)) { now_time = get_tick_count (); } dispatch_expired_timers (bctx, now_time); } return 0; }
/* * Fills internal buffer up to want bytes. * returns when size reached or transfer ended */ int fill_internal_buffer(churl_context* context, int want) { fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd; struct timeval timeout; int nfds, curl_error; /* attempt to fill buffer */ while (context->curl_still_running && ((context->download_buffer->top - context->download_buffer->bot) < want)) { FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); /* * Allow canceling a query while waiting for input from remote service */ CHECK_FOR_INTERRUPTS(); /* set a suitable timeout to fail on */ timeout.tv_sec = 5; timeout.tv_usec = 0; /* get file descriptors from the transfers */ if (CURLE_OK != (curl_error = curl_multi_fdset(context->multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd))) elog(ERROR, "internal error: curl_multi_fdset failed (%d - %s)", curl_error, curl_easy_strerror(curl_error)); if (maxfd <= 0) { context->curl_still_running = 0; break; } if (-1 == (nfds = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout))) { if (errno == EINTR || errno == EAGAIN) continue; elog(ERROR, "internal error: select failed on curl_multi_fdset (maxfd %d) (%d - %s)", maxfd, errno, strerror(errno)); } if (nfds > 0) multi_perform(context); } return 0; }
/** * downloadTimerCallback. At each call, check and perform transfers. */ void BCResourceHandleManagerCURL::downloadTimerCallback(WebCore::Timer<BCResourceHandleManagerCURL>* timer) { fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd = 0; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); curl_multi_fdset(m_curlMultiHandle, &fdread, &fdwrite, &fdexcep, &maxfd); struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds WebCore::setDeferringTimers(true); int rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); WebCore::setDeferringTimers(false); if (-1 == rc) { // we may end here if a timer fires on Linux (signals interrupt select) // so we must either set timeout to 0, or enclose select() // between setDeferringTimers() to disable timers #ifndef NDEBUG printf("bad: select() returned -1\n"); #endif return; } int runningHandles = 0; CURLMcode curlCode = CURLM_CALL_MULTI_PERFORM; while (CURLM_CALL_MULTI_PERFORM == curlCode) { curlCode = curl_multi_perform(m_curlMultiHandle, &runningHandles); } // check the curl messages indicating completed transfers // and free their resources int messagesInQueue; while (CURLMsg* msg = curl_multi_info_read(m_curlMultiHandle, &messagesInQueue)) { CURL* handle = msg->easy_handle; assert(handle); BCResourceHandleCURL* job; curl_easy_getinfo(handle, CURLINFO_PRIVATE, &job); job->processMessage(msg); } if (!m_downloadTimer.isActive() && (runningHandles > 0)) m_downloadTimer.startOneShot(pollTimeSeconds); }
size_t Curlreader_Read(CURLREADER *r, void *ptr, size_t size, size_t nmemb) { size*=nmemb; while (r->still_running && (r->sbuf.len - r->pos) < size) { fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd; struct timeval timeout; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); timeout.tv_sec = 10; timeout.tv_usec = 0; r->errM = curl_multi_fdset(r->curlmh, &fdread, &fdwrite, &fdexcep, &maxfd); if (r->errM != CURLM_OK) return 0; switch(select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout)) { case -1: r->still_running = 0; #ifdef _DEBUG fputs("Curlreader select() error!", stderr); #endif break; case 0: /* timeout */ default: while((r->errM = curl_multi_perform(r->curlmh, &r->still_running)) == CURLM_CALL_MULTI_PERFORM); if (r->errM != CURLM_OK) return 0; break; } } if (r->pos == (size_t)r->sbuf.len) return 0; nmemb = r->sbuf.len - r->pos; if (nmemb < size) { memcpy(ptr, r->sbuf.str+r->pos, nmemb); r->pos += nmemb; return nmemb; } memcpy(ptr, r->sbuf.str+r->pos, size); r->pos += size; return size; }
int http_get_fds(fd_set *fdr, fd_set *fdw, fd_set *fde, void *d){ struct http_data *data=(struct http_data*)d; int maxfd; int ret; if(data->cm==NULL) return -2; if((ret=curl_multi_fdset(data->cm,fdr,fdw,fde,&maxfd))){ return -3; } return maxfd; }
static void perform() { fd_set fdread, fdwrite, fdexcep; int ret; int maxfd; int connections = 0; select_timeout.tv_sec = 0; select_timeout.tv_usec = 50000; do { do { ret = check_multi(curl_multi_perform(curlm, &connections), "curl_multi_perform() failed"); } while (ret == CURLM_CALL_MULTI_PERFORM); if (show_progress) { print_progress(); } if (connections) { size_t i; for (i = 0; i < num_slices; ++i) { if (slices[i].finished) slice_finalize(&slices[i]); } FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); check_multi(curl_multi_fdset(curlm, &fdread, &fdwrite, &fdexcep, &maxfd), "curl_multi_fdset() failed"); ret = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &select_timeout); if (ret == -1) die("select() error: %s\n", strerror(errno)); } } while (connections); size_t i; for (i = 0; i < num_slices; ++i) { if (slices[i].curl) slice_finalize(&slices[i]); } }
static int l_multi_perform_internal (lua_State *L) { l_multi_userdata *privatep = LUACURL_PRIVATE_MULTIP_UPVALUE(L, 1); CURLM *curlm = privatep->curlm; CURLMcode rc; int remain; int n; l_multi_perform_internal_getfrombuffer(L, privatep); /* no data in buffer: try another perform */ while (lua_isnil(L, -1)) { lua_pop(L, -1); if (privatep->last_remain == 0) return 0; /* returns nil*/ while ((rc = curl_multi_perform(curlm, &remain)) == CURLM_CALL_MULTI_PERFORM); /* loop */ if (rc != CURLM_OK) luaL_error(L, "cannot perform: %s", curl_multi_strerror(rc)); privatep->last_remain = remain; /* got data ? */ l_multi_perform_internal_getfrombuffer(L, privatep); /* block for more data */ if (lua_isnil(L, -1) && remain) { fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); if ((rc = curl_multi_fdset(curlm, &fdread, &fdwrite, &fdexcep, &maxfd)) != CURLM_OK) luaL_error(L, "curl_multi_fdset: %s", curl_multi_strerror(rc)); if ((n = select(maxfd+1, &fdread, &fdwrite, &fdexcep, NULL)) < 0) luaL_error(L, "select: %s", strerror(errno)); } } /* unpack table */ n = lua_gettop(L); lua_rawgeti(L, n, 1); /* data */ lua_rawgeti(L, n, 2); /* type */ lua_rawgeti(L, n, 3); /* easy */ lua_remove(L, n); return 3; }
static int fetch_curl_fdset(lwc_string *scheme, fd_set *read_set, fd_set *write_set, fd_set *error_set) { CURLMcode code; int maxfd = -1; code = curl_multi_fdset(fetch_curl_multi, read_set, write_set, error_set, &maxfd); assert(code == CURLM_OK); return maxfd; }
static CURLMcode perform(CURLM * multi) { int handles, maxfd; CURLMcode code; fd_set fdread, fdwrite, fdexcep; struct timeval mp_start; char mp_timedout = FALSE; mp_timedout = FALSE; mp_start = tutil_tvnow(); for (;;) { code = curl_multi_perform(multi, &handles); if (tutil_tvdiff(tutil_tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) { mp_timedout = TRUE; break; } if (handles <= 0) return CURLM_OK; switch (code) { case CURLM_OK: break; case CURLM_CALL_MULTI_PERFORM: continue; default: return code; } FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); if (maxfd < 0) return (CURLMcode) ~CURLM_OK; if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, 0) == -1) return (CURLMcode) ~CURLM_OK; } /* We only reach this point if (mp_timedout) */ if (mp_timedout) fprintf(stderr, "mp_timedout\n"); fprintf(stderr, "ABORTING TEST, since it seems " "that it would have run forever.\n"); return (CURLMcode) ~CURLM_OK; }
static gpointer selectThread(gpointer data) { int fdCount; struct timeval timeout; assert(data == 0); /* Just to get rid of unused param warning */ D((stderr, "selectThread\n")); g_mutex_lock(curlSrc->mutex); D((stderr, "selectThread: got lock\n")); curlSrc->selectRunning = TRUE; while (curlSrc->selectRunning) { FD_ZERO(&curlSrc->fdRead); FD_ZERO(&curlSrc->fdWrite); FD_ZERO(&curlSrc->fdExc); curlSrc->fdMax = -1; /* What fds does libcurl want us to poll? */ curl_multi_fdset(curlSrc->multiHandle, &curlSrc->fdRead, &curlSrc->fdWrite, &curlSrc->fdExc, &curlSrc->fdMax); timeout.tv_sec = GLIBCURL_TIMEOUT / 1000; timeout.tv_usec = (GLIBCURL_TIMEOUT % 1000) * 1000; fdCount = select(curlSrc->fdMax + 1, &curlSrc->fdRead, &curlSrc->fdWrite, &curlSrc->fdExc, &timeout); D((stderr, "selectThread: select() fdCount=%d\n", fdCount)); g_atomic_int_inc(&curlSrc->gtkBlockAndWait); /* "GTK thread, block!" */ D((stderr, "selectThread: waking up GTK thread %d\n", curlSrc->gtkBlockAndWait)); /* GTK thread will almost immediately block in prepare() */ g_main_context_wakeup(NULL); /* Now unblock GTK thread, continue after it signals us */ D((stderr, "selectThread: pre-wait\n")); g_cond_wait(curlSrc->cond, curlSrc->mutex); D((stderr, "selectThread: post-wait\n")); } curlSrc->selectThread = NULL; D((stderr, "selectThread: exit\n")); g_mutex_unlock(curlSrc->mutex); return NULL; }
void HttpProtocol::getFdSet(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *exc_fd_set, int *max_fd) { LOG(0, "enter getFdSet, read_fd_set = %p, write_fd_set = %p, exc_fd_set = %p, max_fd = %p\n", read_fd_set, write_fd_set, exc_fd_set, max_fd); // check task status. CURLMcode retm = curl_multi_fdset(d->handle, read_fd_set, write_fd_set, exc_fd_set, max_fd); if (retm != CURLM_OK) { throw DOWNLOADEXCEPTION(retm, "CURL", curl_multi_strerror(retm)); } }
// Ask curl_multi for its handles directly // This is preferable as we get to know which // are blocking on reads, and which on writes. int CurlMultiAwait::addLowHandles(req::ptr<CurlMultiResource> multi) { fd_set read_fds, write_fds; int max_fd = -1, count = 0; FD_ZERO(&read_fds); FD_ZERO(&write_fds); if ((CURLM_OK != curl_multi_fdset(multi->get(), &read_fds, &write_fds, nullptr, &max_fd)) || (max_fd < 0)) { return count; } for (int i = 0 ; i <= max_fd; ++i) { int events = 0; if (FD_ISSET(i, &read_fds)) events |= AsioEventHandler::READ; if (FD_ISSET(i, &write_fds)) events |= AsioEventHandler::WRITE; if (events) { addHandle(i, events); ++count; } } return count; }
static int wait_perform() { fd_set rd, wr, ex; int maxfd, nrunning; long timeout; CURLMcode errm; FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); if (curl_multi_fdset(curl.multi, &rd, &wr, &ex, &maxfd) != CURLM_OK) maxfd = -1, timeout = 1000; else if (maxfd < 0) timeout = 100; // as recommended by curl_multi_fdset(3) else { if (curl_multi_timeout(curl.multi, &timeout) != CURLM_OK) timeout = 1000; else if (timeout < 0) timeout = 10000; // as recommended by curl_multi_timeout(3) } if (timeout > 0 && ! curl.perform_again) { struct timeval tval; tval.tv_sec = (timeout / 1000); tval.tv_usec = (timeout % 1000) * 1000; if (select(maxfd + 1, &rd, &wr, &ex, &tval) < 0) return -1; } errm = curl_multi_perform(curl.multi, &nrunning); curl.perform_again = 0; if (errm == CURLM_CALL_MULTI_PERFORM) curl.perform_again = 1; else if (errm != CURLM_OK) { errno = multi_errno(errm); return -1; } if (nrunning < curl.nrunning) process_messages(); return 0; }
/** * Run all deferred multi calls and wait for the result * * @param sdb the SimpleDB handle * @return the result */ int sdb_multi_run_and_wait(struct SDB* sdb) { // This code was inspired by the implementation of readdir() in s3fs by Randy Rizun int running, r; while (curl_multi_perform(sdb->curl_multi, &running) == CURLM_CALL_MULTI_PERFORM) usleep(5); while (running) { fd_set read_fd_set; fd_set write_fd_set; fd_set exc_fd_set; FD_ZERO(&read_fd_set); FD_ZERO(&write_fd_set); FD_ZERO(&exc_fd_set); long ms; if ((r = curl_multi_timeout(sdb->curl_multi, &ms)) != CURLM_OK) return SDB_CURLM_ERROR(r); if (ms < 0) ms = 50; if (ms > 0) { struct timeval timeout; timeout.tv_sec = 1000 * ms / 1000000; timeout.tv_usec = 1000 * ms % 1000000; int max_fd; if ((r = curl_multi_fdset(sdb->curl_multi, &read_fd_set, &write_fd_set, &exc_fd_set, &max_fd)) != CURLM_OK) return SDB_CURLM_ERROR(r); if (select(max_fd + 1, &read_fd_set, &write_fd_set, &exc_fd_set, &timeout) == -1) return SDB_E_FD_ERROR; } while (curl_multi_perform(sdb->curl_multi, &running) == CURLM_CALL_MULTI_PERFORM) usleep(5); } return SDB_OK; }
/* * 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/"); curl_easy_setopt(http_handle, CURLOPT_DEBUGFUNCTION, my_trace); curl_easy_setopt(http_handle, CURLOPT_VERBOSE, TRUE); /* 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; }
/* * Simply download a HTTP file. */ int main(void) { 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.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_cleanup(multi_handle); curl_easy_cleanup(http_handle); return 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; MHD_socket max; int running; struct CURLMsg *msg; time_t start; struct timeval tv; unsigned int pos = 0; int done_flag = 0; multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_DEBUG, 1082, NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); if (d == NULL) return 256; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1082/hello_world"); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 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, 1); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 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, 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)) { 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); 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); 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) { 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; }
static void curl_main () { fd_set rs; fd_set ws; fd_set es; int max; struct GNUNET_NETWORK_FDSet nrs; struct GNUNET_NETWORK_FDSet nws; struct GNUNET_TIME_Relative delay; long timeout; int running; struct CURLMsg *msg; max = 0; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); curl_multi_perform (multi, &running); if (running == 0) { GNUNET_assert (NULL != (msg = curl_multi_info_read (multi, &running))); if (msg->msg == CURLMSG_DONE) { if (msg->data.result != CURLE_OK) { fprintf (stderr, "%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); global_ret = 1; } } curl_multi_remove_handle (multi, curl); curl_multi_cleanup (multi); curl_easy_cleanup (curl); curl = NULL; multi = NULL; if (cbc.pos != strlen ("/hello_world")) { GNUNET_break (0); global_ret = 2; } if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) { GNUNET_break (0); global_ret = 3; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download complete, shutting down!\n"); do_shutdown (); return; } GNUNET_assert (CURLM_OK == curl_multi_fdset (multi, &rs, &ws, &es, &max)); if ( (CURLM_OK != curl_multi_timeout (multi, &timeout)) || (-1 == timeout) ) delay = GNUNET_TIME_UNIT_SECONDS; else delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout); GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max + 1); curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, &nrs, &nws, &curl_task, NULL); }
CURLcode CURLNetRequest::CURLHolder::perform() { activate(); int const CHUNK = 1; long noactivity = 0; CURLcode result; for(;;) { int running; CURLMcode err = curl_multi_perform(m_curlm, &running); if (err == CURLM_CALL_MULTI_PERFORM) continue; if (err != CURLM_OK) { RAWLOG_ERROR1("curl_multi_perform error: %d", (int)err); } else { if (running > 0 && noactivity < timeout) { RAWTRACE("we still have active transfers but no data ready at this moment; waiting..."); fd_set rfd, wfd, efd; int n = 0; FD_ZERO(&rfd); FD_ZERO(&wfd); FD_ZERO(&efd); err = curl_multi_fdset(m_curlm, &rfd, &wfd, &efd, &n); if (err == CURLM_OK) { if (n > 0) { timeval tv; tv.tv_sec = CHUNK; tv.tv_usec = 0; int e = select(n + 1, &rfd, &wfd, &efd, &tv); if (e < 0) { RAWLOG_ERROR1("select (on curl handles) error: %d", errno); } else { if (e == 0) { RAWTRACE("No activity on sockets, check them again"); noactivity += CHUNK; } else noactivity = 0; continue; } } } else { RAWLOG_ERROR1("curl_multi_fdset error: %d", (int)err); } } } int nmsgs; CURLMsg *msg = curl_multi_info_read(m_curlm, &nmsgs); result = CURLE_OK; if (msg && msg->msg == CURLMSG_DONE) result = msg->data.result; if (result == CURLE_OK && noactivity >= timeout) result = CURLE_OPERATION_TIMEDOUT; if (result == CURLE_OK || result == CURLE_PARTIAL_FILE) RAWTRACE("Operation completed successfully"); else RAWLOG_ERROR2("Operation finished with error %d: %s", (int)result, curl_easy_strerror(result)); break; } deactivate(); return result; }
/*************************************************************************** * 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; }
static void tr_webThreadFunc( void * vsession ) { int unused; CURLM * multi; struct tr_web * web; int taskCount = 0; 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; multi = curl_multi_init( ); session->web = web; for( ;; ) { long msec; CURLMsg * msg; CURLMcode mcode; struct tr_web_task * task; if( web->close_mode == TR_WEB_CLOSE_NOW ) break; if( ( web->close_mode == TR_WEB_CLOSE_WHEN_IDLE ) && !taskCount ) 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, 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( 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 )) { struct tr_web_task * task; CURL * e = msg->easy_handle; curl_easy_getinfo( e, CURLINFO_PRIVATE, (void*)&task ); curl_easy_getinfo( e, CURLINFO_RESPONSE_CODE, &task->code ); 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; } } } /* cleanup */ curl_multi_cleanup( multi ); tr_lockFree( web->taskLock ); tr_free( web ); session->web = NULL; }
int test(char *URL) { CURL *easy; CURLM *multi_handle; int still_running; /* keep number of running handles */ CURLMsg *msg; /* for picking up messages with the transfer status */ int msgs_left; /* how many messages are left */ /* Allocate one CURL handle per transfer */ easy = curl_easy_init(); /* init a multi stack */ multi_handle = curl_multi_init(); /* add the individual transfer */ curl_multi_add_handle(multi_handle, easy); /* set the options (I left out a few, you'll get the point anyway) */ curl_easy_setopt(easy, CURLOPT_URL, URL); curl_easy_setopt(easy, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)testDataSize); curl_easy_setopt(easy, CURLOPT_POSTFIELDS, testData); /* 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 */ 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: /* timeout */ default: /* action */ curl_multi_perform(multi_handle, &still_running); break; } } while(still_running); /* See how the transfers went */ while((msg = curl_multi_info_read(multi_handle, &msgs_left))) { if(msg->msg == CURLMSG_DONE) { printf("HTTP transfer completed with status %d\n", msg->data.result); break; } } curl_multi_cleanup(multi_handle); /* Free the CURL handles */ curl_easy_cleanup(easy); return 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 max; 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_DEBUG, 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, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); /* note that the string below intentionally uses the various ways cookies can be specified to exercise the parser! Do not change! */ curl_easy_setopt (c, CURLOPT_COOKIE, "name1=var1; name2=var2,name3 ;name4=\"var4 with spaces\";"); 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)) { 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); 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); 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) { 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; }
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; int max; 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_DEBUG | MHD_USE_SSL, 1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, MHD_OPTION_END); if (d == NULL) return 256; char *aes256_sha = "AES256-SHA"; if (curl_uses_nss_ssl() == 0) { aes256_sha = "rsa_aes_256_sha"; } c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "https://localhost:1082/hello_world"); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); /* TLS options */ curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3); curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, aes256_sha); curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0); 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, 15L); /* 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)) { 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); 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); 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) { 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; }
static int testExternalPost () { 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; struct curl_httppost *pd; int i; multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_ERROR_LOG */ , 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL, 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://localhost:1082/hello_world"); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); pd = make_form (); curl_easy_setopt (c, CURLOPT_HTTPPOST, pd); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 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, 15L); // NOTE: use of CONNECTTIMEOUT without also // setting NOSIGNAL results in really weird // crashes on my system! curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); mret = curl_multi_add_handle (multi, c); if (mret != CURLM_OK) { curl_multi_cleanup (multi); curl_formfree (pd); 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); curl_formfree (pd); 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); curl_formfree (pd); 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); } curl_formfree (pd); } fprintf (stderr, "\n"); zzuf_socat_stop (); MHD_stop_daemon (d); return 0; }