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 /*-------------------------------------------------------------------------*\
58 * Initializes module
59 \*-------------------------------------------------------------------------*/
luaopen_socket_serial(lua_State * L)60 LUASOCKET_API int luaopen_socket_serial(lua_State *L) {
61     /* create classes */
62     auxiliar_newclass(L, "serial{client}", serial_methods);
63     /* create class groups */
64     auxiliar_add2group(L, "serial{client}", "serial{any}");
65     lua_pushcfunction(L, global_create);
66     return 1;
67 }
68 
69 /*=========================================================================*\
70 * Lua methods
71 \*=========================================================================*/
72 /*-------------------------------------------------------------------------*\
73 * Just call buffered IO methods
74 \*-------------------------------------------------------------------------*/
meth_send(lua_State * L)75 static int meth_send(lua_State *L) {
76     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
77     return buffer_meth_send(L, &un->buf);
78 }
79 
meth_receive(lua_State * L)80 static int meth_receive(lua_State *L) {
81     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
82     return buffer_meth_receive(L, &un->buf);
83 }
84 
meth_getstats(lua_State * L)85 static int meth_getstats(lua_State *L) {
86     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
87     return buffer_meth_getstats(L, &un->buf);
88 }
89 
meth_setstats(lua_State * L)90 static int meth_setstats(lua_State *L) {
91     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
92     return buffer_meth_setstats(L, &un->buf);
93 }
94 
95 /*-------------------------------------------------------------------------*\
96 * Select support methods
97 \*-------------------------------------------------------------------------*/
meth_getfd(lua_State * L)98 static int meth_getfd(lua_State *L) {
99     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
100     lua_pushnumber(L, (int) un->sock);
101     return 1;
102 }
103 
104 /* this is very dangerous, but can be handy for those that are brave enough */
meth_setfd(lua_State * L)105 static int meth_setfd(lua_State *L) {
106     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
107     un->sock = (t_socket) luaL_checknumber(L, 2);
108     return 0;
109 }
110 
meth_dirty(lua_State * L)111 static int meth_dirty(lua_State *L) {
112     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
113     lua_pushboolean(L, !buffer_isempty(&un->buf));
114     return 1;
115 }
116 
117 /*-------------------------------------------------------------------------*\
118 * Closes socket used by object
119 \*-------------------------------------------------------------------------*/
meth_close(lua_State * L)120 static int meth_close(lua_State *L)
121 {
122     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
123     socket_destroy(&un->sock);
124     lua_pushnumber(L, 1);
125     return 1;
126 }
127 
128 
129 /*-------------------------------------------------------------------------*\
130 * Just call tm methods
131 \*-------------------------------------------------------------------------*/
meth_settimeout(lua_State * L)132 static int meth_settimeout(lua_State *L) {
133     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
134     return timeout_meth_settimeout(L, &un->tm);
135 }
136 
137 /*=========================================================================*\
138 * Library functions
139 \*=========================================================================*/
140 
141 
142 /*-------------------------------------------------------------------------*\
143 * Creates a serial object
144 \*-------------------------------------------------------------------------*/
global_create(lua_State * L)145 static int global_create(lua_State *L) {
146     const char* path = luaL_checkstring(L, 1);
147 
148     /* allocate unix object */
149     p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
150 
151     /* open serial device */
152     t_socket sock = open(path, O_NOCTTY|O_RDWR);
153 
154     /*printf("open %s on %d\n", path, sock);*/
155 
156     if (sock < 0)  {
157         lua_pushnil(L);
158         lua_pushstring(L, socket_strerror(errno));
159         lua_pushnumber(L, errno);
160         return 3;
161     }
162     /* set its type as client object */
163     auxiliar_setclass(L, "serial{client}", -1);
164     /* initialize remaining structure fields */
165     socket_setnonblocking(&sock);
166     un->sock = sock;
167     io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
168             (p_error) socket_ioerror, &un->sock);
169     timeout_init(&un->tm, -1, -1);
170     buffer_init(&un->buf, &un->io, &un->tm);
171     return 1;
172 }
173