#include "conference.h"
#include <sys/utsname.h>
void con_server_browsewalk(gpointer key, gpointer data, gpointer arg)
{
cnr room = (cnr)data;
jpacket jp = (jpacket)arg;
char users[10];
char maxu[10];
xmlnode x;
if(room == NULL)
{
log_warn(NAME, "[%s] Aborting: NULL room %s", FZONE, key);
return;
}
if(room->public == 0 && !in_room(room, jp->to) && !is_admin(room, jp->to) && !is_member(room, jp->to))
return;
if(room->locked == 1)
return;
x = xmlnode_insert_tag(jp->iq, "item");
xmlnode_put_attrib(x, "category", "conference");
if(room->public == 0)
xmlnode_put_attrib(x, "type", "private");
else
xmlnode_put_attrib(x, "type", "public");
xmlnode_put_attrib(x, "jid", jid_full(room->id));
if(room->maxusers > 0)
xmlnode_put_attrib(x, "name", spools(jp->p, room->name, " (", itoa(room->count, users), "/", itoa(room->maxusers, maxu), ")", jp->p));
else
xmlnode_put_attrib(x, "name", spools(jp->p, room->name, " (", itoa(room->count, users), ")", jp->p));
}
void _server_discowalk(gpointer key, gpointer data, gpointer arg)
{
cnr room = (cnr)data;
jpacket jp = (jpacket)arg;
xmlnode x;
if(room == NULL)
{
log_warn(NAME, "[%s] Aborting: NULL room %s", FZONE, key);
return;
}
if(room->public == 0 && !in_room(room, jp->to) && !is_admin(room, jp->to) && !is_member(room, jp->to))
return;
if(room->locked == 1)
return;
x = xmlnode_insert_tag(jp->iq, "item");
xmlnode_put_attrib(x, "jid", jid_full(room->id));
xmlnode_put_attrib(x, "name", spools(jp->p, room->name, jp->p));
}
void con_server(cni master, jpacket jp)
{
char *str;
struct utsname un;
xmlnode x;
int start, status;
time_t t;
char *from;
char nstr[10];
jid user;
log_debug(NAME, "[%s] server packet", FZONE);
if(jp->type == JPACKET_PRESENCE)
{
log_debug(NAME, "[%s] Server packet: Presence - Not Implemented", FZONE);
jutil_error(jp->x, TERROR_NOTIMPL);
deliver(dpacket_new(jp->x),NULL);
return;
}
if(jp->type != JPACKET_IQ)
{
log_debug(NAME, "[%s] Server packet: Dropping non-IQ packet", FZONE);
xmlnode_free(jp->x);
return;
}
if(jpacket_subtype(jp) == JPACKET__SET)
{
log_debug(NAME, "[%s] Server packet - IQ Set", FZONE);
if(NSCHECK(jp->iq,NS_REGISTER))
{
log_debug(NAME, "[%s] TERROR_NOTIMPL", FZONE);
jutil_error(jp->x, TERROR_NOTIMPL);
deliver(dpacket_new(jp->x),NULL);
return;
log_debug(NAME, "[%s] Server packet - Registration Handler", FZONE);
str = xmlnode_get_tag_data(jp->iq, "name");
x = xmlnode_get_tag(jp->iq, "remove");
from = xmlnode_get_attrib(jp->x, "from");
user = jid_new(jp->p, from);
status = is_registered(master, jid_full(jid_user(user)), str);
if(x)
{
log_debug(NAME, "[%s] Server packet - UnReg Submission", FZONE);
set_data(master, str, from, NULL, 1);
jutil_iqresult(jp->x);
}
else if(status == -1)
{
log_debug(NAME, "[%s] Server packet - Registration Submission : Already taken", FZONE);
jutil_error(jp->x, TERROR_MUC_NICKREG);
}
else if(status == 0)
{
log_debug(NAME, "[%s] Server packet - Registration Submission", FZONE);
set_data(master, str, from, NULL, 0);
jutil_iqresult(jp->x);
}
else
{
log_debug(NAME, "[%s] Server packet - Registration Submission : already set", FZONE);
jutil_iqresult(jp->x);
}
deliver(dpacket_new(jp->x), NULL);
}
}
else if(jpacket_subtype(jp) == JPACKET__GET)
{
if(NSCHECK(jp->iq,NS_REGISTER))
{
log_debug(NAME, "[%s] Server packet - Registration Request", FZONE);
log_debug(NAME, "[%s] TERROR_NOTIMPL", FZONE);
jutil_error(jp->x, TERROR_NOTIMPL);
deliver(dpacket_new(jp->x),NULL);
return;
x = get_data_byjid(master, xmlnode_get_attrib(jp->x, "from"));
str = xmlnode_get_attrib(x, "nick") ? xmlnode_get_attrib(x, "nick") : "";
jutil_iqresult(jp->x);
xmlnode_put_attrib(xmlnode_insert_tag(jp->x, "query"), "xmlns", NS_REGISTER);
jpacket_reset(jp);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "instructions"), "Enter the nickname you wish to reserve for this conference service", -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "name"), str, -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "key"), jutil_regkey(NULL, jid_full(jp->to)), -1);
if(x != NULL)
xmlnode_insert_tag(jp->iq, "registered");
deliver(dpacket_new(jp->x), NULL);
}
else if(NSCHECK(jp->iq,NS_TIME))
{
log_debug(NAME, "[%s] Server packet - Time Request", FZONE);
jutil_iqresult(jp->x);
xmlnode_put_attrib(xmlnode_insert_tag(jp->x, "query"), "xmlns", NS_TIME);
jpacket_reset(jp);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "utc"), jutil_timestamp(), -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "tz"), tzname[0], -1);
t = time(NULL);
str = ctime(&t);
str[strlen(str) - 1] = '\0';
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "display"), pstrdup(jp->p, str), -1);
deliver(dpacket_new(jp->x),NULL);
}
else if(NSCHECK(jp->iq,NS_VERSION))
{
log_debug(NAME, "[%s] Server packet - Version Request", FZONE);
jutil_iqresult(jp->x);
xmlnode_put_attrib(xmlnode_insert_tag(jp->x, "query"), "xmlns", NS_VERSION);
jpacket_reset(jp);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "name"), NAME, -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "version"), VERSION, -1);
uname(&un);
x = xmlnode_insert_tag(jp->iq,"os");
xmlnode_insert_cdata(x, pstrdup(jp->p, un.sysname),-1);
xmlnode_insert_cdata(x," ",1);
xmlnode_insert_cdata(x,pstrdup(jp->p, un.release),-1);
deliver(dpacket_new(jp->x),NULL);
}
else if(NSCHECK(jp->iq,NS_BROWSE))
{
log_debug(NAME, "[%s] Server packet - Browse Request", FZONE);
jutil_iqresult(jp->x);
xmlnode_put_attrib(xmlnode_insert_tag(jp->x, "item"), "xmlns", NS_BROWSE);
jpacket_reset(jp);
xmlnode_put_attrib(jp->iq, "category", "conference");
xmlnode_put_attrib(jp->iq, "type", "public");
xmlnode_put_attrib(jp->iq, "jid", master->i->id);
xmlnode_put_attrib(jp->iq, "name", xmlnode_get_tag_data(master->config, "vCard/FN"));
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "ns"), NS_MUC, -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "ns"), NS_DISCO, -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "ns"), NS_BROWSE, -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "ns"), NS_VERSION, -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "ns"), NS_TIME, -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "ns"), NS_LAST, -1);
xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq, "ns"), NS_VCARD, -1);
g_hash_table_foreach(master->rooms, con_server_browsewalk, (void*)jp);
deliver(dpacket_new(jp->x), NULL);
}
else if(NSCHECK(jp->iq, NS_DISCO_INFO))
{
log_debug(NAME, "[%s] Server packet - Disco Info Request", FZONE);
jutil_iqresult(jp->x);
xmlnode_put_attrib(xmlnode_insert_tag(jp->x,"query"), "xmlns", NS_DISCO_INFO);
jpacket_reset(jp);
x = xmlnode_insert_tag(jp->iq,"identity");
xmlnode_put_attrib(x, "category", "conference");
xmlnode_put_attrib(x, "type", "text");
xmlnode_put_attrib(x, "name", xmlnode_get_tag_data(master->config, "vCard/FN"));
xmlnode_put_attrib(xmlnode_insert_tag(jp->iq,"feature"), "var", NS_MUC);
xmlnode_put_attrib(xmlnode_insert_tag(jp->iq,"feature"), "var", NS_DISCO);
xmlnode_put_attrib(xmlnode_insert_tag(jp->iq,"feature"), "var", NS_BROWSE);
xmlnode_put_attrib(xmlnode_insert_tag(jp->iq,"feature"), "var", NS_VERSION);
xmlnode_put_attrib(xmlnode_insert_tag(jp->iq,"feature"), "var", NS_TIME);
xmlnode_put_attrib(xmlnode_insert_tag(jp->iq,"feature"), "var", NS_LAST);
xmlnode_put_attrib(xmlnode_insert_tag(jp->iq,"feature"), "var", NS_VCARD);
deliver(dpacket_new(jp->x),NULL);
}
else if(NSCHECK(jp->iq, NS_DISCO_ITEMS))
{
log_debug(NAME, "[%s] Server packet - Disco Items Request", FZONE);
jutil_iqresult(jp->x);
xmlnode_put_attrib(xmlnode_insert_tag(jp->x,"query"),"xmlns", NS_DISCO_ITEMS);
jpacket_reset(jp);
g_hash_table_foreach(master->rooms,_server_discowalk, (void*)jp);
deliver(dpacket_new(jp->x),NULL);
}
else if(NSCHECK(jp->iq, NS_LAST))
{
log_debug(NAME, "[%s] Server packet - Last Request", FZONE);
jutil_iqresult(jp->x);
xmlnode_put_attrib(xmlnode_insert_tag(jp->x,"query"),"xmlns",NS_LAST);
jpacket_reset(jp);
start = time(NULL) - master->start;
sprintf(nstr,"%d",start);
xmlnode_put_attrib(jp->iq,"seconds", pstrdup(jp->p, nstr));
deliver(dpacket_new(jp->x),NULL);
}
else if(NSCHECK(jp->iq,NS_VCARD))
{
log_debug(NAME, "[%s] Server packet - VCard Request", FZONE);
jutil_iqresult(jp->x);
xmlnode_put_attrib(xmlnode_insert_tag(jp->x,"vCard"),"xmlns",NS_VCARD);
jpacket_reset(jp);
xmlnode_insert_node(jp->iq,xmlnode_get_firstchild(xmlnode_get_tag(master->config,"vCard")));
deliver(dpacket_new(jp->x),NULL);
}
}
else
{
log_debug(NAME, "[%s] TERROR_NOTIMPL", FZONE);
jutil_error(jp->x, TERROR_NOTIMPL);
deliver(dpacket_new(jp->x),NULL);
}
return;
}
void _con_packets(void *arg)
{
jpacket jp = (jpacket)arg;
cni master = (cni)jp->aux1;
cnr room;
cnu u, u2;
char *s, *reason;
xmlnode node;
int priority = -1;
int created = 0;
time_t now = time(NULL);
#ifndef _JCOMP
pth_mutex_acquire(&master->lock, 0, NULL);
#else
g_mutex_lock(master->lock);
#endif
if(jp->to->user == NULL)
{
con_server(master, jp);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
log_debug(NAME, "[%s] processing packet %s", FZONE, xmlnode2str(jp->x));
for(s = jp->to->user; *s != '\0'; s++)
*s = tolower(*s);
if((room = g_hash_table_lookup(master->rooms, jid_full(jid_user(jid_fix(jp->to))))) == NULL)
{
log_debug(NAME, "[%s] Room not found (%s)", FZONE, jid_full(jid_user(jp->to)));
if((master->roomlock == 1 && !is_sadmin(master, jp->from)) || master->loader == 0)
{
log_debug(NAME, "[%s] Room building request denied", FZONE);
jutil_error(jp->x, TERROR_MUC_ROOM);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
else if(jp->type == JPACKET_IQ && jpacket_subtype(jp) == JPACKET__GET && NSCHECK(jp->iq, NS_MUC_OWNER))
{
room = con_room_new(master, jid_user(jp->to), jp->from, NULL, NULL, 1, 1, 0);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
xmlnode_free(jp->x);
return;
}
else if(jp->to->resource == NULL)
{
log_debug(NAME, "[%s] Room %s doesn't exist: Returning Bad Request", FZONE, jp->to->user);
jutil_error(jp->x, TERROR_BAD);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
else if(jpacket_subtype(jp) == JPACKET__UNAVAILABLE)
{
log_debug(NAME, "[%s] Room %s doesn't exist: dropping unavailable presence", FZONE, jp->to->user);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
xmlnode_free(jp->x);
return;
}
else
{
if(master->dynamic == -1)
room = con_room_new(master, jid_user(jp->to), jp->from, NULL, NULL, 1, 0, 1);
else
room = con_room_new(master, jid_user(jp->to), jp->from, NULL, NULL, 1, 0, 0);
created = 1;
}
}
u = g_hash_table_lookup(room->remote, jid_full(jid_fix(jp->from)));
if(jpacket_subtype(jp) == JPACKET__ERROR)
{
log_debug(NAME, "[%s] Error Handler: init", FZONE);
if(jp->to->resource == NULL || jp->type != JPACKET_IQ)
{
if(u != NULL && u->localid != NULL)
{
log_debug(NAME, "[%s] Error Handler: Zapping user", FZONE);
node = xmlnode_new_tag("reason");
xmlnode_insert_cdata(node, "Lost connection", -1);
con_user_zap(u, node);
}
else
{
log_debug(NAME, "[%s] Error Handler: No cnu/lid found for user", FZONE);
}
}
xmlnode_free(jp->x);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
if(jp->type == JPACKET_MESSAGE && u == NULL)
{
log_debug(NAME, "[%s] Blocking message from outsider (%s)", FZONE, jid_full(jp->to));
jutil_error(jp->x, TERROR_MUC_OUTSIDE);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
if(jp->type == JPACKET_PRESENCE)
priority = jutil_priority(jp->x);
if(u == NULL && priority >= 0)
u = con_user_new(room, jp->from);
room->last = now;
room->packets++;
if(u != NULL)
{
u->last = now;
u->packets++;
}
if(priority >= 0 && jp->to->resource != NULL)
{
u2 = con_room_usernick(room, jp->to->resource);
if(u2 == u)
{
jp->to = jid_user(jp->to);
xmlnode_put_attrib(jp->x, "to", jid_full(jp->to));
if(u)
{
xmlnode_free(u->presence);
u->presence = xmlnode_dup(jp->x);
}
con_room_process(room, u, jp);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
if(u2 != NULL)
{
log_debug(NAME, "[%s] Nick Conflict (%s)", FZONE, jid_full(jid_user(jp->to)));
jutil_error(jp->x, TERROR_MUC_NICK);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
if(is_registered(master, jid_full(jid_user(jid_fix(u->realid))), jp->to->resource) == -1)
{
log_debug(NAME, "[%s] Nick Conflict with registered nick (%s)", FZONE, jid_full(jid_fix(jp->to)));
jutil_error(jp->x, TERROR_MUC_NICKREG);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
if(is_outcast(room, u->realid) && !is_admin(room, u->realid))
{
log_debug(NAME, "[%s] Blocking Banned user (%s)", FZONE, jid_full(jid_user(jid_fix(jp->to))));
jutil_error(jp->x, TERROR_MUC_BANNED);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
if(room->invitation == 1 && !is_member(room, u->realid) && !is_owner(room, u->realid))
{
jutil_error(jp->x, TERROR_MUC_INVITED);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
if(room->count >= room->maxusers && room->maxusers != 0 && !is_admin(room, u->realid))
{
log_debug(NAME, "[%s] Room over quota - disallowing entry", FZONE);
jutil_error(jp->x, TERROR_MUC_FULL);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
if(room->locked && !is_owner(room, u->realid))
{
log_debug(NAME, "[%s] Room has been locked", FZONE);
jutil_error(jp->x, TERROR_NOTFOUND);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
deliver(dpacket_new(jp->x),NULL);
return;
}
if(u->localid != NULL)
{
xmlnode_free(u->presence);
u->presence = xmlnode_dup(jp->x);
con_user_nick(u, jp->to->resource, NULL);
xmlnode_free(jp->x);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
else if(room->secret == NULL || is_sadmin(master, jp->from))
{
if(NSCHECK(xmlnode_get_tag(jp->x,"x"), NS_MUC))
{
u->legacy = 0;
node = xmlnode_get_tag(jp->x,"x");
xmlnode_hide(node);
if(master->roomlock == -1)
{
created = 0;
}
}
else
{
u->legacy = 1;
created = 0;
}
xmlnode_free(u->presence);
u->presence = xmlnode_dup(jp->x);
jutil_delay(u->presence, NULL);
log_debug(NAME, "[%s] About to enter room, legacy<%d>, presence [%s]", FZONE, u->legacy, xmlnode2str(u->presence));
con_user_enter(u, jp->to->resource, created);
xmlnode_free(jp->x);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
else if(jp->type == JPACKET_PRESENCE)
{
if(NSCHECK(xmlnode_get_tag(jp->x,"x"), NS_MUC))
{
log_debug(NAME, "[%s] Password?", FZONE);
if(j_strcmp(room->secret, xmlnode_get_tag_data(xmlnode_get_tag(jp->x,"x"), "password")) == 0)
{
u->legacy = 0;
node = xmlnode_get_tag(jp->x,"x");
xmlnode_hide(node);
xmlnode_free(u->presence);
u->presence = xmlnode_dup(jp->x);
jutil_delay(u->presence, NULL);
con_user_enter(u, jp->to->resource, created);
xmlnode_free(jp->x);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
}
}
jutil_error(jp->x, TERROR_MUC_PASSWORD);
deliver(dpacket_new(jp->x), NULL);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
if(jpacket_subtype(jp) == JPACKET__UNAVAILABLE)
{
log_debug(NAME, "[%s] Calling user zap", FZONE);
if(u != NULL)
{
reason = xmlnode_get_tag_data(jp->x, "status");
xmlnode_free(u->presence);
u->presence = xmlnode_dup(jp->x);
node = xmlnode_new_tag("reason");
if (reason)
xmlnode_insert_cdata(node, reason, -1);
con_user_zap(u, node);
}
xmlnode_free(jp->x);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
if(u == NULL || u->localid == NULL)
{
if(u == NULL)
{
log_debug(NAME, "[%s] No cnu found for user", FZONE);
}
else
{
log_debug(NAME, "[%s] No lid found for %s", FZONE, jid_full(u->realid));
}
if(jp->to->resource != NULL)
{
jutil_error(jp->x, TERROR_NOTFOUND);
deliver(dpacket_new(jp->x),NULL);
}
else
{
con_room_outsider(room, u, jp);
}
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
if(jp->to->resource != NULL)
{
if((u2 = g_hash_table_lookup(room->local, jp->to->resource)) == NULL && (u2 = con_room_usernick(room, jp->to->resource)) == NULL)
{
jutil_error(jp->x, TERROR_NOTFOUND);
deliver(dpacket_new(jp->x),NULL);
}
else
{
con_user_process(u2, u, jp);
}
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return;
}
con_room_process(room, u, jp);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
}
result con_packets(instance i, dpacket dp, void *arg)
{
cni master = (cni)arg;
jpacket jp;
if(dp == NULL)
{
log_warn(NAME, "[%s] Err: Sent a NULL dpacket!", FZONE);
return r_DONE;
}
if(dp->type == p_ROUTE)
{
log_debug(NAME, "[%s] Rejecting ROUTE packet", FZONE);
deliver_fail(dp,"Illegal Packet");
return r_DONE;
}
else
{
jp = jpacket_new(dp->x);
}
if(jp == NULL)
{
log_warn(NAME, "[%s] Rejecting Illegal Packet", FZONE);
deliver_fail(dp,"Illegal Packet");
return r_DONE;
}
if(jp->type == JPACKET_UNKNOWN || jp->to == NULL)
{
log_warn(NAME, "[%s] Bouncing Bad Packet", FZONE);
jutil_error(jp->x, TERROR_BAD);
deliver(dpacket_new(jp->x),NULL);
return r_DONE;
}
jp->aux1 = (void*)master;
#ifdef _JCOMP
_con_packets((void *)jp);
#else
mtq_send(master->q, jp->p, _con_packets, (void *)jp);
#endif
return r_DONE;
}
void _con_shutdown_rooms(gpointer key, gpointer data, gpointer arg)
{
cnr room = (cnr)data;
if(room == NULL)
{
log_warn(NAME, "[%s] SHUTDOWN: Aborting attempt to clear %s", FZONE, key);
return;
}
#ifdef _JCOMP
if(room->persistent == 1)
xdb_room_set(room);
#endif
con_room_cleanup(room);
}
void con_shutdown(void *arg)
{
cni master = (cni)arg;
if(master->shutdown == 1)
{
log_debug(NAME, "[%s] SHUTDOWN: Already commencing. Aborting attempt", FZONE);
return;
}
else
{
master->shutdown = 1;
}
log_debug(NAME, "[%s] SHUTDOWN: Clearing configuration", FZONE);
xmlnode_free(master->config);
log_debug(NAME, "[%s] SHUTDOWN: Zapping sadmin table", FZONE);
g_hash_table_destroy(master->sadmin);
log_debug(NAME, "[%s] SHUTDOWN: Clear users from rooms", FZONE);
g_hash_table_foreach(master->rooms, _con_shutdown_rooms, NULL);
log_debug(NAME, "[%s] SHUTDOWN: Zapping rooms", FZONE);
g_hash_table_destroy(master->rooms);
free(master->day);
log_debug(NAME, "[%s] SHUTDOWN: Sequence completed", FZONE);
}
void _con_beat_user(gpointer key, gpointer data, gpointer arg)
{
cnu user = (cnu)data;
int now = (int)arg;
if(user == NULL)
{
log_warn(NAME, "[%s] Aborting : NULL cnu for %s", FZONE, key);
return;
}
if(user->localid == NULL && (now - user->last) > 120)
{
log_debug(NAME, "[%s] Marking zombie", FZONE);
g_queue_push_tail(user->room->queue, g_strdup(jid_full(user->realid)));
}
}
void _con_beat_idle(gpointer key, gpointer data, gpointer arg)
{
cnr room = (cnr)data;
int now = (int)arg;
xmlnode node;
char *user_name;
log_debug(NAME, "[%s] HBTICK: Idle check for >%s<", FZONE, key);
if(room == NULL)
{
log_warn(NAME, "[%s] Aborting : NULL cnr for %s", FZONE, key);
return;
}
room->queue = g_queue_new();
g_hash_table_foreach(room->remote, _con_beat_user, arg);
while ((user_name = (char *)g_queue_pop_head(room->queue)) != NULL)
{
node = xmlnode_new_tag("reason");
xmlnode_insert_cdata(node, "Clearing zombie", -1);
con_user_zap(g_hash_table_lookup(room->remote, user_name), node);
log_debug(NAME, "[%s] HBTICK: removed zombie '%s' in the queue", FZONE, user_name);
g_free(user_name);
}
g_queue_free(room->queue);
if(room->persistent == 0 && room->count == 0 && (now - room->last) > 240)
{
log_debug(NAME, "[%s] HBTICK: Locking room and adding %s to remove queue", FZONE, key, now);
room->locked = 1;
g_queue_push_tail(room->master->queue, g_strdup(jid_full(room->id)));
}
}
void _con_beat_logrotate(gpointer key, gpointer data, gpointer arg)
{
cnr room = (cnr)data;
if(room == NULL)
{
log_warn(NAME, "[%s] Aborting : NULL cnr for %s", FZONE, key);
return;
}
if(room->logfile)
{
log_debug(NAME, "[%s] Rotating log for room %s", FZONE, jid_full(room->id));
con_room_log_close(room);
con_room_log_new(room);
}
}
void _con_beat_logupdate(gpointer key, gpointer data, gpointer arg)
{
cnr room = (cnr)data;
char *timestamp = (char*)arg;
if(room == NULL)
{
log_warn(NAME, "[%s] Aborting : NULL cnr for %s", FZONE, key);
return;
}
if(room->logformat == LOG_XHTML && room->logfile)
{
log_debug(NAME, "[%s] Adding anchor >%s< for room %s", FZONE, timestamp, jid_full(room->id));
fprintf(room->logfile, "<a name=\"%s\"></a>\n", timestamp);
fflush(room->logfile);
}
}
result con_beat_update(void *arg)
{
cni master = (cni)arg;
time_t t = time(NULL);
int mins = minuteget(t);
char *tstamp = timeget(t);
char *dstamp = dateget(t);
char *room_name;
log_debug(NAME, "[%s] HBTICK", FZONE);
if(mins % 2 == 0)
{
#ifndef _JCOMP
pth_mutex_acquire(&master->lock, 0, NULL);
#else
g_mutex_lock(master->lock);
#endif
log_debug(NAME, "[%s] HBTICK: Idle check started", FZONE);
master->queue = g_queue_new();
g_hash_table_foreach(master->rooms, _con_beat_idle, (void*)t);
while ((room_name = (char *)g_queue_pop_head(master->queue)) != NULL)
{
log_debug(NAME, "[%s] HBTICK: removed room '%s' in the queue", FZONE, room_name);
con_room_zap(g_hash_table_lookup(master->rooms, room_name));
log_debug(NAME, "[%s] HBTICK: removed room '%s' in the queue", FZONE, room_name);
g_free(room_name);
}
g_queue_free(master->queue);
log_debug(NAME, "[%s] HBTICK: Idle check complete", FZONE);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
}
if(mins % 5 == 0)
{
#ifndef _JCOMP
pth_mutex_acquire(&master->lock, 0, NULL);
#else
g_mutex_lock(master->lock);
#endif
g_hash_table_foreach(master->rooms, _con_beat_logupdate, (void*)tstamp);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
}
free(tstamp);
if(j_strcmp(master->day, dstamp) == 0)
{
free(dstamp);
return r_DONE;
}
free(master->day);
master->day = j_strdup(dstamp);
free(dstamp);
#ifndef _JCOMP
pth_mutex_acquire(&master->lock, 0, NULL);
#else
g_mutex_lock(master->lock);
#endif
g_hash_table_foreach(master->rooms, _con_beat_logrotate, NULL);
#ifndef _JCOMP
pth_mutex_release(&master->lock);
#else
g_mutex_unlock(master->lock);
#endif
return r_DONE;
}
result con_beat_housekeep(void *arg)
{
cni master = (cni)arg;
master->loader = 1;
xdb_rooms_get(master);
return r_UNREG;
}
void conference(instance i, xmlnode x)
{
#ifdef _JCOMP
extern jcr_instance jcr;
#endif
cni master;
xmlnode cfg;
jid sadmin;
xmlnode current;
xmlnode node;
xmlnode tmp;
pool tp;
time_t now = time(NULL);
log_debug(NAME, "[%s] mu-conference loading - Service ID: %s", FZONE, i->id);
tp = pool_new();
log_debug(NAME, "[%s] Malloc: _cni=%d", FZONE, sizeof(_cni));
master = pmalloco(i->p, sizeof(_cni));
master->i = i;
#ifndef _JCOMP
master->xdbc = xdb_cache(i);
cfg = xdb_get(master->xdbc, jid_new(xmlnode_pool(x), "config@-internal"), "jabber:config:conference");
master->q = mtq_new(i->p);
#else
cfg = xmlnode_get_tag(jcr->config, "conference");
#endif
master->loader = 0;
master->start = now;
master->rooms = g_hash_table_new_full(g_str_hash, g_str_equal, ght_remove_key, ght_remove_cnr);
master->history = j_atoi(xmlnode_get_tag_data(cfg,"history"),20);
master->config = xmlnode_dup(cfg);
master->day = dateget(now);
master->logdir = xmlnode_get_tag_data(cfg, "logdir");
if(xmlnode_get_tag(cfg,"public"))
master->public = 1;
if(xmlnode_get_tag(cfg,"defaults"))
master->roomlock = -1;
if(xmlnode_get_tag(cfg,"roomlock"))
master->roomlock = 1;
if(xmlnode_get_tag(cfg,"dynamic"))
master->dynamic = 1;
if(xmlnode_get_tag(cfg,"persistent"))
master->dynamic = -1;
master->sadmin = g_hash_table_new_full(g_str_hash,g_str_equal, ght_remove_key, ght_remove_xmlnode);
if(xmlnode_get_tag(cfg, "sadmin"))
{
node = xmlnode_get_tag(cfg, "sadmin");
for(current = xmlnode_get_firstchild(node); current != NULL; current = xmlnode_get_nextsibling(current))
{
sadmin = jid_new(tp, xmlnode_get_data(current));
if(sadmin != NULL)
{
log_debug(NAME, "[%s] Adding sadmin %s", FZONE, jid_full(sadmin));
tmp = xmlnode_new_tag("sadmin");
g_hash_table_insert(master->sadmin, j_strdup(jid_full(jid_user(jid_fix(sadmin)))), (void*)tmp);
}
}
}
#ifndef _JCOMP
register_phandler(i, o_DELIVER, con_packets, (void*)master);
register_shutdown(con_shutdown,(void *) master);
register_beat(60, con_beat_update, (void *)master);
register_beat(1, con_beat_housekeep, (void *)master);
#else
master->lock = g_mutex_new();
master->loader = 1;
xdb_rooms_get(master);
register_phandler(i, o_DELIVER, con_packets, (void*)master);
register_shutdown(con_shutdown,(void *) master);
g_timeout_add(60000, (GSourceFunc)con_beat_update, (void *)master);
#endif
pool_free(tp);
}