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