summaryrefslogtreecommitdiffstats
path: root/ircxmpp.c
diff options
context:
space:
mode:
Diffstat (limited to 'ircxmpp.c')
-rw-r--r--ircxmpp.c88
1 files changed, 61 insertions, 27 deletions
diff --git a/ircxmpp.c b/ircxmpp.c
index e8d8e97..52e9355 100644
--- a/ircxmpp.c
+++ b/ircxmpp.c
@@ -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);
}