26 #include <QDataStream> 36 #include "SignOn/blobiohandler.h" 37 #include "SignOn/ipc.h" 47 RemotePluginProcess::RemotePluginProcess(QObject *parent):
51 m_readnotifier = NULL;
54 qRegisterMetaType<SignOn::SessionData>(
"SignOn::SessionData");
55 qRegisterMetaType<QString>(
"QString");
61 delete m_readnotifier;
81 rpp->m_plugin->type() != type) {
90 TRACE() <<
" loading auth library for " << type;
92 QLibrary lib(getPluginName(type));
95 qCritical() << QString(
"Failed to load %1 (reason: %2)")
96 .arg(getPluginName(type)).arg(lib.errorString());
100 TRACE() <<
"library loaded";
102 typedef AuthPluginInterface* (*SsoAuthPluginInstanceF)();
103 SsoAuthPluginInstanceF instance =
104 (SsoAuthPluginInstanceF)lib.resolve(
"auth_plugin_instance");
106 qCritical() << QString(
"Failed to resolve init function in %1 " 108 .arg(getPluginName(type)).arg(lib.errorString());
112 TRACE() <<
"constructor resolved";
114 m_plugin = qobject_cast<AuthPluginInterface *>(instance());
117 qCritical() << QString(
"Failed to cast object for %1 type")
122 connect(m_plugin, SIGNAL(result(
const SignOn::SessionData&)),
123 this, SLOT(result(
const SignOn::SessionData&)));
125 connect(m_plugin, SIGNAL(store(
const SignOn::SessionData&)),
126 this, SLOT(store(
const SignOn::SessionData&)));
128 connect(m_plugin, SIGNAL(error(
const SignOn::Error &)),
129 this, SLOT(error(
const SignOn::Error &)));
131 connect(m_plugin, SIGNAL(userActionRequired(
const SignOn::UiSessionData&)),
132 this, SLOT(userActionRequired(
const SignOn::UiSessionData&)));
134 connect(m_plugin, SIGNAL(refreshed(
const SignOn::UiSessionData&)),
135 this, SLOT(refreshed(
const SignOn::UiSessionData&)));
138 SIGNAL(statusChanged(
const AuthPluginState,
const QString&)),
139 this, SLOT(statusChanged(
const AuthPluginState,
const QString&)));
141 m_plugin->setParent(
this);
143 TRACE() <<
"plugin is fully initialized";
151 m_inFile.open(STDIN_FILENO, QIODevice::ReadOnly);
152 m_outFile.open(STDOUT_FILENO, QIODevice::WriteOnly);
154 m_readnotifier =
new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read);
155 m_errnotifier =
new QSocketNotifier(STDIN_FILENO,
156 QSocketNotifier::Exception);
158 connect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
159 connect(m_errnotifier, SIGNAL(activated(
int)),
165 TRACE() <<
"cancel thread created";
167 m_blobIOHandler =
new BlobIOHandler(&m_inFile, &m_outFile,
this);
169 connect(m_blobIOHandler,
170 SIGNAL(dataReceived(
const QVariantMap &)),
174 connect(m_blobIOHandler,
177 SLOT(blobIOError()));
179 m_blobIOHandler->setReadChannelSocketNotifier(m_readnotifier);
193 QNetworkProxyFactory::setApplicationProxyFactory(proxyFactory);
199 void RemotePluginProcess::blobIOError()
202 Error(Error::InternalServer,
203 QLatin1String(
"Failed to I/O session data to/from the signon daemon.")));
204 connect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
207 void RemotePluginProcess::result(
const SignOn::SessionData &data)
209 disableCancelThread();
210 QDataStream out(&m_outFile);
211 QVariantMap resultDataMap;
213 foreach(QString key, data.propertyNames())
214 resultDataMap[key] = data.getProperty(key);
216 out << (quint32)PLUGIN_RESPONSE_RESULT;
218 m_blobIOHandler->sendData(resultDataMap);
223 void RemotePluginProcess::store(
const SignOn::SessionData &data)
225 QDataStream out(&m_outFile);
226 QVariantMap storeDataMap;
228 foreach(QString key, data.propertyNames())
229 storeDataMap[key] = data.getProperty(key);
231 out << (quint32)PLUGIN_RESPONSE_STORE;
233 m_blobIOHandler->sendData(storeDataMap);
238 void RemotePluginProcess::error(
const SignOn::Error &err)
240 disableCancelThread();
242 QDataStream out(&m_outFile);
244 out << (quint32)PLUGIN_RESPONSE_ERROR;
245 out << (quint32)err.type();
246 out << err.message();
249 TRACE() <<
"error is sent" << err.type() <<
" " << err.message();
252 void RemotePluginProcess::userActionRequired(
const SignOn::UiSessionData &data)
255 disableCancelThread();
257 QDataStream out(&m_outFile);
258 QVariantMap resultDataMap;
260 foreach(QString key, data.propertyNames())
261 resultDataMap[key] = data.getProperty(key);
263 out << (quint32)PLUGIN_RESPONSE_UI;
264 m_blobIOHandler->sendData(resultDataMap);
268 void RemotePluginProcess::refreshed(
const SignOn::UiSessionData &data)
271 disableCancelThread();
273 QDataStream out(&m_outFile);
274 QVariantMap resultDataMap;
276 foreach(QString key, data.propertyNames())
277 resultDataMap[key] = data.getProperty(key);
279 m_readnotifier->setEnabled(
true);
281 out << (quint32)PLUGIN_RESPONSE_REFRESHED;
283 m_blobIOHandler->sendData(resultDataMap);
288 void RemotePluginProcess::statusChanged(
const AuthPluginState state,
289 const QString &message)
292 QDataStream out(&m_outFile);
294 out << (quint32)PLUGIN_RESPONSE_SIGNAL;
295 out << (quint32)state;
301 QString RemotePluginProcess::getPluginName(
const QString &type)
303 QString dirName = qgetenv(
"SSO_PLUGINS_DIR");
304 if (dirName.isEmpty())
306 QString fileName = dirName +
315 void RemotePluginProcess::type()
317 QDataStream out(&m_outFile);
318 out << m_plugin->type();
321 void RemotePluginProcess::mechanisms()
323 QDataStream out(&m_outFile);
324 QStringList mechanisms = m_plugin->mechanisms();
325 QVariant mechsVar = mechanisms;
329 void RemotePluginProcess::process()
331 QDataStream in(&m_inFile);
334 in >> m_currentMechanism;
336 int processBlobSize = -1;
337 in >> processBlobSize;
339 disconnect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
341 m_currentOperation = PLUGIN_OP_PROCESS;
342 m_blobIOHandler->receiveData(processBlobSize);
345 void RemotePluginProcess::userActionFinished()
347 QDataStream in(&m_inFile);
348 int processBlobSize = -1;
349 in >> processBlobSize;
351 disconnect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
353 m_currentOperation = PLUGIN_OP_PROCESS_UI;
354 m_blobIOHandler->receiveData(processBlobSize);
357 void RemotePluginProcess::refresh()
359 QDataStream in(&m_inFile);
360 int processBlobSize = -1;
361 in >> processBlobSize;
363 disconnect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
365 m_currentOperation = PLUGIN_OP_REFRESH;
366 m_blobIOHandler->receiveData(processBlobSize);
371 enableCancelThread();
372 TRACE() <<
"The cancel thread is started";
374 if (m_currentOperation == PLUGIN_OP_PROCESS) {
375 SessionData inData(sessionDataMap);
376 m_plugin->process(inData, m_currentMechanism);
377 m_currentMechanism.clear();
379 }
else if(m_currentOperation == PLUGIN_OP_PROCESS_UI) {
380 UiSessionData inData(sessionDataMap);
381 m_plugin->userActionFinished(inData);
383 }
else if(m_currentOperation == PLUGIN_OP_REFRESH) {
384 UiSessionData inData(sessionDataMap);
385 m_plugin->refresh(inData);
388 TRACE() <<
"Wrong operation code.";
389 error(Error(Error::InternalServer,
390 QLatin1String(
"Plugin process - invalid operation code.")));
393 m_currentOperation = PLUGIN_OP_STOP;
394 connect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
397 void RemotePluginProcess::enableCancelThread()
400 connect(cancelThread,
405 m_readnotifier->setEnabled(
false);
406 QTimer::singleShot(0.5*1000, &loop, SLOT(quit()));
407 cancelThread->start();
409 QThread::yieldCurrentThread();
412 void RemotePluginProcess::disableCancelThread()
414 if (!cancelThread->isRunning())
423 cancelThread->quit();
425 TRACE() <<
"Before the isFinished loop ";
428 while (!cancelThread->isFinished()) {
429 cancelThread->quit();
430 TRACE() <<
"Internal iteration " << i++;
431 usleep(0.005 * 1000000);
434 if (!cancelThread->wait(500)) {
435 BLAME() <<
"Cannot disable cancel thread";
437 for (i = 0; i < 5; i++) {
438 usleep(0.01 * 1000000);
439 if (cancelThread->wait(500))
444 BLAME() <<
"Cannot do anything with cancel thread";
445 cancelThread->terminate();
446 cancelThread->wait();
450 m_readnotifier->setEnabled(
true);
455 quint32 opcode = PLUGIN_OP_STOP;
456 bool is_stopped =
false;
458 QDataStream in(&m_inFile);
462 case PLUGIN_OP_CANCEL:
464 m_plugin->cancel();
break;
473 case PLUGIN_OP_MECHANISMS:
476 case PLUGIN_OP_PROCESS:
479 case PLUGIN_OP_PROCESS_UI:
480 userActionFinished();
482 case PLUGIN_OP_REFRESH:
490 qCritical() <<
" unknown operation code: " << opcode;
496 TRACE() <<
"operation is completed";
499 if (!m_outFile.flush())
513 m_cancelNotifier = 0;
518 delete m_cancelNotifier;
523 if (!m_cancelNotifier) {
524 m_cancelNotifier =
new QSocketNotifier(STDIN_FILENO,
525 QSocketNotifier::Read);
526 connect(m_cancelNotifier, SIGNAL(activated(
int)),
527 this, SLOT(cancel()), Qt::DirectConnection);
530 m_cancelNotifier->setEnabled(
true);
532 m_cancelNotifier->setEnabled(
false);
541 if (!(n = read(STDIN_FILENO, buf, 4))) {
542 qCritical() <<
"Cannot read from cancel socket";
549 QByteArray ba(buf, 4);
554 if (opcode != PLUGIN_OP_CANCEL)
555 qCritical() <<
"wrong operation code: breakage of remotepluginprocess " 556 "threads synchronization: " << opcode;
bool setupProxySettings()
#define SIGNON_PLUGIN_SUFFIX
void sessionDataReceived(const QVariantMap &sessionDataMap)
static RemotePluginProcess * createRemotePluginProcess(QString &type, QObject *parent)
bool loadPlugin(QString &type)
Thread to enable cancel functionality.
Class to execute plugin process.
#define SIGNON_PLUGIN_PREFIX
RemotePluginProcess(QObject *parent)
#define SIGNOND_PLUGINS_DIR
CancelEventThread(AuthPluginInterface *plugin)