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 | \*-------------------------------------------------------------------------*/ |
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 | \*-------------------------------------------------------------------------*/ |
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 | |
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 | |
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 | |
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 | \*-------------------------------------------------------------------------*/ |
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 */ |
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 | |
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 | \*-------------------------------------------------------------------------*/ |
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 | \*-------------------------------------------------------------------------*/ |
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 | \*-------------------------------------------------------------------------*/ |
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 | |