From aab30433237de57b4bc8e7d968801f083dfb37af Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Thu, 28 Aug 2014 14:06:24 +0500 Subject: [PATCH] Fix. Implement `wait` method based on `select` function. --- doc/lcurl.ldoc | 4 +-- examples/multi.lua | 24 ++++++++++++++++ msvc/lcurl.vcproj | 2 +- src/lcmulti.c | 71 ++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 examples/multi.lua diff --git a/doc/lcurl.ldoc b/doc/lcurl.ldoc index 996d9a3..d14cbb5 100644 --- a/doc/lcurl.ldoc +++ b/doc/lcurl.ldoc @@ -375,14 +375,14 @@ function setopt_timerfunction() end --- Polls on all easy objects in a multi object. -- --- @tparam number timeout millisecnds timeout +-- @tparam[opt] number timeout milliseconds timeout. By default it is `multi:timeout()`. -- @treturn number number of affected objects -- function wait() end --- How long to wait for action before proceeding. -- --- @treturn number timeout millisecnds timeout +-- @treturn number timeout milliseconds timeout -- function timeout() end diff --git a/examples/multi.lua b/examples/multi.lua new file mode 100644 index 0000000..666cc72 --- /dev/null +++ b/examples/multi.lua @@ -0,0 +1,24 @@ +local cURL = require("lcurl") + +local f1 = assert(io.open("lua.html","a+")) + +local f2 = assert(io.open("luajit.html","a+")) + +c = cURL.easy() + :setopt_url("http://www.lua.org/") + :setopt_writefunction(f1) + +c2 = cURL.easy() + :setopt_url("http://luajit.org/") + :setopt_writefunction(f2) + +m = cURL.multi() + :add_handle(c) + :add_handle(c2) + +while m:perform() > 0 do + m:wait() +end + +print(m:info_read()) +print(m:info_read()) diff --git a/msvc/lcurl.vcproj b/msvc/lcurl.vcproj index 85ac04a..da42396 100644 --- a/msvc/lcurl.vcproj +++ b/msvc/lcurl.vcproj @@ -61,7 +61,7 @@ /> +#else +# include +#endif + #include "lcurl.h" #include "lceasy.h" #include "lcmulti.h" @@ -109,21 +119,68 @@ static int lcurl_multi_info_read(lua_State *L){ return 1; } -#if LCURL_CURL_VER_GE(7,28,0) - static int lcurl_multi_wait(lua_State *L){ lcurl_multi_t *p = lcurl_getmulti(L); - int n, ms = luaL_optint(L, 2, 0); + CURLMcode code; + int maxfd; long ms; + + if(lua_isnoneornil(L, 2)){ + code = curl_multi_timeout(p->curl, &ms); + if(code != CURLM_OK){ + lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code); + } + } + else{ + ms = luaL_checklong(L, 2); + } + + if(ms < 0){ + /* if libcurl returns a -1 timeout here, it just means that libcurl + currently has no stored timeout value. You must not wait too long + (more than a few seconds perhaps) before you call + curl_multi_perform() again. + */ + ms = 1000; + } + +#if LCURL_CURL_VER_GE(7,28,0) //! @todo supports extra_fds - CURLMcode code = curl_multi_wait(p->curl, 0, 0, ms, &n); + code = curl_multi_wait(p->curl, 0, 0, ms, &maxfd); if(code != CURLM_OK){ lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code); } - lua_pushnumber(L, n); + lua_pushnumber(L, maxfd); return 1; -} +#else + { + fd_set fdread, fdwrite, fdexcep; + FD_ZERO(&fdread); + FD_ZERO(&fdwrite); + FD_ZERO(&fdexcep); + + code = curl_multi_fdset(p->curl, &fdread, &fdwrite, &fdexcep, &maxfd); + if(code != CURLM_OK){ + lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code); + } + + //if(maxfd > 0) + { + struct timeval tv; + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms % 1000) * 1000; + + maxfd = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv); + if(maxfd < 0){ + //! @fixme return error + } + } + + lua_pushnumber(L, maxfd); + return 1; + } #endif +} static int lcurl_multi_timeout(lua_State *L){ lcurl_multi_t *p = lcurl_getmulti(L); @@ -344,9 +401,7 @@ static const struct luaL_Reg lcurl_multi_methods[] = { {"perform", lcurl_multi_perform }, {"info_read", lcurl_multi_info_read }, {"setopt", lcurl_multi_setopt }, -#if LCURL_CURL_VER_GE(7,28,0) {"wait", lcurl_multi_wait }, -#endif {"timeout", lcurl_multi_timeout }, #define OPT_ENTRY(L, N, T, S) { "setopt_"#L, lcurl_multi_set_##N },