示例#1
0
void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users)
{
	bool created;
	Channel *c = Channel::FindOrCreate(chan, created, ts ? ts : Anope::CurTime);
	bool keep_their_modes = true;

	if (created)
		c->syncing = true;
	/* Some IRCds do not include a TS */
	else if (!ts)
		;
	/* Our creation time is newer than what the server gave us, so reset the channel to the older time */
	else if (c->creation_time > ts)
	{
		c->creation_time = ts;
		c->Reset();
	}
	/* Their TS is newer, don't accept any modes from them */
	else if (ts > c->creation_time)
		keep_their_modes = false;

	/* Update the modes for the channel */
	if (keep_their_modes && !modes.empty())
		/* If we are syncing, mlock is checked later in Channel::Sync. It is important to not check it here
		 * so that Channel::SetCorrectModes can correctly detect the presence of channel mode +r.
		 */
		c->SetModesInternal(source, modes, ts, !c->syncing);

	for (std::list<SJoinUser>::const_iterator it = users.begin(), it_end = users.end(); it != it_end; ++it)
	{
		const ChannelStatus &status = it->first;
		User *u = it->second;
		keep_their_modes = ts <= c->creation_time; // OnJoinChannel can call modules which can modify this channel's ts

		if (c->FindUser(u))
			continue;

		/* Add the user to the channel */
		c->JoinUser(u, keep_their_modes ? &status : NULL);

		/* Check if the user is allowed to join */
		if (c->CheckKick(u))
			continue;

		/* Set whatever modes the user should have, and remove any that
		 * they aren't allowed to have (secureops etc).
		 */
		c->SetCorrectModes(u, true);

		EventManager::Get()->Dispatch(&Event::JoinChannel::OnJoinChannel, u, c);
	}

	/* Channel is done syncing */
	if (c->syncing)
	{
		/* Sync the channel (mode lock, topic, etc) */
		/* the channel is synced when the netmerge is complete */
		Server *src = source.GetServer() ? source.GetServer() : Me;
		if (src && src->IsSynced())
		{
			c->Sync();

			if (c->CheckDelete())
				delete c;
		}
	}
}
示例#2
0
	bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> &params)
	{
		Channel *c = findchan(params[1]);
		time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0;
		bool keep_their_modes = true;

		if (!c)
		{
			c = new Channel(params[1], ts);
			c->SetFlag(CH_SYNCING);
		}
		/* Our creation time is newer than what the server gave us */
		else if (c->creation_time > ts)
		{
			c->creation_time = ts;
			c->Reset();
		}
		/* Their TS is newer than ours, our modes > theirs, unset their modes if need be */
		else if (ts > c->creation_time)
			keep_their_modes = false;

		/* If we need to keep their modes, and this SJOIN string contains modes */
		if (keep_their_modes && params.size() >= 4)
		{
			/* Set the modes internally */
			Anope::string modes;
			for (unsigned i = 2; i < params.size(); ++i)
				modes += " " + params[i];
			if (!modes.empty())
				modes.erase(modes.begin());
			c->SetModesInternal(NULL, modes);
		}

		/* For some reason, bahamut will send a SJOIN from the user joining a channel
		 * if the channel already existed
		 */
		if (!c->HasFlag(CH_SYNCING) && params.size() == 2)
		{
			User *u = finduser(source);
			if (!u)
				Log(LOG_DEBUG) << "SJOIN for nonexistant user " << source << " on " << c->name;
			else
			{
				EventReturn MOD_RESULT;
				FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));

				/* Add the user to the channel */
				c->JoinUser(u);

				/* Now set whatever modes this user is allowed to have on the channel */
				chan_set_correct_modes(u, c, 1);

				/* Check to see if modules want the user to join, if they do
				 * check to see if they are allowed to join (CheckKick will kick/ban them)
				 * Don't trigger OnJoinChannel event then as the user will be destroyed
				 */
				if (MOD_RESULT == EVENT_STOP && (!c->ci || !c->ci->CheckKick(u)))
				{
					FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
				}
			}
		}
		else
		{
			spacesepstream sep(params[params.size() - 1]);
			Anope::string buf;
			while (sep.GetToken(buf))
			{
				std::list<ChannelMode *> Status;
				char ch;

				/* Get prefixes from the nick */
				while ((ch = ModeManager::GetStatusChar(buf[0])))
				{
					buf.erase(buf.begin());
					ChannelMode *cm = ModeManager::FindChannelModeByChar(ch);
					if (!cm)
					{
						Log() << "Received unknown mode prefix " << cm << " in SJOIN string";
						continue;
					}

					if (keep_their_modes)
						Status.push_back(cm);
				}

				User *u = finduser(buf);
				if (!u)
				{
					Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name;
					continue;
				}

				EventReturn MOD_RESULT;
				FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));

				/* Add the user to the channel */
				c->JoinUser(u);

				/* Update their status internally on the channel
				 * This will enforce secureops etc on the user
				 */
				for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
					c->SetModeInternal(*it, buf);

				/* Now set whatever modes this user is allowed to have on the channel */
				chan_set_correct_modes(u, c, 1);

				/* Check to see if modules want the user to join, if they do
				 * check to see if they are allowed to join (CheckKick will kick/ban them)
				 * Don't trigger OnJoinChannel event then as the user will be destroyed
				 */
				if (MOD_RESULT != EVENT_STOP && c->ci && c->ci->CheckKick(u))
					continue;

				FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
			}
		}

		/* Channel is done syncing */
		if (c->HasFlag(CH_SYNCING))
		{
			/* Unset the syncing flag */
			c->UnsetFlag(CH_SYNCING);
			c->Sync();
		}

		return true;
	}
