⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conference.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(room->invitation == 1 && !is_member(room, u->realid) && !is_owner(room, u->realid))
	{
	    jutil_error(jp->x, TERROR_MUC_INVITED);
	    deliver(dpacket_new(jp->x),NULL);
	    return;
	}

	/* Room is full, return full room error */
	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);
	    deliver(dpacket_new(jp->x),NULL);
	    return;
	}

	/* Room has been locked against entry */
	if(room->locked && !is_owner(room, u->realid))
	{
	    log_debug(NAME, "[%s] Room has been locked", FZONE);
	    jutil_error(jp->x, TERROR_NOTFOUND);
	    deliver(dpacket_new(jp->x),NULL);
	    return;
	}

	/* User already in room, simply a nick change */
        if(u->localid != NULL)
        {
            xmlnode_free(u->presence);
	    u->presence = xmlnode_dup(jp->x);
            con_user_nick(u, jp->to->resource, NULL); /* broadcast nick rename */
	    xmlnode_free(jp->x);
	    return;

        }
	else if(room->secret == NULL || is_sadmin(master, jp->from)) /* No password required, just go right in, or you're an sadmin */
	{
	    if(NSCHECK(xmlnode_get_tag(jp->x,"x"), NS_MUC))
	    {
		/* Set legacy value to room value */
	        u->legacy = 0;
		node = xmlnode_get_tag(jp->x,"x");
		xmlnode_hide(node);
              
                /* Enable room defaults automatically */ 
                if(master->roomlock == -1)
                {
                    created = 0;
                }

	    }
	    else
	    {
		u->legacy = 1;
		created = 0; /* Override created flag for non-MUC compliant clients */
	    } 

            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); /* join the room */

	    xmlnode_free(jp->x);
	    return;

        }
	else if(jp->type == JPACKET_PRESENCE) /* Hopefully you are including a password, this room is locked */
	{
	    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)
		{
		    /* Set legacy value to room value */
		    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); /* join the room */

		    xmlnode_free(jp->x);
		    return;
		}
	    }
	}

	/* No password found, room is password protected. Return password error */
        jutil_error(jp->x, TERROR_MUC_PASSWORD);
        deliver(dpacket_new(jp->x), NULL);
        return;
    }

    /* kill any user sending unavailable presence */
    if(jpacket_subtype(jp) == JPACKET__UNAVAILABLE)
    {
	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);
        return;
    }

    /* handle errors */
    if(jpacket_subtype(jp) == JPACKET__ERROR)
    {
        /* only allow iq errors that are to a resource (direct-chat) */
        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);
        return;
    }

    /* not in the room yet? foo */
    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(jid_fix(u->realid)));
	}

        if(jp->to->resource != NULL)
        {
            jutil_error(jp->x, TERROR_NOTFOUND);
            deliver(dpacket_new(jp->x),NULL);
	    return;
        }
	else
	{
            con_room_outsider(room, u, jp); /* non-participants get special treatment */
        }
	
        return;
    }

    /* packets to a specific resource?  one on one chats, browse lookups, etc */
    if(jp->to->resource != NULL)
    {
        if((u2 = htb_get(&room->local, jp->to->resource)) == NULL && (u2 = con_room_usernick(room, jp->to->resource)) == NULL) /* gotta have a recipient */
        {
            jutil_error(jp->x, TERROR_NOTFOUND);
            deliver(dpacket_new(jp->x),NULL);
	    return;
        }
	else
	{
            con_user_process(u2, u, jp);
        }
        
	return;
    }

    /* finally, handle packets just to a room from a participant, msgs, pres, iq browse/conferencing, etc */
    con_room_process(room, u, jp);

}

/* phandler callback, send packets to another server */
result con_packets(instance i, dpacket dp, void *arg)
{
    cni master = (cni)arg;
    jpacket jp;

    /* routes are from dnsrv w/ the needed ip */
    if(dp->type == p_ROUTE)
        jp = jpacket_new(xmlnode_get_firstchild(dp->x));
    else
        jp = jpacket_new(dp->x);

    /* if the delivery failed */
    if(jp == NULL)
    {
        deliver_fail(dp,"Illegal Packet");
        return r_DONE;
    }

    /* bad packet??? ick */
    if(jp->type == JPACKET_UNKNOWN || jp->to == NULL)
    {
        jutil_error(jp->x, TERROR_BAD);
        deliver(dpacket_new(jp->x),NULL);
        return r_DONE;
    }

    /* we want things processed in order, and don't like re-entrancy! */
    jp->aux1 = (void*)master;
    mtq_send(master->q, jp->p, _con_packets, (void *)jp);
    return r_DONE;
}

void _con_shutdown_rooms(const char *key, void *data, void *arg)
{
    cnr room = (cnr)data;

    con_room_cleanup(room);
}

void con_shutdown(void *arg)
{
    cni master = (cni)arg;

    log_debug(NAME, "[%s] SHUTDOWN: Clearing configuration", FZONE);
    xmlnode_free(master->config);
    log_debug(NAME, "[%s] SHUTDOWN: Zapping sadmin table", FZONE);
    htb_free(&master->sadmin);
    log_debug(NAME, "[%s] SHUTDOWN: Clear users from rooms", FZONE);
    htb_walk(&master->rooms, _con_shutdown_rooms, NULL);
    log_debug(NAME, "[%s] SHUTDOWN: Zapping rooms", FZONE);
    htb_free(&master->rooms);
    log_debug(NAME, "[%s] SHUTDOWN: Sequence completed", FZONE);
}

