mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Merge pull request #3648
Diadlo (1): refactor(toxdns): Removed using of toxdns
This commit is contained in:
commit
76c4cf7d39
12
qtox.pro
12
qtox.pro
|
@ -95,7 +95,7 @@ contains(DEFINES, QTOX_PLATFORM_EXT) {
|
|||
# Rules for Windows, Mac OSX, and Linux
|
||||
win32 {
|
||||
RC_FILE = windows/qtox.rc
|
||||
LIBS += -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lsodium -lvpx -lpthread
|
||||
LIBS += -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -lsodium -lvpx -lpthread
|
||||
LIBS += -L$$PWD/libs/lib -lavdevice -lavformat -lavcodec -lavutil -lswscale -lOpenAL32 -lopus
|
||||
LIBS += -lqrencode -lsqlcipher -lcrypto
|
||||
LIBS += -lopengl32 -lole32 -loleaut32 -lvfw32 -lws2_32 -liphlpapi -lgdi32 -lshlwapi -luuid
|
||||
|
@ -106,7 +106,7 @@ win32 {
|
|||
ICON = img/icons/qtox.icns
|
||||
QMAKE_INFO_PLIST = osx/info.plist
|
||||
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lvpx -lopus -framework OpenAL -lavformat -lavdevice -lavcodec -lavutil -lswscale -mmacosx-version-min=10.7
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -lsodium -lvpx -lopus -framework OpenAL -lavformat -lavdevice -lavcodec -lavutil -lswscale -mmacosx-version-min=10.7
|
||||
LIBS += -framework AVFoundation -framework Foundation -framework CoreMedia -framework ApplicationServices
|
||||
LIBS += -lqrencode -lsqlcipher
|
||||
contains(DEFINES, QTOX_PLATFORM_EXT) { LIBS += -framework IOKit -framework CoreFoundation }
|
||||
|
@ -143,12 +143,12 @@ win32 {
|
|||
|
||||
# If we're building a package, static link libtox[core,av] and libsodium, since they are not provided by any package
|
||||
contains(STATICPKG, YES) {
|
||||
LIBS += -L$$PWD/libs/lib/ -lopus -lvpx -lopenal -Wl,-Bstatic -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lavformat -lavdevice -lavcodec -lavutil -lswscale -lz -Wl,-Bdynamic
|
||||
LIBS += -L$$PWD/libs/lib/ -lopus -lvpx -lopenal -Wl,-Bstatic -ltoxcore -ltoxav -ltoxencryptsave -lsodium -lavformat -lavdevice -lavcodec -lavutil -lswscale -lz -Wl,-Bdynamic
|
||||
LIBS += -Wl,-Bstatic -ljpeg -ltiff -lpng -ljasper -lIlmImf -lIlmThread -lIex -ldc1394 -lraw1394 -lHalf -lz -llzma -ljbig
|
||||
LIBS += -Wl,-Bdynamic -lv4l1 -lv4l2 -lavformat -lavcodec -lavutil -lswscale -lusb-1.0
|
||||
LIBS += -lqrencode -lsqlcipher
|
||||
} else {
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lvpx -lsodium -lopenal -lavformat -lavdevice -lavcodec -lavutil -lswscale
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -lvpx -lsodium -lopenal -lavformat -lavdevice -lavcodec -lavutil -lswscale
|
||||
LIBS += -lqrencode -lsqlcipher
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ win32 {
|
|||
}
|
||||
|
||||
contains(JENKINS, YES) {
|
||||
LIBS = ./libs/lib/libtoxav.a ./libs/lib/libvpx.a ./libs/lib/libopus.a ./libs/lib/libtoxdns.a ./libs/lib/libtoxencryptsave.a ./libs/lib/libtoxcore.a ./libs/lib/libopenal.a ./libs/lib/libsodium.a ./libs/lib/libavdevice.a ./libs/lib/libavformat.a ./libs/lib/libavcodec.a ./libs/lib/libavutil.a ./libs/lib/libswscale.a ./libs/lib/libqrencode.a -ldl -lX11 -lXss
|
||||
LIBS = ./libs/lib/libtoxav.a ./libs/lib/libvpx.a ./libs/lib/libopus.a ./libs/lib/libtoxencryptsave.a ./libs/lib/libtoxcore.a ./libs/lib/libopenal.a ./libs/lib/libsodium.a ./libs/lib/libavdevice.a ./libs/lib/libavformat.a ./libs/lib/libavcodec.a ./libs/lib/libavutil.a ./libs/lib/libswscale.a ./libs/lib/libqrencode.a -ldl -lX11 -lXss
|
||||
contains(ENABLE_SYSTRAY_UNITY_BACKEND, YES) {
|
||||
LIBS += -lgobject-2.0 -lappindicator -lgtk-x11-2.0
|
||||
}
|
||||
|
@ -276,7 +276,6 @@ HEADERS += \
|
|||
src/core/recursivesignalblocker.h \
|
||||
src/core/toxcall.h \
|
||||
src/net/toxuri.h \
|
||||
src/net/toxdns.h \
|
||||
src/net/autoupdate.h \
|
||||
src/net/toxme.h \
|
||||
src/net/avatarbroadcaster.h \
|
||||
|
@ -399,7 +398,6 @@ SOURCES += \
|
|||
src/chatlog/pixmapcache.cpp \
|
||||
src/net/autoupdate.cpp \
|
||||
src/net/toxuri.cpp \
|
||||
src/net/toxdns.cpp \
|
||||
src/net/toxme.cpp \
|
||||
src/net/avatarbroadcaster.cpp \
|
||||
src/persistence/historykeeper.cpp \
|
||||
|
|
|
@ -1,256 +0,0 @@
|
|||
/*
|
||||
Copyright © 2014-2015 by The qTox Project
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
qTox is libre software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qTox is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "src/net/toxdns.h"
|
||||
#include "src/core/cdata.h"
|
||||
#include <QMessageBox>
|
||||
#include <QCoreApplication>
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
#include <tox/tox.h>
|
||||
#include <tox/toxdns.h>
|
||||
|
||||
#define TOX_HEX_ID_LENGTH 2*TOX_ADDRESS_SIZE
|
||||
|
||||
/**
|
||||
* @class ToxDNS
|
||||
* @brief Handles tox1 and tox3 DNS queries.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct tox3_server
|
||||
* @brief Represents a tox3 server.
|
||||
*
|
||||
* @var const char* tox3_server::name
|
||||
* @brief Hostname of the server, e.g. toxme.se.
|
||||
*
|
||||
* @var uint8_t* tox3_server::pubkey
|
||||
* @brief Public key of the tox3 server, usually 256bit long.
|
||||
*/
|
||||
|
||||
const ToxDNS::tox3_server ToxDNS::pinnedServers[]
|
||||
{
|
||||
{"toxme.se", (uint8_t[32]){0x5D, 0x72, 0xC5, 0x17, 0xDF, 0x6A, 0xEC, 0x54, 0xF1, 0xE9, 0x77, 0xA6, 0xB6, 0xF2, 0x59, 0x14,
|
||||
0xEA, 0x4C, 0xF7, 0x27, 0x7A, 0x85, 0x02, 0x7C, 0xD9, 0xF5, 0x19, 0x6D, 0xF1, 0x7E, 0x0B, 0x13}},
|
||||
{"utox.org", (uint8_t[32]){0xD3, 0x15, 0x4F, 0x65, 0xD2, 0x8A, 0x5B, 0x41, 0xA0, 0x5D, 0x4A, 0xC7, 0xE4, 0xB3, 0x9C, 0x6B,
|
||||
0x1C, 0x23, 0x3C, 0xC8, 0x57, 0xFB, 0x36, 0x5C, 0x56, 0xE8, 0x39, 0x27, 0x37, 0x46, 0x2A, 0x12}},
|
||||
{"sr.ht", (uint8_t[32]){0x05, 0x08, 0x88, 0xFE, 0x0C, 0x88, 0x29, 0xAA, 0x43, 0xE0, 0xC9, 0xFD, 0x49, 0x6D, 0x6C, 0x4A,
|
||||
0xFE, 0xEF, 0xEB, 0x6D, 0x55, 0x71, 0xF4, 0x2F, 0x30, 0xEB, 0x5F, 0x3B, 0x4C, 0xD9, 0x4F, 0xE5}},
|
||||
{"toxme.io", (uint8_t[32]){ 0x1A, 0x39, 0xE7, 0xA5, 0xD5, 0xFA, 0x9C, 0xF1, 0x55, 0xC7, 0x51, 0x57, 0x0A, 0x32, 0xE6, 0x25,
|
||||
0x69, 0x8A, 0x60, 0xA5, 0x5F, 0x6D, 0x88, 0x02, 0x8F, 0x94, 0x9F, 0x66, 0x14, 0x4F, 0x4F, 0x25 }}
|
||||
};
|
||||
|
||||
void ToxDNS::showWarning(const QString &message)
|
||||
{
|
||||
QMessageBox warning;
|
||||
warning.setWindowTitle("Tox DNS");
|
||||
warning.setText(message);
|
||||
warning.setIcon(QMessageBox::Warning);
|
||||
warning.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to fetch the first entry of the given TXT record.
|
||||
* @param record Record to search.
|
||||
* @param silent May display message boxes on error if silent is false.
|
||||
* @return An empty object on failure. May block for up to ~3s.
|
||||
*/
|
||||
QByteArray ToxDNS::fetchLastTextRecord(const QString& record, bool silent)
|
||||
{
|
||||
QDnsLookup dns;
|
||||
dns.setType(QDnsLookup::TXT);
|
||||
dns.setName(record);
|
||||
dns.lookup();
|
||||
|
||||
int timeout;
|
||||
for (timeout = 0; timeout<30 && !dns.isFinished(); ++timeout)
|
||||
{
|
||||
qApp->processEvents();
|
||||
QThread::msleep(100);
|
||||
}
|
||||
if (timeout >= 30)
|
||||
{
|
||||
dns.abort();
|
||||
if (!silent)
|
||||
showWarning(tr("The connection timed out","The DNS gives the Tox ID associated to toxme.se addresses"));
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
if (dns.error() == QDnsLookup::NotFoundError)
|
||||
{
|
||||
if (!silent)
|
||||
showWarning(tr("This address does not exist","The DNS gives the Tox ID associated to toxme.se addresses"));
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
else if (dns.error() != QDnsLookup::NoError)
|
||||
{
|
||||
if (!silent)
|
||||
showWarning(tr("Error while looking up DNS","The DNS gives the Tox ID associated to toxme.se addresses"));
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
const QList<QDnsTextRecord> textRecords = dns.textRecords();
|
||||
if (textRecords.isEmpty())
|
||||
{
|
||||
if (!silent)
|
||||
showWarning(tr("No text record found", "Error with the DNS"));
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
const QList<QByteArray> textRecordValues = textRecords.last().values();
|
||||
if (textRecordValues.length() != 1)
|
||||
{
|
||||
if (!silent)
|
||||
showWarning(tr("Unexpected number of values in text record", "Error with the DNS"));
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return textRecordValues.first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send query to DNS to find Tox Id.
|
||||
* @note Will *NOT* fallback on queryTox1 anymore.
|
||||
* @param server Server to sending query.
|
||||
* @param record Should look like user@domain.tld.
|
||||
* @param silent If true, there will be no output on error.
|
||||
* @return Tox Id string.
|
||||
*/
|
||||
QString ToxDNS::queryTox3(const tox3_server& server, const QString &record, bool silent)
|
||||
{
|
||||
QByteArray nameData = record.left(record.indexOf('@')).toUtf8(), id, realRecord;
|
||||
QString entry, toxIdStr;
|
||||
int toxIdSize, idx, verx, dns_string_len;
|
||||
const int dns_string_maxlen = 128;
|
||||
|
||||
void* tox_dns3 = tox_dns3_new(server.pubkey);
|
||||
if (!tox_dns3)
|
||||
{
|
||||
qWarning() << "failed to create a tox_dns3 object for "<<server.name<<", using toxdns1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
uint32_t request_id;
|
||||
uint8_t dns_string[dns_string_maxlen];
|
||||
dns_string_len = tox_generate_dns3_string(tox_dns3, dns_string, dns_string_maxlen, &request_id,
|
||||
(uint8_t*)nameData.data(), nameData.size());
|
||||
|
||||
if (dns_string_len < 0) // We can always fallback on toxdns1 if toxdns3 fails
|
||||
{
|
||||
qWarning() << "failed to generate dns3 string for "<<server.name<<", using toxdns1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
|
||||
realRecord = '_'+QByteArray((char*)dns_string, dns_string_len)+"._tox."+server.name;
|
||||
entry = fetchLastTextRecord(realRecord, silent);
|
||||
if (entry.isEmpty())
|
||||
{
|
||||
qWarning() << "Server "<<server.name<<" returned no record, assuming the Tox ID doesn't exist";
|
||||
return toxIdStr;
|
||||
}
|
||||
|
||||
// Check toxdns protocol version
|
||||
verx = entry.indexOf("v=");
|
||||
if (verx!=-1)
|
||||
{
|
||||
verx += 2;
|
||||
int verend = entry.indexOf(';', verx);
|
||||
if (verend!=-1)
|
||||
{
|
||||
QString ver = entry.mid(verx, verend-verx);
|
||||
if (ver != "tox3")
|
||||
{
|
||||
qWarning() << "Server "<<server.name<<" returned a bad version ("<<ver<<"), using toxdns1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get and decrypt the tox id
|
||||
idx = entry.indexOf("id=");
|
||||
if (idx < 0)
|
||||
{
|
||||
qWarning() << "Server "<<server.name<<" returned an empty id, using toxdns1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
|
||||
idx += 3;
|
||||
id = entry.mid(idx).toUtf8();
|
||||
uint8_t toxId[TOX_ADDRESS_SIZE];
|
||||
toxIdSize = tox_decrypt_dns3_TXT(tox_dns3, toxId, (uint8_t*)id.data(), id.size(), request_id);
|
||||
if (toxIdSize < 0) // We can always fallback on toxdns1 if toxdns3 fails
|
||||
{
|
||||
qWarning() << "Failed to decrypt dns3 reply for "<<server.name<<", using toxdns1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
|
||||
tox_dns3_kill(tox_dns3);
|
||||
toxIdStr = CFriendAddress::toString(toxId);
|
||||
return toxIdStr;
|
||||
|
||||
// Centralized error handling, fallback on toxdns1 queries
|
||||
fallbackOnTox1:
|
||||
if (tox_dns3)
|
||||
tox_dns3_kill(tox_dns3);
|
||||
|
||||
return toxIdStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tries to map a text string to a ToxId struct, will query Tox DNS records if necessary.
|
||||
* @param address Adress to search for Tox ID.
|
||||
* @param silent If true, there will be no output on error.
|
||||
* @return Found Tox Id.
|
||||
*/
|
||||
ToxId ToxDNS::resolveToxAddress(const QString &address, bool silent)
|
||||
{
|
||||
if (address.isEmpty())
|
||||
return ToxId();
|
||||
|
||||
if (ToxId::isToxId(address))
|
||||
return ToxId(address);
|
||||
|
||||
// If we're querying one of our pinned servers, do a toxdns3 request directly
|
||||
QString servname = address.mid(address.indexOf('@')+1);
|
||||
for (const ToxDNS::tox3_server& pin : ToxDNS::pinnedServers)
|
||||
{
|
||||
if (servname == pin.name)
|
||||
return ToxId(queryTox3(pin, address, silent));
|
||||
}
|
||||
|
||||
// Otherwise try toxdns3 if we can get a pubkey or fallback to toxdns1
|
||||
QByteArray pubkey = fetchLastTextRecord("_tox."+servname, true);
|
||||
if (!pubkey.isEmpty())
|
||||
{
|
||||
pubkey = QByteArray::fromHex(pubkey);
|
||||
|
||||
QByteArray servnameData = servname.toUtf8();
|
||||
ToxDNS::tox3_server server;
|
||||
server.name = servnameData.data();
|
||||
server.pubkey = (uint8_t*)pubkey.data();
|
||||
return ToxId(queryTox3(server, address, silent));
|
||||
}
|
||||
|
||||
return ToxId();
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
Copyright © 2014-2015 by The qTox Project
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
qTox is libre software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qTox is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef QTOXDNS_H
|
||||
#define QTOXDNS_H
|
||||
|
||||
#include "src/core/corestructs.h"
|
||||
#include "src/core/toxid.h"
|
||||
#include <QDnsLookup>
|
||||
#include <QObject>
|
||||
|
||||
class ToxDNS : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct tox3_server
|
||||
{
|
||||
tox3_server()=default;
|
||||
tox3_server(const char* _name, uint8_t _pk[32]):name{_name},pubkey{_pk}{}
|
||||
|
||||
const char* name;
|
||||
uint8_t* pubkey;
|
||||
};
|
||||
|
||||
public:
|
||||
static ToxId resolveToxAddress(const QString& address, bool silent=true);
|
||||
static QString queryTox3(const tox3_server& server, const QString& record, bool silent=true);
|
||||
|
||||
protected:
|
||||
static void showWarning(const QString& message);
|
||||
ToxDNS()=default;
|
||||
|
||||
private:
|
||||
static QByteArray fetchLastTextRecord(const QString& record, bool silent=true);
|
||||
|
||||
public:
|
||||
static const tox3_server pinnedServers[4];
|
||||
};
|
||||
|
||||
#endif // QTOXDNS_H
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
|
||||
#include "src/net/toxuri.h"
|
||||
#include "src/net/toxdns.h"
|
||||
#include "src/net/toxme.h"
|
||||
#include "src/widget/tool/friendrequestdialog.h"
|
||||
#include "src/nexus.h"
|
||||
|
@ -68,13 +67,11 @@ bool handleToxURI(const QString &toxURI)
|
|||
QString toxId = Toxme::lookup(toxaddr).toString();
|
||||
if (toxId.isEmpty())
|
||||
{
|
||||
toxId = ToxDNS::resolveToxAddress(toxaddr, true).toString();
|
||||
if (toxId.isEmpty())
|
||||
{
|
||||
QMessageBox::warning(0, "qTox", toxaddr + " is not a valid Tox address.");
|
||||
QMessageBox::warning(0, "qTox",
|
||||
ToxURIDialog::tr("%1 is not a valid Toxme address.")
|
||||
.arg(toxaddr));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ToxURIDialog dialog(0, toxaddr, QObject::tr("%1 here! Tox me maybe?",
|
||||
"Default message in Tox URI friend requests. Write something appropriate!")
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "src/nexus.h"
|
||||
#include "src/core/core.h"
|
||||
#include "src/core/cdata.h"
|
||||
#include "src/net/toxdns.h"
|
||||
#include "src/net/toxme.h"
|
||||
#include "src/persistence/settings.h"
|
||||
#include "src/widget/gui.h"
|
||||
|
@ -162,29 +161,20 @@ void AddFriendForm::onSendTriggered()
|
|||
if (!ToxId::isToxId(id))
|
||||
{
|
||||
ToxId toxId = Toxme::lookup(id); // Try Toxme
|
||||
if (toxId.toString().isEmpty()) // If it isn't supported
|
||||
{
|
||||
qDebug() << "Toxme didn't return a ToxID, trying ToxDNS";
|
||||
if (Settings::getInstance().getProxyType() != Settings::ProxyType::ptNone)
|
||||
{
|
||||
QMessageBox::StandardButton btn = QMessageBox::warning(main, "qTox", tr("qTox needs to use the Tox DNS, but can't do it through a proxy.\n\
|
||||
Ignore the proxy and connect to the Internet directly?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
|
||||
if (btn != QMessageBox::Yes)
|
||||
return;
|
||||
}
|
||||
toxId = ToxDNS::resolveToxAddress(id, true); // Use ToxDNS
|
||||
if (toxId.toString().isEmpty())
|
||||
{
|
||||
GUI::showWarning(tr("Couldn't add friend"), tr("This Tox ID does not exist","DNS error"));
|
||||
GUI::showWarning(tr("Couldn't add friend"),
|
||||
tr("This Tox ID does not exist", "Toxme error"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
id = toxId.toString();
|
||||
}
|
||||
|
||||
deleteFriendRequest(id);
|
||||
if (id.toUpper() == Core::getInstance()->getSelfId().toString().toUpper())
|
||||
GUI::showWarning(tr("Couldn't add friend"), tr("You can't add yourself as a friend!","When trying to add your own Tox ID as friend"));
|
||||
GUI::showWarning(tr("Couldn't add friend"),
|
||||
tr("You can't add yourself as a friend!",
|
||||
"When trying to add your own Tox ID as friend"));
|
||||
else
|
||||
emit friendRequested(id, getMessage());
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user