marrakesh/mrklib_serv.c

462 lines
13 KiB
C

#include "mrklib_priv.h"
struct _Mrk_Serve
{
const char *listen;
int port;
const char *repodir;
const char *bldsh;
Ecore_Ipc_Server *server;
Eina_List *handlers;
Eina_Inlist *clients;
Mrk_Repodb *rdb;
};
typedef struct
{
EINA_INLIST;
Mrk_Serve *server;
Ecore_Ipc_Client *client;
const char *uuid;
const char *arch;
const char *version;
const char *file;
const char *dir;
FILE *f;
Ecore_Exe *exe;
} Client;
static void
client_upload_cancel(Client *c)
{
if (c->f) fclose(c->f);
if (c->file) eina_stringshare_del(c->file);
if (c->dir)
{
ecore_file_recursive_rm(c->dir);
eina_stringshare_del(c->dir);
}
c->f = NULL;
c->file = NULL;
c->dir = NULL;
}
static void
client_upload_new(Client *c, const char *file)
{
char tmp[PATH_MAX];
Eina_Tmpstr *s = NULL;
if (c->f) client_upload_cancel(c);
c->file = eina_stringshare_add(file);
if (!c->file) return;
if (eina_file_mkdtemp("marrekesh-up-XXXXXX", &s))
{
c->dir = eina_stringshare_add(s);
eina_tmpstr_del(s);
if (c->dir)
{
snprintf(tmp, sizeof(tmp), "%s/%s", c->dir, c->file);
c->f = fopen(tmp, "wb");
}
}
}
static void
client_upload_data(Client *c, void *data, int size)
{
if (c->f) fwrite(data, size, 1, c->f);
}
static void
client_upload_end(Client *c)
{
char tmp[PATH_MAX];
if (c->f)
{
fclose(c->f);
c->f = NULL;
snprintf(tmp, sizeof(tmp), "%s %s %s",
c->server->bldsh, c->dir, c->server->repodir);
c->exe = ecore_exe_pipe_run(tmp,
ECORE_EXE_TERM_WITH_PARENT |
ECORE_EXE_NOT_LEADER, c);
if (c->exe) ecore_exe_tag_set(c->exe, "-=# mrk serve - build exe #=-");
}
}
static void
client_send(Client *c, const char *subrepo, const char *name, int op_start, int op_data, int op_end)
{
char tmp[PATH_MAX];
char *lnk;
snprintf(tmp, sizeof(tmp), "%s/%s/%s", c->server->repodir, subrepo, name);
lnk = ecore_file_readlink(tmp);
if (!lnk)
ecore_ipc_client_send(c->client, M_OP, op_start, 0, 0, 0,
NULL, 0);
else
{
FILE *f = fopen(tmp, "rb");
if (!f)
ecore_ipc_client_send(c->client, M_OP, op_start, 0, 0, 0,
NULL, 0);
else
{
long sz, pos;
fseek(f, 0, SEEK_END);
sz = ftell(f);
fseek(f, 0, SEEK_SET);
ecore_ipc_client_send(c->client, M_OP, op_start, (int)sz, 0, 0,
lnk, strlen(lnk));
for (pos = 0; pos < sz;)
{
size_t size;
char buf[10000];
size = fread(buf, 1, 10000, f);
if (size <= 0) break;
pos += size;
ecore_ipc_client_send(c->client, M_OP, op_data,
(int)pos, (int)sz, 0,
buf, size);
}
ecore_ipc_client_send(c->client, M_OP, op_end, 0, 0, 0,
NULL, 0);
fclose(f);
}
free(lnk);
}
}
static Eina_Bool
_mrk_id_data(Mrk_Serve *server EINA_UNUSED, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if (e->minor == M_ID_UUID)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
eina_stringshare_replace(&(c->uuid), str);
free(str);
}
return EINA_TRUE;
}
else if (e->minor == M_ID_VERSION)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
eina_stringshare_replace(&(c->version), str);
free(str);
}
return EINA_TRUE;
}
else if (e->minor == M_ID_ARCH)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_arch_ok(str))
eina_stringshare_replace(&(c->arch), str);
free(str);
}
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_upload_data(Mrk_Serve *server EINA_UNUSED, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if ((!c->uuid) || (!c->version) || (!c->arch)) return EINA_FALSE;
if (e->minor == M_UP_START)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_plain_file_check(str))
client_upload_new(c, str);
free(str);
}
return EINA_TRUE;
}
else if (e->minor == M_UP_DATA)
{
if ((e->data) && (e->size <= 10000))
client_upload_data(c, e->data, e->size);
return EINA_TRUE;
}
else if (e->minor == M_UP_END)
{
client_upload_end(c);
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_query_data(Mrk_Serve *server EINA_UNUSED, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if ((!c->uuid) || (!c->version) || (!c->arch)) return EINA_FALSE;
if (e->minor == M_QRY_LIST)
{
const Eina_List *list = NULL, *l;
ecore_ipc_client_send(c->client, M_OP, M_ANS_START, 0, 0, 0, NULL, 0);
if (!e->data) list = mrk_repodb_category_list(c->server->rdb,
c->arch, NULL);
else
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
list = mrk_repodb_category_list(c->server->rdb,
c->arch, str);
free(str);
}
}
if (list)
{
const char *s;
EINA_LIST_FOREACH(list, l, s)
{
ecore_ipc_client_send(c->client, M_OP, M_ANS_DATA,
0, 0, 0,
s, strlen(s));
}
}
ecore_ipc_client_send(c->client, M_OP, M_ANS_END, 0, 0, 0, NULL, 0);
return EINA_TRUE;
}
else if (e->minor == M_QRY_SEARCH)
{
ecore_ipc_client_send(c->client, M_OP, M_ANS_START, 0, 0, 0, NULL, 0);
if (e->data)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
Eina_List *list;
const char *s;
list = mrk_repodb_search(c->server->rdb, c->arch, str);
EINA_LIST_FREE(list, s)
{
ecore_ipc_client_send(c->client, M_OP, M_ANS_DATA,
0, 0, 0,
s, strlen(s));
eina_stringshare_del(s);
}
free(str);
}
}
ecore_ipc_client_send(c->client, M_OP, M_ANS_END, 0, 0, 0, NULL, 0);
return EINA_TRUE;
}
else if (e->minor == M_QRY_GET)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_plain_file_check(str))
client_send(c, c->arch, str,
M_DOWN_START, M_DOWN_DATA, M_DOWN_END);
free(str);
}
return EINA_TRUE;
}
else if (e->minor == M_QRY_GETSRC)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_plain_file_check(str))
client_send(c, "src", str,
M_SRC_START, M_SRC_DATA, M_SRC_END);
free(str);
}
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_inf_data(Mrk_Serve *server EINA_UNUSED, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if ((!c->uuid) || (!c->version) || (!c->arch)) return EINA_FALSE;
if (e->minor == M_INF_GET_IC)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_plain_file_check(str))
{
char *str2 = malloc(strlen(str) + 1 + 8);
if (str2)
{
strcpy(str2, str);
strcat(str2, ".icn.png");
client_send(c, "src", str2,
M_INF_START, M_INF_DATA, M_INF_END);
free(str2);
}
}
free(str);
}
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_data_handle(Mrk_Serve *server, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if ((e->minor > M_UP_B) && (e->minor < M_UP_E))
return _mrk_upload_data(server, c, e);
else if ((e->minor > M_QRY_B) && (e->minor < M_QRY_E))
return _mrk_query_data(server, c, e);
else if ((e->minor > M_ID_B) && (e->minor < M_ID_E))
return _mrk_id_data(server, c, e);
else if ((e->minor > M_INF_B) && (e->minor < M_INF_E))
return _mrk_inf_data(server, c, e);
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_add(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Ipc_Event_Client_Add *e = event;
Mrk_Serve *server = data;
Client *c;
if (server->server != ecore_ipc_client_server_get(e->client)) return EINA_TRUE;
c = calloc(1, sizeof(Client));
c->server = server;
c->client = e->client;
ecore_ipc_client_data_set(e->client, c);
server->clients = eina_inlist_append(server->clients, EINA_INLIST_GET(c));
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_del(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Ipc_Event_Client_Del *e = event;
Mrk_Serve *server = data;
Client *c;
if (server->server != ecore_ipc_client_server_get(e->client)) return EINA_TRUE;
c = ecore_ipc_client_data_get(e->client);
if (c)
{
client_upload_cancel(c);
eina_stringshare_del(c->uuid);
eina_stringshare_del(c->arch);
eina_stringshare_del(c->version);
if (c->exe) ecore_exe_free(c->exe);
server->clients = eina_inlist_remove(server->clients,
EINA_INLIST_GET(c));
free(c);
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_data(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Ipc_Event_Client_Data *e = event;
Mrk_Serve *server = data;
Client *c;
if (server->server != ecore_ipc_client_server_get(e->client)) return EINA_TRUE;
c = ecore_ipc_client_data_get(e->client);
if (!c) return EINA_TRUE;
if (e->major != M_OP) return EINA_TRUE;
if (!_mrk_data_handle(server, c, e)) return EINA_TRUE;
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_exe_del(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Exe_Event_Del *e = event;
Mrk_Serve *server = data;
Client *c;
const char *tag;
if (!e->exe) return EINA_TRUE;
tag = ecore_exe_tag_get(e->exe);
if (!tag) return EINA_TRUE;
if (!strcmp(tag, "-=# mrk serve - build exe #=-"))
{
c = ecore_exe_data_get(e->exe);
if (!c) return EINA_TRUE;
if (c->exe != e->exe) return EINA_TRUE;
c->exe = NULL;
if (e->exit_code == 0)
{
ecore_ipc_client_send(c->client, M_OP, M_UP_OK, 0, 0, 0, NULL, 0);
mrk_repodb_update(server->rdb);
}
else
ecore_ipc_client_send(c->client, M_OP, M_UP_FAIL, 0, 0, 0, NULL, 0);
return EINA_FALSE;
}
return EINA_TRUE;
}
EAPI Mrk_Serve *
mrk_serve(const char *listen, int port, const char *repodir, const char *bldsh)
{
Mrk_Serve *server;
server = calloc(1, sizeof(Mrk_Serve));
if (!server) return server;
if (!listen) listen = "0.0.0.0";
if (port <= 0) port = MRK_SERVER_PORT;
server->listen = eina_stringshare_add(listen);
server->port = port;
server->repodir = eina_stringshare_add(repodir);
server->bldsh = eina_stringshare_add(bldsh);
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_CLIENT_ADD,
_mrk_cb_add, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_CLIENT_DEL,
_mrk_cb_del, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_CLIENT_DATA,
_mrk_cb_data, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_EXE_EVENT_DEL,
_mrk_cb_exe_del, server));
server->server = ecore_ipc_server_add(ECORE_IPC_REMOTE_SYSTEM,
server->listen, server->port, server);
server->rdb = mrk_repodb_load(repodir);
return server;
}
EAPI void
mrk_unserve(Mrk_Serve *server)
{
Ecore_Event_Handler *hnd;
mrk_repodb_free(server->rdb);
ecore_ipc_server_del(server->server);
EINA_LIST_FREE(server->handlers, hnd) ecore_event_handler_del(hnd);
eina_stringshare_del(server->listen);
eina_stringshare_del(server->repodir);
eina_stringshare_del(server->bldsh);
if (!server) return;
free(server);
}