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