aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Roberts <vieuxtech@gmail.com>2012-02-23 17:12:37 -0800
committerSam Roberts <vieuxtech@gmail.com>2012-04-11 13:45:59 -0700
commitb1f7c349b5714ebe304f93e43576a0ff3f721fc1 (patch)
treed3c4f5539507be4fe69452f100e8843ee55567ac
parent3b19f2a7edbcde798a9cf5f1f6175d360e891744 (diff)
downloadluasocket-b1f7c349b5714ebe304f93e43576a0ff3f721fc1.tar.gz
luasocket-b1f7c349b5714ebe304f93e43576a0ff3f721fc1.tar.bz2
luasocket-b1f7c349b5714ebe304f93e43576a0ff3f721fc1.zip
Add support for serial devices as socket streams on unix.
-rw-r--r--config1
-rw-r--r--makefile1
-rw-r--r--src/makefile18
-rw-r--r--src/serial.c183
-rw-r--r--src/socket.h3
-rw-r--r--src/usocket.c60
6 files changed, 265 insertions, 1 deletions
diff --git a/config b/config
index d6085ad..7d73638 100644
--- a/config
+++ b/config
@@ -11,6 +11,7 @@ MIME_V=1.0.2
11SOCKET_SO=socket.$(EXT).$(SOCKET_V) 11SOCKET_SO=socket.$(EXT).$(SOCKET_V)
12MIME_SO=mime.$(EXT).$(MIME_V) 12MIME_SO=mime.$(EXT).$(MIME_V)
13UNIX_SO=unix.$(EXT) 13UNIX_SO=unix.$(EXT)
14SERIAL_SO=serial.$(EXT)
14 15
15#------ 16#------
16# Lua includes and libraries 17# Lua includes and libraries
diff --git a/makefile b/makefile
index 97a72e9..b1c9f18 100644
--- a/makefile
+++ b/makefile
@@ -48,6 +48,7 @@ install: all
48 48
49install-unix: install all-unix 49install-unix: install all-unix
50 cd src; $(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_LIB)/$(UNIX_SO) 50 cd src; $(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_LIB)/$(UNIX_SO)
51 cd src; $(INSTALL_EXEC) $(SERIAL_SO) $(INSTALL_SOCKET_LIB)/$(SERIAL_SO)
51 52
52#------ 53#------
53# End of makefile 54# End of makefile
diff --git a/src/makefile b/src/makefile
index 6ec8718..c5c22f2 100644
--- a/src/makefile
+++ b/src/makefile
@@ -47,6 +47,17 @@ UNIX_OBJS:=\
47 usocket.o \ 47 usocket.o \
48 unix.o 48 unix.o
49 49
50#------
51# Modules belonging to serial (device streams)
52#
53SERIAL_OBJS:=\
54 buffer.o \
55 auxiliar.o \
56 timeout.o \
57 io.o \
58 usocket.o \
59 serial.o
60
50all: $(SOCKET_SO) $(MIME_SO) 61all: $(SOCKET_SO) $(MIME_SO)
51 62
52$(SOCKET_SO): $(SOCKET_OBJS) 63$(SOCKET_SO): $(SOCKET_OBJS)
@@ -55,11 +66,14 @@ $(SOCKET_SO): $(SOCKET_OBJS)
55$(MIME_SO): $(MIME_OBJS) 66$(MIME_SO): $(MIME_OBJS)
56 $(LD) $(LDFLAGS) -o $@ $(MIME_OBJS) 67 $(LD) $(LDFLAGS) -o $@ $(MIME_OBJS)
57 68
58all-unix: all $(UNIX_SO) 69all-unix: all $(UNIX_SO) $(SERIAL_SO)
59 70
60$(UNIX_SO): $(UNIX_OBJS) 71$(UNIX_SO): $(UNIX_OBJS)
61 $(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS) 72 $(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS)
62 73
74$(SERIAL_SO): $(SERIAL_OBJS)
75 $(LD) $(LDFLAGS) -o $@ $(SERIAL_OBJS)
76
63#------ 77#------
64# List of dependencies 78# List of dependencies
65# 79#
@@ -74,6 +88,8 @@ mime.o: mime.c mime.h
74options.o: options.c auxiliar.h options.h socket.h io.h timeout.h \ 88options.o: options.c auxiliar.h options.h socket.h io.h timeout.h \
75 usocket.h inet.h 89 usocket.h inet.h
76select.o: select.c socket.h io.h timeout.h usocket.h select.h 90select.o: select.c socket.h io.h timeout.h usocket.h select.h
91serial.o: serial.c auxiliar.h socket.h io.h timeout.h usocket.h \
92 unix.h buffer.h
77tcp.o: tcp.c auxiliar.h socket.h io.h timeout.h usocket.h inet.h \ 93tcp.o: tcp.c auxiliar.h socket.h io.h timeout.h usocket.h inet.h \
78 options.h tcp.h buffer.h 94 options.h tcp.h buffer.h
79timeout.o: timeout.c auxiliar.h timeout.h 95timeout.o: timeout.c auxiliar.h timeout.h
diff --git a/src/serial.c b/src/serial.c
new file mode 100644
index 0000000..b356a3a
--- /dev/null
+++ b/src/serial.c
@@ -0,0 +1,183 @@
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/*
17Reuses userdata definition from unix.h, since it is useful for all
18stream-like objects.
19
20If we stored the serial path for use in error messages or userdata
21printing, we might need our own userdata definition.
22
23Group usage is semi-inherited from unix.c, but unnecessary since we
24have only one object type.
25*/
26
27/*=========================================================================*\
28* Internal function prototypes
29\*=========================================================================*/
30static int global_create(lua_State *L);
31static int meth_send(lua_State *L);
32static int meth_receive(lua_State *L);
33static int meth_close(lua_State *L);
34static int meth_settimeout(lua_State *L);
35static int meth_getfd(lua_State *L);
36static int meth_setfd(lua_State *L);
37static int meth_dirty(lua_State *L);
38static int meth_getstats(lua_State *L);
39static int meth_setstats(lua_State *L);
40
41/* serial object methods */
42static luaL_reg un[] = {
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 */
58static luaL_reg func[] = {
59 {"serial", global_create},
60 {NULL, NULL}
61};
62
63
64/*-------------------------------------------------------------------------*\
65* Initializes module
66\*-------------------------------------------------------------------------*/
67int luaopen_socket_serial(lua_State *L) {
68 /* create classes */
69 auxiliar_newclass(L, "serial{client}", un);
70 /* create class groups */
71 auxiliar_add2group(L, "serial{client}", "serial{any}");
72 /* make sure the function ends up in the package table */
73 luaL_openlib(L, "socket", func, 0);
74 /* return the function instead of the 'socket' table */
75 lua_pushstring(L, "serial");
76 lua_gettable(L, -2);
77 return 1;
78}
79
80/*=========================================================================*\
81* Lua methods
82\*=========================================================================*/
83/*-------------------------------------------------------------------------*\
84* Just call buffered IO methods
85\*-------------------------------------------------------------------------*/
86static int meth_send(lua_State *L) {
87 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
88 return buffer_meth_send(L, &un->buf);
89}
90
91static int meth_receive(lua_State *L) {
92 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
93 return buffer_meth_receive(L, &un->buf);
94}
95
96static int meth_getstats(lua_State *L) {
97 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
98 return buffer_meth_getstats(L, &un->buf);
99}
100
101static int meth_setstats(lua_State *L) {
102 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
103 return buffer_meth_setstats(L, &un->buf);
104}
105
106/*-------------------------------------------------------------------------*\
107* Select support methods
108\*-------------------------------------------------------------------------*/
109static int meth_getfd(lua_State *L) {
110 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
111 lua_pushnumber(L, (int) un->sock);
112 return 1;
113}
114
115/* this is very dangerous, but can be handy for those that are brave enough */
116static int meth_setfd(lua_State *L) {
117 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
118 un->sock = (t_socket) luaL_checknumber(L, 2);
119 return 0;
120}
121
122static int meth_dirty(lua_State *L) {
123 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
124 lua_pushboolean(L, !buffer_isempty(&un->buf));
125 return 1;
126}
127
128/*-------------------------------------------------------------------------*\
129* Closes socket used by object
130\*-------------------------------------------------------------------------*/
131static int meth_close(lua_State *L)
132{
133 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
134 socket_destroy(&un->sock);
135 lua_pushnumber(L, 1);
136 return 1;
137}
138
139
140/*-------------------------------------------------------------------------*\
141* Just call tm methods
142\*-------------------------------------------------------------------------*/
143static int meth_settimeout(lua_State *L) {
144 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
145 return timeout_meth_settimeout(L, &un->tm);
146}
147
148/*=========================================================================*\
149* Library functions
150\*=========================================================================*/
151
152
153/*-------------------------------------------------------------------------*\
154* Creates a serial object
155\*-------------------------------------------------------------------------*/
156static int global_create(lua_State *L) {
157 const char* path = luaL_checkstring(L, 1);
158
159 /* allocate unix object */
160 p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
161
162 /* open serial device */
163 t_socket sock = open(path, O_NOCTTY|O_RDWR);
164
165 /*printf("open %s on %d\n", path, sock);*/
166
167 if (sock < 0) {
168 lua_pushnil(L);
169 lua_pushstring(L, socket_strerror(errno));
170 lua_pushnumber(L, errno);
171 return 3;
172 }
173 /* set its type as client object */
174 auxiliar_setclass(L, "serial{client}", -1);
175 /* initialize remaining structure fields */
176 socket_setnonblocking(&sock);
177 un->sock = sock;
178 io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
179 (p_error) socket_ioerror, &un->sock);
180 timeout_init(&un->tm, -1, -1);
181 buffer_init(&un->buf, &un->io, &un->tm);
182 return 1;
183}
diff --git a/src/socket.h b/src/socket.h
index de5d79f..debb13a 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -68,6 +68,9 @@ const char *socket_strerror(int err);
68int socket_send(p_socket ps, const char *data, size_t count, 68int socket_send(p_socket ps, const char *data, size_t count,
69 size_t *sent, p_timeout tm); 69 size_t *sent, p_timeout tm);
70int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); 70int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
71int socket_write(p_socket ps, const char *data, size_t count,
72 size_t *sent, p_timeout tm);
73int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
71const char *socket_ioerror(p_socket ps, int err); 74const char *socket_ioerror(p_socket ps, int err);
72 75
73int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); 76int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp);
diff --git a/src/usocket.c b/src/usocket.c
index e43cfa4..46087c6 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -300,6 +300,66 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
300 return IO_UNKNOWN; 300 return IO_UNKNOWN;
301} 301}
302 302
303
304/*-------------------------------------------------------------------------*\
305* Write with timeout
306*
307* socket_read and socket_write are cut-n-paste of socket_send and socket_recv,
308* with send/recv replaced with write/read. We can't just use write/read
309* in the socket version, because behaviour when size is zero is different.
310\*-------------------------------------------------------------------------*/
311int socket_write(p_socket ps, const char *data, size_t count,
312 size_t *sent, p_timeout tm)
313{
314 int err;
315 *sent = 0;
316 /* avoid making system calls on closed sockets */
317 if (*ps == SOCKET_INVALID) return IO_CLOSED;
318 /* loop until we send something or we give up on error */
319 for ( ;; ) {
320 long put = (long) write(*ps, data, count);
321 /* if we sent anything, we are done */
322 if (put >= 0) {
323 *sent = put;
324 return IO_DONE;
325 }
326 err = errno;
327 /* EPIPE means the connection was closed */
328 if (err == EPIPE) return IO_CLOSED;
329 /* we call was interrupted, just try again */
330 if (err == EINTR) continue;
331 /* if failed fatal reason, report error */
332 if (err != EAGAIN) return err;
333 /* wait until we can send something or we timeout */
334 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
335 }
336 /* can't reach here */
337 return IO_UNKNOWN;
338}
339
340/*-------------------------------------------------------------------------*\
341* Read with timeout
342* See note for socket_write
343\*-------------------------------------------------------------------------*/
344int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) {
345 int err;
346 *got = 0;
347 if (*ps == SOCKET_INVALID) return IO_CLOSED;
348 for ( ;; ) {
349 long taken = (long) read(*ps, data, count);
350 if (taken > 0) {
351 *got = taken;
352 return IO_DONE;
353 }
354 err = errno;
355 if (taken == 0) return IO_CLOSED;
356 if (err == EINTR) continue;
357 if (err != EAGAIN) return err;
358 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
359 }
360 return IO_UNKNOWN;
361}
362
303/*-------------------------------------------------------------------------*\ 363/*-------------------------------------------------------------------------*\
304* Put socket into blocking mode 364* Put socket into blocking mode
305\*-------------------------------------------------------------------------*/ 365\*-------------------------------------------------------------------------*/