/* * Kraken * Copyright (C) 2007 Rodrigo Cacilhas * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "kforker.h" #include "KrakenSocket.h" /* * Constantes */ #define MAXCONNECTIONS 120 const char *tcpmodulename = "-- socket type --"; /* * Cabeçalhos das funções */ static void set_info(lua_State *); static int kraken_loop(lua_State *); static void kraken_pushsocket(lua_State *, KrakenSocket *); static int kraken_registerAddress(lua_State *); static int kraken_registerApplication(lua_State *); static int kraken_registerUser(lua_State *); int luaopen_socket(lua_State *); int luaopen_kraken(lua_State *); static int socket_accept(lua_State *); static int socket_bind(lua_State *); static int socket_close(lua_State *); static int socket_getsockopt(lua_State *); static int socket_gettimeout(lua_State *); static int socket_new(lua_State *); static int socket_listen(lua_State *); static int socket_rawrecv(lua_State *); static int socket_rawsend(lua_State *); static int socket_receive(lua_State *); static int socket_send(lua_State *); static int socket_setsockopt(lua_State *); static int socket_settimeout(lua_State *); void dealwith(KrakenSocket *); int getIdByUsername(const string &); void makeDosEol(string &); bool prepareSocket(KrakenSocket *, const pair *); void prepareState(lua_State *, const string &); /* * Dados persistentes */ lua_State *application; pair *address; uid_t userid; /*---------------------------------------------------------------------- * Corpo principal */ int main(int argc, char **argv) { // Declara variáveis string conffile("/etc/kraken.lua"); string filename; struct stat buff; int status = -1; // 1º parâmetro: script com a aplicação if (argc > 1) filename = argv[1]; // 2º parâmetro: arquivo de configuração if (argc > 2) conffile = argv[2]; // Cria estado Lua lua_State *L = lua_open(); prepareState(L, conffile); // Executa o programa if (stat(filename.c_str(), &buff) == 0) status = luaL_loadfile(L, filename.c_str()); // Devolve erro sem piedade if (status) { cerr << lua_tostring(L, -1) << endl; lua_pop(L, 1); } else if (lua_pcall(L, 0, 0, 0)) { cout << lua_tostring(L, -1) << endl; lua_pop(L, 1); } // Fim! lua_close(L); return status; }// int main(int, char **) /*---------------------------------------------------------------------- * Funções principais */ int luaopen_kraken(lua_State *L) { /* * Função que carrega o módulo kraken */ // Ao carregar módulo: application = NULL; // zera aplicação address = NULL; // zera endereço userid = getuid(); // determina usuário // Funções do módulo static const luaL_reg krakenFuncs[] = { { "socket", socket_new }, { "registerAddress", kraken_registerAddress }, { "registerApplication", kraken_registerApplication }, { "registerUser", kraken_registerUser }, { "loop", kraken_loop }, { NULL, NULL } // fim }; // Registra o módulo no estado luaL_register(L, "kraken", krakenFuncs); set_info(L); return 1; }// int luaopen_kraken(lua_State *) int luaopen_socket(lua_State *L) { /* * Função que carrega o submódulo KrakenSocket * * Este submódulo dá suporte à classe homónima, para tanto, * ele deve ser carregado apenas como metatabela. */ // Métodos da classe static const luaL_reg tcpFuncs[] = { { "accept", socket_accept }, { "bind", socket_bind }, { "close", socket_close }, { "getoption", socket_getsockopt }, { "gettimeout", socket_gettimeout }, { "listen", socket_listen }, { "rawrecv", socket_rawrecv }, { "rawsend", socket_rawsend }, { "receive", socket_receive }, { "send", socket_send }, { "setoption", socket_setsockopt }, { "settimeout", socket_settimeout }, { NULL, NULL } // fim }; // Registra o submódulo e o torna um emulador de classe luaL_register(L, tcpmodulename, tcpFuncs); lua_pushliteral(L, "__index"); lua_getglobal(L, tcpmodulename); lua_settable(L, -3); return 1; }// int luaopen_socket(lua_State *) /*---------------------------------------------------------------------- * Ajusta outras informações */ static void set_info(lua_State *L) { /* * Função para ajustar informações do módulo e constantes úteis */ lua_pushliteral(L, "_COPYRIGHT"); lua_pushliteral(L, "Copyright (C) 2007 Rodrigo Cacilhas"); lua_settable(L, -3); lua_pushliteral(L, "_DESCRIPTION"); lua_pushliteral(L, "Kraken dispatcher"); lua_settable(L, -3); lua_pushliteral(L, "_NAME"); lua_pushliteral(L, "kraken"); lua_settable(L, -3); lua_pushliteral(L, "_VERSION"); lua_pushliteral(L, "8.09.0"); lua_settable(L, -3); /* * AF_* */ lua_pushliteral(L, "AF"); lua_newtable(L); lua_pushliteral(L, "APPLETALK"); lua_pushnumber(L, AF_APPLETALK); lua_settable(L, -3); lua_pushliteral(L, "ATMPVC"); lua_pushnumber(L, AF_ATMPVC); lua_settable(L, -3); lua_pushliteral(L, "AX25"); lua_pushnumber(L, AF_AX25); lua_settable(L, -3); lua_pushliteral(L, "INET"); lua_pushnumber(L, AF_INET); lua_settable(L, -3); lua_pushliteral(L, "INET6"); lua_pushnumber(L, AF_INET6); lua_settable(L, -3); lua_pushliteral(L, "IPX"); lua_pushnumber(L, AF_IPX); lua_settable(L, -3); lua_pushliteral(L, "NETLINK"); lua_pushnumber(L, AF_NETLINK); lua_settable(L, -3); lua_pushliteral(L, "PACKET"); lua_pushnumber(L, AF_PACKET); lua_settable(L, -3); lua_pushliteral(L, "UNIX"); lua_pushnumber(L, AF_UNIX); lua_settable(L, -3); lua_pushliteral(L, "X25"); lua_pushnumber(L, AF_X25); lua_settable(L, -3); lua_settable(L, -3); // tabela AF /* * SO_* */ lua_pushliteral(L, "SO"); lua_newtable(L); lua_pushliteral(L, "ACCEPTCONN"); lua_pushnumber(L, SO_ACCEPTCONN); lua_settable(L, -3); lua_pushliteral(L, "BSDCOMPAT"); lua_pushnumber(L, SO_BSDCOMPAT); lua_settable(L, -3); //lua_pushliteral(L, "BINDTODEVICE"); //lua_pushnumber(L, SO_BINDTODEVICE); //lua_settable(L, -3); lua_pushliteral(L, "BROADCAST"); lua_pushnumber(L, SO_BROADCAST); lua_settable(L, -3); lua_pushliteral(L, "DEBUG"); lua_pushnumber(L, SO_DEBUG); lua_settable(L, -3); lua_pushliteral(L, "ERROR"); lua_pushnumber(L, SO_ERROR); lua_settable(L, -3); lua_pushliteral(L, "DONTROUTE"); lua_pushnumber(L, SO_DONTROUTE); lua_settable(L, -3); lua_pushliteral(L, "KEEPALIVE"); lua_pushnumber(L, SO_KEEPALIVE); lua_settable(L, -3); lua_pushliteral(L, "LINGER"); lua_pushnumber(L, SO_LINGER); lua_settable(L, -3); lua_pushliteral(L, "OOBINLINE"); lua_pushnumber(L, SO_OOBINLINE); lua_settable(L, -3); lua_pushliteral(L, "PASSCRED"); lua_pushnumber(L, SO_PASSCRED); lua_settable(L, -3); lua_pushliteral(L, "PEERCRED"); lua_pushnumber(L, SO_PEERCRED); lua_settable(L, -3); lua_pushliteral(L, "PRIORITY"); lua_pushnumber(L, SO_PRIORITY); lua_settable(L, -3); lua_pushliteral(L, "RCVLOWAT"); lua_pushnumber(L, SO_RCVLOWAT); lua_settable(L, -3); lua_pushliteral(L, "SNDLOWAT"); lua_pushnumber(L, SO_SNDLOWAT); lua_settable(L, -3); lua_pushliteral(L, "RCVTIMEO"); lua_pushnumber(L, SO_RCVTIMEO); lua_settable(L, -3); lua_pushliteral(L, "SNDTIMEO"); lua_pushnumber(L, SO_SNDTIMEO); lua_settable(L, -3); lua_pushliteral(L, "RCVBUF"); lua_pushnumber(L, SO_RCVBUF); lua_settable(L, -3); //lua_pushliteral(L, "RCVBUFFORCE"); //lua_pushnumber(L, SO_RCVBUFFORCE); //lua_settable(L, -3); lua_pushliteral(L, "REUSEADDR"); lua_pushnumber(L, SO_REUSEADDR); lua_settable(L, -3); lua_pushliteral(L, "SNDBUF"); lua_pushnumber(L, SO_SNDBUF); lua_settable(L, -3); //lua_pushliteral(L, "SNDBUFFORCE"); //lua_pushnumber(L, SO_SNDBUFFORCE); //lua_settable(L, -3); lua_pushliteral(L, "TIMESTAMP"); lua_pushnumber(L, SO_TIMESTAMP); lua_settable(L, -3); lua_pushliteral(L, "TYPE"); lua_pushnumber(L, SO_TYPE); lua_settable(L, -3); lua_settable(L, -3); // tabela SO /* * SOCK_* */ lua_pushliteral(L, "SOCK"); lua_newtable(L); lua_pushliteral(L, "DGRAM"); lua_pushnumber(L, SOCK_DGRAM); lua_settable(L, -3); lua_pushliteral(L, "PACKET"); lua_pushnumber(L, SOCK_PACKET); lua_settable(L, -3); lua_pushliteral(L, "RAW"); lua_pushnumber(L, SOCK_RAW); lua_settable(L, -3); lua_pushliteral(L, "RDM"); lua_pushnumber(L, SOCK_RDM); lua_settable(L, -3); lua_pushliteral(L, "SEQPACKET"); lua_pushnumber(L, SOCK_SEQPACKET); lua_settable(L, -3); lua_pushliteral(L, "STREAM"); lua_pushnumber(L, SOCK_STREAM); lua_settable(L, -3); lua_settable(L, -3); // tabela SOCK }// static void set_info(lua_State *) /*---------------------------------------------------------------------- * Corpo das funções */ void dealwith(KrakenSocket *skt) { /* * Esta função é executada para cada conexão recebida * * skt: socket cliente recebido */ // Usa a aplicação como estado lua a ser executado lua_State *L = application; // IP e porta do socket string ip(skt->getip()); unsigned int port = skt->getport(); // Primeiro parâmetro: socket kraken_pushsocket(L, skt); // Segundo parâmetro: tabela com IP e porta lua_newtable(L); lua_pushstring(L, "host"); lua_pushstring(L, ip.c_str()); lua_settable(L, -3); lua_pushstring(L, "port"); lua_pushnumber(L, port); lua_settable(L, -3); // Executa a aplicação if (lua_pcall(L, 2, 0, 0) != 0) { cerr << lua_tostring(L, -1) << endl; lua_pop(L, 2); } // Fecha socket cliente e estado lua ao final skt->close(); lua_close(L); }// void dealwith(KrakenSocket *) int getIdByUsername(const string &username) { /* * Função que retorna o UID referente ao login fornecido */ int uid = -1; struct passwd *p = getpwnam(username.c_str()); if (p != NULL) { uid = static_cast(p->pw_uid); delete p; } return uid; }// int getIdByUsername(const string &username) static int kraken_loop(lua_State *L) { /* * kraken.loop() * * Inicia a aplicação * * @returns true */ if (application == NULL) { // sem aplicação não funciona lua_pushnil(L); lua_pushstring(L, "no application registered"); return 2; } else if (address == NULL) { // sem endereço não funciona lua_pushnil(L); lua_pushstring(L, "no address registered"); return 2; } else { // Cria novo socket mestre KrakenSocket *server = new KrakenSocket(AF_INET, SOCK_STREAM); if (server->isclosed()) { // Erro ao criar o socket lua_pushnil(L); lua_pushstring(L, "socket error"); return 2; } // Transforma o socket em servidor associando o endereço prepareSocket(server, address); // Muda o usuário setreuid(userid, userid); // Ciclo principal bool onLoop = true; while (onLoop) { // Aceita conexões KrakenSocket *client = server->accept(); if (client != NULL) { if (kfork() == 0) { // Processo filho server->close(); delete server; dealwith(client); onLoop = false; /* * TODO: bacalhau * FIXME: previne erro de corrupção de memória * * *** glibc detected *** kraken: malloc(): memory corruption: 0x08073830 *** */ client->close(); _exit(0); } // Encerra socket cliente client->close(); delete client; } } // Retorna verdadeiro lua_pushboolean(L, 1); return 1; } }// static int kraken_loop(lua_State *) void kraken_pushsocket(lua_State *L, KrakenSocket *skt) { /* * Registra uma instância de KrakenSocket no estado lua */ lua_pushlightuserdata(L, skt); lua_getglobal(L, tcpmodulename); lua_setmetatable(L, -2); }// void kraken_pushsocket(lua_State *, KrakenSocket *) static int kraken_registerAddress(lua_State *L) { /* * kraken.registerAddress() * * Registra endereço * * @param table { * host = string, * port = number * } * * @returns true */ // Declara variáveis string ip; unsigned int port; // Valor da chave host do 1º parâmetro é o IP lua_getfield(L, 1, "host"); if (lua_type(L, -1) != LUA_TSTRING) { lua_pushnil(L); lua_pushstring(L, "Parameter: { host = ##IP##, port = port }"); return 2; } ip = (char *) lua_tostring(L, -1); // Valor da chave port do 1º parâmetro é a porta lua_getfield(L, 1, "port"); if (!lua_isnumber(L, -1)) { lua_pushnil(L); lua_pushstring(L, "Parameter: { host = IP, port = ##port## }"); return 2; } port = static_cast(lua_tonumber(L, -1)); // Registra IP e porta recebidos address = new pair(ip, port); lua_pushboolean(L, 1); return 1; }// static int kraken_registerAddress(lua_State *) static int kraken_registerApplication(lua_State *L) { /* * kraken.registerApplication() * * Registra aplicação * * @param coroutine * * @returns nil, string * @returns true */ if (application != NULL) { // a aplicação já foi registrada lua_pushnil(L); lua_pushstring(L, "there's already an application registered"); return 2; } else if (lua_type(L, 1) != LUA_TTHREAD) { // não é corrotina lua_pushnil(L); lua_pushstring(L, "the parameter must be a coroutine"); return 2; } else { // Pega corrotina do estado lua application = lua_tothread(L, 1); if (application == NULL) { // algo saiu errado lua_pushnil(L); lua_pushstring(L, "error while loading function"); return 2; } else { // ok! lua_pushboolean(L, 1); return 1; } } return 0; // Jamais retornará 0 }// static int kraken_registerApplication(lua_State *) static int kraken_registerUser(lua_State *L) { /* * kraken.registerUser() * * Muda o usuário (se possível) * * @param number || string * * @returns boolean */ if (lua_isnumber(L, 1)) { // número // Recolhe número do estado e armazena userid = static_cast(lua_tonumber(L, 1)); // Retorna verdadeiro lua_pushboolean(L, 1); } else if (lua_type(L, 1) == LUA_TSTRING) { // string // Recolhe string do estado string aux(lua_tostring(L, 1)); // Determina o UID int id = getIdByUsername(aux); if (id < 0) lua_pushboolean(L, 0); // algo saiu errado else { userid = id; lua_pushboolean(L, 1); // ok! } } else lua_pushboolean(L, 0); // tipo inesperado return 1; }// static int kraken_registerUser(lua_State *) void makeDosEol(string &s) { /* * Converte string para terminação CRLF */ // Remove terminação atual int len = s.length(); while ((len > 0) and ((s[len - 1] == '\r') or (s[len - 1] == '\n'))) s.erase(--len); // Acrescenta CRLF s += "\r\n"; }// string makeDosEol(string) void prepareState(lua_State *L, const string &conffile) { /* * Carrega configurações iniciais no estado lua */ struct stat buff; luaL_openlibs(L); // carrega bibliotecas padrão luaopen_kraken(L); // carrega módulo kraken luaopen_socket(L); // carrega submódulo KrakenSocket // Carrega configurações iniciais (/etc/kraken.lua) if (stat(conffile.c_str(), &buff) == 0) { luaL_loadfile(L, conffile.c_str()); if (lua_pcall(L, 0, 0, 0)) { cerr << "Config-error: " << lua_tostring(L, -1) << endl; lua_pop(L, -1); } } }// void prepareState(lua_State *, const string) bool prepareSocket(KrakenSocket *skt, const pair *addr) { /* * Transforma um socket mestre em socket servidor associando um * endereço */ skt->setsockopt(SO_REUSEADDR, true); // libera endereço após uso skt->bind(addr->first, addr->second); // associa endereço return skt->listen(MAXCONNECTIONS); // retorna se listen foi ok }// bool prepareSocket(KrakenSocket *, const pair *) /*---------------------------------------------------------------------- * Métodos de KrakenSocket */ static int socket_accept(lua_State *L) { /* * obj:accept() * * Aceita conexões * * @returns nil, string * @returns client-socket, table { * host = string, * port = number * } */ // Recebe socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Aceita conexão KrakenSocket *client = skt->accept(); if (client == NULL) { // Erro lua_pushnil(L); lua_pushstring(L, "socket error"); } else { // Envia socket cliente para o estado lua kraken_pushsocket(L, client); // Envia tabela com IP e porta lua_newtable(L); lua_pushstring(L, "host"); lua_pushstring(L, client->getip().c_str()); lua_settable(L, -3); lua_pushstring(L, "port"); lua_pushnumber(L, client->getport()); lua_settable(L, -3); } return 2; }// static int socket_accept(lua_State *) static int socket_bind(lua_State *L) { /* * obj:bind() * * Associa endereço a um socket * * @param table { * host = string, * port = number * } * * @returns boolean */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Obtém tabela de endereço lua_getfield(L, 2, "host"); string ip(lua_tostring(L, -1)); lua_getfield(L, 2, "port"); unsigned int port = static_cast(lua_tonumber(L, -1)); // Associa IP e porta ao socket if (skt->bind(ip, port)) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); return 1; }// static int socket_bind(lua_State *) static int socket_close(lua_State *L) { /* * obj:close() * * Encerra o socket * * @return boolean */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Encerra o socket if (skt->close()) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); return 1; }// static int socket_close(lua_State *) static int socket_getsockopt(lua_State *L) { /* * obj:getsockopt() * * Retorna opção do socket * * @param number * * @returns boolean */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Obtém código numérico da opção int optname = static_cast(lua_tonumber(L, 2)); if (skt->getsockopt(optname)) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); return 1; }// static int socket_getsockopt(lua_State *) static int socket_gettimeout(lua_State *L) { /* * obj:gettimeout() * * Retorna o timeout * * @returns number, table { * number (rcvtimeo), * number (sndtimeo) * } */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Obtém o timeout int *timeout = skt->gettimeout(); if ((timeout[0] == -1) or (timeout[1] == -1)) { // Algo saiu errado lua_pushnil(L); lua_pushstring(L, "socket error"); } else { // Retorna número ao estado lua lua_pushnumber(L, timeout[0]); // Retorna tabela ao estado lua lua_newtable(L); lua_pushstring(L, "rcvtimeo"); lua_pushnumber(L, timeout[0]); lua_settable(L, -3); lua_pushstring(L, "sndtimeo"); lua_pushnumber(L, timeout[1]); lua_settable(L, -3); } return 2; }// static int socket_gettimeout(lua_State *) static int socket_new(lua_State *L) { /* * kraken.socket() * * Cria um socket mestre * * @param number domínio (AF_INET por defeito) * @param number tipo (SOCK_STREAM por defeito) * * @returns nil, string * @returns KrakenSocket */ // Valores por defeito int domain = AF_INET; int type = SOCK_STREAM; // Obtém parâmetros if (lua_type(L, 1) == LUA_TNUMBER) domain = static_cast(lua_tonumber(L, 1)); if (lua_type(L, 2) == LUA_TNUMBER) type = static_cast(lua_tonumber(L, 2)); // Cria novo socket KrakenSocket *skt = new KrakenSocket(domain, type); if (skt->isclosed()) { // Deu problema lua_pushnil(L); lua_pushstring(L, "socket error"); delete skt; return 2; } else { // Retorna socket kraken_pushsocket(L, skt); return 1; } return 0; // nunca retornará 0 }// static int socket_new(lua_State *) static int socket_listen(lua_State *L) { /* * obj:listen() * * Registra limite de fila do socket * * @parameter number (1 por defeito) * * @returns boolean */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Limite unsigned int max = 1; // Obtém limite do estado lua if (lua_type(L, 2) == LUA_TNUMBER) max = static_cast(lua_tonumber(L, 2)); // Retorna verdadeiro ou falso lua_pushboolean(L, static_cast(skt->listen(max))); return 1; }// static int socket_listen(lua_State *) static int socket_rawrecv(lua_State *L) { /* * obj:rawrecv() * * Versão crua de recv() * * @param number tamanho esperado * * @returns string arbitária */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Obtém tamanho esperado do estado lua int len = static_cast(lua_tonumber(L, 2)); // Recebe string pelo socket string received(skt->recv(len)); // Envia string ao estado lua lua_pushstring(L, received.c_str()); return 1; }// static int socket_rawrecv(lua_State *) static int socket_rawsend(lua_State *L) { /* * obj:rawsend() * * Versão crua de send() * * @param number || string * * @returns boolean */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); bool ok = false; if (lua_type(L, 2) == LUA_TNUMBER) { // Se o segundo argumento for um número, interpreta como código // ASCII de um carácter a ser enviado unsigned char tosend = static_cast(lua_tonumber(L, 2)); ok = skt->send(tosend); } else { // Se o segundo argumento for uma string, envia-a string tosend(lua_tostring(L, 2)); ok = skt->send(tosend); } // Retorna verdadeiro ou falso lua_pushboolean(L, static_cast(ok)); return 1; }// static int socket_rawsend(lua_State *) static int socket_receive(lua_State *L) { /* * obj:receive() * * Recebe uma string bem formada de tamanho arbitário sem mudança de * linha * * @returns string */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); string aux; string tmp; // Enquanto não receber mudança de linham, continua coletando do // socket carácter por carácter while (tmp[0] != '\n') { tmp = skt->recv(1); aux += tmp[0]; } // Converte para formato DOS (CRLF) e remove a mudança de linha makeDosEol(aux); aux.erase(aux.length() - 2); // Envia string para o estado lua lua_pushstring(L, aux.c_str()); return 1; }// static int socket_receive(lua_State *) static int socket_send(lua_State *L) { /* * obj:send() * * Envia uma string bem formada para o socket * * @param string * * @returns boolean */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Obtém string do estado lua string tosend(lua_tostring(L, 2)); // Converte string para formato DOS (CRLF) makeDosEol(tosend); // Envia string pelo socket e sinal de ok para o estado lua lua_pushboolean(L, static_cast(skt->send(tosend))); return 1; }// static int socket_send(lua_State *) static int socket_setsockopt(lua_State *L) { /* * obj:setsockopt() * * Ajusta opção de socket * * @param number opção * @param boolean * * @returns boolean */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Obtém código numérico da opção int optname = static_cast(lua_tonumber(L, 2)); // Obtém verdadeiro ou falso bool on = true; if (lua_type(L, 3) == LUA_TBOOLEAN) { on = static_cast(lua_toboolean(L, 3)); } // Altera opção de socket e avisa o estado lua lua_pushboolean(L, static_cast(skt->setsockopt(optname, on))); return 1; }// static int socket_setsockopt(lua_State *) static int socket_settimeout(lua_State *L) { /* * obj:settimeout() * * Ajusta timeout * * @param number * * @returns boolean */ // Obtém socket do estado lua KrakenSocket *skt = reinterpret_cast(lua_touserdata(L, 1)); // Obtém timeout do estado lua int timeout = static_cast(lua_tonumber(L, 2)); // Ajusta timeout do socket e retorna verdadeiro ou falso para lua lua_pushboolean(L, static_cast(skt->settimeout(timeout))); return 1; }// static int socket_settimeout(lua_State *)