#include "skynet.h" #include "globals.h" #include //#include "dialogs/viewcertdialog.h" #include "contacts.h" #include "openssltool.h" //#include //debug //#include "dialogs/forgedcertdialog.h" #include #include "history.h" SkyNet::SkyNet() : nodes(config_dbname), QObject(0) { self_aware = false; PICA_client_callbacks cbs = { newmsg_cb, msgok_cb, channel_established_cb, channel_failed, accept_cb, notfound_cb, channel_closed_cb, nodelist_cb, peer_cert_verify_cb }; PICA_client_init(&cbs); nodelink = NULL; connect(this, SIGNAL(PeerCertificateReceived(QByteArray,QString,bool*)), this, SLOT(verify_peer_cert(QByteArray,QString,bool*)),Qt::DirectConnection); } void SkyNet::nodethread_finished() { //удалить здесь завершившийся поток for (int i=0;iisFinished()) { delete threads.takeAt(i); break; } } if (threads.count() == 0) { self_aware = false; emit LostSelfAwareness(); } } void SkyNet::nodethread_connected(QString addr, quint16 port, NodeThread *thread) { if (self_aware) { emit BecameSelfAware(); //restore old peer connections, if any QList c2c_peer_ids; //load undelivered messages from history if (msgqueues.isEmpty()) { History h(config_dbname, Accounts::GetCurrentAccount().id); msgqueues = h.GetUndeliveredMessages(); } c2c_peer_ids = msgqueues.keys(); for (int i = 0; i < c2c_peer_ids.size(); i++) { int ret; write_mutex.lock(); struct PICA_chaninfo *chan = NULL; ret = PICA_create_channel(nodelink, (const unsigned char*)c2c_peer_ids[i].constData(), &chan); qDebug()<<"restoring channel to "< c2c_peer_ids = msgqueues.keys(); write_mutex.lock(); c2c_peer_ids = filter_existing_chans(c2c_peer_ids); for (int i = 0; i < c2c_peer_ids.size(); i++) { int ret; struct PICA_chaninfo *chan = NULL; ret = PICA_create_channel(nodelink, (const unsigned char*)c2c_peer_ids[i].constData(), &chan); qDebug()<<"restoring channel to "<timerId()); Accounts::AccountRecord acc = this->CurrentAccount(); Join(acc); } } void SkyNet::Join(Accounts::AccountRecord &accrec) { QList nodelist; skynet_account = accrec; nodelist = nodes.GetNodes(); if (nodelist.count()==0) { status = QObject::tr("No known Pica Pica nodes"); return; } for (int i=0;iCloseThread(); self_aware = false; killTimer(timer_id); } bool SkyNet::isSelfAware() { return self_aware; } void SkyNet::SendMessage(QByteArray to, QString msg) { int ret = PICA_OK; struct PICA_chaninfo *iptr; write_mutex.lock();//<< if ( (iptr = find_active_chan(to)) ) { //write_mutex.lock();//<< ret = PICA_send_msg(iptr, msg.toUtf8().data(), msg.toUtf8().size()); //write_mutex.unlock();//>> if (ret != PICA_OK) emit UnableToDeliver(to, msg); write_mutex.unlock();//>> return; } if (msgqueues.contains(to)) { msgqueues[to].append(msg); } else { struct PICA_chaninfo *chan = NULL; ret = PICA_create_channel(nodelink, (const unsigned char*)to.constData(), &chan); QList l; l.append(msg); msgqueues[to] = l; } write_mutex.unlock();//>> if (ret != PICA_OK) emit UnableToDeliver(to, msg); } void SkyNet::flush_msgqueue(QByteArray to) { struct PICA_chaninfo *chan; int ret; if (self_aware && msgqueues.contains(to)) { qDebug()<<"flushing "<chan_list_head; while(iptr) { if (iptr->state == PICA_CHANSTATE_ACTIVE && QByteArray((const char*)iptr->peer_id, PICA_ID_SIZE) == peer_id) break; iptr = iptr->next; } return iptr; } QList SkyNet::filter_existing_chans(QList peer_ids) { QList ret = peer_ids; if (!nodelink) return ret; struct PICA_chaninfo *iptr = nodelink->chan_list_head; while(iptr) { if (peer_ids.contains(QByteArray((const char*)iptr->peer_id, PICA_ID_SIZE))) ret.removeOne((const char*)iptr->peer_id); iptr = iptr->next; } return ret; } void SkyNet::emit_Delivered(QByteArray to) { emit Delivered(to); } void SkyNet::emit_MessageReceived(QByteArray from, QString msg) { emit MessageReceived(from, msg); } void SkyNet::emit_UnableToDeliver(QByteArray to, QString msg) { emit UnableToDeliver(to, msg); } void SkyNet::emit_PeerCertificateReceived(QByteArray peer_id, QString cert_pem, bool *verified) { emit PeerCertificateReceived(peer_id, cert_pem, verified); } //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, char *msgbuf, unsigned int nb, int type) { QString msg = QString::fromUtf8(msgbuf, nb); skynet->emit_MessageReceived(QByteArray((const char*)peer_id, PICA_ID_SIZE), msg); } 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) { skynet->flush_msgqueue(QByteArray((const char*)peer_id, PICA_ID_SIZE)); } void SkyNet::channel_failed(const unsigned char *peer_id) { qDebug()<<"channel failed ("<msgqueues.contains(callee_id)) { while ( ! skynet->msgqueues[callee_id].empty()) { skynet->emit_UnableToDeliver(callee_id, skynet->msgqueues[callee_id].last()); skynet->msgqueues[callee_id].removeLast(); } // msgqueues.remove(callee_id) was forgotten } */ } void SkyNet::channel_closed_cb(const unsigned char *peer_id, int reason) { qDebug()<<"channel closed ("<nodes.Add(nr); } int SkyNet::peer_cert_verify_cb(const unsigned char *peer_id, const char *cert_pem, unsigned int nb) { bool verified = true; skynet->emit_PeerCertificateReceived(QByteArray((const char*)peer_id, PICA_ID_SIZE), QString::fromAscii(cert_pem, nb), &verified); if (!verified) return 0; return 1; }