242 lines
5.7 KiB
C
242 lines
5.7 KiB
C
#include "private.h"
|
|
|
|
/* local variables */
|
|
static int_least8_t _init_count = 0;
|
|
|
|
/* external variables */
|
|
int _exp_log_dom = -1;
|
|
Eina_Hash *_networks = NULL;
|
|
|
|
static void
|
|
_cb_networks_free(void *data)
|
|
{
|
|
Express_Network *net;
|
|
|
|
if (!(net = data)) return;
|
|
|
|
if (net->servers) eina_hash_free(net->servers);
|
|
net->servers = NULL;
|
|
|
|
if (net->name) eina_stringshare_del(net->name);
|
|
if (net->user) eina_stringshare_del(net->user);
|
|
if (net->nick) eina_stringshare_del(net->nick);
|
|
if (net->nick_pass) eina_stringshare_del(net->nick_pass);
|
|
if (net->server_pass) eina_stringshare_del(net->server_pass);
|
|
|
|
free(net);
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_server_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
|
{
|
|
Ecore_Con_Event_Server_Add *ev;
|
|
Express_Network *net;
|
|
const char *server;
|
|
|
|
ev = event;
|
|
if (!(net = ecore_con_server_data_get(ev->server)))
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
server = ecore_con_server_name_get(ev->server);
|
|
DBG("Server Added %s %s", net->name, server);
|
|
|
|
net->connecting = EINA_FALSE;
|
|
net->connected = ecore_con_server_connected_get(ev->server);
|
|
|
|
if (net->connected)
|
|
{
|
|
if (net->callbacks.connect)
|
|
(*net->callbacks.connect)(net, "CONNECT", server, NULL, 0,
|
|
net->callbacks.data);
|
|
|
|
/* NB: RFC says send Pass, Nick, User to register */
|
|
/* express_network_server_password_send(net); */
|
|
/* express_network_nick_password_send(net); */
|
|
/* express_network_nickname_send(net); */
|
|
/* express_network_username_send(net); */
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
|
{
|
|
Ecore_Con_Event_Server_Del *ev;
|
|
Express_Network *net;
|
|
|
|
ev = event;
|
|
if (!(net = ecore_con_server_data_get(ev->server)))
|
|
return ECORE_CALLBACK_RENEW;
|
|
DBG("Server Del Message: %s %s",
|
|
net->name, ecore_con_server_name_get(net->conn));
|
|
|
|
net->connected = EINA_FALSE;
|
|
if ((net->connecting) && (net->autoconnect))
|
|
{
|
|
Express_Server *srv;
|
|
const char *server_name;
|
|
|
|
/* get name of failed server */
|
|
server_name = ecore_con_server_name_get(ev->server);
|
|
|
|
DBG("Connection to %s Failed", server_name);
|
|
|
|
/* delete existing connection */
|
|
if (net->conn) ecore_con_server_del(net->conn);
|
|
net->conn = NULL;
|
|
|
|
/* find this server in the network list */
|
|
if ((srv = express_network_server_find(net, server_name)))
|
|
srv->skip = EINA_TRUE;
|
|
|
|
/* try the next server
|
|
* NB: This function will iterate existing servers and ignore
|
|
* any with the 'skip' flag set */
|
|
express_network_connect(net);
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static int
|
|
_find_crlf(const char *data, const int len)
|
|
{
|
|
int o = 0;
|
|
|
|
for (; o < len; o++)
|
|
{
|
|
if ((data[o] == 0x0D) && (o < len - 1) && (data[o + 1] == 0x0A))
|
|
return o;
|
|
if (data[o] == 0x0A) return o;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_find_crlf_offset(const char *data, int offset, const int len)
|
|
{
|
|
for (; offset < len; offset++)
|
|
{
|
|
if ((data[offset] != 0x0D) && (data[offset] != 0x0A))
|
|
break;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
|
{
|
|
Ecore_Con_Event_Server_Data *ev;
|
|
Express_Network *net;
|
|
int offset = 0;
|
|
char *msg;
|
|
|
|
// max 512 len per line (510 without \r\n)
|
|
|
|
ev = event;
|
|
if (ev->size <= 0) return ECORE_CALLBACK_RENEW;
|
|
|
|
if (!(net = ecore_con_server_data_get(ev->server)))
|
|
return ECORE_CALLBACK_RENEW;
|
|
if (!net->connected) return ECORE_CALLBACK_RENEW;
|
|
|
|
DBG("Server Data Message: %s %s %d",
|
|
net->name, ecore_con_server_name_get(net->conn), ev->size);
|
|
DBG("%s", (char *)ev->data);
|
|
|
|
msg = calloc((ev->size + 1), sizeof(char));
|
|
strncpy(msg, ev->data, ev->size);
|
|
|
|
net->offset = ev->size;
|
|
// net->offset += ev->size;
|
|
|
|
while ((offset = _find_crlf(msg, net->offset)) > 0)
|
|
{
|
|
_express_network_data_process(net, msg, offset);
|
|
|
|
offset = _find_crlf_offset(msg, offset, net->offset);
|
|
|
|
if ((net->offset - offset) > 0)
|
|
memmove(msg, msg + offset, net->offset - offset);
|
|
|
|
net->offset -= offset;
|
|
}
|
|
|
|
net->offset = 0;
|
|
free(msg);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
/* public functions */
|
|
EXAPI int
|
|
express_init(void)
|
|
{
|
|
if (++_init_count != 1) return _init_count;
|
|
|
|
if (!eina_init()) return --_init_count;
|
|
|
|
_exp_log_dom =
|
|
eina_log_domain_register("libexpress", EXP_DEFAULT_LOG_COLOR);
|
|
if (_exp_log_dom < 0)
|
|
{
|
|
EINA_LOG_ERR("Could not create a log domain for Express library");
|
|
goto log_err;
|
|
}
|
|
|
|
if (!ecore_init())
|
|
{
|
|
ERR("Could not initialize Ecore");
|
|
goto ecore_err;
|
|
}
|
|
|
|
if (!ecore_con_init())
|
|
{
|
|
ERR("Could not initialize Ecore_Con");
|
|
goto conn_err;
|
|
}
|
|
|
|
_networks = eina_hash_string_small_new(_cb_networks_free);
|
|
|
|
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD,
|
|
_cb_server_add, NULL);
|
|
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL,
|
|
_cb_server_del, NULL);
|
|
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
|
|
_cb_server_data, NULL);
|
|
|
|
return _init_count;
|
|
|
|
conn_err:
|
|
ecore_shutdown();
|
|
ecore_err:
|
|
eina_log_domain_unregister(_exp_log_dom);
|
|
_exp_log_dom = -1;
|
|
log_err:
|
|
eina_shutdown();
|
|
return --_init_count;
|
|
}
|
|
|
|
EXAPI int
|
|
express_shutdown(void)
|
|
{
|
|
if (--_init_count != 0) return _init_count;
|
|
|
|
if (_networks) eina_hash_free(_networks);
|
|
_networks = NULL;
|
|
|
|
ecore_con_shutdown();
|
|
|
|
ecore_shutdown();
|
|
|
|
eina_log_domain_unregister(_exp_log_dom);
|
|
_exp_log_dom = -1;
|
|
|
|
eina_shutdown();
|
|
|
|
return _init_count;
|
|
}
|