/****************************************************************************** * $Id: psock_lua.c,v 1.11 2006/01/13 21:46:54 gareuselesinge Exp $ * This file is part of FreePOPs (http://www.freepops.org) * * This file is distributed under the terms of GNU GPL license. * ******************************************************************************/ /****************************************************************************** * File description: * lua bindings for portablesocket * Notes: * * Authors: * Name ******************************************************************************/ #include #include #include "lua.h" #include "lauxlib.h" #include "socketcommon.h" #include "luabind.h" #include "compat-5.1.h" #include "log.h" #define LOG_ZONE "psock" #define METANAME "sockstate.type" #define BUFSIZE 2048 #define DBG_NONE (0<<0) #define DBG_SEND (1<<0) #define DBG_RECV (1<<1) #define DBG_INFO (1<<2) #define DBG_ALL (DBG_INFO|DBG_RECV|DBG_SEND) #define IS_ACTIVE(a) ((a) & (debug_opt)) #define BEGIN_WITH(s,a) (!strncmp((s),(a),strlen(a))) // only one debug mode for the whole library... // FIXME write more selective_print and choose the right one or add extra // parameter to print in the sockets.. static int debug_opt = DBG_NONE; // returns and checks a stringhack from the stack static struct sock_state_t* check_sockstate(lua_State*L) { void* tmp = luaL_checkudata(L,1,METANAME); luaL_argcheck(L,tmp != NULL,1,"sockstate expected"); return *(struct sock_state_t**)tmp; } // prints only selected messages (third connect parameter) static void selective_print(char*s) { if (BEGIN_WITH(s,SOCK_ERROR)) { ERROR_PRINT(s); } else if (IS_ACTIVE(DBG_INFO) && BEGIN_WITH(s,SOCK_INFO)) { DBG("%s",s); } else if (IS_ACTIVE(DBG_SEND) && BEGIN_WITH(s,SOCK_SENT)) { DBG("%s",s); } else if (IS_ACTIVE(DBG_RECV) && BEGIN_WITH(s,SOCK_RECEIVED)) { DBG("%s",s); } } /* function: connect */ static int lua_psock_connect(lua_State* L) { struct sock_state_t** s; struct sock_state_t* tmp; const char* host; int port; int flag; L_checknarg(L,3,"connect wants 'host', 'port' and 'flag'"); host = luaL_checkstring(L,1); port = luaL_checkint(L,2); flag = luaL_checkint(L,3); tmp = sock_connect((char*)host,port,BUFSIZE*2,selective_print); if(tmp == NULL || sock_error_occurred(tmp)) { lua_pushnil(L); return 1; } s = lua_newuserdata(L,sizeof(struct sock_state_t*)); luaL_getmetatable(L,METANAME); lua_setmetatable(L,-2); *s = tmp; debug_opt = flag; return 1; } static int lua_psock_send(lua_State* L) { struct sock_state_t* tmp = check_sockstate(L); const char* data = luaL_checkstring(L,2); int rc; L_checknarg(L,2,"send wants 'data'"); rc = sock_send(tmp,(char*)data); lua_pushnumber(L,rc); return 1; } static int lua_psock_recv(lua_State* L) { struct sock_state_t* tmp = check_sockstate(L); char b[BUFSIZE]=""; int rc; L_checknarg(L,1,"recv wants no arguments"); rc = sock_receive(tmp,b,BUFSIZE); if(rc < 0) lua_pushnil(L); else lua_pushstring(L,b); return 1; } static int lua_psock_disconnect(lua_State* L) { struct sock_state_t* tmp = check_sockstate(L); sock_disconnect(tmp); return 0; } static const struct luaL_reg psock_f [] = { {"connect",lua_psock_connect}, {NULL,NULL} }; static const struct L_const psock_c [] = { {"SEND",DBG_SEND}, {"RECV",DBG_RECV}, {"ALL",DBG_ALL}, {"INFO",DBG_INFO}, {"NONE",DBG_NONE}, {NULL,0} }; static const struct luaL_reg psock_m [] = { {"send",lua_psock_send}, {"recv",lua_psock_recv}, {NULL,NULL} }; /* Open function */ int luaopen_psock (lua_State*L) { luaL_newmetatable(L,METANAME); lua_pushstring(L,"__gc"); lua_pushcfunction(L,lua_psock_disconnect); lua_settable(L,-3); lua_pushstring(L,"__index"); lua_pushvalue(L,-2); lua_settable(L,-3); luaL_openlib(L,NULL,psock_m,0); luaL_openlib(L,"psock",psock_f,0); L_openconst(L,psock_c); return 1; }