mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Implement tox3 support, keep tox1 as silent fallback
This commit is contained in:
parent
de3befe116
commit
0b6a4a6481
21
qtox.pro
21
qtox.pro
|
@ -63,43 +63,32 @@ contains(JENKINS,YES) {
|
|||
# Rules for Windows, Mac OSX, and Linux
|
||||
win32 {
|
||||
RC_FILE = windows/qtox.rc
|
||||
LIBS += -liphlpapi -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -lvpx -lpthread
|
||||
LIBS += -liphlpapi -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lvpx -lpthread
|
||||
LIBS += -L$$PWD/libs/lib -lopencv_core248 -lopencv_highgui248 -lopencv_imgproc248 -lOpenAL32 -lopus
|
||||
LIBS += -lz -lopengl32 -lole32 -loleaut32 -luuid -lvfw32 -ljpeg -ltiff -lpng -ljasper -lIlmImf -lHalf -lws2_32
|
||||
} else {
|
||||
macx {
|
||||
ICON = img/icons/qtox.icns
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -lsodium -lvpx -framework OpenAL -lopencv_core -lopencv_highgui
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lvpx -framework OpenAL -lopencv_core -lopencv_highgui
|
||||
} else {
|
||||
# If we're building a package, static link libtox[core,av] and libsodium, since they are not provided by any package
|
||||
contains(STATICPKG, YES) {
|
||||
target.path = /usr/bin
|
||||
INSTALLS += target
|
||||
LIBS += -L$$PWD/libs/lib/ -lopus -lvpx -lopenal -Wl,-Bstatic -ltoxcore -ltoxav -ltoxencryptsave -lsodium -lopencv_highgui -lopencv_imgproc -lopencv_core -lz -Wl,-Bdynamic
|
||||
LIBS += -L$$PWD/libs/lib/ -lopus -lvpx -lopenal -Wl,-Bstatic -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lopencv_highgui -lopencv_imgproc -lopencv_core -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
|
||||
|
||||
} else {
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -lvpx -lopenal -lopencv_core -lopencv_highgui -lopencv_imgproc
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lvpx -lopenal -lopencv_core -lopencv_highgui -lopencv_imgproc
|
||||
}
|
||||
|
||||
contains(JENKINS, YES) {
|
||||
LIBS = ./libs/lib/libsodium.a ./libs/lib/libtoxcore.a ./libs/lib/libtoxav.a ./libs/lib/libtoxencryptsave.a ./libs/lib/libvpx.a ./libs/lib/libopus.a -lopencv_core -lopencv_highgui -lopenal
|
||||
LIBS = ./libs/lib/libsodium.a ./libs/lib/libtoxcore.a ./libs/lib/libtoxav.a ./libs/lib/libtoxencryptsave.a ./libs/lib/libtoxdns.a ./libs/lib/libvpx.a ./libs/lib/libopus.a -lopencv_core -lopencv_highgui -lopenal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#### Static linux build
|
||||
#LIBS += -Wl,-Bstatic -ltoxcore -ltoxav -lsodium -lvpx -lopus \
|
||||
# -lgstbase-0.10 -lgstreamer-0.10 -lgmodule-2.0 -lgstaudio-0.10 -lxml2 \
|
||||
# -lX11-xcb -lXi -lxcb-render-util -lxcb-glx -lxcb-render -ldbus-1 \
|
||||
# -lxcb -lXau -lXdmcp -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape \
|
||||
# -lxcb-keysyms -lxcb-xkb -lfontconfig -lfreetype -lXrender -lXext -lX11 \
|
||||
# -lpng -lz -licui18n -licuuc -licudata -lm -lgthread-2.0 \
|
||||
# -pthread -lrt -lGL -lpthread -Wl,-Bdynamic -ldl -lc
|
||||
#QMAKE_CXXFLAGS += -Os -flto -static-libstdc++ -static-libgcc
|
||||
|
||||
HEADERS += src/widget/form/addfriendform.h \
|
||||
src/widget/form/chatform.h \
|
||||
src/widget/form/groupchatform.h \
|
||||
|
|
|
@ -18,12 +18,25 @@
|
|||
|
||||
#include <QFont>
|
||||
#include <QMessageBox>
|
||||
#include <QThread>
|
||||
#include <tox/tox.h>
|
||||
#include "ui_mainwindow.h"
|
||||
#include "src/core.h"
|
||||
#include "src/misc/cdata.h"
|
||||
#include "tox/toxdns.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define TOX_ID_LENGTH 2*TOX_FRIEND_ADDRESS_SIZE
|
||||
|
||||
const AddFriendForm::tox3_server AddFriendForm::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}}
|
||||
};
|
||||
|
||||
AddFriendForm::AddFriendForm() : dns(this)
|
||||
{
|
||||
dns.setType(QDnsLookup::TXT);
|
||||
|
@ -50,7 +63,6 @@ AddFriendForm::AddFriendForm() : dns(this)
|
|||
headLayout.addWidget(&headLabel);
|
||||
|
||||
connect(&sendButton, SIGNAL(clicked()), this, SLOT(onSendTriggered()));
|
||||
connect(&dns, SIGNAL(finished()), this, SLOT(handleDnsLookup()));
|
||||
}
|
||||
|
||||
AddFriendForm::~AddFriendForm()
|
||||
|
@ -99,50 +111,102 @@ void AddFriendForm::onSendTriggered()
|
|||
showWarning(tr("You can't add yourself as a friend!","When trying to add your own Tox ID as friend"));
|
||||
else
|
||||
emit friendRequested(id, getMessage());
|
||||
this->toxId.setText("");
|
||||
this->message.setText("");
|
||||
this->toxId.clear();
|
||||
this->message.clear();
|
||||
} else {
|
||||
id = id.replace("@", "._tox.");
|
||||
dns.setName(id);
|
||||
dns.lookup();
|
||||
// If we're querying one of our pinned server, do a tox3 request directly
|
||||
QString servname = id.mid(id.indexOf('@')+1);
|
||||
for (const AddFriendForm::tox3_server& pin : pinnedServers)
|
||||
{
|
||||
if (servname == pin.name)
|
||||
{
|
||||
queryTox3(pin, id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AddFriendForm::handleDnsLookup()
|
||||
// Otherwise try tox3 if we can get a pubkey or fallback to tox1
|
||||
QByteArray pubkey = fetchLastTextRecord("_tox."+servname);
|
||||
if (!pubkey.isEmpty())
|
||||
{
|
||||
const QString idKeyWord("id="), verKeyWord("v=");
|
||||
QByteArray servnameData = servname.toUtf8();
|
||||
AddFriendForm::tox3_server server;
|
||||
server.name = servnameData.data();
|
||||
server.pubkey = (uint8_t*)pubkey.data();
|
||||
queryTox3(server, id);
|
||||
}
|
||||
else
|
||||
{
|
||||
queryTox1(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray AddFriendForm::fetchLastTextRecord(const QString& record, bool silent)
|
||||
{
|
||||
QByteArray result;
|
||||
|
||||
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 result;
|
||||
}
|
||||
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
||||
const QList<QDnsTextRecord> textRecords = dns.textRecords();
|
||||
if (textRecords.length() != 1) {
|
||||
showWarning(tr("Unexpected number of text records", "Error with the DNS"));
|
||||
return;
|
||||
if (textRecords.isEmpty()) {
|
||||
if (!silent)
|
||||
showWarning(tr("No text record found", "Error with the DNS"));
|
||||
return result;
|
||||
}
|
||||
|
||||
const QList<QByteArray> textRecordValues = textRecords.first().values();
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
||||
const QString entry(textRecordValues.first());
|
||||
result = textRecordValues.first();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check toxdns protocol version, we only support tox1 for now
|
||||
int verx = entry.indexOf(verKeyWord);
|
||||
void AddFriendForm::queryTox1(const QString& record)
|
||||
{
|
||||
QString realRecord = record;
|
||||
realRecord.replace("@", "._tox.");
|
||||
const QString entry = fetchLastTextRecord(realRecord, false);
|
||||
if (entry.isEmpty())
|
||||
return;
|
||||
|
||||
// Check toxdns protocol version
|
||||
int verx = entry.indexOf("v=");
|
||||
if (verx) {
|
||||
verx += verKeyWord.size();
|
||||
verx += 2;
|
||||
int verend = entry.indexOf(';', verx);
|
||||
if (verend)
|
||||
{
|
||||
QString ver = entry.mid(verx, verend);
|
||||
QString ver = entry.mid(verx, verend-verx);
|
||||
if (ver != "tox1")
|
||||
{
|
||||
showWarning(tr("The version of Tox DNS used by this server is not supported", "Error with the DNS"));
|
||||
|
@ -151,13 +215,14 @@ void AddFriendForm::handleDnsLookup()
|
|||
}
|
||||
}
|
||||
|
||||
int idx = entry.indexOf(idKeyWord);
|
||||
// Get the tox id
|
||||
int idx = entry.indexOf("id=");
|
||||
if (idx < 0) {
|
||||
showWarning(tr("The DNS lookup does not contain any Tox ID", "Error with the DNS"));
|
||||
return;
|
||||
}
|
||||
|
||||
idx += idKeyWord.length();
|
||||
idx += 3;
|
||||
if (entry.length() < idx + static_cast<int>(TOX_ID_LENGTH)) {
|
||||
showWarning(tr("The DNS lookup does not contain a valid Tox ID", "Error with the DNS"));
|
||||
return;
|
||||
|
@ -171,6 +236,86 @@ void AddFriendForm::handleDnsLookup()
|
|||
|
||||
// finally we got it
|
||||
emit friendRequested(friendAdress, getMessage());
|
||||
this->toxId.setText("");
|
||||
this->message.setText("");
|
||||
this->toxId.clear();
|
||||
this->message.clear();
|
||||
}
|
||||
|
||||
void AddFriendForm::queryTox3(const tox3_server& server, QString &record)
|
||||
{
|
||||
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() << "queryTox3: failed to create a tox_dns3 object for "<<server.name<<", using tox1 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 tox1 if toxdns3 fails
|
||||
{
|
||||
qWarning() << "queryTox3: failed to generate dns3 string for "<<server.name<<", using tox1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
|
||||
realRecord = '_'+QByteArray((char*)dns_string, dns_string_len)+"._tox."+server.name;
|
||||
entry = fetchLastTextRecord(realRecord, false);
|
||||
if (entry.isEmpty())
|
||||
{
|
||||
qWarning() << "queryTox3: Server "<<server.name<<" returned no record, using tox1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
|
||||
// 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() << "queryTox3: Server "<<server.name<<" returned a bad version ("<<ver<<"), using tox1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get and decrypt the tox id
|
||||
idx = entry.indexOf("id=");
|
||||
if (idx < 0) {
|
||||
qWarning() << "queryTox3: Server "<<server.name<<" returned an empty id, using tox1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
|
||||
idx += 3;
|
||||
id = entry.mid(idx).toUtf8();
|
||||
uint8_t toxId[TOX_FRIEND_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 tox1 if toxdns3 fails
|
||||
{
|
||||
qWarning() << "queryTox3: failed to decrypt dns3 reply for "<<server.name<<", using tox1 as a fallback";
|
||||
goto fallbackOnTox1;
|
||||
}
|
||||
|
||||
tox_dns3_kill(tox_dns3);
|
||||
toxIdStr = CFriendAddress::toString(toxId);
|
||||
emit friendRequested(toxIdStr, getMessage());
|
||||
this->toxId.clear();
|
||||
this->message.clear();
|
||||
return;
|
||||
|
||||
// Centralized error handling, fallback on tox1 queries
|
||||
fallbackOnTox1:
|
||||
if (tox_dns3)
|
||||
tox_dns3_kill(tox_dns3);
|
||||
queryTox1(record);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,24 @@ signals:
|
|||
|
||||
private slots:
|
||||
void onSendTriggered();
|
||||
void handleDnsLookup();
|
||||
|
||||
private:
|
||||
struct tox3_server
|
||||
{
|
||||
tox3_server()=default;
|
||||
tox3_server(const char* _name, uint8_t _pk[32]):name{_name},pubkey{_pk}{}
|
||||
|
||||
const char* name; ///< Hostname of the server, e.g. toxme.se
|
||||
uint8_t* pubkey; ///< Public key of the tox3 server, usually 256bit long
|
||||
};
|
||||
|
||||
private:
|
||||
void queryTox1(const QString& record); ///< Record should look like user@domain.tld
|
||||
void queryTox3(const tox3_server& server, QString& record); ///< Record should look like user@domain.tld, may fallback on queryTox1
|
||||
/// Try to fetch the first entry of the given TXT record
|
||||
/// Returns an empty object on failure. May block for up to ~3s
|
||||
/// May display message boxes on error if silent if false
|
||||
QByteArray fetchLastTextRecord(const QString& record, bool silent=true);
|
||||
|
||||
private:
|
||||
QLabel headLabel, toxIdLabel, messageLabel;
|
||||
|
@ -55,6 +72,7 @@ private:
|
|||
|
||||
/** will be used for dns discovery if necessary */
|
||||
QDnsLookup dns;
|
||||
static const tox3_server pinnedServers[];
|
||||
};
|
||||
|
||||
#endif // ADDFRIENDFORM_H
|
||||
|
|
Loading…
Reference in New Issue
Block a user