diff --git a/doc/lcurl.ldoc b/doc/lcurl.ldoc index 22fb583..83be79a 100644 --- a/doc/lcurl.ldoc +++ b/doc/lcurl.ldoc @@ -312,6 +312,16 @@ function perfom() end -- @treturn[3] error error code function info_read() end +--- Set options. +-- +-- @tparam number opt one of `curl.OPT_MULTI_XXX` constant +-- @param ... value +-- @treturn easy self +-- +-- @usage +-- c:setopt(curl.OPT_MULTI_MAXCONNECTS, 10) +function setopt() end + --- End multi session. -- function close() end diff --git a/msvc/lcurl.vcproj b/msvc/lcurl.vcproj index ffb66c7..42685ec 100644 --- a/msvc/lcurl.vcproj +++ b/msvc/lcurl.vcproj @@ -251,6 +251,10 @@ RelativePath="..\src\lcopteasy.h" > + + diff --git a/src/lcmulti.c b/src/lcmulti.c index 83e826f..4ba54b8 100644 --- a/src/lcmulti.c +++ b/src/lcmulti.c @@ -108,6 +108,91 @@ static int lcurl_multi_info_read(lua_State *L){ return 1; } +//{ OPTIONS +static int lcurl_opt_set_long_(lua_State *L, int opt){ + lcurl_multi_t *p = lcurl_getmulti(L); + long val; CURLMcode code; + + if(lua_isboolean(L, 2)) val = lua_toboolean(L, 2); + else{ + luaL_argcheck(L, lua_type(L, 2) == LUA_TNUMBER, 2, "number or boolean expected"); + val = luaL_checklong(L, 2); + } + + code = curl_multi_setopt(p->curl, opt, val); + if(code != CURLM_OK){ + return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code); + } + lua_settop(L, 1); + return 1; +} + +static int lcurl_opt_set_string_array_(lua_State *L, int opt){ + lcurl_multi_t *p = lcurl_getmulti(L); + CURLMcode code; + int n; + luaL_argcheck(L, lua_type(L, 2) == LUA_TTABLE, 2, "array expected"); + n = lua_rawlen(L, 2); + if(n == 0){ + char *val[] = {NULL}; + code = curl_multi_setopt(p->curl, opt, val); + } + else{ + int i; + char const* *val = malloc(sizeof(char*) * (n + 1)); + if(!*val){ + return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, CURLM_OUT_OF_MEMORY); + } + for(i = 1; i <= n; ++i){ + lua_rawgeti(L, 2, i); + val[i-1] = lua_tostring(L, -1); + lua_pop(L, 1); + } + val[n] = NULL; + code = curl_multi_setopt(p->curl, opt, val); + free((void*)val); + } + + if(code != CURLM_OK){ + return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code); + } + + lua_settop(L, 1); + return 1; +} + +#define LCURL_LNG_OPT(N, S) static int lcurl_multi_set_##N(lua_State *L){\ + return lcurl_opt_set_long_(L, CURLMOPT_##N);\ +} + +#define LCURL_STR_ARR_OPT(N, S) static int lcurl_multi_set_##N(lua_State *L){\ + return lcurl_opt_set_string_array_(L, CURLMOPT_##N);\ +} + +#define OPT_ENTRY(L, N, T, S) LCURL_##T##_OPT(N, S) + +#include "lcoptmulti.h" + +#undef OPT_ENTRY +#undef LCURL_LNG_OPT +#undef LCURL_STR_ARR_OPT + +static int lcurl_multi_setopt(lua_State *L){ + lcurl_multi_t *p = lcurl_getmulti(L); + int opt = luaL_checklong(L, 2); + lua_remove(L, 2); + +#define OPT_ENTRY(l, N, T, S) case CURLMOPT_##N: return lcurl_multi_set_##N(L); + switch(opt){ + #include "lcoptmulti.h" + } +#undef OPT_ENTRY + + return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, CURLM_UNKNOWN_OPTION); +} + +//} + //} static const struct luaL_Reg lcurl_multi_methods[] = { @@ -115,6 +200,11 @@ static const struct luaL_Reg lcurl_multi_methods[] = { {"remove_handle", lcurl_multi_remove_handle }, {"perform", lcurl_multi_perform }, {"info_read", lcurl_multi_info_read }, + {"setopt", lcurl_multi_setopt }, + +#define OPT_ENTRY(L, N, T, S) { "setopt_"#L, lcurl_multi_set_##N }, + #include "lcoptmulti.h" +#undef OPT_ENTRY {"close", lcurl_multi_cleanup }, {"__gc", lcurl_multi_cleanup }, @@ -123,6 +213,9 @@ static const struct luaL_Reg lcurl_multi_methods[] = { }; static const lcurl_const_t lcurl_multi_opt[] = { +#define OPT_ENTRY(L, N, T, S) { "OPT_MULTI_"#N, CURLMOPT_##N }, +#include "lcoptmulti.h" +#undef OPT_ENTRY {NULL, 0} }; diff --git a/src/lcoptmulti.h b/src/lcoptmulti.h new file mode 100644 index 0000000..654f07e --- /dev/null +++ b/src/lcoptmulti.h @@ -0,0 +1,12 @@ + +OPT_ENTRY(pipelining, PIPELINING, LNG, 0 ) +OPT_ENTRY(maxconnects, MAXCONNECTS, LNG, 0 ) +#if LCURL_CURL_VER_GE(7,30,0) +OPT_ENTRY(max_host_connections, MAX_HOST_CONNECTIONS, LNG, 0 ) +OPT_ENTRY(max_pipeline_length, MAX_PIPELINE_LENGTH, LNG, 0 ) +OPT_ENTRY(content_length_penalty_size, CONTENT_LENGTH_PENALTY_SIZE, LNG, 0 ) +OPT_ENTRY(chunk_length_penalty_size, CHUNK_LENGTH_PENALTY_SIZE, LNG, 0 ) +OPT_ENTRY(pipelining_site_bl, PIPELINING_SITE_BL, STR_ARR, 0 ) +OPT_ENTRY(pipelining_server_bl, PIPELINING_SERVER_BL, STR_ARR, 0 ) +OPT_ENTRY(max_total_connections, MAX_TOTAL_CONNECTIONS, LNG, 0 ) +#endif