1 /* LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
2 * Licensed as LGPL - See doc/COPYING for details */
3 #include "buffer_event.h"
8 #include "event_buffer.h"
10 #define BUFFER_EVENT_MT "BUFFER_EVENT_MT"
12 /* Obtains an le_bufferevent structure from a given index */
13 static le_bufferevent
* buffer_event_get(lua_State
* L
, int idx
) {
14 return (le_bufferevent
*)luaL_checkudata(L
, idx
, BUFFER_EVENT_MT
);
17 /* Obtains an le_bufferevent structure from a given index
18 AND checks that it hadn't been prematurely freed
20 le_bufferevent
* buffer_event_check(lua_State
* L
, int idx
) {
21 le_bufferevent
* buf
= (le_bufferevent
*)luaL_checkudata(L
, idx
, BUFFER_EVENT_MT
);
23 luaL_argerror(L
, idx
, "Attempt to use closed buffer_event object");
27 /* Checks if the given index contains an le_buffer object */
28 int is_buffer_event(lua_State
* L
, int idx
) {
30 lua_getmetatable(L
, idx
);
31 luaL_getmetatable(L
, BUFFER_EVENT_MT
);
32 ret
= lua_rawequal(L
, -2, -1);
37 static void handle_callback(le_bufferevent
* le_ev
, short what
, int callbackIndex
) {
38 lua_State
* L
= le_ev
->base
->loop_L
;
39 le_weak_get(L
, le_ev
);
41 lua_rawgeti(L
, -1, callbackIndex
);
45 /* func, bufferevent */
46 lua_pushinteger(L
, what
);
47 /* What to do w/ errors...? */
48 lua_pcall(L
, 3, 0, 0);
51 static void buffer_event_readcb(struct bufferevent
*ev
, void *ptr
) {
52 handle_callback((le_bufferevent
*)ptr
, EVBUFFER_READ
, 1);
55 static void buffer_event_writecb(struct bufferevent
*ev
, void *ptr
) {
56 handle_callback((le_bufferevent
*)ptr
, EVBUFFER_WRITE
, 2);
59 static void buffer_event_errorcb(struct bufferevent
*ev
, short what
, void *ptr
) {
60 handle_callback((le_bufferevent
*)ptr
, what
, 3);
63 /* LUA: new(fd, read, write, error)
64 Pushes a new bufferevent instance on the stack
65 Accepts: base, fd, read, write, error cb
66 Requires base, fd and error cb
68 static int buffer_event_push(lua_State
* L
) {
70 le_base
* base
= event_base_get(L
, 1);
71 /* NOTE: Should probably reference the socket as well... */
72 int fd
= getSocketFd(L
, 2);
73 luaL_checktype(L
, 5, LUA_TFUNCTION
);
74 if(!lua_isnil(L
, 3)) luaL_checktype(L
, 3, LUA_TFUNCTION
);
75 if(!lua_isnil(L
, 4)) luaL_checktype(L
, 4, LUA_TFUNCTION
);
76 ev
= (le_bufferevent
*)lua_newuserdata(L
, sizeof(le_bufferevent
));
77 luaL_getmetatable(L
, BUFFER_EVENT_MT
);
78 lua_setmetatable(L
, -2);
79 ev
->ev
= bufferevent_new(fd
, buffer_event_readcb
, buffer_event_writecb
, buffer_event_errorcb
, ev
);
80 lua_createtable(L
, 5, 0);
82 lua_rawseti(L
, -2, 1); // Read
84 lua_rawseti(L
, -2, 2); // Write
86 lua_rawseti(L
, -2, 3); // Err
88 event_buffer_push(L
, ev
->ev
->input
);
89 lua_rawseti(L
, -2, 4);
90 event_buffer_push(L
, ev
->ev
->output
);
91 lua_rawseti(L
, -2, 5);
97 /* LUA: __gc and buffer:close()
98 Releases the buffer resources
100 static int buffer_event_gc(lua_State
* L
) {
101 le_bufferevent
* ev
= buffer_event_get(L
, 1);
103 le_buffer
*read
, *write
;
104 bufferevent_free(ev
->ev
);
106 /* Also clear out the associated input/output event_buffers
107 * since they would have already been freed.. */
109 lua_rawgeti(L
, -1, 4);
110 lua_rawgeti(L
, -2, 5);
111 read
= event_buffer_check(L
, -2);
112 write
= event_buffer_check(L
, -1);
113 /* Erase their knowledge of the buffer so that the GC won't try to double-free */
115 write
->buffer
= NULL
;
120 static luaL_Reg buffer_event_funcs
[] = {
124 static luaL_Reg funcs
[] = {
125 {"new", buffer_event_push
},
129 int buffer_event_register(lua_State
* L
) {
130 luaL_newmetatable(L
, BUFFER_EVENT_MT
);
131 lua_pushcfunction(L
, buffer_event_gc
);
132 lua_setfield(L
, -2, "__gc");
134 luaL_register(L
, NULL
, buffer_event_funcs
);
135 lua_setfield(L
, -2, "__index");
138 luaL_register(L
, "luaevent.core.bufferevent", funcs
);