summaryrefslogtreecommitdiffstats
path: root/pica-client
diff options
context:
space:
mode:
Diffstat (limited to 'pica-client')
-rw-r--r--pica-client/askpassword.cpp73
-rw-r--r--pica-client/askpassword.h8
-rw-r--r--pica-client/dialogs/settingsdialog.cpp168
-rw-r--r--pica-client/dialogs/settingsdialog.h44
-rw-r--r--pica-client/filetransfercontroller.cpp8
-rw-r--r--pica-client/main.cpp41
-rw-r--r--pica-client/mainwindow.cpp9
-rw-r--r--pica-client/mainwindow.h3
-rw-r--r--pica-client/msguirouter.cpp6
-rw-r--r--pica-client/msguirouter.h2
-rw-r--r--pica-client/nodethread.cpp11
-rw-r--r--pica-client/nodethread.h8
-rw-r--r--pica-client/pica-client.pro10
-rw-r--r--pica-client/picaactioncenter.cpp17
-rw-r--r--pica-client/picaactioncenter.h3
-rw-r--r--pica-client/settings.cpp69
-rw-r--r--pica-client/settings.h24
-rw-r--r--pica-client/skynet.cpp446
-rw-r--r--pica-client/skynet.h47
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 = &ac;
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);
};