/* callback for walking each user in a room */
void _con_beat_user(const char *key, void *data, void *arg)
{
    cnu user = (cnu)data;
    int now = (int)arg;
    xmlnode node;

    if(user->localid == NULL && (now - user->last) > 120)
    {
	log_debug(NAME, "[%s] Removing zombie", FZONE);

	node = xmlnode_new_tag("reason");
        xmlnode_insert_cdata(node, "Clearing zombie", -1);
        con_user_zap(user, node);
    }
}

/* callback for walking each room */
void _con_beat_idle(const char *key, void *data, void *arg)
{
    cnr room = (cnr)data;
    int now = (int)arg;

    htb_walk(&room->remote, _con_beat_user, arg); /* makes sure nothing stale is in the room */

    if(room->persistant == 0 && room->count == 0 && (now - room->last) > 240)
        con_room_zap(room);
}

/* heartbeat checker for timed out idle rooms */
void _con_beat_logrotate(const char *key, void *data, void *arg)
{
    cnr room = (cnr)data;

    
    if(room->logfile)
    {
	log_debug(NAME, "[%s] Rotating log for room %s", FZONE, jid_full(jid_fix(room->id)));

	con_room_log_close(room);
	con_room_log_new(room);
    }
}

/* heartbeat checker for timed out idle rooms */
void _con_beat_logupdate(const char *key, void *data, void *arg)
{
    cnr room = (cnr)data;
    char *timestamp = (char*)arg;

    if(room->logformat == LOG_XHTML && room->logfile)
    {
	log_debug(NAME, "[%s] Adding anchor >%s< for room %s", FZONE, timestamp, jid_full(jid_fix(room->id)));
	fprintf(room->logfile, "<a name=\"%s\"></a>\n", timestamp);
	fflush(room->logfile);
    }
}

/* heartbeat checker for maintainance */
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);

    /* Check for timed out idle rooms */
    if(mins % 2 == 0)
    {
	htb_walk(&master->rooms, _con_beat_idle,(void*)t);
    }

    /* Check for logfiles requiring updating */
    if(mins % 5 == 0)
    {
        htb_walk(&master->rooms,_con_beat_logupdate,(void*)tstamp);
        free(tstamp);
    }

    if(j_strcmp(master->day, dstamp) == 0)
    {
        free(dstamp);
        return r_DONE;
    }

    master->day = pstrdup(master->i->p, dstamp);
    free(dstamp);

    htb_walk(&master->rooms, _con_beat_logrotate, NULL);
    return r_DONE;
}

/* heartbeat checker for miscellaneous tasks */
result con_beat_housekeep(void *arg)
{
    cni master = (cni)arg;

    master->loader = 1;
    xdb_rooms_get(master);

    /* Remove unwanted heartbeat */
    return r_UNREG;
}

/*** everything starts here ***/
void conference(instance i, xmlnode x)
{
    cni master;
    xmlnode cfg;
    jid sadmin;
    xmlnode current;
    xmlnode node;
    time_t now = time(NULL);

    log_debug(NAME, "[%s] mu-conference loading %s %d", FZONE, i->id, i->type);

    /* Allocate space for cni struct and link to instance */
    log_debug(NAME, "[%s] Malloc: _cni=%d", FZONE, sizeof(_cni));
    master = pmalloco(i->p, sizeof(_cni));
    master->i = i;

    /* Set up xdb interface */
    master->xdbc = xdb_cache(i);

    /* get the config */
    cfg = xdb_get(master->xdbc, jid_new(xmlnode_pool(x), "config@-internal"), "jabber:config:conference");

    /* Parse config and initialise variables */
    master->q = mtq_new(i->p);
    master->maxhash = j_atoi(xmlnode_get_tag_data(cfg,"maxhash"),401);

    /* Check Hash size is prime */
    if(isPrime(master->maxhash))
    {
        log_debug(NAME, "[%s] Prime check passed", FZONE);
    }
    else
    {
        log_debug(NAME, "[%s] Prime check failed - setting to 401", FZONE);
	master->maxhash = 401;
    }

    master->loader = 0;
    master->start = now;

    htb_init_table(&master->rooms, master->maxhash);

    master->history = j_atoi(xmlnode_get_tag_data(cfg,"history"),10);
    master->config = cfg;					/* Store a copy of the config for later usage */
    master->day = pstrdup(i->p, dateget(now)); 				/* Used to determine when to rotate logs */
    master->logdir = xmlnode_get_tag_data(cfg, "logdir");	/* Directory where to store logs */

    /* If requested, set default room state to 'public', otherwise will default to 'private */
    if(xmlnode_get_tag(cfg,"public"))
        master->public = 1;

    /* If requested, rooms are given a default configuration */
    if(xmlnode_get_tag(cfg,"defaults"))
        master->roomlock = -1;

    /* If requested, stop any new rooms being created */
    if(xmlnode_get_tag(cfg,"roomlock"))
        master->roomlock = 1;

    /* If requested, stop any new rooms being created */
    if(xmlnode_get_tag(cfg,"dynamic"))
        master->dynamic = 1;

    /* If requested, stop any new rooms being created */
    if(xmlnode_get_tag(cfg,"persistent"))
        master->dynamic = -1;

    htb_init_table(&master->sadmin, master->maxhash);

    /* sadmin code */
    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(i->p, xmlnode_get_data(current));

	    if(sadmin != NULL)
	    {
                log_debug(NAME, "[%s] Adding sadmin %s", FZONE, jid_full(sadmin));
		htb_put(&master->sadmin, jid_full(jid_user(jid_fix(sadmin))), (void*)1);
	    }
	}
    }

    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);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -