Blame src/serial.c

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