src/luaevent.c

1
/* LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
2
 * Licensed as LGPL - See doc/COPYING for details */
3
 
4
#include "event_callback.h"
5
#include "event_buffer.h"
6
#include "buffer_event.h"
7
 
8
#include <lauxlib.h>
9
#include <assert.h>
10
#include <string.h>
11
 
12
#define EVENT_BASE_MT "EVENT_BASE_MT"
13
 
14
le_base* event_base_get(lua_State* L, int idx) {
15
	return (le_base*)luaL_checkudata(L, idx, EVENT_BASE_MT);
16
}
17
 
18
int luaevent_newbase(lua_State* L) {
19
	le_base *base = (le_base*)lua_newuserdata(L, sizeof(le_base));
20
	base->loop_L = NULL; /* No running loop */
21
	base->base = event_init();
22
	luaL_getmetatable(L, EVENT_BASE_MT);
23
	lua_setmetatable(L, -2);
24
	return 1;
25
}
26
 
27
int luaevent_libevent_version(lua_State* L) {
28
	lua_pushstring(L, event_get_version());
29
	return 1;
30
}
31
 
32
static int luaevent_base_gc(lua_State* L) {
33
	le_base *base = event_base_get(L, 1);
34
	if(base->base) {
35
		event_base_free(base->base);
36
		base->base = NULL;
37
	}
38
	return 0;
39
}
40
 
41
int getSocketFd(lua_State* L, int idx) {
42
	int fd;
43
	if(lua_isnumber(L, idx)) {
44
		fd = lua_tonumber(L, idx);
45
	} else {
46
		luaL_checktype(L, idx, LUA_TUSERDATA);
47
		lua_getfield(L, idx, "getfd");
48
		if(lua_isnil(L, -1))
49
			return luaL_error(L, "Socket type missing 'getfd' method");
50
		lua_pushvalue(L, idx);
51
		lua_call(L, 1, 1);
52
		fd = lua_tointeger(L, -1);
53
		lua_pop(L, 1);
54
	}
55
	return fd;
56
}
57
 
58
void load_timeval(double time, struct timeval *tv) {
59
	tv->tv_sec = (int) time;
60
	tv->tv_usec = (int)( (time - tv->tv_sec) * 1000000 );
61
}
62
 
63
/* sock, event, callback, timeout */
64
static int luaevent_addevent(lua_State* L) {
65
	int fd, event;
66
	le_callback* arg = event_callback_push(L, 1, 4);
67
	struct timeval *tv = &arg->timeout;
68
	if(lua_isnil(L, 2) && lua_isnumber(L, 5)) {
69
		fd = -1; /* Per event_timer_set.... */
70
	} else {
71
		fd = getSocketFd(L, 2);
72
	}
73
	event = luaL_checkinteger(L, 3);
74
	if(lua_isnumber(L, 5)) {
75
		double time = lua_tonumber(L, 5);
76
		load_timeval(time, tv);
77
	} else {
78
		tv = NULL;
79
	}
80
 
81
	/* Setup event... */
82
	event_set(&arg->ev, fd, event | EV_PERSIST, luaevent_callback, arg);
83
	event_base_set(arg->base->base, &arg->ev);
84
	event_add(&arg->ev, tv);
85
	return 1;
86
}
87
 
88
static int luaevent_loop(lua_State* L) {
89
	int ret;
90
	le_base *base = event_base_get(L, 1);
91
	base->loop_L = L;
92
	ret = event_base_loop(base->base, 0);
93
	lua_pushinteger(L, ret);
94
	return 1;
95
}
96
 
97
static int luaevent_loopexit(lua_State*L) {
98
	int ret;
99
	le_base *base = event_base_get(L, 1);
100
	struct timeval tv = { 0, 0 };
101
	if(lua_gettop(L) >= 2) /* Optional timeout before exiting the loop */
102
		load_timeval(luaL_checknumber(L, 2), &tv);
103
	ret = event_base_loopexit(base->base, &tv);
104
	lua_pushinteger(L, ret);
105
	return 1;
106
}
107
 
108
static int luaevent_method(lua_State* L) {
109
	#ifdef _EVENT_VERSION
110
	le_base *base = event_base_get(L, 1);
111
	if(strcmp(_EVENT_VERSION, "1.3")<0)
112
		lua_pushstring(L, event_base_get_method(base->base));
113
	else
114
	#endif
115
		lua_pushstring(L, event_get_method());
116
	return 1;
117
}
118
 
119
static luaL_Reg base_funcs[] = {
120
	{ "addevent", luaevent_addevent },
121
	{ "loop", luaevent_loop },
122
	{ "loopexit", luaevent_loopexit },
123
	{ "method", luaevent_method },
124
	{ NULL, NULL }
125
};
126
 
127
static luaL_Reg funcs[] = {
128
	{ "new", luaevent_newbase },
129
	{ "libevent_version", luaevent_libevent_version },
130
	{ NULL, NULL }
131
};
132
 
133
typedef struct {
134
	const char* name;
135
	int value;
136
} namedInteger;
137
 
138
static namedInteger consts[] = {
139
	{"LEAVE", -1},
140
	{"EV_READ", EV_READ},
141
	{"EV_WRITE", EV_WRITE},
142
	{"EV_TIMEOUT", EV_TIMEOUT},
143
	{"EV_SIGNAL", EV_SIGNAL},
144
	{"EV_PERSIST", EV_PERSIST},
145
	/* bufferevent */
146
	{"EVBUFFER_READ", EVBUFFER_READ},
147
	{"EVBUFFER_WRITE", EVBUFFER_WRITE},
148
	{"EVBUFFER_EOF", EVBUFFER_EOF},
149
	{"EVBUFFER_ERROR", EVBUFFER_ERROR},
150
	{"EVBUFFER_TIMEOUT", EVBUFFER_TIMEOUT},
151
	{NULL, 0}
152
};
153
 
154
void setNamedIntegers(lua_State* L, namedInteger* p) {
155
	while(p->name) {
156
		lua_pushinteger(L, p->value);
157
		lua_setfield(L, -2, p->name);
158
		p++;
159
	}
160
}
161
 
162
/* Verified ok */
163
int luaopen_luaevent_core(lua_State* L) {
164
#ifdef _WIN32
165
	WORD wVersionRequested = MAKEWORD(2, 2);
166
	WSADATA wsaData;
167
	WSAStartup(wVersionRequested, &wsaData);
168
#endif
169
	event_init( );
170
	/* Register external items */
171
	event_callback_register(L);
172
	event_buffer_register(L);
173
	buffer_event_register(L);
174
	lua_settop(L, 0);
175
	/* Setup metatable */
176
	luaL_newmetatable(L, EVENT_BASE_MT);
177
	lua_newtable(L);
178
	luaL_register(L, NULL, base_funcs);
179
	lua_setfield(L, -2, "__index");
180
	lua_pushcfunction(L, luaevent_base_gc);
181
	lua_setfield(L, -2, "__gc");
182
	lua_pop(L, 1);
183
 
184
	luaL_register(L, "luaevent.core", funcs);
185
	setNamedIntegers(L, consts);
186
	return 1;
187
}