462 lines
13 KiB
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);
|
|
}
|