<commit_before>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "Client.h"
#include "TundraLogicModule.h"
#include "KristalliProtocolModule.h"
#include "SyncManager.h"
#include "TundraMessages.h"
#include "MsgLogin.h"
#include "MsgLoginReply.h"
#include "MsgClientJoined.h"
#include "MsgClientLeft.h"
#include "UserConnectedResponseData.h"

#include "LoggingFunctions.h"
#include "CoreStringUtils.h"
#include "SceneAPI.h"
#include "Scene.h"
#include "Application.h"

#include <kNet.h>

#include "MemoryLeakCheck.h"

using namespace kNet;

namespace TundraLogic
{

Client::Client(TundraLogicModule* owner) :
    owner_(owner),
    framework_(owner->GetFramework()),
    loginstate_(NotConnected),
    reconnect_(false),
    client_id_(0)
{
}

Client::~Client()
{
}

void Client::Update(f64 frametime)
{
    // If we aren't a server, check pending login
    if (!owner_->IsServer())
        CheckLogin();
}

void Client::Login(const QUrl& loginUrl)
{
    // We support tundra, http and https scheme login urls
    QString urlScheme = loginUrl.scheme().toLower();
    if (urlScheme.isEmpty())
        return;
    if (urlScheme != "tundra" && urlScheme != "http" && urlScheme != "https")
        return;

    // Make sure to logout to empty the previous properties map.
    if (IsConnected())
        DoLogout();

    // Set properties that the "lower" overload wont be adding:
    // Iterate all query items and parse them to go into the login properties.
    // This will leave percent encoding to the parameters! We remove it by hand from username below!
    QList<QPair<QString, QString> > queryItems = loginUrl.queryItems();
    for (int i=0; i<queryItems.size(); i++)
    {
        QPair<QString, QString> queryItem = queryItems.at(i);
        // Skip the ones that are handled by below logic
        if (queryItem.first == "username" || queryItem.first == "password" || queryItem.first == "protocol")
            continue;
        SetLoginProperty(queryItem.first, queryItem.second);
    }

    // Parse values from url
    QByteArray username = loginUrl.queryItemValue("username").toUtf8();
    QString password = loginUrl.queryItemValue("password");
    QString protocol = loginUrl.queryItemValue("protocol");
    QString address = loginUrl.host();
    int port = loginUrl.port();

    // If the username is more exotic or has spaces, prefer 
    // decoding the percent encoding before it is sent to the server.
    if (username.contains('%'))
        username = QByteArray::fromPercentEncoding(username);

    // Validation: Username and address is the minimal set that with we can login with
    if (username.isEmpty() || address.isEmpty())
        return;
    if (port < 0)
        port = 2345;

    Login(address, port, username, password, protocol);
}

void Client::Login(const QString& address, unsigned short port, const QString& username, const QString& password, const QString &protocol)
{
    if (IsConnected())
        DoLogout();

    // Set properties that the "lower" overload wont be adding.
    SetLoginProperty("username", username);
    SetLoginProperty("password", password);

    QString p = protocol.trimmed().toLower();
    kNet::SocketTransportLayer transportLayer = kNet::InvalidTransportLayer;
    if (p == "tcp")
        transportLayer = kNet::SocketOverTCP;
    else if (p == "udp")
        transportLayer = kNet::SocketOverUDP;
    else
        ::LogInfo("Client::Login: Unrecognized protocol: " + p);
    Login(address, port, transportLayer);
}

void Client::Login(const QString& address, unsigned short port, kNet::SocketTransportLayer protocol)
{
    if (owner_->IsServer())
    {
        ::LogError("Already running a server, cannot login to a world as a client");
        return;
    }

    reconnect_ = false;<commit_msg>Use SocketOverUDP as default when connecting using --login.<commit_after>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "Client.h"
#include "TundraLogicModule.h"
#include "KristalliProtocolModule.h"
#include "SyncManager.h"
#include "TundraMessages.h"
#include "MsgLogin.h"
#include "MsgLoginReply.h"
#include "MsgClientJoined.h"
#include "MsgClientLeft.h"
#include "UserConnectedResponseData.h"

#include "LoggingFunctions.h"
#include "CoreStringUtils.h"
#include "SceneAPI.h"
#include "Scene.h"
#include "Application.h"

#include <kNet.h>

#include "MemoryLeakCheck.h"

using namespace kNet;

namespace TundraLogic
{

Client::Client(TundraLogicModule* owner) :
    owner_(owner),
    framework_(owner->GetFramework()),
    loginstate_(NotConnected),
    reconnect_(false),
    client_id_(0)
{
}

Client::~Client()
{
}

void Client::Update(f64 frametime)
{
    // If we aren't a server, check pending login
    if (!owner_->IsServer())
        CheckLogin();
}

void Client::Login(const QUrl& loginUrl)
{
    // We support tundra, http and https scheme login urls
    QString urlScheme = loginUrl.scheme().toLower();
    if (urlScheme.isEmpty())
        return;
    if (urlScheme != "tundra" && urlScheme != "http" && urlScheme != "https")
        return;

    // Make sure to logout to empty the previous properties map.
    if (IsConnected())
        DoLogout();

    // Set properties that the "lower" overload wont be adding:
    // Iterate all query items and parse them to go into the login properties.
    // This will leave percent encoding to the parameters! We remove it by hand from username below!
    QList<QPair<QString, QString> > queryItems = loginUrl.queryItems();
    for (int i=0; i<queryItems.size(); i++)
    {
        QPair<QString, QString> queryItem = queryItems.at(i);
        // Skip the ones that are handled by below logic
        if (queryItem.first == "username" || queryItem.first == "password" || queryItem.first == "protocol")
            continue;
        SetLoginProperty(queryItem.first, queryItem.second);
    }

    // Parse values from url
    QByteArray username = loginUrl.queryItemValue("username").toUtf8();
    QString password = loginUrl.queryItemValue("password");
    QString protocol = loginUrl.queryItemValue("protocol");
    QString address = loginUrl.host();
    int port = loginUrl.port();

    // If the username is more exotic or has spaces, prefer 
    // decoding the percent encoding before it is sent to the server.
    if (username.contains('%'))
        username = QByteArray::fromPercentEncoding(username);

    // Validation: Username and address is the minimal set that with we can login with
    if (username.isEmpty() || address.isEmpty())
        return;
    if (port < 0)
        port = 2345;

    Login(address, port, username, password, protocol);
}

void Client::Login(const QString& address, unsigned short port, const QString& username, const QString& password, const QString &protocol)
{
    if (IsConnected())
        DoLogout();

    // Set properties that the "lower" overload wont be adding.
    SetLoginProperty("username", username);
    SetLoginProperty("password", password);

    QString p = protocol.trimmed().toLower();
    kNet::SocketTransportLayer transportLayer = kNet::SocketOverUDP;
    if (p == "tcp")
        transportLayer = kNet::SocketOverTCP;
    else if (p == "udp")
        transportLayer = kNet::SocketOverUDP;
    else
    {
        ::LogError("Client::Login: Unrecognized protocol: " + p);
        return;
    }
    Login(address, port, transportLayer);
}

void Client::Login(const QString& address, unsigned short port, kNet::SocketTransportLayer protocol)
{
    if (owner_->IsServer())
    {
        ::LogError("Already running a server, cannot login to a world as a client");
        return;
    }

    reconnect_ = false;
{'fraction_non_alphanumeric': 0.11984055548411984, 'fraction_numerical': 0.0025716857400025716, 'mean_word_length': 3.5752941176470587, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '3386971', 'n_tokens_mistral': 2288, 'n_tokens_neox': 2248, 'n_words': 693}