#include "sm.h"
void sess_route(sess_t sess, pkt_t pkt) {
int ns;
log_debug(ZONE, "routing pkt 0x%X to %s (%s) for %s", pkt, sess->c2s, sess->c2s_id, jid_full(sess->jid));
if(pkt == NULL)
return;
ns = nad_append_namespace(pkt->nad, 1, uri_SESSION, "sm");
nad_set_attr(pkt->nad, 1, ns, "c2s", sess->c2s_id, 0);
nad_set_attr(pkt->nad, 1, ns, "sm", sess->sm_id, 0);
nad_set_attr(pkt->nad, 0, -1, "to", sess->c2s, 0);
nad_set_attr(pkt->nad, 0, -1, "from", sess->user->sm->id, 0);
sx_nad_write(sess->user->sm->router, pkt->nad);
if(pkt->rto != NULL) jid_free(pkt->rto);
if(pkt->rfrom != NULL) jid_free(pkt->rfrom);
if(pkt->to != NULL) jid_free(pkt->to);
if(pkt->from != NULL) jid_free(pkt->from);
free(pkt);
}
static void _sess_end_guts(sess_t sess) {
sess_t scan;
if(sess->available || sess->invisible || sess->A != NULL)
mm_in_sess(sess->user->sm->mm, sess, pkt_create(sess->user->sm, "presence", "unavailable", NULL, NULL));
mm_sess_end(sess->user->sm->mm, sess);
if(sess->user->sessions == sess)
sess->user->sessions = sess->next;
else {
for(scan = sess->user->sessions; scan != NULL && scan->next != sess; scan = scan->next);
if(scan != NULL)
scan->next = sess->next;
}
xhash_zap(sess->user->sm->sessions, sess->sm_id);
}
void sess_end(sess_t sess) {
log_debug(ZONE, "shutting down session %s", jid_full(sess->jid));
_sess_end_guts(sess);
log_write(sess->user->sm->log, LOG_NOTICE, "session ended: jid=%s", jid_full(sess->jid));
if(sess->user->sessions == NULL)
user_free(sess->user);
pool_free(sess->p);
}
sess_t sess_start(sm_t sm, jid_t jid) {
pool p;
user_t user;
sess_t sess, scan;
sha1_state_t sha1;
char hash[20];
int replaced = 0;
log_debug(ZONE, "session requested for %s", jid_full(jid));
user = user_load(sm, jid);
if(user == NULL) {
if(config_get(sm->config, "user.auto-create") == NULL) {
log_write(sm->log, LOG_NOTICE, "user not found, can't start session: jid=%s", jid_full(jid));
return NULL;
}
log_debug(ZONE, "auto-creating user %s", jid_user(jid));
if(user_create(sm, jid) != 0)
return NULL;
user = user_load(sm, jid);
if(user == NULL) {
log_write(sm->log, LOG_NOTICE, "couldn't load user, can't start session: jid=%s", jid_full(jid));
return NULL;
}
}
for(scan = user->sessions; scan != NULL; scan = scan->next)
if(jid_compare_full(scan->jid, jid) == 0) {
log_debug(ZONE, "replacing session %s (%s)", jid_full(jid), scan->c2s_id);
sm_c2s_action(scan, "replaced", NULL);
_sess_end_guts(scan);
pool_free(scan->p);
replaced = 1;
break;
}
p = pool_new();
sess = (sess_t) pmalloco(p, sizeof(struct sess_st));
sess->p = p;
sess->pri = 0;
sess->user = user;
sess->jid = jid_dup(jid);
pool_cleanup(sess->p, (void (*))(void *) jid_free, sess->jid);
sess->module_data = (void **) pmalloco(sess->p, sizeof(void *) * sess->user->sm->mm->nindex);
sess->next = user->sessions;
user->sessions = sess;
sha1_init(&sha1);
datetime_out(time(NULL), dt_DATETIME, sess->sm_id, 41);
sha1_append(&sha1, sess->sm_id, strlen(sess->sm_id));
sha1_append(&sha1, jid_full(sess->jid), strlen(jid_full(sess->jid)));
sha1_finish(&sha1, hash);
hex_from_raw(hash, 20, sess->sm_id);
log_debug(ZONE, "smid is %s", sess->sm_id);
xhash_put(sm->sessions, sess->sm_id, sess);
mm_sess_start(sm->mm, sess);
if(replaced)
log_write(sm->log, LOG_NOTICE, "session replaced: jid=%s", jid_full(sess->jid));
else
log_write(sm->log, LOG_NOTICE, "session started: jid=%s", jid_full(sess->jid));
return sess;
}
sess_t sess_match(user_t user, char *resource) {
sess_t sess;
for(sess = user->sessions; sess != NULL; sess = sess->next) {
if(strcmp(sess->jid->resource, resource) == 0)
return sess;
}
return NULL;
}