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