1*0374f408SAnton Filimonov #include "socketexternalcom.h" 2*0374f408SAnton Filimonov 3*0374f408SAnton Filimonov #include <QLocalServer> 4*0374f408SAnton Filimonov #include <QLocalSocket> 5*0374f408SAnton Filimonov #include <QSharedMemory> 6*0374f408SAnton Filimonov 7*0374f408SAnton Filimonov #ifdef Q_OS_UNIX 8*0374f408SAnton Filimonov #include <signal.h> 9*0374f408SAnton Filimonov #include <unistd.h> 10*0374f408SAnton Filimonov #endif 11*0374f408SAnton Filimonov 12*0374f408SAnton Filimonov #include "log.h" 13*0374f408SAnton Filimonov 14*0374f408SAnton Filimonov static const char* GLOG_SERVICE_NAME = "org.bonnefon.glogg"; 15*0374f408SAnton Filimonov 16*0374f408SAnton Filimonov #ifdef Q_OS_UNIX 17*0374f408SAnton Filimonov QSharedMemory* g_staticSharedMemory = nullptr; 18*0374f408SAnton Filimonov 19*0374f408SAnton Filimonov void terminate(int signum) 20*0374f408SAnton Filimonov { 21*0374f408SAnton Filimonov if (g_staticSharedMemory) { 22*0374f408SAnton Filimonov delete g_staticSharedMemory; 23*0374f408SAnton Filimonov } 24*0374f408SAnton Filimonov ::exit(128 + signum); 25*0374f408SAnton Filimonov } 26*0374f408SAnton Filimonov 27*0374f408SAnton Filimonov void setCrashHandler(QSharedMemory* memory) 28*0374f408SAnton Filimonov { 29*0374f408SAnton Filimonov g_staticSharedMemory = memory; 30*0374f408SAnton Filimonov 31*0374f408SAnton Filimonov // Handle any further termination signals to ensure the 32*0374f408SAnton Filimonov // QSharedMemory block is deleted even if the process crashes 33*0374f408SAnton Filimonov signal(SIGSEGV, terminate); 34*0374f408SAnton Filimonov signal(SIGABRT, terminate); 35*0374f408SAnton Filimonov signal(SIGFPE, terminate); 36*0374f408SAnton Filimonov signal(SIGILL, terminate); 37*0374f408SAnton Filimonov signal(SIGINT, terminate); 38*0374f408SAnton Filimonov signal(SIGTERM, terminate); 39*0374f408SAnton Filimonov } 40*0374f408SAnton Filimonov 41*0374f408SAnton Filimonov #endif 42*0374f408SAnton Filimonov 43*0374f408SAnton Filimonov SocketExternalInstance::SocketExternalInstance() 44*0374f408SAnton Filimonov : ExternalInstance(), memory_(new QSharedMemory(GLOG_SERVICE_NAME) ) 45*0374f408SAnton Filimonov { 46*0374f408SAnton Filimonov if ( !memory_->attach( QSharedMemory::ReadOnly ) ) { 47*0374f408SAnton Filimonov throw CantCreateExternalErr(); 48*0374f408SAnton Filimonov } 49*0374f408SAnton Filimonov 50*0374f408SAnton Filimonov #ifdef Q_OS_UNIX 51*0374f408SAnton Filimonov // Handle any further termination signals to ensure the 52*0374f408SAnton Filimonov // QSharedMemory block is deleted even if the process crashes 53*0374f408SAnton Filimonov setCrashHandler(memory_); 54*0374f408SAnton Filimonov #endif 55*0374f408SAnton Filimonov } 56*0374f408SAnton Filimonov 57*0374f408SAnton Filimonov void SocketExternalInstance::loadFile(const QString &file_name) const 58*0374f408SAnton Filimonov { 59*0374f408SAnton Filimonov QLocalSocket socket; 60*0374f408SAnton Filimonov socket.connectToServer(GLOG_SERVICE_NAME); 61*0374f408SAnton Filimonov if (!socket.waitForConnected(1000)) { 62*0374f408SAnton Filimonov LOG( logERROR ) << "Failed to connect to socket"; 63*0374f408SAnton Filimonov return; 64*0374f408SAnton Filimonov } 65*0374f408SAnton Filimonov 66*0374f408SAnton Filimonov socket.write(file_name.toUtf8()); 67*0374f408SAnton Filimonov if (!socket.waitForBytesWritten(1000)) { 68*0374f408SAnton Filimonov LOG( logERROR ) << "Failed to send filename"; 69*0374f408SAnton Filimonov } 70*0374f408SAnton Filimonov 71*0374f408SAnton Filimonov socket.close(); 72*0374f408SAnton Filimonov } 73*0374f408SAnton Filimonov 74*0374f408SAnton Filimonov uint32_t SocketExternalInstance::getVersion() const 75*0374f408SAnton Filimonov { 76*0374f408SAnton Filimonov return *reinterpret_cast<uint32_t*>(memory_->data()); 77*0374f408SAnton Filimonov } 78*0374f408SAnton Filimonov 79*0374f408SAnton Filimonov SocketExternalCommunicator::SocketExternalCommunicator() 80*0374f408SAnton Filimonov : ExternalCommunicator() 81*0374f408SAnton Filimonov , memory_(new QSharedMemory(GLOG_SERVICE_NAME)) 82*0374f408SAnton Filimonov , server_(new QLocalServer) 83*0374f408SAnton Filimonov {} 84*0374f408SAnton Filimonov 85*0374f408SAnton Filimonov SocketExternalCommunicator::~SocketExternalCommunicator() 86*0374f408SAnton Filimonov { 87*0374f408SAnton Filimonov delete memory_; 88*0374f408SAnton Filimonov server_->close(); 89*0374f408SAnton Filimonov delete server_; 90*0374f408SAnton Filimonov } 91*0374f408SAnton Filimonov 92*0374f408SAnton Filimonov void SocketExternalCommunicator::startListening() 93*0374f408SAnton Filimonov { 94*0374f408SAnton Filimonov if ( memory_->create(sizeof(qint32))) { 95*0374f408SAnton Filimonov #ifdef Q_OS_UNIX 96*0374f408SAnton Filimonov // Handle any further termination signals to ensure the 97*0374f408SAnton Filimonov // QSharedMemory block is deleted even if the process crashes 98*0374f408SAnton Filimonov setCrashHandler(memory_); 99*0374f408SAnton Filimonov #endif 100*0374f408SAnton Filimonov 101*0374f408SAnton Filimonov *reinterpret_cast<qint32*>(memory_->data()) = version(); 102*0374f408SAnton Filimonov QLocalServer::removeServer(GLOG_SERVICE_NAME); 103*0374f408SAnton Filimonov 104*0374f408SAnton Filimonov connect(server_, SIGNAL(newConnection()), SLOT(onConnection())); 105*0374f408SAnton Filimonov server_->listen(GLOG_SERVICE_NAME); 106*0374f408SAnton Filimonov } 107*0374f408SAnton Filimonov } 108*0374f408SAnton Filimonov 109*0374f408SAnton Filimonov qint32 SocketExternalCommunicator::version() const 110*0374f408SAnton Filimonov { 111*0374f408SAnton Filimonov return 3; 112*0374f408SAnton Filimonov } 113*0374f408SAnton Filimonov 114*0374f408SAnton Filimonov ExternalInstance* SocketExternalCommunicator::otherInstance() const 115*0374f408SAnton Filimonov { 116*0374f408SAnton Filimonov try { 117*0374f408SAnton Filimonov return static_cast<ExternalInstance*>( new SocketExternalInstance() ); 118*0374f408SAnton Filimonov } 119*0374f408SAnton Filimonov catch ( CantCreateExternalErr ) { 120*0374f408SAnton Filimonov LOG(logINFO) << "Cannot find external correspondant, we are the only glogg out there."; 121*0374f408SAnton Filimonov return nullptr; 122*0374f408SAnton Filimonov } 123*0374f408SAnton Filimonov } 124*0374f408SAnton Filimonov 125*0374f408SAnton Filimonov void SocketExternalCommunicator::onConnection() 126*0374f408SAnton Filimonov { 127*0374f408SAnton Filimonov QLocalSocket *socket = server_->nextPendingConnection(); 128*0374f408SAnton Filimonov QByteArray data; 129*0374f408SAnton Filimonov while(socket->waitForReadyRead(100)) { 130*0374f408SAnton Filimonov data.append(socket->readAll()); 131*0374f408SAnton Filimonov } 132*0374f408SAnton Filimonov 133*0374f408SAnton Filimonov socket->close(); 134*0374f408SAnton Filimonov 135*0374f408SAnton Filimonov emit loadFile(QString::fromUtf8(data)); 136*0374f408SAnton Filimonov } 137*0374f408SAnton Filimonov 138*0374f408SAnton Filimonov 139*0374f408SAnton Filimonov 140