1 /*=========================================================================*\
2 * Serial stream
3 * LuaSocket toolkit
4 \*=========================================================================*/
5 #include <string.h>
6
7 #include "lua.h"
8 #include "lauxlib.h"
9 #include "luasocket.h"
10
11 #include "auxiliar.h"
12 #include "socket.h"
13 #include "options.h"
14 #include "unix.h"
15 #include <sys/un.h>
16
17 /*
18 Reuses userdata definition from unix.h, since it is useful for all
19 stream-like objects.
20
21 If we stored the serial path for use in error messages or userdata
22 printing, we might need our own userdata definition.
23
24 Group usage is semi-inherited from unix.c, but unnecessary since we
25 have only one object type.
26 */
27
28 /*=========================================================================*\
29 * Internal function prototypes
30 \*=========================================================================*/
31 static int global_create(lua_State *L);
32 static int meth_send(lua_State *L);
33 static int meth_receive(lua_State *L);
34 static int meth_close(lua_State *L);
35 static int meth_settimeout(lua_State *L);
36 static int meth_getfd(lua_State *L);
37 static int meth_setfd(lua_State *L);
38 static int meth_dirty(lua_State *L);
39 static int meth_getstats(lua_State *L);
40 static int meth_setstats(lua_State *L);
41
42 /* serial object methods */
43 static luaL_Reg serial_methods[] = {
44 {"__gc", meth_close},
45 {"__tostring", auxiliar_tostring},
46 {"close", meth_close},
47 {"dirty", meth_dirty},
48 {"getfd", meth_getfd},
49 {"getstats", meth_getstats},
50 {"setstats", meth_setstats},
51 {"receive", meth_receive},
52 {"send", meth_send},
53 {"setfd", meth_setfd},
54 {"settimeout", meth_settimeout},
55 {NULL, NULL}
56 };
57
58 /*-------------------------------------------------------------------------*\
59 * Initializes module
60 \*-------------------------------------------------------------------------*/
luaopen_socket_serial(lua_State * L)61 LUASOCKET_API int luaopen_socket_serial(lua_State *L) {
62 /* create classes */
63 auxiliar_newclass(L, "serial{client}", serial_methods);
64 /* create class groups */
65 auxiliar_add2group(L, "serial{client}", "serial{any}");
66 lua_pushcfunction(L, global_create);
67 return 1;
68 }
69
70 /*=========================================================================*\
71 * Lua methods
72 \*=========================================================================*/
73 /*-------------------------------------------------------------------------*\
74 * Just call buffered IO methods
75 \*-------------------------------------------------------------------------*/
meth_send(lua_State * L)76 static int meth_send(lua_State *L) {
77 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
78 return buffer_meth_send(L, &un->buf);
79 }
80
meth_receive(lua_State * L)81 static int meth_receive(lua_State *L) {
82 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
83 return buffer_meth_receive(L, &un->buf);
84 }
85
meth_getstats(lua_State * L)86 static int meth_getstats(lua_State *L) {
87 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
88 return buffer_meth_getstats(L, &un->buf);
89 }
90
meth_setstats(lua_State * L)91 static int meth_setstats(lua_State *L) {
92 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
93 return buffer_meth_setstats(L, &un->buf);
94 }
95
96 /*-------------------------------------------------------------------------*\
97 * Select support methods
98 \*-------------------------------------------------------------------------*/
meth_getfd(lua_State * L)99 static int meth_getfd(lua_State *L) {
100 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
101 lua_pushnumber(L, (int) un->sock);
102 return 1;
103 }
104
105 /* this is very dangerous, but can be handy for those that are brave enough */
meth_setfd(lua_State * L)106 static int meth_setfd(lua_State *L) {
107 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
108 un->sock = (t_socket) luaL_checknumber(L, 2);
109 return 0;
110 }
111
meth_dirty(lua_State * L)112 static int meth_dirty(lua_State *L) {
113 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
114 lua_pushboolean(L, !buffer_isempty(&un->buf));
115 return 1;
116 }
117
118 /*-------------------------------------------------------------------------*\
119 * Closes socket used by object
120 \*-------------------------------------------------------------------------*/
meth_close(lua_State * L)121 static int meth_close(lua_State *L)
122 {
123 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
124 socket_destroy(&un->sock);
125 lua_pushnumber(L, 1);
126 return 1;
127 }
128
129
130 /*-------------------------------------------------------------------------*\
131 * Just call tm methods
132 \*-------------------------------------------------------------------------*/
meth_settimeout(lua_State * L)133 static int meth_settimeout(lua_State *L) {
134 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
135 return timeout_meth_settimeout(L, &un->tm);
136 }
137
138 /*=========================================================================*\
139 * Library functions
140 \*=========================================================================*/
141
142
143 /*-------------------------------------------------------------------------*\
144 * Creates a serial object
145 \*-------------------------------------------------------------------------*/
global_create(lua_State * L)146 static int global_create(lua_State *L) {
147 const char* path = luaL_checkstring(L, 1);
148
149 /* allocate unix object */
150 p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
151
152 /* open serial device */
153 t_socket sock = open(path, O_NOCTTY|O_RDWR);
154
155 /*printf("open %s on %d\n", path, sock);*/
156
157 if (sock < 0) {
158 lua_pushnil(L);
159 lua_pushstring(L, socket_strerror(errno));
160 lua_pushnumber(L, errno);
161 return 3;
162 }
163 /* set its type as client object */
164 auxiliar_setclass(L, "serial{client}", -1);
165 /* initialize remaining structure fields */
166 socket_setnonblocking(&sock);
167 un->sock = sock;
168 io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
169 (p_error) socket_ioerror, &un->sock);
170 timeout_init(&un->tm, -1, -1);
171 buffer_init(&un->buf, &un->io, &un->tm);
172 return 1;
173 }
174