core: updates to MIT-style license and properly includes in file heading
[luaevent.git] / src / luaevent.c
blobd16255cdf5f7629378689685747507df13cab72d
1 /* LuaEvent
2 Copyright (C) 2007,2012,2013 Thomas Harning <harningt@gmail.com>
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
23 #include "event_callback.h"
24 #include "event_buffer.h"
25 #include "buffer_event.h"
27 #include <lauxlib.h>
28 #include <assert.h>
29 #include <string.h>
31 #define EVENT_BASE_MT "EVENT_BASE_MT"
33 le_base* event_base_get(lua_State* L, int idx) {
34 return (le_base*)luaL_checkudata(L, idx, EVENT_BASE_MT);
37 int luaevent_newbase(lua_State* L) {
38 le_base *base = (le_base*)lua_newuserdata(L, sizeof(le_base));
39 base->loop_L = NULL; /* No running loop */
40 base->base = event_init();
41 luaL_getmetatable(L, EVENT_BASE_MT);
42 lua_setmetatable(L, -2);
43 return 1;
46 int luaevent_libevent_version(lua_State* L) {
47 lua_pushstring(L, event_get_version());
48 return 1;
51 static int luaevent_base_gc(lua_State* L) {
52 le_base *base = event_base_get(L, 1);
53 if(base->base) {
54 event_base_free(base->base);
55 base->base = NULL;
57 return 0;
60 int getSocketFd(lua_State* L, int idx) {
61 int fd;
62 if(lua_isnumber(L, idx)) {
63 fd = lua_tonumber(L, idx);
64 } else {
65 luaL_checktype(L, idx, LUA_TUSERDATA);
66 lua_getfield(L, idx, "getfd");
67 if(lua_isnil(L, -1))
68 return luaL_error(L, "Socket type missing 'getfd' method");
69 lua_pushvalue(L, idx);
70 lua_call(L, 1, 1);
71 fd = lua_tointeger(L, -1);
72 lua_pop(L, 1);
74 return fd;
77 void load_timeval(double time, struct timeval *tv) {
78 tv->tv_sec = (int) time;
79 tv->tv_usec = (int)( (time - tv->tv_sec) * 1000000 );
82 /* sock, event, callback, timeout */
83 static int luaevent_addevent(lua_State* L) {
84 int fd, event;
85 le_callback* arg = event_callback_push(L, 1, 4);
86 struct timeval *tv = &arg->timeout;
87 if(lua_isnil(L, 2) && lua_isnumber(L, 5)) {
88 fd = -1; /* Per event_timer_set.... */
89 } else {
90 fd = getSocketFd(L, 2);
92 event = luaL_checkinteger(L, 3);
93 if(lua_isnumber(L, 5)) {
94 double time = lua_tonumber(L, 5);
95 load_timeval(time, tv);
96 } else {
97 tv = NULL;
100 /* Setup event... */
101 event_set(&arg->ev, fd, event | EV_PERSIST, luaevent_callback, arg);
102 event_base_set(arg->base->base, &arg->ev);
103 event_add(&arg->ev, tv);
104 return 1;
107 static int luaevent_loop(lua_State* L) {
108 int ret;
109 le_base *base = event_base_get(L, 1);
110 base->loop_L = L;
111 base->errorMessage = LUA_NOREF;
112 ret = event_base_loop(base->base, 0);
113 if(base->errorMessage != LUA_NOREF)
115 lua_rawgeti(L, LUA_REGISTRYINDEX, base->errorMessage);
116 luaL_unref(L, LUA_REGISTRYINDEX, base->errorMessage);
117 base->errorMessage = LUA_NOREF;
118 return lua_error(L);
120 lua_pushinteger(L, ret);
121 return 1;
124 static int luaevent_loopexit(lua_State*L) {
125 int ret;
126 le_base *base = event_base_get(L, 1);
127 struct timeval tv = { 0, 0 };
128 if(lua_gettop(L) >= 2) /* Optional timeout before exiting the loop */
129 load_timeval(luaL_checknumber(L, 2), &tv);
130 ret = event_base_loopexit(base->base, &tv);
131 lua_pushinteger(L, ret);
132 return 1;
135 static int luaevent_method(lua_State* L) {
136 #ifdef _EVENT_VERSION
137 le_base *base = event_base_get(L, 1);
138 if(strcmp(_EVENT_VERSION, "1.3")<0)
139 lua_pushstring(L, event_base_get_method(base->base));
140 else
141 #endif
142 lua_pushstring(L, event_get_method());
143 return 1;
146 static luaL_Reg base_funcs[] = {
147 { "addevent", luaevent_addevent },
148 { "loop", luaevent_loop },
149 { "loopexit", luaevent_loopexit },
150 { "method", luaevent_method },
151 { NULL, NULL }
154 static luaL_Reg funcs[] = {
155 { "new", luaevent_newbase },
156 { "libevent_version", luaevent_libevent_version },
157 { NULL, NULL }
160 typedef struct {
161 const char* name;
162 int value;
163 } namedInteger;
165 static namedInteger consts[] = {
166 {"LEAVE", -1},
167 {"EV_READ", EV_READ},
168 {"EV_WRITE", EV_WRITE},
169 {"EV_TIMEOUT", EV_TIMEOUT},
170 {"EV_SIGNAL", EV_SIGNAL},
171 {"EV_PERSIST", EV_PERSIST},
172 /* bufferevent */
173 {"EVBUFFER_READ", EVBUFFER_READ},
174 {"EVBUFFER_WRITE", EVBUFFER_WRITE},
175 {"EVBUFFER_EOF", EVBUFFER_EOF},
176 {"EVBUFFER_ERROR", EVBUFFER_ERROR},
177 {"EVBUFFER_TIMEOUT", EVBUFFER_TIMEOUT},
178 {NULL, 0}
181 void setNamedIntegers(lua_State* L, namedInteger* p) {
182 while(p->name) {
183 lua_pushinteger(L, p->value);
184 lua_setfield(L, -2, p->name);
185 p++;
189 /* Verified ok */
190 int luaopen_luaevent_core(lua_State* L) {
191 #ifdef _WIN32
192 WORD wVersionRequested = MAKEWORD(2, 2);
193 WSADATA wsaData;
194 WSAStartup(wVersionRequested, &wsaData);
195 #endif
196 event_init( );
197 /* Setup metatable */
198 luaL_newmetatable(L, EVENT_BASE_MT);
199 lua_newtable(L);
200 luaL_register(L, NULL, base_funcs);
201 lua_setfield(L, -2, "__index");
202 lua_pushcfunction(L, luaevent_base_gc);
203 lua_setfield(L, -2, "__gc");
204 lua_pop(L, 1);
206 lua_newtable(L);
207 luaL_register(L, NULL, funcs);
208 setNamedIntegers(L, consts);
210 /* Register external items */
211 event_callback_register(L);
212 event_buffer_register(L, lua_gettop(L));
213 buffer_event_register(L, lua_gettop(L));
215 return 1;