1 /* LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
2 * Licensed as LGPL - See doc/COPYING for details */
4 #include "buffer_event.h"
7 #include "event_buffer.h"
9 #define BUFFER_EVENT_MT "BUFFER_EVENT_MT"
11 /* Locations of READ/WRITE buffers in the fenv */
12 #define READ_BUFFER_LOCATION 4
13 #define WRITE_BUFFER_LOCATION 5
15 /* Obtains an le_bufferevent structure from a given index */
16 static le_bufferevent
* buffer_event_get(lua_State
* L
, int idx
) {
17 return (le_bufferevent
*)luaL_checkudata(L
, idx
, BUFFER_EVENT_MT
);
20 /* Obtains an le_bufferevent structure from a given index
21 AND checks that it hadn't been prematurely freed
23 le_bufferevent
* buffer_event_check(lua_State
* L
, int idx
) {
24 le_bufferevent
* buf
= (le_bufferevent
*)luaL_checkudata(L
, idx
, BUFFER_EVENT_MT
);
26 luaL_argerror(L
, idx
, "Attempt to use closed buffer_event object");
30 /* Checks if the given index contains an le_buffer object */
31 int is_buffer_event(lua_State
* L
, int idx
) {
33 lua_getmetatable(L
, idx
);
34 luaL_getmetatable(L
, BUFFER_EVENT_MT
);
35 ret
= lua_rawequal(L
, -2, -1);
40 static void handle_callback(le_bufferevent
* le_ev
, short what
, int callbackIndex
) {
41 lua_State
* L
= le_ev
->base
->loop_L
;
42 le_weak_get(L
, le_ev
);
44 lua_rawgeti(L
, -1, callbackIndex
);
48 /* func, bufferevent */
49 lua_pushinteger(L
, what
);
50 /* What to do w/ errors...? */
51 if(!lua_pcall(L
, 2, 0, 0))
53 /* FIXME: Perhaps luaevent users should be
54 * able to set an error handler? */
55 lua_pop(L
, 1); /* Pop error message */
59 static void buffer_event_readcb(struct bufferevent
*ev
, void *ptr
) {
60 handle_callback((le_bufferevent
*)ptr
, EVBUFFER_READ
, 1);
63 static void buffer_event_writecb(struct bufferevent
*ev
, void *ptr
) {
64 handle_callback((le_bufferevent
*)ptr
, EVBUFFER_WRITE
, 2);
67 static void buffer_event_errorcb(struct bufferevent
*ev
, short what
, void *ptr
) {
68 handle_callback((le_bufferevent
*)ptr
, what
, 3);
71 /* LUA: new(fd, read, write, error)
72 Pushes a new bufferevent instance on the stack
73 Accepts: base, fd, read, write, error cb
74 Requires base, fd and error cb
76 static int buffer_event_push(lua_State
* L
) {
78 le_base
* base
= event_base_get(L
, 1);
79 /* NOTE: Should probably reference the socket as well... */
80 int fd
= getSocketFd(L
, 2);
81 luaL_checktype(L
, 5, LUA_TFUNCTION
);
82 if(!lua_isnil(L
, 3)) luaL_checktype(L
, 3, LUA_TFUNCTION
);
83 if(!lua_isnil(L
, 4)) luaL_checktype(L
, 4, LUA_TFUNCTION
);
84 ev
= (le_bufferevent
*)lua_newuserdata(L
, sizeof(le_bufferevent
));
85 luaL_getmetatable(L
, BUFFER_EVENT_MT
);
86 lua_setmetatable(L
, -2);
87 ev
->ev
= bufferevent_new(fd
, buffer_event_readcb
, buffer_event_writecb
, buffer_event_errorcb
, ev
);
88 lua_createtable(L
, 5, 0);
90 lua_rawseti(L
, -2, 1); // Read
92 lua_rawseti(L
, -2, 2); // Write
94 lua_rawseti(L
, -2, 3); // Err
96 event_buffer_push(L
, ev
->ev
->input
);
97 lua_rawseti(L
, -2, READ_BUFFER_LOCATION
);
98 event_buffer_push(L
, ev
->ev
->output
);
99 lua_rawseti(L
, -2, WRITE_BUFFER_LOCATION
);
105 /* LUA: __gc and buffer:close()
106 Releases the buffer resources
108 static int buffer_event_gc(lua_State
* L
) {
109 le_bufferevent
* ev
= buffer_event_get(L
, 1);
111 le_buffer
*read
, *write
;
112 bufferevent_free(ev
->ev
);
114 /* Also clear out the associated input/output event_buffers
115 * since they would have already been freed.. */
117 lua_rawgeti(L
, -1, READ_BUFFER_LOCATION
);
118 lua_rawgeti(L
, -2, WRITE_BUFFER_LOCATION
);
119 read
= event_buffer_check(L
, -2);
120 write
= event_buffer_check(L
, -1);
121 /* Erase Lua's link to the buffers */
123 /* LS: ..., fenv, readBuf, writeBuf, nil */
124 lua_rawseti(L
, -4, READ_BUFFER_LOCATION
);
126 lua_rawseti(L
, -4, WRITE_BUFFER_LOCATION
);
127 /* Erase their knowledge of the buffer so that the GC won't try to double-free */
129 write
->buffer
= NULL
;
134 static int buffer_event_get_read(lua_State
* L
) {
135 (void)buffer_event_get(L
, 1);
137 lua_rawgeti(L
, -1, READ_BUFFER_LOCATION
);
141 static int buffer_event_get_write(lua_State
* L
) {
142 (void)buffer_event_get(L
, 1);
144 lua_rawgeti(L
, -1, WRITE_BUFFER_LOCATION
);
148 static int buffer_event_set_read_watermarks(lua_State
* L
) {
150 le_bufferevent
* ev
= buffer_event_get(L
, 1);
151 if(!ev
->ev
) return 0;
153 low
= lua_tonumber(L
, 2);
154 high
= lua_tonumber(L
, 3);
156 bufferevent_setwatermark(ev
->ev
, EV_READ
, low
, high
);
160 static int buffer_event_set_write_watermarks(lua_State
* L
) {
162 le_bufferevent
* ev
= buffer_event_get(L
, 1);
163 if(!ev
->ev
) return 0;
165 low
= lua_tonumber(L
, 2);
166 high
= lua_tonumber(L
, 3);
168 bufferevent_setwatermark(ev
->ev
, EV_WRITE
, low
, high
);
172 static int buffer_event_set_timeouts(lua_State
* L
) {
173 int timeout_read
, timeout_write
;
174 le_bufferevent
* ev
= buffer_event_get(L
, 1);
175 if(!ev
->ev
) return 0;
177 timeout_read
= lua_tointeger(L
, 2);
178 timeout_write
= lua_tointeger(L
, 3);
180 bufferevent_settimeout(ev
->ev
, timeout_read
, timeout_write
);
184 static int buffer_event_enable(lua_State
* L
) {
185 le_bufferevent
* ev
= buffer_event_get(L
, 1);
186 if(!ev
->ev
) return 0;
188 lua_pushinteger(L
, bufferevent_enable(ev
->ev
, luaL_checkinteger(L
, 2)));
192 static int buffer_event_disable(lua_State
* L
) {
193 le_bufferevent
* ev
= buffer_event_get(L
, 1);
194 if(!ev
->ev
) return 0;
196 lua_pushinteger(L
, bufferevent_disable(ev
->ev
, luaL_checkinteger(L
, 2)));
200 static luaL_Reg buffer_event_funcs
[] = {
201 {"get_read", buffer_event_get_read
},
202 {"get_write", buffer_event_get_write
},
203 {"set_read_watermarks", buffer_event_set_read_watermarks
},
204 {"set_write_watermarks", buffer_event_set_write_watermarks
},
205 {"set_timeouts", buffer_event_set_timeouts
},
206 {"enable", buffer_event_enable
},
207 {"disable", buffer_event_disable
},
211 static luaL_Reg funcs
[] = {
212 {"new", buffer_event_push
},
216 int buffer_event_register(lua_State
* L
) {
217 luaL_newmetatable(L
, BUFFER_EVENT_MT
);
218 lua_pushcfunction(L
, buffer_event_gc
);
219 lua_setfield(L
, -2, "__gc");
221 luaL_register(L
, NULL
, buffer_event_funcs
);
222 lua_setfield(L
, -2, "__index");
225 luaL_register(L
, "luaevent.core.bufferevent", funcs
);