marrakesh/mrklib_svc.c

542 lines
17 KiB
C

#include "mrklib_priv.h"
struct _Mrk
{
const char *host;
int port;
Ecore_Ipc_Server *server;
Eina_List *handlers;
FILE *f;
const char *file;
Eina_Bool query;
struct {
void (*connect) (void *data, Mrk *server);
void (*disconnect) (void *data, Mrk *server);
void (*upload_begin) (void *data, Mrk *server);
void (*upload_progress) (void *data, Mrk *server, double pos);
void (*upload_end) (void *data, Mrk *server);
void (*upload_success) (void *data, Mrk *server, Eina_Bool sucess);
void (*download_begin) (void *data, Mrk *server);
void (*download_progress) (void *data, Mrk *server, double pos);
void (*download_end) (void *data, Mrk *server);
void (*download_success) (void *data, Mrk *server, const char *file);
void (*answer_begin) (void *data, Mrk *server);
void (*answer_progress) (void *data, Mrk *server, const char *result);
void (*answer_end) (void *data, Mrk *server);
void (*getkey) (void *data, Mrk *server, const char *result);
} func;
struct {
void *connect;
void *disconnect;
void *upload_begin;
void *upload_progress;
void *upload_end;
void *upload_success;
void *download_begin;
void *download_progress;
void *download_end;
void *download_success;
void *answer_begin;
void *answer_progress;
void *answer_end;
void *getkey;
} data;
};
static void
_mrk_identify(Mrk *server)
{
char tmp[PATH_MAX];
// send client uuid - should be unique per client just to tell one
// apart from another - nothing more
ecore_ipc_server_send(server->server, M_OP, M_ID_UUID, 0, 0, 0,
_mrk_uuid, _mrk_uuid_len);
// send arch string - determined by compile time macros
snprintf(tmp, sizeof(tmp),
"%s-%s",
OS,
ARCH);
ecore_ipc_server_send(server->server, M_OP, M_ID_ARCH, 0, 0, 0,
tmp, strlen(tmp));
// send efl version - this is used by the server to filter results
// that are only relevent to you
snprintf(tmp, sizeof(tmp),
"%i.%i.%i",
eina_version->major,
eina_version->minor,
eina_version->micro);
ecore_ipc_server_send(server->server, M_OP, M_ID_VERSION, 0, 0, 0,
tmp, strlen(tmp));
}
static Eina_Bool
_mrk_upload(Mrk *server, const char *file)
{
FILE *f;
char buf[10000];
size_t size;
const char *fname;
if ((server->f) || (server->query)) return EINA_FALSE;
// XXX: adjust protocol so we get ack's for each buf
f = fopen(file, "rb");
if (!f) return EINA_FALSE;
server->f = f;
fname = ecore_file_file_get(file);
if (!fname) goto done;
ecore_ipc_server_send(server->server, M_OP, M_UP_START, 0, 0, 0,
fname, strlen(fname));
if (server->func.upload_begin)
server->func.upload_begin(server->data.upload_begin, server);
for (;;)
{
size = fread(buf, 1, 10000, f);
if (size > 0)
{
ecore_ipc_server_send(server->server, 10, M_UP_DATA, 0, 0, 0,
buf, size);
// XXX: calculate position 0.0 -> 1.0
if (server->func.upload_progress)
server->func.upload_progress(server->data.upload_progress, server, 0.5);
}
else break;
}
ecore_ipc_server_send(server->server, M_OP, M_UP_END, 0, 0, 0,
NULL, 0);
if (server->func.upload_end)
server->func.upload_end(server->data.upload_end, server);
done:
return EINA_TRUE;
}
static Eina_Bool
_mrk_upload_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
if (e->minor == M_UP_OK)
{
if (server->f) fclose(server->f);
server->f = NULL;
if (server->func.upload_success)
server->func.upload_success(server->data.upload_success, server, EINA_TRUE);
return EINA_TRUE;
}
else if (e->minor == M_UP_FAIL)
{
if (server->f) fclose(server->f);
server->f = NULL;
// XXX: e->data should contain some failure string/info
if (server->func.upload_success)
server->func.upload_success(server->data.upload_success, server, EINA_FALSE);
return EINA_TRUE;
}
// XXX: we should have some other status - eg unpack src worked,
// src sanity check passed, some build failed when/where or succeeded
// etc. etc.
return EINA_FALSE;
}
static Eina_Bool
_mrk_download(Mrk *server, const char *package)
{
if ((server->f) || (server->query)) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_QRY_GET, 0, 0, 0,
package, strlen(package));
return EINA_TRUE;
}
static Eina_Bool
_mrk_download_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
char *file = NULL;
if ((e->minor == M_DOWN_START) || (e->minor == M_SRC_START))
{
if ((e->size > 0) && (e->size <= 1000) && (e->data))
{
char *file = _mrk_util_proto_string(e);
if (file)
{
if (_mrk_util_plain_file_check(file))
{
FILE *f;
char tmp[PATH_MAX];
snprintf(tmp, sizeof(tmp), "%s/%s",
_mrk_appdir_tmp, file);
f = fopen(tmp, "wb");
if (!f) goto fail;
server->f = f;
server->file = eina_stringshare_add(tmp);
if (server->func.download_begin)
server->func.download_begin(server->data.download_begin, server);
}
else goto fail;
}
else goto fail;
}
else
{
fail:
if (server->func.download_success)
server->func.download_success(server->data.download_success, server, NULL);
}
free(file);
return EINA_TRUE;
}
else if ((e->minor == M_DOWN_DATA) || (e->minor == M_SRC_DATA))
{
double pos = 0.5;
if (e->ref_to > 0) pos = (double)e->ref / (double)e->ref_to;
if ((server->f) && (e->data) && (e->size > 0) && (e->size <= 10000))
{
fwrite(e->data, e->size, 1, server->f);
if (server->func.download_progress)
server->func.download_progress(server->data.download_progress, server, pos);
}
return EINA_TRUE;
}
else if ((e->minor == M_DOWN_END) || (e->minor == M_SRC_END))
{
const char *file = server->file;
server->file = NULL;
if (server->f) fclose(server->f);
server->f = NULL;
if (server->func.download_end)
server->func.download_end(server->data.download_end, server);
// XXX: check signature so we can verify dl is not broken and it's
// from a proper pkg server (signed by pkg server priv key, check
// with pub key
if (server->func.download_success)
server->func.download_success(server->data.download_success, server, file);
eina_stringshare_del(file);
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_download_src(Mrk *server, const char *package)
{
if ((server->f) || (server->query)) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_QRY_GETSRC, 0, 0, 0,
package, strlen(package));
return EINA_TRUE;
}
static Eina_Bool
_mrk_download_src_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
return _mrk_download_data(server, e);
}
static Eina_Bool
_mrk_query_list(Mrk *server, const char *category)
{
if ((server->f) || (server->query)) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_QRY_LIST, 0, 0, 0,
category, category ? strlen(category) : 0);
return EINA_TRUE;
}
static Eina_Bool
_mrk_query_search(Mrk *server, const char *keywords)
{
if ((server->f) || (server->query)) return EINA_FALSE;
if (!keywords) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_QRY_SEARCH, 0, 0, 0,
keywords, strlen(keywords));
return EINA_TRUE;
}
static Eina_Bool
_mrk_query_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
if (e->minor == M_ANS_START)
{
if (server->func.answer_begin)
server->func.answer_begin(server->data.answer_begin, server);
return EINA_TRUE;
}
else if (e->minor == M_ANS_DATA)
{
if ((e->data) && (e->size > 0) && (e->size <= 10000))
{
char *str = _mrk_util_proto_string(e);
if (str)
{
if (server->func.answer_progress)
server->func.answer_progress(server->data.answer_progress, server, str);
free(str);
}
}
return EINA_TRUE;
}
else if (e->minor == M_ANS_END)
{
server->query = EINA_FALSE;
if (server->func.answer_end)
server->func.answer_end(server->data.answer_end, server);
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_getkey(Mrk *server)
{
if (server->f) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_GETKEY_REQ, 0, 0, 0, NULL, 0);
return EINA_TRUE;
}
static Eina_Bool
_mrk_getkey_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
if (e->minor == M_GETKEY_ANS)
{
if ((e->data) && (e->size > 0) && (e->size <= 100000))
{
char *str = _mrk_util_proto_string(e);
if (str)
{
if (server->func.getkey)
server->func.getkey(server->data.getkey, server, str);
free(str);
}
}
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_data_handle(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
if ((e->minor > M_UP_B) && (e->minor < M_UP_E))
return _mrk_upload_data(server, e);
else if ((e->minor > M_DOWN_B) && (e->minor < M_DOWN_E))
return _mrk_download_data(server, e);
else if ((e->minor > M_SRC_B) && (e->minor < M_SRC_E))
return _mrk_download_src_data(server, e);
else if ((e->minor > M_ANS_B) && (e->minor < M_ANS_E))
return _mrk_query_data(server, e);
else if ((e->minor > M_GETKEY_B) && (e->minor < M_GETKEY_E))
return _mrk_getkey_data(server, e);
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_add(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Ipc_Event_Server_Add *e = event;
Mrk *server = data;
if (server->server != e->server) return EINA_TRUE;
if (server->func.connect)
server->func.connect(server->data.connect, server);
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_del(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Ipc_Event_Server_Del *e = event;
Mrk *server = data;
if (server->server != e->server) return EINA_TRUE;
if (server->func.disconnect)
server->func.disconnect(server->data.disconnect, server);
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_data(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Ipc_Event_Server_Data *e = event;
Mrk *server = data;
if (server->server != e->server) return EINA_TRUE;
if (e->major != M_OP) return EINA_TRUE;
if (!_mrk_data_handle(server, e)) return EINA_TRUE;
return EINA_FALSE;
}
EAPI Mrk *
mrk_connect(const char *host, int port)
{
Mrk *server;
if (!host) host = _mrk_server_host;
if (port <= 0) port = _mrk_server_port;
server = calloc(1, sizeof(Mrk));
if (!server) return NULL;
server->host = eina_stringshare_add(host);
server->port = port;
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_SERVER_ADD,
_mrk_cb_add, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_SERVER_DEL,
_mrk_cb_del, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_SERVER_DATA,
_mrk_cb_data, server));
server->server = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM,
(char *)server->host,
server->port,
server);
_mrk_identify(server);
return server;
}
EAPI void
mrk_disconnect(Mrk *server)
{
Ecore_Event_Handler *hnd;
if (!server) return;
ecore_ipc_server_del(server->server);
EINA_LIST_FREE(server->handlers, hnd) ecore_event_handler_del(hnd);
eina_stringshare_del(server->host);
if (server->f)
{
fclose(server->f);
if (server->file) ecore_file_unlink(server->file);
}
eina_stringshare_del(server->file);
free(server);
}
EAPI Eina_Bool
mrk_upload(Mrk *server, const char *file)
{
return _mrk_upload(server, file);
}
EAPI Eina_Bool
mrk_download(Mrk *server, const char *package)
{
return _mrk_download(server, package);
}
EAPI Eina_Bool
mrk_download_source(Mrk *server, const char *package)
{
return _mrk_download_src(server, package);
}
EAPI Eina_Bool
mrk_list(Mrk *server, const char *category)
{
return _mrk_query_list(server, category);
}
EAPI Eina_Bool
mrk_search(Mrk *server, const char *keys)
{
return _mrk_query_search(server, keys);
}
EAPI Eina_Bool
mrk_getkey(Mrk *server)
{
return _mrk_getkey(server);
}
EAPI void
mrk_callback_connect_set(Mrk *server,
void (*connect) (void *data, Mrk *server),
void *connect_data,
void (*disconnect) (void *data, Mrk *server),
void *disconnect_data)
{
server->func.connect = connect;
server->data.connect = connect_data;
server->func.disconnect = disconnect;
server->data.disconnect = disconnect_data;
}
EAPI void
mrk_callback_upload_set(Mrk *server,
void (*upload_begin) (void *data, Mrk *server),
void *upload_begin_data,
void (*upload_progress) (void *data, Mrk *server, double pos),
void *upload_progress_data,
void (*upload_end) (void *data, Mrk *server),
void *upload_end_data,
void (*upload_success) (void *data, Mrk *server, Eina_Bool sucess),
void *upload_success_data)
{
server->func.upload_begin = upload_begin;
server->data.upload_begin = upload_begin_data;
server->func.upload_progress = upload_progress;
server->data.upload_progress = upload_progress_data;
server->func.upload_end = upload_end;
server->data.upload_end = upload_end_data;
server->func.upload_success = upload_success;
server->data.upload_success = upload_success_data;
}
EAPI void
mrk_callback_download_set(Mrk *server,
void (*download_begin) (void *data, Mrk *server),
void *download_begin_data,
void (*download_progress) (void *data, Mrk *server, double pos),
void *download_progress_data,
void (*download_end) (void *data, Mrk *server),
void *download_end_data,
void (*download_success) (void *data, Mrk *server, const char *file),
void *download_success_data)
{
server->func.download_begin = download_begin;
server->data.download_begin = download_begin_data;
server->func.download_progress = download_progress;
server->data.download_progress = download_progress_data;
server->func.download_end = download_end;
server->data.download_end = download_end_data;
server->func.download_success = download_success;
server->data.download_success = download_success_data;
}
EAPI void
mrk_callback_answer_set(Mrk *server,
void (*answer_begin) (void *data, Mrk *server),
void *answer_begin_data,
void (*answer_progress) (void *data, Mrk *server, const char *result),
void *answer_progress_data,
void (*answer_end) (void *data, Mrk *server),
void *answer_end_data)
{
server->func.answer_begin = answer_begin;
server->data.answer_begin = answer_begin_data;
server->func.answer_progress = answer_progress;
server->data.answer_progress = answer_progress_data;
server->func.answer_end = answer_end;
server->data.answer_end = answer_end_data;
}
EAPI void
mrk_callback_getkey_set(Mrk *server,
void (*getkey) (void *data, Mrk *server, const char *keydata),
void *getkey_data)
{
server->func.getkey = getkey;
server->data.getkey = getkey_data;
}