diff options
Diffstat (limited to 'ircxmpp.c')
-rw-r--r-- | ircxmpp.c | 88 |
1 files changed, 61 insertions, 27 deletions
@@ -63,13 +63,13 @@ static void free_bridge (struct bridge * bridge, const char * razlog) { LOG(bridge->ircxmpp, IRCXMPP_DEBUG, "freeing bridge with reason: %s", razlog); if (bridge->irc) { irc_cmd_quit(bridge->irc, razlog); - if (strcmp(razlog, "free_bridge_from_tdestroy")) + if (strcmp(razlog, "free_bridge_from_tdestroy")) // če nismo iz tdestroy irc_run_once(bridge); // verjetno je to potrebno, da pošlje quit irc_destroy_session(bridge->irc); } if (bridge->conn) xmpp_conn_release(bridge->conn); // graceful disconnect, what is that? - if (strcmp(razlog, "free_bridge_from_tdestroy")) + if (strcmp(razlog, "free_bridge_from_tdestroy")) // če nismo iz tdestroy tdelete(bridge, &bridge->ircxmpp->bridges, bridge_compare); free(bridge->identifier); for (size_t i = 0; i < bridge->messages_length; i++) @@ -133,6 +133,10 @@ static void bridge_forward (const char * f, const char * m, struct ircxmpp * irc m ? m : "[join only]"); if (!bridge) { bridge = calloc(1, sizeof(struct bridge)); + if (!bridge) { + return; + LOG(ircxmpp, IRCXMPP_ERROR, "calloc bridge failed"); + } bridge->identifier = strdup(f); bridge->ircxmpp = ircxmpp; bridge->side = !s; @@ -181,8 +185,12 @@ static void bridge_forward (const char * f, const char * m, struct ircxmpp * irc } irc_run_once(bridge); } else if (m) { - bridge->messages = realloc(bridge->messages, - sizeof(*bridge->messages) * (bridge->messages_length+1)); + typeof(bridge->messages) new = reallocarray(bridge->messages, bridge->messages_length+1, sizeof(*bridge->messages)); + if (!new) { + LOG(ircxmpp, IRCXMPP_ERROR, "reallocarray(bridge->messages, bridge->messages_length+1 = %z, sizeof(*bridge->messages) = %z) failed", bridge->messages_length+1, sizeof*(bridge->messages)); + return; + } + bridge->messages = new; bridge->messages[bridge->messages_length++] = strdup(m); } } /* m can be NULL, in that case we only join. */ @@ -272,8 +280,7 @@ static void conn_handler_bridge (xmpp_conn_t * const conn __attribute__((unused) xmpp_send(bridge->conn, pres); xmpp_stanza_release(pres); } else - LOG(bridge->ircxmpp, IRCXMPP_WARN, "control disconnected from XMPP."); - + LOG(bridge->ircxmpp, IRCXMPP_WARN, "bridge disconnected from XMPP."); } /* IRC */ @@ -395,12 +402,12 @@ static void event_nick_control ( } static void event_topic_control ( irc_session_t * s, const char * e, const char * o, const char ** p, unsigned c) { - dump_event_control(s, e, o, p, c); /* o je avtor, p[0] je kanal, p[1] je nova tema/zadeva */ + dump_event_control(s, e, o, p, c); // o avtor, p[0] kanal, p[1] je nova tema struct ircxmpp * ircxmpp = (struct ircxmpp *) irc_get_ctx(s); char buf[1024]; snprintf(buf, 1024, "/me je nastavil IRC temo na: %s", p[1]); bridge_forward(o, buf, ircxmpp, XMPP); -} /* TODO */ +} static void event_numeric ( irc_session_t * s, unsigned int e, const char * o, const char ** p, unsigned c) { char b[512]; @@ -693,10 +700,13 @@ void ircxmpp_set_domain (struct ircxmpp * ircxmpp, const char * domain) { ircxmpp->domain = strdup(domain); // this intentionally crashes } static void obdelaj_bridge (const void * nodep, VISIT which __attribute__((unused)), - int depth __attribute__((unused))) { + int depth __attribute__((unused))) { // to be called only from twalk struct bridge * bridge = *(struct bridge **) nodep; if (bridge->irc && irc_run_once(bridge)) { - free_bridge(bridge, "irc connection dropped"); + MR(bridge->ircxmpp->to_free_bridges); + MR(bridge->ircxmpp->to_free_reasons); + bridge->ircxmpp->to_free_bridges[bridge->ircxmpp->to_free_bridges_length++] = bridge; + bridge->ircxmpp->to_free_reasons[bridge->ircxmpp->to_free_reasons_length++] = "irc connection dropped"; return; } if (bridge->conn && !xmpp_conn_is_connected(bridge->conn) @@ -704,8 +714,12 @@ static void obdelaj_bridge (const void * nodep, VISIT which __attribute__((unuse if (bridge->side == IRC && bridge->messages_length) { LOG(bridge->ircxmpp, IRCXMPP_WARN, "RECONNECTING dead BRIDGE with msgs!"); xmpp_connect_client(bridge->conn, NULL, 0, conn_handler_bridge, bridge); - } else - free_bridge(bridge, "xmpp connection dropped"); + } else { + MR(bridge->ircxmpp->to_free_bridges); + MR(bridge->ircxmpp->to_free_reasons); + bridge->ircxmpp->to_free_bridges[bridge->ircxmpp->to_free_bridges_length++] = bridge; + bridge->ircxmpp->to_free_reasons[bridge->ircxmpp->to_free_reasons_length++] = "xmpp connection dropped"; + } return; } const char * jid = NULL; @@ -737,9 +751,9 @@ void ircxmpp_run_once (struct ircxmpp * ircxmpp) { if (!ircxmpp->ctx || !ircxmpp->conn || (!xmpp_conn_is_connected(ircxmpp->conn) && !xmpp_conn_is_connecting(ircxmpp->conn))) { LOG(ircxmpp, IRCXMPP_WARN, "XMPP control is DISCONNECTED! CONNECTING!"); - if (!ircxmpp->bridges) { // bridges contain ctx inside of their conns. - if (ircxmpp->conn) // maybe conn can be freed but i don't know - xmpp_conn_release(ircxmpp->conn); // bottom line: ctx really can't be + if (!ircxmpp->bridges) { // bridges contain ctx inside of their conns + if (ircxmpp->conn) + xmpp_conn_release(ircxmpp->conn); if (ircxmpp->ctx) xmpp_ctx_free(ircxmpp->ctx); ircxmpp->ctx = xmpp_ctx_new(NULL, &ircxmpp->xmpp_logger); @@ -757,9 +771,25 @@ void ircxmpp_run_once (struct ircxmpp * ircxmpp) { irc_destroy_session(ircxmpp->irc); init_irc_control(ircxmpp); } + ircxmpp->to_free_bridges_length = ircxmpp->to_free_reasons_length = 0; + ircxmpp->to_free_bridges_sizeof = ircxmpp->to_free_reasons_sizeof = ALLOC_CHUNK; + size_t req = sizeof(*ircxmpp->to_free_bridges)*ircxmpp->to_free_bridges_sizeof; + ircxmpp->to_free_bridges = malloc(req); + ircxmpp->to_free_reasons = malloc(req); + if (!ircxmpp->to_free_reasons || !ircxmpp->to_free_bridges) { + LOG(ircxmpp, IRCXMPP_ERROR, "malloc(%z) to_free failed!", req); + goto r; + } twalk(ircxmpp->bridges, obdelaj_bridge); + for (size_t i = 0; i < ircxmpp->to_free_bridges_length; i++) + free_bridge(ircxmpp->to_free_bridges[i], ircxmpp->to_free_reasons[i]); +r: + free(ircxmpp->to_free_bridges); + free(ircxmpp->to_free_reasons); + ircxmpp->to_free_bridges_length = ircxmpp->to_free_bridges_sizeof = ircxmpp->to_free_reasons_length = ircxmpp->to_free_reasons_sizeof = 0; } void ircxmpp_free (struct ircxmpp * ircxmpp) { + LOG(ircxmpp, IRCXMPP_DEBUG, "engaging the freeing routine"); free_bridges(&ircxmpp->bridges); xmpp_conn_release(ircxmpp->conn); xmpp_ctx_free(ircxmpp->ctx); @@ -797,8 +827,8 @@ int main (void) { size_t handles_length = 0; char * domain = NULL; // to know if we want to run dns server or not ircxmpp ** handles = NULL; - while (1) { // note that if input config is invalid we leak memory before exiting - char b[64]; // i don't free any allocated shit and just return, probably it's ok + while (1) { + char b[64]; if (handles_length++) sprintf(b, "IX_JID%zu", handles_length); else @@ -806,6 +836,7 @@ int main (void) { if (!getenv(b)) { if (handles_length == 1) { fprintf(stderr, USAGE "FAIL: at least one link is required!\n"); + free(handles); return 1; } handles_length--; @@ -820,16 +851,19 @@ int main (void) { sprintf(b, "IX_" config "%zu", handles_length); \ if (getenv(b)) \ ircxmpp_set_##value(handles[handles_length-1], function(getenv(b))); \ - else if (required) \ - fprintf(stderr, USAGE "FAIL: environment variable %s was expected to be set.\n", b) - PREPARE_HANDLE(jid, "JID", str2str, 1); - PREPARE_HANDLE(password, "PASS", str2str, 1); - PREPARE_HANDLE(hostname, "HOST", str2str, 1); - PREPARE_HANDLE(port, "PORT", atoi, 1); - PREPARE_HANDLE(channel, "CHANNEL", str2str, 1); - PREPARE_HANDLE(muc, "MUC", str2str, 1); - PREPARE_HANDLE(channel_password, "CHPASS", str2str, 0); - PREPARE_HANDLE(domain, "DOMAIN", str2str, 0); + else if (required) { \ + fprintf(stderr, USAGE "FAIL: environment variable %s was expected to be set.\n", b); \ + free(handles); \ + return 2; \ + } + PREPARE_HANDLE(jid, "JID", str2str, 1) + PREPARE_HANDLE(password, "PASS", str2str, 1) + PREPARE_HANDLE(hostname, "HOST", str2str, 1) + PREPARE_HANDLE(port, "PORT", atoi, 1) + PREPARE_HANDLE(channel, "CHANNEL", str2str, 1) + PREPARE_HANDLE(muc, "MUC", str2str, 1) + PREPARE_HANDLE(channel_password, "CHPASS", str2str, 0) + PREPARE_HANDLE(domain, "DOMAIN", str2str, 0) if (getenv(b)) domain = getenv(b); } |