542 lines
17 KiB
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;
|
|
}
|