201 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*=========================================================================*\
 | |
| * Serial stream
 | |
| * LuaSocket toolkit
 | |
| \*=========================================================================*/
 | |
| #include <string.h> 
 | |
| 
 | |
| #include "lua.h"
 | |
| #include "lauxlib.h"
 | |
| #include "luasocket.h"
 | |
| 
 | |
| #include "auxiliar.h"
 | |
| #include "socket.h"
 | |
| #include "options.h"
 | |
| #include "unix.h"
 | |
| 
 | |
| #ifndef _WIN32
 | |
| #include <sys/un.h> 
 | |
| #endif
 | |
| 
 | |
| /*
 | |
| Reuses userdata definition from unix.h, since it is useful for all
 | |
| stream-like objects.
 | |
| 
 | |
| If we stored the serial path for use in error messages or userdata
 | |
| printing, we might need our own userdata definition.
 | |
| 
 | |
| Group usage is semi-inherited from unix.c, but unnecessary since we
 | |
| have only one object type.
 | |
| */
 | |
| 
 | |
| namespace NS_SLUA {    
 | |
| 
 | |
| /*=========================================================================*\
 | |
| * Internal function prototypes
 | |
| \*=========================================================================*/
 | |
| static int serial_global_create(lua_State *L);
 | |
| static int serial_meth_send(lua_State *L);
 | |
| static int serial_meth_receive(lua_State *L);
 | |
| static int serial_meth_close(lua_State *L);
 | |
| static int serial_meth_settimeout(lua_State *L);
 | |
| static int serial_meth_getfd(lua_State *L);
 | |
| static int serial_meth_setfd(lua_State *L);
 | |
| static int serial_meth_dirty(lua_State *L);
 | |
| static int serial_meth_getstats(lua_State *L);
 | |
| static int serial_meth_setstats(lua_State *L);
 | |
| 
 | |
| /* serial object methods */
 | |
| static luaL_Reg serial_methods[] = {
 | |
|     {"__gc",        serial_meth_close},
 | |
|     {"__tostring",  auxiliar_tostring},
 | |
|     {"close",       serial_meth_close},
 | |
|     {"dirty",       serial_meth_dirty},
 | |
|     {"getfd",       serial_meth_getfd},
 | |
|     {"getstats",    serial_meth_getstats},
 | |
|     {"setstats",    serial_meth_setstats},
 | |
|     {"receive",     serial_meth_receive},
 | |
|     {"send",        serial_meth_send},
 | |
|     {"setfd",       serial_meth_setfd},
 | |
|     {"settimeout",  serial_meth_settimeout},
 | |
|     {NULL,          NULL}
 | |
| };
 | |
| 
 | |
| /* our socket creation function */
 | |
| /* this is an ad-hoc module that returns a single function 
 | |
|  * as such, do not include other functions in this array. */
 | |
| static luaL_Reg serial_func[] = {
 | |
|     {"serial", serial_global_create},
 | |
|     {NULL,          NULL}
 | |
| };
 | |
| 
 | |
| 
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Initializes module
 | |
| \*-------------------------------------------------------------------------*/
 | |
| LUASOCKET_API int luaopen_socket_serial(lua_State *L) {
 | |
|     /* create classes */
 | |
|     auxiliar_newclass(L, "serial{client}", serial_methods);
 | |
|     /* create class groups */
 | |
|     auxiliar_add2group(L, "serial{client}", "serial{any}");
 | |
| #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
 | |
|     lua_pushcfunction(L, serial_global_create);
 | |
|     (void)serial_func;
 | |
| #else
 | |
|     /* set function into socket namespace */
 | |
|     luaL_openlib(L, "socket", serial_func, 0);
 | |
|     lua_pushcfunction(L, serial_global_create);
 | |
| #endif
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /*=========================================================================*\
 | |
| * Lua methods
 | |
| \*=========================================================================*/
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Just call buffered IO methods
 | |
| \*-------------------------------------------------------------------------*/
 | |
| static int serial_meth_send(lua_State *L) {
 | |
|     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
 | |
|     return buffer_meth_send(L, &un->buf);
 | |
| }
 | |
| 
 | |
| static int serial_meth_receive(lua_State *L) {
 | |
|     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
 | |
|     return buffer_meth_receive(L, &un->buf);
 | |
| }
 | |
| 
 | |
| static int serial_meth_getstats(lua_State *L) {
 | |
|     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
 | |
|     return buffer_meth_getstats(L, &un->buf);
 | |
| }
 | |
| 
 | |
| static int serial_meth_setstats(lua_State *L) {
 | |
|     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
 | |
|     return buffer_meth_setstats(L, &un->buf);
 | |
| }
 | |
| 
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Select support methods
 | |
| \*-------------------------------------------------------------------------*/
 | |
| static int serial_meth_getfd(lua_State *L) {
 | |
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
 | |
|     lua_pushnumber(L, (int) un->sock);
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /* this is very dangerous, but can be handy for those that are brave enough */
 | |
| static int serial_meth_setfd(lua_State *L) {
 | |
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
 | |
|     un->sock = (t_socket) luaL_checknumber(L, 2); 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static int serial_meth_dirty(lua_State *L) {
 | |
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
 | |
|     lua_pushboolean(L, !buffer_isempty(&un->buf));
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Closes socket used by object 
 | |
| \*-------------------------------------------------------------------------*/
 | |
| static int serial_meth_close(lua_State *L)
 | |
| {
 | |
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
 | |
|     socket_destroy(&un->sock);
 | |
|     lua_pushnumber(L, 1);
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Just call tm methods
 | |
| \*-------------------------------------------------------------------------*/
 | |
| static int serial_meth_settimeout(lua_State *L) {
 | |
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
 | |
|     return timeout_meth_settimeout(L, &un->tm);
 | |
| }
 | |
| 
 | |
| /*=========================================================================*\
 | |
| * Library functions
 | |
| \*=========================================================================*/
 | |
| 
 | |
| 
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Creates a serial object 
 | |
| \*-------------------------------------------------------------------------*/
 | |
| static int serial_global_create(lua_State *L) {
 | |
| #ifndef _WIN32
 | |
|     const char* path = luaL_checkstring(L, 1);
 | |
| 
 | |
|     /* allocate unix object */
 | |
|     p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
 | |
| 
 | |
|     /* open serial device */
 | |
|     t_socket sock = open(path, O_NOCTTY|O_RDWR);
 | |
| 
 | |
|     /*printf("open %s on %d\n", path, sock);*/
 | |
| 
 | |
|     if (sock < 0)  {
 | |
|         lua_pushnil(L);
 | |
|         lua_pushstring(L, socket_strerror(errno));
 | |
|         lua_pushnumber(L, errno);
 | |
|         return 3;
 | |
|     }
 | |
|     /* set its type as client object */
 | |
|     auxiliar_setclass(L, "serial{client}", -1);
 | |
|     /* initialize remaining structure fields */
 | |
|     socket_setnonblocking(&sock);
 | |
|     un->sock = sock;
 | |
|     io_init(&un->io, (p_send) socket_write, (p_recv) socket_read, 
 | |
|             (p_error) socket_ioerror, &un->sock);
 | |
|     timeout_init(&un->tm, -1, -1);
 | |
|     buffer_init(&un->buf, &un->io, &un->tm);
 | |
|     return 1;
 | |
| #else
 | |
| 	return -1;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| } // end NS_SLUA
 |