1
0
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:
Tux3 / Mlkj / !Lev.uXFMLA 2014-11-05 23:27:51 +01:00
parent de3befe116
commit 0b6a4a6481
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
3 changed files with 196 additions and 44 deletions

View File

@ -63,43 +63,32 @@ contains(JENKINS,YES) {
# Rules for Windows, Mac OSX, and Linux # Rules for Windows, Mac OSX, and Linux
win32 { win32 {
RC_FILE = windows/qtox.rc 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 += -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 LIBS += -lz -lopengl32 -lole32 -loleaut32 -luuid -lvfw32 -ljpeg -ltiff -lpng -ljasper -lIlmImf -lHalf -lws2_32
} else { } else {
macx { macx {
ICON = img/icons/qtox.icns 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 { } else {
# If we're building a package, static link libtox[core,av] and libsodium, since they are not provided by any package # If we're building a package, static link libtox[core,av] and libsodium, since they are not provided by any package
contains(STATICPKG, YES) { contains(STATICPKG, YES) {
target.path = /usr/bin target.path = /usr/bin
INSTALLS += target 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,-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 += -Wl,-Bdynamic -lv4l1 -lv4l2 -lavformat -lavcodec -lavutil -lswscale -lusb-1.0
} else { } 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) { 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 \ HEADERS += src/widget/form/addfriendform.h \
src/widget/form/chatform.h \ src/widget/form/chatform.h \
src/widget/form/groupchatform.h \ src/widget/form/groupchatform.h \

View File

@ -18,12 +18,25 @@
#include <QFont> #include <QFont>
#include <QMessageBox> #include <QMessageBox>
#include <QThread>
#include <tox/tox.h> #include <tox/tox.h>
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "src/core.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 #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) AddFriendForm::AddFriendForm() : dns(this)
{ {
dns.setType(QDnsLookup::TXT); dns.setType(QDnsLookup::TXT);
@ -50,7 +63,6 @@ AddFriendForm::AddFriendForm() : dns(this)
headLayout.addWidget(&headLabel); headLayout.addWidget(&headLabel);
connect(&sendButton, SIGNAL(clicked()), this, SLOT(onSendTriggered())); connect(&sendButton, SIGNAL(clicked()), this, SLOT(onSendTriggered()));
connect(&dns, SIGNAL(finished()), this, SLOT(handleDnsLookup()));
} }
AddFriendForm::~AddFriendForm() 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")); showWarning(tr("You can't add yourself as a friend!","When trying to add your own Tox ID as friend"));
else else
emit friendRequested(id, getMessage()); emit friendRequested(id, getMessage());
this->toxId.setText(""); this->toxId.clear();
this->message.setText(""); this->message.clear();
} else { } else {
id = id.replace("@", "._tox."); // If we're querying one of our pinned server, do a tox3 request directly
dns.setName(id); QString servname = id.mid(id.indexOf('@')+1);
dns.lookup(); 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 (dns.error() == QDnsLookup::NotFoundError) {
if (!silent)
showWarning(tr("This address does not exist","The DNS gives the Tox ID associated to toxme.se addresses")); 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) { 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")); 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(); const QList<QDnsTextRecord> textRecords = dns.textRecords();
if (textRecords.length() != 1) { if (textRecords.isEmpty()) {
showWarning(tr("Unexpected number of text records", "Error with the DNS")); if (!silent)
return; 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 (textRecordValues.length() != 1) {
if (!silent)
showWarning(tr("Unexpected number of values in text record", "Error with the DNS")); 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 void AddFriendForm::queryTox1(const QString& record)
int verx = entry.indexOf(verKeyWord); {
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) { if (verx) {
verx += verKeyWord.size(); verx += 2;
int verend = entry.indexOf(';', verx); int verend = entry.indexOf(';', verx);
if (verend) if (verend)
{ {
QString ver = entry.mid(verx, verend); QString ver = entry.mid(verx, verend-verx);
if (ver != "tox1") if (ver != "tox1")
{ {
showWarning(tr("The version of Tox DNS used by this server is not supported", "Error with the DNS")); 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) { if (idx < 0) {
showWarning(tr("The DNS lookup does not contain any Tox ID", "Error with the DNS")); showWarning(tr("The DNS lookup does not contain any Tox ID", "Error with the DNS"));
return; return;
} }
idx += idKeyWord.length(); idx += 3;
if (entry.length() < idx + static_cast<int>(TOX_ID_LENGTH)) { 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")); showWarning(tr("The DNS lookup does not contain a valid Tox ID", "Error with the DNS"));
return; return;
@ -171,6 +236,86 @@ void AddFriendForm::handleDnsLookup()
// finally we got it // finally we got it
emit friendRequested(friendAdress, getMessage()); emit friendRequested(friendAdress, getMessage());
this->toxId.setText(""); this->toxId.clear();
this->message.setText(""); 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;
} }

View File

@ -43,7 +43,24 @@ signals:
private slots: private slots:
void onSendTriggered(); 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: private:
QLabel headLabel, toxIdLabel, messageLabel; QLabel headLabel, toxIdLabel, messageLabel;
@ -55,6 +72,7 @@ private:
/** will be used for dns discovery if necessary */ /** will be used for dns discovery if necessary */
QDnsLookup dns; QDnsLookup dns;
static const tox3_server pinnedServers[];
}; };
#endif // ADDFRIENDFORM_H #endif // ADDFRIENDFORM_H