Added EVBUFFER_* constants to luaevent.core
[luaevent.git] / src / buffer_event.c
blob0058ed92ee1549364af844cc74d1839f50198a62
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 /* 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);
22 if(!buf->ev)
23 luaL_argerror(L, idx, "Attempt to use closed buffer_event object");
24 return buf;
27 /* Checks if the given index contains an le_buffer object */
28 int is_buffer_event(lua_State* L, int idx) {
29 int ret;
30 lua_getmetatable(L, idx);
31 luaL_getmetatable(L, BUFFER_EVENT_MT);
32 ret = lua_rawequal(L, -2, -1);
33 lua_pop(L, 2);
34 return ret;
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);
40 lua_getfenv(L, -1);
41 lua_rawgeti(L, -1, callbackIndex);
42 lua_remove(L, -2);
43 lua_pushvalue(L, -2);
44 lua_remove(L, -3);
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) {
69 le_bufferevent *ev;
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);
81 lua_pushvalue(L, 3);
82 lua_rawseti(L, -2, 1); // Read
83 lua_pushvalue(L, 4);
84 lua_rawseti(L, -2, 2); // Write
85 lua_pushvalue(L, 5);
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);
92 lua_setfenv(L, -2);
93 ev->base = base;
94 return 1;
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);
102 if(ev->ev) {
103 le_buffer *read, *write;
104 bufferevent_free(ev->ev);
105 ev->ev = NULL;
106 /* Also clear out the associated input/output event_buffers
107 * since they would have already been freed.. */
108 lua_getfenv(L, 1);
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 */
114 read->buffer = NULL;
115 write->buffer = NULL;
117 return 0;
120 static luaL_Reg buffer_event_funcs[] = {
121 {NULL, NULL}
124 static luaL_Reg funcs[] = {
125 {"new", buffer_event_push},
126 {NULL, NULL}
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");
133 lua_newtable(L);
134 luaL_register(L, NULL, buffer_event_funcs);
135 lua_setfield(L, -2, "__index");
136 lua_pop(L, 1);
138 luaL_register(L, "luaevent.core.bufferevent", funcs);
139 return 1;