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 /* Locations of READ/WRITE buffers in the fenv */
13 #define READ_BUFFER_LOCATION 4
14 #define WRITE_BUFFER_LOCATION 5
16 /* Obtains an le_bufferevent structure from a given index */
17 static le_bufferevent
* buffer_event_get(lua_State
* L
, int idx
) {
18 return (le_bufferevent
*)luaL_checkudata(L
, idx
, BUFFER_EVENT_MT
);
21 /* Obtains an le_bufferevent structure from a given index
22 AND checks that it hadn't been prematurely freed
24 le_bufferevent
* buffer_event_check(lua_State
* L
, int idx
) {
25 le_bufferevent
* buf
= (le_bufferevent
*)luaL_checkudata(L
, idx
, BUFFER_EVENT_MT
);
27 luaL_argerror(L
, idx
, "Attempt to use closed buffer_event object");
31 /* Checks if the given index contains an le_buffer object */
32 int is_buffer_event(lua_State
* L
, int idx
) {
34 lua_getmetatable(L
, idx
);
35 luaL_getmetatable(L
, BUFFER_EVENT_MT
);
36 ret
= lua_rawequal(L
, -2, -1);
41 static void handle_callback(le_bufferevent
* le_ev
, short what
, int callbackIndex
) {
42 lua_State
* L
= le_ev
->base
->loop_L
;
43 le_weak_get(L
, le_ev
);
45 lua_rawgeti(L
, -1, callbackIndex
);
49 /* func, bufferevent */
50 lua_pushinteger(L
, what
);
51 /* What to do w/ errors...? */
52 lua_pcall(L
, 3, 0, 0);
55 static void buffer_event_readcb(struct bufferevent
*ev
, void *ptr
) {
56 handle_callback((le_bufferevent
*)ptr
, EVBUFFER_READ
, 1);
59 static void buffer_event_writecb(struct bufferevent
*ev
, void *ptr
) {
60 handle_callback((le_bufferevent
*)ptr
, EVBUFFER_WRITE
, 2);
63 static void buffer_event_errorcb(struct bufferevent
*ev
, short what
, void *ptr
) {
64 handle_callback((le_bufferevent
*)ptr
, what
, 3);
67 /* LUA: new(fd, read, write, error)
68 Pushes a new bufferevent instance on the stack
69 Accepts: base, fd, read, write, error cb
70 Requires base, fd and error cb
72 static int buffer_event_push(lua_State
* L
) {
74 le_base
* base
= event_base_get(L
, 1);
75 /* NOTE: Should probably reference the socket as well... */
76 int fd
= getSocketFd(L
, 2);
77 luaL_checktype(L
, 5, LUA_TFUNCTION
);
78 if(!lua_isnil(L
, 3)) luaL_checktype(L
, 3, LUA_TFUNCTION
);
79 if(!lua_isnil(L
, 4)) luaL_checktype(L
, 4, LUA_TFUNCTION
);
80 ev
= (le_bufferevent
*)lua_newuserdata(L
, sizeof(le_bufferevent
));
81 luaL_getmetatable(L
, BUFFER_EVENT_MT
);
82 lua_setmetatable(L
, -2);
83 ev
->ev
= bufferevent_new(fd
, buffer_event_readcb
, buffer_event_writecb
, buffer_event_errorcb
, ev
);
84 lua_createtable(L
, 5, 0);
86 lua_rawseti(L
, -2, 1); // Read
88 lua_rawseti(L
, -2, 2); // Write
90 lua_rawseti(L
, -2, 3); // Err
92 event_buffer_push(L
, ev
->ev
->input
);
93 lua_rawseti(L
, -2, READ_BUFFER_LOCATION
);
94 event_buffer_push(L
, ev
->ev
->output
);
95 lua_rawseti(L
, -2, WRITE_BUFFER_LOCATION
);
101 /* LUA: __gc and buffer:close()
102 Releases the buffer resources
104 static int buffer_event_gc(lua_State
* L
) {
105 le_bufferevent
* ev
= buffer_event_get(L
, 1);
107 le_buffer
*read
, *write
;
108 bufferevent_free(ev
->ev
);
110 /* Also clear out the associated input/output event_buffers
111 * since they would have already been freed.. */
113 lua_rawgeti(L
, -1, READ_BUFFER_LOCATION
);
114 lua_rawgeti(L
, -2, WRITE_BUFFER_LOCATION
);
115 read
= event_buffer_check(L
, -2);
116 write
= event_buffer_check(L
, -1);
117 /* Erase their knowledge of the buffer so that the GC won't try to double-free */
119 write
->buffer
= NULL
;
124 static luaL_Reg buffer_event_funcs
[] = {
128 static luaL_Reg funcs
[] = {
129 {"new", buffer_event_push
},
133 int buffer_event_register(lua_State
* L
) {
134 luaL_newmetatable(L
, BUFFER_EVENT_MT
);
135 lua_pushcfunction(L
, buffer_event_gc
);
136 lua_setfield(L
, -2, "__gc");
138 luaL_register(L
, NULL
, buffer_event_funcs
);
139 lua_setfield(L
, -2, "__index");
142 luaL_register(L
, "luaevent.core.bufferevent", funcs
);