buffer_event: removed magic numbers for read/write buffer locations
[luaevent.git] / src / buffer_event.c
blob7030551fa667cdf685a2d3151b9782ae6b87fe34
1 /* LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
2 * Licensed as LGPL - See doc/COPYING for details */
3 #include "buffer_event.h"
4 #include "luaevent.h"
5 #include "utility.h"
6 #include <lauxlib.h>
7 #include <malloc.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);
26 if(!buf->ev)
27 luaL_argerror(L, idx, "Attempt to use closed buffer_event object");
28 return buf;
31 /* Checks if the given index contains an le_buffer object */
32 int is_buffer_event(lua_State* L, int idx) {
33 int ret;
34 lua_getmetatable(L, idx);
35 luaL_getmetatable(L, BUFFER_EVENT_MT);
36 ret = lua_rawequal(L, -2, -1);
37 lua_pop(L, 2);
38 return ret;
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);
44 lua_getfenv(L, -1);
45 lua_rawgeti(L, -1, callbackIndex);
46 lua_remove(L, -2);
47 lua_pushvalue(L, -2);
48 lua_remove(L, -3);
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) {
73 le_bufferevent *ev;
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);
85 lua_pushvalue(L, 3);
86 lua_rawseti(L, -2, 1); // Read
87 lua_pushvalue(L, 4);
88 lua_rawseti(L, -2, 2); // Write
89 lua_pushvalue(L, 5);
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);
96 lua_setfenv(L, -2);
97 ev->base = base;
98 return 1;
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);
106 if(ev->ev) {
107 le_buffer *read, *write;
108 bufferevent_free(ev->ev);
109 ev->ev = NULL;
110 /* Also clear out the associated input/output event_buffers
111 * since they would have already been freed.. */
112 lua_getfenv(L, 1);
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 */
118 read->buffer = NULL;
119 write->buffer = NULL;
121 return 0;
124 static luaL_Reg buffer_event_funcs[] = {
125 {NULL, NULL}
128 static luaL_Reg funcs[] = {
129 {"new", buffer_event_push},
130 {NULL, NULL}
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");
137 lua_newtable(L);
138 luaL_register(L, NULL, buffer_event_funcs);
139 lua_setfield(L, -2, "__index");
140 lua_pop(L, 1);
142 luaL_register(L, "luaevent.core.bufferevent", funcs);
143 return 1;