Implement basic multi iterface.
This commit is contained in:
parent
bf72021579
commit
d18fb3adca
39
README.md
39
README.md
@ -56,6 +56,43 @@ curl:easy()
|
|||||||
)
|
)
|
||||||
:perform()
|
:perform()
|
||||||
:close()
|
:close()
|
||||||
|
```
|
||||||
|
|
||||||
|
```Lua
|
||||||
|
-- Multi FTP Upload
|
||||||
|
|
||||||
|
-- We get error E_LOGIN_DENIED for this operation
|
||||||
|
e1 = curl:easy()
|
||||||
|
:setopt_url("ftp://moteus:999999@127.0.0.1/test1.dat")
|
||||||
|
:setopt_upload(true)
|
||||||
|
:setopt_readfunction(
|
||||||
|
function(t) return table.remove(t) end, {"1111", "2222"}
|
||||||
|
)
|
||||||
|
|
||||||
|
e2 = curl:easy()
|
||||||
|
:setopt_url("ftp://moteus:123456@127.0.0.1/test2.dat")
|
||||||
|
:setopt_upload(true)
|
||||||
|
:setopt_readfunction(get_bin_by(("e"):rep(1000), 5))
|
||||||
|
|
||||||
|
m = curl:multi()
|
||||||
|
m:add_handle(e1)
|
||||||
|
m:add_handle(e2)
|
||||||
|
|
||||||
|
while m:perform() > 0 do end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
h, ok, err = m:info_read()
|
||||||
|
if h == 0 then break end
|
||||||
|
|
||||||
|
if h == e1 then
|
||||||
|
assert(ok == nil)
|
||||||
|
assert(err:name() == "LOGIN_DENIED")
|
||||||
|
assert(err:no() == curl.E_LOGIN_DENIED)
|
||||||
|
end
|
||||||
|
|
||||||
|
if h == e2 then
|
||||||
|
assert(ok == true)
|
||||||
|
end
|
||||||
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ function setopt_writefunction() end
|
|||||||
|
|
||||||
--- Set writer function.
|
--- Set writer function.
|
||||||
--
|
--
|
||||||
-- This call same as easy:set_writefunction(writer.write, writer)
|
-- This call same as easy:setopt_writefunction(writer.write, writer)
|
||||||
--
|
--
|
||||||
-- @tparam object writer
|
-- @tparam object writer
|
||||||
-- @return[1] self
|
-- @return[1] self
|
||||||
@ -205,7 +205,7 @@ function setopt_headerfunction() end
|
|||||||
|
|
||||||
--- Set header function.
|
--- Set header function.
|
||||||
--
|
--
|
||||||
-- This call same as easy:set_headerfunction(writer.header, writer)
|
-- This call same as easy:setopt_headerfunction(writer.header, writer)
|
||||||
--
|
--
|
||||||
-- @tparam object writer
|
-- @tparam object writer
|
||||||
-- @return[1] self
|
-- @return[1] self
|
||||||
@ -228,7 +228,7 @@ function setopt_readfunction() end
|
|||||||
|
|
||||||
--- Set reader function.
|
--- Set reader function.
|
||||||
--
|
--
|
||||||
-- This call same as easy:set_readfunction(reader.read, reader)
|
-- This call same as easy:setopt_readfunction(reader.read, reader)
|
||||||
--
|
--
|
||||||
-- @tparam object reader
|
-- @tparam object reader
|
||||||
-- @return[1] self
|
-- @return[1] self
|
||||||
@ -252,17 +252,19 @@ function setopt_readfunction() end
|
|||||||
--
|
--
|
||||||
function setopt_progressfunction() end
|
function setopt_progressfunction() end
|
||||||
|
|
||||||
--- Set reader function.
|
--- Set progress function.
|
||||||
--
|
--
|
||||||
-- This call same as easy:set_readfunction(reader.read, reader)
|
-- This call same as easy:setopt_progressfunction(progress.progress, progress)
|
||||||
--
|
--
|
||||||
-- @tparam object reader
|
-- @tparam object progress
|
||||||
-- @return[1] self
|
-- @return[1] self
|
||||||
--
|
--
|
||||||
function setopt_readfunction() end
|
function setopt_progressfunction() end
|
||||||
|
|
||||||
--- Set HTTP multipart/formdata
|
--- Set HTTP multipart/formdata
|
||||||
--
|
--
|
||||||
|
-- Caller does not have to save data.
|
||||||
|
--
|
||||||
-- @tparam httpform data
|
-- @tparam httpform data
|
||||||
-- @return[1] self
|
-- @return[1] self
|
||||||
function setopt_httpform() end
|
function setopt_httpform() end
|
||||||
@ -281,8 +283,37 @@ end
|
|||||||
--
|
--
|
||||||
do
|
do
|
||||||
|
|
||||||
--- End multi session
|
--- Add Easy object.
|
||||||
--
|
--
|
||||||
|
-- Caller must ensure that easy object is alive until end of operation.
|
||||||
|
--
|
||||||
|
-- @treturn multi self
|
||||||
|
-- @tparam easy handle
|
||||||
|
function add_handle() end
|
||||||
|
|
||||||
|
--- Remove Easy object.
|
||||||
|
--
|
||||||
|
-- @tparam easy handle
|
||||||
|
-- @treturn multi self
|
||||||
|
function remove_handle() end
|
||||||
|
|
||||||
|
--- reads/writes available data from each easy handle.
|
||||||
|
--
|
||||||
|
-- @treturn number handles number of active easy handles
|
||||||
|
function perfom() end
|
||||||
|
|
||||||
|
--- Read multi stack informationals.
|
||||||
|
--
|
||||||
|
-- @treturn[1] number 0 there no informationals
|
||||||
|
-- @treturn[2] easy handle
|
||||||
|
-- @treturn[2] boolean true
|
||||||
|
-- @treturn[3] easy handle
|
||||||
|
-- @treturn[3] nil
|
||||||
|
-- @treturn[3] error error code
|
||||||
|
function info_read() end
|
||||||
|
|
||||||
|
--- End multi session.
|
||||||
|
--
|
||||||
function close() end
|
function close() end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -15,6 +15,9 @@ int lcurl_multi_create(lua_State *L, int error_mode){
|
|||||||
lcurl_multi_t *p = lutil_newudatap(L, lcurl_multi_t, LCURL_MULTI);
|
lcurl_multi_t *p = lutil_newudatap(L, lcurl_multi_t, LCURL_MULTI);
|
||||||
p->curl = curl_multi_init();
|
p->curl = curl_multi_init();
|
||||||
if(!p->curl) return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, CURLM_INTERNAL_ERROR);
|
if(!p->curl) return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, CURLM_INTERNAL_ERROR);
|
||||||
|
p->err_mode = error_mode;
|
||||||
|
lcurl_util_new_weak_table(L, "v");
|
||||||
|
p->h_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -32,15 +35,89 @@ static int lcurl_multi_cleanup(lua_State *L){
|
|||||||
p->curl = NULL;
|
p->curl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(p->h_ref != LUA_NOREF){
|
||||||
|
luaL_unref(L, LCURL_LUA_REGISTRY, p->h_ref);
|
||||||
|
p->h_ref = LUA_NOREF;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lcurl_multi_add_handle(lua_State *L){
|
||||||
|
lcurl_multi_t *p = lcurl_getmulti(L);
|
||||||
|
lcurl_easy_t *e = lcurl_geteasy_at(L, 2);
|
||||||
|
CURLMcode code = curl_multi_add_handle(p->curl, e->curl);
|
||||||
|
if(code != CURLM_OK){
|
||||||
|
lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
|
||||||
|
}
|
||||||
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
|
||||||
|
lua_pushvalue(L, 2);
|
||||||
|
lua_rawsetp(L, -2, e->curl);
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_multi_remove_handle(lua_State *L){
|
||||||
|
lcurl_multi_t *p = lcurl_getmulti(L);
|
||||||
|
lcurl_easy_t *e = lcurl_geteasy_at(L, 2);
|
||||||
|
CURLMcode code = curl_multi_remove_handle(p->curl, e->curl);
|
||||||
|
if(code != CURLM_OK){
|
||||||
|
lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
|
||||||
|
}
|
||||||
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_rawsetp(L, -2, e->curl);
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_multi_perform(lua_State *L){
|
||||||
|
lcurl_multi_t *p = lcurl_getmulti(L);
|
||||||
|
int running_handles = 0;
|
||||||
|
CURLMcode code = curl_multi_perform(p->curl, &running_handles);
|
||||||
|
if(code != CURLM_OK){
|
||||||
|
lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
|
||||||
|
}
|
||||||
|
lua_pushnumber(L, running_handles);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_multi_info_read(lua_State *L){
|
||||||
|
lcurl_multi_t *p = lcurl_getmulti(L);
|
||||||
|
int msgs_in_queue = 0;
|
||||||
|
CURLMsg *msg = curl_multi_info_read(p->curl, &msgs_in_queue);
|
||||||
|
lcurl_easy_t *e;
|
||||||
|
if(!msg){
|
||||||
|
lua_pushnumber(L, msgs_in_queue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg->msg == CURLMSG_DONE){
|
||||||
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
|
||||||
|
lua_rawgetp(L, -1, msg->easy_handle);
|
||||||
|
e = lcurl_geteasy_at(L, -1);
|
||||||
|
if(msg->data.result == CURLE_OK){
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 1 + lcurl_fail_ex(L, LCURL_ERROR_RETURN, LCURL_ERROR_EASY, msg->data.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo handle unknown message
|
||||||
|
lua_pushboolean(L, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
static const struct luaL_Reg lcurl_multi_methods[] = {
|
static const struct luaL_Reg lcurl_multi_methods[] = {
|
||||||
{"close", lcurl_multi_cleanup },
|
{"add_handle", lcurl_multi_add_handle },
|
||||||
{"__gc", lcurl_multi_cleanup },
|
{"remove_handle", lcurl_multi_remove_handle },
|
||||||
|
{"perform", lcurl_multi_perform },
|
||||||
|
{"info_read", lcurl_multi_info_read },
|
||||||
|
|
||||||
|
{"close", lcurl_multi_cleanup },
|
||||||
|
{"__gc", lcurl_multi_cleanup },
|
||||||
|
|
||||||
{NULL,NULL}
|
{NULL,NULL}
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
typedef struct lcurl_multi_tag{
|
typedef struct lcurl_multi_tag{
|
||||||
CURLM *curl;
|
CURLM *curl;
|
||||||
int err_mode;
|
int err_mode;
|
||||||
|
int h_ref;
|
||||||
}lcurl_multi_t;
|
}lcurl_multi_t;
|
||||||
|
|
||||||
int lcurl_multi_create(lua_State *L, int error_mode);
|
int lcurl_multi_create(lua_State *L, int error_mode);
|
||||||
|
@ -116,3 +116,13 @@ int lcurl_util_push_cb(lua_State *L, lcurl_callback_t *c){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lcurl_util_new_weak_table(lua_State*L, const char *mode){
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushstring(L, mode);
|
||||||
|
lua_setfield(L, -2, "__mode");
|
||||||
|
lua_setmetatable(L,-2);
|
||||||
|
assert((top+1) == lua_gettop(L));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -38,4 +38,6 @@ void lcurl_util_set_const(lua_State *L, const lcurl_const_t *reg);
|
|||||||
|
|
||||||
int lcurl_util_push_cb(lua_State *L, lcurl_callback_t *c);
|
int lcurl_util_push_cb(lua_State *L, lcurl_callback_t *c);
|
||||||
|
|
||||||
|
int lcurl_util_new_weak_table(lua_State*L, const char *mode);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user