From d7bc357b2d1ec596e1b7fc982d0e299db3b4135c Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 3 Jan 2016 00:06:41 +1000 Subject: Beat the server connection manegement into shape. --- src/GuiLua/GuiLua.h | 2 +- src/LuaSL/LuaSL.h | 1 - src/extantz/extantz.c | 181 ++++++--------- src/extantz/extantz.h | 4 +- src/libraries/Runnr.h | 6 +- src/libraries/SledjHamr.c | 513 ++++++++++++++++++++++++----------------- src/libraries/SledjHamr.h | 21 +- src/love/love.c | 577 +++++++++++++++++++++------------------------- src/purkle/purkle.c | 7 +- 9 files changed, 670 insertions(+), 642 deletions(-) diff --git a/src/GuiLua/GuiLua.h b/src/GuiLua/GuiLua.h index d82d244..0e13c84 100644 --- a/src/GuiLua/GuiLua.h +++ b/src/GuiLua/GuiLua.h @@ -22,7 +22,7 @@ typedef struct _GuiLua winFang *us; // Our window, if it exists. winFang *parent; // Our parent window, if it exists. EPhysics_World *world; // Our world, if it exists. - Ecore_Con_Server *server; + Connection *server; int inDel; Eina_Clist node; diff --git a/src/LuaSL/LuaSL.h b/src/LuaSL/LuaSL.h index dba6550..d93298b 100644 --- a/src/LuaSL/LuaSL.h +++ b/src/LuaSL/LuaSL.h @@ -16,7 +16,6 @@ typedef struct _gameGlobals gameGlobals; // Define this here, so LuaSL_threads.h struct _gameGlobals { - Ecore_Con_Server *server; Eina_Hash *names; const char *address; int port; diff --git a/src/extantz/extantz.c b/src/extantz/extantz.c index 5a7d030..49e2ebe 100644 --- a/src/extantz/extantz.c +++ b/src/extantz/extantz.c @@ -12,7 +12,6 @@ static void on_pixels(void *data, Evas_Object *obj); int logDom = -1; // Our logging domain. globals ourGlobals; -static Eina_Strbuf *serverStream; //static char *myKey = "12345678-1234-4321-abcd-0123456789ab"; //static char *myName = "onefang rejected"; @@ -22,8 +21,8 @@ static Eina_Bool _add(void *data, int type, Ecore_Con_Event_Server_Add *ev) { globals *ourGlobals = data; - PI("Connected to love server."); - ourGlobals->server = ev->server; + PI("Spread the love."); + ourGlobals->server = ecore_con_server_data_get(ev->server); if (ourGlobals->LSLGuiMess) ourGlobals->LSLGuiMess->server = ourGlobals->server; if (ourGlobals->purkle) ourGlobals->purkle->server = ourGlobals->server; @@ -33,110 +32,86 @@ static Eina_Bool _add(void *data, int type, Ecore_Con_Event_Server_Add *ev) return ECORE_CALLBACK_RENEW; } -static Eina_Bool _data(void *data, int type, Ecore_Con_Event_Server_Data *ev) +static Eina_Bool clientParser(void *data, Connection *connection, char *SID, char *command, char *arguments) { globals *ourGlobals = data; char buf[PATH_MAX]; - char SID[PATH_MAX]; - const char *command; - char *ext; - eina_strbuf_append_length(serverStream, ev->data, ev->size); - command = eina_strbuf_string_get(serverStream); - while ((ext = index(command, '\n'))) + if ((0 == strncmp(command, "llOwnerSay(", 11)) + || (0 == strncmp(command, "llWhisper(", 10)) + || (0 == strncmp(command, "llSay(", 6)) + || (0 == strncmp(command, "llShout(", 8))) { - int length = ext - command; - strncpy(SID, command, length + 1); - SID[length] = '\0'; - eina_strbuf_remove(serverStream, 0, length + 1); - ext = index(SID, '.'); - if (ext) + sprintf(buf, "%s: %s", SID, command); + if (ourGlobals->purkle) { - ext[0] = '\0'; - command = ext + 1; - if ((0 == strncmp(command, "llOwnerSay(", 11)) - || (0 == strncmp(command, "llWhisper(", 10)) - || (0 == strncmp(command, "llSay(", 6)) - || (0 == strncmp(command, "llShout(", 8))) - { - - sprintf(buf, "%s: %s", SID, command); - if (ourGlobals->purkle) - { - int _P; - - lua_getfield(ourGlobals->purkle->L, LUA_REGISTRYINDEX, ourGlobals->purkle->name); - _P = lua_gettop(ourGlobals->purkle->L); - push_lua(ourGlobals->purkle->L, "@ ( $ )", _P, "append", buf, 0); - } - else - PW("No purkle to put - %s", buf); - } - else if (0 == strncmp(command, "llDialog(", 9)) - { - if (ourGlobals->LSLGuiMess) - { - int _M; - - lua_getfield(ourGlobals->LSLGuiMess->L, LUA_REGISTRYINDEX, ourGlobals->LSLGuiMess->name); - _M = lua_gettop(ourGlobals->LSLGuiMess->L); - - // TODO - Somewhere in the chain the new lines that MLP likes to put into llDialog's message munge things. Fix that. - push_lua(ourGlobals->LSLGuiMess->L, "@ ( $ )", _M, "doLua", command, 0); - } - else - PE("No LSLGuiMess to send - %s", command); - - } - else if (0 == strncmp(command, "loadSim(", 8)) - { + int _P; + + lua_getfield(ourGlobals->purkle->L, LUA_REGISTRYINDEX, ourGlobals->purkle->name); + _P = lua_gettop(ourGlobals->purkle->L); + push_lua(ourGlobals->purkle->L, "@ ( $ )", _P, "append", buf, 0); + } + else + PW("No purkle to put - %s", buf); + } + else if (0 == strncmp(command, "llDialog(", 9)) + { + if (ourGlobals->LSLGuiMess) + { + int _M; + + lua_getfield(ourGlobals->LSLGuiMess->L, LUA_REGISTRYINDEX, ourGlobals->LSLGuiMess->name); + _M = lua_gettop(ourGlobals->LSLGuiMess->L); + + // TODO - Somewhere in the chain the new lines that MLP likes to put into llDialog's message munge things. Fix that. + push_lua(ourGlobals->LSLGuiMess->L, "@ ( $ )", _M, "doLua", command, 0); + } + else + PE("No LSLGuiMess to send - %s", command); + + } + else if (0 == strncmp(command, "loadSim(", 8)) + { #if USE_EVAS_3D - char *p, *t; - int scenriLua; + char *p, *t; + int scenriLua; #endif - // Pretend we logged in. Actually in the case of a local love server, we realy have logged in now. - strcpy(ourGlobals->uuid, SID); - PI("Your UUID is %s.", ourGlobals->uuid); + // Pretend we logged in. Actually in the case of a local love server, we realy have logged in now. + strcpy(ourGlobals->uuid, SID); + PI("Your UUID is %s.", ourGlobals->uuid); #if USE_EVAS_3D - strcpy(buf, &command[8]); - p = buf; - while ('"' == p[0]) - p++; - while ('\'' == p[0]) - p++; - t = p; - while (('"' != p[0]) && ('\'' != p[0])) - p++; - p[0] = '\0'; - // TODO - For now, assume it's a file:// URL. - t += 7; - //strcat(t, "/index.omg"); - strcpy(ourGlobals->scene->sim, t); - PI("Loading local sim from %s", t); - - // TODO - Later do the same with eet files in C code, but keep both implementations. - lua_getglobal(ourGlobals->scene->L, "package"); - lua_getfield(ourGlobals->scene->L, lua_gettop(ourGlobals->scene->L), "loaded"); - lua_remove(ourGlobals->scene->L, -2); // Removes "package" - lua_getfield(ourGlobals->scene->L, lua_gettop(ourGlobals->scene->L), "scenriLua"); - lua_remove(ourGlobals->scene->L, -2); // Removes "loaded" - scenriLua = lua_gettop(ourGlobals->scene->L); - - push_lua(ourGlobals->scene->L, "@ ( $ )", scenriLua, "loadSim", t, 0); - PI("Loaded local sim from %s", t); + strcpy(buf, &command[8]); + p = buf; + while ('"' == p[0]) + p++; + while ('\'' == p[0]) + p++; + t = p; + while (('"' != p[0]) && ('\'' != p[0])) + p++; + p[0] = '\0'; + // TODO - For now, assume it's a file:// URL. + t += 7; + //strcat(t, "/index.omg"); + strcpy(ourGlobals->scene->sim, t); + PI("Loading local sim from %s", t); + + // TODO - Later do the same with eet files in C code, but keep both implementations. + lua_getglobal(ourGlobals->scene->L, "package"); + lua_getfield(ourGlobals->scene->L, lua_gettop(ourGlobals->scene->L), "loaded"); + lua_remove(ourGlobals->scene->L, -2); // Removes "package" + lua_getfield(ourGlobals->scene->L, lua_gettop(ourGlobals->scene->L), "scenriLua"); + lua_remove(ourGlobals->scene->L, -2); // Removes "loaded" + scenriLua = lua_gettop(ourGlobals->scene->L); + + push_lua(ourGlobals->scene->L, "@ ( $ )", scenriLua, "loadSim", t, 0); + PI("Loaded local sim from %s", t); #endif - } - else - { - PI("Some random command %s", command); - } - } - - // Get the next blob to check it. - command = eina_strbuf_string_get(serverStream); } + else + PI("Some random command %s", command); return ECORE_CALLBACK_RENEW; } @@ -144,26 +119,12 @@ static Eina_Bool _data(void *data, int type, Ecore_Con_Event_Server_Data *ev) static Eina_Bool _del(void *data, int type, Ecore_Con_Event_Server_Del *ev) { globals *ourGlobals = data; - static int count = 0; ourGlobals->server = NULL; - // Let it fail a couple of times during startup, then try to start our own love server. - count++; - if (1 < count) - { - char buf[PATH_MAX]; - - PW("Failed to connect to a world server, starting our own."); - - // TODO - Should use Ecore_Exe for this sort of thing. - sprintf(buf, "%s/love &", prefix_bin_get()); - system(buf); - count = 0; - } - if (ourGlobals->running) return ECORE_CALLBACK_RENEW; + return ECORE_CALLBACK_CANCEL; } @@ -710,8 +671,6 @@ EAPI_MAIN int elm_main(int argc, char **argv) ephysics_world_del(ourGlobals.world); ephysics_shutdown(); - if (ourGlobals.server) ecore_con_server_del(ourGlobals.server); - if (ourGlobals.win) { ecore_animator_del(ourGlobals.animator); diff --git a/src/extantz/extantz.h b/src/extantz/extantz.h index c7edc07..2eddeb6 100644 --- a/src/extantz/extantz.h +++ b/src/extantz/extantz.h @@ -254,8 +254,8 @@ typedef struct _globals GuiLua *purkle; GuiLua *LSLGuiMess; - Ecore_Con_Server *server; - char uuid[42]; + Connection *server; + char uuid[42]; } globals; diff --git a/src/libraries/Runnr.h b/src/libraries/Runnr.h index a2098d9..b44dca4 100644 --- a/src/libraries/Runnr.h +++ b/src/libraries/Runnr.h @@ -12,6 +12,8 @@ #include #include +#include "SledjHamr.h" + // Stick with Plan C for now. // TODO - Should make this choosable at run time after more testing of Ecore_Thead. #define THREADIT 0 @@ -41,7 +43,7 @@ typedef struct _LuaCompile { char *file, *SID, *luaName; int bugCount; - Ecore_Con_Client *client; + Connection *client; compileCb parser; compileCb cb; boolean doConstants; @@ -69,7 +71,7 @@ typedef struct _script runnrStatus status; RunnrServerCb send2server; Eina_Clist messages; - Ecore_Con_Client *client; + Connection *client; Ecore_Timer *timer; } script; diff --git a/src/libraries/SledjHamr.c b/src/libraries/SledjHamr.c index 3445e52..10eeca5 100644 --- a/src/libraries/SledjHamr.c +++ b/src/libraries/SledjHamr.c @@ -5,15 +5,6 @@ #include "SledjHamr.h" -struct _conct -{ - char *address; - int port; - void *pointer; - Ecore_Event_Handler_Cb addCb, dataCb, delCb; - Ecore_Event_Handler *add, *data, *del; -}; - struct _message { Eina_Clist node; @@ -21,48 +12,6 @@ struct _message }; -static Eina_Bool _add(void *data, int type, Ecore_Con_Event_Server_Del *ev) -{ - struct _conct *this = data; - - if (this->addCb) - this->addCb(this->pointer, type, ev); - if (this->dataCb) - ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, this->dataCb, this->pointer); - - return ECORE_CALLBACK_RENEW; -} - -static Eina_Bool _delTimer(void *data) -{ - struct _conct *this = data; - - reachOut(this->address, this->port, this->pointer, this->addCb, this->dataCb, this->delCb); - return ECORE_CALLBACK_CANCEL; -} - -static Eina_Bool _del(void *data, int type, Ecore_Con_Event_Server_Del *ev) -{ - struct _conct *this = data; - - printf("FAILED connection to server %s:%d, trying again in a second!\n", this->address, this->port); - ecore_event_handler_del(this->add); - ecore_event_handler_del(this->del); - - if (this->delCb) - { - if (ECORE_CALLBACK_RENEW == this->delCb(this->pointer, type, ev)) - ecore_timer_add(1.0, _delTimer, this); - } - - if (ev->server) ecore_con_server_del(ev->server); - // TODO - Hmm, I think this is where this should be freed, but it causes a seggie in reachOut's while loop. - // Which is odd, so leave it commented for now and investigate later. -// free(this); - - return ECORE_CALLBACK_CANCEL; -} - void *addMessage(Eina_Clist *list, size_t size, const char *message, ...) { va_list args; @@ -82,10 +31,68 @@ void *addMessage(Eina_Clist *list, size_t size, const char *message, ...) return result; } -void sendBack(Ecore_Con_Client *client, const char *SID, const char *message, ...) +static boolean checkConnection(Connection *conn, char *func, connType wanted, boolean isLocal) +{ + boolean result = TRUE; + + if ((conn->type != CT_CLIENT) && (conn->type != CT_SERVER)) + { + result = FALSE; + printf("CONNECTION OBJECT in %s() is of unknown type %d\n", func, (int) conn->type); + } + else if (conn->type != wanted) + { + result = FALSE; + switch (wanted) + { + case CT_CLIENT : + if (conn->type == CT_SERVER) + printf("INVALID CONNECTION OBJECT in %s(), it might be a server object!\n", func); + else + printf("INVALID CONNECTION OBJECT in %s(), type is %d!\n", func, (int) conn->type); + if (conn->conn.client.myServer == NULL) + printf("CONNECTION OBJECT in %s() is a local client, but should be a remote client mirror!\n", func); + break; + + case CT_SERVER : + if (conn->type == CT_CLIENT) + printf("INVALID CONNECTION OBJECT in %s(), it might be a client object!\n", func); + else + printf("INVALID CONNECTION OBJECT in %s(), type is %d!\n", func, (int) conn->type); + if (isLocal) + { + if (conn->conn.server.clients == NULL) + printf("CONNECTION OBJECT in %s() is a remote server mirror, but should be a local server!\n", func); + } + else + { + if (conn->conn.server.clients != NULL) + printf("CONNECTION OBJECT in %s() is a local server, but should be a remote server mirror!\n", func); + } + break; + + default : + printf("CONNECTION OBJECT in %s(), silly coder asked for an unknown type!""\n", func); + break; + } + + if (NULL == conn->name) + { + result = FALSE; + printf("CONNECTION OBJECT in %s() has no name!\n", func); + } + } + +//if (result) printf("%s(\"%s\")\n", func, conn->name); + + return result; +} + +void sendBack(Connection *conn, const char *SID, const char *message, ...) { va_list args; - char buf[PATH_MAX]; +// Ecore_Con_Client *client = conn->conn.client.client; + char buf[PATH_MAX * 2]; int length = strlen(SID); strncpy(buf, SID, length); @@ -95,15 +102,18 @@ void sendBack(Ecore_Con_Client *client, const char *SID, const char *message, .. va_end(args); buf[length++] = '\n'; buf[length] = '\0'; -// printf("sendBack(%s)", buf); - ecore_con_client_send(client, buf, length); - ecore_con_client_flush(client); +// printf("sendBack(%s", buf); +// ecore_con_client_send(client, buf, length); +// ecore_con_client_flush(client); +//Connection *conn = ecore_con_client_data_get(client); +if (conn) send2(conn, SID, buf); else printf("sendBack() can't find Connection!\n"); } -void sendForth(Ecore_Con_Server *server, const char *SID, const char *message, ...) +void sendForth(Connection *conn, const char *SID, const char *message, ...) { va_list args; - char buf[PATH_MAX]; +// Ecore_Con_Server *server = conn->conn.server.server; + char buf[PATH_MAX * 2]; int length = strlen(SID); strncpy(buf, SID, length); @@ -113,123 +123,196 @@ void sendForth(Ecore_Con_Server *server, const char *SID, const char *message, . va_end(args); buf[length++] = '\n'; buf[length] = '\0'; -// printf("sendForth(%s)", buf); - ecore_con_server_send(server, buf, length); - ecore_con_server_flush(server); +// printf("sendForth(%s", buf); +// ecore_con_server_send(server, buf, length); +// ecore_con_server_flush(server); +//Connection *conn = ecore_con_server_data_get(server); +if (conn) send2(conn, SID, buf); else printf("sendForth() can't find Connection!\n"); } +void send2(Connection *conn, const char *SID, const char *message, ...) +{ + va_list args; + char buf[PATH_MAX * 2]; + int length = strlen(SID); +length = 0; +// strncpy(buf, SID, length); +// buf[length++] = '.'; + va_start(args, message); +// length += vsprintf(&buf[length], message, args); + va_end(args); +strcpy(buf, message); +length = strlen(buf); +// buf[length++] = '\n'; + buf[length] = '\0'; +// TODO - Should check if this is always gonna be local? Likely not. + if (checkConnection(conn, "send2", conn->type, FALSE)) + { + switch (conn->type) + { + case CT_CLIENT : +// printf("vvv send2(%*s", length, buf); + ecore_con_client_send(conn->conn.client.client, strndup(buf, length), length); + ecore_con_client_flush(conn->conn.client.client); + break; + + case CT_SERVER : +// printf("^^^ send2(%*s", length, buf); + ecore_con_server_send(conn->conn.server.server, strndup(buf, length), length); + ecore_con_server_flush(conn->conn.server.server); + break; + + default : + printf("send2() unable to send to partially bogus Connection object!\n"); + break; + } + } + else + printf("send2() unable to send to bogus Connection object!\n"); +} static Eina_Bool parseStream(void *data, int type, void *evData, int evSize, void *ev) { - Connection *connection = data; + Connection *conn = data; char SID[PATH_MAX]; const char *command; char *ext; - if (NULL == connection->stream) - connection->stream = eina_strbuf_new(); +//printf("parseStream(%s, \"%*s\")\n", conn->name, evSize, (char *) evData); + if (NULL == conn->stream) + conn->stream = eina_strbuf_new(); - eina_strbuf_append_length(connection->stream, evData, evSize); - command = eina_strbuf_string_get(connection->stream); + eina_strbuf_append_length(conn->stream, evData, evSize); + command = eina_strbuf_string_get(conn->stream); while ((ext = index(command, '\n'))) { int length = ext - command; strncpy(SID, command, length + 1); SID[length] = '\0'; - eina_strbuf_remove(connection->stream, 0, length + 1); + eina_strbuf_remove(conn->stream, 0, length + 1); ext = index(SID, '.'); if (ext) { ext[0] = '\0'; command = ext + 1; - ext = index(SID, '('); + ext = index(command, '('); if (ext) { - streamParser func = eina_hash_find(connection->commands, command); -//PW("COMMAND - %s", command); - - ext[0] = '\0'; + streamParser func = eina_hash_find(conn->commands, command); +//printf("parseStream(%s>> %s\"\n", conn->name, command); +// ext[0] = '\0'; // Need a callback if we can't find the command. if (NULL == func) - func = connection->unknownCommand; + func = conn->unknownCommand; if (func) - func(data, connection, SID, (char *) command, ext + 1); + func(conn->pointer, conn, SID, (char *) command, ext + 1); + else + printf("parseStream() No function found for command %s!\n", command); } } // Get the next blob to check it. - command = eina_strbuf_string_get(connection->stream); + command = eina_strbuf_string_get(conn->stream); } - if (connection->_data) - connection->_data(data, type, ev); + if (conn->_data) + conn->_data(conn->pointer, type, ev); return ECORE_CALLBACK_RENEW; } -Eina_Bool parseClientStream(void *data, int type, Ecore_Con_Event_Client_Data *ev) +static Eina_Bool parseClientStream(void *data, int type, Ecore_Con_Event_Client_Data *ev) { - // data is the server connection, but we want the client one. - return parseStream(ecore_con_client_data_get(ev->client), type, ev->data, ev->size, ev); + Connection *conn = /*data*/ ecore_con_client_data_get(ev->client); + + if (checkConnection(conn, "parseClientStream", CT_CLIENT, FALSE)) + return parseStream(conn, type, ev->data, ev->size, ev); + return ECORE_CALLBACK_RENEW; } -Eina_Bool parseServerStream(void *data, int type, Ecore_Con_Event_Server_Data *ev) +static Eina_Bool parseServerStream(void *data, int type, Ecore_Con_Event_Server_Data *ev) { - return parseStream(data, type, ev->data, ev->size, ev); -} + Connection *conn = /*data*/ ecore_con_server_data_get(ev->server); + + if (checkConnection(conn, "parseServerStream", CT_SERVER, FALSE)) + return parseStream(conn, type, ev->data, ev->size, ev); + return ECORE_CALLBACK_RENEW; +} -Eina_Bool clientAdd(void *data, int type, Ecore_Con_Event_Client_Add *ev) +static Eina_Bool clientAdd(void *data, int type, Ecore_Con_Event_Client_Add *ev) { - Connection *conn, *connection = data; + Connection *conn, *connection = data; + if (checkConnection(connection, "clientAdd", CT_SERVER, TRUE)) + { ecore_con_client_timeout_set(ev->client, 0); conn = calloc(1, sizeof(Connection)); conn->type = CT_CLIENT; conn->conn.client.client = ev->client; conn->conn.client.myServer = connection; + conn->conn.client.server = malloc(sizeof(Eina_Clist)); + eina_clist_element_init(conn->conn.client.server); + eina_clist_add_tail(connection->conn.server.clients, conn->conn.client.server); conn->name = strdup(connection->name); conn->address = strdup(connection->address); conn->port = connection->port; conn->pointer = connection->pointer; + conn->_add = connection->_add; + conn->_data = connection->_data; + conn->_del = connection->_del; + conn->unknownCommand = connection->unknownCommand; conn->commands = eina_hash_string_superfast_new(NULL); ecore_con_client_data_set(ev->client, conn); if (connection->_add) return connection->_add(connection->pointer, type, ev); - return ECORE_CALLBACK_RENEW; + } + + return ECORE_CALLBACK_RENEW; } -Eina_Bool clientDel(void *data, int type, Ecore_Con_Event_Client_Del *ev) +static Eina_Bool clientDel(void *data, int type, Ecore_Con_Event_Client_Del *ev) { - Connection *connection = data; + Connection *conn = data; + if (checkConnection(conn, "clientDel", CT_SERVER, TRUE)) + { if (ev->client) { Eina_List const *clients; + if (conn->_del) + conn->_del(conn->pointer, type, ev); + + ecore_con_client_del(ev->client); + + // This is only really for testing, normally it just runs 24/7, or until told not to. - clients = ecore_con_server_clients_get(connection->conn.server.server); + // The "- 1" is coz this server is still counted. + clients = ecore_con_server_clients_get(conn->conn.server.server) - 1; if (0 == eina_list_count(clients)) - printf("No more clients, exiting."); + printf("No more clients for %s, exiting.\n", conn->name); else - printf("Some %d more clients, exiting anyway.", eina_list_count(clients)); - -// TODO - Probably should just keep running, both servers, and go away when all clients are gone for testing. + printf("Some (%d) more clients for %s, exiting anyway.\n", eina_list_count(clients), conn->name); - if (connection->_del) - connection->_del(connection->pointer, type, ev); + // TODO - the Connection free function should take care of all of this, and we should call it here. ish. + eina_clist_remove(conn->conn.client.server); + free(conn->conn.client.server); + conn->conn.client.server = NULL; - ecore_con_client_del(ev->client); +// TODO - Probably should just keep running, both servers, and go away when all clients are gone for testing. ecore_main_loop_quit(); } + } - return ECORE_CALLBACK_RENEW; + free(conn); + return ECORE_CALLBACK_RENEW; } Connection *openArms(char *name, const char *address, int port, void *data, Ecore_Event_Handler_Cb _add, Ecore_Event_Handler_Cb _data, Ecore_Event_Handler_Cb _del, streamParser _parser) @@ -238,11 +321,11 @@ Connection *openArms(char *name, const char *address, int port, void *data, Ecor Ecore_Con_Server *server; conn->type = CT_SERVER; -// conn->conn.server.serverCommand = ; + conn->conn.server.clients = malloc(sizeof(Eina_Clist)); + eina_clist_init(conn->conn.server.clients); conn->name = strdup(name); conn->address = strdup(address); conn->port = port; - conn->pointer = data; conn->_add = _add; conn->_data = _data; @@ -250,21 +333,23 @@ Connection *openArms(char *name, const char *address, int port, void *data, Ecor conn->unknownCommand = _parser; conn->commands = eina_hash_string_superfast_new(NULL); - if ((server = ecore_con_server_add(ECORE_CON_REMOTE_TCP, address, port, data))) + conn->add = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, (Ecore_Event_Handler_Cb) clientAdd, conn); + conn->data = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, (Ecore_Event_Handler_Cb) parseClientStream, conn); + conn->del = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, (Ecore_Event_Handler_Cb) clientDel, conn); +// conn->died = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _serverDied, conn); + + if ((server = ecore_con_server_add(ECORE_CON_REMOTE_TCP, address, port, conn))) { conn->conn.server.server = server; - - conn->add = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, (Ecore_Event_Handler_Cb) clientAdd, conn); - conn->add = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, (Ecore_Event_Handler_Cb) parseClientStream, conn); - conn->add = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, (Ecore_Event_Handler_Cb) clientDel, conn); - ecore_con_server_timeout_set(server, 0); - ecore_con_server_client_limit_set(server, -1, 0); - ecore_con_server_data_set(server, conn); -// ecore_con_server_timeout_set(server, 10); -// ecore_con_server_client_limit_set(server, 3, 0); + ecore_con_server_timeout_set(server, 0); + ecore_con_server_client_limit_set(server, -1, 0); +// ecore_con_server_timeout_set(server, 10); +// ecore_con_server_client_limit_set(server, 3, 0); + printf("ACTUALLY created the %s server %s:%d.\n", name, address, port); } else { + // TODO - Connection needs a generic free function. Only reason we are getting away with this is during initial testing, the Connections last the entire run anyway. free(conn->address); free(conn); conn = NULL; @@ -273,142 +358,154 @@ Connection *openArms(char *name, const char *address, int port, void *data, Ecor return conn; } -Eina_Bool serverAdd(void *data, int type, Ecore_Con_Event_Server_Add *ev) +static Eina_Bool serverAdd(void *data, int type, Ecore_Con_Event_Server_Add *ev) { - Connection *connection = data; - - connection->conn.server.hackyCount++; + Connection *conn = data; - // Alledgedly this checks for real conections, but given that the first time it's called, there's no real connection, this is failing somehow. - //if (ecore_con_server_connected_get(ev->server)) - if (connection->conn.server.hackyCount <= 1) - printf("Bogus server ignored."); - else + if (checkConnection(conn, "serverAdd", CT_SERVER, FALSE)) { - printf("Connected to %s server.", connection->name); - connection->conn.server.server = ev->server; - // In case the server crashed, clear out any waiting data. - if (connection->stream) - eina_strbuf_reset(connection->stream); + conn->conn.server.hackyCount++; + conn->stage++; - if (connection->_add) - connection->_add(data, type, ev); + if (conn->name) + printf("serverAdd()^^^^^^^^^^^^^^^^^^^^^^^Connected to %s server.\n", conn->name); + else + printf("serverAdd()^^^^^^^^^^^^^^^^^^^^^^^Connected to UNKNOWN server.\n"); + + // In case the server crashed, clear out any waiting data. + if (conn->stream) + eina_strbuf_reset(conn->stream); + if (conn->_add) + conn->_add(conn->pointer, type, ev); } return ECORE_CALLBACK_RENEW; } -Eina_Bool serverDel(void *data, int type, Ecore_Con_Event_Server_Del *ev) +static Eina_Bool serverDel(void *data, int type, Ecore_Con_Event_Server_Del *ev) { - Connection *connection = data; + Eina_Bool result = ECORE_CALLBACK_RENEW; + Connection *conn = data; - connection->conn.server.server = NULL; - -// connection->server.hackyCount--; - // Let it fail a couple of times during startup, then try to start our own script server. - connection->conn.server.count++; - if (1 < connection->conn.server.count) + if (checkConnection(conn, "serverDel", CT_SERVER, FALSE)) { - char buf[PATH_MAX]; - - printf("Failed to connect to a %s server, starting our own.", connection->name); - // TODO - Should use Ecore_Exe for this sort of thing. - sprintf(buf, "%s/%s &", prefix_bin_get(), connection->conn.server.serverCommand); - system(buf); - connection->conn.server.count = 0; - // TODO - There's also the question of what to do if the connection failed. - // Did the server crash, or was it just the connection? - // Probably gonna need some smarts, for now we just restart all the scripts. - // Which I think gets done on server add. + conn->conn.server.server = NULL; + conn->stage = -3; + if (conn->_del) + result = conn->_del(conn->pointer, type, ev); } - if (connection->_del) - connection->_del(data, type, ev); - - - // TODO - May want to renew even if it's not running the GUI, but then we still need some sort of "shut down" signal, which we don't need during testing. -// if (ourGlobals->ui) - return ECORE_CALLBACK_RENEW; - -// ecore_main_loop_quit(); - -// return ECORE_CALLBACK_CANCEL; - + return result; +} +static Eina_Bool _serverDied(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Connection *conn = data; +// Ecore_Exe_Event_Data *dataFromProcess = (Ecore_Exe_Event_Data *)event; -/* Extantz does this instead of the above returns - + conn->stage = -3; + conn->conn.server.serverHandle = NULL; + conn->conn.server.pid = 0; - if (ourGlobals->running) - return ECORE_CALLBACK_RENEW; - return ECORE_CALLBACK_CANCEL; -*/ + return ECORE_CALLBACK_DONE; } - - -#if 1 -Ecore_Con_Server *reachOut(char *address, int port, void *data, Ecore_Event_Handler_Cb _addCb, Ecore_Event_Handler_Cb _dataCb, Ecore_Event_Handler_Cb _delCb) +// TODO - instead of a timer, try to make this event driven. Use jobs, or idler, or something. +static Eina_Bool _reachOutTimer(void *data) { + Eina_Bool result = ECORE_CALLBACK_RENEW; + Connection *conn = data; Ecore_Con_Server *server = NULL; - struct _conct *this = malloc(sizeof(struct _conct)); - int count = 0; - - this->address = address; - this->port = port; - this->pointer = data; - this->addCb = _addCb; - this->dataCb = _dataCb; - this->delCb = _delCb; - // This loop is overkill I think. - while ((!server) && (10 > count)) + + switch (conn->stage) { - if ((server = ecore_con_server_connect(ECORE_CON_REMOTE_TCP, address, port, this->pointer))) - { - this->add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, (Ecore_Event_Handler_Cb) _add, this); - this->del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, (Ecore_Event_Handler_Cb) _del, this); - } - count++; - } + // TODO - Seems Ecore_con now has trouble with my try first, then start method, so start first, then try. Fix this, or do something else. + case -3 : + printf("Failed to connect to a %s server, starting our own.\n", conn->name); + conn->conn.server.serverHandle = ecore_exe_pipe_run(conn->conn.server.serverCommand, ECORE_EXE_NONE /*| ECORE_EXE_TERM_WITH_PARENT*/, conn); + if (conn->conn.server.serverHandle) + { + conn->conn.server.pid = ecore_exe_pid_get(conn->conn.server.serverHandle); + if (conn->conn.server.pid == -1) + fprintf(stderr, "Could not retrive the PID!\n"); + else + fprintf(stdout, "The child process has PID:%u\n", (unsigned int)conn->conn.server.pid); + } + else + fprintf(stderr, "Could not create server process %s!\n", conn->conn.server.serverCommand); + + // TODO - There's also the question of what to do if the connection failed. + // Did the server crash, or was it just the connection? + // Also, I'm assuming the connection failed here, rather than went away after running for some time. Should differentiate. + // Probably gonna need some smarts, for now we just restart all the scripts. + // Which I think gets done on server add. + break; + +// TODO - Alternate strategy : Keep track of if we started a server, then keep pinging it's port until it answers, +// with a timeout until we kill the server and start again. + + case -2 : // Give the server some time to start up. + case -1 : // Give the server some time to start up. + // Check if the server is still running here, if not, reset stage to previous -3 (taking into account the increment at the end). + if (conn->conn.server.pid) + printf("Waiting for %s server to start from command \"%s\"\n", conn->name, conn->conn.server.serverCommand); + else + conn->stage = -4; + break; + + case 0 : + printf("Attempting to connect to the %s server %s:%d.\n", conn->name, conn->address, conn->port); + // This should only return NULL if something goes wrong with the setup, + // you wont know if the connection worked until you get the add callback, + // or you get the del calback if it failed. + if ((server = ecore_con_server_connect(ECORE_CON_REMOTE_TCP, conn->address, conn->port, conn))) + printf("MAYBE connecting to the %s server %s:%d.\n", conn->name, conn->address, conn->port); + else + printf("FAILED to create the connection to the %s server %s:%d!\n", conn->name, conn->address, conn->port); + conn->conn.server.server = server; + break; - if (!server) - printf("Failed to connect to server %s:%d!\n", this->address, this->port); + case 1 : // This stage is the serverAdd callback. + break; - return server; + case 2 : // Give the server a chance to die. + break; + + default : + if (5 < conn->stage) + conn->stage = 2; // loop back to nothing. +// result = ECORE_CALLBACK_CANCEL; + break; + } + conn->stage++; + + return result; } -#else -Connection *reachOut(char *name, char *command, char *address, int port, void *data, Ecore_Event_Handler_Cb _add, Ecore_Event_Handler_Cb _data, Ecore_Event_Handler_Cb _del) + +Connection *reachOut(char *name, char *command, char *address, int port, void *data, Ecore_Event_Handler_Cb _add, Ecore_Event_Handler_Cb _data, Ecore_Event_Handler_Cb _del, streamParser _parser) { Connection *conn = calloc(1, sizeof(Connection)); - Ecore_Con_Server *server = NULL; - int count = 0; conn->type = CT_SERVER; conn->conn.server.serverCommand = strdup(command); + // Sure, this is essentially a NOP, but lets be explicit here, this is a remote server, so no list of clients, not just an empty list. + conn->conn.server.clients = NULL; conn->name = strdup(name); conn->address = strdup(address); conn->port = port; conn->pointer = data; - conn-> = _add; - conn-> = _data; - conn-> = _del; + conn->_add = _add; + conn->_data = _data; + conn->_del = _del; + conn->unknownCommand = _parser; conn->commands = eina_hash_string_superfast_new(NULL); - // This loop is overkill I think. - while ((!server) && (10 > count)) - { - if ((server = ecore_con_server_connect(ECORE_CON_REMOTE_TCP, address, port, data))) - { - conn->add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, (Ecore_Event_Handler_Cb) serverAdd, conn); - conn->data = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, (Ecore_Event_Handler_Cb) parseServerStream, conn); - conn->del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, (Ecore_Event_Handler_Cb) serverDel, conn); - ecore_con_server_data_set(server, conn); - } - count++; - } + conn->add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, (Ecore_Event_Handler_Cb) serverAdd, conn); + conn->data = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, (Ecore_Event_Handler_Cb) parseServerStream, conn); + conn->del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, (Ecore_Event_Handler_Cb) serverDel, conn); + conn->died = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _serverDied, conn); - if (!server) - printf("Failed to connect to the %s server %s:%d!\n", name, address, port); + ecore_timer_add(1.0, _reachOutTimer, conn); return conn; } -#endif diff --git a/src/libraries/SledjHamr.h b/src/libraries/SledjHamr.h index 467fcc6..326e423 100644 --- a/src/libraries/SledjHamr.h +++ b/src/libraries/SledjHamr.h @@ -23,12 +23,22 @@ struct _ConnServer Ecore_Con_Server *server; char *serverCommand; int count, hackyCount; + // A list of connected remote clients. + // A NULL list means this is a remote server stored in a local clients Connection. + // An empty list means this is a local server, with no clients. + // An actual list means this is a local server, with connected remote clients. + Eina_Clist *clients; // HEAD element. + Ecore_Exe *serverHandle; // For running the server. + pid_t pid; }; struct _ConnClient { Ecore_Con_Client *client; + // If this is a local client, then myServer is a server Connection representing the remote server, and the server list entry element can be NULL. + // If this is a remote client, then myServer is NULL, and this Connection is stored in a list in the local server's Connection. Connection *myServer; + Eina_Clist *server; // Entry element. }; struct _Connection @@ -48,16 +58,19 @@ struct _Connection // Callbacks. void *pointer; Ecore_Event_Handler_Cb _add, _data, _del; - Ecore_Event_Handler *add, *data, *del; + Ecore_Event_Handler *add, *data, *del, *died; streamParser unknownCommand; + + int stage; // Stage of creation for the Connection. }; -Ecore_Con_Server *reachOut(char *address, int port, void *data, Ecore_Event_Handler_Cb _add, Ecore_Event_Handler_Cb _data, Ecore_Event_Handler_Cb _del); void *addMessage(Eina_Clist *list, size_t size, const char *message, ...); -void sendBack(Ecore_Con_Client *client, const char *SID, const char *message, ...); -void sendForth(Ecore_Con_Server *server, const char *SID, const char *message, ...); +void sendBack(Connection *conn, const char *SID, const char *message, ...); +void sendForth(Connection *conn, const char *SID, const char *message, ...); +void send2(Connection *conn, const char *SID, const char *message, ...); Connection *openArms(char *name, const char *address, int port, void *data, Ecore_Event_Handler_Cb _add, Ecore_Event_Handler_Cb _data, Ecore_Event_Handler_Cb _del, streamParser _parser); +Connection *reachOut(char *name, char *command, char *address, int port, void *data, Ecore_Event_Handler_Cb _add, Ecore_Event_Handler_Cb _data, Ecore_Event_Handler_Cb _del, streamParser _parser); #endif diff --git a/src/love/love.c b/src/love/love.c index 0465ee5..372141d 100644 --- a/src/love/love.c +++ b/src/love/love.c @@ -33,9 +33,8 @@ typedef struct _gameGlobals Evas *canvas; // The canvas for drawing directly onto. Evas_Object *bg; // Our background edje, also the game specific stuff. Evas_Object *edje; // The edje of the background. - Ecore_Con_Server *serverLuaSL; - Ecore_Con_Server *server; - Ecore_Con_Client *client; // TODO - Really should be a bunch of these. + Connection *serverLuaSL; + Connection *client; // TODO - Really should be a bunch of these. Eina_Hash *scripts; const char *address; int port; @@ -52,7 +51,6 @@ typedef struct _Lscript int logDom = -1; // Our logging domain. -static Eina_Strbuf *LuaSLStream; static int scriptCount = 0; static int compiledCount = 0; static struct timeval startTime; @@ -149,12 +147,14 @@ static void dirList_compile(const char *name, const char *path, void *data) } } + static Eina_Bool _addLuaSL(void *data, int type, Ecore_Con_Event_Server_Add *ev) { gameGlobals *ourGlobals = data; char buf[PATH_MAX]; - ourGlobals->serverLuaSL = ev->server; + PI("LuaSL server added, sending it scripts to compile and run."); + ourGlobals->serverLuaSL = ecore_con_server_data_get(ev->server); // Zero everything. eina_hash_free(ourGlobals->scripts); @@ -191,299 +191,277 @@ char *get_rawline(int fd, long *plen, char end) } -static Eina_Bool _dataLuaSL(void *data, int type, Ecore_Con_Event_Server_Data *ev) +static Eina_Bool LuaSLParser(void *data, Connection *conn, char *SID, char *command, char *arguments) { gameGlobals *ourGlobals = data; - char buf[PATH_MAX]; - char SID[PATH_MAX]; - const char *command; - char *ext; + LoveScript *me; - eina_strbuf_append_length(LuaSLStream, ev->data, ev->size); - command = eina_strbuf_string_get(LuaSLStream); - while ((ext = index(command, '\n'))) +PW("COMMAND - %s - %s", SID, command); + me = eina_hash_find(ourGlobals->scripts, SID); + if (0 == strncmp(command, "compilerWarning(", 16)) { - int length = ext - command; - - strncpy(SID, command, length + 1); - SID[length] = '\0'; - eina_strbuf_remove(LuaSLStream, 0, length + 1); - ext = index(SID, '.'); - if (ext) + char *temp; + char *line; + char *column; + char *text; + + strcpy(buf, &command[16]); + temp = buf; + line = temp; + while (',' != temp[0]) + temp++; + temp[0] = '\0'; + column = ++temp; + while (',' != temp[0]) + temp++; + temp[0] = '\0'; + text = ++temp; + while (')' != temp[0]) + temp++; + temp[0] = '\0'; + PW("%s @ line %s, column %s.", text, line, column); + if (me) + me->warnings++; + } + else if (0 == strncmp(command, "compilerError(", 14)) + { + char *temp; + char *line; + char *column; + char *text; + + strcpy(buf, &command[14]); + temp = buf; + line = temp; + while (',' != temp[0]) + temp++; + temp[0] = '\0'; + column = ++temp; + while (',' != temp[0]) + temp++; + temp[0] = '\0'; + text = ++temp; + while (')' != temp[0]) + temp++; + temp[0] = '\0'; + PE("%s @ line %s, column %s.", text, line, column); + if (me) + me->bugs++; + } + else if (0 == strcmp(command, "compiled(false)")) + { +// PE("The compile of %s failed!", SID); + if (me) { - LoveScript *me; + struct timeval now; - ext[0] = '\0'; - command = ext + 1; - me = eina_hash_find(ourGlobals->scripts, SID); - if (0 == strncmp(command, "compilerWarning(", 16)) + compiledCount++; + if (compiledCount == scriptCount) { - char *temp; - char *line; - char *column; - char *text; - - strcpy(buf, &command[16]); - temp = buf; - line = temp; - while (',' != temp[0]) - temp++; - temp[0] = '\0'; - column = ++temp; - while (',' != temp[0]) - temp++; - temp[0] = '\0'; - text = ++temp; - while (')' != temp[0]) - temp++; - temp[0] = '\0'; - PW("%s @ line %s, column %s.", text, line, column); - if (me) - me->warnings++; + float total = timeDiff(&now, &startTime); + PD("Compile speed scripts: %d time: %fs total: %f scripts per second", compiledCount, total, compiledCount / total); } - else if (0 == strncmp(command, "compilerError(", 14)) + } + } + else if (0 == strcmp(command, "compiled(true)")) + { + if (me) + { + struct timeval now; + + compiledCount++; + if (compiledCount == scriptCount) { - char *temp; - char *line; - char *column; - char *text; - - strcpy(buf, &command[14]); - temp = buf; - line = temp; - while (',' != temp[0]) - temp++; - temp[0] = '\0'; - column = ++temp; - while (',' != temp[0]) - temp++; - temp[0] = '\0'; - text = ++temp; - while (')' != temp[0]) - temp++; - temp[0] = '\0'; - PE("%s @ line %s, column %s.", text, line, column); - if (me) - me->bugs++; + float total = timeDiff(&now, &startTime); + PD("Compile speed scripts: %d time: %fs total: %f scripts per second", compiledCount, total, compiledCount / total); } - else if (0 == strcmp(command, "compiled(false)")) - { -// PE("The compile of %s failed!", SID); - if (me) - { - struct timeval now; + } + PD("About to run %s", me->fileName); + sendForth(ourGlobals->serverLuaSL, SID, "run(%s)", me->fileName); + } + else + { + // Send back some random or fixed values for testing. + if (0 == strcmp(command, "llGetKey()")) + sendForth(ourGlobals->serverLuaSL, SID, "return \"%08lx-%04lx-%04lx-%04lx-%012lx\"", random(), random() % 0xFFFF, random() % 0xFFFF, random() % 0xFFFF, random()); + else if (0 == strcmp(command, "llGetOwner()")) + sendForth(ourGlobals->serverLuaSL, SID, "return \"%s\"", ownerKey); + else if (0 == strcmp(command, "llGetPermissionsKey()")) + sendForth(ourGlobals->serverLuaSL, SID, "return \"%s\"", ownerKey); + else if (0 == strncmp(command, "llRequestPermissions(", 21)) + PI("Faked %s", command); + else if (0 == strcmp(command, "llGetPos()")) + sendForth(ourGlobals->serverLuaSL, SID, "return {x=128.0, y=128.0, z=128.0}"); + else if (0 == strcmp(command, "llGetRot()")) + sendForth(ourGlobals->serverLuaSL, SID, "return {x=0.0, y=0.0, z=0.0, s=1.0}"); + else if (0 == strcmp(command, "llGetFreeMemory()")) + sendForth(ourGlobals->serverLuaSL, SID, "return 654321"); + else if (0 == strcmp(command, "llGetObjectDesc()")) + sendForth(ourGlobals->serverLuaSL, SID, "return \"\""); + else if (0 == strncmp(command, "llGetAlpha(", 11)) + sendForth(ourGlobals->serverLuaSL, SID, "return 1.0"); + else if (0 == strcmp(command, "llGetInventoryNumber(7)")) + sendForth(ourGlobals->serverLuaSL, SID, "return 3"); + else if (0 == strcmp(command, "llGetLinkNumber()")) + sendForth(ourGlobals->serverLuaSL, SID, "return 1"); + else if (0 == strcmp(command, "llGetInventoryName(7, 2)")) + sendForth(ourGlobals->serverLuaSL, SID, "return \".readme\""); + else if (0 == strcmp(command, "llGetInventoryName(7, 1)")) + sendForth(ourGlobals->serverLuaSL, SID, "return \".POSITIONS\""); + else if (0 == strcmp(command, "llGetInventoryName(7, 0)")) + sendForth(ourGlobals->serverLuaSL, SID, "return \".MENUITEMS\""); + else if (0 == strncmp(command, "llListen(", 9)) + { + PI("Faked %s", command); + sendForth(ourGlobals->serverLuaSL, SID, "return %d", random()); + } + else if (0 == strncmp(command, "llSameGroup(", 12)) + sendForth(ourGlobals->serverLuaSL, SID, "return true"); + else if (0 == strncmp(command, "llKey2Name(", 11)) + { + char *temp; + + strcpy(buf, &command[12]); + temp = buf; + while (')' != temp[0]) + temp++; + temp[0] = '\0'; + if (0 == strcmp(buf, ownerKey)) + temp = ownerName; + else + temp = "Unknown User"; + // TODO - Sanitize the name, no telling what weird shit people put in their names. + snprintf(buf, sizeof(buf), "return \"%s\"", temp); + sendForth(ourGlobals->serverLuaSL, SID, buf); + } + // Send "back" stuff on to the one and only client. + // TODO - All of these output functions should just use one thing to append stuff to either local or an IM tab. + // Love filtering out stuff that should not go there. + // Extantz registering any channel it wants to listen to, mostly for client side scripts. + // Extantz is then only responsible for the registered channels, it can do what it likes with them. + // Dialogs, notifications, and other stuff goes through some other functions. + else if (0 == strncmp(command, "llOwnerSay(", 11)) + { + if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); + else PW("No where to send %s", command); + } + else if (0 == strncmp(command, "llWhisper(", 10)) + { + if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); + else PW("No where to send %s", command); + } + else if (0 == strncmp(command, "llRegionSay(", 12)) + { + if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); + else PW("No where to send %s", command); + } + else if (0 == strncmp(command, "llSay(", 6)) + { + if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); + else PW("No where to send %s", command); + } + else if (0 == strncmp(command, "llShout(", 8)) + { + if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); + else PW("No where to send %s", command); + // TODO - Temporary so we have a place to log stuff from LSL. + PD("SHOUTING %s", command); + } + else if (0 == strncmp(command, "llDialog(", 9)) + { + if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); + else PW("No where to send %s", command); + } + else if (0 == strncmp(command, "llMessageLinked(", 16)) + { + Eina_Iterator *scripts; + LoveScript *me; - compiledCount++; - if (compiledCount == scriptCount) - { - float total = timeDiff(&now, &startTime); - PD("Compile speed scripts: %d time: %fs total: %f scripts per second", compiledCount, total, compiledCount / total); - } - } - } - else if (0 == strcmp(command, "compiled(true)")) + // TODO - For now, just send it to everyone. + scripts = eina_hash_iterator_data_new(ourGlobals->scripts); + while(eina_iterator_next(scripts, (void **) &me)) { - if (me) - { - struct timeval now; - - compiledCount++; - if (compiledCount == scriptCount) - { - float total = timeDiff(&now, &startTime); - PD("Compile speed scripts: %d time: %fs total: %f scripts per second", compiledCount, total, compiledCount / total); - } - } - sendForth(ourGlobals->serverLuaSL, SID, "run(%s)", me->fileName); + sendForth(ourGlobals->serverLuaSL, me->SID, "events.link_message%s", &command[15]); } - else + eina_iterator_free(scripts); + } + else if (0 == strncmp(command, "llGetNotecardLine(", 18)) + { + char *notecard, *temp, *line, key[PATH_MAX]; + int lineNo, fd; + + strcpy(buf, &command[19]); + notecard = buf; + temp = notecard; + while ('"' != temp[0]) + temp++; + temp[0] = '\0'; + while (',' != temp[0]) + temp++; + while (' ' != temp[0]) + temp++; + line = temp; + while (')' != temp[0]) + temp++; + temp[0] = '\0'; + lineNo = atoi(line); + snprintf(key, sizeof(key), "%s/Test%%20sim/onefang%%27s%%20test%%20bed/%s", prefix_data_get(), notecard); + + fd = open(key, O_RDONLY); + if (-1 != fd) { - // Send back some random or fixed values for testing. - if (0 == strcmp(command, "llGetKey()")) - sendForth(ourGlobals->serverLuaSL, SID, "return \"%08lx-%04lx-%04lx-%04lx-%012lx\"", random(), random() % 0xFFFF, random() % 0xFFFF, random() % 0xFFFF, random()); - else if (0 == strcmp(command, "llGetOwner()")) - sendForth(ourGlobals->serverLuaSL, SID, "return \"%s\"", ownerKey); - else if (0 == strcmp(command, "llGetPermissionsKey()")) - sendForth(ourGlobals->serverLuaSL, SID, "return \"%s\"", ownerKey); - else if (0 == strncmp(command, "llRequestPermissions(", 21)) - PI("Faked %s", command); - else if (0 == strcmp(command, "llGetPos()")) - sendForth(ourGlobals->serverLuaSL, SID, "return {x=128.0, y=128.0, z=128.0}"); - else if (0 == strcmp(command, "llGetRot()")) - sendForth(ourGlobals->serverLuaSL, SID, "return {x=0.0, y=0.0, z=0.0, s=1.0}"); - else if (0 == strcmp(command, "llGetFreeMemory()")) - sendForth(ourGlobals->serverLuaSL, SID, "return 654321"); - else if (0 == strcmp(command, "llGetObjectDesc()")) - sendForth(ourGlobals->serverLuaSL, SID, "return \"\""); - else if (0 == strncmp(command, "llGetAlpha(", 11)) - sendForth(ourGlobals->serverLuaSL, SID, "return 1.0"); - else if (0 == strcmp(command, "llGetInventoryNumber(7)")) - sendForth(ourGlobals->serverLuaSL, SID, "return 3"); - else if (0 == strcmp(command, "llGetLinkNumber()")) - sendForth(ourGlobals->serverLuaSL, SID, "return 1"); - else if (0 == strcmp(command, "llGetInventoryName(7, 2)")) - sendForth(ourGlobals->serverLuaSL, SID, "return \".readme\""); - else if (0 == strcmp(command, "llGetInventoryName(7, 1)")) - sendForth(ourGlobals->serverLuaSL, SID, "return \".POSITIONS\""); - else if (0 == strcmp(command, "llGetInventoryName(7, 0)")) - sendForth(ourGlobals->serverLuaSL, SID, "return \".MENUITEMS\""); - else if (0 == strncmp(command, "llListen(", 9)) - { - PI("Faked %s", command); - sendForth(ourGlobals->serverLuaSL, SID, "return %d", random()); - } - else if (0 == strncmp(command, "llSameGroup(", 12)) - sendForth(ourGlobals->serverLuaSL, SID, "return true"); - else if (0 == strncmp(command, "llKey2Name(", 11)) - { - char *temp; - - strcpy(buf, &command[12]); - temp = buf; - while (')' != temp[0]) - temp++; - temp[0] = '\0'; - if (0 == strcmp(buf, ownerKey)) - temp = ownerName; - else - temp = "Unknown User"; - // TODO - Sanitize the name, no telling what weird shit people put in their names. - snprintf(buf, sizeof(buf), "return \"%s\"", temp); - sendForth(ourGlobals->serverLuaSL, SID, buf); - } - // Send "back" stuff on to the one and only client. - // TODO - All of these output functions should just use one thing to append stuff to either local or an IM tab. - // Love filtering out stuff that should not go there. - // Extantz registering any channel it wants to listen to, mostly for client side scripts. - // Extantz is then only responsible for the registered channels, it can do what it likes with them. - // Dialogs, notifications, and other stuff goes through some other functions. - else if (0 == strncmp(command, "llOwnerSay(", 11)) - { - if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); - else PW("No where to send %s", command); - } - else if (0 == strncmp(command, "llWhisper(", 10)) - { - if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); - else PW("No where to send %s", command); - } - else if (0 == strncmp(command, "llRegionSay(", 12)) - { - if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); - else PW("No where to send %s", command); - } - else if (0 == strncmp(command, "llSay(", 6)) - { - if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); - else PW("No where to send %s", command); - } - else if (0 == strncmp(command, "llShout(", 8)) - { - if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); - else PW("No where to send %s", command); - // TODO - Temporary so we have a place to log stuff from LSL. - PD("SHOUTING %s", command); - } - else if (0 == strncmp(command, "llDialog(", 9)) - { - if (ourGlobals->client) sendBack(ourGlobals->client, SID, command); - else PW("No where to send %s", command); - } - else if (0 == strncmp(command, "llMessageLinked(", 16)) - { - Eina_Iterator *scripts; - LoveScript *me; + Eina_Iterator *scripts; + LoveScript *me; + long len; - // TODO - For now, just send it to everyone. - scripts = eina_hash_iterator_data_new(ourGlobals->scripts); - while(eina_iterator_next(scripts, (void **) &me)) - { - sendForth(ourGlobals->serverLuaSL, me->SID, "events.link_message%s", &command[15]); - } - eina_iterator_free(scripts); - } - else if (0 == strncmp(command, "llGetNotecardLine(", 18)) + temp = NULL; + do { - char *notecard, *temp, *line, key[PATH_MAX]; - int lineNo, fd; - - strcpy(buf, &command[19]); - notecard = buf; - temp = notecard; - while ('"' != temp[0]) - temp++; - temp[0] = '\0'; - while (',' != temp[0]) - temp++; - while (' ' != temp[0]) - temp++; - line = temp; - while (')' != temp[0]) - temp++; - temp[0] = '\0'; - lineNo = atoi(line); - snprintf(key, sizeof(key), "%s/Test%%20sim/onefang%%27s%%20test%%20bed/%s", prefix_data_get(), notecard); - - fd = open(key, O_RDONLY); - if (-1 != fd) + free(temp); + temp = get_rawline(fd, &len, '\n'); + if (temp) { - Eina_Iterator *scripts; - LoveScript *me; - long len; + if (temp[len - 1] == '\n') + temp[--len] = '\0'; + } + } while (temp && (0 < lineNo--)); - temp = NULL; - do - { - free(temp); - temp = get_rawline(fd, &len, '\n'); - if (temp) - { - if (temp[len - 1] == '\n') - temp[--len] = '\0'; - } - } while (temp && (0 < lineNo--)); + sprintf(key, FAKE_UUID); + sendForth(ourGlobals->serverLuaSL, SID, "return \"%s\"", key); - sprintf(key, FAKE_UUID); - sendForth(ourGlobals->serverLuaSL, SID, "return \"%s\"", key); + // TODO - For now, just send it to everyone. + scripts = eina_hash_iterator_data_new(ourGlobals->scripts); + while(eina_iterator_next(scripts, (void **) &me)) + { + if (temp) + { + char buf2[PATH_MAX]; + int i, j, len = strlen(temp); - // TODO - For now, just send it to everyone. - scripts = eina_hash_iterator_data_new(ourGlobals->scripts); - while(eina_iterator_next(scripts, (void **) &me)) + // Escape ' and \ characters. + for (i = 0, j = 0; i <= len; i++) { - if (temp) - { - char buf2[PATH_MAX]; - int i, j, len = strlen(temp); - - // Escape ' and \ characters. - for (i = 0, j = 0; i <= len; i++) - { - if ('\'' == temp[i]) - buf2[j++] = '\\'; - if ('\\' == temp[i]) - buf2[j++] = '\\'; - buf2[j++] = temp[i]; - } - sendForth(ourGlobals->serverLuaSL, me->SID, "events.dataserver(\"%s\", '%s')", key, buf2); - } - else - sendForth(ourGlobals->serverLuaSL, me->SID, "events.dataserver(\"%s\", \"EndOfFuckingAround\")", key); + if ('\'' == temp[i]) + buf2[j++] = '\\'; + if ('\\' == temp[i]) + buf2[j++] = '\\'; + buf2[j++] = temp[i]; } - eina_iterator_free(scripts); - free(temp); - - close(fd); + sendForth(ourGlobals->serverLuaSL, me->SID, "events.dataserver(\"%s\", '%s')", key, buf2); } - + else + sendForth(ourGlobals->serverLuaSL, me->SID, "events.dataserver(\"%s\", \"EndOfFuckingAround\")", key); } - else - PI("Script %s sent command %s", SID, command); + eina_iterator_free(scripts); + free(temp); + + close(fd); } - } - // Get the next blob to check it. - command = eina_strbuf_string_get(LuaSLStream); + } + else + PI("Script %s sent command %s", SID, command); } return ECORE_CALLBACK_RENEW; @@ -492,26 +470,9 @@ static Eina_Bool _dataLuaSL(void *data, int type, Ecore_Con_Event_Server_Data *e static Eina_Bool _delLuaSL(void *data, int type, Ecore_Con_Event_Server_Del *ev) { gameGlobals *ourGlobals = data; - static int count = 0; ourGlobals->serverLuaSL = NULL; - // Let it fail a couple of times during startup, then try to start our own script server. - count++; - if (1 < count) - { - char buf[PATH_MAX]; - - PW("Failed to connect to a script server, starting our own."); - sprintf(buf, "%s/LuaSL &", prefix_bin_get()); - system(buf); - count = 0; - // TODO - There's also the question of what to do if the connection failed. - // Did the server crash, or was it just the connection? - // Probably gonna need some smarts, for now we just restart all the scripts. - // Which I think gets done on server add. - } - // TODO - May want to renew even if it's not running the GUI, but then we still need some sort of "shut down" signal, which we don't need during testing. // if (ourGlobals->ui) return ECORE_CALLBACK_RENEW; @@ -525,7 +486,7 @@ static Eina_Bool _addClient(void *data, int type, Ecore_Con_Event_Client_Add *ev { gameGlobals *ourGlobals = data; - ourGlobals->client = ev->client; + ourGlobals->client = ecore_con_client_data_get(ev->client); if (ourGlobals->client) { @@ -536,12 +497,11 @@ static Eina_Bool _addClient(void *data, int type, Ecore_Con_Event_Client_Add *ev return ECORE_CALLBACK_RENEW; } - -Eina_Bool clientParser(void *data, Connection *connection, char *SID, char *command, char *arguments) +static Eina_Bool clientParser(void *data, Connection *conn, char *SID, char *command, char *arguments) { gameGlobals *ourGlobals = data; - if (0 == strncmp(command, "events.touch_start", 18)) + if (0 == strncmp(command, "events.touch_start(", 19)) { Eina_Iterator *scripts; LoveScript *me; @@ -556,7 +516,7 @@ Eina_Bool clientParser(void *data, Connection *connection, char *SID, char *comm } eina_iterator_free(scripts); } - else if (0 == strncmp(command, "events.listen", 13)) + else if (0 == strncmp(command, "events.listen(", 14)) { Eina_Iterator *scripts; LoveScript *me; @@ -605,11 +565,6 @@ int main(int argc, char **argv) if (ecore_con_init()) { - LuaSLStream = eina_strbuf_new(); - reachOut("127.0.0.1", 8211, &ourGlobals, (Ecore_Event_Handler_Cb) _addLuaSL, (Ecore_Event_Handler_Cb) _dataLuaSL, (Ecore_Event_Handler_Cb) _delLuaSL); - - if (openArms("love", ourGlobals.address, ourGlobals.port + 1, &ourGlobals, (Ecore_Event_Handler_Cb) _addClient, NULL, (Ecore_Event_Handler_Cb) _delClient, clientParser)) - { if (ecore_evas_init()) { if (edje_init()) @@ -721,20 +676,30 @@ int main(int argc, char **argv) edje_object_signal_callback_add(ourGlobals.edje, "*", "game_*", _edje_signal_cb, &ourGlobals); } - ecore_main_loop_begin(); - PD("Fell out of the main loop"); + PD("About to try connecting to a LuaSL server."); + // Try to connect to a local LuaSL server. + reachOut("LuaSL", "./LuaSL", "127.0.0.1", ourGlobals.port, &ourGlobals, (Ecore_Event_Handler_Cb) _addLuaSL, /*(Ecore_Event_Handler_Cb) _dataLuaSL*/ NULL, (Ecore_Event_Handler_Cb) _delLuaSL, LuaSLParser); + + PD("Love is about to try creating a love server."); + if (openArms("love", ourGlobals.address, ourGlobals.port + 1, &ourGlobals, (Ecore_Event_Handler_Cb) _addClient, NULL, (Ecore_Event_Handler_Cb) _delClient, clientParser)) + { + ecore_main_loop_begin(); + PD("Fell out of the main loop"); - if (ourGlobals.server) ecore_con_server_del(ourGlobals.server); - if (ourGlobals.serverLuaSL) ecore_con_server_del(ourGlobals.serverLuaSL); +// if (ourGlobals.server) ecore_con_server_del(ourGlobals.server); +// if (ourGlobals.serverLuaSL) ecore_con_server_del(ourGlobals.serverLuaSL); + + } + else + PC("Failed to add server!"); if (ourGlobals.ui) { ecore_animator_del(ani); ecore_evas_free(ourGlobals.ee); } - } - edje_shutdown(); + } } else PC("Failed to init edje!"); @@ -743,10 +708,6 @@ int main(int argc, char **argv) else PC("Failed to init ecore_evas!"); - } - else - PC("Failed to add server!"); - ecore_con_shutdown(); } else diff --git a/src/purkle/purkle.c b/src/purkle/purkle.c index d00fd67..9a21700 100644 --- a/src/purkle/purkle.c +++ b/src/purkle/purkle.c @@ -49,17 +49,14 @@ static int say(lua_State *L) if (id && text) { GuiLua *gl; - Ecore_Con_Server *server = NULL; snprintf(buf, sizeof(buf), "events.listen(%d, '%s', '%s', '%s')", channel, name, id, text); // We do this rather than caching it, coz the server might change out from under us. lua_getfield(L, LUA_REGISTRYINDEX, glName); gl = lua_touserdata(L, -1); lua_pop(L, 1); - if (gl) - server = gl->server; - if (server) - sendForth(server, id, buf); + if (gl && gl->server) + sendForth(gl->server, id, buf); else PW("PURKLE NOT SAY, no where to send %s", buf); } -- cgit v1.1