mreturn mod_roster_auto_in_s10n(mapi m, void *arg) { xmlnode reply, x; log_debug("AUTO ROSTER"); //in not s10n if (m->packet->type != JPACKET_S10N) return M_IGNORE; //if no to if (m->packet->to == NULL) return M_PASS; //if from me if (jid_cmpx(m->s->uid, m->packet->from, JID_USER | JID_SERVER) == 0) return M_PASS; log_debug("handling incoming s10n"); switch (jpacket_subtype(m->packet)) { case JPACKET__SUBSCRIBE: log_debug("SUBSCRIBE"); reply = jutil_presnew(JPACKET__SUBSCRIBED, jid_full(m->packet->from), NULL); js_session_from(m->s, jpacket_new(reply)); reply = jutil_presnew(JPACKET__SUBSCRIBE, jid_full(m->packet->from), NULL); js_session_from(m->s, jpacket_new(reply)); break; case JPACKET__SUBSCRIBED: break; case JPACKET__UNSUBSCRIBE: log_debug("UNSUBSCRIBE"); //reply = jutil_presnew(JPACKET__UNSUBSCRIBED, jid_full(m->packet->from),NULL); //js_session_from(m->s, jpacket_new(reply)); //remove account. reply = jutil_iqnew(JPACKET__SET, NS_ROSTER); x = xmlnode_get_tag(reply, "query"); x = xmlnode_insert_tag(x, "item"); xmlnode_put_attrib(x, "jid", jid_full(jid_user(m->packet->from))); xmlnode_put_attrib(x, "subscription", "remove"); js_session_from(m->s, jpacket_new(reply)); // reply = jutil_iqnewpresnew(JPACKET__UNSUBSCRIBE, jid_full(m->packet->from),NULL); // js_session_from(m->s, jpacket_new(reply)); break; case JPACKET__UNSUBSCRIBED: break; } xmlnode_free(m->packet->x); return M_HANDLED; }
void con_room_leaveall(gpointer key, gpointer data, gpointer arg) { cnu user = (cnu)data; xmlnode info = (xmlnode)arg; char *alt, *reason; xmlnode presence; xmlnode tag; xmlnode element; xmlnode node; xmlnode destroy; log_debug(NAME, "[%s] reason : %s", FZONE, xmlnode2str(info)); if(user == NULL) { log_warn(NAME, "[%s] Aborting - NULL user attribute found", FZONE); return; } if (user->remote == 1) return; presence = jutil_presnew(JPACKET__UNAVAILABLE, NULL, NULL); tag = xmlnode_insert_tag(presence,"x"); xmlnode_put_attrib(tag, "xmlns", NS_MUC_USER); element = xmlnode_insert_tag(tag, "item"); xmlnode_put_attrib(element, "role", "none"); xmlnode_put_attrib(element, "affiliation", "none"); if (info != NULL) { destroy = xmlnode_insert_tag(tag, "destroy"); reason = xmlnode_get_tag_data(info, "reason"); node = xmlnode_insert_tag(destroy, "reason"); if(reason != NULL) { xmlnode_insert_cdata(node, reason, -1); } alt = xmlnode_get_attrib(info, "jid"); if (alt != NULL) { xmlnode_put_attrib(destroy, "jid", alt); } } con_user_send(user, user, presence); }
/* child that cleans up a session session thread */ void _js_session_end(session s) { xmlnode x, temp; /* debug message */ log_debug("THREAD:SESSION exiting"); /* only for moules es_END */ temp = s->presence; if (temp != NULL && j_strcmp(xmlnode_get_attrib(temp, "type"), "unavailable") != 0) { /* create a new presence packet with the reason the user is unavailable */ x = jutil_presnew(JPACKET__UNAVAILABLE, NULL, NULL); xmlnode_put_attrib(x, "from", jid_full(s->id)); /* free the old presence packet */ s->presence = x; } else { temp = NULL; } /* make sure the service knows the session is gone */ if (s->sid != NULL) js_session_route(s, NULL); /* let the modules have their heyday */ js_mapi_call(NULL, es_END, NULL, s->u, s); /* let the user struct go */ THREAD_DEC(s->u->ref); /* free old presence */ if (temp) xmlnode_free(temp); /* free the session's presence state */ temp = s->presence; s->presence = NULL; s->q->count--; /* free the session's memory pool */ register_beat(60, js_session_free, s); /* free unavailable presence we have set */ if (temp) xmlnode_free(temp); }
/* session thread */ mreturn mod_presence_in(mapi m, void *arg) { modpres mp = (modpres) arg; xmlnode pres; if (m->packet->type != JPACKET_PRESENCE) return M_IGNORE; log_debug("incoming filter for %s", jid_full(m->s->id)); if (jpacket_subtype(m->packet) == JPACKET__PROBE) { /* reply with our presence */ if (m->s->presence == NULL) { log_debug("probe from %s and no presence to return", jid_full(m->packet->from)); } else if (!mp->invisible && js_trust(m->user, m->packet->from) && !_mod_presence_search(m->packet->from, mp->I)) { /* compliment of I in T */ log_debug("got a probe, responding to %s", jid_full(m->packet->from)); pres = xmlnode_dup(m->s->presence); xmlnode_put_attrib(pres, "to", jid_full(m->packet->from)); js_session_from(m->s, jpacket_new(pres)); } else if (mp->invisible && js_trust(m->user, m->packet->from) && _mod_presence_search(m->packet->from, mp->A)) { /* when invisible, intersection of A and T */ log_debug("got a probe when invisible, responding to %s", jid_full(m->packet->from)); pres = jutil_presnew(JPACKET__AVAILABLE, jid_full(m->packet->from), NULL); js_session_from(m->s, jpacket_new(pres)); } else { log_debug("%s attempted to probe by someone not qualified", jid_full(m->packet->from)); } xmlnode_free(m->packet->x); return M_HANDLED; } if (jid_cmp(m->packet->from, m->s->id) == 0) { /* this is our presence, don't send to ourselves */ xmlnode_free(m->packet->x); return M_HANDLED; } /* if a presence packet bounced, remove from the A list */ if (jpacket_subtype(m->packet) == JPACKET__ERROR) mp->A = _mod_presence_whack(m->packet->from, mp->A); /* doh! this is a user, they should see invisibles as unavailables */ if (jpacket_subtype(m->packet) == JPACKET__INVISIBLE) xmlnode_put_attrib(m->packet->x, "type", "unavailable"); return M_PASS; }
/* * js_session_new -- creates a new session, registers the resource for it * * Sets up all the data associated with the new session, then send it a * start spacket, which basically notifies all modules about the new session * * returns * a pointer to the new session */ session js_session_new(jsmi si, dpacket dp) { pool p; session s, cur; udata u; int i; char routeres[10]; /* screen out illegal calls */ if (dp == NULL || dp->id->user == NULL || dp->id->resource == NULL || xmlnode_get_attrib(dp->x, "from") == NULL) return NULL; if ((u = js_user(si, dp->id, 0)) == NULL) return NULL; if (u->scount >= MAX_USER_SESSIONS) { THREAD_DEC(u->ref); return NULL; } log_debug("session_create %s", jid_full(dp->id)); /* create session */ p = pool_heap(1024); s = pmalloco(p, sizeof(struct session_struct)); s->p = p; s->si = si; /* save authorative remote session id */ s->sid = jid_new(p, xmlnode_get_attrib(dp->x, "from")); /* session identity */ s->id = jid_new(p, jid_full(dp->id)); /* id bez resource */ s->uid = jid_user(s->id); s->route = jid_new(p, jid_full(dp->id)); snprintf(routeres, 9, "%X", s); jid_set(s->route, routeres, JID_RESOURCE); s->res = pstrdup(p, dp->id->resource); s->u = u; jid_full(s->sid); jid_full(s->uid); jid_full(s->id); jid_full(s->route); { register char *text; text = xmlnode_get_attrib(dp->x, "ip"); if (text) { s->ip = pstrdup(s->p, xmlnode_get_attrib(dp->x, "ip")); xmlnode_hide_attrib(dp->x, "ip"); } else s->ip = "none"; } /* default settings */ s->exit_flag = 0; s->roster = 0; s->priority = -129; s->presence = jutil_presnew(JPACKET__UNAVAILABLE, NULL, NULL); xmlnode_put_attrib(s->presence, "from", jid_full(s->id)); s->c_in = s->c_out = 0; for (i = 0; i < es_LAST; i++) s->events[i] = NULL; SEM_LOCK(u->sem); if (u->sessions != NULL) { s->q = get_mtq_queue(si, u->sessions->q); for (cur = u->sessions; cur != NULL; cur = cur->next) if (j_strcmp(dp->id->resource, cur->res) == 0) js_session_end_nosem(cur, "Replaced by new connection"); } else { s->q = get_mtq_queue(si, NULL); } /* make sure we're linked with the user */ s->next = s->u->sessions; s->u->sessions = s; s->u->scount++; SEM_UNLOCK(u->sem); /* session start */ { packet_thread_p pt; pt = malloc(sizeof(packet_thread_t)); pt->s = s; pt->type = 0; fast_mtq_send(s->q->mtq, pt); } THREAD_DEC(u->ref); return s; }
/* session thread */ mreturn mod_presence_out(mapi m, void *arg) { xmlnode pnew, delay, pold; modpres mp = (modpres) arg; session cur = NULL; int oldpri, newpri; char *priority; if (m->packet->type != JPACKET_PRESENCE) return M_IGNORE; if (m->packet->to != NULL || jpacket_subtype(m->packet) == JPACKET__PROBE || jpacket_subtype(m->packet) == JPACKET__ERROR) return M_PASS; log_debug("new presence from %s of %s", jid_full(m->s->id), xmlnode2str(m->packet->x)); /* pre-existing conditions (no, we are not an insurance company) */ oldpri = m->s->priority; /* check that the priority is in the valid range */ priority = xmlnode_get_tag_data(m->packet->x, "priority"); if (priority == NULL) { newpri = 0; } else { newpri = j_atoi(priority, 0); if (newpri < -128 || newpri > 127) { log_notice("mod_presence", "got presence with invalid priority value from %s", jid_full(m->s->id)); xmlnode_free(m->packet->x); return M_HANDLED; } } /* invisible mode is special, don't you wish you were special too? */ if (jpacket_subtype(m->packet) == JPACKET__INVISIBLE) { log_debug("handling invisible mode request"); /* if we get this and we're available, it means go unavail first then reprocess this packet, nifty trick :) */ if (oldpri >= -128) { js_session_from(m->s, jpacket_new(jutil_presnew (JPACKET__UNAVAILABLE, NULL, xmlnode_get_tag_data(m->packet->x,"status") ))); js_session_from(m->s, m->packet); return M_HANDLED; } /* now, pretend we come online :) */ /* (this is the handling of the reinjected invisible presence * or an initial invisible presence) */ mp->invisible = 1; mod_presence_roster(m, NULL); /* send out probes to users we are subscribed to */ m->s->priority = newpri; /* store presence in xdb? */ if (mp->conf->pres_to_xdb > 0) mod_presence_store(m); xmlnode_free(m->packet->x); /* we do not broadcast invisible presences without a to attribute */ return M_HANDLED; } /* our new presence */ pnew = xmlnode_dup(m->packet->x); /* store presence in xdb? */ if (mp->conf->pres_to_xdb > 0) mod_presence_store(m); /* stamp the sessions presence */ delay = xmlnode_insert_tag(pnew, "x"); xmlnode_put_attrib(delay, "xmlns", NS_DELAY); xmlnode_put_attrib(delay, "from", jid_full(m->s->id)); xmlnode_put_attrib(delay, "stamp", jutil_timestamp()); /* our old presence */ pold = m->s->presence; m->s->presence = pnew; m->s->priority = jutil_priority(pnew); log_debug("presence oldp %d newp %d", oldpri, m->s->priority); /* if we're going offline now, let everyone know */ if (m->s->priority < -128) { /* jutil_priority returns -129 in case the "type" attribute is missing */ if (!mp->invisible) /* bcc's don't get told if we were invisible */ _mod_presence_broadcast(m->s, mp->conf->bcc, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->A, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->I, m->packet->x, NULL); /* reset vars */ mp->invisible = 0; mp->A->next = NULL; mp->I = NULL; xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; } /* available presence updates, intersection of A and T */ if (oldpri >= -128 && !mp->invisible) { _mod_presence_broadcast_trusted(m->s, mp->A, m->packet->x); xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; } /* at this point we're coming out of the closet */ mp->invisible = 0; /* make sure we get notified for any presence about ourselves */ /* XXX: the following is the original code: it caused existing presences * to be stamped several times and the presence to be sent out twice. pnew = jutil_presnew(JPACKET__PROBE,jid_full(m->s->uid),NULL); xmlnode_put_attrib(pnew,"from",jid_full(m->s->uid)); js_session_from(m->s, jpacket_new(pnew)); */ /* XXX: I think this should be okay as well: */ /* send us all presences of our other resources */ for (cur = m->user->sessions; cur != NULL; cur = cur->next) { pool pool_for_existing_presence = NULL; xmlnode duplicated_presence = NULL; jpacket packet = NULL; /* skip our own session (and sanity check) */ if (cur == m->s || cur->presence == NULL) { continue; } /* send the presence to us: we need a new pool as js_session_to() will free the packet's pool */ pool_for_existing_presence = pool_new(); duplicated_presence = xmlnode_dup_pool(pool_for_existing_presence, cur->presence); xmlnode_put_attrib(duplicated_presence, "to", jid_full(m->user->id)); packet = jpacket_new(duplicated_presence); js_session_to(m->s, packet); } /* probe s10ns and populate A */ mod_presence_roster(m, mp->A); /* we broadcast this baby! */ _mod_presence_broadcast(m->s, mp->conf->bcc, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->A, m->packet->x, NULL); xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; }