#include "jsm.h"
void js_deliver_local(jsmi si, jpacket p, HASHTABLE ht)
{
udata user = NULL;
session s = NULL;
user = js_user(si, p->to, ht);
s = js_session_get(user, p->to->resource);
log_debug(ZONE,"delivering locally to %s",jid_full(p->to));
if(js_mapi_call(si, e_DELIVER, p, user, s))
return;
if(p->to->user == NULL)
{
js_psend(si,p,js_server_main);
return;
}
if(s != NULL)
{
js_session_to(s, p);
return;
}
if(user != NULL)
{
p->aux1 = (void *)user;
user->ref++;
js_psend(si,p,js_offline_main);
return;
}
js_bounce(si,p->x,TERROR_NOTFOUND);
}
result js_packet(instance i, dpacket p, void *arg)
{
jsmi si = (jsmi)arg;
jpacket jp = NULL;
HASHTABLE ht;
session s = NULL;
udata u;
char *type, *authto;
xmlnode child;
log_debug(ZONE,"(%X)incoming packet %s",si,xmlnode2str(p->x));
if((ht = (HASHTABLE)ghash_get(si->hosts,p->host)) == NULL)
{
ht = ghash_create(j_atoi(xmlnode_get_data(js_config(si,"maxusers")),USERS_PRIME),(KEYHASHFUNC)str_hash_code,(KEYCOMPAREFUNC)j_strcmp);
log_debug(ZONE,"creating user hash %X for %s",ht,p->host);
ghash_put(si->hosts,pstrdup(si->p,p->host), (void *)ht);
log_debug(ZONE,"checking %X",ghash_get(si->hosts,p->host));
}
if(p->type == p_ROUTE)
{
type = xmlnode_get_attrib(p->x,"type");
if(j_strcmp(type,"session") == 0)
{
if((s = js_session_new(si, p)) == NULL)
{
log_warn(p->host,"Unable to create session %s",jid_full(p->id));
xmlnode_put_attrib(p->x,"type","error");
xmlnode_put_attrib(p->x,"error","Session Failed");
}else{
xmlnode_put_attrib(p->x,"to",jid_full(s->route));
}
jutil_tofrom(p->x);
deliver(dpacket_new(p->x), i);
return r_DONE;
}
child = xmlnode_get_firstchild(p->x);
while (child != NULL)
{
if (xmlnode_get_type(child) == NTYPE_TAG)
break;
child = xmlnode_get_nextsibling(child);
}
if (child != NULL)
jp = jpacket_new(child);
if(jp != NULL && j_strcmp(type,"auth") == 0)
{
if((authto = xmlnode_get_data(js_config(si,"auth"))) != NULL)
{
xmlnode_put_attrib(p->x,"oto",xmlnode_get_attrib(p->x,"to"));
xmlnode_put_attrib(p->x,"to",authto);
deliver(dpacket_new(p->x), i);
return r_DONE;
}
xmlnode_put_attrib(jp->x,"to",xmlnode_get_attrib(p->x,"to"));
xmlnode_put_attrib(jp->x,"from",xmlnode_get_attrib(p->x,"from"));
xmlnode_put_attrib(jp->x,"route",xmlnode_get_attrib(p->x,"type"));
jpacket_reset(jp);
jp->aux1 = (void *)si;
mtq_send(NULL,jp->p,js_authreg,(void *)jp);
return r_DONE;
}
u = js_user(si, p->id, ht);
if(u == NULL)
{
log_notice(p->host,"Bouncing packet intended for nonexistant user: %s",xmlnode2str(p->x));
deliver_fail(dpacket_new(p->x), "Invalid User");
return r_DONE;
}
for(s = u->sessions; s != NULL; s = s->next)
if(j_strcmp(p->id->resource, s->route->resource) == 0)
break;
if(j_strcmp(type,"error") == 0)
{
if(s != NULL)
{
s->sid = NULL;
js_session_end(s, "Disconnected");
}else if(p->id->resource == NULL){
for(s = u->sessions; s != NULL; s = s->next)
js_session_end(s,"Removed");
u->pass = NULL;
xmlnode_free(p->x);
return r_DONE;
}
if(jp != NULL && jp->type == JPACKET_MESSAGE)
{
js_deliver_local(si, jp, ht);
return r_DONE;
}
if(xmlnode_get_firstchild(p->x) != NULL)
log_notice(p->host, "Dropping a bounced session packet to %s", jid_full(p->id));
xmlnode_free(p->x);
return r_DONE;
}
if(jp == NULL)
{
log_notice(p->host,"Dropping an invalid or empty route packet: %s",xmlnode2str(p->x),jid_full(p->id));
xmlnode_free(p->x);
return r_DONE;
}
if(s != NULL)
{
js_session_from(s, jp);
}else{
log_notice(p->host,"Bouncing %s packet intended for session %s",xmlnode_get_name(jp->x),jid_full(p->id));
deliver_fail(dpacket_new(p->x), "Invalid Session");
}
return r_DONE;
}
jp = jpacket_new(p->x);
if(jp == NULL)
{
log_warn(p->host,"Dropping invalid incoming packet: %s",xmlnode2str(p->x));
xmlnode_free(p->x);
return r_DONE;
}
js_deliver_local(si, jp, ht);
return r_DONE;
}
void js_deliver(jsmi si, jpacket p)
{
HASHTABLE ht;
if(p->to == NULL)
{
log_warn(NULL,"jsm: Invalid Recipient, returning data %s",xmlnode2str(p->x));
js_bounce(si,p->x,TERROR_BAD);
return;
}
if(p->from == NULL)
{
log_warn(NULL,"jsm: Invalid Sender, discarding data %s",xmlnode2str(p->x));
xmlnode_free(p->x);
return;
}
log_debug(ZONE,"deliver(to[%s],from[%s],type[%d],packet[%s])",jid_full(p->to),jid_full(p->from),p->type,xmlnode2str(p->x));
if((ht = (HASHTABLE)ghash_get(si->hosts,p->to->server)) != NULL)
{
js_deliver_local(si, p, ht);
return;
}
deliver(dpacket_new(p->x), si->i);
}
void js_psend(jsmi si, jpacket p, mtq_callback f)
{
jpq q;
if(p == NULL || si == NULL)
return;
log_debug(ZONE,"psending to %X packet %X",f,p);
q = pmalloc(p->p, sizeof(_jpq));
q->p = p;
q->si = si;
mtq_send(NULL, p->p, f, (void *)q);
}