diff options
Diffstat (limited to 'pica-client')
| -rw-r--r-- | pica-client/askpassword.cpp | 73 | ||||
| -rw-r--r-- | pica-client/askpassword.h | 8 | ||||
| -rw-r--r-- | pica-client/dialogs/settingsdialog.cpp | 168 | ||||
| -rw-r--r-- | pica-client/dialogs/settingsdialog.h | 44 | ||||
| -rw-r--r-- | pica-client/filetransfercontroller.cpp | 8 | ||||
| -rw-r--r-- | pica-client/main.cpp | 41 | ||||
| -rw-r--r-- | pica-client/mainwindow.cpp | 9 | ||||
| -rw-r--r-- | pica-client/mainwindow.h | 3 | ||||
| -rw-r--r-- | pica-client/msguirouter.cpp | 6 | ||||
| -rw-r--r-- | pica-client/msguirouter.h | 2 | ||||
| -rw-r--r-- | pica-client/nodethread.cpp | 11 | ||||
| -rw-r--r-- | pica-client/nodethread.h | 8 | ||||
| -rw-r--r-- | pica-client/pica-client.pro | 10 | ||||
| -rw-r--r-- | pica-client/picaactioncenter.cpp | 17 | ||||
| -rw-r--r-- | pica-client/picaactioncenter.h | 3 | ||||
| -rw-r--r-- | pica-client/settings.cpp | 69 | ||||
| -rw-r--r-- | pica-client/settings.h | 24 | ||||
| -rw-r--r-- | pica-client/skynet.cpp | 446 | ||||
| -rw-r--r-- | pica-client/skynet.h | 47 |
19 files changed, 811 insertions, 186 deletions
diff --git a/pica-client/askpassword.cpp b/pica-client/askpassword.cpp index a171217..70f8644 100644 --- a/pica-client/askpassword.cpp +++ b/pica-client/askpassword.cpp @@ -2,38 +2,54 @@ #include "globals.h" #include <string.h> #include <QInputDialog> +#include <QThread> #include "accounts.h" QMutex AskPassword::passwd_mutex; -QMap<QByteArray,QString> AskPassword::idpasswd; +char AskPassword::current_password[256]; +int AskPassword::is_invalid = 0; +int AskPassword::is_cancelled = 0; +int AskPassword::is_set = 0; AskPassword::AskPassword(QObject *parent) : QObject(parent) { - connect(this,SIGNAL(password_requested()),this,SLOT(password_dialog()),Qt::BlockingQueuedConnection); + connect(this,SIGNAL(password_requested()),this,SLOT(password_dialog()), Qt::BlockingQueuedConnection); +} + +AskPassword::~AskPassword() +{ + memset(current_password, 0, sizeof(current_password)); } int AskPassword::ask_password_cb(char *buf, int size, int rwflag, void *userdata) { - QString pswd; - QByteArray id = QByteArray((const char*) userdata, PICA_ID_SIZE); + //QString pswd; + //QByteArray id = QByteArray((const char*) userdata, PICA_ID_SIZE); + + if (is_cancelled) + return 0; passwd_mutex.lock(); - if (idpasswd.contains(id)) + if (!is_set || is_invalid) { - pswd = idpasswd[id]; + if (askpassword->thread() != QThread::currentThread()) + askpassword->emit_sig(); + else + askpassword->password_dialog(); } - else + + if (is_set) { - askpassword->emit_sig(); - pswd = idpasswd[id]; + strncpy(buf, current_password, size); + buf[size - 1] = 0; } + passwd_mutex.unlock(); - strncpy(buf, pswd.toUtf8().constData(), size); - buf[size - 1] = 0; - return(strlen(buf)); + + return is_set ? (strlen(buf)) : 0; } void AskPassword::emit_sig() @@ -41,15 +57,42 @@ void AskPassword::emit_sig() emit password_requested(); } +void AskPassword::clear() +{ + passwd_mutex.lock(); + is_invalid = 0; + is_set = 0; + is_cancelled = 0; + memset(current_password, 0, sizeof(current_password)); + passwd_mutex.unlock(); + +} + +void AskPassword::setInvalidPassword() +{ + passwd_mutex.lock(); + is_invalid = 1; + memset(current_password, 0, sizeof(current_password)); + passwd_mutex.unlock(); +} + void AskPassword::password_dialog() { - bool ok; - QString title = QObject::tr("Enter private key passphrase"); + bool ok = false; + QString title = is_invalid ? QObject::tr("Invalid passphrase, try again") : QObject::tr("Enter private key passphrase"); QString text = QObject::tr(QString("Passphrase for account %1 \n (%2)") .arg(Accounts::GetCurrentAccount().name) .arg(Accounts::GetCurrentAccount().id.toBase64().constData()).toUtf8().constData()); QString psw = QInputDialog::getText((QWidget*)mainwindow,title,text,QLineEdit::Password,QString(),&ok); + if (ok) - idpasswd[Accounts::GetCurrentAccount().id] = psw; + { + strncpy(current_password, psw.toUtf8().constData(), sizeof(current_password)); + current_password[sizeof(current_password) - 1] = 0; + is_set = 1; + is_invalid = 0; + } + else + is_cancelled = 1; } diff --git a/pica-client/askpassword.h b/pica-client/askpassword.h index 6abc009..9deb691 100644 --- a/pica-client/askpassword.h +++ b/pica-client/askpassword.h @@ -10,12 +10,18 @@ class AskPassword : public QObject Q_OBJECT public: explicit AskPassword(QObject *parent = 0); + ~AskPassword(); static int ask_password_cb(char *buf, int size, int rwflag, void *userdata); + static void setInvalidPassword(); + static void clear(); private: void emit_sig(); - static QMap<QByteArray,QString> idpasswd; static QMutex passwd_mutex; + static char current_password[256]; + static int is_cancelled; + static int is_invalid; + static int is_set; signals: void password_requested(); diff --git a/pica-client/dialogs/settingsdialog.cpp b/pica-client/dialogs/settingsdialog.cpp new file mode 100644 index 0000000..852cc95 --- /dev/null +++ b/pica-client/dialogs/settingsdialog.cpp @@ -0,0 +1,168 @@ +#include "settingsdialog.h" +#include "../settings.h" +#include "../globals.h" + +#include <QGroupBox> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QLabel> +#include <QVariant> +#include <QListWidget> +#include <QNetworkInterface> +#include <QHostAddress> +#include <QTabWidget> + +SettingsDialog::SettingsDialog(QWidget *parent) : + QDialog(parent) +{ + QVBoxLayout *settingsLayout = new QVBoxLayout(); + + QTabWidget *tabW = new QTabWidget(this); + QWidget* directc2ctab = new QWidget(0); + QWidget* soundstab = new QWidget(0); + + //QGroupBox *groupBox = new QGroupBox(tr("Direct Connections"), directc2ctab); + QVBoxLayout *directc2cLayout = new QVBoxLayout(); + + rbDisableDirectConns = new QRadioButton(tr("Disable direct connections"), this); + rbEnableOutgoingConns = new QRadioButton(tr("Connect to the remote peer directly if possible"), this); + rbEnableIncomingConns = new QRadioButton(tr("Enable incoming direct connections"), this); + + rbEnableIncomingConns->setChecked(true); + connect(rbEnableIncomingConns, SIGNAL(toggled(bool)), this, SLOT(toggleIncomingConnections(bool))); + + QLabel *lbAddr = new QLabel(tr("Public address for incoming connections"), this); + addr = new QComboBox(this); + QLabel *lbPubPort = new QLabel(tr("External TCP port for incoming connections"), this); + publicPort = new QSpinBox(this); + QLabel *lbLocPort = new QLabel(tr("Local TCP port for incoming connections"), this); + localPort = new QSpinBox(this); + + addr->setEditable(true); + + publicPort->setRange(1, 65535); + localPort->setRange(1, 65535); + + publicPort->setValue(2298); + localPort->setValue(2298); + + QList<QHostAddress> hostIfAddrs = QNetworkInterface::allAddresses(); + QHostAddress ifAddr; + + foreach (ifAddr, hostIfAddrs) + if (ifAddr.protocol() == QAbstractSocket::IPv4Protocol) + addr->addItem(ifAddr.toString()); + + + directc2cLayout->addWidget(rbDisableDirectConns); + directc2cLayout->addWidget(rbEnableOutgoingConns); + directc2cLayout->addWidget(rbEnableIncomingConns); + directc2cLayout->addWidget(lbAddr); + directc2cLayout->addWidget(addr); + directc2cLayout->addWidget(lbPubPort); + directc2cLayout->addWidget(publicPort); + directc2cLayout->addWidget(lbLocPort); + directc2cLayout->addWidget(localPort); + directc2cLayout->addStretch(1); + + //groupBox->setLayout(directc2cLayout); + directc2ctab->setLayout(directc2cLayout); + + //settingsLayout->addWidget(groupBox); + tabW->addTab(directc2ctab, tr("Direct Connections")); + tabW->addTab(soundstab, tr("Sounds")); + settingsLayout->addWidget(tabW); + + QHBoxLayout *buttonsLayout = new QHBoxLayout; + + btOk = new QPushButton(tr("&OK"), this); + btCancel = new QPushButton(tr("Cancel"), this); + + buttonsLayout->addStretch(1); + buttonsLayout->addWidget(btOk); + buttonsLayout->addWidget(btCancel); + + settingsLayout->addLayout(buttonsLayout); + + setLayout(settingsLayout); + + connect(btOk, SIGNAL(clicked()), this, SLOT(OK())); + connect(btCancel, SIGNAL(clicked()), this, SLOT(Cancel())); + + loadSettings(); + + setWindowTitle(tr("Pica Pica Messenger Settings")); +} + +void SettingsDialog::toggleIncomingConnections(bool checked) +{ + addr->setEnabled(checked); + publicPort->setEnabled(checked); + localPort->setEnabled(checked); +} + +void SettingsDialog::OK() +{ + storeSettings(); + done(1); +} + +void SettingsDialog::Cancel() +{ + done(0); +} + +void SettingsDialog::loadSettings() +{ + Settings st(config_dbname); + + //Direct c2c connections + int c2c_state; + + c2c_state = st.loadValue("direct_c2c.state", 1).toInt(); + + switch (c2c_state) + { + case 0: + rbDisableDirectConns->setChecked(true); + break; + + case 1: + rbEnableOutgoingConns->setChecked(true); + break; + + case 2: + rbEnableIncomingConns->setChecked(true); + break; + + default: + break; + } + + addr->lineEdit()->setText(st.loadValue("direct_c2c.public_addr", "0.0.0.0").toString()); + + publicPort->setValue(st.loadValue("direct_c2c.public_port", 2298).toInt()); + localPort->setValue(st.loadValue("direct_c2c.local_port", 2298).toInt()); + +} + +void SettingsDialog::storeSettings() +{ + Settings st(config_dbname); + + //Direct c2c connections + int c2c_state; + + if (rbDisableDirectConns->isChecked()) + c2c_state = 0; + else if (rbEnableOutgoingConns->isChecked()) + c2c_state = 1; + else if (rbEnableIncomingConns->isChecked()) + c2c_state = 2; + + st.storeValue("direct_c2c.state", QString::number(c2c_state)); + + st.storeValue("direct_c2c.public_addr", addr->lineEdit()->text()); + st.storeValue("direct_c2c.public_port", QString::number(publicPort->value())); + st.storeValue("direct_c2c.local_port", QString::number(localPort->value())); +} diff --git a/pica-client/dialogs/settingsdialog.h b/pica-client/dialogs/settingsdialog.h new file mode 100644 index 0000000..9b11630 --- /dev/null +++ b/pica-client/dialogs/settingsdialog.h @@ -0,0 +1,44 @@ +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include <QDialog> +#include <QLineEdit> +#include <QPushButton> +#include <QSpinBox> +#include <QRadioButton> +#include <QComboBox> + +class SettingsDialog : public QDialog +{ + Q_OBJECT +public: + explicit SettingsDialog(QWidget *parent = 0); + +signals: + +public slots: +private slots: + +private: + QRadioButton *rbDisableDirectConns; + QRadioButton *rbEnableOutgoingConns; + QRadioButton *rbEnableIncomingConns; + + QComboBox *addr; + QSpinBox *publicPort; + QSpinBox *localPort; + + QPushButton *btOk; + QPushButton *btCancel; + + void loadSettings(); + void storeSettings(); + +private slots: + void OK(); + void Cancel(); + void toggleIncomingConnections(bool checked); + +}; + +#endif // SETTINGSDIALOG_H diff --git a/pica-client/filetransfercontroller.cpp b/pica-client/filetransfercontroller.cpp index 9f07a38..44dba15 100644 --- a/pica-client/filetransfercontroller.cpp +++ b/pica-client/filetransfercontroller.cpp @@ -19,7 +19,7 @@ FileTransferController::FileTransferController(QObject *parent) : connect(skynet, SIGNAL(OutgoingFileRequestDenied(QByteArray)), this, SLOT(file_denied_by_peer(QByteArray))); - connect(skynet, SIGNAL(ChannelClosed(QByteArray)), this, SLOT(file_peer_disconnected(QByteArray))); + connect(skynet, SIGNAL(c2cClosed(QByteArray)), this, SLOT(file_peer_disconnected(QByteArray))); } void FileTransferController::file_peer_disconnected(QByteArray peer_id) @@ -217,7 +217,7 @@ void FileTransferController::send_file(QByteArray peer_id) if (ftdialogs_out.contains(peer_id)) { - msguirouter->notification(tr("There is already file transfer in progress. Wait until it is finished.")); + msguirouter->notification(tr("There is already file transfer in progress. Wait until it is finished."), true); return; } @@ -230,13 +230,13 @@ void FileTransferController::send_file(QByteArray peer_id) if (!fi.exists()) { - msguirouter->notification(tr("File \"%1\" does not exist.").arg(filepath)); + msguirouter->notification(tr("File \"%1\" does not exist.").arg(filepath), true); return; } if (fi.size() == 0) { - msguirouter->notification(tr("Cannot send empty file.")); + msguirouter->notification(tr("Cannot send empty file."), true); } skynet->SendFile(peer_id, filepath); diff --git a/pica-client/main.cpp b/pica-client/main.cpp index 7df81ce..1441b5c 100644 --- a/pica-client/main.cpp +++ b/pica-client/main.cpp @@ -14,6 +14,8 @@ #include <QIcon> #include "../PICA_client.h" #include "dhparam.h" +#include "settings.h" +#include "dialogs/settingsdialog.h" //globals QString config_dir; @@ -135,7 +137,18 @@ static bool create_database() if (query.lastError().isValid()) goto showerror; - query.exec("insert into schema_version values (2, strftime('%s','now'));"); //current schema version. update when needed + query.exec("create table settings \ + ( \ + name varchar(255) not null, \ + value varchar(255) not null, \ + constraint pk primary key (name) on conflict replace \ + );" + ); + + if (query.lastError().isValid()) + goto showerror; + + query.exec("insert into schema_version values (3, strftime('%s','now'));"); //current schema version. update when needed if (query.lastError().isValid()) showerror: @@ -363,6 +376,23 @@ static bool update_database() schema_ver = 2; } + if (schema_ver == 2) + { + query.exec("create table settings \ + ( \ + name varchar(255) not null, \ + value varchar(255) not null, \ + constraint pk primary key (name) on conflict replace \ + );" + ); + + if (query.lastError().isValid()) + goto showerror; + + query.exec("insert into schema_version values (3, strftime('%s','now'));"); + schema_ver = 3; + } + if (query.lastError().isValid()) showerror: { @@ -465,6 +495,15 @@ int main(int argc, char *argv[]) picapica_ico_fly = QIcon("share\\picapica-icon-fly.png"); #endif + Settings st(config_dbname); + + if (st.isEmpty()) //show settings dialog on first start + { + SettingsDialog sd; + + sd.exec(); + } + PicaActionCenter ac; action_center = ∾ diff --git a/pica-client/mainwindow.cpp b/pica-client/mainwindow.cpp index c440e20..8f4702f 100644 --- a/pica-client/mainwindow.cpp +++ b/pica-client/mainwindow.cpp @@ -111,6 +111,9 @@ void MainWindow::createMenus() nodesMenu=menuBar()->addMenu(tr("&Nodes")); + settingsMenu = menuBar()->addMenu(tr("&Settings")); + settingsMenu->addAction(action_center->SettingsAct()); + helpMenu=menuBar()->addMenu(tr("&Help")); helpMenu->addAction(action_center->AboutAct()); @@ -138,11 +141,13 @@ void MainWindow::showhide_click() hide_notifications(); } -void MainWindow::AddNotification(QString &text) +void MainWindow::AddNotification(QString &text, bool is_critical) { notifications->addItem(text); notifications->item(notifications->count() -1) ->setForeground(QBrush(QColor(230, 10, 10, 196))); - show_notifications(); + + if (is_critical) + show_notifications(); } diff --git a/pica-client/mainwindow.h b/pica-client/mainwindow.h index ba73c9a..b61f31a 100644 --- a/pica-client/mainwindow.h +++ b/pica-client/mainwindow.h @@ -23,7 +23,7 @@ public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); - void AddNotification(QString &text); + void AddNotification(QString &text, bool is_critical); protected: private: @@ -39,6 +39,7 @@ private: QMenu *helpMenu; QMenu *nodesMenu; QMenu *accountMenu; + QMenu *settingsMenu; bool status_change_disable_flag; void SetStatus(bool connected); diff --git a/pica-client/msguirouter.cpp b/pica-client/msguirouter.cpp index 3264490..84bbf56 100644 --- a/pica-client/msguirouter.cpp +++ b/pica-client/msguirouter.cpp @@ -23,7 +23,7 @@ MsgUIRouter::MsgUIRouter(QObject *parent) : connect(skynet, SIGNAL(UnableToDeliver(QByteArray,QString)), this, SLOT(delivery_failed(QByteArray,QString))); connect(skynet, SIGNAL(Delivered(QByteArray)), this, SLOT(delivered(QByteArray))); connect(skynet, SIGNAL(CertificateForged(QByteArray,QString,QString)), this, SLOT(scary_cert_message(QByteArray,QString,QString))); - connect(skynet, SIGNAL(ErrMsgFromNode(QString)), this, SLOT(notification(QString))); + connect(skynet, SIGNAL(StatusMsg(QString, bool)), this, SLOT(notification(QString, bool))); connect(systray, SIGNAL(doubleclicked()), this, SLOT(trayicon_dclick())); } @@ -166,8 +166,8 @@ void MsgUIRouter::scary_cert_message(QByteArray peer_id, QString received_cert, fcd.exec(); } -void MsgUIRouter::notification(QString text) +void MsgUIRouter::notification(QString text, bool is_critical) { if (mainwindow) - mainwindow->AddNotification(text); + mainwindow->AddNotification(text, is_critical); } diff --git a/pica-client/msguirouter.h b/pica-client/msguirouter.h index 9fb404c..aefef2c 100644 --- a/pica-client/msguirouter.h +++ b/pica-client/msguirouter.h @@ -27,7 +27,7 @@ public slots: void delivered(QByteArray to); void scary_cert_message(QByteArray peer_id, QString received_cert, QString stored_cert); - void notification(QString text); + void notification(QString text, bool is_critical); void trayicon_dclick(); private: diff --git a/pica-client/nodethread.cpp b/pica-client/nodethread.cpp index 393c156..ee6504f 100644 --- a/pica-client/nodethread.cpp +++ b/pica-client/nodethread.cpp @@ -6,7 +6,7 @@ QMutex NodeThread::finished_mutex; -NodeThread::NodeThread(Nodes::NodeRecord &addr, bool *completed, Accounts::AccountRecord &acc, PICA_conninfo **pica_conn, QMutex *wm) : +NodeThread::NodeThread(Nodes::NodeRecord &addr, bool *completed, PICA_acc *acc, PICA_c2n **pica_conn, QMutex *wm) : QThread(0) { node_addr = addr; @@ -23,14 +23,15 @@ void NodeThread::run() int ret; exit = 0; - ret = PICA_new_connection(node_addr.address.toUtf8().constData(), + /*ret = PICA_new_c2n(node_addr.address.toUtf8().constData(), node_addr.port, user_account.CA_file.toUtf8().constData(), user_account.cert_file.toUtf8().constData(), user_account.pkey_file.toUtf8().constData(), DHParam::GetDHParamFilename().toUtf8().constData(), AskPassword::ask_password_cb, - &ci); + &ci);*/ + ret = PICA_new_c2n(user_account, node_addr.address.toUtf8().constData(), node_addr.port, &ci); switch(ret) { @@ -41,7 +42,7 @@ void NodeThread::run() finished_mutex.lock(); if (*finished_flag) { - PICA_close_connection(ci); + PICA_close_c2n(ci); exit = 1; } else @@ -105,7 +106,7 @@ void NodeThread::run() while (!exit); write_mutex->lock(); - PICA_close_connection(ci); + PICA_close_c2n(ci); *connection = NULL; write_mutex->unlock(); } diff --git a/pica-client/nodethread.h b/pica-client/nodethread.h index 79de4d0..8974255 100644 --- a/pica-client/nodethread.h +++ b/pica-client/nodethread.h @@ -12,7 +12,7 @@ class NodeThread : public QThread { Q_OBJECT public: - explicit NodeThread( Nodes::NodeRecord &addr, bool *completed,Accounts::AccountRecord &acc,struct PICA_conninfo **pica_conn, QMutex *wm); + explicit NodeThread( Nodes::NodeRecord &addr, bool *completed, PICA_acc *acc,struct PICA_c2n **pica_conn, QMutex *wm); void CloseThread(); private: void run(); @@ -22,9 +22,9 @@ private: bool *finished_flag; Nodes::NodeRecord node_addr; - struct PICA_conninfo *ci; - Accounts::AccountRecord user_account; - struct PICA_conninfo **connection; + struct PICA_c2n *ci; + struct PICA_acc *user_account; + struct PICA_c2n **connection; int exit; diff --git a/pica-client/pica-client.pro b/pica-client/pica-client.pro index 70c1222..ef9f9fd 100644 --- a/pica-client/pica-client.pro +++ b/pica-client/pica-client.pro @@ -22,7 +22,6 @@ SOURCES += main.cpp\ accountswindow.cpp \ accounts.cpp \ dialogs/addaccountdialog.cpp \ - nodethread.cpp \ askpassword.cpp \ msguirouter.cpp \ picasystray.cpp \ @@ -37,7 +36,9 @@ SOURCES += main.cpp\ dialogs/showpicaiddialog.cpp \ dialogs/filetransferdialog.cpp \ filetransfercontroller.cpp \ - sound.cpp + sound.cpp \ + dialogs/settingsdialog.cpp \ + settings.cpp HEADERS += mainwindow.h \ chatwindow.h \ @@ -51,7 +52,6 @@ HEADERS += mainwindow.h \ accountswindow.h \ accounts.h \ dialogs/addaccountdialog.h \ - nodethread.h \ askpassword.h \ msguirouter.h \ picasystray.h \ @@ -68,7 +68,9 @@ HEADERS += mainwindow.h \ dialogs/showpicaiddialog.h \ dialogs/filetransferdialog.h \ filetransfercontroller.h \ - sound.h + sound.h \ + dialogs/settingsdialog.h \ + settings.h DEFINES = PICA_MULTITHREADED diff --git a/pica-client/picaactioncenter.cpp b/pica-client/picaactioncenter.cpp index bbd19ab..9303ca6 100644 --- a/pica-client/picaactioncenter.cpp +++ b/pica-client/picaactioncenter.cpp @@ -7,6 +7,7 @@ #include "accounts.h" #include "dialogs/showpicaiddialog.h" #include "sound.h" +#include "dialogs/settingsdialog.h" #include <QMessageBox> @@ -27,6 +28,9 @@ PicaActionCenter::PicaActionCenter(QObject *parent) : muteSoundsAct = new QAction(tr("&Mute Sounds"), this); muteSoundsAct->setCheckable(true); connect(muteSoundsAct, SIGNAL(triggered(bool)), this, SLOT(muteSounds(bool))); + + settingsAct = new QAction(tr("&Configure Messenger..."), this); + connect(settingsAct, SIGNAL(triggered(bool)), this, SLOT(showsettings())); } void PicaActionCenter::about() @@ -40,9 +44,10 @@ void PicaActionCenter::about() mbx.setWindowIcon(picapica_ico_sit); mbx.setIconPixmap(picapica_ico_sit.pixmap(32)); mbx.setTextFormat(Qt::RichText); - mbx.setText(tr("<b>Pica Pica Messenger "VERSION_STRING"<br>(c) 2012 - 2016 Anton Sviridenko</b><br>\ -<a href=https://picapica.im>https://picapica.im</a><br><br>Contributors:<br>Daniil Ustinov - bugfixes<br>EXL - bugfixes<br><br>\ -protocol version " PICA_PROTO_VER_STRING)); + mbx.setText(tr("<b>Pica Pica Messenger "VERSION_STRING"<br>(c) 2012 - 2017 Anton Sviridenko</b><br>\ +<a href=http://picapica.im>http://picapica.im</a><br><br>Contributors:<br>Daniil Ustinov - bugfixes<br>EXL - bugfixes<br><br>\ +protocol version " PICA_PROTO_VER_STRING "<br>" + "client protocol version " PICA_PROTO_CLIENT_VER_STRING)); mbx.exec(); } @@ -55,6 +60,12 @@ void PicaActionCenter::exit() QApplication::instance()->quit(); } +void PicaActionCenter::showsettings() +{ + SettingsDialog sd; + sd.exec(); +} + void PicaActionCenter::showmyid() { ShowPicaIdDialog d(Accounts::GetCurrentAccount().name, Accounts::GetCurrentAccount().id, tr("My Current Account")); diff --git a/pica-client/picaactioncenter.h b/pica-client/picaactioncenter.h index 6361d01..7fa98c4 100644 --- a/pica-client/picaactioncenter.h +++ b/pica-client/picaactioncenter.h @@ -14,12 +14,14 @@ public: QAction *ExitAct() {return exitAct;}; QAction *ShowMyIDAct() {return showmyidAct;}; QAction *MuteSoundsAct() {return muteSoundsAct;}; + QAction *SettingsAct() {return settingsAct; }; private: QAction *aboutAct; QAction *exitAct; QAction *showmyidAct; QAction *muteSoundsAct; + QAction *settingsAct; signals: @@ -29,6 +31,7 @@ private slots: void exit(); void showmyid(); void muteSounds(bool yes); + void showsettings(); }; #endif // PICAACTIONCENTER_H diff --git a/pica-client/settings.cpp b/pica-client/settings.cpp new file mode 100644 index 0000000..4b5485d --- /dev/null +++ b/pica-client/settings.cpp @@ -0,0 +1,69 @@ +#include "settings.h" + +Settings::Settings(QString storage) +{ + dbconn=QSqlDatabase::addDatabase("QSQLITE"); + dbconn.setDatabaseName(storage); + + if (!dbconn.open()) + { + lasterr=dbconn.lastError(); + return; + } + +} + +QString Settings::GetLastError() +{ + return lasterr.text(); +} + +bool Settings::isEmpty() +{ + QSqlQuery query; + + query.exec("select count(*) from settings"); + + lasterr = query.lastError(); + + query.next(); + + if (query.isValid() && query.value(0).toInt() == 0) + { + return true; + } + + return false; +} + +QVariant Settings::loadValue(QString name, QVariant defval) +{ + QSqlQuery query; + + query.prepare("select value from settings where name = :name"); + query.bindValue(":name", name); + query.exec(); + + lasterr = query.lastError(); + + query.next(); + + if (!query.isValid()) + { + return defval; + } + + return query.value(0); +} + +void Settings::storeValue(QString name, QString val) +{ + QSqlQuery query; + + query.prepare("insert into settings (name, value) values (:name, :val)"); + query.bindValue(":addr", name); + query.bindValue(":val", val); + query.exec(); + + lasterr = query.lastError(); +} diff --git a/pica-client/settings.h b/pica-client/settings.h new file mode 100644 index 0000000..9476ab5 --- /dev/null +++ b/pica-client/settings.h @@ -0,0 +1,24 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include <QtSql> +#include <QSqlDatabase> +#include <QVariant> + +class Settings +{ +public: + Settings(QString storage); + + QVariant loadValue(QString name, QVariant defval); + void storeValue(QString name, QString val); + bool isEmpty(); + + QString GetLastError(); + +private: + QSqlDatabase dbconn; + QSqlError lasterr; +}; + +#endif // SETTINGS_H diff --git a/pica-client/skynet.cpp b/pica-client/skynet.cpp index 63da308..a016b48 100644 --- a/pica-client/skynet.cpp +++ b/pica-client/skynet.cpp @@ -8,21 +8,23 @@ //#include "dialogs/forgedcertdialog.h" #include <QDebug> #include "history.h" +#include "dhparam.h" +#include "askpassword.h" +#include "settings.h" SkyNet::SkyNet() : nodes(config_dbname), QObject(0) { self_aware = false; - reconnect_enabled = false; PICA_client_callbacks cbs = { newmsg_cb, msgok_cb, - channel_established_cb, - channel_failed, + c2c_established_cb, + c2c_failed, accept_cb, notfound_cb, - channel_closed_cb, + c2c_closed_cb, nodelist_cb, peer_cert_verify_cb, accept_file_cb, @@ -30,81 +32,144 @@ PICA_client_callbacks cbs = { denied_file_cb, file_progress, file_control, - file_finished + file_finished, + c2n_established_cb, + c2n_failed_cb, + c2n_closed_cb, + listener_error_cb }; PICA_client_init(&cbs); -nodelink = NULL; +this->active_nodelink = NULL; +this->acc = NULL; +this->listener = NULL; connect(this, SIGNAL(PeerCertificateReceived(QByteArray,QString,bool*)), this, SLOT(verify_peer_cert(QByteArray,QString,bool*)),Qt::DirectConnection); -timer_id = startTimer(10000); +event_loop_timer_id = startTimer(0); + } -void SkyNet::nodethread_finished() +void SkyNet::nodelink_activated(PICA_c2n *c2n) { -//удалить здесь завершившийся поток - for (int i=0;i<threads.count();i++) - { - if (threads[i]->isFinished()) - { - delete threads.takeAt(i); - break; - } - } + for (int i = 0; i < connecting_nodes.size(); i++) + { + if (connecting_nodes[i].first == c2n) + { + node_status_changed(connecting_nodes[i].second, true); + connecting_nodes.removeAt(i); + break; + } + } - if (threads.count() == 0) - { - self_aware = false; - emit LostSelfAwareness(); - } -} + if (self_aware) + { + PICA_close_c2n(c2n); + } + else + { + self_aware = true; + active_nodelink = c2n; -void SkyNet::nodethread_connected(QString addr, quint16 port, NodeThread *thread) -{ - if (self_aware) - { - emit BecameSelfAware(); + emit BecameSelfAware(); + // + //restore old peer connections, if any + QList<QByteArray> c2c_peer_ids; - //restore old peer connections, if any - QList<QByteArray> c2c_peer_ids; + //load undelivered messages from history + if (msgqueues.isEmpty()) + { + History h(config_dbname, Accounts::GetCurrentAccount().id); - //load undelivered messages from history - if (msgqueues.isEmpty()) - { - History h(config_dbname, Accounts::GetCurrentAccount().id); + msgqueues = h.GetUndeliveredMessages(); + } - msgqueues = h.GetUndeliveredMessages(); - } + //load file transfers to be completed + // sndfilequeues = ... - //load file transfers to be completed - // sndfilequeues = ... + QMap<QByteArray, QList<QString> > queues = msgqueues; - QMap<QByteArray, QList<QString> > queues = msgqueues; + queues.unite(sndfilequeues); - queues.unite(sndfilequeues); + c2c_peer_ids = queues.uniqueKeys(); - c2c_peer_ids = queues.uniqueKeys(); + for (int i = 0; i < c2c_peer_ids.size(); i++) + { + int ret; + struct PICA_c2c *chan = NULL; - for (int i = 0; i < c2c_peer_ids.size(); i++) - { - int ret; - write_mutex.lock(); - struct PICA_chaninfo *chan = NULL; + ret = PICA_new_c2c(active_nodelink, (const unsigned char*)c2c_peer_ids[i].constData(), NULL, &chan); - ret = PICA_create_channel(nodelink, (const unsigned char*)c2c_peer_ids[i].constData(), &chan); + qDebug()<<"restoring c2c to "<<c2c_peer_ids[i]<<" ret ="<<ret<<"\n"; + } - qDebug()<<"restoring channel to "<<c2c_peer_ids[i]<<" ret ="<<ret<<"\n"; - write_mutex.unlock(); - } + //start timer + retry_timer_id = startTimer(10000); + // + } - } + +} + +void SkyNet::nodelink_closed(PICA_c2n *c2n, int error) +{ + if (self_aware && c2n == active_nodelink) + { + active_nodelink = NULL; + emit LostSelfAwareness(); + } + else + { + for (int i = 0; i < connecting_nodes.size(); i++) + { + if (connecting_nodes[i].first == c2n) + { + connecting_nodes.removeAt(i); + break; + } + } + } +} + +void SkyNet::nodelink_failed(PICA_c2n *c2n, int error) +{ + for (int i = 0; i < connecting_nodes.size(); i++) + { + if (connecting_nodes[i].first == c2n) + { + switch(error) + { + case PICA_ERRPROTONEW: + + emit StatusMsg(QString("Node %1:%2 has newer protocol version. Please check if update for pica-client is available") + .arg(connecting_nodes[i].second.address) + .arg(connecting_nodes[i].second.port), + true); + break; + + case PICA_ERRPROTOOLD: + + emit StatusMsg(QString("Node %1:%2 has older protocol. Disconnected.") + .arg(connecting_nodes[i].second.address) + .arg(connecting_nodes[i].second.port), + false); + break; + } + + node_status_changed(connecting_nodes[i].second, false); + connecting_nodes.removeAt(i); + break; + } + } + if (connecting_nodes.empty()) + emit LostSelfAwareness(); } -void SkyNet::node_status_changed(QString addr, quint16 port, bool alive) + + +void SkyNet::node_status_changed(Nodes::NodeRecord nr, bool alive) { - Nodes::NodeRecord nr = {addr, port}; nodes.UpdateStatus(nr, alive); } @@ -166,70 +231,184 @@ void SkyNet::verify_peer_cert(QByteArray peer_id, QString cert_pem, bool *verifi void SkyNet::timerEvent(QTimerEvent *e) { + if (e->timerId() == event_loop_timer_id) + { + if (connecting_nodes.size() > 0 || self_aware) + { + int ret; + QVector<struct PICA_c2n *> nodelinks; + + nodelinks.reserve(connecting_nodes.size() + 1); + + for (int i = 0; i < connecting_nodes.size(); i++) + nodelinks.append(connecting_nodes[i].first); + + if (self_aware) + nodelinks.append(active_nodelink); + + nodelinks.append(NULL); + + ret = PICA_event_loop(nodelinks.data(), 1); + + if (ret != PICA_OK) + emit StatusMsg("event loop error!", true);//show some error message + } + + return; + } + + if (self_aware) { - if (write_mutex.tryLock(10)) - { - QMap<QByteArray, QList<QString> > queues = msgqueues; - queues.unite(sndfilequeues); + QMap<QByteArray, QList<QString> > queues = msgqueues; + queues.unite(sndfilequeues); - QList<QByteArray> c2c_peer_ids = queues.uniqueKeys(); + QList<QByteArray> c2c_peer_ids = queues.uniqueKeys(); - c2c_peer_ids = filter_existing_chans(c2c_peer_ids); + c2c_peer_ids = filter_existing_chans(c2c_peer_ids); - for (int i = 0; i < c2c_peer_ids.size(); i++) - { - int ret; + for (int i = 0; i < c2c_peer_ids.size(); i++) + { + int ret; - struct PICA_chaninfo *chan = NULL; + struct PICA_c2c *chan = NULL; - ret = PICA_create_channel(nodelink, (const unsigned char*)c2c_peer_ids[i].constData(), &chan); + ret = PICA_new_c2c(active_nodelink, (const unsigned char*)c2c_peer_ids[i].constData(), NULL, &chan); - qDebug()<<"restoring channel to "<<c2c_peer_ids[i]<<" ret ="<<ret<<" in timer event\n"; + qDebug()<<"restoring c2c to "<<c2c_peer_ids[i]<<" ret ="<<ret<<" in timer event\n"; + + } - } - write_mutex.unlock(); - } } -else if (threads.count() == 0 && reconnect_enabled) +else { + killTimer(e->timerId()); Accounts::AccountRecord acc = this->CurrentAccount(); Join(acc); } } +bool SkyNet::open_account() +{ + int ret; + + AskPassword::clear(); + do + { + ret = PICA_open_acc(skynet_account.cert_file.toUtf8().constData(), + skynet_account.pkey_file.toUtf8().constData(), + DHParam::GetDHParamFilename().toUtf8().constData(), + AskPassword::ask_password_cb, + &acc); + + if (ret == PICA_ERRINVPKEYPASSPHRASE) + AskPassword::setInvalidPassword(); + } while (ret == PICA_ERRINVPKEYPASSPHRASE); + + qDebug() << "PICA_open_acc() returned " << ret; + + if (ret != PICA_OK) + return false; + + return true; +} + void SkyNet::Join(Accounts::AccountRecord &accrec) { - QList<Nodes::NodeRecord> nodelist; + PICA_directc2c_config directc2c_cfg = PICA_DIRECTC2C_CFG_DISABLED; + Settings st(config_dbname); + skynet_account = accrec; - nodelist = nodes.GetNodes(); - reconnect_enabled = true; - if (nodelist.count()==0) + QList<Nodes::NodeRecord> noderecords = nodes.GetNodes(); + + if (!acc) + { + if (!open_account()) + return; + } + + if (noderecords.count()==0) { - status = QObject::tr("No known Pica Pica nodes"); + emit StatusMsg(QString(tr("No known Pica Pica nodes")), true); return; } + directc2c_cfg = (PICA_directc2c_config)st.loadValue("direct_c2c.state", 1).toInt(); + + if (!listener && directc2c_cfg == PICA_DIRECTC2C_CFG_ALLOWINCOMING) + { + int pub_port = st.loadValue("direct_c2c.public_port", 2298).toInt(); + int loc_port = st.loadValue("direct_c2c.local_port", 2298).toInt(); + + int ret = PICA_new_listener(acc, + st.loadValue("direct_c2c.public_addr", "0.0.0.0").toString().toAscii().constData(), + pub_port, + loc_port, &listener); + if (ret != PICA_OK) + { + emit StatusMsg(QString(tr("Failed to open port %1 for incoming direct connections")).arg(loc_port), true); + directc2c_cfg = PICA_DIRECTC2C_CFG_CONNECTONLY; + } + } + + if (!connecting_nodes.empty()) + { + for (int i = 0; i < connecting_nodes.size(); i++) + PICA_close_c2n(connecting_nodes[i].first); + + connecting_nodes.clear(); + } + + for (int i = 0; i < noderecords.size();i++) + { + int ret; + struct PICA_c2n *c2n = NULL; + + ret = PICA_new_c2n(acc, noderecords[i].address.toUtf8().constData(), noderecords[i].port, + directc2c_cfg, listener, &c2n); + + if (ret == PICA_OK) + { + connecting_nodes.append(QPair<struct PICA_c2n *, Nodes::NodeRecord>(c2n, noderecords[i])); + } + else + { + node_status_changed(noderecords[i], false); + } + } +/* for (int i=0;i<nodelist.count() && !self_aware;i++) {//TODO FIXME сделать запуск потоков порциями, а не все сразу - threads.append(new NodeThread(nodelist[i],&self_aware,skynet_account,&nodelink, &write_mutex)); + threads.append(new NodeThread(nodelist[i],&self_aware, acc,&nodelink, &write_mutex)); connect(threads.last(), SIGNAL(finished()),this,SLOT(nodethread_finished())); connect(threads.last(), SIGNAL(NodeStatusChanged(QString,quint16,bool)), this, SLOT(node_status_changed(QString,quint16,bool))); connect(threads.last(), SIGNAL(ConnectedToNode(QString,quint16,NodeThread*)), this, SLOT(nodethread_connected(QString,quint16,NodeThread*))); connect(threads.last(), SIGNAL(ErrorMsg(QString)), this, SIGNAL(ErrMsgFromNode(QString))); - } + }*/ } void SkyNet::Exit() { - for (int i = 0; i< threads.count(); i++) - threads[i]->CloseThread(); + if (self_aware && active_nodelink) + { + PICA_close_c2n(active_nodelink); + active_nodelink = NULL; + } self_aware = false; - reconnect_enabled = false; - emit LostSelfAwareness(); + + killTimer(retry_timer_id); + + msgqueues.clear(); + + for (int i = 0; i < connecting_nodes.size(); i++) + PICA_close_c2n(connecting_nodes[i].first); + + connecting_nodes.clear(); + + emit LostSelfAwareness(); } bool SkyNet::isSelfAware() @@ -240,9 +419,9 @@ bool SkyNet::isSelfAware() void SkyNet::SendFile(QByteArray to, QString filepath) { int ret = PICA_OK; -struct PICA_chaninfo *iptr; +struct PICA_c2c *iptr; + -write_mutex.lock();//<< if ( (iptr = find_active_chan(to)) ) { @@ -253,7 +432,7 @@ if ( (iptr = find_active_chan(to)) ) //show error somewhere somehow } - write_mutex.unlock();//>> + return; } @@ -263,16 +442,16 @@ if ( (iptr = find_active_chan(to)) ) } else { - struct PICA_chaninfo *chan = NULL; + struct PICA_c2c *chan = NULL; - ret = PICA_create_channel(nodelink, (const unsigned char*)to.constData(), &chan); + ret = PICA_new_c2c(active_nodelink, (const unsigned char*)to.constData(), NULL, &chan); QList<QString> l; l.append(filepath); sndfilequeues[to] = l; } -write_mutex.unlock();//>> + if (ret!= PICA_OK) { @@ -283,9 +462,9 @@ write_mutex.unlock();//>> void SkyNet::AcceptFile(QByteArray from, QString filepath) { int ret = PICA_OK; -struct PICA_chaninfo *iptr; +struct PICA_c2c *iptr; + -write_mutex.lock();//<< if ( (iptr = find_active_chan(from)) ) { ret = PICA_accept_file(iptr, filepath.toUtf8().data(), filepath.toUtf8().size()); @@ -296,15 +475,15 @@ if ( (iptr = find_active_chan(from)) ) //show error somewhere somehow } } -write_mutex.unlock();//>> + } void SkyNet::DenyFile(QByteArray from) { int ret = PICA_OK; -struct PICA_chaninfo *iptr; +struct PICA_c2c *iptr; + -write_mutex.lock();//<< if ( (iptr = find_active_chan(from)) ) { ret = PICA_deny_file(iptr); @@ -315,15 +494,15 @@ if ( (iptr = find_active_chan(from)) ) //show error somewhere somehow } } -write_mutex.unlock();//>> + } void SkyNet::PauseFile(QByteArray peer_id, bool pause_sending) { int ret = PICA_OK; -struct PICA_chaninfo *iptr; +struct PICA_c2c *iptr; + -write_mutex.lock();//<< if ( (iptr = find_active_chan(peer_id)) ) { qDebug() << "calling PICA_pause_file(" << iptr << "," << pause_sending << ")\n"; @@ -334,15 +513,15 @@ if ( (iptr = find_active_chan(peer_id)) ) qDebug() << "PICA_pause_file() returned " << ret << "\n"; } } -write_mutex.unlock();//>> + } void SkyNet::ResumeFile(QByteArray peer_id, bool resume_sending) { int ret = PICA_OK; -struct PICA_chaninfo *iptr; +struct PICA_c2c *iptr; + -write_mutex.lock();//<< if ( (iptr = find_active_chan(peer_id)) ) { ret = PICA_resume_file(iptr, (int)resume_sending ); @@ -352,15 +531,15 @@ if ( (iptr = find_active_chan(peer_id)) ) //show error somewhere somehow } } -write_mutex.unlock();//>> + } void SkyNet::CancelFile(QByteArray peer_id, bool cancel_sending) { int ret = PICA_OK; -struct PICA_chaninfo *iptr; +struct PICA_c2c *iptr; + -write_mutex.lock();//<< if ( (iptr = find_active_chan(peer_id)) ) { ret = PICA_cancel_file(iptr, (int)cancel_sending ); @@ -370,15 +549,15 @@ if ( (iptr = find_active_chan(peer_id)) ) //show error somewhere somehow } } -write_mutex.unlock();//>> + } void SkyNet::SendMessage(QByteArray to, QString msg) { int ret = PICA_OK; -struct PICA_chaninfo *iptr; +struct PICA_c2c *iptr; + -write_mutex.lock();//<< if ( (iptr = find_active_chan(to)) ) { @@ -389,7 +568,7 @@ if ( (iptr = find_active_chan(to)) ) if (ret != PICA_OK) emit UnableToDeliver(to, msg); - write_mutex.unlock();//>> + return; } @@ -399,9 +578,9 @@ if ( (iptr = find_active_chan(to)) ) } else { - struct PICA_chaninfo *chan = NULL; + struct PICA_c2c *chan = NULL; - ret = PICA_create_channel(nodelink, (const unsigned char*)to.constData(), &chan); + ret = PICA_new_c2c(active_nodelink, (const unsigned char*)to.constData(), NULL, &chan); QList<QString> l; l.append(msg); @@ -409,7 +588,7 @@ if ( (iptr = find_active_chan(to)) ) } -write_mutex.unlock();//>> + if (ret != PICA_OK) emit UnableToDeliver(to, msg); @@ -418,7 +597,7 @@ write_mutex.unlock();//>> void SkyNet::flush_queues(QByteArray to) { - struct PICA_chaninfo *chan; + struct PICA_c2c *chan; int ret; if (self_aware && (msgqueues.contains(to) || sndfilequeues.contains(to))) @@ -466,16 +645,16 @@ void SkyNet::flush_queues(QByteArray to) } } -struct PICA_chaninfo * SkyNet::find_active_chan(QByteArray peer_id) +struct PICA_c2c * SkyNet::find_active_chan(QByteArray peer_id) { -if (!nodelink) +if (!active_nodelink) return NULL; -struct PICA_chaninfo *iptr = nodelink->chan_list_head; +struct PICA_c2c *iptr = active_nodelink->chan_list_head; while(iptr) { - if (iptr->state == PICA_CHANSTATE_ACTIVE && QByteArray((const char*)iptr->peer_id, PICA_ID_SIZE) == peer_id) + if (iptr->state == PICA_C2C_STATE_ACTIVE && QByteArray((const char*)iptr->peer_id, PICA_ID_SIZE) == peer_id) break; iptr = iptr->next; @@ -488,10 +667,10 @@ QList<QByteArray> SkyNet::filter_existing_chans(QList<QByteArray> peer_ids) { QList<QByteArray> ret = peer_ids; - if (!nodelink) + if (!active_nodelink) return ret; - struct PICA_chaninfo *iptr = nodelink->chan_list_head; + struct PICA_c2c *iptr = active_nodelink->chan_list_head; while(iptr) { @@ -594,17 +773,14 @@ void SkyNet::emit_IncomingFileFinished(QByteArray peer_id) emit IncomingFileFinished(peer_id); } -void SkyNet::emit_ChannelClosed(QByteArray peer_id) +void SkyNet::emit_c2cClosed(QByteArray peer_id) { - emit ChannelClosed(peer_id); + emit c2cClosed(peer_id); } //callbacks -//all callbacks are executed in separate thread, created in Nodethread instance, REMEMBER THAT !!! -// write_mutex is locked - void SkyNet::newmsg_cb(const unsigned char *peer_id, const char *msgbuf, unsigned int nb, int type) { QString msg = QString::fromUtf8(msgbuf, nb); @@ -617,14 +793,14 @@ void SkyNet::msgok_cb(const unsigned char *peer_id) skynet->emit_Delivered(QByteArray((const char*)peer_id, PICA_ID_SIZE)); } -void SkyNet::channel_established_cb(const unsigned char *peer_id) +void SkyNet::c2c_established_cb(const unsigned char *peer_id) { skynet->flush_queues(QByteArray((const char*)peer_id, PICA_ID_SIZE)); } -void SkyNet::channel_failed(const unsigned char *peer_id) +void SkyNet::c2c_failed(const unsigned char *peer_id) { - qDebug()<<"channel failed ("<<QByteArray((const char*)peer_id, PICA_ID_SIZE).toBase64()<<")\n"; + qDebug()<<"c2c failed ("<<QByteArray((const char*)peer_id, PICA_ID_SIZE).toBase64()<<")\n"; } int SkyNet::accept_cb(const unsigned char *caller_id) @@ -649,12 +825,12 @@ void SkyNet::notfound_cb(const unsigned char *callee_id) */ } -void SkyNet::channel_closed_cb(const unsigned char *peer_id, int reason) +void SkyNet::c2c_closed_cb(const unsigned char *peer_id, int reason) { - qDebug()<<"channel closed ("<<QByteArray((const char*)peer_id, PICA_ID_SIZE).toBase64() + qDebug()<<"c2c closed ("<<QByteArray((const char*)peer_id, PICA_ID_SIZE).toBase64() <<", error_code =" << reason << ")\n"; - skynet->emit_ChannelClosed(QByteArray((const char*)peer_id, PICA_ID_SIZE)); + skynet->emit_c2cClosed(QByteArray((const char*)peer_id, PICA_ID_SIZE)); } void SkyNet::nodelist_cb(int type, void *addr_bin, const char *addr_str, unsigned int port) @@ -759,3 +935,23 @@ void SkyNet::file_finished(const unsigned char *peer_id, int sending) else skynet->emit_IncomingFileFinished(QByteArray((const char *)peer_id, PICA_ID_SIZE)); } + +void SkyNet::c2n_established_cb(struct PICA_c2n *c2n) +{ + skynet->nodelink_activated(c2n); +} + +void SkyNet::c2n_failed_cb(struct PICA_c2n *c2n, int error) +{ + skynet->nodelink_failed(c2n, error); +} + +void SkyNet::c2n_closed_cb(struct PICA_c2n *c2n, int error) +{ + skynet->nodelink_closed(c2n, error); +} + +void SkyNet::listener_error_cb(struct PICA_listener *lst, int errorcode) +{ + +} diff --git a/pica-client/skynet.h b/pica-client/skynet.h index ebc78ff..bea1a21 100644 --- a/pica-client/skynet.h +++ b/pica-client/skynet.h @@ -2,12 +2,13 @@ #define SKYNET_H #include "nodes.h" -#include "nodethread.h" #include "../PICA_client.h" #include "../PICA_proto.h" #include "accounts.h" #include <QObject> #include <QMap> +#include <QVector> +#include <QPair> class SkyNet : public QObject @@ -17,7 +18,6 @@ public: SkyNet(); void Join(Accounts::AccountRecord &accrec); bool isSelfAware(); - QString& Status(); void Exit(); void SendMessage(QByteArray to, QString msg); @@ -38,7 +38,7 @@ signals: void LostSelfAwareness(); void PeerCertificateReceived(QByteArray peer_id, QString cert_pem, bool *verified); void CertificateForged(QByteArray peer_id, QString received_cert, QString stored_cert); - void ErrMsgFromNode(QString msg); + void StatusMsg(QString msg, bool is_critical); void ContactsUpdated(); void IncomingFileRequestReceived(QByteArray peer_id, quint64 file_size, QString filename); void OutgoingFileRequestAccepted(QByteArray peer_id); @@ -55,26 +55,29 @@ signals: void OutgoingFileFinished(QByteArray peer_id); void IncomingFileFinished(QByteArray peer_id); - void ChannelClosed(QByteArray peer_id); + void c2cClosed(QByteArray peer_id); private: Nodes nodes; - QList<NodeThread*> threads; + QList<QPair<struct PICA_c2n *, Nodes::NodeRecord> > connecting_nodes; bool self_aware; QString status; - struct PICA_conninfo *nodelink; + struct PICA_c2n *active_nodelink; + struct PICA_acc *acc; + struct PICA_listener *listener; Accounts::AccountRecord skynet_account; - QMutex write_mutex; + QMap<QByteArray, QList<QString> > msgqueues; QMap<QByteArray, QList<QString> > sndfilequeues; - int timer_id; - bool reconnect_enabled; + int retry_timer_id; + int event_loop_timer_id; void timerEvent(QTimerEvent * e); void flush_queues(QByteArray to); - struct PICA_chaninfo *find_active_chan(QByteArray peer_id); + struct PICA_c2c *find_active_chan(QByteArray peer_id); QList<QByteArray> filter_existing_chans(QList<QByteArray> peer_ids); + bool open_account(); void emit_MessageReceived(QByteArray from, QString msg); void emit_UnableToDeliver(QByteArray to, QString msg); @@ -97,22 +100,22 @@ private: void emit_OutgoingFileFinished(QByteArray peer_id); void emit_IncomingFileFinished(QByteArray peer_id); - void emit_ChannelClosed(QByteArray peer_id); + void emit_c2cClosed(QByteArray peer_id); //получение сообщения. static void newmsg_cb(const unsigned char *peer_id,const char* msgbuf,unsigned int nb,int type); //получение подтверждения о доставке сообщения static void msgok_cb(const unsigned char *peer_id); //создание канала с собеседником - static void channel_established_cb(const unsigned char *peer_id); + static void c2c_established_cb(const unsigned char *peer_id); //создать канал не удалось - static void channel_failed(const unsigned char *peer_id); + static void c2c_failed(const unsigned char *peer_id); //входящий запрос на создание канала от пользователя с номером caller_id static int accept_cb(const unsigned char *caller_id); //запрошенный пользователь не найден, в оффлайне или отказался от общения static void notfound_cb(const unsigned char *callee_id); - static void channel_closed_cb(const unsigned char *peer_id, int reason); + static void c2c_closed_cb(const unsigned char *peer_id, int reason); static void nodelist_cb(int type, void *addr_bin, const char *addr_str, unsigned int port); @@ -130,10 +133,20 @@ private: static void file_finished(const unsigned char *peer_id, int sending); + static void c2n_established_cb(struct PICA_c2n *c2n); + + static void c2n_failed_cb(struct PICA_c2n *c2n, int error); + + static void c2n_closed_cb(struct PICA_c2n *c2n, int error); + + static void listener_error_cb(struct PICA_listener *lst, int errorcode); + private slots: - void nodethread_finished(); - void nodethread_connected(QString addr, quint16 port, NodeThread *thread); - void node_status_changed(QString addr,quint16 port,bool alive); + void nodelink_activated(PICA_c2n *c2n); + void nodelink_closed(PICA_c2n *c2n, int error); + void nodelink_failed(PICA_c2n *c2n, int error); + + void node_status_changed(Nodes::NodeRecord nr,bool alive); void verify_peer_cert(QByteArray peer_id, QString cert_pem, bool *verified); }; |
