xref: /glogg/src/socketexternalcom.cpp (revision 0374f408d6901d76d0f8276791479179a8fc215d)
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