bufferevent learned set_*_watermarks
[luaevent.git] / src / buffer_event.c
blob5d74db28bd4e2876fb2b0d18057b787ffbbc2482
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 Lua's link to the buffers */
118 lua_pushnil(L);
119 /* LS: ..., fenv, readBuf, writeBuf, nil */
120 lua_rawseti(L, -4, READ_BUFFER_LOCATION);
121 lua_pushnil(L);
122 lua_rawseti(L, -4, WRITE_BUFFER_LOCATION);
123 /* Erase their knowledge of the buffer so that the GC won't try to double-free */
124 read->buffer = NULL;
125 write->buffer = NULL;
127 return 0;
130 static int buffer_event_get_read(lua_State* L) {
131 (void)buffer_event_get(L, 1);
132 lua_getfenv(L, 1);
133 lua_rawgeti(L, -1, READ_BUFFER_LOCATION);
134 return 1;
137 static int buffer_event_get_write(lua_State* L) {
138 (void)buffer_event_get(L, 1);
139 lua_getfenv(L, 1);
140 lua_rawgeti(L, -1, WRITE_BUFFER_LOCATION);
141 return 1;
144 static int buffer_event_set_read_watermarks(lua_State* L) {
145 int low, high;
146 le_bufferevent* ev = buffer_event_get(L, 1);
147 if(!ev->ev) return 0;
149 low = lua_tonumber(L, 2);
150 high = lua_tonumber(L, 3);
152 ev->ev->wm_read.low = low;
153 ev->ev->wm_read.high = high;
154 return 0;
157 static int buffer_event_set_write_watermarks(lua_State* L) {
158 int low, high;
159 le_bufferevent* ev = buffer_event_get(L, 1);
160 if(!ev->ev) return 0;
162 low = lua_tonumber(L, 2);
163 high = lua_tonumber(L, 3);
165 ev->ev->wm_write.low = low;
166 ev->ev->wm_write.high = high;
167 return 0;
170 static luaL_Reg buffer_event_funcs[] = {
171 {"get_read", buffer_event_get_read},
172 {"get_write", buffer_event_get_write},
173 {"set_read_watermarks", buffer_event_set_read_watermarks},
174 {"set_write_watermarks", buffer_event_set_write_watermarks},
175 {NULL, NULL}
178 static luaL_Reg funcs[] = {
179 {"new", buffer_event_push},
180 {NULL, NULL}
183 int buffer_event_register(lua_State* L) {
184 luaL_newmetatable(L, BUFFER_EVENT_MT);
185 lua_pushcfunction(L, buffer_event_gc);
186 lua_setfield(L, -2, "__gc");
187 lua_newtable(L);
188 luaL_register(L, NULL, buffer_event_funcs);
189 lua_setfield(L, -2, "__index");
190 lua_pop(L, 1);
192 luaL_register(L, "luaevent.core.bufferevent", funcs);
193 return 1;