2014-06-25 04:11:11 +08:00
/*
Copyright ( C ) 2013 by Maxim Biro < nurupo . contributions @ gmail . com >
This file is part of Tox Qt GUI .
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the COPYING file for more details .
*/
# include "core.h"
2014-09-30 02:28:59 +08:00
# include "misc/cdata.h"
# include "misc/cstring.h"
# include "misc/settings.h"
2014-06-30 10:39:43 +08:00
# include "widget/widget.h"
2014-10-19 01:38:47 +08:00
# include "historykeeper.h"
2014-11-17 02:04:45 +08:00
# include "src/audio.h"
2014-06-25 04:11:11 +08:00
2014-09-11 21:44:34 +08:00
# include <tox/tox.h>
2014-10-12 05:54:25 +08:00
# include <tox/toxencryptsave.h>
2014-09-11 21:44:34 +08:00
2014-08-02 04:24:02 +08:00
# include <ctime>
2014-08-29 03:56:55 +08:00
# include <functional>
2014-08-02 04:24:02 +08:00
2014-06-25 04:11:11 +08:00
# include <QDebug>
# include <QDir>
# include <QFile>
# include <QSaveFile>
# include <QStandardPaths>
# include <QThread>
2014-09-11 21:44:34 +08:00
# include <QTimer>
# include <QCoreApplication>
# include <QDateTime>
2014-09-21 18:30:10 +08:00
# include <QList>
2014-09-24 22:51:16 +08:00
# include <QBuffer>
2014-10-01 19:23:00 +08:00
# include <QMessageBox>
2014-10-29 23:40:09 +08:00
# include <QMutexLocker>
2014-06-25 04:11:11 +08:00
2014-06-29 01:09:16 +08:00
const QString Core : : CONFIG_FILE_NAME = " data " ;
2014-07-17 06:43:30 +08:00
const QString Core : : TOX_EXT = " .tox " ;
2014-06-26 04:43:28 +08:00
QList < ToxFile > Core : : fileSendQueue ;
2014-06-27 01:45:47 +08:00
QList < ToxFile > Core : : fileRecvQueue ;
2014-11-13 19:18:04 +08:00
QHash < int , ToxGroupCall > Core : : groupCalls ;
2014-11-13 20:11:23 +08:00
QThread * Core : : coreThread { nullptr } ;
2014-06-25 04:11:11 +08:00
2014-12-29 01:26:35 +08:00
# define MAX_GROUP_MESSAGE_LEN 1024
2014-11-13 20:11:23 +08:00
Core : : Core ( Camera * cam , QThread * CoreThread , QString loadPath ) :
2014-11-06 22:12:10 +08:00
tox ( nullptr ) , camera ( cam ) , loadPath ( loadPath ) , ready { false }
2014-06-25 04:11:11 +08:00
{
2014-10-14 05:17:42 +08:00
qDebug ( ) < < " Core: loading Tox from " < < loadPath ;
2014-11-13 20:11:23 +08:00
coreThread = CoreThread ;
2014-11-18 08:25:15 +08:00
2014-11-20 05:26:04 +08:00
Audio : : getInstance ( ) ;
2014-11-13 20:11:23 +08:00
2014-07-12 18:50:40 +08:00
videobuf = new uint8_t [ videobufsize ] ;
2014-10-22 21:36:36 +08:00
for ( int i = 0 ; i < ptCounter ; i + + )
2014-10-24 19:25:40 +08:00
pwsaltedkeys [ i ] = nullptr ;
2014-10-22 21:36:36 +08:00
2014-06-25 04:11:11 +08:00
toxTimer = new QTimer ( this ) ;
toxTimer - > setSingleShot ( true ) ;
connect ( toxTimer , & QTimer : : timeout , this , & Core : : process ) ;
2014-06-27 01:45:47 +08:00
//connect(fileTimer, &QTimer::timeout, this, &Core::fileHeartbeat);
2014-09-29 07:08:07 +08:00
connect ( & Settings : : getInstance ( ) , & Settings : : dhtServerListChanged , this , & Core : : process ) ;
2014-07-12 00:05:18 +08:00
connect ( this , SIGNAL ( fileTransferFinished ( ToxFile ) ) , this , SLOT ( onFileTransferFinished ( ToxFile ) ) ) ;
2014-07-07 06:03:37 +08:00
for ( int i = 0 ; i < TOXAV_MAX_CALLS ; i + + )
{
2014-11-17 02:04:45 +08:00
calls [ i ] . active = false ;
calls [ i ] . alSource = 0 ;
2014-07-07 15:37:05 +08:00
calls [ i ] . sendAudioTimer = new QTimer ( ) ;
calls [ i ] . sendVideoTimer = new QTimer ( ) ;
2014-07-07 06:03:37 +08:00
calls [ i ] . sendAudioTimer - > moveToThread ( coreThread ) ;
calls [ i ] . sendVideoTimer - > moveToThread ( coreThread ) ;
connect ( calls [ i ] . sendVideoTimer , & QTimer : : timeout , [ this , i ] ( ) { sendCallVideo ( i ) ; } ) ;
}
2014-08-30 20:40:41 +08:00
// OpenAL init
2015-01-25 02:32:07 +08:00
QString outDevDescr = Settings : : getInstance ( ) . getOutDev ( ) ;
2014-11-17 02:04:45 +08:00
Audio : : openOutput ( outDevDescr ) ;
2014-10-29 04:27:51 +08:00
QString inDevDescr = Settings : : getInstance ( ) . getInDev ( ) ;
2014-11-17 02:04:45 +08:00
Audio : : openInput ( inDevDescr ) ;
2014-06-25 04:11:11 +08:00
}
Core : : ~ Core ( )
{
2015-01-25 02:32:07 +08:00
qDebug ( ) < < " Deleting Core " ;
2014-12-04 08:52:10 +08:00
clearPassword ( Core : : ptMain ) ;
clearPassword ( Core : : ptHistory ) ;
2015-01-24 22:31:11 +08:00
toxTimer - > stop ( ) ;
coreThread - > exit ( 0 ) ;
2015-01-25 02:48:23 +08:00
while ( coreThread - > isRunning ( ) )
{
qApp - > processEvents ( ) ;
coreThread - > wait ( 500 ) ;
}
2015-01-24 22:31:11 +08:00
2014-12-04 08:52:10 +08:00
if ( tox )
{
2014-06-27 06:42:45 +08:00
toxav_kill ( toxav ) ;
2014-12-04 08:52:10 +08:00
toxav = nullptr ;
2014-06-25 04:11:11 +08:00
tox_kill ( tox ) ;
2014-12-04 08:52:10 +08:00
tox = nullptr ;
2014-06-25 04:11:11 +08:00
}
2014-07-12 18:50:40 +08:00
if ( videobuf )
{
delete [ ] videobuf ;
videobuf = nullptr ;
}
2014-08-30 20:40:41 +08:00
2014-11-17 02:04:45 +08:00
Audio : : closeInput ( ) ;
Audio : : closeOutput ( ) ;
2014-06-25 04:11:11 +08:00
}
2014-09-11 21:44:34 +08:00
Core * Core : : getInstance ( )
{
return Widget : : getInstance ( ) - > getCore ( ) ;
}
2014-10-09 09:25:26 +08:00
void Core : : make_tox ( )
2014-06-27 06:42:45 +08:00
{
2014-07-02 06:47:06 +08:00
// IPv6 needed for LAN discovery, but can crash some weird routers. On by default, can be disabled in options.
bool enableIPv6 = Settings : : getInstance ( ) . getEnableIPv6 ( ) ;
2014-10-06 04:49:44 +08:00
bool forceTCP = Settings : : getInstance ( ) . getForceTCP ( ) ;
2014-12-28 20:32:25 +08:00
ProxyType proxyType = Settings : : getInstance ( ) . getProxyType ( ) ;
2014-10-07 10:09:15 +08:00
2014-07-02 06:47:06 +08:00
if ( enableIPv6 )
qDebug ( ) < < " Core starting with IPv6 enabled " ;
else
qWarning ( ) < < " Core starting with IPv6 disabled. LAN discovery may not work properly. " ;
2014-08-17 20:57:54 +08:00
Tox_Options toxOptions ;
toxOptions . ipv6enabled = enableIPv6 ;
2014-10-06 04:49:44 +08:00
toxOptions . udp_disabled = forceTCP ;
2014-10-07 10:09:15 +08:00
// No proxy by default
2014-12-28 20:32:25 +08:00
toxOptions . proxy_type = TOX_PROXY_NONE ;
2014-08-17 20:57:54 +08:00
toxOptions . proxy_address [ 0 ] = 0 ;
toxOptions . proxy_port = 0 ;
2014-12-28 20:32:25 +08:00
if ( proxyType ! = ProxyType : : ptNone )
2014-10-06 04:49:44 +08:00
{
2014-10-07 10:09:15 +08:00
QString proxyAddr = Settings : : getInstance ( ) . getProxyAddr ( ) ;
int proxyPort = Settings : : getInstance ( ) . getProxyPort ( ) ;
if ( proxyAddr . length ( ) > 255 )
{
qWarning ( ) < < " Core: proxy address " < < proxyAddr < < " is too long " ;
}
else if ( proxyAddr ! = " " & & proxyPort > 0 )
{
qDebug ( ) < < " Core: using proxy " < < proxyAddr < < " : " < < proxyPort ;
2014-12-28 20:32:25 +08:00
// protection against changings in TOX_PROXY_TYPE enum
if ( proxyType = = ProxyType : : ptSOCKS5 )
toxOptions . proxy_type = TOX_PROXY_SOCKS5 ;
else if ( proxyType = = ProxyType : : ptHTTP )
toxOptions . proxy_type = TOX_PROXY_HTTP ;
2014-10-07 10:09:15 +08:00
uint16_t sz = CString : : fromString ( proxyAddr , ( unsigned char * ) toxOptions . proxy_address ) ;
toxOptions . proxy_address [ sz ] = 0 ;
toxOptions . proxy_port = proxyPort ;
}
2014-10-06 04:49:44 +08:00
}
2014-08-17 20:57:54 +08:00
tox = tox_new ( & toxOptions ) ;
2014-06-27 06:42:45 +08:00
if ( tox = = nullptr )
{
2014-08-10 04:07:32 +08:00
if ( enableIPv6 ) // Fallback to IPv4
{
2014-08-17 20:57:54 +08:00
toxOptions . ipv6enabled = false ;
tox = tox_new ( & toxOptions ) ;
2014-08-10 04:07:32 +08:00
if ( tox = = nullptr )
{
2014-12-28 20:32:25 +08:00
if ( toxOptions . proxy_type ! = TOX_PROXY_NONE )
2014-10-06 04:49:44 +08:00
{
//QMessageBox::critical(Widget::getInstance(), tr("Proxy failure", "popup title"),
//tr("toxcore failed to start with your proxy settings. qTox cannot run; please modify your "
//"settings and restart.", "popup text"));
qCritical ( ) < < " Core: bad proxy! no toxcore! " ;
emit badProxy ( ) ;
}
else
{
qCritical ( ) < < " Tox core failed to start " ;
emit failedToStart ( ) ;
}
2014-08-10 04:07:32 +08:00
return ;
}
2014-08-10 04:12:34 +08:00
else
qWarning ( ) < < " Core failed to start with IPv6, falling back to IPv4. LAN discovery may not work properly. " ;
2014-08-10 04:07:32 +08:00
}
2014-12-28 20:32:25 +08:00
else if ( toxOptions . proxy_type ! = TOX_PROXY_NONE )
2014-10-06 04:49:44 +08:00
{
emit badProxy ( ) ;
return ;
}
2014-08-10 04:07:32 +08:00
else
{
qCritical ( ) < < " Tox core failed to start " ;
emit failedToStart ( ) ;
return ;
}
2014-06-27 06:42:45 +08:00
}
toxav = toxav_new ( tox , TOXAV_MAX_CALLS ) ;
if ( toxav = = nullptr )
{
qCritical ( ) < < " Toxav core failed to start " ;
emit failedToStart ( ) ;
return ;
}
2014-09-10 21:12:43 +08:00
}
void Core : : start ( )
{
2014-10-09 09:25:26 +08:00
make_tox ( ) ;
2014-06-27 06:42:45 +08:00
2014-07-28 04:55:22 +08:00
qsrand ( time ( nullptr ) ) ;
2014-10-11 06:07:18 +08:00
if ( loadPath ! = " " )
{
if ( ! loadConfiguration ( loadPath ) ) // loadPath is meaningless after this
{
2014-10-25 02:55:54 +08:00
qCritical ( ) < < " Core: loadConfiguration failed, exiting now " ;
2014-10-11 06:07:18 +08:00
emit failedToStart ( ) ;
tox_kill ( tox ) ;
tox = nullptr ;
return ;
}
loadPath = " " ;
2014-10-01 19:23:00 +08:00
}
2014-10-20 11:07:51 +08:00
else // new ID
{
setStatusMessage ( tr ( " Toxing on qTox " ) ) ; // this also solves the not updating issue
setUsername ( tr ( " qTox User " ) ) ;
2014-10-25 19:01:23 +08:00
QMetaObject : : invokeMethod ( Widget : : getInstance ( ) , " onSettingsClicked " ) ; // update ui with new profile
2014-10-20 11:07:51 +08:00
}
2014-06-27 06:42:45 +08:00
tox_callback_friend_request ( tox , onFriendRequest , this ) ;
tox_callback_friend_message ( tox , onFriendMessage , this ) ;
tox_callback_friend_action ( tox , onAction , this ) ;
tox_callback_name_change ( tox , onFriendNameChange , this ) ;
tox_callback_typing_change ( tox , onFriendTypingChange , this ) ;
tox_callback_status_message ( tox , onStatusMessageChanged , this ) ;
tox_callback_user_status ( tox , onUserStatusChanged , this ) ;
tox_callback_connection_status ( tox , onConnectionStatusChanged , this ) ;
tox_callback_group_invite ( tox , onGroupInvite , this ) ;
tox_callback_group_message ( tox , onGroupMessage , this ) ;
tox_callback_group_namelist_change ( tox , onGroupNamelistChange , this ) ;
2014-11-06 08:22:50 +08:00
tox_callback_group_title ( tox , onGroupTitleChange , this ) ;
2014-10-30 16:40:47 +08:00
tox_callback_group_action ( tox , onGroupAction , this ) ;
2014-06-27 06:42:45 +08:00
tox_callback_file_send_request ( tox , onFileSendRequestCallback , this ) ;
tox_callback_file_control ( tox , onFileControlCallback , this ) ;
tox_callback_file_data ( tox , onFileDataCallback , this ) ;
2014-09-24 22:51:16 +08:00
tox_callback_avatar_info ( tox , onAvatarInfoCallback , this ) ;
tox_callback_avatar_data ( tox , onAvatarDataCallback , this ) ;
2014-11-01 22:19:11 +08:00
tox_callback_read_receipt ( tox , onReadReceiptCallback , this ) ;
2014-06-27 06:42:45 +08:00
2014-07-23 05:59:27 +08:00
toxav_register_callstate_callback ( toxav , onAvInvite , av_OnInvite , this ) ;
toxav_register_callstate_callback ( toxav , onAvStart , av_OnStart , this ) ;
toxav_register_callstate_callback ( toxav , onAvCancel , av_OnCancel , this ) ;
toxav_register_callstate_callback ( toxav , onAvReject , av_OnReject , this ) ;
toxav_register_callstate_callback ( toxav , onAvEnd , av_OnEnd , this ) ;
toxav_register_callstate_callback ( toxav , onAvRinging , av_OnRinging , this ) ;
2014-11-18 06:17:54 +08:00
toxav_register_callstate_callback ( toxav , onAvMediaChange , av_OnPeerCSChange , this ) ;
toxav_register_callstate_callback ( toxav , onAvMediaChange , av_OnSelfCSChange , this ) ;
2014-07-23 05:59:27 +08:00
toxav_register_callstate_callback ( toxav , onAvRequestTimeout , av_OnRequestTimeout , this ) ;
toxav_register_callstate_callback ( toxav , onAvPeerTimeout , av_OnPeerTimeout , this ) ;
2014-06-27 07:17:10 +08:00
2014-11-30 23:20:32 +08:00
toxav_register_audio_callback ( toxav , playCallAudio , this ) ;
toxav_register_video_callback ( toxav , playCallVideo , this ) ;
2014-07-09 15:55:25 +08:00
2014-09-28 06:19:30 +08:00
QPixmap pic = Settings : : getInstance ( ) . getSavedAvatar ( getSelfId ( ) . toString ( ) ) ;
2014-09-24 22:51:16 +08:00
if ( ! pic . isNull ( ) & & ! pic . size ( ) . isEmpty ( ) )
{
QByteArray data ;
QBuffer buffer ( & data ) ;
buffer . open ( QIODevice : : WriteOnly ) ;
2014-09-24 23:28:38 +08:00
pic . save ( & buffer , " PNG " ) ;
2014-09-24 22:51:16 +08:00
buffer . close ( ) ;
2014-09-28 05:37:39 +08:00
setAvatar ( TOX_AVATAR_FORMAT_PNG , data ) ;
2014-09-24 22:51:16 +08:00
}
else
2014-09-28 06:19:30 +08:00
qDebug ( ) < < " Core: Error loading self avatar " ;
2014-09-29 07:08:07 +08:00
2014-11-06 22:12:10 +08:00
ready = true ;
2014-09-29 07:08:07 +08:00
process ( ) ; // starts its own timer
2014-06-27 06:42:45 +08:00
}
2014-09-30 10:24:31 +08:00
/* Using the now commented out statements in checkConnection(), I watched how
* many ticks disconnects - after - initial - connect lasted . Out of roughly 15 trials ,
* 5 disconnected ; 4 were DCd for less than 20 ticks , while the 5 th was ~ 50 ticks .
* So I set the tolerance here at 25 , and initial DCs should be very rare now .
* This should be able to go to 50 or 100 without affecting legitimate disconnects '
2014-10-09 16:59:35 +08:00
* downtime , but lets be conservative for now . Edit : now ~ ~ 40 ~ ~ 30.
2014-09-30 10:24:31 +08:00
*/
2014-10-09 16:59:35 +08:00
# define CORE_DISCONNECT_TOLERANCE 30
2014-09-30 10:24:31 +08:00
2014-09-29 07:08:07 +08:00
void Core : : process ( )
2014-06-26 19:09:08 +08:00
{
2014-07-01 02:53:29 +08:00
if ( ! tox )
return ;
2014-09-29 07:08:07 +08:00
2014-09-30 10:24:31 +08:00
static int tolerance = CORE_DISCONNECT_TOLERANCE ;
2014-09-29 07:08:07 +08:00
tox_do ( tox ) ;
2014-11-18 06:17:54 +08:00
toxav_do ( toxav ) ;
2014-09-29 07:21:08 +08:00
2014-09-29 07:08:07 +08:00
# ifdef DEBUG
//we want to see the debug messages immediately
fflush ( stdout ) ;
# endif
2014-09-29 07:21:08 +08:00
if ( checkConnection ( ) )
2014-09-30 10:24:31 +08:00
tolerance = CORE_DISCONNECT_TOLERANCE ;
2014-09-30 10:29:39 +08:00
else if ( ! ( - - tolerance ) )
2014-09-29 07:21:08 +08:00
{
2014-06-26 19:09:08 +08:00
bootstrapDht ( ) ;
2014-09-29 07:21:08 +08:00
}
2014-09-29 07:08:07 +08:00
2014-11-18 06:17:54 +08:00
toxTimer - > start ( qMin ( tox_do_interval ( tox ) , toxav_do_interval ( toxav ) ) ) ;
2014-09-29 07:08:07 +08:00
}
bool Core : : checkConnection ( )
{
static bool isConnected = false ;
2014-09-30 10:24:31 +08:00
//static int count = 0;
2014-09-29 07:08:07 +08:00
bool toxConnected = tox_isconnected ( tox ) ;
if ( toxConnected & & ! isConnected ) {
qDebug ( ) < < " Core: Connected to DHT " ;
emit connected ( ) ;
isConnected = true ;
2014-09-30 10:24:31 +08:00
//if (count) qDebug() << "Core: disconnect count:" << count;
//count = 0;
2014-09-29 07:08:07 +08:00
} else if ( ! toxConnected & & isConnected ) {
qDebug ( ) < < " Core: Disconnected to DHT " ;
emit disconnected ( ) ;
isConnected = false ;
2014-09-30 10:24:31 +08:00
//count++;
} //else if (!toxConnected) count++;
2014-09-29 07:08:07 +08:00
return isConnected ;
}
void Core : : bootstrapDht ( )
{
const Settings & s = Settings : : getInstance ( ) ;
QList < Settings : : DhtServer > dhtServerList = s . getDhtServerList ( ) ;
int listSize = dhtServerList . size ( ) ;
2014-11-18 09:41:34 +08:00
if ( listSize = = 0 )
{
qDebug ( ) < < " Settings: no bootstrap list?!? " ;
return ;
}
2014-09-29 07:08:07 +08:00
static int j = qrand ( ) % listSize ;
2015-01-13 23:55:06 +08:00
qDebug ( ) < < " Core: Bootstrapping to the DHT ... " ;
2014-09-29 07:08:07 +08:00
int i = 0 ;
2014-10-01 07:50:12 +08:00
while ( i < 2 ) // i think the more we bootstrap, the more we jitter because the more we overwrite nodes
2014-09-29 07:08:07 +08:00
{
const Settings : : DhtServer & dhtServer = dhtServerList [ j % listSize ] ;
if ( tox_bootstrap_from_address ( tox , dhtServer . address . toLatin1 ( ) . data ( ) ,
dhtServer . port , CUserId ( dhtServer . userId ) . data ( ) ) = = 1 )
2015-01-13 23:55:06 +08:00
qDebug ( ) < < QString ( " Core: Bootstrapping from " ) + dhtServer . name + QString ( " , addr " ) + dhtServer . address . toLatin1 ( ) . data ( )
2014-09-29 07:08:07 +08:00
+ QString ( " , port " ) + QString ( ) . setNum ( dhtServer . port ) ;
else
2015-01-13 23:55:06 +08:00
qDebug ( ) < < " Core: Error bootstrapping from " + dhtServer . name ;
2014-09-29 07:08:07 +08:00
j + + ;
i + + ;
}
2014-06-26 19:09:08 +08:00
}
2014-06-25 04:11:11 +08:00
void Core : : onFriendRequest ( Tox */ * tox */ , const uint8_t * cUserId , const uint8_t * cMessage , uint16_t cMessageSize , void * core )
{
emit static_cast < Core * > ( core ) - > friendRequestReceived ( CUserId : : toString ( cUserId ) , CString : : toString ( cMessage , cMessageSize ) ) ;
}
2014-07-03 15:22:12 +08:00
void Core : : onFriendMessage ( Tox */ * tox */ , int friendId , const uint8_t * cMessage , uint16_t cMessageSize , void * core )
2014-06-25 04:11:11 +08:00
{
2014-10-02 14:01:23 +08:00
emit static_cast < Core * > ( core ) - > friendMessageReceived ( friendId , CString : : toString ( cMessage , cMessageSize ) , false ) ;
2014-06-25 04:11:11 +08:00
}
2014-07-03 15:22:12 +08:00
void Core : : onFriendNameChange ( Tox */ * tox */ , int friendId , const uint8_t * cName , uint16_t cNameSize , void * core )
2014-06-25 04:11:11 +08:00
{
emit static_cast < Core * > ( core ) - > friendUsernameChanged ( friendId , CString : : toString ( cName , cNameSize ) ) ;
}
void Core : : onFriendTypingChange ( Tox */ * tox */ , int friendId , uint8_t isTyping , void * core )
{
emit static_cast < Core * > ( core ) - > friendTypingChanged ( friendId , isTyping ? true : false ) ;
}
2014-07-03 15:22:12 +08:00
void Core : : onStatusMessageChanged ( Tox */ * tox */ , int friendId , const uint8_t * cMessage , uint16_t cMessageSize , void * core )
2014-06-25 04:11:11 +08:00
{
emit static_cast < Core * > ( core ) - > friendStatusMessageChanged ( friendId , CString : : toString ( cMessage , cMessageSize ) ) ;
}
void Core : : onUserStatusChanged ( Tox */ * tox */ , int friendId , uint8_t userstatus , void * core )
{
Status status ;
switch ( userstatus ) {
case TOX_USERSTATUS_NONE :
status = Status : : Online ;
break ;
case TOX_USERSTATUS_AWAY :
status = Status : : Away ;
break ;
case TOX_USERSTATUS_BUSY :
status = Status : : Busy ;
break ;
default :
status = Status : : Online ;
break ;
}
2014-09-24 23:28:38 +08:00
if ( status = = Status : : Online | | status = = Status : : Away )
2014-09-29 09:54:28 +08:00
tox_request_avatar_info ( static_cast < Core * > ( core ) - > tox , friendId ) ;
2014-09-24 23:28:38 +08:00
2014-06-25 04:11:11 +08:00
emit static_cast < Core * > ( core ) - > friendStatusChanged ( friendId , status ) ;
}
void Core : : onConnectionStatusChanged ( Tox */ * tox */ , int friendId , uint8_t status , void * core )
{
Status friendStatus = status ? Status : : Online : Status : : Offline ;
emit static_cast < Core * > ( core ) - > friendStatusChanged ( friendId , friendStatus ) ;
if ( friendStatus = = Status : : Offline ) {
static_cast < Core * > ( core ) - > checkLastOnline ( friendId ) ;
2014-09-30 00:14:19 +08:00
for ( ToxFile & f : fileSendQueue )
{
if ( f . friendId = = friendId & & f . status = = ToxFile : : TRANSMITTING )
{
f . status = ToxFile : : BROKEN ;
emit static_cast < Core * > ( core ) - > fileTransferBrokenUnbroken ( f , true ) ;
}
}
for ( ToxFile & f : fileRecvQueue )
{
if ( f . friendId = = friendId & & f . status = = ToxFile : : TRANSMITTING )
{
f . status = ToxFile : : BROKEN ;
emit static_cast < Core * > ( core ) - > fileTransferBrokenUnbroken ( f , true ) ;
}
}
} else {
for ( ToxFile & f : fileRecvQueue )
{
if ( f . friendId = = friendId & & f . status = = ToxFile : : BROKEN )
{
2014-09-30 00:36:42 +08:00
qDebug ( ) < < QString ( " Core::onConnectionStatusChanged: %1: resuming broken filetransfer from position: %2 " ) . arg ( f . file - > fileName ( ) ) . arg ( f . bytesSent ) ;
tox_file_send_control ( static_cast < Core * > ( core ) - > tox , friendId , 1 , f . fileNum , TOX_FILECONTROL_RESUME_BROKEN , reinterpret_cast < const uint8_t * > ( & f . bytesSent ) , sizeof ( uint64_t ) ) ;
2014-09-30 00:14:19 +08:00
emit static_cast < Core * > ( core ) - > fileTransferBrokenUnbroken ( f , false ) ;
}
}
2014-06-25 04:11:11 +08:00
}
}
2014-07-03 15:22:12 +08:00
void Core : : onAction ( Tox */ * tox */ , int friendId , const uint8_t * cMessage , uint16_t cMessageSize , void * core )
2014-06-25 04:11:11 +08:00
{
2014-10-02 14:01:23 +08:00
emit static_cast < Core * > ( core ) - > friendMessageReceived ( friendId , CString : : toString ( cMessage , cMessageSize ) , true ) ;
2014-06-25 04:11:11 +08:00
}
2014-10-30 16:40:47 +08:00
void Core : : onGroupAction ( Tox * , int groupnumber , int peernumber , const uint8_t * action , uint16_t length , void * _core )
{
Core * core = static_cast < Core * > ( _core ) ;
2014-11-23 23:55:49 +08:00
emit core - > groupMessageReceived ( groupnumber , peernumber , CString : : toString ( action , length ) , true ) ;
2014-10-30 16:40:47 +08:00
}
2014-11-11 22:03:08 +08:00
void Core : : onGroupInvite ( Tox * , int friendnumber , uint8_t type , const uint8_t * data , uint16_t length , void * core )
2014-06-25 04:11:11 +08:00
{
2014-11-13 07:13:11 +08:00
QByteArray pk ( ( char * ) data , length ) ;
2014-11-11 22:03:08 +08:00
if ( type = = TOX_GROUPCHAT_TYPE_TEXT )
{
qDebug ( ) < < QString ( " Core: Text group invite by %1 " ) . arg ( friendnumber ) ;
2014-11-13 07:13:11 +08:00
emit static_cast < Core * > ( core ) - > groupInviteReceived ( friendnumber , type , pk ) ;
2014-11-11 22:03:08 +08:00
}
else if ( type = = TOX_GROUPCHAT_TYPE_AV )
{
2014-11-11 23:05:01 +08:00
qDebug ( ) < < QString ( " Core: AV group invite by %1 " ) . arg ( friendnumber ) ;
2014-11-13 07:13:11 +08:00
emit static_cast < Core * > ( core ) - > groupInviteReceived ( friendnumber , type , pk ) ;
2014-11-11 22:03:08 +08:00
}
else
{
qWarning ( ) < < " Core: Group invite with unknown type " < < type ;
}
2014-06-25 04:11:11 +08:00
}
2014-10-06 14:46:30 +08:00
void Core : : onGroupMessage ( Tox * , int groupnumber , int peernumber , const uint8_t * message , uint16_t length , void * _core )
2014-06-25 04:11:11 +08:00
{
2014-10-06 14:46:30 +08:00
Core * core = static_cast < Core * > ( _core ) ;
2014-11-23 23:55:49 +08:00
emit core - > groupMessageReceived ( groupnumber , peernumber , CString : : toString ( message , length ) , false ) ;
2014-06-25 04:11:11 +08:00
}
void Core : : onGroupNamelistChange ( Tox * , int groupnumber , int peernumber , uint8_t change , void * core )
{
qDebug ( ) < < QString ( " Core: Group namelist change %1:%2 %3 " ) . arg ( groupnumber ) . arg ( peernumber ) . arg ( change ) ;
emit static_cast < Core * > ( core ) - > groupNamelistChanged ( groupnumber , peernumber , change ) ;
}
2014-11-06 08:22:50 +08:00
void Core : : onGroupTitleChange ( Tox * , int groupnumber , int peernumber , const uint8_t * title , uint8_t len , void * _core )
{
qDebug ( ) < < " Core: group " < < groupnumber < < " title changed by " < < peernumber ;
Core * core = static_cast < Core * > ( _core ) ;
QString author ;
2014-11-06 10:50:32 +08:00
if ( peernumber > = 0 )
2014-11-06 08:22:50 +08:00
author = core - > getGroupPeerName ( groupnumber , peernumber ) ;
emit core - > groupTitleChanged ( groupnumber , author , CString : : toString ( title , len ) ) ;
}
2014-06-27 01:45:47 +08:00
void Core : : onFileSendRequestCallback ( Tox * , int32_t friendnumber , uint8_t filenumber , uint64_t filesize ,
2014-07-03 15:22:12 +08:00
const uint8_t * filename , uint16_t filename_length , void * core )
2014-06-26 04:43:28 +08:00
{
2014-06-27 01:45:47 +08:00
qDebug ( ) < < QString ( " Core: Received file request %1 with friend %2 " ) . arg ( filenumber ) . arg ( friendnumber ) ;
2014-07-01 19:33:59 +08:00
ToxFile file { filenumber , friendnumber ,
CString : : toString ( filename , filename_length ) . toUtf8 ( ) , " " , ToxFile : : RECEIVING } ;
file . filesize = filesize ;
fileRecvQueue . append ( file ) ;
2014-06-27 01:45:47 +08:00
emit static_cast < Core * > ( core ) - > fileReceiveRequested ( fileRecvQueue . last ( ) ) ;
2014-06-26 04:43:28 +08:00
}
2014-08-05 09:00:17 +08:00
void Core : : onFileControlCallback ( Tox * tox , int32_t friendnumber , uint8_t receive_send , uint8_t filenumber ,
2014-09-30 00:36:42 +08:00
uint8_t control_type , const uint8_t * data , uint16_t length , void * core )
2014-06-26 04:43:28 +08:00
{
2014-06-26 06:30:24 +08:00
ToxFile * file { nullptr } ;
2014-06-27 01:45:47 +08:00
if ( receive_send = = 1 )
2014-06-26 06:30:24 +08:00
{
2014-06-27 01:45:47 +08:00
for ( ToxFile & f : fileSendQueue )
2014-06-26 06:30:24 +08:00
{
2014-06-27 01:45:47 +08:00
if ( f . fileNum = = filenumber & & f . friendId = = friendnumber )
{
file = & f ;
break ;
}
}
}
else
{
for ( ToxFile & f : fileRecvQueue )
{
if ( f . fileNum = = filenumber & & f . friendId = = friendnumber )
{
file = & f ;
break ;
}
2014-06-26 06:30:24 +08:00
}
}
if ( ! file )
{
qWarning ( " Core::onFileControlCallback: No such file in queue " ) ;
return ;
}
2014-08-05 09:00:17 +08:00
if ( receive_send = = 1 & & control_type = = TOX_FILECONTROL_ACCEPT )
2014-06-26 04:43:28 +08:00
{
2014-06-27 01:45:47 +08:00
file - > status = ToxFile : : TRANSMITTING ;
emit static_cast < Core * > ( core ) - > fileTransferAccepted ( * file ) ;
2014-06-26 04:43:28 +08:00
qDebug ( ) < < " Core: File control callback, file accepted " ;
2014-08-29 03:56:55 +08:00
file - > sendTimer = new QTimer ( static_cast < Core * > ( core ) ) ;
connect ( file - > sendTimer , & QTimer : : timeout , std : : bind ( sendAllFileData , static_cast < Core * > ( core ) , file ) ) ;
file - > sendTimer - > setSingleShot ( true ) ;
file - > sendTimer - > start ( TOX_FILE_INTERVAL ) ;
2014-06-26 04:43:28 +08:00
}
2014-06-26 06:30:24 +08:00
else if ( receive_send = = 1 & & control_type = = TOX_FILECONTROL_KILL )
{
2014-06-27 01:45:47 +08:00
qDebug ( ) < < QString ( " Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2 " )
. arg ( file - > fileNum ) . arg ( file - > friendId ) ;
file - > status = ToxFile : : STOPPED ;
emit static_cast < Core * > ( core ) - > fileTransferCancelled ( file - > friendId , file - > fileNum , ToxFile : : SENDING ) ;
2014-08-31 19:07:31 +08:00
// Wait for sendAllFileData to return before deleting the ToxFile, we MUST ensure this or we'll use after free
2014-08-31 19:57:59 +08:00
if ( file - > sendTimer )
2014-08-31 19:07:31 +08:00
{
QThread : : msleep ( 1 ) ;
qApp - > processEvents ( ) ;
2014-08-31 19:57:59 +08:00
if ( file - > sendTimer )
{
delete file - > sendTimer ;
file - > sendTimer = nullptr ;
}
2014-08-31 19:07:31 +08:00
}
2014-08-05 09:00:17 +08:00
removeFileFromQueue ( ( bool ) receive_send , file - > friendId , file - > fileNum ) ;
}
else if ( receive_send = = 1 & & control_type = = TOX_FILECONTROL_FINISHED )
{
qDebug ( ) < < QString ( " Core::onFileControlCallback: Transfer of file %1 to friend %2 is complete " )
. arg ( file - > fileNum ) . arg ( file - > friendId ) ;
file - > status = ToxFile : : STOPPED ;
emit static_cast < Core * > ( core ) - > fileTransferFinished ( * file ) ;
removeFileFromQueue ( ( bool ) receive_send , file - > friendId , file - > fileNum ) ;
2014-06-27 01:45:47 +08:00
}
else if ( receive_send = = 0 & & control_type = = TOX_FILECONTROL_KILL )
{
qDebug ( ) < < QString ( " Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2 " )
. arg ( file - > fileNum ) . arg ( file - > friendId ) ;
2014-06-26 06:30:24 +08:00
file - > status = ToxFile : : STOPPED ;
2014-06-27 01:45:47 +08:00
emit static_cast < Core * > ( core ) - > fileTransferCancelled ( file - > friendId , file - > fileNum , ToxFile : : RECEIVING ) ;
2014-08-05 09:00:17 +08:00
removeFileFromQueue ( ( bool ) receive_send , file - > friendId , file - > fileNum ) ;
2014-06-27 01:45:47 +08:00
}
else if ( receive_send = = 0 & & control_type = = TOX_FILECONTROL_FINISHED )
{
qDebug ( ) < < QString ( " Core::onFileControlCallback: Reception of file %1 from %2 finished " )
. arg ( file - > fileNum ) . arg ( file - > friendId ) ;
file - > status = ToxFile : : STOPPED ;
emit static_cast < Core * > ( core ) - > fileTransferFinished ( * file ) ;
2014-08-05 09:00:17 +08:00
// confirm receive is complete
2014-08-29 18:52:09 +08:00
tox_file_send_control ( tox , file - > friendId , 1 , file - > fileNum , TOX_FILECONTROL_FINISHED , nullptr , 0 ) ;
2014-08-29 02:20:28 +08:00
removeFileFromQueue ( ( bool ) receive_send , file - > friendId , file - > fileNum ) ;
2014-06-26 06:30:24 +08:00
}
2014-09-11 21:36:57 +08:00
else if ( receive_send = = 0 & & control_type = = TOX_FILECONTROL_ACCEPT )
{
2014-09-30 01:22:19 +08:00
if ( file - > status = = ToxFile : : BROKEN )
{
emit static_cast < Core * > ( core ) - > fileTransferBrokenUnbroken ( * file , false ) ;
file - > status = ToxFile : : TRANSMITTING ;
}
2014-09-11 21:36:57 +08:00
emit static_cast < Core * > ( core ) - > fileTransferRemotePausedUnpaused ( * file , false ) ;
}
else if ( ( receive_send = = 0 | | receive_send = = 1 ) & & control_type = = TOX_FILECONTROL_PAUSE )
{
emit static_cast < Core * > ( core ) - > fileTransferRemotePausedUnpaused ( * file , true ) ;
}
2014-09-29 21:59:07 +08:00
else if ( receive_send = = 1 & & control_type = = TOX_FILECONTROL_RESUME_BROKEN )
{
2014-09-30 00:36:42 +08:00
if ( length ! = sizeof ( uint64_t ) )
return ;
2014-09-29 21:59:07 +08:00
qDebug ( ) < < " Core::onFileControlCallback: TOX_FILECONTROL_RESUME_BROKEN " ;
2014-09-30 00:36:42 +08:00
uint64_t resumePos = * reinterpret_cast < const uint64_t * > ( data ) ;
2014-09-29 21:59:07 +08:00
2014-10-14 08:27:24 +08:00
if ( resumePos > = ( unsigned ) file - > filesize )
2014-09-29 21:59:07 +08:00
{
qWarning ( ) < < " Core::onFileControlCallback: invalid resume position " ;
tox_file_send_control ( tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_KILL , nullptr , 0 ) ; // don't sure about it
return ;
}
2014-09-30 01:22:19 +08:00
file - > status = ToxFile : : TRANSMITTING ;
emit static_cast < Core * > ( core ) - > fileTransferBrokenUnbroken ( * file , false ) ;
2014-09-29 21:59:07 +08:00
file - > bytesSent = resumePos ;
tox_file_send_control ( tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_ACCEPT , nullptr , 0 ) ;
}
2014-06-26 04:43:28 +08:00
else
{
qDebug ( ) < < QString ( " Core: File control callback, receive_send=%1, control_type=%2 " )
. arg ( receive_send ) . arg ( control_type ) ;
}
}
2014-07-03 15:22:12 +08:00
void Core : : onFileDataCallback ( Tox * , int32_t friendnumber , uint8_t filenumber , const uint8_t * data , uint16_t length , void * core )
2014-06-26 04:43:28 +08:00
{
2014-06-27 01:45:47 +08:00
ToxFile * file { nullptr } ;
for ( ToxFile & f : fileRecvQueue )
{
if ( f . fileNum = = filenumber & & f . friendId = = friendnumber )
{
file = & f ;
break ;
}
}
if ( ! file )
{
qWarning ( " Core::onFileDataCallback: No such file in queue " ) ;
return ;
}
2014-07-01 19:33:59 +08:00
file - > file - > write ( ( char * ) data , length ) ;
2014-06-27 01:45:47 +08:00
file - > bytesSent + = length ;
2014-07-13 00:40:01 +08:00
//qDebug() << QString("Core::onFileDataCallback: received %1/%2 bytes").arg(file->bytesSent).arg(file->filesize);
2014-06-27 01:45:47 +08:00
emit static_cast < Core * > ( core ) - > fileTransferInfo ( file - > friendId , file - > fileNum ,
file - > filesize , file - > bytesSent , ToxFile : : RECEIVING ) ;
2014-06-26 04:43:28 +08:00
}
2014-09-24 23:28:38 +08:00
void Core : : onAvatarInfoCallback ( Tox * , int32_t friendnumber , uint8_t format ,
2014-09-29 09:54:28 +08:00
uint8_t * hash , void * _core )
2014-09-24 22:51:16 +08:00
{
2014-09-29 09:54:28 +08:00
Core * core = static_cast < Core * > ( _core ) ;
2014-09-25 00:22:09 +08:00
2014-09-27 03:56:51 +08:00
if ( format = = TOX_AVATAR_FORMAT_NONE )
2014-09-30 10:24:31 +08:00
{
2014-11-02 21:23:18 +08:00
//qDebug() << "Core: Got null avatar info from" << core->getFriendUsername(friendnumber);
2014-09-29 09:54:28 +08:00
emit core - > friendAvatarRemoved ( friendnumber ) ;
2014-10-09 16:07:26 +08:00
QFile : : remove ( QDir ( Settings : : getSettingsDirPath ( ) ) . filePath ( " avatars/ " + core - > getFriendAddress ( friendnumber ) . left ( 64 ) + " .png " ) ) ;
QFile : : remove ( QDir ( Settings : : getSettingsDirPath ( ) ) . filePath ( " avatars/ " + core - > getFriendAddress ( friendnumber ) . left ( 64 ) + " .hash " ) ) ;
2014-09-30 10:24:31 +08:00
}
2014-09-27 03:23:20 +08:00
else
2014-09-29 09:54:28 +08:00
{
QByteArray oldHash = Settings : : getInstance ( ) . getAvatarHash ( core - > getFriendAddress ( friendnumber ) ) ;
2014-09-30 05:36:23 +08:00
if ( QByteArray ( ( char * ) hash , TOX_HASH_LENGTH ) ! = oldHash )
// comparison failed miserably if I didn't convert hash to QByteArray
2014-09-30 10:24:31 +08:00
{
qDebug ( ) < < " Core: Got new avatar info from " < < core - > getFriendUsername ( friendnumber ) ;
2014-09-29 09:54:28 +08:00
tox_request_avatar_data ( core - > tox , friendnumber ) ;
2014-09-30 10:24:31 +08:00
}
2014-11-02 21:23:18 +08:00
//else
// qDebug() << "Core: Got same avatar info from" << core->getFriendUsername(friendnumber);
2014-09-29 09:54:28 +08:00
}
2014-09-24 22:51:16 +08:00
}
2014-09-24 23:28:38 +08:00
void Core : : onAvatarDataCallback ( Tox * , int32_t friendnumber , uint8_t ,
2014-09-29 09:54:28 +08:00
uint8_t * hash , uint8_t * data , uint32_t datalen , void * core )
2014-09-24 22:51:16 +08:00
{
2014-09-24 23:28:38 +08:00
QPixmap pic ;
pic . loadFromData ( ( uchar * ) data , datalen ) ;
2014-09-30 05:36:23 +08:00
if ( ! pic . isNull ( ) )
2014-09-24 23:28:38 +08:00
{
2014-09-30 10:24:31 +08:00
qDebug ( ) < < " Core: Got avatar data from " < < static_cast < Core * > ( core ) - > getFriendUsername ( friendnumber ) ;
2014-09-28 06:19:30 +08:00
Settings : : getInstance ( ) . saveAvatar ( pic , static_cast < Core * > ( core ) - > getFriendAddress ( friendnumber ) ) ;
2014-09-29 09:54:28 +08:00
Settings : : getInstance ( ) . saveAvatarHash ( QByteArray ( ( char * ) hash , TOX_HASH_LENGTH ) , static_cast < Core * > ( core ) - > getFriendAddress ( friendnumber ) ) ;
2014-09-24 23:28:38 +08:00
emit static_cast < Core * > ( core ) - > friendAvatarChanged ( friendnumber , pic ) ;
}
2014-09-24 22:51:16 +08:00
}
2014-11-01 22:19:11 +08:00
void Core : : onReadReceiptCallback ( Tox * , int32_t friendnumber , uint32_t receipt , void * core )
{
emit static_cast < Core * > ( core ) - > receiptRecieved ( friendnumber , receipt ) ;
}
2014-06-25 04:11:11 +08:00
void Core : : acceptFriendRequest ( const QString & userId )
{
int friendId = tox_add_friend_norequest ( tox , CUserId ( userId ) . data ( ) ) ;
if ( friendId = = - 1 ) {
emit failedToAddFriend ( userId ) ;
} else {
2014-07-04 01:38:30 +08:00
saveConfiguration ( ) ;
2014-06-25 04:11:11 +08:00
emit friendAdded ( friendId , userId ) ;
}
}
void Core : : requestFriendship ( const QString & friendAddress , const QString & message )
{
const QString userId = friendAddress . mid ( 0 , TOX_CLIENT_ID_SIZE * 2 ) ;
2014-11-10 03:23:43 +08:00
2014-12-12 02:05:52 +08:00
if ( hasFriendWithAddress ( friendAddress ) )
2014-11-10 08:04:35 +08:00
{
emit failedToAddFriend ( userId , QString ( tr ( " Friend is already added " ) ) ) ;
2014-11-10 03:23:43 +08:00
}
2014-11-10 08:04:35 +08:00
else
{
2014-11-10 03:23:43 +08:00
qDebug ( ) < < " Core: requesting friendship of " + friendAddress ;
CString cMessage ( message ) ;
int friendId = tox_add_friend ( tox , CFriendAddress ( friendAddress ) . data ( ) , cMessage . data ( ) , cMessage . size ( ) ) ;
2014-11-10 08:04:35 +08:00
if ( friendId < 0 )
{
2014-11-10 03:23:43 +08:00
emit failedToAddFriend ( userId ) ;
2014-11-10 08:04:35 +08:00
}
else
{
2014-11-10 03:23:43 +08:00
// Update our friendAddresses
Settings : : getInstance ( ) . updateFriendAdress ( friendAddress ) ;
emit friendAdded ( friendId , userId ) ;
}
2014-06-25 04:11:11 +08:00
}
2014-07-05 12:25:01 +08:00
saveConfiguration ( ) ;
2014-06-25 04:11:11 +08:00
}
2014-11-09 20:32:19 +08:00
int Core : : sendMessage ( int friendId , const QString & message )
2014-06-25 04:11:11 +08:00
{
2014-11-09 20:32:19 +08:00
QMutexLocker ml ( & messageSendMutex ) ;
CString cMessage ( message ) ;
int receipt = tox_send_message ( tox , friendId , cMessage . data ( ) , cMessage . size ( ) ) ;
emit messageSentResult ( friendId , message , receipt ) ;
return receipt ;
2014-06-25 04:11:11 +08:00
}
2014-11-09 20:32:19 +08:00
int Core : : sendAction ( int friendId , const QString & action )
2014-06-25 04:11:11 +08:00
{
2014-11-09 20:32:19 +08:00
QMutexLocker ml ( & messageSendMutex ) ;
2014-06-25 04:11:11 +08:00
CString cMessage ( action ) ;
2014-11-09 20:32:19 +08:00
int receipt = tox_send_action ( tox , friendId , cMessage . data ( ) , cMessage . size ( ) ) ;
emit messageSentResult ( friendId , action , receipt ) ;
return receipt ;
2014-06-25 04:11:11 +08:00
}
void Core : : sendTyping ( int friendId , bool typing )
{
int ret = tox_set_user_is_typing ( tox , friendId , typing ) ;
if ( ret = = - 1 )
emit failedToSetTyping ( typing ) ;
}
void Core : : sendGroupMessage ( int groupId , const QString & message )
{
2014-12-29 01:26:35 +08:00
QList < CString > cMessages = splitMessage ( message , MAX_GROUP_MESSAGE_LEN ) ;
2014-06-25 04:11:11 +08:00
2014-09-21 18:30:10 +08:00
for ( auto & cMsg : cMessages )
{
2014-09-24 00:35:06 +08:00
int ret = tox_group_message_send ( tox , groupId , cMsg . data ( ) , cMsg . size ( ) ) ;
2014-11-01 21:00:43 +08:00
if ( ret = = - 1 )
emit groupSentResult ( groupId , message , ret ) ;
}
}
void Core : : sendGroupAction ( int groupId , const QString & message )
{
2014-12-29 01:26:35 +08:00
QList < CString > cMessages = splitMessage ( message , MAX_GROUP_MESSAGE_LEN ) ;
2014-11-01 21:00:43 +08:00
for ( auto & cMsg : cMessages )
{
int ret = tox_group_action_send ( tox , groupId , cMsg . data ( ) , cMsg . size ( ) ) ;
2014-09-24 00:35:06 +08:00
if ( ret = = - 1 )
emit groupSentResult ( groupId , message , ret ) ;
2014-09-21 18:30:10 +08:00
}
2014-06-25 04:11:11 +08:00
}
2014-11-06 08:22:50 +08:00
void Core : : changeGroupTitle ( int groupId , const QString & title )
{
CString cTitle ( title ) ;
int err = tox_group_set_title ( tox , groupId , cTitle . data ( ) , cTitle . size ( ) ) ;
if ( ! err )
2014-11-06 10:50:32 +08:00
emit groupTitleChanged ( groupId , getUsername ( ) , title ) ;
2014-11-06 08:22:50 +08:00
}
2014-07-01 19:33:59 +08:00
void Core : : sendFile ( int32_t friendId , QString Filename , QString FilePath , long long filesize )
2014-06-26 04:43:28 +08:00
{
2014-10-29 23:40:09 +08:00
QMutexLocker mlocker ( & fileSendMutex ) ;
2014-06-26 04:43:28 +08:00
QByteArray fileName = Filename . toUtf8 ( ) ;
2014-07-01 19:33:59 +08:00
int fileNum = tox_new_file_sender ( tox , friendId , filesize , ( uint8_t * ) fileName . data ( ) , fileName . size ( ) ) ;
2014-06-26 04:43:28 +08:00
if ( fileNum = = - 1 )
{
qWarning ( ) < < " Core::sendFile: Can't create the Tox file sender " ;
2014-09-24 00:52:06 +08:00
emit fileSendFailed ( friendId , Filename ) ;
2014-06-26 04:43:28 +08:00
return ;
}
2014-06-27 01:45:47 +08:00
qDebug ( ) < < QString ( " Core::sendFile: Created file sender %1 with friend %2 " ) . arg ( fileNum ) . arg ( friendId ) ;
2014-07-01 19:33:59 +08:00
ToxFile file { fileNum , friendId , fileName , FilePath , ToxFile : : SENDING } ;
file . filesize = filesize ;
2014-07-02 01:54:26 +08:00
if ( ! file . open ( false ) )
{
qWarning ( ) < < QString ( " Core::sendFile: Can't open file, error: %1 " ) . arg ( file . file - > errorString ( ) ) ;
}
2014-07-01 19:33:59 +08:00
fileSendQueue . append ( file ) ;
2014-06-27 01:45:47 +08:00
emit fileSendStarted ( fileSendQueue . last ( ) ) ;
}
2014-06-26 04:43:28 +08:00
2014-06-27 01:45:47 +08:00
void Core : : pauseResumeFileSend ( int friendId , int fileNum )
{
ToxFile * file { nullptr } ;
for ( ToxFile & f : fileSendQueue )
{
if ( f . fileNum = = fileNum & & f . friendId = = friendId )
{
file = & f ;
break ;
}
}
if ( ! file )
{
2014-08-31 19:07:31 +08:00
qWarning ( " Core::pauseResumeFileSend: No such file in queue " ) ;
2014-06-27 01:45:47 +08:00
return ;
}
if ( file - > status = = ToxFile : : TRANSMITTING )
{
file - > status = ToxFile : : PAUSED ;
emit fileTransferPaused ( file - > friendId , file - > fileNum , ToxFile : : SENDING ) ;
tox_file_send_control ( tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_PAUSE , nullptr , 0 ) ;
}
else if ( file - > status = = ToxFile : : PAUSED )
{
file - > status = ToxFile : : TRANSMITTING ;
emit fileTransferAccepted ( * file ) ;
tox_file_send_control ( tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_ACCEPT , nullptr , 0 ) ;
}
else
qWarning ( ) < < " Core::pauseResumeFileSend: File is stopped " ;
}
2014-06-26 06:30:24 +08:00
2014-06-27 01:45:47 +08:00
void Core : : pauseResumeFileRecv ( int friendId , int fileNum )
{
ToxFile * file { nullptr } ;
for ( ToxFile & f : fileRecvQueue )
{
if ( f . fileNum = = fileNum & & f . friendId = = friendId )
{
file = & f ;
break ;
}
}
if ( ! file )
{
qWarning ( " Core::cancelFileRecv: No such file in queue " ) ;
return ;
}
if ( file - > status = = ToxFile : : TRANSMITTING )
{
file - > status = ToxFile : : PAUSED ;
emit fileTransferPaused ( file - > friendId , file - > fileNum , ToxFile : : RECEIVING ) ;
tox_file_send_control ( tox , file - > friendId , 1 , file - > fileNum , TOX_FILECONTROL_PAUSE , nullptr , 0 ) ;
}
else if ( file - > status = = ToxFile : : PAUSED )
{
file - > status = ToxFile : : TRANSMITTING ;
emit fileTransferAccepted ( * file ) ;
tox_file_send_control ( tox , file - > friendId , 1 , file - > fileNum , TOX_FILECONTROL_ACCEPT , nullptr , 0 ) ;
}
else
2014-09-30 00:14:19 +08:00
qWarning ( ) < < " Core::pauseResumeFileRecv: File is stopped or broken " ;
2014-06-26 04:43:28 +08:00
}
2014-06-27 01:45:47 +08:00
void Core : : cancelFileSend ( int friendId , int fileNum )
2014-06-26 07:48:20 +08:00
{
2014-06-27 01:45:47 +08:00
ToxFile * file { nullptr } ;
for ( ToxFile & f : fileSendQueue )
{
if ( f . fileNum = = fileNum & & f . friendId = = friendId )
{
file = & f ;
break ;
}
}
if ( ! file )
{
qWarning ( " Core::cancelFileSend: No such file in queue " ) ;
return ;
}
2014-06-26 07:48:20 +08:00
file - > status = ToxFile : : STOPPED ;
2014-06-27 01:45:47 +08:00
emit fileTransferCancelled ( file - > friendId , file - > fileNum , ToxFile : : SENDING ) ;
2014-06-26 07:48:20 +08:00
tox_file_send_control ( tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_KILL , nullptr , 0 ) ;
2014-08-29 03:56:55 +08:00
while ( file - > sendTimer ) QThread : : msleep ( 1 ) ; // Wait until sendAllFileData returns before deleting
2014-06-27 01:45:47 +08:00
removeFileFromQueue ( true , friendId , fileNum ) ;
}
void Core : : cancelFileRecv ( int friendId , int fileNum )
{
ToxFile * file { nullptr } ;
for ( ToxFile & f : fileRecvQueue )
{
if ( f . fileNum = = fileNum & & f . friendId = = friendId )
{
file = & f ;
break ;
}
}
if ( ! file )
{
qWarning ( " Core::cancelFileRecv: No such file in queue " ) ;
return ;
}
file - > status = ToxFile : : STOPPED ;
emit fileTransferCancelled ( file - > friendId , file - > fileNum , ToxFile : : RECEIVING ) ;
tox_file_send_control ( tox , file - > friendId , 1 , file - > fileNum , TOX_FILECONTROL_KILL , nullptr , 0 ) ;
removeFileFromQueue ( true , friendId , fileNum ) ;
}
void Core : : rejectFileRecvRequest ( int friendId , int fileNum )
{
ToxFile * file { nullptr } ;
for ( ToxFile & f : fileRecvQueue )
{
if ( f . fileNum = = fileNum & & f . friendId = = friendId )
{
file = & f ;
break ;
}
}
if ( ! file )
{
qWarning ( " Core::rejectFileRecvRequest: No such file in queue " ) ;
return ;
}
file - > status = ToxFile : : STOPPED ;
emit fileTransferCancelled ( file - > friendId , file - > fileNum , ToxFile : : SENDING ) ;
tox_file_send_control ( tox , file - > friendId , 1 , file - > fileNum , TOX_FILECONTROL_KILL , nullptr , 0 ) ;
removeFileFromQueue ( false , friendId , fileNum ) ;
}
2014-07-02 01:54:26 +08:00
void Core : : acceptFileRecvRequest ( int friendId , int fileNum , QString path )
2014-06-27 01:45:47 +08:00
{
ToxFile * file { nullptr } ;
for ( ToxFile & f : fileRecvQueue )
{
if ( f . fileNum = = fileNum & & f . friendId = = friendId )
{
file = & f ;
break ;
}
}
if ( ! file )
{
qWarning ( " Core::acceptFileRecvRequest: No such file in queue " ) ;
return ;
}
2014-07-02 01:54:26 +08:00
file - > setFilePath ( path ) ;
if ( ! file - > open ( true ) )
{
qWarning ( ) < < " Core::acceptFileRecvRequest: Unable to open file " ;
return ;
}
2014-06-27 01:45:47 +08:00
file - > status = ToxFile : : TRANSMITTING ;
emit fileTransferAccepted ( * file ) ;
tox_file_send_control ( tox , file - > friendId , 1 , file - > fileNum , TOX_FILECONTROL_ACCEPT , nullptr , 0 ) ;
2014-06-26 07:48:20 +08:00
}
2014-11-12 07:00:24 +08:00
void Core : : removeFriend ( int friendId , bool fake )
2014-06-25 04:11:11 +08:00
{
2014-11-12 07:00:24 +08:00
if ( ! tox | | fake )
2014-09-11 04:47:48 +08:00
return ;
2014-06-25 04:11:11 +08:00
if ( tox_del_friend ( tox , friendId ) = = - 1 ) {
emit failedToRemoveFriend ( friendId ) ;
} else {
2014-07-04 01:38:30 +08:00
saveConfiguration ( ) ;
2014-06-25 04:11:11 +08:00
emit friendRemoved ( friendId ) ;
}
}
2014-11-12 07:00:24 +08:00
void Core : : removeGroup ( int groupId , bool fake )
2014-06-25 04:11:11 +08:00
{
2014-11-12 07:00:24 +08:00
if ( ! tox | | fake )
2014-10-09 16:59:35 +08:00
return ;
2014-06-25 04:11:11 +08:00
tox_del_groupchat ( tox , groupId ) ;
2014-11-17 00:45:06 +08:00
2014-11-17 02:11:37 +08:00
if ( groupCalls [ groupId ] . active )
leaveGroupCall ( groupId ) ;
2014-06-25 04:11:11 +08:00
}
2014-11-03 01:36:27 +08:00
QString Core : : getUsername ( ) const
2014-07-12 04:38:39 +08:00
{
2014-10-27 04:18:45 +08:00
QString sname ;
2014-07-12 04:38:39 +08:00
int size = tox_get_self_name_size ( tox ) ;
uint8_t * name = new uint8_t [ size ] ;
if ( tox_get_self_name ( tox , name ) = = size )
2014-10-27 04:18:45 +08:00
sname = CString : : toString ( name , size ) ;
2014-07-12 04:38:39 +08:00
delete [ ] name ;
2014-10-27 04:18:45 +08:00
return sname ;
2014-07-12 04:38:39 +08:00
}
2014-06-25 04:11:11 +08:00
void Core : : setUsername ( const QString & username )
{
CString cUsername ( username ) ;
if ( tox_set_name ( tox , cUsername . data ( ) , cUsername . size ( ) ) = = - 1 ) {
emit failedToSetUsername ( username ) ;
} else {
emit usernameSet ( username ) ;
2014-07-27 16:27:15 +08:00
saveConfiguration ( ) ;
2014-06-25 04:11:11 +08:00
}
}
2014-09-24 22:51:16 +08:00
void Core : : setAvatar ( uint8_t format , const QByteArray & data )
{
if ( tox_set_avatar ( tox , format , ( uint8_t * ) data . constData ( ) , data . size ( ) ) ! = 0 )
{
qWarning ( ) < < " Core: Failed to set self avatar " ;
return ;
}
QPixmap pic ;
pic . loadFromData ( data ) ;
2014-09-28 06:19:30 +08:00
Settings : : getInstance ( ) . saveAvatar ( pic , getSelfId ( ) . toString ( ) ) ;
2014-09-24 22:51:16 +08:00
emit selfAvatarChanged ( pic ) ;
2014-09-28 06:19:30 +08:00
// Broadcast our new avatar!
// according to tox.h, we need not broadcast this ourselves, but initial testing indicated elsewise
const uint32_t friendCount = tox_count_friendlist ( tox ) ; ;
for ( unsigned i = 0 ; i < friendCount ; i + + )
tox_send_avatar_info ( tox , i ) ;
2014-09-24 22:51:16 +08:00
}
2014-11-03 01:36:27 +08:00
ToxID Core : : getSelfId ( ) const
2014-09-11 19:40:27 +08:00
{
uint8_t friendAddress [ TOX_FRIEND_ADDRESS_SIZE ] ;
tox_get_address ( tox , friendAddress ) ;
2014-09-12 21:41:41 +08:00
return ToxID : : fromString ( CFriendAddress : : toString ( friendAddress ) ) ;
2014-09-11 19:40:27 +08:00
}
2014-11-03 01:36:27 +08:00
QString Core : : getIDString ( ) const
2014-09-13 02:53:29 +08:00
{
2014-10-09 09:25:26 +08:00
return getSelfId ( ) . toString ( ) . left ( 12 ) ;
2014-09-13 02:53:29 +08:00
// 12 is the smallest multiple of four such that
// 16^n > 10^10 (which is roughly the planet's population)
}
2014-11-03 01:36:27 +08:00
QString Core : : getStatusMessage ( ) const
2014-07-12 04:38:39 +08:00
{
2014-10-27 04:33:24 +08:00
QString sname ;
2014-07-12 04:38:39 +08:00
int size = tox_get_self_status_message_size ( tox ) ;
uint8_t * name = new uint8_t [ size ] ;
if ( tox_get_self_status_message ( tox , name , size ) = = size )
2014-10-27 04:33:24 +08:00
sname = CString : : toString ( name , size ) ;
2014-07-12 04:38:39 +08:00
delete [ ] name ;
2014-10-27 04:33:24 +08:00
return sname ;
2014-07-12 04:38:39 +08:00
}
2014-06-25 04:11:11 +08:00
void Core : : setStatusMessage ( const QString & message )
{
CString cMessage ( message ) ;
if ( tox_set_status_message ( tox , cMessage . data ( ) , cMessage . size ( ) ) = = - 1 ) {
emit failedToSetStatusMessage ( message ) ;
} else {
2014-07-04 01:38:30 +08:00
saveConfiguration ( ) ;
2014-06-25 04:11:11 +08:00
emit statusMessageSet ( message ) ;
}
}
void Core : : setStatus ( Status status )
{
TOX_USERSTATUS userstatus ;
switch ( status ) {
case Status : : Online :
userstatus = TOX_USERSTATUS_NONE ;
break ;
case Status : : Away :
userstatus = TOX_USERSTATUS_AWAY ;
break ;
case Status : : Busy :
userstatus = TOX_USERSTATUS_BUSY ;
break ;
default :
userstatus = TOX_USERSTATUS_INVALID ;
break ;
}
if ( tox_set_user_status ( tox , userstatus ) = = 0 ) {
2014-07-04 01:38:30 +08:00
saveConfiguration ( ) ;
2014-06-25 04:11:11 +08:00
emit statusSet ( status ) ;
} else {
emit failedToSetStatus ( status ) ;
}
}
2014-07-12 00:05:18 +08:00
void Core : : onFileTransferFinished ( ToxFile file )
{
if ( file . direction = = file . SENDING )
2014-07-16 09:37:08 +08:00
emit fileUploadFinished ( file . filePath ) ;
2014-07-12 00:05:18 +08:00
else
2014-07-16 09:37:08 +08:00
emit fileDownloadFinished ( file . filePath ) ;
2014-07-12 00:05:18 +08:00
}
2014-07-23 17:22:09 +08:00
QString Core : : sanitize ( QString name )
2014-06-25 04:11:11 +08:00
{
2014-09-13 03:38:14 +08:00
// these are pretty much Windows banned filename characters
QList < QChar > banned = { ' / ' , ' \\ ' , ' : ' , ' < ' , ' > ' , ' " ' , ' | ' , ' ? ' , ' * ' } ;
for ( QChar c : banned )
name . replace ( c , ' _ ' ) ;
// also remove leading and trailing periods
if ( name [ 0 ] = = ' . ' )
name [ 0 ] = ' _ ' ;
if ( name . endsWith ( ' . ' ) )
name [ name . length ( ) - 1 ] = ' _ ' ;
2014-07-17 06:43:30 +08:00
return name ;
}
2014-10-09 09:25:26 +08:00
bool Core : : loadConfiguration ( QString path )
2014-09-10 21:36:11 +08:00
{
2014-07-27 16:27:15 +08:00
// setting the profile is now the responsibility of the caller
2014-06-25 04:11:11 +08:00
QFile configurationFile ( path ) ;
2014-07-17 06:43:30 +08:00
qDebug ( ) < < " Core::loadConfiguration: reading from " < < path ;
2014-06-25 04:11:11 +08:00
if ( ! configurationFile . exists ( ) ) {
qWarning ( ) < < " The Tox configuration file was not found " ;
2014-10-01 19:23:00 +08:00
return true ;
2014-06-25 04:11:11 +08:00
}
if ( ! configurationFile . open ( QIODevice : : ReadOnly ) ) {
qCritical ( ) < < " File " < < path < < " cannot be opened " ;
2014-10-01 19:23:00 +08:00
return true ;
2014-06-25 04:11:11 +08:00
}
qint64 fileSize = configurationFile . size ( ) ;
if ( fileSize > 0 ) {
QByteArray data = configurationFile . readAll ( ) ;
2014-10-01 19:23:00 +08:00
int error = tox_load ( tox , reinterpret_cast < uint8_t * > ( data . data ( ) ) , data . size ( ) ) ;
if ( error < 0 )
{
2014-10-19 01:38:47 +08:00
qWarning ( ) < < " Core: tox_load failed with error " < < error ;
2014-10-01 19:23:00 +08:00
}
else if ( error = = 1 ) // Encrypted data save
{
2014-10-24 21:56:27 +08:00
if ( ! Settings : : getInstance ( ) . getEncryptTox ( ) )
Widget : : getInstance ( ) - > showWarningMsgBox ( tr ( " Encryption error " ) , tr ( " The .tox file is encrypted, but encryption was not checked, continuing regardless. " ) ) ;
2014-10-24 19:25:40 +08:00
uint8_t salt [ tox_pass_salt_length ( ) ] ;
tox_get_salt ( reinterpret_cast < uint8_t * > ( data . data ( ) ) , salt ) ;
2014-10-19 15:35:11 +08:00
do
2014-10-01 19:23:00 +08:00
{
2014-10-24 19:25:40 +08:00
while ( ! pwsaltedkeys [ ptMain ] )
2014-10-12 18:24:57 +08:00
{
2014-10-24 19:25:40 +08:00
emit blockingGetPassword ( tr ( " Tox datafile decryption password " ) , ptMain , salt ) ;
if ( ! pwsaltedkeys [ ptMain ] )
2014-10-24 02:39:28 +08:00
Widget : : getInstance ( ) - > showWarningMsgBox ( tr ( " Password error " ) , tr ( " Failed to setup password. \n Empty password. " ) ) ;
2014-10-12 18:24:57 +08:00
}
2014-10-19 15:35:11 +08:00
2014-10-24 19:25:40 +08:00
error = tox_encrypted_key_load ( tox , reinterpret_cast < uint8_t * > ( data . data ( ) ) , data . size ( ) , pwsaltedkeys [ ptMain ] ) ;
2014-10-19 15:35:11 +08:00
if ( error ! = 0 )
2014-10-12 18:24:57 +08:00
{
2014-10-19 15:35:11 +08:00
QMessageBox msgb ;
2014-10-24 02:39:28 +08:00
msgb . moveToThread ( qApp - > thread ( ) ) ;
2014-10-19 15:35:11 +08:00
QPushButton * tryAgain = msgb . addButton ( tr ( " Try Again " ) , QMessageBox : : AcceptRole ) ;
QPushButton * cancel = msgb . addButton ( tr ( " Change profile " ) , QMessageBox : : RejectRole ) ;
QPushButton * wipe = msgb . addButton ( tr ( " Reinit current profile " ) , QMessageBox : : ActionRole ) ;
msgb . setDefaultButton ( tryAgain ) ;
2014-10-19 22:59:58 +08:00
msgb . setWindowTitle ( tr ( " Password error " ) ) ;
msgb . setText ( tr ( " Wrong password has been entered " ) ) ;
// msgb.setInformativeText(tr(""));
2014-10-19 15:35:11 +08:00
msgb . exec ( ) ;
if ( msgb . clickedButton ( ) = = tryAgain )
2014-10-22 21:36:36 +08:00
clearPassword ( ptMain ) ;
2014-10-24 19:25:40 +08:00
else if ( msgb . clickedButton ( ) = = cancel )
2014-10-19 15:35:11 +08:00
{
configurationFile . close ( ) ;
return false ;
2014-10-24 19:25:40 +08:00
}
else if ( msgb . clickedButton ( ) = = wipe )
2014-10-19 15:35:11 +08:00
{
2014-10-22 21:36:36 +08:00
clearPassword ( ptMain ) ;
2014-10-19 15:35:11 +08:00
Settings : : getInstance ( ) . setEncryptTox ( false ) ;
error = 0 ;
}
}
2014-10-24 19:25:40 +08:00
else
Settings : : getInstance ( ) . setEncryptTox ( true ) ;
2014-10-19 15:35:11 +08:00
} while ( error ! = 0 ) ;
}
}
2014-06-25 04:11:11 +08:00
configurationFile . close ( ) ;
2014-07-12 04:38:39 +08:00
// set GUI with user and statusmsg
QString name = getUsername ( ) ;
2014-10-18 09:15:26 +08:00
if ( ! name . isEmpty ( ) )
2014-07-12 04:38:39 +08:00
emit usernameSet ( name ) ;
QString msg = getStatusMessage ( ) ;
2014-10-18 09:15:26 +08:00
if ( ! msg . isEmpty ( ) )
2014-07-12 04:38:39 +08:00
emit statusMessageSet ( msg ) ;
2014-10-18 09:15:26 +08:00
QString id = getSelfId ( ) . toString ( ) ;
if ( ! id . isEmpty ( ) )
emit idSet ( id ) ;
2014-10-24 19:25:40 +08:00
// tox core is already decrypted
if ( Settings : : getInstance ( ) . getEnableLogging ( ) & & Settings : : getInstance ( ) . getEncryptLogs ( ) )
{
bool error = true ;
// get salt
QFile file ( HistoryKeeper : : getHistoryPath ( ) ) ;
file . open ( QIODevice : : ReadOnly ) ;
QByteArray data = file . read ( tox_pass_encryption_extra_length ( ) ) ;
file . close ( ) ;
uint8_t salt [ tox_pass_salt_length ( ) ] ;
int err = tox_get_salt ( reinterpret_cast < uint8_t * > ( data . data ( ) ) , salt ) ;
if ( err )
{ // maybe we should handle this better
qWarning ( ) < < " Core: history db isn't encrypted, but encryption is set!! No history loaded... " ;
}
else
{
do
{
while ( ! pwsaltedkeys [ ptHistory ] )
{
emit blockingGetPassword ( tr ( " History Log decryption password " ) , Core : : ptHistory , salt ) ;
if ( ! pwsaltedkeys [ ptHistory ] )
Widget : : getInstance ( ) - > showWarningMsgBox ( tr ( " Password error " ) , tr ( " Failed to setup password. \n Empty password. " ) ) ;
}
if ( ! HistoryKeeper : : checkPassword ( ) )
{
if ( QMessageBox : : Ok = = Widget : : getInstance ( ) - > showWarningMsgBox ( tr ( " Encrypted log " ) ,
2014-11-26 04:22:21 +08:00
tr ( " Your history is encrypted with different password. \n Do you want to try another password? " ) ,
2014-10-24 19:25:40 +08:00
QMessageBox : : Ok | QMessageBox : : Cancel ) )
{
error = true ;
clearPassword ( ptHistory ) ;
}
else
{
error = false ;
clearPassword ( ptHistory ) ;
2014-11-26 04:22:21 +08:00
Widget : : getInstance ( ) - > showWarningMsgBox ( tr ( " History " ) , tr ( " Due to incorret password history will be disabled. " ) ) ;
2014-10-24 19:25:40 +08:00
Settings : : getInstance ( ) . setEncryptLogs ( false ) ;
Settings : : getInstance ( ) . setEnableLogging ( false ) ;
}
} else {
error = false ;
}
} while ( error ) ;
}
}
2014-06-25 04:11:11 +08:00
loadFriends ( ) ;
2014-10-01 19:23:00 +08:00
return true ;
2014-06-25 04:11:11 +08:00
}
2014-07-25 03:50:47 +08:00
void Core : : saveConfiguration ( )
2014-06-25 04:11:11 +08:00
{
2015-01-24 22:31:11 +08:00
if ( QThread : : currentThread ( ) ! = coreThread )
return ( void ) QMetaObject : : invokeMethod ( this , " saveConfiguration " ) ;
2014-07-25 03:50:47 +08:00
QString dir = Settings : : getSettingsDirPath ( ) ;
QDir directory ( dir ) ;
if ( ! directory . exists ( ) & & ! directory . mkpath ( directory . absolutePath ( ) ) ) {
qCritical ( ) < < " Error while creating directory " < < dir ;
2014-07-01 03:26:37 +08:00
return ;
}
2014-07-25 03:50:47 +08:00
QString profile = Settings : : getInstance ( ) . getCurrentProfile ( ) ;
2014-10-16 00:18:32 +08:00
2014-07-25 03:50:47 +08:00
if ( profile = = " " )
{ // no profile active; this should only happen on startup, if at all
profile = sanitize ( getUsername ( ) ) ;
2014-10-16 00:18:32 +08:00
2014-07-27 16:27:15 +08:00
if ( profile = = " " ) // happens on creation of a new Tox ID
profile = getIDString ( ) ;
2014-10-16 00:18:32 +08:00
2014-07-25 03:50:47 +08:00
Settings : : getInstance ( ) . setCurrentProfile ( profile ) ;
}
2014-10-16 00:18:32 +08:00
QString path = directory . filePath ( profile + TOX_EXT ) ;
2014-07-27 16:27:15 +08:00
saveConfiguration ( path ) ;
2014-07-25 03:50:47 +08:00
}
2014-07-01 03:26:37 +08:00
2014-07-25 03:50:47 +08:00
void Core : : saveConfiguration ( const QString & path )
{
2015-01-24 22:31:11 +08:00
if ( QThread : : currentThread ( ) ! = coreThread )
return ( void ) QMetaObject : : invokeMethod ( this , " saveConfiguration " , Q_ARG ( const QString & , path ) ) ;
2014-07-25 03:50:47 +08:00
if ( ! tox )
2014-07-17 06:43:30 +08:00
{
2014-07-25 03:50:47 +08:00
qWarning ( ) < < " Core::saveConfiguration: Tox not started, aborting! " ;
return ;
2014-06-25 04:11:11 +08:00
}
2014-10-09 09:25:26 +08:00
Settings : : getInstance ( ) . save ( ) ;
2014-06-25 04:11:11 +08:00
QSaveFile configurationFile ( path ) ;
2015-01-24 22:31:11 +08:00
if ( ! configurationFile . open ( QIODevice : : WriteOnly ) )
{
2014-06-25 04:11:11 +08:00
qCritical ( ) < < " File " < < path < < " cannot be opened " ;
return ;
}
2014-07-17 06:43:30 +08:00
qDebug ( ) < < " Core: writing tox_save to " < < path ;
2014-09-05 05:13:59 +08:00
2015-01-24 22:31:11 +08:00
uint32_t fileSize ;
bool encrypt = Settings : : getInstance ( ) . getEncryptTox ( ) ;
2014-10-24 19:25:40 +08:00
if ( encrypt )
2014-10-12 15:31:48 +08:00
fileSize = tox_encrypted_size ( tox ) ;
else
fileSize = tox_size ( tox ) ;
2015-01-24 22:31:11 +08:00
if ( fileSize > 0 & & fileSize < = INT32_MAX )
{
2014-06-25 04:11:11 +08:00
uint8_t * data = new uint8_t [ fileSize ] ;
2014-10-24 19:25:40 +08:00
if ( encrypt )
2014-10-12 15:31:48 +08:00
{
2014-10-24 19:25:40 +08:00
if ( ! pwsaltedkeys [ ptMain ] )
2014-10-12 15:31:48 +08:00
{
2014-10-24 02:39:28 +08:00
Widget : : getInstance ( ) - > showWarningMsgBox ( tr ( " NO Password " ) , tr ( " Will be saved without encryption! " ) ) ;
2014-10-19 22:59:58 +08:00
tox_save ( tox , data ) ;
2014-10-24 19:25:40 +08:00
}
else
{
int ret = tox_encrypted_key_save ( tox , data , pwsaltedkeys [ ptMain ] ) ;
2014-10-19 22:59:58 +08:00
if ( ret = = - 1 )
{
qCritical ( ) < < " Core::saveConfiguration: encryption of save file failed!!! " ;
return ;
}
2014-10-12 15:31:48 +08:00
}
2014-10-19 22:59:58 +08:00
}
2014-10-24 19:25:40 +08:00
else
2015-01-24 22:31:11 +08:00
{
2014-10-24 19:25:40 +08:00
tox_save ( tox , data ) ;
2015-01-24 22:31:11 +08:00
}
2014-10-12 15:31:48 +08:00
2014-06-25 04:11:11 +08:00
configurationFile . write ( reinterpret_cast < char * > ( data ) , fileSize ) ;
configurationFile . commit ( ) ;
delete [ ] data ;
}
}
2014-10-15 10:06:44 +08:00
void Core : : switchConfiguration ( const QString & profile )
2014-09-10 21:12:43 +08:00
{
2014-10-14 05:17:42 +08:00
if ( profile . isEmpty ( ) )
2014-10-20 11:07:51 +08:00
qDebug ( ) < < " Core: creating new Id " ;
2014-10-14 05:17:42 +08:00
else
qDebug ( ) < < " Core: switching from " < < Settings : : getInstance ( ) . getCurrentProfile ( ) < < " to " < < profile ;
2014-12-03 08:26:17 +08:00
2014-10-16 00:18:32 +08:00
saveConfiguration ( ) ;
2014-12-03 08:26:17 +08:00
ready = false ;
2014-10-22 21:36:36 +08:00
clearPassword ( ptMain ) ;
clearPassword ( ptHistory ) ;
2014-11-06 22:12:10 +08:00
2014-10-09 09:25:26 +08:00
toxTimer - > stop ( ) ;
2014-11-02 19:24:14 +08:00
Widget : : getInstance ( ) - > setEnabledThreadsafe ( false ) ;
2014-09-10 21:12:43 +08:00
if ( tox ) {
toxav_kill ( toxav ) ;
2014-09-11 04:47:48 +08:00
toxav = nullptr ;
2014-09-10 21:12:43 +08:00
tox_kill ( tox ) ;
2014-09-11 04:47:48 +08:00
tox = nullptr ;
2014-09-10 21:12:43 +08:00
}
2014-12-03 08:26:17 +08:00
2014-10-09 16:59:35 +08:00
emit selfAvatarChanged ( QPixmap ( " :/img/contact_dark.png " ) ) ;
2014-10-15 10:06:44 +08:00
emit blockingClearContacts ( ) ; // we need this to block, but signals are required for thread safety
2014-10-20 11:07:51 +08:00
if ( profile . isEmpty ( ) )
loadPath = " " ;
else
loadPath = QDir ( Settings : : getSettingsDirPath ( ) ) . filePath ( profile + TOX_EXT ) ;
2014-12-03 08:26:17 +08:00
// the new profile needs to be set before resetting the settings, so that
// we don't load the old profile's profile.ini
Settings : : getInstance ( ) . setCurrentProfile ( profile ) ;
Settings : : getInstance ( ) . save ( false ) ; // save new profile, but don't write old profile info to newprofile.ini
Settings : : resetInstance ( ) ;
2014-10-19 01:38:47 +08:00
HistoryKeeper : : getInstance ( ) - > resetInstance ( ) ;
2014-10-19 01:52:43 +08:00
2014-10-09 16:59:35 +08:00
start ( ) ;
2014-11-02 19:24:14 +08:00
Widget : : getInstance ( ) - > setEnabledThreadsafe ( true ) ;
2014-09-10 21:12:43 +08:00
}
2014-06-25 04:11:11 +08:00
void Core : : loadFriends ( )
{
const uint32_t friendCount = tox_count_friendlist ( tox ) ;
if ( friendCount > 0 ) {
// assuming there are not that many friends to fill up the whole stack
int32_t * ids = new int32_t [ friendCount ] ;
tox_get_friendlist ( tox , ids , friendCount ) ;
uint8_t clientId [ TOX_CLIENT_ID_SIZE ] ;
for ( int32_t i = 0 ; i < static_cast < int32_t > ( friendCount ) ; + + i ) {
if ( tox_get_client_id ( tox , ids [ i ] , clientId ) = = 0 ) {
emit friendAdded ( ids [ i ] , CUserId : : toString ( clientId ) ) ;
2014-10-09 16:59:35 +08:00
2014-06-25 04:11:11 +08:00
const int nameSize = tox_get_name_size ( tox , ids [ i ] ) ;
if ( nameSize > 0 ) {
uint8_t * name = new uint8_t [ nameSize ] ;
if ( tox_get_name ( tox , ids [ i ] , name ) = = nameSize ) {
2014-09-29 01:57:27 +08:00
emit friendUsernameChanged ( ids [ i ] , CString : : toString ( name , nameSize ) ) ;
2014-06-25 04:11:11 +08:00
}
delete [ ] name ;
}
const int statusMessageSize = tox_get_status_message_size ( tox , ids [ i ] ) ;
if ( statusMessageSize > 0 ) {
uint8_t * statusMessage = new uint8_t [ statusMessageSize ] ;
if ( tox_get_status_message ( tox , ids [ i ] , statusMessage , statusMessageSize ) = = statusMessageSize ) {
2014-09-29 01:57:27 +08:00
emit friendStatusMessageChanged ( ids [ i ] , CString : : toString ( statusMessage , statusMessageSize ) ) ;
2014-06-25 04:11:11 +08:00
}
delete [ ] statusMessage ;
}
checkLastOnline ( ids [ i ] ) ;
}
}
delete [ ] ids ;
}
}
void Core : : checkLastOnline ( int friendId ) {
const uint64_t lastOnline = tox_get_last_online ( tox , friendId ) ;
if ( lastOnline > 0 ) {
emit friendLastSeenChanged ( friendId , QDateTime : : fromTime_t ( lastOnline ) ) ;
}
}
int Core : : getGroupNumberPeers ( int groupId ) const
{
return tox_group_number_peers ( tox , groupId ) ;
}
QString Core : : getGroupPeerName ( int groupId , int peerId ) const
{
QString name ;
uint8_t nameArray [ TOX_MAX_NAME_LENGTH ] ;
int length = tox_group_peername ( tox , groupId , peerId , nameArray ) ;
if ( length = = - 1 )
{
qWarning ( ) < < " Core::getGroupPeerName: Unknown error " ;
return name ;
}
name = CString : : toString ( nameArray , length ) ;
return name ;
}
2014-11-23 23:55:49 +08:00
ToxID Core : : getGroupPeerToxID ( int groupId , int peerId ) const
{
ToxID peerToxID ;
uint8_t rawID [ TOX_CLIENT_ID_SIZE ] ;
int res = tox_group_peer_pubkey ( tox , groupId , peerId , rawID ) ;
if ( res = = - 1 )
{
qWarning ( ) < < " Core::getGroupPeerToxID: Unknown error " ;
return peerToxID ;
}
peerToxID = ToxID : : fromString ( CUserId : : toString ( rawID ) ) ;
return peerToxID ;
}
2014-06-25 04:11:11 +08:00
QList < QString > Core : : getGroupPeerNames ( int groupId ) const
{
QList < QString > names ;
int nPeers = getGroupNumberPeers ( groupId ) ;
if ( nPeers = = - 1 )
{
qWarning ( ) < < " Core::getGroupPeerNames: Unable to get number of peers " ;
return names ;
}
uint8_t namesArray [ nPeers ] [ TOX_MAX_NAME_LENGTH ] ;
uint16_t * lengths = new uint16_t [ nPeers ] ;
int result = tox_group_get_names ( tox , groupId , namesArray , lengths , nPeers ) ;
if ( result ! = nPeers )
{
qWarning ( ) < < " Core::getGroupPeerNames: Unexpected result " ;
return names ;
}
for ( int i = 0 ; i < nPeers ; i + + )
names . push_back ( CString : : toString ( namesArray [ i ] , lengths [ i ] ) ) ;
return names ;
}
2014-11-11 23:05:01 +08:00
int Core : : joinGroupchat ( int32_t friendnumber , uint8_t type , const uint8_t * friend_group_public_key , uint16_t length ) const
2014-06-25 04:11:11 +08:00
{
2014-11-11 23:05:01 +08:00
if ( type = = TOX_GROUPCHAT_TYPE_TEXT )
{
qDebug ( ) < < QString ( " Trying to join text groupchat invite sent by friend %1 " ) . arg ( friendnumber ) ;
return tox_join_groupchat ( tox , friendnumber , friend_group_public_key , length ) ;
}
else if ( type = = TOX_GROUPCHAT_TYPE_AV )
{
qDebug ( ) < < QString ( " Trying to join AV groupchat invite sent by friend %1 " ) . arg ( friendnumber ) ;
2014-11-20 05:26:04 +08:00
return toxav_join_av_groupchat ( tox , friendnumber , friend_group_public_key , length ,
& Audio : : playGroupAudioQueued , const_cast < Core * > ( this ) ) ;
2014-11-11 23:05:01 +08:00
}
else
{
qWarning ( ) < < " Core::joinGroupchat: Unknown groupchat type " < < type ;
return - 1 ;
}
2014-06-25 04:11:11 +08:00
}
void Core : : quitGroupChat ( int groupId ) const
{
tox_del_groupchat ( tox , groupId ) ;
}
2014-06-27 01:45:47 +08:00
void Core : : removeFileFromQueue ( bool sendQueue , int friendId , int fileId )
{
bool found = false ;
if ( sendQueue )
{
for ( int i = 0 ; i < fileSendQueue . size ( ) ; )
{
if ( fileSendQueue [ i ] . friendId = = friendId & & fileSendQueue [ i ] . fileNum = = fileId )
{
found = true ;
2014-07-02 01:54:26 +08:00
fileSendQueue [ i ] . file - > close ( ) ;
delete fileSendQueue [ i ] . file ;
2014-06-27 01:45:47 +08:00
fileSendQueue . removeAt ( i ) ;
continue ;
}
i + + ;
}
}
else
{
for ( int i = 0 ; i < fileRecvQueue . size ( ) ; )
{
if ( fileRecvQueue [ i ] . friendId = = friendId & & fileRecvQueue [ i ] . fileNum = = fileId )
{
found = true ;
2014-07-02 01:54:26 +08:00
fileRecvQueue [ i ] . file - > close ( ) ;
delete fileRecvQueue [ i ] . file ;
2014-06-27 01:45:47 +08:00
fileRecvQueue . removeAt ( i ) ;
continue ;
}
i + + ;
}
}
if ( ! found )
qWarning ( ) < < " Core::removeFileFromQueue: No such file in queue " ;
}
void Core : : sendAllFileData ( Core * core , ToxFile * file )
{
2014-08-29 03:56:55 +08:00
if ( file - > status = = ToxFile : : PAUSED )
2014-06-27 01:45:47 +08:00
{
2014-08-31 19:13:46 +08:00
file - > sendTimer - > start ( 5 + TOX_FILE_INTERVAL ) ;
2014-06-27 08:08:33 +08:00
return ;
}
2014-08-29 03:56:55 +08:00
else if ( file - > status = = ToxFile : : STOPPED )
2014-06-27 09:06:56 +08:00
{
2014-08-29 03:56:55 +08:00
qWarning ( " Core::sendAllFileData: File is stopped " ) ;
file - > sendTimer - > disconnect ( ) ;
delete file - > sendTimer ;
file - > sendTimer = nullptr ;
2014-06-27 09:06:56 +08:00
return ;
}
2014-08-29 03:56:55 +08:00
emit core - > fileTransferInfo ( file - > friendId , file - > fileNum , file - > filesize , file - > bytesSent , ToxFile : : SENDING ) ;
2014-11-02 21:03:39 +08:00
// qApp->processEvents();
2014-08-29 03:56:55 +08:00
long long chunkSize = tox_file_data_size ( core - > tox , file - > friendId ) ;
if ( chunkSize = = - 1 )
2014-06-27 08:08:33 +08:00
{
2014-08-29 03:56:55 +08:00
qWarning ( " Core::fileHeartbeat: Error getting preffered chunk size, aborting file send " ) ;
file - > status = ToxFile : : STOPPED ;
emit core - > fileTransferCancelled ( file - > friendId , file - > fileNum , ToxFile : : SENDING ) ;
tox_file_send_control ( core - > tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_KILL , nullptr , 0 ) ;
removeFileFromQueue ( true , file - > friendId , file - > fileNum ) ;
2014-06-27 08:08:33 +08:00
return ;
}
2014-08-29 03:56:55 +08:00
//qDebug() << "chunkSize: " << chunkSize;
chunkSize = std : : min ( chunkSize , file - > filesize ) ;
uint8_t * data = new uint8_t [ chunkSize ] ;
file - > file - > seek ( file - > bytesSent ) ;
int readSize = file - > file - > read ( ( char * ) data , chunkSize ) ;
if ( readSize = = - 1 )
2014-06-27 09:06:56 +08:00
{
2014-08-29 03:56:55 +08:00
qWarning ( ) < < QString ( " Core::sendAllFileData: Error reading from file: %1 " ) . arg ( file - > file - > errorString ( ) ) ;
delete [ ] data ;
2014-08-29 18:52:09 +08:00
file - > status = ToxFile : : STOPPED ;
emit core - > fileTransferCancelled ( file - > friendId , file - > fileNum , ToxFile : : SENDING ) ;
tox_file_send_control ( core - > tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_KILL , nullptr , 0 ) ;
removeFileFromQueue ( true , file - > friendId , file - > fileNum ) ;
2014-06-27 09:06:56 +08:00
return ;
}
2014-08-29 03:56:55 +08:00
else if ( readSize = = 0 )
2014-06-28 03:59:25 +08:00
{
2014-08-29 03:56:55 +08:00
qWarning ( ) < < QString ( " Core::sendAllFileData: Nothing to read from file: %1 " ) . arg ( file - > file - > errorString ( ) ) ;
delete [ ] data ;
2014-08-29 18:52:09 +08:00
file - > status = ToxFile : : STOPPED ;
emit core - > fileTransferCancelled ( file - > friendId , file - > fileNum , ToxFile : : SENDING ) ;
tox_file_send_control ( core - > tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_KILL , nullptr , 0 ) ;
removeFileFromQueue ( true , file - > friendId , file - > fileNum ) ;
2014-06-28 03:59:25 +08:00
return ;
}
2014-08-29 03:56:55 +08:00
if ( tox_file_send_data ( core - > tox , file - > friendId , file - > fileNum , data , readSize ) = = - 1 )
2014-06-30 05:38:48 +08:00
{
2014-08-29 03:56:55 +08:00
//qWarning("Core::fileHeartbeat: Error sending data chunk");
//core->process();
2014-07-02 01:54:26 +08:00
delete [ ] data ;
2014-09-01 05:06:31 +08:00
//QThread::msleep(1);
file - > sendTimer - > start ( 1 + TOX_FILE_INTERVAL ) ;
2014-06-30 05:38:48 +08:00
return ;
}
2014-08-29 03:56:55 +08:00
delete [ ] data ;
file - > bytesSent + = readSize ;
//qDebug() << QString("Core::fileHeartbeat: sent %1/%2 bytes").arg(file->bytesSent).arg(file->fileData.size());
2014-06-27 08:08:33 +08:00
2014-08-29 03:56:55 +08:00
if ( file - > bytesSent < file - > filesize )
2014-06-28 03:59:25 +08:00
{
2014-08-29 03:56:55 +08:00
file - > sendTimer - > start ( TOX_FILE_INTERVAL ) ;
2014-06-30 10:39:43 +08:00
return ;
}
else
2014-06-30 05:38:48 +08:00
{
2014-08-29 18:52:09 +08:00
//qDebug("Core: File transfer finished");
2014-08-29 03:56:55 +08:00
file - > sendTimer - > disconnect ( ) ;
delete file - > sendTimer ;
file - > sendTimer = nullptr ;
tox_file_send_control ( core - > tox , file - > friendId , 0 , file - > fileNum , TOX_FILECONTROL_FINISHED , nullptr , 0 ) ;
2014-08-29 18:52:09 +08:00
//emit core->fileTransferFinished(*file);
2014-06-30 05:38:48 +08:00
}
}
2014-06-28 16:53:38 +08:00
void Core : : groupInviteFriend ( int friendId , int groupId )
{
tox_invite_friend ( tox , friendId , groupId ) ;
}
2014-06-30 05:38:48 +08:00
2014-11-11 23:05:01 +08:00
void Core : : createGroup ( uint8_t type )
2014-06-30 05:38:48 +08:00
{
2014-11-11 23:05:01 +08:00
if ( type = = TOX_GROUPCHAT_TYPE_TEXT )
2014-11-13 19:18:04 +08:00
{
2014-11-11 23:05:01 +08:00
emit emptyGroupCreated ( tox_add_groupchat ( tox ) ) ;
2014-11-13 19:18:04 +08:00
}
2014-11-11 23:05:01 +08:00
else if ( type = = TOX_GROUPCHAT_TYPE_AV )
2014-11-13 19:18:04 +08:00
{
2014-11-20 05:26:04 +08:00
emit emptyGroupCreated ( toxav_add_av_groupchat ( tox , & Audio : : playGroupAudioQueued , this ) ) ;
2014-11-13 19:18:04 +08:00
}
2014-11-11 23:05:01 +08:00
else
2014-11-13 19:18:04 +08:00
{
2014-11-11 23:05:01 +08:00
qWarning ( ) < < " Core::createGroup: Unknown type " < < type ;
2014-11-13 19:18:04 +08:00
}
2014-06-30 05:38:48 +08:00
}
2014-07-12 20:10:24 +08:00
2014-11-10 03:23:43 +08:00
bool Core : : hasFriendWithAddress ( const QString & addr ) const
{
// Valid length check
2014-12-12 02:05:52 +08:00
if ( addr . length ( ) ! = ( TOX_FRIEND_ADDRESS_SIZE * 2 ) )
2014-11-10 08:04:35 +08:00
{
2014-11-10 03:23:43 +08:00
return false ;
}
QString pubkey = addr . left ( TOX_CLIENT_ID_SIZE * 2 ) ;
return hasFriendWithPublicKey ( pubkey ) ;
}
bool Core : : hasFriendWithPublicKey ( const QString & pubkey ) const
{
// Valid length check
2014-12-12 02:05:52 +08:00
if ( pubkey . length ( ) ! = ( TOX_CLIENT_ID_SIZE * 2 ) )
2014-11-10 08:04:35 +08:00
{
2014-11-10 03:23:43 +08:00
return false ;
}
bool found = false ;
const uint32_t friendCount = tox_count_friendlist ( tox ) ;
2014-11-10 08:04:35 +08:00
if ( friendCount > 0 )
{
2014-11-10 03:23:43 +08:00
int32_t * ids = new int32_t [ friendCount ] ;
tox_get_friendlist ( tox , ids , friendCount ) ;
2014-11-10 08:04:35 +08:00
for ( int32_t i = 0 ; i < static_cast < int32_t > ( friendCount ) ; + + i )
{
2014-11-10 03:23:43 +08:00
// getFriendAddress may return either id (public key) or address
QString addrOrId = getFriendAddress ( ids [ i ] ) ;
// Set true if found
2014-12-12 02:05:52 +08:00
if ( addrOrId . toUpper ( ) . startsWith ( pubkey . toUpper ( ) ) )
2014-11-10 08:04:35 +08:00
{
2014-11-10 03:23:43 +08:00
found = true ;
break ;
}
}
delete [ ] ids ;
}
return found ;
}
2014-09-01 04:26:45 +08:00
QString Core : : getFriendAddress ( int friendNumber ) const
2014-07-12 20:10:24 +08:00
{
2014-09-01 04:26:45 +08:00
// If we don't know the full address of the client, return just the id, otherwise get the full address
uint8_t rawid [ TOX_CLIENT_ID_SIZE ] ;
tox_get_client_id ( tox , friendNumber , rawid ) ;
QByteArray data ( ( char * ) rawid , TOX_CLIENT_ID_SIZE ) ;
QString id = data . toHex ( ) . toUpper ( ) ;
2014-07-12 20:10:24 +08:00
2014-11-08 00:02:10 +08:00
QString addr = Settings : : getInstance ( ) . getFriendAdress ( id ) ;
if ( addr . size ( ) > id . size ( ) )
return addr ;
2014-09-01 04:26:45 +08:00
return id ;
2014-07-12 20:10:24 +08:00
}
2014-09-21 18:30:10 +08:00
2014-09-30 10:24:31 +08:00
QString Core : : getFriendUsername ( int friendnumber ) const
{
uint8_t name [ TOX_MAX_NAME_LENGTH ] ;
tox_get_name ( tox , friendnumber , name ) ;
return CString : : toString ( name , tox_get_name_size ( tox , friendnumber ) ) ;
}
2014-12-29 01:26:35 +08:00
QList < CString > Core : : splitMessage ( const QString & message , int maxLen )
2014-09-21 18:30:10 +08:00
{
QList < CString > splittedMsgs ;
QByteArray ba_message ( message . toUtf8 ( ) ) ;
2014-12-29 01:26:35 +08:00
while ( ba_message . size ( ) > maxLen )
2014-09-21 18:30:10 +08:00
{
2014-12-29 01:26:35 +08:00
int splitPos = ba_message . lastIndexOf ( ' ' , maxLen - 1 ) ;
2014-09-21 18:30:10 +08:00
if ( splitPos < = 0 )
{
2014-12-29 01:26:35 +08:00
splitPos = maxLen ;
2014-09-21 18:30:10 +08:00
if ( ba_message [ splitPos ] & 0x80 )
{
do {
splitPos - - ;
} while ( ! ( ba_message [ splitPos ] & 0x40 ) ) ;
}
splitPos - - ;
}
splittedMsgs . push_back ( CString ( ba_message . left ( splitPos + 1 ) ) ) ;
ba_message = ba_message . mid ( splitPos + 1 ) ;
}
splittedMsgs . push_back ( CString ( ba_message ) ) ;
return splittedMsgs ;
}
2014-10-12 05:54:25 +08:00
2014-10-24 19:25:40 +08:00
void Core : : setPassword ( QString & password , PasswordType passtype , uint8_t * salt )
2014-10-12 05:54:25 +08:00
{
2014-10-12 07:58:10 +08:00
if ( password . isEmpty ( ) )
{
2014-10-22 21:36:36 +08:00
clearPassword ( passtype ) ;
2014-10-12 07:58:10 +08:00
return ;
}
2014-10-24 19:25:40 +08:00
if ( ! pwsaltedkeys [ passtype ] )
pwsaltedkeys [ passtype ] = new uint8_t [ tox_pass_key_length ( ) ] ;
2014-10-12 07:58:10 +08:00
2014-10-12 05:54:25 +08:00
CString str ( password ) ;
2014-10-24 19:25:40 +08:00
if ( salt )
tox_derive_key_with_salt ( str . data ( ) , str . size ( ) , salt , pwsaltedkeys [ passtype ] ) ;
else
tox_derive_key_from_pass ( str . data ( ) , str . size ( ) , pwsaltedkeys [ passtype ] ) ;
2014-10-17 23:53:06 +08:00
2014-10-12 05:54:25 +08:00
password . clear ( ) ;
}
2014-10-22 21:36:36 +08:00
void Core : : clearPassword ( PasswordType passtype )
2014-10-12 07:58:10 +08:00
{
2014-10-24 19:25:40 +08:00
if ( pwsaltedkeys [ passtype ] )
2014-10-12 07:58:10 +08:00
{
2014-10-24 19:25:40 +08:00
delete [ ] pwsaltedkeys [ passtype ] ;
pwsaltedkeys [ passtype ] = nullptr ;
2014-10-12 07:58:10 +08:00
}
}
2014-10-22 21:36:36 +08:00
QByteArray Core : : encryptData ( const QByteArray & data , PasswordType passtype )
2014-10-12 07:58:10 +08:00
{
2014-10-24 19:25:40 +08:00
if ( ! pwsaltedkeys [ passtype ] )
2014-10-12 15:31:48 +08:00
return QByteArray ( ) ;
2014-10-12 16:27:48 +08:00
uint8_t encrypted [ data . size ( ) + tox_pass_encryption_extra_length ( ) ] ;
2014-10-24 19:25:40 +08:00
if ( tox_pass_key_encrypt ( reinterpret_cast < const uint8_t * > ( data . data ( ) ) , data . size ( ) , pwsaltedkeys [ passtype ] , encrypted ) = = - 1 )
2014-10-12 07:58:10 +08:00
{
qWarning ( ) < < " Core::encryptData: encryption failed " ;
return QByteArray ( ) ;
}
2014-10-12 16:27:48 +08:00
return QByteArray ( reinterpret_cast < char * > ( encrypted ) , data . size ( ) + tox_pass_encryption_extra_length ( ) ) ;
2014-10-12 07:58:10 +08:00
}
2014-10-22 21:36:36 +08:00
QByteArray Core : : decryptData ( const QByteArray & data , PasswordType passtype )
2014-10-12 18:24:57 +08:00
{
2014-10-24 19:25:40 +08:00
if ( ! pwsaltedkeys [ passtype ] )
2014-10-12 18:24:57 +08:00
return QByteArray ( ) ;
int sz = data . size ( ) - tox_pass_encryption_extra_length ( ) ;
uint8_t decrypted [ sz ] ;
2014-10-24 19:25:40 +08:00
if ( tox_pass_key_decrypt ( reinterpret_cast < const uint8_t * > ( data . data ( ) ) , data . size ( ) , pwsaltedkeys [ passtype ] , decrypted ) ! = sz )
2014-10-12 18:24:57 +08:00
{
qWarning ( ) < < " Core::decryptData: decryption failed " ;
return QByteArray ( ) ;
}
return QByteArray ( reinterpret_cast < char * > ( decrypted ) , sz ) ;
}
2014-10-19 01:38:47 +08:00
2014-10-22 21:36:36 +08:00
bool Core : : isPasswordSet ( PasswordType passtype )
2014-10-19 01:38:47 +08:00
{
2014-10-24 19:25:40 +08:00
if ( pwsaltedkeys [ passtype ] )
2014-10-19 01:38:47 +08:00
return true ;
return false ;
}
2014-11-03 01:36:27 +08:00
QString Core : : getPeerName ( const ToxID & id ) const
{
QString name ;
CUserId cid ( id . toString ( ) ) ;
int friendId = tox_get_friend_number ( tox , ( uint8_t * ) cid . data ( ) ) ;
if ( friendId < 0 )
{
qWarning ( ) < < " Core::getPeerName: No such peer " + id . toString ( ) ;
return name ;
}
2014-11-03 06:37:54 +08:00
const int nameSize = tox_get_name_size ( tox , friendId ) ;
if ( nameSize < = 0 )
2014-11-03 01:36:27 +08:00
{
2014-11-11 22:19:14 +08:00
//qDebug() << "Core::getPeerName: Can't get name of friend "+QString().setNum(friendId)+" ("+id.toString()+")";
2014-11-03 01:36:27 +08:00
return name ;
}
2014-11-03 06:37:54 +08:00
uint8_t * cname = new uint8_t [ nameSize < TOX_MAX_NAME_LENGTH ? TOX_MAX_NAME_LENGTH : nameSize ] ;
if ( tox_get_name ( tox , friendId , cname ) ! = nameSize )
{
qWarning ( ) < < " Core::getPeerName: Can't get name of friend " + QString ( ) . setNum ( friendId ) + " ( " + id . toString ( ) + " ) " ;
delete [ ] cname ;
return name ;
}
2014-11-03 01:36:27 +08:00
name = name . fromLocal8Bit ( ( char * ) cname , nameSize ) ;
2014-11-03 06:37:54 +08:00
delete [ ] cname ;
2014-11-03 01:36:27 +08:00
return name ;
}
2014-11-06 22:12:10 +08:00
bool Core : : isReady ( )
{
return ready ;
}
2014-11-16 00:10:04 +08:00
void Core : : setNospam ( uint32_t nospam )
{
uint8_t * nspm = reinterpret_cast < uint8_t * > ( & nospam ) ;
std : : reverse ( nspm , nspm + 4 ) ;
tox_set_nospam ( tox , nospam ) ;
}
2014-11-16 23:41:30 +08:00
2014-11-17 02:04:45 +08:00
void Core : : resetCallSources ( )
2014-11-16 23:41:30 +08:00
{
2014-11-16 23:51:33 +08:00
for ( ToxGroupCall & call : groupCalls )
call . alSources . clear ( ) ;
2014-11-17 02:04:45 +08:00
for ( ToxCall & call : calls )
2014-11-16 23:41:30 +08:00
{
2014-11-17 02:04:45 +08:00
if ( call . active & & call . alSource )
2014-11-16 23:41:30 +08:00
{
2014-11-17 02:04:45 +08:00
ALuint tmp = call . alSource ;
call . alSource = 0 ;
alDeleteSources ( 1 , & tmp ) ;
2014-11-16 23:41:30 +08:00
2014-11-17 02:04:45 +08:00
alGenSources ( 1 , & call . alSource ) ;
}
2014-11-16 23:41:30 +08:00
}
}