summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xPICA_client.c118
-rwxr-xr-xPICA_client.h8
-rw-r--r--pica-client/contactlistwidget.cpp6
-rw-r--r--pica-client/dialogs/filetransferdialog.cpp20
-rw-r--r--pica-client/dialogs/filetransferdialog.h16
-rw-r--r--pica-client/filetransfercontroller.cpp137
-rw-r--r--pica-client/filetransfercontroller.h45
-rw-r--r--pica-client/globals.h1
-rw-r--r--pica-client/main.cpp4
-rw-r--r--pica-client/pica-client.pro6
-rw-r--r--pica-client/skynet.cpp161
-rw-r--r--pica-client/skynet.h28
12 files changed, 492 insertions, 58 deletions
diff --git a/PICA_client.c b/PICA_client.c
index 771730d..bc0939d 100755
--- a/PICA_client.c
+++ b/PICA_client.c
@@ -3,9 +3,7 @@
#include "PICA_msgproc.h"
#include "PICA_common.h"
#include <openssl/dh.h>
-//#ifdef NO_RAND_DEV
-//#include "PICA_rand_seed.h"
-//#endif
+#include <string.h>
#define PICA_DEBUG // debug
@@ -653,12 +651,60 @@ else
return 1;
}
+int PICA_deny_file(struct PICA_chaninfo *chan)
+{
+struct PICA_proto_msg *mp;
+
+if (chan->recvfilestate != PICA_CHANRECVFILESTATE_WAITACCEPT)
+ return PICA_ERRINVARG;
+
+chan->recvfilestate = PICA_CHANRECVFILESTATE_IDLE;
+
+mp = c2c_writebuf_push(chan, PICA_PROTO_DENIEDFILE, PICA_PROTO_DENIEDFILE_SIZE);
+
+if (mp)
+ {
+ RAND_bytes(mp->tail, 2);
+ }
+else
+ return PICA_ERRNOMEM;
+
+return PICA_OK;
+}
+
+int PICA_accept_file(struct PICA_chaninfo *chan, char *filename, unsigned int filenamesize)
+{
+struct PICA_proto_msg *mp;
+int ret;
+
+if (chan->recvfilestate != PICA_CHANRECVFILESTATE_WAITACCEPT)
+ return PICA_ERRINVARG;
+
+//open file
+ret = PICA_recvfile_open_write(chan, filename, filenamesize);
+
+if (ret != PICA_OK)
+ return ret;
+
+mp = c2c_writebuf_push(chan, PICA_PROTO_ACCEPTEDFILE, PICA_PROTO_ACCEPTEDFILE_SIZE);
+
+if (mp)
+ {
+ RAND_bytes(mp->tail, 2);
+ }
+else
+ return PICA_ERRNOMEM;
+
+chan->recvfilestate = PICA_CHANRECVFILESTATE_RECEIVING;
+
+return PICA_OK;
+}
+
static unsigned int procmsg_SENDFILEREQUEST(unsigned char* buf, unsigned int nb, void* p)
{
struct PICA_chaninfo *chan = (struct PICA_chaninfo *)p;
struct PICA_proto_msg *mp;
-unsigned int reply;
-unsigned int replysize;
+int ret;
char *filename = buf + 12;
unsigned int filenamesize = *(uint16_t*)(buf + 2) - 8;
@@ -666,32 +712,27 @@ unsigned int filenamesize = *(uint16_t*)(buf + 2) - 8;
if (chan->recvfilestate != PICA_CHANRECVFILESTATE_IDLE)
return 0;
-reply = PICA_PROTO_DENIEDFILE;
-reply = PICA_PROTO_DENIEDFILE_SIZE;
+chan->recvfilestate = PICA_CHANRECVFILESTATE_WAITACCEPT;
+chan->recvfile_size = *(uint64_t*)(buf + 4);
+chan->recvfile_pos = 0;
+ret = callbacks.accept_file_cb(chan->peer_id, *(uint64_t*)(buf + 4), filename, filenamesize);
-if (callbacks.accept_file_cb(chan->peer_id, *(uint64_t*)(buf + 4), filename, filenamesize))
+if (ret > 0)
{
- chan->recvfilestate = PICA_CHANRECVFILESTATE_RECEIVING;
- chan->recvfile_size = *(uint64_t*)(buf + 4);
- chan->recvfile_pos = 0;
-
- //open file
- if (PICA_recvfile_open_write(chan, filename, filenamesize) == PICA_OK)
+ if (ret == 1)
{
- reply = PICA_PROTO_ACCEPTEDFILE;
- replysize = PICA_PROTO_ACCEPTEDFILE_SIZE;
+ if (PICA_accept_file(chan, filename, filenamesize) != PICA_OK)
+ if (PICA_deny_file(chan) != PICA_OK)
+ return 0;
}
- }
-
-mp = c2c_writebuf_push( chan, reply, replysize);
-if (mp)
+ }
+else
{
- RAND_bytes(mp->tail, 2);
+ if (PICA_deny_file(chan) != PICA_OK)
+ return 0;
}
-else
- return 0;
return 1;
}
@@ -743,6 +784,7 @@ if (fwrite(buf + 4, nb - 4, 1, chan->recvfile_stream) != 1)
struct PICA_proto_msg *mp;
fclose(chan->recvfile_stream);
+ chan->recvfile_stream = NULL;
chan->recvfilestate = PICA_CHANRECVFILESTATE_IDLE;
@@ -763,6 +805,7 @@ if (chan->recvfile_pos == chan->recvfile_size)
{
chan->recvfilestate = PICA_CHANRECVFILESTATE_IDLE;
fclose(chan->recvfile_stream);
+ chan->recvfile_stream = NULL;
}
if (chan->recvfile_pos > chan->recvfile_size) //received more than file_size
@@ -808,6 +851,7 @@ switch(sender_cmd)
case PICA_PROTO_FILECONTROL_IOERROR:
chan->recvfilestate = PICA_CHANRECVFILESTATE_IDLE;
fclose(chan->recvfile_stream);
+ chan->recvfile_stream = NULL;
break;
case PICA_PROTO_FILECONTROL_VOID:
@@ -837,6 +881,7 @@ switch(receiver_cmd)
case PICA_PROTO_FILECONTROL_IOERROR:
chan->sendfilestate = PICA_CHANSENDFILESTATE_IDLE;
fclose(chan->sendfile_stream);
+ chan->sendfile_stream = NULL;
break;
default:
@@ -1663,25 +1708,38 @@ else
return PICA_OK;
}
-int PICA_send_file(struct PICA_chaninfo *chn, const char *filename)
+int PICA_send_file(struct PICA_chaninfo *chn, const char *filepath)
{
struct PICA_proto_msg *mp;
size_t namelen;
uint64_t file_size;
int ret;
+const char *filename;//file name part of the filepath
if (chn->sendfilestate != PICA_CHANSENDFILESTATE_IDLE)
return PICA_ERRFILETRANSFERINPROGRESS;
-if (filename == NULL)
+if (filepath == NULL)
return PICA_ERRINVFILENAME;
+#ifndef WIN32
+filename = strrchr(filepath, '/');
+#else
+filename = strrchr(filepath, '\\');
+#endif
+
+if (filename)
+ filename++;
+else
+ filename = filepath;
+
+
namelen = strlen(filename);
if (namelen == 0 || namelen > PICA_PROTO_C2CMSG_MAXFILENAMESIZE)
return PICA_ERRINVFILENAME;
-if ((ret = PICA_sendfile_open_read(chn, filename, &file_size)) != PICA_OK)
+if ((ret = PICA_sendfile_open_read(chn, filepath, &file_size)) != PICA_OK)
return ret;
if ((mp = c2c_writebuf_push(chn, PICA_PROTO_SENDFILEREQUEST, namelen + 12)))
@@ -1689,7 +1747,7 @@ if ((mp = c2c_writebuf_push(chn, PICA_PROTO_SENDFILEREQUEST, namelen + 12)))
*((uint16_t*)mp->tail) = namelen + 8;
*((uint64_t*)(mp->tail + 2)) = file_size;
- memcpy(mp->tail + 10, filename, namelen);
+ memcpy(mp->tail + 10, filename, namelen);
}
else
return PICA_ERRNOMEM;
@@ -1715,6 +1773,7 @@ fragment_size = fread(buf, 1, PICA_FILEFRAGMENTSIZE, chn->sendfile_stream);
if (fragment_size == 0)
{
fclose(chn->sendfile_stream);
+ chn->sendfile_stream = NULL;
chn->sendfilestate = PICA_CHANSENDFILESTATE_IDLE;
if ((mp = c2c_writebuf_push(chn, PICA_PROTO_FILECONTROL, PICA_PROTO_FILECONTROL_SIZE)))
@@ -1743,6 +1802,7 @@ if (chn->sendfile_pos >= chn->sendfile_size)
{
chn->sendfilestate = PICA_CHANSENDFILESTATE_IDLE;
fclose(chn->sendfile_stream);
+ chn->sendfile_stream = NULL;
}
if (chn->sendfile_pos > chn->sendfile_size)
@@ -1948,9 +2008,9 @@ if (chn->recvfile_stream == NULL)
}
#else
-chn->sendfile_stream = fopen(filename_utf8, "rb");
+chn->recvfile_stream = fopen(filename_utf8, "wb");
-if (chn->sendfile_stream == NULL)
+if (chn->recvfile_stream == NULL)
return PICA_ERRFILEOPEN;
#endif
/////////////
diff --git a/PICA_client.h b/PICA_client.h
index 1b00a57..7d1ae3e 100755
--- a/PICA_client.h
+++ b/PICA_client.h
@@ -107,7 +107,7 @@ typedef unsigned __int64 uint64_t;
#define PICA_CHANRECVFILESTATE_IDLE 0
#define PICA_CHANRECVFILESTATE_RECEIVING 24
#define PICA_CHANRECVFILESTATE_PAUSED 25
-
+#define PICA_CHANRECVFILESTATE_WAITACCEPT 26
#define PICA_CHAN_ACTIVATE_TIMEOUT 30
@@ -197,7 +197,7 @@ void (*channel_closed_cb)(const unsigned char *peer_id, int reason);
void (*nodelist_cb)(int type, void *addr_bin, const char *addr_str, unsigned int port);
//сертификат собеседника в формате PEM. Функция должна сравнить предъявленный сертификат с сохранённым (если есть) и вернуть 1 при успешной проверке, 0 - при неуспешной
int (*peer_cert_verify_cb)(const unsigned char *peer_id, const char *cert_pem, unsigned int nb);
-
+// returns 0 if file is rejected, 1 if accepted, 2 if decision is postponed
int (*accept_file_cb)(const unsigned char *peer_id, uint64_t file_size, const char *filename, unsigned int filename_size);
void (*accepted_file_cb)(const unsigned char *peer_id);
@@ -241,7 +241,9 @@ int PICA_send_msg(struct PICA_chaninfo *chn, char *buf,unsigned int len);
int PICA_read_msg(struct PICA_chaninfo *chn,char *buf,unsigned int *n);
//filename - ASCII or UTF-8 encoded string
-int PICA_send_file(struct PICA_chaninfo *chn, const char *filename);
+int PICA_send_file(struct PICA_chaninfo *chn, const char *filepath);
+int PICA_accept_file(struct PICA_chaninfo *chan, char *filename, unsigned int filenamesize);
+int PICA_deny_file(struct PICA_chaninfo *chan);
void PICA_close_channel(struct PICA_chaninfo *chn);
void PICA_close_connection(struct PICA_conninfo *cid);
diff --git a/pica-client/contactlistwidget.cpp b/pica-client/contactlistwidget.cpp
index 10194e8..d73a3f4 100644
--- a/pica-client/contactlistwidget.cpp
+++ b/pica-client/contactlistwidget.cpp
@@ -4,6 +4,7 @@
#include "dialogs/showpicaiddialog.h"
#include "dialogs/filetransferdialog.h"
#include "msguirouter.h"
+#include "filetransfercontroller.h"
#include <QMenu>
#include <QMessageBox>
#include <QContextMenuEvent>
@@ -208,8 +209,5 @@ void ContactListWidget::Reload()
void ContactListWidget::send_file()
{
-//FileTransferDialog *d = new FileTransferDialog("test", 138900713, FileTransferDialog::SENDING, this);
-
-//d->show();
-
+ ftctrl->send_file(wgitem_to_recs[currentItem()]->id);
}
diff --git a/pica-client/dialogs/filetransferdialog.cpp b/pica-client/dialogs/filetransferdialog.cpp
index c7f145d..4643bb8 100644
--- a/pica-client/dialogs/filetransferdialog.cpp
+++ b/pica-client/dialogs/filetransferdialog.cpp
@@ -3,7 +3,9 @@
#include <QHBoxLayout>
#include <stdlib.h>
-FileTransferDialog::FileTransferDialog(QString filename, quint64 size, TransferDirection drct, QWidget *parent) :
+FileTransferDialog::FileTransferDialog(QByteArray peer_id, QString filename, quint64 size,
+ TransferDirection drct, QWidget *parent) :
+ peer_id_(peer_id),
QDialog(parent),
dir_(drct),
filename_(filename),
@@ -72,6 +74,12 @@ void FileTransferDialog::update(quint64 progress)
+ bytestoHumanBase2(filesize_) + QString(" %1 %").arg((int)percents));
pgbar->setValue(percents);
+
+ if (progress == filesize_)
+ {
+ leftbutton->setEnabled(false);
+ rightbutton->setEnabled(false);
+ }
}
void FileTransferDialog::leftbuttonclick()
@@ -82,7 +90,7 @@ void FileTransferDialog::leftbuttonclick()
{
leftbutton->setText("Pause");
rightbutton->setText("Cancel");
- emit acceptedFile();
+ emit acceptedFile(peer_id_);
return;
}
}
@@ -90,12 +98,12 @@ void FileTransferDialog::leftbuttonclick()
if (leftbutton->text() == tr("Pause"))
{
leftbutton->setText(tr("Resume"));
- emit pausedFile();
+ emit pausedFile(peer_id_, this);
}
else if (leftbutton->text() == tr("Resume"))
{
leftbutton->setText(tr("Pause"));
- emit resumedFile();
+ emit resumedFile(peer_id_, this);
}
}
@@ -105,14 +113,14 @@ void FileTransferDialog::rightbuttonclick()
{
if (rightbutton->text() == tr("Deny"))
{
- emit deniedFile();
+ emit deniedFile(peer_id_);
return;
}
}
if (rightbutton->text() == tr("Cancel"))
{
- emit cancelledFile();
+ emit cancelledFile(peer_id_, this);
}
}
diff --git a/pica-client/dialogs/filetransferdialog.h b/pica-client/dialogs/filetransferdialog.h
index a5a4783..406ea70 100644
--- a/pica-client/dialogs/filetransferdialog.h
+++ b/pica-client/dialogs/filetransferdialog.h
@@ -6,6 +6,7 @@
#include <QLabel>
#include <QPushButton>
#include <QTimer>
+#include <QByteArray>
class FileTransferDialog : public QDialog
{
@@ -17,8 +18,10 @@ public:
RECEIVING
};
- explicit FileTransferDialog(QString filename, quint64 size, TransferDirection drct, QWidget *parent = 0);
+ explicit FileTransferDialog(QByteArray peer_id, QString filename, quint64 size,
+ TransferDirection drct, QWidget *parent = 0);
+ TransferDirection getTransferDirection() {return dir_;};
private:
@@ -30,6 +33,7 @@ private:
QPushButton *leftbutton;
QPushButton *rightbutton;
+ QByteArray peer_id_;
TransferDirection dir_;
QString filename_;
quint64 filesize_;
@@ -44,11 +48,11 @@ private:
QTimer *timer;
signals:
- void pausedFile();
- void resumedFile();
- void cancelledFile();
- void acceptedFile();
- void deniedFile();
+ void pausedFile(QByteArray peer_id, FileTransferDialog *sender);
+ void resumedFile(QByteArray peer_id, FileTransferDialog *sender);
+ void cancelledFile(QByteArray peer_id, FileTransferDialog *sender);
+ void acceptedFile(QByteArray peer_id);
+ void deniedFile(QByteArray peer_id);
public slots:
void update(quint64 progress);
diff --git a/pica-client/filetransfercontroller.cpp b/pica-client/filetransfercontroller.cpp
new file mode 100644
index 0000000..9b479c1
--- /dev/null
+++ b/pica-client/filetransfercontroller.cpp
@@ -0,0 +1,137 @@
+#include "filetransfercontroller.h"
+#include "globals.h"
+#include "skynet.h"
+#include "mainwindow.h"
+#include "msguirouter.h"
+#include <QFileDialog>
+#include <QFileInfo>
+
+FileTransferController::FileTransferController(QObject *parent) :
+ QObject(parent)
+{
+ connect(skynet, SIGNAL(IncomingFileRequestReceived(QByteArray,quint64,QString)),
+ this, SLOT(file_request(QByteArray,quint64,QString)));
+
+ connect(skynet, SIGNAL(FileProgress(QByteArray,quint64,quint64)),
+ this, SLOT(file_progress(QByteArray,quint64,quint64)));
+
+ connect(skynet, SIGNAL(OutgoingFileRequestAccepted(QByteArray)), this, SLOT(file_accepted_by_peer(QByteArray)));
+
+ connect(skynet, SIGNAL(OutgoingFileRequestDenied(QByteArray)), this, SLOT(file_denied_by_peer(QByteArray)));
+}
+
+
+void FileTransferController::file_progress(QByteArray peer_id, quint64 bytes_sent, quint64 bytes_received)
+{
+ if (bytes_received > 0)
+ {
+ if (ftdialogs_in.contains(peer_id))
+ {
+ ftdialogs_in[peer_id]->update(bytes_received);
+ }
+ }
+ else if (bytes_sent > 0)
+ {
+ if (ftdialogs_out.contains(peer_id))
+ {
+ ftdialogs_out[peer_id]->update(bytes_sent);
+ }
+ }
+}
+
+void FileTransferController::file_request(QByteArray peer_id, quint64 file_size, QString filename)
+{
+ FileTransferDialog *ftd = new FileTransferDialog(peer_id, filename, file_size, FileTransferDialog::RECEIVING);
+
+ ftdialogs_in[peer_id] = ftd;
+ fsizes[peer_id] = file_size;
+ fnames[peer_id] = filename;
+
+ connect(ftd, SIGNAL(acceptedFile(QByteArray)), this, SLOT(file_accepted_by_me(QByteArray)));
+ connect(ftd, SIGNAL(deniedFile(QByteArray)), this, SLOT(file_denied_by_me(QByteArray)));
+
+ ftd->show();
+}
+
+void FileTransferController::file_accepted_by_peer(QByteArray peer_id)
+{
+
+}
+
+void FileTransferController::file_denied_by_peer(QByteArray peer_id)
+{
+
+}
+
+void FileTransferController::file_accepted_by_me(QByteArray peer_id)
+{
+
+
+ QString filePathToSave = QFileDialog::getSaveFileName(ftdialogs_in[peer_id], tr("Save received file to"),
+ fnames[peer_id], tr("Any file (* *.*)"));
+
+ skynet->AcceptFile(peer_id, filePathToSave);
+
+ connect(ftdialogs_in[peer_id], SIGNAL(cancelledFile(QByteArray,FileTransferDialog*)), this, SLOT(file_cancelled_by_me(QByteArray,FileTransferDialog*)));
+ connect(ftdialogs_in[peer_id], SIGNAL(pausedFile(QByteArray,FileTransferDialog*)), this, SLOT(file_paused_by_me(QByteArray,FileTransferDialog*)));
+ connect(ftdialogs_in[peer_id], SIGNAL(resumedFile(QByteArray,FileTransferDialog*)), this, SLOT(file_resumed_by_me(QByteArray,FileTransferDialog*)));
+}
+
+void FileTransferController::file_denied_by_me(QByteArray peer_id)
+{
+}
+
+void FileTransferController::file_cancelled_by_me(QByteArray peer_id, FileTransferDialog *from)
+{
+
+}
+
+void FileTransferController::file_paused_by_me(QByteArray peer_id, FileTransferDialog *from)
+{
+
+}
+
+void FileTransferController::file_resumed_by_me(QByteArray peer_id, FileTransferDialog *from)
+{
+
+}
+
+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."));
+ return;
+ }
+
+ QString filepath = QFileDialog::getOpenFileName(0, tr("Select file to send"), QString(), tr("Any file (* *.*)"));
+
+ if (filepath.isNull())
+ return;
+
+ QFileInfo fi(filepath);
+
+ if (!fi.exists())
+ {
+ msguirouter->notification(tr("File \"%1\" does not exist.").arg(filepath));
+ return;
+ }
+
+ if (fi.size() == 0)
+ {
+ msguirouter->notification(tr("Cannot send empty file."));
+ }
+
+ skynet->SendFile(peer_id, filepath);
+
+ FileTransferDialog *ftd = new FileTransferDialog(peer_id, fi.fileName(), fi.size(), FileTransferDialog::SENDING);
+
+ ftdialogs_out[peer_id] = ftd;
+
+ connect(ftdialogs_out[peer_id], SIGNAL(cancelledFile(QByteArray,FileTransferDialog*)), this, SLOT(file_cancelled_by_me(QByteArray,FileTransferDialog*)));
+ connect(ftdialogs_out[peer_id], SIGNAL(pausedFile(QByteArray,FileTransferDialog*)), this, SLOT(file_paused_by_me(QByteArray,FileTransferDialog*)));
+ connect(ftdialogs_out[peer_id], SIGNAL(resumedFile(QByteArray,FileTransferDialog*)), this, SLOT(file_resumed_by_me(QByteArray,FileTransferDialog*)));
+
+ ftd->show();
+}
diff --git a/pica-client/filetransfercontroller.h b/pica-client/filetransfercontroller.h
new file mode 100644
index 0000000..72a989e
--- /dev/null
+++ b/pica-client/filetransfercontroller.h
@@ -0,0 +1,45 @@
+#ifndef FILETRANSFERCONTROLLER_H
+#define FILETRANSFERCONTROLLER_H
+
+#include <QObject>
+#include <QMap>
+#include "dialogs/filetransferdialog.h"
+
+class FileTransferController : public QObject
+{
+ Q_OBJECT
+public:
+ explicit FileTransferController(QObject *parent = 0);
+
+signals:
+
+private:
+
+ QMap<QByteArray, FileTransferDialog*> ftdialogs_in;
+ QMap<QByteArray, FileTransferDialog*> ftdialogs_out;
+
+ QMap<QByteArray, quint64> fsizes;
+ QMap<QByteArray, QString> fnames;
+
+
+public slots:
+
+ // from remote peer to me
+ void file_progress(QByteArray peer_id, quint64 bytes_sent, quint64 bytes_received);
+ void file_request(QByteArray peer_id, quint64 file_size, QString filename);
+ void file_accepted_by_peer(QByteArray peer_id);
+ void file_denied_by_peer(QByteArray peer_id);
+ //void file_control(QByteArray peer_id, )
+
+ //from me (file transfer dialog shown to user) to remote peer
+ void file_accepted_by_me(QByteArray peer_id);
+ void file_denied_by_me(QByteArray peer_id);
+ void file_cancelled_by_me(QByteArray peer_id, FileTransferDialog *from);
+ void file_paused_by_me(QByteArray peer_id, FileTransferDialog *from);
+ void file_resumed_by_me(QByteArray peer_id, FileTransferDialog *from);
+
+ void send_file(QByteArray peer_id);
+
+};
+
+#endif // FILETRANSFERCONTROLLER_H
diff --git a/pica-client/globals.h b/pica-client/globals.h
index f60f568..48c3ec8 100644
--- a/pica-client/globals.h
+++ b/pica-client/globals.h
@@ -27,4 +27,5 @@ extern class QIcon picapica_ico_sit;
extern class QIcon picapica_ico_fly;
extern class PicaActionCenter *action_center;
extern class PicaSysTray *systray;
+extern class FileTransferController *ftctrl;
#endif // GLOBALS_H
diff --git a/pica-client/main.cpp b/pica-client/main.cpp
index 40b1cb0..0139bb0 100644
--- a/pica-client/main.cpp
+++ b/pica-client/main.cpp
@@ -5,6 +5,7 @@
#include "contacts.h"
#include "skynet.h"
#include "msguirouter.h"
+#include "filetransfercontroller.h"
#include "picaactioncenter.h"
#include "picasystray.h"
#include <QDir>
@@ -27,6 +28,7 @@ QIcon picapica_ico_fly;
class PicaActionCenter *action_center;
class PicaSysTray *systray;
+class FileTransferController *ftctrl;
// /usr/share/pica-client/pica-pica_CA.pem
//QString config_defaultCA("/home/root_jr/files/projects/picapica_wc/localhost/project_picapica/trunk/tests/trusted_CA.pem");
@@ -475,6 +477,8 @@ int main(int argc, char *argv[])
MsgUIRouter muir;
msguirouter = &muir;
+ FileTransferController ftc;
+ ftctrl = &ftc;
aw.show();
diff --git a/pica-client/pica-client.pro b/pica-client/pica-client.pro
index cffe5b3..df3b729 100644
--- a/pica-client/pica-client.pro
+++ b/pica-client/pica-client.pro
@@ -35,7 +35,8 @@ SOURCES += main.cpp\
../PICA_id.c \
dhparam.cpp \
dialogs/showpicaiddialog.cpp \
- dialogs/filetransferdialog.cpp
+ dialogs/filetransferdialog.cpp \
+ filetransfercontroller.cpp
HEADERS += mainwindow.h \
chatwindow.h \
@@ -64,7 +65,8 @@ HEADERS += mainwindow.h \
../PICA_id.h \
dhparam.h \
dialogs/showpicaiddialog.h \
- dialogs/filetransferdialog.h
+ dialogs/filetransferdialog.h \
+ filetransfercontroller.h
DEFINES = PICA_MULTITHREADED
diff --git a/pica-client/skynet.cpp b/pica-client/skynet.cpp
index e868903..1077df2 100644
--- a/pica-client/skynet.cpp
+++ b/pica-client/skynet.cpp
@@ -23,7 +23,12 @@ PICA_client_callbacks cbs = {
notfound_cb,
channel_closed_cb,
nodelist_cb,
- peer_cert_verify_cb
+ peer_cert_verify_cb,
+ accept_file_cb,
+ accepted_file_cb,
+ denied_file_cb,
+ file_progress,
+ file_control
};
PICA_client_init(&cbs);
@@ -70,7 +75,14 @@ void SkyNet::nodethread_connected(QString addr, quint16 port, NodeThread *thread
msgqueues = h.GetUndeliveredMessages();
}
- c2c_peer_ids = msgqueues.keys();
+ //load file transfers to be completed
+ // sndfilequeues = ...
+
+ QMap<QByteArray, QList<QString> > queues = msgqueues;
+
+ queues.unite(sndfilequeues);
+
+ c2c_peer_ids = queues.uniqueKeys();
for (int i = 0; i < c2c_peer_ids.size(); i++)
{
@@ -157,7 +169,10 @@ void SkyNet::timerEvent(QTimerEvent *e)
{
if (write_mutex.tryLock(10))
{
- QList<QByteArray> c2c_peer_ids = msgqueues.keys();
+ QMap<QByteArray, QList<QString> > queues = msgqueues;
+ queues.unite(sndfilequeues);
+
+ QList<QByteArray> c2c_peer_ids = queues.uniqueKeys();
c2c_peer_ids = filter_existing_chans(c2c_peer_ids);
@@ -221,6 +236,68 @@ bool SkyNet::isSelfAware()
return self_aware;
}
+void SkyNet::SendFile(QByteArray to, QString filepath)
+{
+int ret = PICA_OK;
+struct PICA_chaninfo *iptr;
+
+write_mutex.lock();//<<
+
+if ( (iptr = find_active_chan(to)) )
+ {
+ ret = PICA_send_file(iptr, filepath.toUtf8().data());
+
+ if (ret != PICA_OK)
+ {
+ //show error somewhere somehow
+ }
+
+ write_mutex.unlock();//>>
+ return;
+ }
+
+ if (sndfilequeues.contains(to))
+ {
+ //sending multiple files is not supported yet
+ }
+ else
+ {
+ struct PICA_chaninfo *chan = NULL;
+
+ ret = PICA_create_channel(nodelink, (const unsigned char*)to.constData(), &chan);
+
+ QList<QString> l;
+ l.append(filepath);
+ sndfilequeues[to] = l;
+ }
+
+write_mutex.unlock();//>>
+
+ if (ret!= PICA_OK)
+ {
+ //report error
+ }
+}
+
+void SkyNet::AcceptFile(QByteArray from, QString filepath)
+{
+int ret = PICA_OK;
+struct PICA_chaninfo *iptr;
+
+write_mutex.lock();//<<
+if ( (iptr = find_active_chan(from)) )
+ {
+ ret = PICA_accept_file(iptr, filepath.toUtf8().data(), filepath.toUtf8().size());
+
+ qDebug() << "PICA_accept_file(" << filepath.toUtf8().data() << ", " << filepath.toUtf8().size() << ") returned " << ret << "\n";
+ if (ret != PICA_OK)
+ {
+ //show error somewhere somehow
+ }
+ }
+write_mutex.unlock();//>>
+}
+
void SkyNet::SendMessage(QByteArray to, QString msg)
{
int ret = PICA_OK;
@@ -241,7 +318,6 @@ if ( (iptr = find_active_chan(to)) )
return;
}
-
if (msgqueues.contains(to))
{
msgqueues[to].append(msg);
@@ -265,17 +341,18 @@ write_mutex.unlock();//>>
}
-void SkyNet::flush_msgqueue(QByteArray to)
+void SkyNet::flush_queues(QByteArray to)
{
struct PICA_chaninfo *chan;
int ret;
- if (self_aware && msgqueues.contains(to))
+ if (self_aware && (msgqueues.contains(to) || sndfilequeues.contains(to)))
{
qDebug()<<"flushing "<<to<<" message queue\n";
if ((chan = find_active_chan(to)))
{
+ /////// messages
while( !msgqueues[to].empty() )
{
ret = PICA_send_msg(chan, msgqueues[to].first().toUtf8().data(), msgqueues[to].first().toUtf8().size());
@@ -292,6 +369,24 @@ void SkyNet::flush_msgqueue(QByteArray to)
if (msgqueues[to].empty())
msgqueues.remove(to);
+
+
+ ///////// files
+ while (!sndfilequeues[to].empty())
+ {
+ ret = PICA_send_file(chan, sndfilequeues[to].first().toUtf8().data());
+
+ if (ret != PICA_OK)
+ {
+ //report error somehow
+ break;
+ }
+
+ sndfilequeues[to].removeFirst();
+ }
+
+ if (sndfilequeues[to].empty())
+ sndfilequeues.remove(to);
}
}
}
@@ -354,6 +449,26 @@ void SkyNet::emit_PeerCertificateReceived(QByteArray peer_id, QString cert_pem,
emit PeerCertificateReceived(peer_id, cert_pem, verified);
}
+void SkyNet::emit_IncomingFileRequestReceived(QByteArray peer_id, quint64 file_size, QString filename)
+{
+ emit IncomingFileRequestReceived(peer_id, file_size, filename);
+}
+
+void SkyNet::emit_OutgoingFileRequestAccepted(QByteArray peer_id)
+{
+ emit OutgoingFileRequestAccepted(peer_id);
+}
+
+void SkyNet::emit_OutgoingFileRequestDenied(QByteArray peer_id)
+{
+ emit OutgoingFileRequestDenied(peer_id);
+}
+
+void SkyNet::emit_FileProgress(QByteArray peer_id, quint64 bytes_sent, quint64 bytes_received)
+{
+ emit FileProgress(peer_id, bytes_sent, bytes_received);
+}
+
//callbacks
//all callbacks are executed in separate thread, created in Nodethread instance, REMEMBER THAT !!!
@@ -373,7 +488,7 @@ skynet->emit_Delivered(QByteArray((const char*)peer_id, PICA_ID_SIZE));
void SkyNet::channel_established_cb(const unsigned char *peer_id)
{
-skynet->flush_msgqueue(QByteArray((const char*)peer_id, PICA_ID_SIZE));
+skynet->flush_queues(QByteArray((const char*)peer_id, PICA_ID_SIZE));
}
void SkyNet::channel_failed(const unsigned char *peer_id)
@@ -426,3 +541,35 @@ int SkyNet::peer_cert_verify_cb(const unsigned char *peer_id, const char *cert_p
return 1;
}
+
+int SkyNet::accept_file_cb(const unsigned char *peer_id, uint64_t file_size, const char *filename, unsigned int filename_size)
+{
+ skynet->emit_IncomingFileRequestReceived(QByteArray((const char*)peer_id, PICA_ID_SIZE),
+ file_size, QString::fromUtf8(filename, filename_size));
+
+ return 2;//??? accept later code
+}
+
+void SkyNet::accepted_file_cb(const unsigned char *peer_id)
+{
+ qDebug()<<"FILE: file was accepted by remote side\n";
+
+ skynet->emit_OutgoingFileRequestAccepted(QByteArray((const char *)peer_id, PICA_ID_SIZE));
+}
+
+void SkyNet::denied_file_cb(const unsigned char *peer_id)
+{
+ skynet->emit_OutgoingFileRequestDenied(QByteArray((const char *)peer_id, PICA_ID_SIZE));
+}
+
+void SkyNet::file_progress(const unsigned char *peer_id, uint64_t sent, uint64_t received)
+{
+ qDebug()<<"FILE: file progress" << sent << " sent " << received << "received\n";
+ skynet->emit_FileProgress(QByteArray((const char *)peer_id, PICA_ID_SIZE), sent, received);
+}
+
+void SkyNet::file_control(const unsigned char *peer_id, unsigned int sender_cmd, unsigned int receiver_cmd)
+{
+ //implement me
+}
+
diff --git a/pica-client/skynet.h b/pica-client/skynet.h
index 6c43d6a..f512fb1 100644
--- a/pica-client/skynet.h
+++ b/pica-client/skynet.h
@@ -20,6 +20,8 @@ public:
void Exit();
void SendMessage(QByteArray to, QString msg);
+ void SendFile(QByteArray to, QString filepath);
+ void AcceptFile(QByteArray from, QString filepath);
Accounts::AccountRecord CurrentAccount() {return skynet_account;};
signals:
@@ -32,6 +34,14 @@ signals:
void CertificateForged(QByteArray peer_id, QString received_cert, QString stored_cert);
void ErrMsgFromNode(QString msg);
void ContactsUpdated();
+ void IncomingFileRequestReceived(QByteArray peer_id, quint64 file_size, QString filename);
+ void OutgoingFileRequestAccepted(QByteArray peer_id);
+ void OutgoingFileRequestDenied(QByteArray peer_id);
+ void FileProgress(QByteArray peer_id, quint64 bytes_sent, quint64 bytes_received);
+ void IncomingFilePaused(QByteArray peer_id);
+ void IncomingFileCancelled(QByteArray peer_id);
+ void IncomingFileIoError(QByteArray peer_id);
+ void IncomingFileResumed(QByteArray peer_id);
private:
Nodes nodes;
@@ -42,11 +52,12 @@ private:
Accounts::AccountRecord skynet_account;
QMutex write_mutex;
QMap<QByteArray, QList<QString> > msgqueues;
+ QMap<QByteArray, QList<QString> > sndfilequeues;
int timer_id;
void timerEvent(QTimerEvent * e);
- void flush_msgqueue(QByteArray to);
+ void flush_queues(QByteArray to);
struct PICA_chaninfo *find_active_chan(QByteArray peer_id);
QList<QByteArray> filter_existing_chans(QList<QByteArray> peer_ids);
@@ -54,6 +65,11 @@ private:
void emit_UnableToDeliver(QByteArray to, QString msg);
void emit_Delivered(QByteArray to);
void emit_PeerCertificateReceived(QByteArray peer_id, QString cert_pem, bool *verified);
+ void emit_IncomingFileRequestReceived(QByteArray peer_id, quint64 file_size, QString filename);
+ void emit_OutgoingFileRequestAccepted(QByteArray peer_id);
+ void emit_OutgoingFileRequestDenied(QByteArray peer_id);
+ void emit_FileProgress(QByteArray peer_id, quint64 bytes_sent, quint64 bytes_received);
+ //incoming/outgoing x paused, cancelled, io error
//получение сообщения.
static void newmsg_cb(const unsigned char *peer_id,const char* msgbuf,unsigned int nb,int type);
@@ -74,6 +90,16 @@ private:
static int peer_cert_verify_cb(const unsigned char *peer_id, const char *cert_pem, unsigned int nb);
+ static int accept_file_cb(const unsigned char *peer_id, uint64_t file_size, const char *filename, unsigned int filename_size);
+
+ static void accepted_file_cb(const unsigned char *peer_id);
+
+ static void denied_file_cb(const unsigned char *peer_id);
+
+ static void file_progress(const unsigned char *peer_id, uint64_t sent, uint64_t received);
+
+ static void file_control(const unsigned char *peer_id, unsigned int sender_cmd, unsigned int receiver_cmd);
+
private slots:
void nodethread_finished();
void nodethread_connected(QString addr, quint16 port, NodeThread *thread);