express/src/lib/main.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;
}