src/buffer_event.c

changeset 41
fce1995f0db8
child 42
b1742e841e5a
equal deleted inserted replaced
40:11810d219ddb 41:fce1995f0db8
1 /* LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
2 * Licensed as LGPL - See doc/COPYING for details */
3
4 #include "buffer_event.h"
5 #include "luaevent.h"
6 #include "utility.h"
7 #include <lauxlib.h>
8 #include <malloc.h>
9 #include "event_buffer.h"
10
11 #define BUFFER_EVENT_MT "BUFFER_EVENT_MT"
12
13 /* Obtains an le_bufferevent structure from a given index */
14 static le_bufferevent* buffer_event_get(lua_State* L, int idx) {
15 return (le_bufferevent*)luaL_checkudata(L, idx, BUFFER_EVENT_MT);
16 }
17
18 /* Obtains an le_bufferevent structure from a given index
19 AND checks that it hadn't been prematurely freed
20 */
21 le_bufferevent* buffer_event_check(lua_State* L, int idx) {
22 le_bufferevent* buf = (le_bufferevent*)luaL_checkudata(L, idx, BUFFER_EVENT_MT);
23 if(!buf->ev)
24 luaL_argerror(L, idx, "Attempt to use closed buffer_event object");
25 return buf;
26 }
27
28 /* Checks if the given index contains an le_buffer object */
29 int is_buffer_event(lua_State* L, int idx) {
30 int ret;
31 lua_getmetatable(L, idx);
32 luaL_getmetatable(L, BUFFER_EVENT_MT);
33 ret = lua_rawequal(L, -2, -1);
34 lua_pop(L, 2);
35 return ret;
36 }
37
38 static void handle_callback(le_bufferevent* le_ev, short what, int callbackIndex) {
39 lua_State* L = le_ev->base->loop_L;
40 le_weak_get(L, le_ev);
41 lua_getfenv(L, -1);
42 lua_rawgeti(L, -1, callbackIndex);
43 lua_remove(L, -2);
44 lua_pushvalue(L, -2);
45 lua_remove(L, -3);
46 /* func, bufferevent */
47 lua_pushinteger(L, what);
48 /* What to do w/ errors...? */
49 lua_pcall(L, 3, 0, 0);
50 }
51
52 static void buffer_event_readcb(struct bufferevent *ev, void *ptr) {
53 handle_callback((le_bufferevent*)ptr, EVBUFFER_READ, 1);
54 }
55
56 static void buffer_event_writecb(struct bufferevent *ev, void *ptr) {
57 handle_callback((le_bufferevent*)ptr, EVBUFFER_WRITE, 2);
58 }
59
60 static void buffer_event_errorcb(struct bufferevent *ev, short what, void *ptr) {
61 handle_callback((le_bufferevent*)ptr, what, 3);
62 }
63
64 /* LUA: new(fd, read, write, error)
65 Pushes a new bufferevent instance on the stack
66 Accepts: base, fd, read, write, error cb
67 Requires base, fd and error cb
68 */
69 static int buffer_event_push(lua_State* L) {
70 le_bufferevent *ev;
71 le_base* base = event_base_get(L, 1);
72 /* NOTE: Should probably reference the socket as well... */
73 int fd = getSocketFd(L, 2);
74 luaL_checktype(L, 5, LUA_TFUNCTION);
75 if(!lua_isnil(L, 3)) luaL_checktype(L, 3, LUA_TFUNCTION);
76 if(!lua_isnil(L, 4)) luaL_checktype(L, 4, LUA_TFUNCTION);
77 ev= (le_bufferevent*)lua_newuserdata(L, sizeof(le_bufferevent));
78 luaL_getmetatable(L, BUFFER_EVENT_MT);
79 lua_setmetatable(L, -2);
80 ev->ev = bufferevent_new(fd, buffer_event_readcb, buffer_event_writecb, buffer_event_errorcb, ev);
81 lua_createtable(L, 5, 0);
82 lua_pushvalue(L, 3);
83 lua_rawseti(L, -2, 1); // Read
84 lua_pushvalue(L, 4);
85 lua_rawseti(L, -2, 2); // Write
86 lua_pushvalue(L, 5);
87 lua_rawseti(L, -2, 3); // Err
88
89 event_buffer_push(L, ev->ev->input);
90 lua_rawseti(L, -2, 4);
91 event_buffer_push(L, ev->ev->output);
92 lua_rawseti(L, -2, 5);
93 lua_setfenv(L, -2);
94 ev->base = base;
95 return 1;
96 }
97
98 /* LUA: __gc and buffer:close()
99 Releases the buffer resources
100 */
101 static int buffer_event_gc(lua_State* L) {
102 le_bufferevent* ev = buffer_event_get(L, 1);
103 if(ev->ev) {
104 le_buffer *read, *write;
105 bufferevent_free(ev->ev);
106 ev->ev = NULL;
107 /* Also clear out the associated input/output event_buffers
108 * since they would have already been freed.. */
109 lua_getfenv(L, 1);
110 lua_rawgeti(L, -1, 4);
111 lua_rawgeti(L, -2, 5);
112 read = event_buffer_check(L, -2);
113 write = event_buffer_check(L, -1);
114 /* Erase their knowledge of the buffer so that the GC won't try to double-free */
115 read->buffer = NULL;
116 write->buffer = NULL;
117 }
118 return 0;
119 }
120
121 static luaL_Reg buffer_event_funcs[] = {
122 {NULL, NULL}
123 };
124
125 static luaL_Reg funcs[] = {
126 {"new", buffer_event_push},
127 {NULL, NULL}
128 };
129
130 int buffer_event_register(lua_State* L) {
131 luaL_newmetatable(L, BUFFER_EVENT_MT);
132 lua_pushcfunction(L, buffer_event_gc);
133 lua_setfield(L, -2, "__gc");
134 lua_newtable(L);
135 luaL_register(L, NULL, buffer_event_funcs);
136 lua_setfield(L, -2, "__index");
137 lua_pop(L, 1);
138
139 luaL_register(L, "luaevent.core.bufferevent", funcs);
140 return 1;
141 }

mercurial