qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
core.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2013 by Maxim Biro <nurupo.contributions@gmail.com>
3  Copyright © 2014-2019 by The qTox Project Contributors
4 
5  This file is part of qTox, a Qt-based graphical interface for Tox.
6 
7  qTox is libre software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  qTox is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with qTox. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "core.h"
22 #include "coreav.h"
23 #include "corefile.h"
24 
25 #include "src/core/coreext.h"
26 #include "src/core/dhtserver.h"
27 #include "src/core/icoresettings.h"
28 #include "src/core/toxlogger.h"
29 #include "src/core/toxoptions.h"
30 #include "src/core/toxstring.h"
31 #include "src/model/groupinvite.h"
32 #include "src/model/status.h"
35 #include "util/strongtype.h"
36 #include "util/compatiblerecursivemutex.h"
37 
38 #include <QCoreApplication>
39 #include <QDateTime>
40 #include <QRegularExpression>
41 #include <QString>
42 #include <QStringBuilder>
43 #include <QTimer>
44 
45 #include <algorithm>
46 #include <cassert>
47 #include <chrono>
48 #include <memory>
49 #include <random>
50 
51 const QString Core::TOX_EXT = ".tox";
52 
53 #define ASSERT_CORE_THREAD assert(QThread::currentThread() == coreThread.get())
54 
55 namespace {
62 #define PARSE_ERR(err) parseErr(err, __LINE__)
63 
64 bool parseErr(Tox_Err_Conference_Title error, int line)
65 {
66  switch (error) {
67  case TOX_ERR_CONFERENCE_TITLE_OK:
68  return true;
69 
70  case TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND:
71  qCritical() << line << ": Conference title not found";
72  return false;
73 
74  case TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH:
75  qCritical() << line << ": Invalid conference title length";
76  return false;
77 
78  case TOX_ERR_CONFERENCE_TITLE_FAIL_SEND:
79  qCritical() << line << ": Failed to send title packet";
80  return false;
81 
82  default:
83  qCritical() << line << ": Unknown Tox_Err_Conference_Title error code:" << error;
84  return false;
85  }
86 }
87 
88 bool parseErr(Tox_Err_Friend_Send_Message error, int line)
89 {
90  switch (error) {
91  case TOX_ERR_FRIEND_SEND_MESSAGE_OK:
92  return true;
93 
94  case TOX_ERR_FRIEND_SEND_MESSAGE_NULL:
95  qCritical() << line << "Send friend message passed an unexpected null argument";
96  return false;
97 
98  case TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND:
99  qCritical() << line << "Send friend message could not find friend";
100  return false;
101 
102  case TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED:
103  qCritical() << line << "Send friend message: friend is offline";
104  return false;
105 
106  case TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ:
107  qCritical() << line << "Failed to allocate more message queue";
108  return false;
109 
110  case TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG:
111  qCritical() << line << "Attemped to send message that's too long";
112  return false;
113 
114  case TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY:
115  qCritical() << line << "Attempted to send an empty message";
116  return false;
117 
118  default:
119  qCritical() << line << "Unknown friend send message error:" << static_cast<int>(error);
120  return false;
121  }
122 }
123 
124 bool parseErr(Tox_Err_Conference_Send_Message error, int line)
125 {
126  switch (error) {
127  case TOX_ERR_CONFERENCE_SEND_MESSAGE_OK:
128  return true;
129 
130  case TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND:
131  qCritical() << line << "Conference not found";
132  return false;
133 
134  case TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND:
135  qCritical() << line << "Conference message failed to send";
136  return false;
137 
138  case TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION:
139  qCritical() << line << "No connection";
140  return false;
141 
142  case TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG:
143  qCritical() << line << "Message too long";
144  return false;
145 
146  default:
147  qCritical() << line << "Unknown Tox_Err_Conference_Send_Message error:" << static_cast<int>(error);
148  return false;
149  }
150 }
151 
152 bool parseErr(Tox_Err_Conference_Peer_Query error, int line)
153 {
154  switch (error) {
155  case TOX_ERR_CONFERENCE_PEER_QUERY_OK:
156  return true;
157 
158  case TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND:
159  qCritical() << line << "Conference not found";
160  return false;
161 
162  case TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION:
163  qCritical() << line << "No connection";
164  return false;
165 
166  case TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND:
167  qCritical() << line << "Peer not found";
168  return false;
169 
170  default:
171  qCritical() << line << "Unknown Tox_Err_Conference_Peer_Query error code:" << error;
172  return false;
173  }
174 }
175 
176 bool parseErr(Tox_Err_Conference_Join error, int line)
177 {
178  switch (error) {
179  case TOX_ERR_CONFERENCE_JOIN_OK:
180  return true;
181 
182  case TOX_ERR_CONFERENCE_JOIN_DUPLICATE:
183  qCritical() << line << "Conference duplicate";
184  return false;
185 
186  case TOX_ERR_CONFERENCE_JOIN_FAIL_SEND:
187  qCritical() << line << "Conference join failed to send";
188  return false;
189 
190  case TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND:
191  qCritical() << line << "Friend not found";
192  return false;
193 
194  case TOX_ERR_CONFERENCE_JOIN_INIT_FAIL:
195  qCritical() << line << "Init fail";
196  return false;
197 
198  case TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH:
199  qCritical() << line << "Invalid length";
200  return false;
201 
202  case TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE:
203  qCritical() << line << "Wrong conference type";
204  return false;
205 
206  default:
207  qCritical() << line << "Unknown Tox_Err_Conference_Join error code:" << error;
208  return false;
209  }
210 }
211 
212 bool parseErr(Tox_Err_Conference_Get_Type error, int line)
213 {
214  switch (error) {
215  case TOX_ERR_CONFERENCE_GET_TYPE_OK:
216  return true;
217 
218  case TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND:
219  qCritical() << line << "Conference not found";
220  return false;
221 
222  default:
223  qCritical() << line << "Unknown Tox_Err_Conference_Get_Type error code:" << error;
224  return false;
225  }
226 }
227 
228 bool parseErr(Tox_Err_Conference_Invite error, int line)
229 {
230  switch (error) {
231  case TOX_ERR_CONFERENCE_INVITE_OK:
232  return true;
233 
234  case TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND:
235  qCritical() << line << "Conference not found";
236  return false;
237 
238  case TOX_ERR_CONFERENCE_INVITE_FAIL_SEND:
239  qCritical() << line << "Conference invite failed to send";
240  return false;
241 
242  case TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION:
243  qCritical() << line << "Cannot invite to conference that we're not connected to";
244  return false;
245 
246  default:
247  qWarning() << "Unknown Tox_Err_Conference_Invite error code:" << error;
248  return false;
249  }
250 }
251 
252 bool parseErr(Tox_Err_Conference_New error, int line)
253 {
254  switch (error) {
255  case TOX_ERR_CONFERENCE_NEW_OK:
256  return true;
257 
258  case TOX_ERR_CONFERENCE_NEW_INIT:
259  qCritical() << line << "The conference instance failed to initialize";
260  return false;
261 
262  default:
263  qCritical() << line << "Unknown Tox_Err_Conference_New error code:" << error;
264  return false;
265  }
266 }
267 
268 bool parseErr(Tox_Err_Friend_By_Public_Key error, int line)
269 {
270  switch (error) {
271  case TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK:
272  return true;
273 
274  case TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL:
275  qCritical() << line << "null argument when not expected";
276  return false;
277 
278  case TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND:
279  // we use this as a check for friendship, so this can be an expected result
280  return false;
281 
282  default:
283  qCritical() << line << "Unknown Tox_Err_Friend_By_Public_Key error code:" << error;
284  return false;
285  }
286 }
287 
288 bool parseErr(Tox_Err_Bootstrap error, int line)
289 {
290  switch(error) {
291  case TOX_ERR_BOOTSTRAP_OK:
292  return true;
293 
294  case TOX_ERR_BOOTSTRAP_NULL:
295  qCritical() << line << "null argument when not expected";
296  return false;
297 
298  case TOX_ERR_BOOTSTRAP_BAD_HOST:
299  qCritical() << line << "Could not resolve hostname, or invalid IP address";
300  return false;
301 
302  case TOX_ERR_BOOTSTRAP_BAD_PORT:
303  qCritical() << line << "out of range port";
304  return false;
305 
306  default:
307  qCritical() << line << "Unknown Tox_Err_bootstrap error code:" << error;
308  return false;
309  }
310 }
311 
312 bool parseErr(Tox_Err_Friend_Add error, int line)
313 {
314  switch(error) {
315  case TOX_ERR_FRIEND_ADD_OK:
316  return true;
317 
318  case TOX_ERR_FRIEND_ADD_NULL:
319  qCritical() << line << "null argument when not expected";
320  return false;
321 
322  case TOX_ERR_FRIEND_ADD_TOO_LONG:
323  qCritical() << line << "The length of the friend request message exceeded";
324  return false;
325 
326  case TOX_ERR_FRIEND_ADD_NO_MESSAGE:
327  qCritical() << line << "The friend request message was empty.";
328  return false;
329 
330  case TOX_ERR_FRIEND_ADD_OWN_KEY:
331  qCritical() << line << "The friend address belongs to the sending client.";
332  return false;
333 
334  case TOX_ERR_FRIEND_ADD_ALREADY_SENT:
335  qCritical() << line << "The address belongs to a friend that is already on the friend list.";
336  return false;
337 
338  case TOX_ERR_FRIEND_ADD_BAD_CHECKSUM:
339  qCritical() << line << "The friend address checksum failed.";
340  return false;
341 
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.";
344  return false;
345 
346  case TOX_ERR_FRIEND_ADD_MALLOC:
347  qCritical() << line << "A memory allocation failed when trying to increase the friend list size.";
348  return false;
349 
350  default:
351  qCritical() << line << "Unknown Tox_Err_Friend_Add error code:" << error;
352  return false;
353 
354  }
355 }
356 
357 bool parseErr(Tox_Err_Friend_Delete error, int line)
358 {
359  switch(error) {
360  case TOX_ERR_FRIEND_DELETE_OK:
361  return true;
362 
363  case TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND:
364  qCritical() << line << "There is no friend with the given friend number";
365  return false;
366 
367  default:
368  qCritical() << line << "Unknown Tox_Err_Friend_Delete error code:" << error;
369  return false;
370  }
371 }
372 
373 bool parseErr(Tox_Err_Set_Info error, int line)
374 {
375  switch (error) {
376  case TOX_ERR_SET_INFO_OK:
377  return true;
378 
379  case TOX_ERR_SET_INFO_NULL:
380  qCritical() << line << "null argument when not expected";
381  return false;
382 
383  case TOX_ERR_SET_INFO_TOO_LONG:
384  qCritical() << line << "Information length exceeded maximum permissible size.";
385  return false;
386 
387  default:
388  qCritical() << line << "Unknown Tox_Err_Set_Info error code:" << error;
389  return false;
390  }
391 }
392 
393 bool parseErr(Tox_Err_Friend_Query error, int line)
394 {
395  switch (error) {
396  case TOX_ERR_FRIEND_QUERY_OK:
397  return true;
398 
399  case TOX_ERR_FRIEND_QUERY_NULL:
400  qCritical() << line << "null argument when not expected";
401  return false;
402 
403  case TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND:
404  qCritical() << line << "The friend_number did not designate a valid friend.";
405  return false;
406 
407  default:
408  qCritical() << line << "Unknown Tox_Err_Friend_Query error code:" << error;
409  return false;
410  }
411 }
412 
413 bool parseErr(Tox_Err_Friend_Get_Public_Key error, int line)
414 {
415  switch (error) {
416  case TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK:
417  return true;
418 
419  case TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND:
420  qCritical() << line << "There is no friend with the given friend number";
421  return false;
422 
423  default:
424  qCritical() << line << "Unknown Tox_Err_Friend_Get_Public_Key error code:" << error;
425  return false;
426  }
427 }
428 
429 bool parseErr(Tox_Err_Friend_Get_Last_Online error, int line)
430 {
431  switch (error) {
432  case TOX_ERR_FRIEND_GET_LAST_ONLINE_OK:
433  return true;
434 
435  case TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND:
436  qCritical() << line << "There is no friend with the given friend number";
437  return false;
438 
439  default:
440  qCritical() << line << "Unknown Tox_Err_Friend_Get_Last_Online error code:" << error;
441  return false;
442  }
443 }
444 
445 bool parseErr(Tox_Err_Set_Typing error, int line)
446 {
447  switch (error) {
448  case TOX_ERR_SET_TYPING_OK:
449  return true;
450 
451  case TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND:
452  qCritical() << line << "There is no friend with the given friend number";
453  return false;
454 
455  default:
456  qCritical() << line << "Unknown Tox_Err_Set_Typing error code:" << error;
457  return false;
458  }
459 }
460 
461 bool parseErr(Tox_Err_Conference_Delete error, int line)
462 {
463  switch (error) {
464  case TOX_ERR_CONFERENCE_DELETE_OK:
465  return true;
466 
467  case TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND:
468  qCritical() << line << "The conference number passed did not designate a valid conference.";
469  return false;
470 
471  default:
472  qCritical() << line << "Unknown Tox_Err_Conference_Delete error code:" << error;
473  return false;
474  }
475 }
476 
477 QList<DhtServer> shuffleBootstrapNodes(QList<DhtServer> bootstrapNodes)
478 {
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;
482 }
483 
484 } // namespace
485 
486 Core::Core(QThread* coreThread, IBootstrapListGenerator& _bootstrapListGenerator, const ICoreSettings& _settings)
487  : tox(nullptr)
488  , toxTimer{new QTimer{this}}
489  , coreThread(coreThread)
490  , bootstrapListGenerator(_bootstrapListGenerator)
491  , settings(_settings)
492 {
493  assert(toxTimer);
494  toxTimer->setSingleShot(true);
495  connect(toxTimer, &QTimer::timeout, this, &Core::process);
496  connect(coreThread, &QThread::finished, toxTimer, &QTimer::stop);
497 }
498 
500 {
501  /*
502  * First stop the thread to stop the timer and avoid Core emitting callbacks
503  * into an already destructed CoreAV.
504  */
505  coreThread->exit(0);
506  coreThread->wait();
507 
508  tox.reset();
509 }
510 
516 {
517  tox_callback_friend_request(tox, onFriendRequest);
518  tox_callback_friend_message(tox, onFriendMessage);
519  tox_callback_friend_name(tox, onFriendNameChange);
520  tox_callback_friend_typing(tox, onFriendTypingChange);
521  tox_callback_friend_status_message(tox, onStatusMessageChanged);
522  tox_callback_friend_status(tox, onUserStatusChanged);
523  tox_callback_friend_connection_status(tox, onConnectionStatusChanged);
524  tox_callback_friend_read_receipt(tox, onReadReceiptCallback);
525  tox_callback_conference_invite(tox, onGroupInvite);
526  tox_callback_conference_message(tox, onGroupMessage);
527  tox_callback_conference_peer_list_changed(tox, onGroupPeerListChange);
528  tox_callback_conference_peer_name(tox, onGroupPeerNameChange);
529  tox_callback_conference_title(tox, onGroupTitleChange);
530  tox_callback_friend_lossless_packet(tox, onLosslessPacket);
531 }
532 
539 ToxCorePtr Core::makeToxCore(const QByteArray& savedata, const ICoreSettings& settings,
540  IBootstrapListGenerator& bootstrapNodes, ToxCoreErrors* err)
541 {
542  QThread* thread = new QThread();
543  if (thread == nullptr) {
544  qCritical() << "Could not allocate Core thread";
545  return {};
546  }
547  thread->setObjectName("qTox Core");
548 
549  auto toxOptions = ToxOptions::makeToxOptions(savedata, settings);
550  if (toxOptions == nullptr) {
551  qCritical() << "Could not allocate ToxOptions data structure";
552  if (err) {
554  }
555  return {};
556  }
557 
558  ToxCorePtr core(new Core(thread, bootstrapNodes, settings));
559  if (core == nullptr) {
560  if (err) {
562  }
563  return {};
564  }
565 
566  Tox_Err_New tox_err;
567  core->tox = ToxPtr(tox_new(*toxOptions, &tox_err));
568 
569  switch (tox_err) {
570  case TOX_ERR_NEW_OK:
571  break;
572 
573  case TOX_ERR_NEW_LOAD_BAD_FORMAT:
574  qCritical() << "Failed to parse Tox save data";
575  if (err) {
577  }
578  return {};
579 
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.";
587  break;
588  }
589  }
590 
591  qCritical() << "Can't to bind the port";
592  if (err) {
594  }
595  return {};
596 
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;
601  if (err) {
603  }
604  return {};
605 
606  case TOX_ERR_NEW_PROXY_NOT_FOUND:
607  qCritical() << "Proxy not found";
608  if (err) {
610  }
611  return {};
612 
613  case TOX_ERR_NEW_LOAD_ENCRYPTED:
614  qCritical() << "Attempted to load encrypted Tox save data";
615  if (err) {
617  }
618  return {};
619 
620  case TOX_ERR_NEW_MALLOC:
621  qCritical() << "Memory allocation failed";
622  if (err) {
624  }
625  return {};
626 
627  case TOX_ERR_NEW_NULL:
628  qCritical() << "A parameter was null";
629  if (err) {
631  }
632  return {};
633 
634  default:
635  qCritical() << "Toxcore failed to start, unknown error code:" << tox_err;
636  if (err) {
638  }
639  return {};
640  }
641 
642  // tox should be valid by now
643  assert(core->tox != nullptr);
644 
645  // create CoreFile
646  core->file = CoreFile::makeCoreFile(core.get(), core->tox.get(), core->coreLoopLock);
647  if (!core->file) {
648  qCritical() << "CoreFile failed to start";
649  if (err) {
651  }
652  return {};
653  }
654 
655  core->ext = CoreExt::makeCoreExt(core->tox.get());
656  connect(core.get(), &Core::friendStatusChanged, core->ext.get(), &CoreExt::onFriendStatusChanged);
657 
658  registerCallbacks(core->tox.get());
659 
660  // connect the thread with the Core
661  connect(thread, &QThread::started, core.get(), &Core::onStarted);
662  core->moveToThread(thread);
663 
664  // when leaving this function 'core' should be ready for it's start() action or
665  // a nullptr
666  return core;
667 }
668 
670 {
672 
673  // One time initialization stuff
674  QString name = getUsername();
675  if (!name.isEmpty()) {
676  emit usernameSet(name);
677  }
678 
679  QString msg = getStatusMessage();
680  if (!msg.isEmpty()) {
681  emit statusMessageSet(msg);
682  }
683 
684  ToxId id = getSelfId();
685  // Id comes from toxcore, must be valid
686  assert(id.isValid());
687  emit idSet(id);
688 
689  loadFriends();
690  loadGroups();
691 
692  process(); // starts its own timer
693 }
694 
699 {
700  coreThread->start();
701 }
702 
703 const CoreAV* Core::getAv() const
704 {
705  return av;
706 }
707 
709 {
710  return av;
711 }
712 
713 void Core::setAv(CoreAV *coreAv)
714 {
715  av = coreAv;
716 }
717 
719 {
720  return file.get();
721 }
722 
723 Tox* Core::getTox() const
724 {
725  return tox.get();
726 }
727 
728 CompatibleRecursiveMutex &Core::getCoreLoopLock() const
729 {
730  return coreLoopLock;
731 }
732 
733 const CoreExt* Core::getExt() const
734 {
735  return ext.get();
736 }
737 
739 {
740  return ext.get();
741 }
742 
747 {
748  QMutexLocker ml{&coreLoopLock};
749 
751 
752  tox_iterate(tox.get(), this);
753  ext->process();
754 
755 #ifdef DEBUG
756  // we want to see the debug messages immediately
757  fflush(stdout);
758 #endif
759 
760  // TODO(sudden6): recheck if this is still necessary
761  if (checkConnection()) {
763  } else if (!(--tolerance)) {
764  bootstrapDht();
766  }
767 
768  unsigned sleeptime =
769  qMin(tox_iteration_interval(tox.get()), getCoreFile()->corefileIterationInterval());
770  toxTimer->start(sleeptime);
771 }
772 
774 {
776  auto selfConnection = tox_self_get_connection_status(tox.get());
777  QString connectionName;
778  bool toxConnected = false;
779  switch (selfConnection)
780  {
781  case TOX_CONNECTION_NONE:
782  toxConnected = false;
783  break;
784  case TOX_CONNECTION_TCP:
785  toxConnected = true;
786  connectionName = "a TCP relay";
787  break;
788  case TOX_CONNECTION_UDP:
789  toxConnected = true;
790  connectionName = "the UDP DHT";
791  break;
792  qWarning() << "tox_self_get_connection_status returned unknown enum!";
793  }
794 
795  if (toxConnected && !isConnected) {
796  qDebug().noquote() << "Connected to" << connectionName;
797  emit connected();
798  } else if (!toxConnected && isConnected) {
799  qDebug() << "Disconnected from the DHT";
800  emit disconnected();
801  }
802 
803  isConnected = toxConnected;
804  return toxConnected;
805 }
806 
811 {
813 
814 
815  auto const shuffledBootstrapNodes = shuffleBootstrapNodes(bootstrapListGenerator.getBootstrapnodes());
816  if (shuffledBootstrapNodes.empty()) {
817  qWarning() << "No bootstrap node list";
818  return;
819  }
820 
821  // i think the more we bootstrap, the more we jitter because the more we overwrite nodes
822  auto numNewNodes = 2;
823  for (int i = 0; i < numNewNodes && i < shuffledBootstrapNodes.size(); ++i) {
824  const auto& dhtServer = shuffledBootstrapNodes.at(i);
825  QByteArray address;
826  if (!dhtServer.ipv4.isEmpty()) {
827  address = dhtServer.ipv4.toLatin1();
828  } else if (!dhtServer.ipv6.isEmpty() && settings.getEnableIPv6()) {
829  address = dhtServer.ipv6.toLatin1();
830  } else {
831  ++numNewNodes;
832  continue;
833  }
834 
835  ToxPk pk{dhtServer.publicKey};
836  qDebug() << "Connecting to bootstrap node" << pk.toString();
837  const uint8_t* pkPtr = pk.getData();
838 
839  Tox_Err_Bootstrap error;
840  if (dhtServer.statusUdp) {
841  tox_bootstrap(tox.get(), address.constData(), dhtServer.udpPort, pkPtr, &error);
842  PARSE_ERR(error);
843  }
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);
848  PARSE_ERR(error);
849  }
850  }
851 }
852 
853 void Core::onFriendRequest(Tox*, const uint8_t* cFriendPk, const uint8_t* cMessage,
854  size_t cMessageSize, void* core)
855 {
856  ToxPk friendPk(cFriendPk);
857  QString requestMessage = ToxString(cMessage, cMessageSize).getQString();
858  emit static_cast<Core*>(core)->friendRequestReceived(friendPk, requestMessage);
859 }
860 
861 void Core::onFriendMessage(Tox*, uint32_t friendId, Tox_Message_Type type, const uint8_t* cMessage,
862  size_t cMessageSize, void* core)
863 {
864  bool isAction = (type == TOX_MESSAGE_TYPE_ACTION);
865  QString msg = ToxString(cMessage, cMessageSize).getQString();
866  emit static_cast<Core*>(core)->friendMessageReceived(friendId, msg, isAction);
867 }
868 
869 void Core::onFriendNameChange(Tox*, uint32_t friendId, const uint8_t* cName, size_t cNameSize, void* core)
870 {
871  QString newName = ToxString(cName, cNameSize).getQString();
872  // no saveRequest, this callback is called on every connection, not just on name change
873  emit static_cast<Core*>(core)->friendUsernameChanged(friendId, newName);
874 }
875 
876 void Core::onFriendTypingChange(Tox*, uint32_t friendId, bool isTyping, void* core)
877 {
878  emit static_cast<Core*>(core)->friendTypingChanged(friendId, isTyping);
879 }
880 
881 void Core::onStatusMessageChanged(Tox*, uint32_t friendId, const uint8_t* cMessage,
882  size_t cMessageSize, void* core)
883 {
884  QString message = ToxString(cMessage, cMessageSize).getQString();
885  // no saveRequest, this callback is called on every connection, not just on name change
886  emit static_cast<Core*>(core)->friendStatusMessageChanged(friendId, message);
887 }
888 
889 void Core::onUserStatusChanged(Tox*, uint32_t friendId, Tox_User_Status userstatus, void* core)
890 {
891  Status::Status status;
892  switch (userstatus) {
893  case TOX_USER_STATUS_AWAY:
894  status = Status::Status::Away;
895  break;
896 
897  case TOX_USER_STATUS_BUSY:
898  status = Status::Status::Busy;
899  break;
900 
901  default:
902  status = Status::Status::Online;
903  break;
904  }
905 
906  // no saveRequest, this callback is called on every connection, not just on name change
907  emit static_cast<Core*>(core)->friendStatusChanged(friendId, status);
908 }
909 
910 void Core::onConnectionStatusChanged(Tox*, uint32_t friendId, Tox_Connection status, void* vCore)
911 {
912  Core* core = static_cast<Core*>(vCore);
913  Status::Status friendStatus;
914  switch (status)
915  {
916  case TOX_CONNECTION_NONE:
917  friendStatus = Status::Status::Offline;
918  qDebug() << "Disconnected from friend" << friendId;
919  break;
920  case TOX_CONNECTION_TCP:
921  friendStatus = Status::Status::Online;
922  qDebug() << "Connected to friend" << friendId << "through a TCP relay";
923  break;
924  case TOX_CONNECTION_UDP:
925  friendStatus = Status::Status::Online;
926  qDebug() << "Connected to friend" << friendId << "directly with UDP";
927  break;
928  qWarning() << "tox_callback_friend_connection_status returned unknown enum!";
929  }
930 
931  // Ignore Online because it will be emited from onUserStatusChanged
932  bool isOffline = friendStatus == Status::Status::Offline;
933  if (isOffline) {
934  emit core->friendStatusChanged(friendId, friendStatus);
935  core->checkLastOnline(friendId);
936  }
937 }
938 
939 void Core::onGroupInvite(Tox* tox, uint32_t friendId, Tox_Conference_Type type,
940  const uint8_t* cookie, size_t length, void* vCore)
941 {
942  Core* core = static_cast<Core*>(vCore);
943  const QByteArray data(reinterpret_cast<const char*>(cookie), length);
944  const GroupInvite inviteInfo(friendId, type, data);
945  switch (type) {
946  case TOX_CONFERENCE_TYPE_TEXT:
947  qDebug() << QString("Text group invite by %1").arg(friendId);
948  emit core->groupInviteReceived(inviteInfo);
949  break;
950 
951  case TOX_CONFERENCE_TYPE_AV:
952  qDebug() << QString("AV group invite by %1").arg(friendId);
953  emit core->groupInviteReceived(inviteInfo);
954  break;
955 
956  default:
957  qWarning() << "Group invite with unknown type " << type;
958  }
959 }
960 
961 void Core::onGroupMessage(Tox*, uint32_t groupId, uint32_t peerId, Tox_Message_Type type,
962  const uint8_t* cMessage, size_t length, void* vCore)
963 {
964  Core* core = static_cast<Core*>(vCore);
965  bool isAction = type == TOX_MESSAGE_TYPE_ACTION;
966  QString message = ToxString(cMessage, length).getQString();
967  emit core->groupMessageReceived(groupId, peerId, message, isAction);
968 }
969 
970 void Core::onGroupPeerListChange(Tox*, uint32_t groupId, void* vCore)
971 {
972  const auto core = static_cast<Core*>(vCore);
973  qDebug() << QString("Group %1 peerlist changed").arg(groupId);
974  // no saveRequest, this callback is called on every connection to group peer, not just on brand new peers
975  emit core->groupPeerlistChanged(groupId);
976 }
977 
978 void Core::onGroupPeerNameChange(Tox*, uint32_t groupId, uint32_t peerId, const uint8_t* name,
979  size_t length, void* vCore)
980 {
981  const auto newName = ToxString(name, length).getQString();
982  qDebug() << QString("Group %1, peer %2, name changed to %3").arg(groupId).arg(peerId).arg(newName);
983  auto* core = static_cast<Core*>(vCore);
984  auto peerPk = core->getGroupPeerPk(groupId, peerId);
985  emit core->groupPeerNameChanged(groupId, peerPk, newName);
986 }
987 
988 void Core::onGroupTitleChange(Tox*, uint32_t groupId, uint32_t peerId, const uint8_t* cTitle,
989  size_t length, void* vCore)
990 {
991  Core* core = static_cast<Core*>(vCore);
992  QString author;
993  // from tox.h: "If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference)."
994  if (peerId != std::numeric_limits<uint32_t>::max()) {
995  author = core->getGroupPeerName(groupId, peerId);
996  }
997  emit core->saveRequest();
998  emit core->groupTitleChanged(groupId, author, ToxString(cTitle, length).getQString());
999 }
1000 
1004 void Core::onLosslessPacket(Tox*, uint32_t friendId,
1005  const uint8_t* data, size_t length, void* vCore)
1006 {
1007  Core* core = static_cast<Core*>(vCore);
1008  core->ext->onLosslessPacket(friendId, data, length);
1009 }
1010 
1011 void Core::onReadReceiptCallback(Tox*, uint32_t friendId, uint32_t receipt, void* core)
1012 {
1013  emit static_cast<Core*>(core)->receiptRecieved(friendId, ReceiptNum{receipt});
1014 }
1015 
1016 void Core::acceptFriendRequest(const ToxPk& friendPk)
1017 {
1018  QMutexLocker ml{&coreLoopLock};
1019  Tox_Err_Friend_Add error;
1020  uint32_t friendId = tox_friend_add_norequest(tox.get(), friendPk.getData(), &error);
1021  if (PARSE_ERR(error)) {
1022  emit saveRequest();
1023  emit friendAdded(friendId, friendPk);
1024  } else {
1025  emit failedToAddFriend(friendPk);
1026  }
1027 }
1028 
1035 QString Core::getFriendRequestErrorMessage(const ToxId& friendId, const QString& message) const
1036 {
1037  QMutexLocker ml{&coreLoopLock};
1038 
1039  if (!friendId.isValid()) {
1040  return tr("Invalid Tox ID", "Error while sending friend request");
1041  }
1042 
1043  if (message.isEmpty()) {
1044  return tr("You need to write a message with your request",
1045  "Error while sending friend request");
1046  }
1047 
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");
1050  }
1051 
1052  if (hasFriendWithPublicKey(friendId.getPublicKey())) {
1053  return tr("Friend is already added", "Error while sending friend request");
1054  }
1055 
1056  return QString{};
1057 }
1058 
1059 void Core::requestFriendship(const ToxId& friendId, const QString& message)
1060 {
1061  QMutexLocker ml{&coreLoopLock};
1062 
1063  ToxPk friendPk = friendId.getPublicKey();
1064  QString errorMessage = getFriendRequestErrorMessage(friendId, message);
1065  if (!errorMessage.isNull()) {
1066  emit failedToAddFriend(friendPk, errorMessage);
1067  emit saveRequest();
1068  return;
1069  }
1070 
1071  ToxString cMessage(message);
1072  Tox_Err_Friend_Add error;
1073  uint32_t friendNumber =
1074  tox_friend_add(tox.get(), friendId.getBytes(), cMessage.data(), cMessage.size(), &error);
1075  if (PARSE_ERR(error)) {
1076  qDebug() << "Requested friendship from " << friendNumber;
1077  emit saveRequest();
1078  emit friendAdded(friendNumber, friendPk);
1079  emit requestSent(friendPk, message);
1080  } else {
1081  qDebug() << "Failed to send friend request";
1082  emit failedToAddFriend(friendPk);
1083  }
1084 }
1085 
1086 bool Core::sendMessageWithType(uint32_t friendId, const QString& message, Tox_Message_Type type,
1087  ReceiptNum& receipt)
1088 {
1089  int size = message.toUtf8().size();
1090  auto maxSize = static_cast<int>(getMaxMessageSize());
1091  if (size > maxSize) {
1092  assert(false);
1093  qCritical() << "Core::sendMessageWithType called with message of size:" << size
1094  << "when max is:" << maxSize << ". Ignoring.";
1095  return false;
1096  }
1097 
1098  ToxString cMessage(message);
1099  Tox_Err_Friend_Send_Message error;
1100  receipt = ReceiptNum{tox_friend_send_message(tox.get(), friendId, type, cMessage.data(),
1101  cMessage.size(), &error)};
1102  if (PARSE_ERR(error)) {
1103  return true;
1104  }
1105  return false;
1106 }
1107 
1108 bool Core::sendMessage(uint32_t friendId, const QString& message, ReceiptNum& receipt)
1109 {
1110  QMutexLocker ml(&coreLoopLock);
1111  return sendMessageWithType(friendId, message, TOX_MESSAGE_TYPE_NORMAL, receipt);
1112 }
1113 
1114 bool Core::sendAction(uint32_t friendId, const QString& action, ReceiptNum& receipt)
1115 {
1116  QMutexLocker ml(&coreLoopLock);
1117  return sendMessageWithType(friendId, action, TOX_MESSAGE_TYPE_ACTION, receipt);
1118 }
1119 
1120 void Core::sendTyping(uint32_t friendId, bool typing)
1121 {
1122  QMutexLocker ml{&coreLoopLock};
1123 
1124  Tox_Err_Set_Typing error;
1125  tox_self_set_typing(tox.get(), friendId, typing, &error);
1126  if (!PARSE_ERR(error)) {
1127  emit failedToSetTyping(typing);
1128  }
1129 }
1130 
1131 void Core::sendGroupMessageWithType(int groupId, const QString& message, Tox_Message_Type type)
1132 {
1133  QMutexLocker ml{&coreLoopLock};
1134 
1135  int size = message.toUtf8().size();
1136  auto maxSize = static_cast<int>(getMaxMessageSize());
1137  if (size > maxSize) {
1138  qCritical() << "Core::sendMessageWithType called with message of size:" << size
1139  << "when max is:" << maxSize << ". Ignoring.";
1140  return;
1141  }
1142 
1143  ToxString cMsg(message);
1144  Tox_Err_Conference_Send_Message error;
1145  tox_conference_send_message(tox.get(), groupId, type, cMsg.data(), cMsg.size(), &error);
1146  if (!PARSE_ERR(error)) {
1147  emit groupSentFailed(groupId);
1148  return;
1149  }
1150 }
1151 
1152 void Core::sendGroupMessage(int groupId, const QString& message)
1153 {
1154  QMutexLocker ml{&coreLoopLock};
1155 
1156  sendGroupMessageWithType(groupId, message, TOX_MESSAGE_TYPE_NORMAL);
1157 }
1158 
1159 void Core::sendGroupAction(int groupId, const QString& message)
1160 {
1161  QMutexLocker ml{&coreLoopLock};
1162 
1163  sendGroupMessageWithType(groupId, message, TOX_MESSAGE_TYPE_ACTION);
1164 }
1165 
1166 void Core::changeGroupTitle(int groupId, const QString& title)
1167 {
1168  QMutexLocker ml{&coreLoopLock};
1169 
1170  ToxString cTitle(title);
1171  Tox_Err_Conference_Title error;
1172  tox_conference_set_title(tox.get(), groupId, cTitle.data(), cTitle.size(), &error);
1173  if (PARSE_ERR(error)) {
1174  emit saveRequest();
1175  emit groupTitleChanged(groupId, getUsername(), title);
1176  }
1177 }
1178 
1179 void Core::removeFriend(uint32_t friendId)
1180 {
1181  QMutexLocker ml{&coreLoopLock};
1182 
1183  Tox_Err_Friend_Delete error;
1184  tox_friend_delete(tox.get(), friendId, &error);
1185  if (!PARSE_ERR(error)) {
1186  emit failedToRemoveFriend(friendId);
1187  return;
1188  }
1189 
1190  emit saveRequest();
1191  emit friendRemoved(friendId);
1192 }
1193 
1194 void Core::removeGroup(int groupId)
1195 {
1196  QMutexLocker ml{&coreLoopLock};
1197 
1198  Tox_Err_Conference_Delete error;
1199  tox_conference_delete(tox.get(), groupId, &error);
1200  if (PARSE_ERR(error)) {
1201  emit saveRequest();
1202 
1203  /*
1204  * TODO(sudden6): this is probably not (thread-)safe, but can be ignored for now since
1205  * we don't change av at runtime.
1206  */
1207 
1208  if (av) {
1209  av->leaveGroupCall(groupId);
1210  }
1211  }
1212 }
1213 
1217 QString Core::getUsername() const
1218 {
1219  QMutexLocker ml{&coreLoopLock};
1220 
1221  QString sname;
1222  if (!tox) {
1223  return sname;
1224  }
1225 
1226  int size = tox_self_get_name_size(tox.get());
1227  if (!size) {
1228  return {};
1229  }
1230  std::vector<uint8_t> nameBuf(size);
1231  tox_self_get_name(tox.get(), nameBuf.data());
1232  return ToxString(nameBuf.data(), size).getQString();
1233 }
1234 
1235 void Core::setUsername(const QString& username)
1236 {
1237  QMutexLocker ml{&coreLoopLock};
1238 
1239  if (username == getUsername()) {
1240  return;
1241  }
1242 
1243  ToxString cUsername(username);
1244  Tox_Err_Set_Info error;
1245  tox_self_set_name(tox.get(), cUsername.data(), cUsername.size(), &error);
1246  if (!PARSE_ERR(error)) {
1247  emit failedToSetUsername(username);
1248  return;
1249  }
1250 
1251  emit usernameSet(username);
1252  emit saveRequest();
1253 }
1254 
1259 {
1260  QMutexLocker ml{&coreLoopLock};
1261 
1262  uint8_t friendId[TOX_ADDRESS_SIZE] = {0x00};
1263  tox_self_get_address(tox.get(), friendId);
1264  return ToxId(friendId, TOX_ADDRESS_SIZE);
1265 }
1266 
1272 {
1273  QMutexLocker ml{&coreLoopLock};
1274 
1275  uint8_t selfPk[TOX_PUBLIC_KEY_SIZE] = {0x00};
1276  tox_self_get_public_key(tox.get(), selfPk);
1277  return ToxPk(selfPk);
1278 }
1279 
1283 QPair<QByteArray, QByteArray> Core::getKeypair() const
1284 {
1285  QMutexLocker ml{&coreLoopLock};
1286 
1287  QPair<QByteArray, QByteArray> keypair;
1288  assert(tox != nullptr);
1289 
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()));
1294  keypair.first = pk;
1295  keypair.second = sk;
1296  return keypair;
1297 }
1298 
1302 QString Core::getStatusMessage() const
1303 {
1304  QMutexLocker ml{&coreLoopLock};
1305 
1306  assert(tox != nullptr);
1307 
1308  size_t size = tox_self_get_status_message_size(tox.get());
1309  if (!size) {
1310  return {};
1311  }
1312  std::vector<uint8_t> nameBuf(size);
1313  tox_self_get_status_message(tox.get(), nameBuf.data());
1314  return ToxString(nameBuf.data(), size).getQString();
1315 }
1316 
1321 {
1322  QMutexLocker ml{&coreLoopLock};
1323 
1324  return static_cast<Status::Status>(tox_self_get_status(tox.get()));
1325 }
1326 
1327 void Core::setStatusMessage(const QString& message)
1328 {
1329  QMutexLocker ml{&coreLoopLock};
1330 
1331  if (message == getStatusMessage()) {
1332  return;
1333  }
1334 
1335  ToxString cMessage(message);
1336  Tox_Err_Set_Info error;
1337  tox_self_set_status_message(tox.get(), cMessage.data(), cMessage.size(), &error);
1338  if (!PARSE_ERR(error)) {
1340  return;
1341  }
1342 
1343  emit saveRequest();
1344  emit statusMessageSet(message);
1345 }
1346 
1348 {
1349  QMutexLocker ml{&coreLoopLock};
1350 
1351  Tox_User_Status userstatus;
1352  switch (status) {
1354  userstatus = TOX_USER_STATUS_NONE;
1355  break;
1356 
1357  case Status::Status::Away:
1358  userstatus = TOX_USER_STATUS_AWAY;
1359  break;
1360 
1361  case Status::Status::Busy:
1362  userstatus = TOX_USER_STATUS_BUSY;
1363  break;
1364 
1365  default:
1366  return;
1367  break;
1368  }
1369 
1370  tox_self_set_status(tox.get(), userstatus);
1371  emit saveRequest();
1372  emit statusSet(status);
1373 }
1374 
1379 {
1380  QMutexLocker ml{&coreLoopLock};
1381 
1382  uint32_t fileSize = tox_get_savedata_size(tox.get());
1383  QByteArray data;
1384  data.resize(fileSize);
1385  tox_get_savedata(tox.get(), reinterpret_cast<uint8_t*>(data.data()));
1386  return data;
1387 }
1388 
1390 {
1391  QMutexLocker ml{&coreLoopLock};
1392 
1393  const size_t friendCount = tox_self_get_friend_list_size(tox.get());
1394  if (friendCount == 0) {
1395  return;
1396  }
1397 
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);
1404  if (!PARSE_ERR(keyError)) {
1405  continue;
1406  }
1407  emit friendAdded(ids[i], ToxPk(friendPk));
1408  emit friendUsernameChanged(ids[i], getFriendUsername(ids[i]));
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();
1415  emit friendStatusMessageChanged(ids[i], friendStatusMessage);
1416  }
1417  checkLastOnline(ids[i]);
1418  }
1419 }
1420 
1422 {
1423  QMutexLocker ml{&coreLoopLock};
1424 
1425  const size_t groupCount = tox_conference_get_chatlist_size(tox.get());
1426  if (groupCount == 0) {
1427  return;
1428  }
1429 
1430  std::vector<uint32_t> groupNumbers(groupCount);
1431  tox_conference_get_chatlist(tox.get(), groupNumbers.data());
1432 
1433  for (size_t i = 0; i < groupCount; ++i) {
1434  Tox_Err_Conference_Title error;
1435  QString name;
1436  const auto groupNumber = groupNumbers[i];
1437  size_t titleSize = tox_conference_get_title_size(tox.get(), groupNumber, &error);
1438  const GroupId persistentId = getGroupPersistentId(groupNumber);
1439  const QString defaultName = tr("Groupchat %1").arg(persistentId.toString().left(8));
1440  if (PARSE_ERR(error) || !titleSize) {
1441  std::vector<uint8_t> nameBuf(titleSize);
1442  tox_conference_get_title(tox.get(), groupNumber, nameBuf.data(), &error);
1443  if (PARSE_ERR(error)) {
1444  name = ToxString(nameBuf.data(), titleSize).getQString();
1445  } else {
1446  name = defaultName;
1447  }
1448  } else {
1449  name = defaultName;
1450  }
1451  if (getGroupAvEnabled(groupNumber)) {
1452  if (toxav_groupchat_enable_av(tox.get(), groupNumber, CoreAV::groupCallCallback, this)) {
1453  qCritical() << "Failed to enable audio on loaded group" << groupNumber;
1454  }
1455  }
1456  emit emptyGroupCreated(groupNumber, persistentId, name);
1457  }
1458 }
1459 
1460 void Core::checkLastOnline(uint32_t friendId)
1461 {
1462  QMutexLocker ml{&coreLoopLock};
1463 
1464  Tox_Err_Friend_Get_Last_Online error;
1465  const uint64_t lastOnline = tox_friend_get_last_online(tox.get(), friendId, &error);
1466  if (PARSE_ERR(error)) {
1467  emit friendLastSeenChanged(friendId, QDateTime::fromTime_t(lastOnline));
1468  }
1469 }
1470 
1474 QVector<uint32_t> Core::getFriendList() const
1475 {
1476  QMutexLocker ml{&coreLoopLock};
1477 
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());
1481  return friends;
1482 }
1483 
1484 GroupId Core::getGroupPersistentId(uint32_t groupNumber) const
1485 {
1486  QMutexLocker ml{&coreLoopLock};
1487 
1488  std::vector<uint8_t> idBuff(TOX_CONFERENCE_UID_SIZE);
1489  if (tox_conference_get_id(tox.get(), groupNumber,
1490  idBuff.data())) {
1491  return GroupId{idBuff.data()};
1492  } else {
1493  qCritical() << "Failed to get conference ID of group" << groupNumber;
1494  return {};
1495  }
1496 }
1497 
1502 uint32_t Core::getGroupNumberPeers(int groupId) const
1503 {
1504  QMutexLocker ml{&coreLoopLock};
1505 
1506  Tox_Err_Conference_Peer_Query error;
1507  uint32_t count = tox_conference_peer_count(tox.get(), groupId, &error);
1508  if (!PARSE_ERR(error)) {
1509  return std::numeric_limits<uint32_t>::max();
1510  }
1511 
1512  return count;
1513 }
1514 
1518 QString Core::getGroupPeerName(int groupId, int peerId) const
1519 {
1520  QMutexLocker ml{&coreLoopLock};
1521 
1522  Tox_Err_Conference_Peer_Query error;
1523  size_t length = tox_conference_peer_get_name_size(tox.get(), groupId, peerId, &error);
1524  if (!PARSE_ERR(error) || !length) {
1525  return QString{};
1526  }
1527 
1528  std::vector<uint8_t> nameBuf(length);
1529  tox_conference_peer_get_name(tox.get(), groupId, peerId, nameBuf.data(), &error);
1530  if (!PARSE_ERR(error)) {
1531  return QString{};
1532  }
1533 
1534  return ToxString(nameBuf.data(), length).getQString();
1535 }
1536 
1540 ToxPk Core::getGroupPeerPk(int groupId, int peerId) const
1541 {
1542  QMutexLocker ml{&coreLoopLock};
1543 
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);
1547  if (!PARSE_ERR(error)) {
1548  return ToxPk{};
1549  }
1550 
1551  return ToxPk(friendPk);
1552 }
1553 
1557 QStringList Core::getGroupPeerNames(int groupId) const
1558 {
1559  QMutexLocker ml{&coreLoopLock};
1560 
1561  assert(tox != nullptr);
1562 
1563  uint32_t nPeers = getGroupNumberPeers(groupId);
1564  if (nPeers == std::numeric_limits<uint32_t>::max()) {
1565  qWarning() << "getGroupPeerNames: Unable to get number of peers";
1566  return {};
1567  }
1568 
1569  QStringList names;
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);
1573 
1574  if (!PARSE_ERR(error) || !length) {
1575  names.append(QString());
1576  continue;
1577  }
1578 
1579  std::vector<uint8_t> nameBuf(length);
1580  tox_conference_peer_get_name(tox.get(), groupId, i, nameBuf.data(), &error);
1581  if (PARSE_ERR(error)) {
1582  names.append(ToxString(nameBuf.data(), length).getQString());
1583  } else {
1584  names.append(QString());
1585  }
1586  }
1587 
1588  assert(names.size() == static_cast<int>(nPeers));
1589 
1590  return names;
1591 }
1592 
1598 bool Core::getGroupAvEnabled(int groupId) const
1599 {
1600  QMutexLocker ml{&coreLoopLock};
1601  Tox_Err_Conference_Get_Type error;
1602  Tox_Conference_Type type = tox_conference_get_type(tox.get(), groupId, &error);
1603  PARSE_ERR(error);
1604  // would be nice to indicate to caller that we don't actually know..
1605  return type == TOX_CONFERENCE_TYPE_AV;
1606 }
1607 
1614 uint32_t Core::joinGroupchat(const GroupInvite& inviteInfo)
1615 {
1616  QMutexLocker ml{&coreLoopLock};
1617 
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()};
1624  switch (confType) {
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);
1629  if (!PARSE_ERR(error)) {
1630  groupNum = std::numeric_limits<uint32_t>::max();
1631  }
1632  break;
1633  }
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,
1637  CoreAV::groupCallCallback, const_cast<Core*>(this));
1638  break;
1639  }
1640  default:
1641  qWarning() << "joinGroupchat: Unknown groupchat type " << confType;
1642  }
1643  if (groupNum != std::numeric_limits<uint32_t>::max()) {
1644  emit saveRequest();
1645  emit groupJoined(groupNum, getGroupPersistentId(groupNum));
1646  }
1647  return groupNum;
1648 }
1649 
1650 void Core::groupInviteFriend(uint32_t friendId, int groupId)
1651 {
1652  QMutexLocker ml{&coreLoopLock};
1653 
1654  Tox_Err_Conference_Invite error;
1655  tox_conference_invite(tox.get(), friendId, groupId, &error);
1656  PARSE_ERR(error);
1657 }
1658 
1659 int Core::createGroup(uint8_t type)
1660 {
1661  QMutexLocker ml{&coreLoopLock};
1662 
1663  if (type == TOX_CONFERENCE_TYPE_TEXT) {
1664  Tox_Err_Conference_New error;
1665  uint32_t groupId = tox_conference_new(tox.get(), &error);
1666  if (PARSE_ERR(error)) {
1667  emit saveRequest();
1668  emit emptyGroupCreated(groupId, getGroupPersistentId(groupId));
1669  return groupId;
1670  } else {
1671  return std::numeric_limits<uint32_t>::max();
1672  }
1673  } else if (type == TOX_CONFERENCE_TYPE_AV) {
1674  // unlike tox_conference_new, toxav_add_av_groupchat does not have an error enum, so -1 group number is our
1675  // only indication of an error
1676  int groupId = toxav_add_av_groupchat(tox.get(), CoreAV::groupCallCallback, this);
1677  if (groupId != -1) {
1678  emit saveRequest();
1679  emit emptyGroupCreated(groupId, getGroupPersistentId(groupId));
1680  } else {
1681  qCritical() << "Unknown error creating AV groupchat";
1682  }
1683  return groupId;
1684  } else {
1685  qWarning() << "createGroup: Unknown type " << type;
1686  return -1;
1687  }
1688 }
1689 
1693 bool Core::isFriendOnline(uint32_t friendId) const
1694 {
1695  QMutexLocker ml{&coreLoopLock};
1696 
1697  Tox_Err_Friend_Query error;
1698  Tox_Connection connection = tox_friend_get_connection_status(tox.get(), friendId, &error);
1699  PARSE_ERR(error);
1700  return connection != TOX_CONNECTION_NONE;
1701 }
1702 
1706 bool Core::hasFriendWithPublicKey(const ToxPk& publicKey) const
1707 {
1708  QMutexLocker ml{&coreLoopLock};
1709 
1710  if (publicKey.isEmpty()) {
1711  return false;
1712  }
1713 
1714  Tox_Err_Friend_By_Public_Key error;
1715  (void)tox_friend_by_public_key(tox.get(), publicKey.getData(), &error);
1716  return PARSE_ERR(error);
1717 }
1718 
1722 ToxPk Core::getFriendPublicKey(uint32_t friendNumber) const
1723 {
1724  QMutexLocker ml{&coreLoopLock};
1725 
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);
1729  if (!PARSE_ERR(error)) {
1730  qWarning() << "getFriendPublicKey: Getting public key failed";
1731  return ToxPk();
1732  }
1733 
1734  return ToxPk(rawid);
1735 }
1736 
1740 QString Core::getFriendUsername(uint32_t friendnumber) const
1741 {
1742  QMutexLocker ml{&coreLoopLock};
1743 
1744  Tox_Err_Friend_Query error;
1745  size_t nameSize = tox_friend_get_name_size(tox.get(), friendnumber, &error);
1746  if (!PARSE_ERR(error) || !nameSize) {
1747  return QString();
1748  }
1749 
1750  std::vector<uint8_t> nameBuf(nameSize);
1751  tox_friend_get_name(tox.get(), friendnumber, nameBuf.data(), &error);
1752  if (!PARSE_ERR(error)) {
1753  return QString();
1754  }
1755  return ToxString(nameBuf.data(), nameSize).getQString();
1756 }
1757 
1758 uint64_t Core::getMaxMessageSize() const
1759 {
1760  /*
1761  * TODO: Remove this hack; the reported max message length we receive from c-toxcore
1762  * as of 08-02-2019 is inaccurate, causing us to generate too large messages when splitting
1763  * them up.
1764  *
1765  * The inconsistency lies in c-toxcore group.c:2480 using MAX_GROUP_MESSAGE_DATA_LEN to verify
1766  * message size is within limit, but tox_max_message_length giving a different size limit to us.
1767  *
1768  * (uint32_t tox_max_message_length(void); declared in tox.h, unable to see explicit definition)
1769  */
1770  return tox_max_message_length() - 50;
1771 }
1772 
1773 QString Core::getPeerName(const ToxPk& id) const
1774 {
1775  QMutexLocker ml{&coreLoopLock};
1776 
1777  Tox_Err_Friend_By_Public_Key keyError;
1778  uint32_t friendId = tox_friend_by_public_key(tox.get(), id.getData(), &keyError);
1779  if (!PARSE_ERR(keyError)) {
1780  qWarning() << "getPeerName: No such peer";
1781  return {};
1782  }
1783 
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) {
1787  return {};
1788  }
1789 
1790  std::vector<uint8_t> nameBuf(nameSize);
1791  tox_friend_get_name(tox.get(), friendId, nameBuf.data(), &queryError);
1792  if (!PARSE_ERR(queryError)) {
1793  qWarning() << "getPeerName: Can't get name of friend " + QString().setNum(friendId);
1794  return {};
1795  }
1796 
1797  return ToxString(nameBuf.data(), nameSize).getQString();
1798 }
1799 
1804 void Core::setNospam(uint32_t nospam)
1805 {
1806  QMutexLocker ml{&coreLoopLock};
1807 
1808  tox_self_set_nospam(tox.get(), nospam);
1809  emit idSet(getSelfId());
1810 }
Core::groupTitleChanged
void groupTitleChanged(int groupnumber, const QString &author, const QString &title)
Core::setNospam
void setNospam(uint32_t nospam)
Sets the NoSpam value to prevent friend request spam.
Definition: core.cpp:1804
Core::getFriendUsername
QString getFriendUsername(uint32_t friendNumber) const
Get the username of a friend.
Definition: core.cpp:1740
Core::failedToSetTyping
void failedToSetTyping(bool typing)
Core::getTox
Tox * getTox() const
Definition: core.cpp:723
profile.h
ContactId::getData
const uint8_t * getData() const
Returns a pointer to the raw id data.
Definition: contactid.cpp:88
CoreAV::groupCallCallback
static void groupCallCallback(void *tox, uint32_t group, uint32_t peer, const int16_t *data, unsigned samples, uint8_t channels, uint32_t sample_rate, void *core)
Called from Tox API when group call receives audio data.
Definition: coreav.cpp:467
Core::onFriendRequest
static void onFriendRequest(Tox *tox, const uint8_t *cUserId, const uint8_t *cMessage, size_t cMessageSize, void *core)
Definition: core.cpp:853
Status::Status
Status
Definition: status.h:28
Core::failedToRemoveFriend
void failedToRemoveFriend(uint32_t friendId)
Core::ToxPtr
std::unique_ptr< Tox, ToxDeleter > ToxPtr
Definition: core.h:263
Core::statusSet
void statusSet(Status::Status status)
Core::sendMessageWithType
bool sendMessageWithType(uint32_t friendId, const QString &message, Tox_Message_Type type, ReceiptNum &receipt)
Definition: core.cpp:1086
ToxString::getQString
QString getQString() const
Gets the string as QString.
Definition: toxstring.cpp:84
Core::start
void start()
Starts toxcore and it's event loop, can be called from any thread.
Definition: core.cpp:698
Core::connected
void connected()
Core::sendAction
bool sendAction(uint32_t friendId, const QString &action, ReceiptNum &receipt) override
Definition: core.cpp:1114
Core::~Core
~Core()
Definition: core.cpp:499
Status::Status::Offline
@ Offline
GroupInvite::getType
uint8_t getType() const
Definition: groupinvite.cpp:47
dhtserver.h
Core::acceptFriendRequest
void acceptFriendRequest(const ToxPk &friendPk)
Definition: core.cpp:1016
Core::getFriendRequestErrorMessage
QString getFriendRequestErrorMessage(const ToxId &friendId, const QString &message) const
Checks that sending friendship request is correct and returns error message accordingly.
Definition: core.cpp:1035
Core::getGroupPeerName
QString getGroupPeerName(int groupId, int peerId) const override
Get the name of a peer of a group.
Definition: core.cpp:1518
Core::coreLoopLock
CompatibleRecursiveMutex coreLoopLock
Definition: core.h:271
Core::getSelfPublicKey
ToxPk getSelfPublicKey() const override
Gets self public key.
Definition: core.cpp:1271
Core::failedToSetStatusMessage
void failedToSetStatusMessage(const QString &message)
Core::friendRequestReceived
void friendRequestReceived(const ToxPk &friendPk, const QString &message)
icoresettings.h
ContactId::isEmpty
bool isEmpty() const
Checks if the ContactId contains a id.
Definition: contactid.cpp:110
Core::onConnectionStatusChanged
static void onConnectionStatusChanged(Tox *tox, uint32_t friendId, Tox_Connection status, void *vCore)
Definition: core.cpp:910
Core::saveRequest
void saveRequest()
Core::registerCallbacks
static void registerCallbacks(Tox *tox)
Registers all toxcore callbacks.
Definition: core.cpp:515
Core::toxTimer
QTimer * toxTimer
Definition: core.h:269
ToxOptions::makeToxOptions
static std::unique_ptr< ToxOptions > makeToxOptions(const QByteArray &savedata, const ICoreSettings &s)
Initializes a ToxOptions instance.
Definition: toxoptions.cpp:69
IBootstrapListGenerator
Definition: ibootstraplistgenerator.h:25
ToxId::isValid
bool isValid() const
Check it it's a valid Tox ID by verifying the checksum.
Definition: toxid.cpp:239
GroupInvite
This class contains information needed to create a group invite.
Definition: groupinvite.h:26
Core::friendStatusMessageChanged
void friendStatusMessageChanged(uint32_t friendId, const QString &message)
ASSERT_CORE_THREAD
#define ASSERT_CORE_THREAD
Definition: core.cpp:53
Status::Status::Busy
@ Busy
Core::failedToSetUsername
void failedToSetUsername(const QString &username)
ToxId::getBytes
const uint8_t * getBytes() const
Gets the ToxID as bytes, convenience function for toxcore interface.
Definition: toxid.cpp:177
ToxCorePtr
std::unique_ptr< Core > ToxCorePtr
Definition: core.h:57
ICoreSettings::getEnableIPv6
virtual bool getEnableIPv6() const =0
Core::checkConnection
bool checkConnection()
Definition: core.cpp:773
Core::ext
std::unique_ptr< CoreExt > ext
Definition: core.h:268
Core::av
CoreAV * av
Definition: core.h:267
Core::TOX_EXT
static const QString TOX_EXT
Definition: core.h:89
coreext.h
Core::ToxCoreErrors::FAILED_TO_START
@ FAILED_TO_START
QList
Definition: friendlist.h:25
Core::groupJoined
void groupJoined(int groupnumber, GroupId groupId)
Core::loadFriends
void loadFriends()
Definition: core.cpp:1389
Core::friendMessageReceived
void friendMessageReceived(uint32_t friendId, const QString &message, bool isAction)
Core::failedToAddFriend
void failedToAddFriend(const ToxPk &friendPk, const QString &errorInfo=QString())
Core::getCoreFile
CoreFile * getCoreFile() const
Definition: core.cpp:718
Core::onReadReceiptCallback
static void onReadReceiptCallback(Tox *tox, uint32_t friendId, uint32_t receipt, void *core)
Definition: core.cpp:1011
Core::onGroupTitleChange
static void onGroupTitleChange(Tox *tox, uint32_t groupId, uint32_t peerId, const uint8_t *cTitle, size_t length, void *vCore)
Definition: core.cpp:988
Core::onFriendNameChange
static void onFriendNameChange(Tox *tox, uint32_t friendId, const uint8_t *cName, size_t cNameSize, void *core)
Definition: core.cpp:869
toxstring.h
Core::coreThread
std::unique_ptr< QThread > coreThread
Definition: core.h:273
Core::onGroupPeerNameChange
static void onGroupPeerNameChange(Tox *, uint32_t groupId, uint32_t peerId, const uint8_t *name, size_t length, void *core)
Definition: core.cpp:978
Core::getAv
const CoreAV * getAv() const
Definition: core.cpp:703
Status::Status::Online
@ Online
Core::tolerance
int tolerance
Definition: core.h:277
Core::file
std::unique_ptr< CoreFile > file
Definition: core.h:266
Core::friendLastSeenChanged
void friendLastSeenChanged(uint32_t friendId, const QDateTime &dateTime)
toxoptions.h
Core::settings
const ICoreSettings & settings
Definition: core.h:275
Core::onFriendMessage
static void onFriendMessage(Tox *tox, uint32_t friendId, Tox_Message_Type type, const uint8_t *cMessage, size_t cMessageSize, void *core)
Definition: core.cpp:861
Core::changeGroupTitle
void changeGroupTitle(int groupId, const QString &title)
Definition: core.cpp:1166
Core::friendAdded
void friendAdded(uint32_t friendId, const ToxPk &friendPk)
Core::groupMessageReceived
void groupMessageReceived(int groupnumber, int peernumber, const QString &message, bool isAction)
coreav.h
Core::isConnected
bool isConnected
Definition: core.h:276
ToxString
Helper to convert safely between strings in the c-toxcore representation and QString.
Definition: toxstring.h:27
Core::isFriendOnline
bool isFriendOnline(uint32_t friendId) const
Checks if a friend is online. Unknown friends are considered offline.
Definition: core.cpp:1693
Core::receiptRecieved
void receiptRecieved(int friedId, ReceiptNum receipt)
Core::getSelfId
ToxId getSelfId() const override
Returns our Tox ID.
Definition: core.cpp:1258
Core::getUsername
QString getUsername() const override
Returns our username, or an empty string on failure.
Definition: core.cpp:1217
Core::emptyGroupCreated
void emptyGroupCreated(int groupnumber, const GroupId groupId, const QString &title=QString())
Core::sendGroupMessageWithType
void sendGroupMessageWithType(int groupId, const QString &message, Tox_Message_Type type)
Definition: core.cpp:1131
CoreExt
Definition: coreext.h:41
Core::getGroupPeerPk
ToxPk getGroupPeerPk(int groupId, int peerId) const override
Get the public key of a peer of a group.
Definition: core.cpp:1540
Core::getMaxMessageSize
uint64_t getMaxMessageSize() const
Definition: core.cpp:1758
HistMessageContentType::message
@ message
Core::getToxSaveData
QByteArray getToxSaveData()
Returns the unencrypted tox save data.
Definition: core.cpp:1378
PARSE_ERR
#define PARSE_ERR(err)
Parse and log toxcore error enums.
Definition: core.cpp:62
ToxId::getPublicKey
ToxPk getPublicKey() const
Gets the Public Key part of the ToxID.
Definition: toxid.cpp:190
ToxPk
This class represents a Tox Public Key, which is a part of Tox ID.
Definition: toxpk.h:26
Core::getGroupPersistentId
GroupId getGroupPersistentId(uint32_t groupNumber) const override
Definition: core.cpp:1484
Core::bootstrapListGenerator
const IBootstrapListGenerator & bootstrapListGenerator
Definition: core.h:274
Core::ToxCoreErrors
ToxCoreErrors
Definition: core.h:67
Core::sendGroupAction
void sendGroupAction(int groupId, const QString &message) override
Definition: core.cpp:1159
Core::getGroupPeerNames
QStringList getGroupPeerNames(int groupId) const override
Get the names of the peers of a group.
Definition: core.cpp:1557
groupinvite.h
Core::getFriendPublicKey
ToxPk getFriendPublicKey(uint32_t friendNumber) const
Get the public key part of the ToxID only.
Definition: core.cpp:1722
Core::onGroupInvite
static void onGroupInvite(Tox *tox, uint32_t friendId, Tox_Conference_Type type, const uint8_t *cookie, size_t length, void *vCore)
Definition: core.cpp:939
Status::Status::Away
@ Away
Core::getCoreLoopLock
CompatibleRecursiveMutex & getCoreLoopLock() const
Definition: core.cpp:728
Core::sendGroupMessage
void sendGroupMessage(int groupId, const QString &message) override
Definition: core.cpp:1152
Core::process
void process()
Processes toxcore events and ensure we stay connected, called by its own timer.
Definition: core.cpp:746
Core::usernameSet
void usernameSet(const QString &username)
Core::requestFriendship
void requestFriendship(const ToxId &friendAddress, const QString &message)
Definition: core.cpp:1059
Core::setStatus
void setStatus(Status::Status status)
Definition: core.cpp:1347
ToxId
This class represents a Tox ID.
Definition: toxid.h:29
CoreAV::leaveGroupCall
void leaveGroupCall(int groupNum)
Will not leave the group, just stop the call.
Definition: coreav.cpp:571
Core::disconnected
void disconnected()
Core::groupPeerlistChanged
void groupPeerlistChanged(int groupnumber)
Core::removeGroup
void removeGroup(int groupId)
Definition: core.cpp:1194
Core::onFriendTypingChange
static void onFriendTypingChange(Tox *tox, uint32_t friendId, bool isTyping, void *core)
Definition: core.cpp:876
GroupId
This class represents a long term persistent group identifier.
Definition: groupid.h:26
Core::onUserStatusChanged
static void onUserStatusChanged(Tox *tox, uint32_t friendId, Tox_User_Status userstatus, void *core)
Definition: core.cpp:889
Core::getGroupNumberPeers
uint32_t getGroupNumberPeers(int groupId) const override
Get number of peers in the conference.
Definition: core.cpp:1502
Core::statusMessageSet
void statusMessageSet(const QString &message)
Core::setUsername
void setUsername(const QString &username)
Definition: core.cpp:1235
Core::onGroupMessage
static void onGroupMessage(Tox *tox, uint32_t groupId, uint32_t peerId, Tox_Message_Type type, const uint8_t *cMessage, size_t length, void *vCore)
Definition: core.cpp:961
corefile.h
Core::checkLastOnline
void checkLastOnline(uint32_t friendId)
Definition: core.cpp:1460
Core::ToxCoreErrors::ERROR_ALLOC
@ ERROR_ALLOC
Core::createGroup
int createGroup(uint8_t type=TOX_CONFERENCE_TYPE_AV)
Definition: core.cpp:1659
Core::ToxCoreErrors::INVALID_SAVE
@ INVALID_SAVE
CoreFile::makeCoreFile
static CoreFilePtr makeCoreFile(Core *core, Tox *tox, CompatibleRecursiveMutex &coreLoopLock)
Definition: corefile.cpp:42
GroupInvite::getFriendId
uint32_t getFriendId() const
Definition: groupinvite.cpp:42
Core::ToxCoreErrors::BAD_PROXY
@ BAD_PROXY
Core::tox
ToxPtr tox
Definition: core.h:264
Core::onStarted
void onStarted()
Definition: core.cpp:669
Core::sendMessage
bool sendMessage(uint32_t friendId, const QString &message, ReceiptNum &receipt) override
Definition: core.cpp:1108
Core::idSet
void idSet(const ToxId &id)
Core::Core
Core(QThread *coreThread, IBootstrapListGenerator &_bootstrapNodes, const ICoreSettings &settings)
Definition: core.cpp:486
Core::getExt
const CoreExt * getExt() const
Definition: core.cpp:733
Core::getKeypair
QPair< QByteArray, QByteArray > getKeypair() const
Returns our public and private keys.
Definition: core.cpp:1283
Core::friendTypingChanged
void friendTypingChanged(uint32_t friendId, bool isTyping)
core.h
IBootstrapListGenerator::getBootstrapnodes
virtual QList< DhtServer > getBootstrapnodes() const =0
Core::onStatusMessageChanged
static void onStatusMessageChanged(Tox *tox, uint32_t friendId, const uint8_t *cMessage, size_t cMessageSize, void *core)
Definition: core.cpp:881
ToxString::size
size_t size() const
Get the number of bytes in the string.
Definition: toxstring.cpp:75
Core::getPeerName
QString getPeerName(const ToxPk &id) const
Definition: core.cpp:1773
ReceiptNum
NamedType< uint32_t, struct ReceiptNumTag, Orderable > ReceiptNum
Definition: receiptnum.h:27
ContactId::toString
QString toString() const
Converts the ContactId to a uppercase hex string.
Definition: contactid.cpp:78
Core::getStatus
Status::Status getStatus() const
Returns our user status.
Definition: core.cpp:1320
Core::makeToxCore
static ToxCorePtr makeToxCore(const QByteArray &savedata, const ICoreSettings &settings, IBootstrapListGenerator &bootstrapNodes, ToxCoreErrors *err=nullptr)
Factory method for the Core object.
Definition: core.cpp:539
Core::setAv
void setAv(CoreAV *coreAv)
Definition: core.cpp:713
Core::onGroupPeerListChange
static void onGroupPeerListChange(Tox *, uint32_t groupId, void *core)
Definition: core.cpp:970
ICoreSettings
Definition: icoresettings.h:28
Core::getGroupAvEnabled
bool getGroupAvEnabled(int groupId) const override
Check, that group has audio or video stream.
Definition: core.cpp:1598
CORE_DISCONNECT_TOLERANCE
#define CORE_DISCONNECT_TOLERANCE
Definition: core.h:261
Core::loadGroups
void loadGroups()
Definition: core.cpp:1421
Core::setStatusMessage
void setStatusMessage(const QString &message)
Definition: core.cpp:1327
Core::friendStatusChanged
void friendStatusChanged(uint32_t friendId, Status::Status status)
Core::requestSent
void requestSent(const ToxPk &friendPk, const QString &message)
Core::joinGroupchat
uint32_t joinGroupchat(const GroupInvite &inviteInfo)
Accept a groupchat invite.
Definition: core.cpp:1614
Core::groupSentFailed
void groupSentFailed(int groupId)
Core::removeFriend
void removeFriend(uint32_t friendId)
Definition: core.cpp:1179
CoreExt::makeCoreExt
static std::unique_ptr< CoreExt > makeCoreExt(Tox *core)
Creates a CoreExt instance. Using a pointer here makes our registrations with extensions significantl...
Definition: coreext.cpp:35
GroupInvite::getInvite
QByteArray getInvite() const
Definition: groupinvite.cpp:52
ToxString::data
const uint8_t * data() const
Returns a pointer to the beginning of the string data.
Definition: toxstring.cpp:66
Core::getStatusMessage
QString getStatusMessage() const
Returns our status message, or an empty string on failure.
Definition: core.cpp:1302
Core::bootstrapDht
void bootstrapDht()
Connects us to the Tox network.
Definition: core.cpp:810
Core::friendUsernameChanged
void friendUsernameChanged(uint32_t friendId, const QString &username)
CoreFile
Manages the file transfer service of toxcore.
Definition: corefile.h:46
Core::groupInviteReceived
void groupInviteReceived(const GroupInvite &inviteInfo)
CoreExt::onFriendStatusChanged
void onFriendStatusChanged(uint32_t friendId, Status::Status status)
Definition: coreext.cpp:157
Core::getFriendList
QVector< uint32_t > getFriendList() const
Returns the list of friendIds in our friendlist, an empty list on error.
Definition: core.cpp:1474
Core::friendRemoved
void friendRemoved(uint32_t friendId)
CoreAV
Definition: coreav.h:47
status.h
Core::groupInviteFriend
void groupInviteFriend(uint32_t friendId, int groupId)
Definition: core.cpp:1650
Core
Definition: core.h:59
Core::sendTyping
void sendTyping(uint32_t friendId, bool typing)
Definition: core.cpp:1120
Core::hasFriendWithPublicKey
bool hasFriendWithPublicKey(const ToxPk &publicKey) const
Checks if we have a friend by public key.
Definition: core.cpp:1706
toxlogger.h
Core::onLosslessPacket
static void onLosslessPacket(Tox *tox, uint32_t friendId, const uint8_t *data, size_t length, void *core)
Handling of custom lossless packets received by toxcore. Currently only used to forward toxext packet...
Definition: core.cpp:1004
ibootstraplistgenerator.h