示例#3
0
bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
{
    int priority = GetPriority(sound);

    // Seeks a channel used which sound is stopped.
    for (auto it : m_channels)
    {
        if (it.second->IsPlaying())
        {
            continue;
        }
        if (it.second->GetSoundType() != sound)
        {
            continue;
        }

        it.second->SetPriority(priority);
        it.second->Reset();
        channel = it.first;
        bAlreadyLoaded = it.second->IsLoaded();
        return true;
    }

    // just add a new channel if we dont have any
    if (m_channels.size() == 0)
    {
        Channel *chn = new Channel();
        // check if we channel ready to play music, if not report error
        if (chn->IsReady())
        {
            chn->SetPriority(priority);
            chn->Reset();
            m_channels[1] = chn;
            channel = 1;
            bAlreadyLoaded = false;
            return true;
        }
        delete chn;
        GetLogger()->Error("Could not open channel to play sound!\n");
        return false;
    }

    // Assigns new channel within limit
    if (m_channels.size() < m_channels_limit)
    {
        auto it = m_channels.end();
        it--;
        int i = (*it).first;
        while (++i)
        {
            if (m_channels.find(i) == m_channels.end())
            {
                Channel *chn = new Channel();
                // check if channel is ready to play music, if not destroy it and seek free one
                if (chn->IsReady())
                {
                    chn->SetPriority(priority);
                    chn->Reset();
                    m_channels[++i] = chn;
                    channel = i;
                    bAlreadyLoaded = false;
                    return true;
                }
                delete chn;
                GetLogger()->Debug("Could not open additional channel to play sound!\n");
            }
        }
    }

    int lowerOrEqual = -1;
    for (auto it : m_channels)
    {
        if (it.second->GetPriority() < priority)
        {
            GetLogger()->Debug("Sound channel with lower priority will be reused.\n");
            channel = it.first;
            it.second->Reset();
            return true;
        }
        if (it.second->GetPriority() <= priority)
            lowerOrEqual = it.first;
    }

    if (lowerOrEqual != -1)
    {
        channel = lowerOrEqual;
        m_channels[channel]->Reset();
        GetLogger()->Debug("Sound channel with lower or equal priority will be reused.\n");
        return true;
    }

    GetLogger()->Debug("Could not find free buffer to use.\n");
    return false;
}