35 #include "util/strongtype.h"
36 #include "util/compatiblerecursivemutex.h"
38 #include <QCoreApplication>
40 #include <QRegularExpression>
42 #include <QStringBuilder>
53 #define ASSERT_CORE_THREAD assert(QThread::currentThread() == coreThread.get())
62 #define PARSE_ERR(err) parseErr(err, __LINE__)
64 bool parseErr(Tox_Err_Conference_Title error,
int line)
67 case TOX_ERR_CONFERENCE_TITLE_OK:
70 case TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND:
71 qCritical() << line <<
": Conference title not found";
74 case TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH:
75 qCritical() << line <<
": Invalid conference title length";
78 case TOX_ERR_CONFERENCE_TITLE_FAIL_SEND:
79 qCritical() << line <<
": Failed to send title packet";
83 qCritical() << line <<
": Unknown Tox_Err_Conference_Title error code:" << error;
88 bool parseErr(Tox_Err_Friend_Send_Message error,
int line)
91 case TOX_ERR_FRIEND_SEND_MESSAGE_OK:
94 case TOX_ERR_FRIEND_SEND_MESSAGE_NULL:
95 qCritical() << line <<
"Send friend message passed an unexpected null argument";
98 case TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND:
99 qCritical() << line <<
"Send friend message could not find friend";
102 case TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED:
103 qCritical() << line <<
"Send friend message: friend is offline";
106 case TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ:
107 qCritical() << line <<
"Failed to allocate more message queue";
110 case TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG:
111 qCritical() << line <<
"Attemped to send message that's too long";
114 case TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY:
115 qCritical() << line <<
"Attempted to send an empty message";
119 qCritical() << line <<
"Unknown friend send message error:" <<
static_cast<int>(error);
124 bool parseErr(Tox_Err_Conference_Send_Message error,
int line)
127 case TOX_ERR_CONFERENCE_SEND_MESSAGE_OK:
130 case TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND:
131 qCritical() << line <<
"Conference not found";
134 case TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND:
135 qCritical() << line <<
"Conference message failed to send";
138 case TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION:
139 qCritical() << line <<
"No connection";
142 case TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG:
143 qCritical() << line <<
"Message too long";
147 qCritical() << line <<
"Unknown Tox_Err_Conference_Send_Message error:" <<
static_cast<int>(error);
152 bool parseErr(Tox_Err_Conference_Peer_Query error,
int line)
155 case TOX_ERR_CONFERENCE_PEER_QUERY_OK:
158 case TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND:
159 qCritical() << line <<
"Conference not found";
162 case TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION:
163 qCritical() << line <<
"No connection";
166 case TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND:
167 qCritical() << line <<
"Peer not found";
171 qCritical() << line <<
"Unknown Tox_Err_Conference_Peer_Query error code:" << error;
176 bool parseErr(Tox_Err_Conference_Join error,
int line)
179 case TOX_ERR_CONFERENCE_JOIN_OK:
182 case TOX_ERR_CONFERENCE_JOIN_DUPLICATE:
183 qCritical() << line <<
"Conference duplicate";
186 case TOX_ERR_CONFERENCE_JOIN_FAIL_SEND:
187 qCritical() << line <<
"Conference join failed to send";
190 case TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND:
191 qCritical() << line <<
"Friend not found";
194 case TOX_ERR_CONFERENCE_JOIN_INIT_FAIL:
195 qCritical() << line <<
"Init fail";
198 case TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH:
199 qCritical() << line <<
"Invalid length";
202 case TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE:
203 qCritical() << line <<
"Wrong conference type";
207 qCritical() << line <<
"Unknown Tox_Err_Conference_Join error code:" << error;
212 bool parseErr(Tox_Err_Conference_Get_Type error,
int line)
215 case TOX_ERR_CONFERENCE_GET_TYPE_OK:
218 case TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND:
219 qCritical() << line <<
"Conference not found";
223 qCritical() << line <<
"Unknown Tox_Err_Conference_Get_Type error code:" << error;
228 bool parseErr(Tox_Err_Conference_Invite error,
int line)
231 case TOX_ERR_CONFERENCE_INVITE_OK:
234 case TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND:
235 qCritical() << line <<
"Conference not found";
238 case TOX_ERR_CONFERENCE_INVITE_FAIL_SEND:
239 qCritical() << line <<
"Conference invite failed to send";
242 case TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION:
243 qCritical() << line <<
"Cannot invite to conference that we're not connected to";
247 qWarning() <<
"Unknown Tox_Err_Conference_Invite error code:" << error;
252 bool parseErr(Tox_Err_Conference_New error,
int line)
255 case TOX_ERR_CONFERENCE_NEW_OK:
258 case TOX_ERR_CONFERENCE_NEW_INIT:
259 qCritical() << line <<
"The conference instance failed to initialize";
263 qCritical() << line <<
"Unknown Tox_Err_Conference_New error code:" << error;
268 bool parseErr(Tox_Err_Friend_By_Public_Key error,
int line)
271 case TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK:
274 case TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL:
275 qCritical() << line <<
"null argument when not expected";
278 case TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND:
283 qCritical() << line <<
"Unknown Tox_Err_Friend_By_Public_Key error code:" << error;
288 bool parseErr(Tox_Err_Bootstrap error,
int line)
291 case TOX_ERR_BOOTSTRAP_OK:
294 case TOX_ERR_BOOTSTRAP_NULL:
295 qCritical() << line <<
"null argument when not expected";
298 case TOX_ERR_BOOTSTRAP_BAD_HOST:
299 qCritical() << line <<
"Could not resolve hostname, or invalid IP address";
302 case TOX_ERR_BOOTSTRAP_BAD_PORT:
303 qCritical() << line <<
"out of range port";
307 qCritical() << line <<
"Unknown Tox_Err_bootstrap error code:" << error;
312 bool parseErr(Tox_Err_Friend_Add error,
int line)
315 case TOX_ERR_FRIEND_ADD_OK:
318 case TOX_ERR_FRIEND_ADD_NULL:
319 qCritical() << line <<
"null argument when not expected";
322 case TOX_ERR_FRIEND_ADD_TOO_LONG:
323 qCritical() << line <<
"The length of the friend request message exceeded";
326 case TOX_ERR_FRIEND_ADD_NO_MESSAGE:
327 qCritical() << line <<
"The friend request message was empty.";
330 case TOX_ERR_FRIEND_ADD_OWN_KEY:
331 qCritical() << line <<
"The friend address belongs to the sending client.";
334 case TOX_ERR_FRIEND_ADD_ALREADY_SENT:
335 qCritical() << line <<
"The address belongs to a friend that is already on the friend list.";
338 case TOX_ERR_FRIEND_ADD_BAD_CHECKSUM:
339 qCritical() << line <<
"The friend address checksum failed.";
342 case TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM:
343 qCritical() << line <<
"The address belongs to a friend that is already on the friend list.";
346 case TOX_ERR_FRIEND_ADD_MALLOC:
347 qCritical() << line <<
"A memory allocation failed when trying to increase the friend list size.";
351 qCritical() << line <<
"Unknown Tox_Err_Friend_Add error code:" << error;
357 bool parseErr(Tox_Err_Friend_Delete error,
int line)
360 case TOX_ERR_FRIEND_DELETE_OK:
363 case TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND:
364 qCritical() << line <<
"There is no friend with the given friend number";
368 qCritical() << line <<
"Unknown Tox_Err_Friend_Delete error code:" << error;
373 bool parseErr(Tox_Err_Set_Info error,
int line)
376 case TOX_ERR_SET_INFO_OK:
379 case TOX_ERR_SET_INFO_NULL:
380 qCritical() << line <<
"null argument when not expected";
383 case TOX_ERR_SET_INFO_TOO_LONG:
384 qCritical() << line <<
"Information length exceeded maximum permissible size.";
388 qCritical() << line <<
"Unknown Tox_Err_Set_Info error code:" << error;
393 bool parseErr(Tox_Err_Friend_Query error,
int line)
396 case TOX_ERR_FRIEND_QUERY_OK:
399 case TOX_ERR_FRIEND_QUERY_NULL:
400 qCritical() << line <<
"null argument when not expected";
403 case TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND:
404 qCritical() << line <<
"The friend_number did not designate a valid friend.";
408 qCritical() << line <<
"Unknown Tox_Err_Friend_Query error code:" << error;
413 bool parseErr(Tox_Err_Friend_Get_Public_Key error,
int line)
416 case TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK:
419 case TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND:
420 qCritical() << line <<
"There is no friend with the given friend number";
424 qCritical() << line <<
"Unknown Tox_Err_Friend_Get_Public_Key error code:" << error;
429 bool parseErr(Tox_Err_Friend_Get_Last_Online error,
int line)
432 case TOX_ERR_FRIEND_GET_LAST_ONLINE_OK:
435 case TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND:
436 qCritical() << line <<
"There is no friend with the given friend number";
440 qCritical() << line <<
"Unknown Tox_Err_Friend_Get_Last_Online error code:" << error;
445 bool parseErr(Tox_Err_Set_Typing error,
int line)
448 case TOX_ERR_SET_TYPING_OK:
451 case TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND:
452 qCritical() << line <<
"There is no friend with the given friend number";
456 qCritical() << line <<
"Unknown Tox_Err_Set_Typing error code:" << error;
461 bool parseErr(Tox_Err_Conference_Delete error,
int line)
464 case TOX_ERR_CONFERENCE_DELETE_OK:
467 case TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND:
468 qCritical() << line <<
"The conference number passed did not designate a valid conference.";
472 qCritical() << line <<
"Unknown Tox_Err_Conference_Delete error code:" << error;
479 std::mt19937 rng(std::chrono::high_resolution_clock::now().time_since_epoch().count());
480 std::shuffle(bootstrapNodes.begin(), bootstrapNodes.end(), rng);
481 return bootstrapNodes;
488 , toxTimer{
new QTimer{
this}}
489 , coreThread(coreThread)
490 , bootstrapListGenerator(_bootstrapListGenerator)
491 , settings(_settings)
494 toxTimer->setSingleShot(
true);
496 connect(coreThread, &QThread::finished, toxTimer, &QTimer::stop);
542 QThread* thread =
new QThread();
543 if (thread ==
nullptr) {
544 qCritical() <<
"Could not allocate Core thread";
547 thread->setObjectName(
"qTox Core");
550 if (toxOptions ==
nullptr) {
551 qCritical() <<
"Could not allocate ToxOptions data structure";
559 if (core ==
nullptr) {
567 core->tox =
ToxPtr(tox_new(*toxOptions, &tox_err));
573 case TOX_ERR_NEW_LOAD_BAD_FORMAT:
574 qCritical() <<
"Failed to parse Tox save data";
580 case TOX_ERR_NEW_PORT_ALLOC:
581 if (toxOptions->getIPv6Enabled()) {
582 toxOptions->setIPv6Enabled(
false);
583 core->tox =
ToxPtr(tox_new(*toxOptions, &tox_err));
584 if (tox_err == TOX_ERR_NEW_OK) {
585 qWarning() <<
"Core failed to start with IPv6, falling back to IPv4. LAN discovery "
586 "may not work properly.";
591 qCritical() <<
"Can't to bind the port";
597 case TOX_ERR_NEW_PROXY_BAD_HOST:
598 case TOX_ERR_NEW_PROXY_BAD_PORT:
599 case TOX_ERR_NEW_PROXY_BAD_TYPE:
600 qCritical() <<
"Bad proxy, error code:" << tox_err;
606 case TOX_ERR_NEW_PROXY_NOT_FOUND:
607 qCritical() <<
"Proxy not found";
613 case TOX_ERR_NEW_LOAD_ENCRYPTED:
614 qCritical() <<
"Attempted to load encrypted Tox save data";
620 case TOX_ERR_NEW_MALLOC:
621 qCritical() <<
"Memory allocation failed";
627 case TOX_ERR_NEW_NULL:
628 qCritical() <<
"A parameter was null";
635 qCritical() <<
"Toxcore failed to start, unknown error code:" << tox_err;
643 assert(core->tox !=
nullptr);
648 qCritical() <<
"CoreFile failed to start";
662 core->moveToThread(thread);
675 if (!name.isEmpty()) {
680 if (!msg.isEmpty()) {
686 assert(
id.isValid());
752 tox_iterate(
tox.get(),
this);
769 qMin(tox_iteration_interval(
tox.get()),
getCoreFile()->corefileIterationInterval());
776 auto selfConnection = tox_self_get_connection_status(
tox.get());
777 QString connectionName;
778 bool toxConnected =
false;
779 switch (selfConnection)
781 case TOX_CONNECTION_NONE:
782 toxConnected =
false;
784 case TOX_CONNECTION_TCP:
786 connectionName =
"a TCP relay";
788 case TOX_CONNECTION_UDP:
790 connectionName =
"the UDP DHT";
792 qWarning() <<
"tox_self_get_connection_status returned unknown enum!";
796 qDebug().noquote() <<
"Connected to" << connectionName;
799 qDebug() <<
"Disconnected from the DHT";
816 if (shuffledBootstrapNodes.empty()) {
817 qWarning() <<
"No bootstrap node list";
822 auto numNewNodes = 2;
823 for (
int i = 0; i < numNewNodes && i < shuffledBootstrapNodes.size(); ++i) {
824 const auto& dhtServer = shuffledBootstrapNodes.at(i);
826 if (!dhtServer.ipv4.isEmpty()) {
827 address = dhtServer.ipv4.toLatin1();
829 address = dhtServer.ipv6.toLatin1();
835 ToxPk pk{dhtServer.publicKey};
836 qDebug() <<
"Connecting to bootstrap node" << pk.
toString();
837 const uint8_t* pkPtr = pk.getData();
839 Tox_Err_Bootstrap error;
840 if (dhtServer.statusUdp) {
841 tox_bootstrap(
tox.get(), address.constData(), dhtServer.udpPort, pkPtr, &error);
844 if (dhtServer.statusTcp) {
845 const auto ports = dhtServer.tcpPorts.size();
846 const auto tcpPort = dhtServer.tcpPorts[rand() % ports];
847 tox_add_tcp_relay(
tox.get(), address.constData(), tcpPort, pkPtr, &error);
854 size_t cMessageSize,
void* core)
856 ToxPk friendPk(cFriendPk);
862 size_t cMessageSize,
void* core)
864 bool isAction = (type == TOX_MESSAGE_TYPE_ACTION);
882 size_t cMessageSize,
void* core)
892 switch (userstatus) {
893 case TOX_USER_STATUS_AWAY:
897 case TOX_USER_STATUS_BUSY:
912 Core* core =
static_cast<Core*
>(vCore);
916 case TOX_CONNECTION_NONE:
918 qDebug() <<
"Disconnected from friend" << friendId;
920 case TOX_CONNECTION_TCP:
922 qDebug() <<
"Connected to friend" << friendId <<
"through a TCP relay";
924 case TOX_CONNECTION_UDP:
926 qDebug() <<
"Connected to friend" << friendId <<
"directly with UDP";
928 qWarning() <<
"tox_callback_friend_connection_status returned unknown enum!";
940 const uint8_t* cookie,
size_t length,
void* vCore)
942 Core* core =
static_cast<Core*
>(vCore);
943 const QByteArray data(
reinterpret_cast<const char*
>(cookie), length);
944 const GroupInvite inviteInfo(friendId, type, data);
946 case TOX_CONFERENCE_TYPE_TEXT:
947 qDebug() << QString(
"Text group invite by %1").arg(friendId);
951 case TOX_CONFERENCE_TYPE_AV:
952 qDebug() << QString(
"AV group invite by %1").arg(friendId);
957 qWarning() <<
"Group invite with unknown type " << type;
962 const uint8_t* cMessage,
size_t length,
void* vCore)
964 Core* core =
static_cast<Core*
>(vCore);
965 bool isAction = type == TOX_MESSAGE_TYPE_ACTION;
972 const auto core =
static_cast<Core*
>(vCore);
973 qDebug() << QString(
"Group %1 peerlist changed").arg(groupId);
979 size_t length,
void* vCore)
982 qDebug() << QString(
"Group %1, peer %2, name changed to %3").arg(groupId).arg(peerId).arg(newName);
983 auto* core =
static_cast<Core*
>(vCore);
985 emit core->groupPeerNameChanged(groupId, peerPk, newName);
989 size_t length,
void* vCore)
991 Core* core =
static_cast<Core*
>(vCore);
994 if (peerId != std::numeric_limits<uint32_t>::max()) {
1005 const uint8_t* data,
size_t length,
void* vCore)
1007 Core* core =
static_cast<Core*
>(vCore);
1008 core->
ext->onLosslessPacket(friendId, data, length);
1019 Tox_Err_Friend_Add error;
1020 uint32_t friendId = tox_friend_add_norequest(
tox.get(), friendPk.
getData(), &error);
1040 return tr(
"Invalid Tox ID",
"Error while sending friend request");
1044 return tr(
"You need to write a message with your request",
1045 "Error while sending friend request");
1048 if (
message.length() >
static_cast<int>(tox_max_friend_request_length())) {
1049 return tr(
"Your message is too long!",
"Error while sending friend request");
1053 return tr(
"Friend is already added",
"Error while sending friend request");
1065 if (!errorMessage.isNull()) {
1072 Tox_Err_Friend_Add error;
1073 uint32_t friendNumber =
1076 qDebug() <<
"Requested friendship from " << friendNumber;
1081 qDebug() <<
"Failed to send friend request";
1089 int size =
message.toUtf8().size();
1091 if (size > maxSize) {
1093 qCritical() <<
"Core::sendMessageWithType called with message of size:" << size
1094 <<
"when max is:" << maxSize <<
". Ignoring.";
1099 Tox_Err_Friend_Send_Message error;
1100 receipt =
ReceiptNum{tox_friend_send_message(
tox.get(), friendId, type, cMessage.
data(),
1101 cMessage.
size(), &error)};
1124 Tox_Err_Set_Typing error;
1125 tox_self_set_typing(
tox.get(), friendId, typing, &error);
1135 int size =
message.toUtf8().size();
1137 if (size > maxSize) {
1138 qCritical() <<
"Core::sendMessageWithType called with message of size:" << size
1139 <<
"when max is:" << maxSize <<
". Ignoring.";
1144 Tox_Err_Conference_Send_Message error;
1145 tox_conference_send_message(
tox.get(), groupId, type, cMsg.
data(), cMsg.
size(), &error);
1171 Tox_Err_Conference_Title error;
1172 tox_conference_set_title(
tox.get(), groupId, cTitle.
data(), cTitle.
size(), &error);
1183 Tox_Err_Friend_Delete error;
1184 tox_friend_delete(
tox.get(), friendId, &error);
1198 Tox_Err_Conference_Delete error;
1199 tox_conference_delete(
tox.get(), groupId, &error);
1226 int size = tox_self_get_name_size(
tox.get());
1230 std::vector<uint8_t> nameBuf(size);
1231 tox_self_get_name(
tox.get(), nameBuf.data());
1244 Tox_Err_Set_Info error;
1245 tox_self_set_name(
tox.get(), cUsername.
data(), cUsername.
size(), &error);
1262 uint8_t friendId[TOX_ADDRESS_SIZE] = {0x00};
1263 tox_self_get_address(
tox.get(), friendId);
1264 return ToxId(friendId, TOX_ADDRESS_SIZE);
1275 uint8_t selfPk[TOX_PUBLIC_KEY_SIZE] = {0x00};
1276 tox_self_get_public_key(
tox.get(), selfPk);
1277 return ToxPk(selfPk);
1287 QPair<QByteArray, QByteArray> keypair;
1288 assert(
tox !=
nullptr);
1290 QByteArray pk(TOX_PUBLIC_KEY_SIZE, 0x00);
1291 QByteArray sk(TOX_SECRET_KEY_SIZE, 0x00);
1292 tox_self_get_public_key(
tox.get(),
reinterpret_cast<uint8_t*
>(pk.data()));
1293 tox_self_get_secret_key(
tox.get(),
reinterpret_cast<uint8_t*
>(sk.data()));
1295 keypair.second = sk;
1306 assert(
tox !=
nullptr);
1308 size_t size = tox_self_get_status_message_size(
tox.get());
1312 std::vector<uint8_t> nameBuf(size);
1313 tox_self_get_status_message(
tox.get(), nameBuf.data());
1336 Tox_Err_Set_Info error;
1337 tox_self_set_status_message(
tox.get(), cMessage.
data(), cMessage.
size(), &error);
1351 Tox_User_Status userstatus;
1354 userstatus = TOX_USER_STATUS_NONE;
1358 userstatus = TOX_USER_STATUS_AWAY;
1362 userstatus = TOX_USER_STATUS_BUSY;
1370 tox_self_set_status(
tox.get(), userstatus);
1382 uint32_t fileSize = tox_get_savedata_size(
tox.get());
1384 data.resize(fileSize);
1385 tox_get_savedata(
tox.get(),
reinterpret_cast<uint8_t*
>(data.data()));
1393 const size_t friendCount = tox_self_get_friend_list_size(
tox.get());
1394 if (friendCount == 0) {
1398 std::vector<uint32_t> ids(friendCount);
1399 tox_self_get_friend_list(
tox.get(), ids.data());
1400 uint8_t friendPk[TOX_PUBLIC_KEY_SIZE] = {0x00};
1401 for (
size_t i = 0; i < friendCount; ++i) {
1402 Tox_Err_Friend_Get_Public_Key keyError;
1403 tox_friend_get_public_key(
tox.get(), ids[i], friendPk, &keyError);
1409 Tox_Err_Friend_Query queryError;
1410 size_t statusMessageSize = tox_friend_get_status_message_size(
tox.get(), ids[i], &queryError);
1411 if (
PARSE_ERR(queryError) && statusMessageSize) {
1412 std::vector<uint8_t> messageData(statusMessageSize);
1413 tox_friend_get_status_message(
tox.get(), ids[i], messageData.data(), &queryError);
1414 QString friendStatusMessage =
ToxString(messageData.data(), statusMessageSize).
getQString();
1425 const size_t groupCount = tox_conference_get_chatlist_size(
tox.get());
1426 if (groupCount == 0) {
1430 std::vector<uint32_t> groupNumbers(groupCount);
1431 tox_conference_get_chatlist(
tox.get(), groupNumbers.data());
1433 for (
size_t i = 0; i < groupCount; ++i) {
1434 Tox_Err_Conference_Title error;
1436 const auto groupNumber = groupNumbers[i];
1437 size_t titleSize = tox_conference_get_title_size(
tox.get(), groupNumber, &error);
1439 const QString defaultName = tr(
"Groupchat %1").arg(persistentId.
toString().left(8));
1441 std::vector<uint8_t> nameBuf(titleSize);
1442 tox_conference_get_title(
tox.get(), groupNumber, nameBuf.data(), &error);
1453 qCritical() <<
"Failed to enable audio on loaded group" << groupNumber;
1464 Tox_Err_Friend_Get_Last_Online error;
1465 const uint64_t lastOnline = tox_friend_get_last_online(
tox.get(), friendId, &error);
1478 QVector<uint32_t> friends;
1479 friends.resize(tox_self_get_friend_list_size(
tox.get()));
1480 tox_self_get_friend_list(
tox.get(), friends.data());
1488 std::vector<uint8_t> idBuff(TOX_CONFERENCE_UID_SIZE);
1489 if (tox_conference_get_id(
tox.get(), groupNumber,
1491 return GroupId{idBuff.data()};
1493 qCritical() <<
"Failed to get conference ID of group" << groupNumber;
1506 Tox_Err_Conference_Peer_Query error;
1507 uint32_t count = tox_conference_peer_count(
tox.get(), groupId, &error);
1509 return std::numeric_limits<uint32_t>::max();
1522 Tox_Err_Conference_Peer_Query error;
1523 size_t length = tox_conference_peer_get_name_size(
tox.get(), groupId, peerId, &error);
1528 std::vector<uint8_t> nameBuf(length);
1529 tox_conference_peer_get_name(
tox.get(), groupId, peerId, nameBuf.data(), &error);
1544 uint8_t friendPk[TOX_PUBLIC_KEY_SIZE] = {0x00};
1545 Tox_Err_Conference_Peer_Query error;
1546 tox_conference_peer_get_public_key(
tox.get(), groupId, peerId, friendPk, &error);
1551 return ToxPk(friendPk);
1561 assert(
tox !=
nullptr);
1564 if (nPeers == std::numeric_limits<uint32_t>::max()) {
1565 qWarning() <<
"getGroupPeerNames: Unable to get number of peers";
1570 for (
int i = 0; i < static_cast<int>(nPeers); ++i) {
1571 Tox_Err_Conference_Peer_Query error;
1572 size_t length = tox_conference_peer_get_name_size(
tox.get(), groupId, i, &error);
1575 names.append(QString());
1579 std::vector<uint8_t> nameBuf(length);
1580 tox_conference_peer_get_name(
tox.get(), groupId, i, nameBuf.data(), &error);
1584 names.append(QString());
1588 assert(names.size() ==
static_cast<int>(nPeers));
1601 Tox_Err_Conference_Get_Type error;
1602 Tox_Conference_Type type = tox_conference_get_type(
tox.get(), groupId, &error);
1605 return type == TOX_CONFERENCE_TYPE_AV;
1618 const uint32_t friendId = inviteInfo.
getFriendId();
1619 const uint8_t confType = inviteInfo.
getType();
1620 const QByteArray invite = inviteInfo.
getInvite();
1621 const uint8_t*
const cookie =
reinterpret_cast<const uint8_t*
>(invite.data());
1622 const size_t cookieLength = invite.length();
1623 uint32_t groupNum{std::numeric_limits<uint32_t>::max()};
1625 case TOX_CONFERENCE_TYPE_TEXT: {
1626 qDebug() << QString(
"Trying to accept invite for text group chat sent by friend %1").arg(friendId);
1627 Tox_Err_Conference_Join error;
1628 groupNum = tox_conference_join(
tox.get(), friendId, cookie, cookieLength, &error);
1630 groupNum = std::numeric_limits<uint32_t>::max();
1634 case TOX_CONFERENCE_TYPE_AV: {
1635 qDebug() << QString(
"Trying to join AV groupchat invite sent by friend %1").arg(friendId);
1636 groupNum = toxav_join_av_groupchat(
tox.get(), friendId, cookie, cookieLength,
1641 qWarning() <<
"joinGroupchat: Unknown groupchat type " << confType;
1643 if (groupNum != std::numeric_limits<uint32_t>::max()) {
1654 Tox_Err_Conference_Invite error;
1655 tox_conference_invite(
tox.get(), friendId, groupId, &error);
1663 if (type == TOX_CONFERENCE_TYPE_TEXT) {
1664 Tox_Err_Conference_New error;
1665 uint32_t groupId = tox_conference_new(
tox.get(), &error);
1671 return std::numeric_limits<uint32_t>::max();
1673 }
else if (type == TOX_CONFERENCE_TYPE_AV) {
1677 if (groupId != -1) {
1681 qCritical() <<
"Unknown error creating AV groupchat";
1685 qWarning() <<
"createGroup: Unknown type " << type;
1697 Tox_Err_Friend_Query error;
1698 Tox_Connection connection = tox_friend_get_connection_status(
tox.get(), friendId, &error);
1700 return connection != TOX_CONNECTION_NONE;
1714 Tox_Err_Friend_By_Public_Key error;
1715 (void)tox_friend_by_public_key(
tox.get(), publicKey.
getData(), &error);
1726 uint8_t rawid[TOX_PUBLIC_KEY_SIZE];
1727 Tox_Err_Friend_Get_Public_Key error;
1728 tox_friend_get_public_key(
tox.get(), friendNumber, rawid, &error);
1730 qWarning() <<
"getFriendPublicKey: Getting public key failed";
1734 return ToxPk(rawid);
1744 Tox_Err_Friend_Query error;
1745 size_t nameSize = tox_friend_get_name_size(
tox.get(), friendnumber, &error);
1750 std::vector<uint8_t> nameBuf(nameSize);
1751 tox_friend_get_name(
tox.get(), friendnumber, nameBuf.data(), &error);
1770 return tox_max_message_length() - 50;
1777 Tox_Err_Friend_By_Public_Key keyError;
1778 uint32_t friendId = tox_friend_by_public_key(
tox.get(),
id.getData(), &keyError);
1780 qWarning() <<
"getPeerName: No such peer";
1784 Tox_Err_Friend_Query queryError;
1785 const size_t nameSize = tox_friend_get_name_size(
tox.get(), friendId, &queryError);
1786 if (!
PARSE_ERR(queryError) || !nameSize) {
1790 std::vector<uint8_t> nameBuf(nameSize);
1791 tox_friend_get_name(
tox.get(), friendId, nameBuf.data(), &queryError);
1793 qWarning() <<
"getPeerName: Can't get name of friend " + QString().setNum(friendId);
1808 tox_self_set_nospam(
tox.get(), nospam);