22 #include <QNetworkProxy>
27 #include <QDataStream>
31 #include <gq/GConfItem>
38 #include "SignOn/blobiohandler.h"
39 #include "SignOn/ipc.h"
41 using namespace SignOn;
43 namespace RemotePluginProcessNS {
49 RemotePluginProcess::RemotePluginProcess(QObject *parent):
53 m_readnotifier = NULL;
56 qRegisterMetaType<SignOn::SessionData>(
"SignOn::SessionData");
57 qRegisterMetaType<QString>(
"QString");
63 delete m_readnotifier;
83 rpp->m_plugin->type() != type) {
92 TRACE() <<
" loading auth library for " << type;
94 QLibrary lib(getPluginName(type));
97 qCritical() << QString(
"Failed to load %1 (reason: %2)")
98 .arg(getPluginName(type)).arg(lib.errorString());
102 TRACE() <<
"library loaded";
104 typedef AuthPluginInterface* (*SsoAuthPluginInstanceF)();
105 SsoAuthPluginInstanceF instance =
106 (SsoAuthPluginInstanceF)lib.resolve(
"auth_plugin_instance");
108 qCritical() << QString(
"Failed to resolve init function in %1 "
110 .arg(getPluginName(type)).arg(lib.errorString());
114 TRACE() <<
"constructor resolved";
116 m_plugin = qobject_cast<AuthPluginInterface *>(instance());
119 qCritical() << QString(
"Failed to cast object for %1 type")
124 connect(m_plugin, SIGNAL(result(
const SignOn::SessionData&)),
125 this, SLOT(result(
const SignOn::SessionData&)));
127 connect(m_plugin, SIGNAL(store(
const SignOn::SessionData&)),
128 this, SLOT(store(
const SignOn::SessionData&)));
130 connect(m_plugin, SIGNAL(error(
const SignOn::Error &)),
131 this, SLOT(error(
const SignOn::Error &)));
133 connect(m_plugin, SIGNAL(userActionRequired(
const SignOn::UiSessionData&)),
134 this, SLOT(userActionRequired(
const SignOn::UiSessionData&)));
136 connect(m_plugin, SIGNAL(refreshed(
const SignOn::UiSessionData&)),
137 this, SLOT(refreshed(
const SignOn::UiSessionData&)));
140 SIGNAL(statusChanged(
const AuthPluginState,
const QString&)),
141 this, SLOT(statusChanged(
const AuthPluginState,
const QString&)));
143 m_plugin->setParent(
this);
145 TRACE() <<
"plugin is fully initialized";
153 m_inFile.open(STDIN_FILENO, QIODevice::ReadOnly);
154 m_outFile.open(STDOUT_FILENO, QIODevice::WriteOnly);
156 m_readnotifier =
new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read);
157 m_errnotifier =
new QSocketNotifier(STDIN_FILENO,
158 QSocketNotifier::Exception);
160 connect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
161 connect(m_errnotifier, SIGNAL(activated(
int)),
167 TRACE() <<
"cancel thread created";
169 m_blobIOHandler =
new BlobIOHandler(&m_inFile, &m_outFile,
this);
171 connect(m_blobIOHandler,
172 SIGNAL(dataReceived(
const QVariantMap &)),
176 connect(m_blobIOHandler,
179 SLOT(blobIOError()));
181 m_blobIOHandler->setReadChannelSocketNotifier(m_readnotifier);
190 QNetworkProxy networkProxy = QNetworkProxy::applicationProxy();
194 GConfItem *hostItem =
new GConfItem(
"/system/http_proxy/host");
195 if (hostItem->value().canConvert(QVariant::String)) {
196 QString host = hostItem->value().toString();
197 GConfItem *portItem =
new GConfItem(
"/system/http_proxy/port");
198 uint port = portItem->value().toUInt();
199 networkProxy = QNetworkProxy(QNetworkProxy::HttpProxy,
207 QString proxy = qgetenv(
"http_proxy");
208 if (!proxy.isEmpty()) {
209 QUrl proxyUrl(proxy);
210 if (!proxyUrl.host().isEmpty()) {
211 networkProxy = QNetworkProxy(QNetworkProxy::HttpProxy,
215 proxyUrl.password());
221 TRACE() << networkProxy.hostName() <<
":" << networkProxy.port();
222 QNetworkProxy::setApplicationProxy(networkProxy);
226 void RemotePluginProcess::blobIOError()
229 Error(Error::InternalServer,
230 QLatin1String(
"Failed to I/O session data to/from the signon daemon.")));
231 connect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
234 void RemotePluginProcess::result(
const SignOn::SessionData &data)
236 disableCancelThread();
237 QDataStream out(&m_outFile);
238 QVariantMap resultDataMap;
240 foreach(QString key, data.propertyNames())
241 resultDataMap[key] = data.getProperty(key);
243 out << (quint32)PLUGIN_RESPONSE_RESULT;
245 m_blobIOHandler->sendData(resultDataMap);
250 void RemotePluginProcess::store(
const SignOn::SessionData &data)
252 QDataStream out(&m_outFile);
253 QVariantMap storeDataMap;
255 foreach(QString key, data.propertyNames())
256 storeDataMap[key] = data.getProperty(key);
258 out << (quint32)PLUGIN_RESPONSE_STORE;
260 m_blobIOHandler->sendData(storeDataMap);
265 void RemotePluginProcess::error(
const SignOn::Error &err)
267 disableCancelThread();
269 QDataStream out(&m_outFile);
271 out << (quint32)PLUGIN_RESPONSE_ERROR;
272 out << (quint32)err.type();
273 out << err.message();
276 TRACE() <<
"error is sent" << err.type() <<
" " << err.message();
279 void RemotePluginProcess::userActionRequired(
const SignOn::UiSessionData &data)
282 disableCancelThread();
284 QDataStream out(&m_outFile);
285 QVariantMap resultDataMap;
287 foreach(QString key, data.propertyNames())
288 resultDataMap[key] = data.getProperty(key);
290 out << (quint32)PLUGIN_RESPONSE_UI;
291 m_blobIOHandler->sendData(resultDataMap);
295 void RemotePluginProcess::refreshed(
const SignOn::UiSessionData &data)
298 disableCancelThread();
300 QDataStream out(&m_outFile);
301 QVariantMap resultDataMap;
303 foreach(QString key, data.propertyNames())
304 resultDataMap[key] = data.getProperty(key);
306 m_readnotifier->setEnabled(
true);
308 out << (quint32)PLUGIN_RESPONSE_REFRESHED;
310 m_blobIOHandler->sendData(resultDataMap);
315 void RemotePluginProcess::statusChanged(
const AuthPluginState state,
316 const QString &message)
319 QDataStream out(&m_outFile);
321 out << (quint32)PLUGIN_RESPONSE_SIGNAL;
322 out << (quint32)state;
328 QString RemotePluginProcess::getPluginName(
const QString &type)
330 QString dirName = qgetenv(
"SSO_PLUGINS_DIR");
331 if (dirName.isEmpty())
333 QString fileName = dirName +
342 void RemotePluginProcess::type()
344 QDataStream out(&m_outFile);
345 out << m_plugin->type();
348 void RemotePluginProcess::mechanisms()
350 QDataStream out(&m_outFile);
351 QStringList mechanisms = m_plugin->mechanisms();
352 QVariant mechsVar = mechanisms;
356 void RemotePluginProcess::process()
358 QDataStream in(&m_inFile);
361 in >> m_currentMechanism;
363 int processBlobSize = -1;
364 in >> processBlobSize;
366 disconnect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
368 m_currentOperation = PLUGIN_OP_PROCESS;
369 m_blobIOHandler->receiveData(processBlobSize);
372 void RemotePluginProcess::userActionFinished()
374 QDataStream in(&m_inFile);
375 int processBlobSize = -1;
376 in >> processBlobSize;
378 disconnect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
380 m_currentOperation = PLUGIN_OP_PROCESS_UI;
381 m_blobIOHandler->receiveData(processBlobSize);
384 void RemotePluginProcess::refresh()
386 QDataStream in(&m_inFile);
387 int processBlobSize = -1;
388 in >> processBlobSize;
390 disconnect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
392 m_currentOperation = PLUGIN_OP_REFRESH;
393 m_blobIOHandler->receiveData(processBlobSize);
398 enableCancelThread();
399 TRACE() <<
"The cancel thread is started";
401 if (m_currentOperation == PLUGIN_OP_PROCESS) {
402 SessionData inData(sessionDataMap);
403 m_plugin->process(inData, m_currentMechanism);
404 m_currentMechanism.clear();
406 }
else if(m_currentOperation == PLUGIN_OP_PROCESS_UI) {
407 UiSessionData inData(sessionDataMap);
408 m_plugin->userActionFinished(inData);
410 }
else if(m_currentOperation == PLUGIN_OP_REFRESH) {
411 UiSessionData inData(sessionDataMap);
412 m_plugin->refresh(inData);
415 TRACE() <<
"Wrong operation code.";
416 error(Error(Error::InternalServer,
417 QLatin1String(
"Plugin process - invalid operation code.")));
420 m_currentOperation = PLUGIN_OP_STOP;
421 connect(m_readnotifier, SIGNAL(activated(
int)),
this, SLOT(
startTask()));
424 void RemotePluginProcess::enableCancelThread()
427 connect(cancelThread,
432 m_readnotifier->setEnabled(
false);
433 QTimer::singleShot(0.5*1000, &loop, SLOT(quit()));
434 cancelThread->start();
436 QThread::yieldCurrentThread();
439 void RemotePluginProcess::disableCancelThread()
441 if (!cancelThread->isRunning())
450 cancelThread->quit();
452 TRACE() <<
"Before the isFinished loop ";
455 while (!cancelThread->isFinished()) {
456 cancelThread->quit();
457 TRACE() <<
"Internal iteration " << i++;
458 usleep(0.005 * 1000000);
461 if (!cancelThread->wait(500)) {
462 BLAME() <<
"Cannot disable cancel thread";
464 for (i = 0; i < 5; i++) {
465 usleep(0.01 * 1000000);
466 if (cancelThread->wait(500))
471 BLAME() <<
"Cannot do anything with cancel thread";
472 cancelThread->terminate();
473 cancelThread->wait();
477 m_readnotifier->setEnabled(
true);
482 quint32 opcode = PLUGIN_OP_STOP;
483 bool is_stopped =
false;
485 QDataStream in(&m_inFile);
489 case PLUGIN_OP_CANCEL:
491 m_plugin->cancel();
break;
500 case PLUGIN_OP_MECHANISMS:
503 case PLUGIN_OP_PROCESS:
506 case PLUGIN_OP_PROCESS_UI:
507 userActionFinished();
509 case PLUGIN_OP_REFRESH:
517 qCritical() <<
" unknown operation code: " << opcode;
523 TRACE() <<
"operation is completed";
526 if (!m_outFile.flush())
540 m_cancelNotifier = 0;
545 delete m_cancelNotifier;
550 if (!m_cancelNotifier) {
551 m_cancelNotifier =
new QSocketNotifier(STDIN_FILENO,
552 QSocketNotifier::Read);
553 connect(m_cancelNotifier, SIGNAL(activated(
int)),
554 this, SLOT(
cancel()), Qt::DirectConnection);
557 m_cancelNotifier->setEnabled(
true);
559 m_cancelNotifier->setEnabled(
false);
568 if (!(n = read(STDIN_FILENO, buf, 4))) {
569 qCritical() <<
"Cannot read from cancel socket";
576 QByteArray ba(buf, 4);
581 if (opcode != PLUGIN_OP_CANCEL)
582 qCritical() <<
"wrong operation code: breakage of remotepluginprocess "
583 "threads synchronization: " << opcode;