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/*
18Reuses userdata definition from unix.h, since it is useful for all
19stream-like objects.
20
21If we stored the serial path for use in error messages or userdata
22printing, we might need our own userdata definition.
23
24Group usage is semi-inherited from unix.c, but unnecessary since we
25have only one object type.
26*/
27
28/*=========================================================================*\
29* Internal function prototypes
30\*=========================================================================*/
31static int global_create(lua_State *L);
32static int meth_send(lua_State *L);
33static int meth_receive(lua_State *L);
34static int meth_close(lua_State *L);
35static int meth_settimeout(lua_State *L);
36static int meth_getfd(lua_State *L);
37static int meth_setfd(lua_State *L);
38static int meth_dirty(lua_State *L);
39static int meth_getstats(lua_State *L);
40static int meth_setstats(lua_State *L);
41
42/* serial object methods */
43static 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\*-------------------------------------------------------------------------*/
61LUASOCKET_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\*-------------------------------------------------------------------------*/
76static 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
81static 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
86static 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
91static 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\*-------------------------------------------------------------------------*/
99static 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 */
106static 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
112static 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\*-------------------------------------------------------------------------*/
121static 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\*-------------------------------------------------------------------------*/
133static 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\*-------------------------------------------------------------------------*/
146static 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