Skip to content

Commit 1747a35

Browse files
committed
Merge pull request #46 from moteus/master
Support `socket_action` interface.
2 parents 8a9d0a0 + eb21f4f commit 1747a35

File tree

8 files changed

+312
-23
lines changed

8 files changed

+312
-23
lines changed

doc/lcurl.ldoc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ function easy() end
2424
--
2525
-- @tparam[opt] table options
2626
-- @treturn[1] multi new curl multi object
27+
--
28+
-- @usage
29+
-- m = curl.multi{
30+
-- socketfunction = handle_socket;
31+
-- timerfunction = start_timeout;
32+
-- }
33+
--
2734
function multi() end
2835

2936
--- Create Share object
@@ -433,6 +440,18 @@ function info_read() end
433440
-- c:setopt{maxconnects = 10}
434441
function setopt() end
435442

443+
--- Perform socket action.
444+
--
445+
-- @tparam[opt=curl.SOCKET_TIMEOUT] number socket
446+
-- @tparam[opt=0] number mask
447+
-- @treturn multi self
448+
--
449+
-- @usage
450+
-- c:socket_action()
451+
-- c:socket_action(sock_fd, curl.CSELECT_IN)
452+
-- c:socket_action(sock_fd, curl.CSELECT_OUT)
453+
function socket_action() end
454+
436455
--- Set timer callback.
437456
--
438457
-- @tparam function timer timer callback

examples/cURLv3/multi-uv.lua

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
local curl = require "cURL"
2+
local uv = require "lluv"
3+
4+
local fprintf = function(f, ...) f:write((string.format(...))) end
5+
local printf = function(...) fprintf(io.stdout, ...) end
6+
7+
local stderr = io.stderr
8+
9+
local timeout, curl_handle
10+
11+
local ACTION_NAMES = {
12+
[curl.POLL_IN ] = "POLL_IN";
13+
[curl.POLL_INOUT ] = "POLL_INOUT";
14+
[curl.POLL_OUT ] = "POLL_OUT";
15+
[curl.POLL_NONE ] = "POLL_NONE";
16+
[curl.POLL_REMOVE ] = "POLL_REMOVE";
17+
}
18+
local EVENT_NAMES = {
19+
[ uv.READABLE ] = "READABLE";
20+
[ uv.WRITABLE ] = "WRITABLE";
21+
[ uv.READABLE + uv.WRITABLE ] = "READABLE + WRITABLE";
22+
}
23+
local FLAGS = {
24+
[ uv.READABLE ] = curl.CSELECT_IN;
25+
[ uv.WRITABLE ] = curl.CSELECT_OUT;
26+
[ uv.READABLE + uv.WRITABLE ] = curl.CSELECT_IN + curl.CSELECT_OUT;
27+
28+
}
29+
30+
local trace = function() end or print
31+
32+
local FILES, CONTEXT = {}, {}
33+
34+
function create_curl_context(sockfd)
35+
local context = {
36+
sockfd = sockfd;
37+
poll_handle = uv.poll_socket(sockfd);
38+
}
39+
context.poll_handle.data = context
40+
41+
return context
42+
end
43+
44+
function destroy_curl_context(context)
45+
context.poll_handle:close()
46+
end
47+
48+
function add_download(url, num)
49+
local filename = tostring(num) .. ".download"
50+
local file = io.open(filename, "w")
51+
if not file then
52+
fprintf(stderr, "Error opening %s\n", filename)
53+
return
54+
end
55+
56+
local handle = curl.easy{
57+
url = url;
58+
writefunction = file;
59+
}
60+
61+
FILES[handle] = file
62+
63+
curl_handle:add_handle(handle)
64+
fprintf(stderr, "Added download %s -> %s\n", url, filename);
65+
end
66+
67+
function check_multi_info()
68+
while true do
69+
local easy, ok, err = curl_handle:info_read()
70+
if not easy then curl_handle:close() error(err) end
71+
if easy == 0 then break end
72+
73+
local context = CONTEXT[e]
74+
if context then destroy_curl_context(context) end
75+
local file = FILES[easy]
76+
if file then FILES[easy] = nil, file:close() end
77+
local done_url = easy:getinfo_effective_url()
78+
easy:close()
79+
if ok then
80+
printf("%s DONE\n", done_url);
81+
elseif data == "error" then
82+
printf("%s ERROR - %s\n", done_url, tostring(err));
83+
end
84+
end
85+
end
86+
87+
function curl_perform(handle, err, events)
88+
-- calls by libuv --
89+
trace("UV::POLL", handle, err, EVENT_NAMES[events] or events)
90+
91+
local flags = assert(FLAGS[events], ("unknown event:" .. events))
92+
93+
context = handle.data
94+
95+
curl_handle:socket_action(context.sockfd, flags)
96+
97+
check_multi_info()
98+
end
99+
100+
function on_timeout(timer)
101+
-- calls by libuv --
102+
trace("UV::TIMEOUT", timer)
103+
104+
local running_handles, err = curl_handle:socket_action()
105+
106+
check_multi_info()
107+
end
108+
109+
function start_timeout(timeout_ms)
110+
-- calls by curl --
111+
trace("CURL::TIMEOUT", timeout_ms)
112+
113+
-- 0 means directly call socket_action, but we'll do it in a bit
114+
if timeout_ms <= 0 then timeout_ms = 1 end
115+
116+
timeout:stop():start(timeout_ms, 0, on_timeout)
117+
end
118+
119+
local handle_socket = function(...)
120+
local ok, err = pcall(handle_socket_impl, ...)
121+
if not ok then uv.defer(function() error(err) end) end
122+
end
123+
124+
function handle_socket_impl(easy, s, action)
125+
-- calls by curl --
126+
127+
trace("CURL::SOCKET", easy, s, ACTION_NAMES[action] or action)
128+
129+
local curl_context = CONTEXT[easy] or create_curl_context(s)
130+
CONTEXT[easy] = curl_context
131+
132+
assert(curl_context.sockfd == s)
133+
134+
if action == curl.POLL_IN then
135+
curl_context.poll_handle:start(uv.READABLE, curl_perform)
136+
elseif action == curl.POLL_OUT then
137+
curl_context.poll_handle:start(uv.WRITABLE, curl_perform)
138+
elseif action == curl.POLL_REMOVE then
139+
CONTEXT[easy] = nil
140+
destroy_curl_context(curl_context)
141+
end
142+
end
143+
144+
timeout = uv.timer()
145+
146+
curl_handle = curl.multi{
147+
socketfunction = handle_socket;
148+
timerfunction = start_timeout;
149+
}
150+
151+
curl_handle = curl.multi{
152+
socketfunction = handle_socket;
153+
timerfunction = start_timeout;
154+
}
155+
156+
for i = 1, math.huge do
157+
local url = arg[i]
158+
if not url then break end
159+
add_download(url, i)
160+
end
161+
162+
uv.run(loop, UV_RUN_DEFAULT)

