xref: /glogg/src/socketexternalcom.cpp (revision 2d1bee565f07168ba29e16133953961ae0fa006c)
10374f408SAnton Filimonov #include "socketexternalcom.h"
20374f408SAnton Filimonov 
30374f408SAnton Filimonov #include <QLocalServer>
40374f408SAnton Filimonov #include <QLocalSocket>
50374f408SAnton Filimonov #include <QSharedMemory>
60374f408SAnton Filimonov 
70374f408SAnton Filimonov #ifdef Q_OS_UNIX
80374f408SAnton Filimonov     #include <signal.h>
90374f408SAnton Filimonov     #include <unistd.h>
100374f408SAnton Filimonov #endif
110374f408SAnton Filimonov 
120374f408SAnton Filimonov #include "log.h"
130374f408SAnton Filimonov 
140374f408SAnton Filimonov static const char* GLOG_SERVICE_NAME = "org.bonnefon.glogg";
150374f408SAnton Filimonov 
160374f408SAnton Filimonov #ifdef Q_OS_UNIX
170374f408SAnton Filimonov QSharedMemory* g_staticSharedMemory = nullptr;
180374f408SAnton Filimonov 
terminate(int signum)190374f408SAnton Filimonov void terminate(int signum)
200374f408SAnton Filimonov {
210374f408SAnton Filimonov     if (g_staticSharedMemory) {
220374f408SAnton Filimonov         delete g_staticSharedMemory;
230374f408SAnton Filimonov     }
240374f408SAnton Filimonov     ::exit(128 + signum);
250374f408SAnton Filimonov }
260374f408SAnton Filimonov 
setCrashHandler(QSharedMemory * memory)270374f408SAnton Filimonov void setCrashHandler(QSharedMemory* memory)
280374f408SAnton Filimonov {
290374f408SAnton Filimonov     g_staticSharedMemory = memory;
300374f408SAnton Filimonov 
310374f408SAnton Filimonov     // Handle any further termination signals to ensure the
320374f408SAnton Filimonov     // QSharedMemory block is deleted even if the process crashes
330374f408SAnton Filimonov     signal(SIGSEGV, terminate);
340374f408SAnton Filimonov     signal(SIGABRT, terminate);
350374f408SAnton Filimonov     signal(SIGFPE,  terminate);
360374f408SAnton Filimonov     signal(SIGILL,  terminate);
370374f408SAnton Filimonov     signal(SIGINT,  terminate);
380374f408SAnton Filimonov     signal(SIGTERM, terminate);
390374f408SAnton Filimonov }
400374f408SAnton Filimonov 
410374f408SAnton Filimonov #endif
420374f408SAnton Filimonov 
SocketExternalInstance()430374f408SAnton Filimonov SocketExternalInstance::SocketExternalInstance()
440374f408SAnton Filimonov     : ExternalInstance(), memory_(new QSharedMemory(GLOG_SERVICE_NAME) )
450374f408SAnton Filimonov {
460374f408SAnton Filimonov     if ( !memory_->attach( QSharedMemory::ReadOnly ) ) {
47*2d1bee56SNicolas Bonnefon         LOG( logERROR ) << "attach failed!";
480374f408SAnton Filimonov         throw CantCreateExternalErr();
490374f408SAnton Filimonov     }
500374f408SAnton Filimonov 
510374f408SAnton Filimonov #ifdef Q_OS_UNIX
520374f408SAnton Filimonov         // Handle any further termination signals to ensure the
530374f408SAnton Filimonov         // QSharedMemory block is deleted even if the process crashes
540374f408SAnton Filimonov         setCrashHandler(memory_);
550374f408SAnton Filimonov #endif
560374f408SAnton Filimonov }
570374f408SAnton Filimonov 
loadFile(const QString & file_name) const580374f408SAnton Filimonov void SocketExternalInstance::loadFile(const QString &file_name) const
590374f408SAnton Filimonov {
600374f408SAnton Filimonov     QLocalSocket socket;
610374f408SAnton Filimonov     socket.connectToServer(GLOG_SERVICE_NAME);
620374f408SAnton Filimonov     if (!socket.waitForConnected(1000)) {
630374f408SAnton Filimonov         LOG( logERROR ) << "Failed to connect to socket";
640374f408SAnton Filimonov         return;
650374f408SAnton Filimonov     }
660374f408SAnton Filimonov 
670374f408SAnton Filimonov     socket.write(file_name.toUtf8());
680374f408SAnton Filimonov     if (!socket.waitForBytesWritten(1000)) {
690374f408SAnton Filimonov         LOG( logERROR ) << "Failed to send filename";
700374f408SAnton Filimonov     }
710374f408SAnton Filimonov 
720374f408SAnton Filimonov     socket.close();
730374f408SAnton Filimonov }
740374f408SAnton Filimonov 
getVersion() const750374f408SAnton Filimonov uint32_t SocketExternalInstance::getVersion() const
760374f408SAnton Filimonov {
770374f408SAnton Filimonov     return *reinterpret_cast<uint32_t*>(memory_->data());
780374f408SAnton Filimonov }
790374f408SAnton Filimonov 
SocketExternalCommunicator()800374f408SAnton Filimonov SocketExternalCommunicator::SocketExternalCommunicator()
810374f408SAnton Filimonov     : ExternalCommunicator()
820374f408SAnton Filimonov     , memory_(new QSharedMemory(GLOG_SERVICE_NAME))
830374f408SAnton Filimonov     , server_(new QLocalServer)
840374f408SAnton Filimonov {}
850374f408SAnton Filimonov 
~SocketExternalCommunicator()860374f408SAnton Filimonov SocketExternalCommunicator::~SocketExternalCommunicator()
870374f408SAnton Filimonov {
880374f408SAnton Filimonov     delete memory_;
890374f408SAnton Filimonov     server_->close();
900374f408SAnton Filimonov     delete server_;
910374f408SAnton Filimonov }
920374f408SAnton Filimonov 
startListening()930374f408SAnton Filimonov void SocketExternalCommunicator::startListening()
940374f408SAnton Filimonov {
950374f408SAnton Filimonov     if ( memory_->create(sizeof(qint32))) {
960374f408SAnton Filimonov #ifdef Q_OS_UNIX
970374f408SAnton Filimonov         // Handle any further termination signals to ensure the
980374f408SAnton Filimonov         // QSharedMemory block is deleted even if the process crashes
990374f408SAnton Filimonov         setCrashHandler(memory_);
1000374f408SAnton Filimonov #endif
1010374f408SAnton Filimonov 
1020374f408SAnton Filimonov         *reinterpret_cast<qint32*>(memory_->data()) = version();
1030374f408SAnton Filimonov         QLocalServer::removeServer(GLOG_SERVICE_NAME);
1040374f408SAnton Filimonov 
1050374f408SAnton Filimonov         connect(server_, SIGNAL(newConnection()), SLOT(onConnection()));
1060374f408SAnton Filimonov         server_->listen(GLOG_SERVICE_NAME);
1070374f408SAnton Filimonov     }
1080374f408SAnton Filimonov }
1090374f408SAnton Filimonov 
version() const1100374f408SAnton Filimonov qint32 SocketExternalCommunicator::version() const
1110374f408SAnton Filimonov {
1120374f408SAnton Filimonov     return 3;
1130374f408SAnton Filimonov }
1140374f408SAnton Filimonov 
otherInstance() const1150374f408SAnton Filimonov ExternalInstance* SocketExternalCommunicator::otherInstance() const
1160374f408SAnton Filimonov {
1170374f408SAnton Filimonov     try {
1180374f408SAnton Filimonov         return static_cast<ExternalInstance*>( new SocketExternalInstance() );
1190374f408SAnton Filimonov     }
1200374f408SAnton Filimonov     catch ( CantCreateExternalErr ) {
1210374f408SAnton Filimonov         LOG(logINFO) << "Cannot find external correspondant, we are the only glogg out there.";
1220374f408SAnton Filimonov         return nullptr;
1230374f408SAnton Filimonov     }
1240374f408SAnton Filimonov }
1250374f408SAnton Filimonov 
onConnection()1260374f408SAnton Filimonov void SocketExternalCommunicator::onConnection()
1270374f408SAnton Filimonov {
1280374f408SAnton Filimonov      QLocalSocket *socket = server_->nextPendingConnection();
1290374f408SAnton Filimonov      QByteArray data;
1300374f408SAnton Filimonov      while(socket->waitForReadyRead(100)) {
1310374f408SAnton Filimonov          data.append(socket->readAll());
1320374f408SAnton Filimonov      }
1330374f408SAnton Filimonov 
1340374f408SAnton Filimonov      socket->close();
1350374f408SAnton Filimonov 
1360374f408SAnton Filimonov      emit loadFile(QString::fromUtf8(data));
1370374f408SAnton Filimonov }
1380374f408SAnton Filimonov 
1390374f408SAnton Filimonov 
1400374f408SAnton Filimonov 
141