<commit_before>/*
 * Copyright (C) 2010  <NAME>, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

#include "icecomponent.h"

#include "iceagent.h"
#include "icelocaltransport.h"
#include "iceturntransport.h"
#include "objectsession.h"
#include "udpportreserver.h"

#include <QTimer>
#include <QUdpSocket>
#include <QUuid>
#include <QtCrypto>
#include <stdlib.h>

namespace XMPP {
static int calc_priority(int typePref, int localPref, int componentId)
{
    Q_ASSERT(typePref >= 0 && typePref <= 126);
    Q_ASSERT(localPref >= 0 && localPref <= 65535);
    Q_ASSERT(componentId >= 1 && componentId <= 256);

    int priority = (1 << 24) * typePref;
    priority += (1 << 8) * localPref;
    priority += (256 - componentId);
    return priority;
}

class IceComponent::Private : public QObject {
    Q_OBJECT

    struct IceSocket {
        using Ptr = QSharedPointer<IceSocket>;

        IceSocket(QUdpSocket *sock, bool borrowed, IceComponent::Private *ic) : sock(sock), ic(ic), borrowed(borrowed)
        {
        }
        ~IceSocket()
        {
            if (!sock)
                return;

            sock->disconnect(ic);
            if (borrowed) {
                Q_ASSERT(ic->portReserver);
                ic->portReserver->returnSockets(QList<QUdpSocket *>() << sock);
            } else {
                sock->deleteLater();
            }
        }

        QUdpSocket *           sock = nullptr;
        IceComponent::Private *ic   = nullptr;
        bool                   borrowed;
    };

public:
    class Config {
    public:
        QList<Ice176::LocalAddress> localAddrs;
<commit_msg>Ensure unused ICE sockets are returned to the reserver from proper thread<commit_after>/*
 * Copyright (C) 2010  <NAME>, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

#include "icecomponent.h"

#include "iceagent.h"
#include "icelocaltransport.h"
#include "iceturntransport.h"
#include "objectsession.h"
#include "udpportreserver.h"

#include <QTimer>
#include <QUdpSocket>
#include <QUuid>
#include <QtCrypto>
#include <stdlib.h>

namespace XMPP {
static int calc_priority(int typePref, int localPref, int componentId)
{
    Q_ASSERT(typePref >= 0 && typePref <= 126);
    Q_ASSERT(localPref >= 0 && localPref <= 65535);
    Q_ASSERT(componentId >= 1 && componentId <= 256);

    int priority = (1 << 24) * typePref;
    priority += (1 << 8) * localPref;
    priority += (256 - componentId);
    return priority;
}

class IceComponent::Private : public QObject {
    Q_OBJECT

    struct IceSocket {
        using Ptr = QSharedPointer<IceSocket>;

        IceSocket(QUdpSocket *sock, bool borrowed, IceComponent::Private *ic) : sock(sock), ic(ic), borrowed(borrowed)
        {
        }
        ~IceSocket()
        {
            if (!sock)
                return;

            sock->disconnect(ic);
            if (borrowed) {
                Q_ASSERT(ic->portReserver);
                // It's quite common to move Ice176 to another thread, but port reserver is not moved anywhere,
                // so we still need to carefully return not needed sockets.
                QTimer::singleShot(0, ic->portReserver->thread(), [pr = ic->portReserver, sock = sock]() {
                    sock->moveToThread(pr->thread());
                    pr->returnSockets(QList<QUdpSocket *>() << sock);
                });
            } else {
                sock->deleteLater();
            }
        }

        QUdpSocket *           sock = nullptr;
        IceComponent::Private *ic   = nullptr;
        bool                   borrowed;
    };

public:
    class Config {
    public:
        QList<Ice176::LocalAddress> localAddrs;

{'fraction_non_alphanumeric': 0.1054456455231491, 'fraction_numerical': 0.013461146236997757, 'mean_word_length': 2.5587808417997095, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 43, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3088196', 'n_tokens_mistral': 1471, 'n_tokens_neox': 1369, 'n_words': 464}