#include "skynet.h" #include "globals.h" #include //#include "dialogs/viewcertdialog.h" #include "contacts.h" #include "openssltool.h" //#include //debug //#include "dialogs/forgedcertdialog.h" #include 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(quint32,QString,bool*)), this, SLOT(verify_peer_cert(quint32,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; 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, c2c_peer_ids[i], &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, c2c_peer_ids[i], &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(quint32 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, to, &chan); QList l; l.append(msg); msgqueues[to] = l; } write_mutex.unlock();//>> if (ret != PICA_OK) emit UnableToDeliver(to, msg); } void SkyNet::flush_msgqueue(quint32 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 && iptr->peer_id == 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(iptr->peer_id)) ret.removeOne(iptr->peer_id); iptr = iptr->next; } return ret; } void SkyNet::emit_Delivered(quint32 to) { emit Delivered(to); } void SkyNet::emit_MessageReceived(quint32 from, QString msg) { emit MessageReceived(from, msg); } void SkyNet::emit_UnableToDeliver(quint32 to, QString msg) { emit UnableToDeliver(to, msg); } void SkyNet::emit_PeerCertificateReceived(quint32 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(unsigned int peer_id, char *msgbuf, unsigned int nb, int type) { QString msg = QString::fromUtf8(msgbuf, nb); skynet->emit_MessageReceived(peer_id, msg); } void SkyNet::msgok_cb(unsigned int peer_id) { skynet->emit_Delivered(peer_id); } void SkyNet::channel_established_cb(unsigned int peer_id) { skynet->flush_msgqueue(peer_id); } void SkyNet::channel_failed(unsigned int 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(unsigned int peer_id, int reason) { qDebug()<<"channel closed ("<nodes.Add(nr); } int SkyNet::peer_cert_verify_cb(unsigned int peer_id, const char *cert_pem, unsigned int nb) { bool verified = true; skynet->emit_PeerCertificateReceived(peer_id, QString::fromAscii(cert_pem, nb), &verified); if (!verified) return 0; return 1; }