src/l52util.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,27 @@ void *lutil_newudatap_impl(lua_State *L, size_t size, const void *p){
155155
lutil_setmetatablep(L, p);
156156
return obj;
157157
}
158+
159+
void lutil_pushint64(lua_State *L, int64_t v){
160+
if(sizeof(lua_Integer) >= sizeof(int64_t)){
161+
lua_pushinteger(L, (lua_Integer)v);
162+
return;
163+
}
164+
lua_pushnumber(L, (lua_Number)v);
165+
}
166+
167+
int64_t lutil_checkint64(lua_State *L, int idx){
168+
if(sizeof(lua_Integer) >= sizeof(int64_t))
169+
return luaL_checkinteger(L, idx);
170+
return (int64_t)luaL_checknumber(L, idx);
171+
}
172+
173+
int64_t lutil_optint64(lua_State *L, int idx, int64_t v){
174+
if(sizeof(lua_Integer) >= sizeof(int64_t))
175+
return luaL_optinteger(L, idx, v);
176+
return (int64_t)luaL_optnumber(L, idx, v);
177+
}
178+
179+
void lutil_pushnvalues(lua_State *L, int n){
180+
for(;n;--n) lua_pushvalue(L, -n);
181+
}

src/l52util.h

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,47 +13,52 @@
1313

1414
#include "lua.h"
1515
#include "lauxlib.h"
16+
#include <stdint.h>
1617

1718
#if LUA_VERSION_NUM >= 503 /* Lua 5.3 */
1819

19-
#ifndef luaL_optint
20-
# define luaL_optint luaL_optinteger
21-
#endif
22-
2320
#ifndef luaL_checkint
24-
# define luaL_checkint luaL_checkinteger
21+
#define luaL_checkint luaL_checkinteger
2522
#endif
2623

2724
#ifndef luaL_checklong
28-
# define luaL_checklong luaL_checkinteger
25+
#define luaL_checklong luaL_checkinteger
2926
#endif
3027

28+
#ifndef luaL_optint
29+
#define luaL_optint luaL_optinteger
3130
#endif
3231

32+
#ifndef luaL_optlong
33+
#define luaL_optlong luaL_optinteger
34+
#endif
3335

34-
#if LUA_VERSION_NUM >= 502 // lua 5.2
36+
#endif
3537

36-
// lua_rawgetp
37-
// lua_rawsetp
38-
// luaL_setfuncs
39-
// lua_absindex
40-
#ifndef lua_objlen
38+
#if LUA_VERSION_NUM >= 502 /* Lua 5.2 */
4139

42-
#define lua_objlen lua_rawlen
40+
/* lua_rawgetp */
41+
/* lua_rawsetp */
42+
/* luaL_setfuncs */
43+
/* lua_absindex */
4344

45+
#ifndef lua_objlen
46+
#define lua_objlen lua_rawlen
4447
#endif
4548

4649
int luaL_typerror (lua_State *L, int narg, const char *tname);
4750

4851
#ifndef luaL_register
49-
5052
void luaL_register (lua_State *L, const char *libname, const luaL_Reg *l);
53+
#endif
5154

55+
#ifndef lua_equal
56+
#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
5257
#endif
5358

54-
#else // lua 5.1
59+
#else /* Lua 5.1 */
5560

56-
// functions form lua 5.2
61+
/* functions form lua 5.2 */
5762

5863
# define lua_absindex(L, i) (((i)>0)?(i):((i)<=LUA_REGISTRYINDEX?(i):(lua_gettop(L)+(i)+1)))
5964
# define lua_rawlen lua_objlen
@@ -78,5 +83,12 @@ int lutil_createmetap (lua_State *L, const void *p, const luaL_Reg *methods,
7883

7984
void *lutil_newudatap_impl (lua_State *L, size_t size, const void *p);
8085

81-
#endif
86+
void lutil_pushint64(lua_State *L, int64_t v);
8287

88+
int64_t lutil_checkint64(lua_State *L, int idx);
89+
90+
int64_t lutil_optint64(lua_State *L, int idx, int64_t v);
91+
92+
void lutil_pushnvalues(lua_State *L, int n);
93+
94+
#endif

0 commit comments

Comments
 (0)