• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kio
slave.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the KDE libraries
3 * Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
4 * 2000 Stephan Kulow <coolo@kde.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License version 2 as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 **/
20
21#include "slave.h"
22
23#include <time.h>
24#include <errno.h>
25#include <unistd.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <signal.h>
29#include <sys/types.h>
30
31#include <QtCore/QFile>
32#include <QtCore/QTimer>
33#include <QtDBus/QtDBus>
34#include <QtCore/QProcess>
35
36#include <kdebug.h>
37#include <klocale.h>
38#include <kglobal.h>
39#include <kstandarddirs.h>
40#include <ktoolinvocation.h>
41#include <klauncher_iface.h>
42#include <klibrary.h>
43
44#include "dataprotocol.h"
45#include "kservice.h"
46#include <kio/global.h>
47#include "kio/connection.h"
48#include <kprotocolinfo.h>
49
50#include "slaveinterface_p.h"
51
52using namespace KIO;
53
54#define SLAVE_CONNECTION_TIMEOUT_MIN 2
55
56// Without debug info we consider it an error if the slave doesn't connect
57// within 10 seconds.
58// With debug info we give the slave an hour so that developers have a chance
59// to debug their slave.
60#ifdef NDEBUG
61#define SLAVE_CONNECTION_TIMEOUT_MAX 10
62#else
63#define SLAVE_CONNECTION_TIMEOUT_MAX 3600
64#endif
65
66namespace KIO {
67
71 class SlavePrivate: public SlaveInterfacePrivate
72 {
73 public:
74 SlavePrivate(const QString &protocol) :
75 m_protocol(protocol),
76 m_slaveProtocol(protocol),
77 slaveconnserver(new KIO::ConnectionServer),
78 m_job(0),
79 m_pid(0),
80 m_port(0),
81 contacted(false),
82 dead(false),
83 contact_started(time(0)),
84 m_idleSince(0),
85 m_refCount(1)
86 {
87 slaveconnserver->listenForRemote();
88 if ( !slaveconnserver->isListening() )
89 kWarning() << "Connection server not listening, could not connect";
90 }
91 ~SlavePrivate()
92 {
93 delete slaveconnserver;
94 }
95
96 QString m_protocol;
97 QString m_slaveProtocol;
98 QString m_host;
99 QString m_user;
100 QString m_passwd;
101 KIO::ConnectionServer *slaveconnserver;
102 KIO::SimpleJob *m_job;
103 pid_t m_pid;
104 quint16 m_port;
105 bool contacted;
106 bool dead;
107 time_t contact_started;
108 time_t m_idleSince;
109 int m_refCount;
110 };
111}
112
113void Slave::accept()
114{
115 Q_D(Slave);
116 d->slaveconnserver->setNextPendingConnection(d->connection);
117 d->slaveconnserver->deleteLater();
118 d->slaveconnserver = 0;
119
120 connect(d->connection, SIGNAL(readyRead()), SLOT(gotInput()));
121}
122
123void Slave::timeout()
124{
125 Q_D(Slave);
126 if (d->dead) //already dead? then slaveDied was emitted and we are done
127 return;
128 if (d->connection->isConnected())
129 return;
130
131 kDebug(7002) << "slave failed to connect to application pid=" << d->m_pid
132 << " protocol=" << d->m_protocol;
133 if (d->m_pid && (::kill(d->m_pid, 0) == 0))
134 {
135 int delta_t = (int) difftime(time(0), d->contact_started);
136 kDebug(7002) << "slave is slow... pid=" << d->m_pid << " t=" << delta_t;
137 if (delta_t < SLAVE_CONNECTION_TIMEOUT_MAX)
138 {
139 QTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, this, SLOT(timeout()));
140 return;
141 }
142 }
143 kDebug(7002) << "Houston, we lost our slave, pid=" << d->m_pid;
144 d->connection->close();
145 d->dead = true;
146 QString arg = d->m_protocol;
147 if (!d->m_host.isEmpty())
148 arg += "://"+d->m_host;
149 kDebug(7002) << "slave died pid = " << d->m_pid;
150
151 ref();
152 // Tell the job about the problem.
153 emit error(ERR_SLAVE_DIED, arg);
154 // Tell the scheduler about the problem.
155 emit slaveDied(this);
156 // After the above signal we're dead!!
157 deref();
158}
159
160Slave::Slave(const QString &protocol, QObject *parent)
161 : SlaveInterface(*new SlavePrivate(protocol), parent)
162{
163 Q_D(Slave);
164 d->slaveconnserver->setParent(this);
165 d->connection = new Connection(this);
166 connect(d->slaveconnserver, SIGNAL(newConnection()), SLOT(accept()));
167}
168
169Slave::~Slave()
170{
171 // kDebug(7002) << "destructing slave object pid = " << d->m_pid;
172 //delete d;
173}
174
175QString Slave::protocol()
176{
177 Q_D(Slave);
178 return d->m_protocol;
179}
180
181void Slave::setProtocol(const QString & protocol)
182{
183 Q_D(Slave);
184 d->m_protocol = protocol;
185}
186
187QString Slave::slaveProtocol()
188{
189 Q_D(Slave);
190 return d->m_slaveProtocol;
191}
192
193QString Slave::host()
194{
195 Q_D(Slave);
196 return d->m_host;
197}
198
199quint16 Slave::port()
200{
201 Q_D(Slave);
202 return d->m_port;
203}
204
205QString Slave::user()
206{
207 Q_D(Slave);
208 return d->m_user;
209}
210
211QString Slave::passwd()
212{
213 Q_D(Slave);
214 return d->m_passwd;
215}
216
217void Slave::setIdle()
218{
219 Q_D(Slave);
220 d->m_idleSince = time(0);
221}
222
223bool Slave::isConnected()
224{
225 Q_D(Slave);
226 return d->contacted;
227}
228
229void Slave::setConnected(bool c)
230{
231 Q_D(Slave);
232 d->contacted = c;
233}
234
235void Slave::ref()
236{
237 Q_D(Slave);
238 d->m_refCount++;
239}
240
241void Slave::deref()
242{
243 Q_D(Slave);
244 d->m_refCount--;
245 if (!d->m_refCount) {
246 d->connection->disconnect(this);
247 this->disconnect();
248 deleteLater();
249 }
250}
251
252time_t Slave::idleTime()
253{
254 Q_D(Slave);
255 if (!d->m_idleSince) {
256 return time_t(0);
257 }
258 return time_t(difftime(time(0), d->m_idleSince));
259}
260
261void Slave::setPID(pid_t pid)
262{
263 Q_D(Slave);
264 d->m_pid = pid;
265}
266
267int Slave::slave_pid()
268{
269 Q_D(Slave);
270 return d->m_pid;
271}
272
273void Slave::setJob(KIO::SimpleJob *job)
274{
275 Q_D(Slave);
276 if (!d->sslMetaData.isEmpty()) {
277 emit metaData(d->sslMetaData);
278 }
279 d->m_job = job;
280}
281
282KIO::SimpleJob *Slave::job() const
283{
284 Q_D(const Slave);
285 return d->m_job;
286}
287
288bool Slave::isAlive()
289{
290 Q_D(Slave);
291 return !d->dead;
292}
293
294void Slave::hold(const KUrl &url)
295{
296 Q_D(Slave);
297 ref();
298 {
299 QByteArray data;
300 QDataStream stream( &data, QIODevice::WriteOnly );
301 stream << url;
302 d->connection->send( CMD_SLAVE_HOLD, data );
303 d->connection->close();
304 d->dead = true;
305 emit slaveDied(this);
306 }
307 deref();
308 // Call KLauncher::waitForSlave(pid);
309 {
310 KToolInvocation::klauncher()->waitForSlave(d->m_pid);
311 }
312}
313
314void Slave::suspend()
315{
316 Q_D(Slave);
317 d->connection->suspend();
318}
319
320void Slave::resume()
321{
322 Q_D(Slave);
323 d->connection->resume();
324}
325
326bool Slave::suspended()
327{
328 Q_D(Slave);
329 return d->connection->suspended();
330}
331
332void Slave::send(int cmd, const QByteArray &arr)
333{
334 Q_D(Slave);
335 d->connection->send(cmd, arr);
336}
337
338void Slave::gotInput()
339{
340 Q_D(Slave);
341 if (d->dead) //already dead? then slaveDied was emitted and we are done
342 return;
343 ref();
344 if (!dispatch())
345 {
346 d->connection->close();
347 d->dead = true;
348 QString arg = d->m_protocol;
349 if (!d->m_host.isEmpty())
350 arg += "://"+d->m_host;
351 kDebug(7002) << "slave died pid = " << d->m_pid;
352 // Tell the job about the problem.
353 emit error(ERR_SLAVE_DIED, arg);
354 // Tell the scheduler about the problem.
355 emit slaveDied(this);
356 }
357 deref();
358 // Here we might be dead!!
359}
360
361void Slave::kill()
362{
363 Q_D(Slave);
364 d->dead = true; // OO can be such simple.
365 kDebug(7002) << "killing slave pid" << d->m_pid
366 << "(" << QString(d->m_protocol) + "://" + d->m_host << ")";
367 if (d->m_pid)
368 {
369#ifndef _WIN32_WCE
370 ::kill(d->m_pid, SIGTERM);
371#else
372 ::kill(d->m_pid, SIGKILL);
373#endif
374 d->m_pid = 0;
375 }
376}
377
378void Slave::setHost( const QString &host, quint16 port,
379 const QString &user, const QString &passwd)
380{
381 Q_D(Slave);
382 d->m_host = host;
383 d->m_port = port;
384 d->m_user = user;
385 d->m_passwd = passwd;
386 d->sslMetaData.clear();
387
388 QByteArray data;
389 QDataStream stream( &data, QIODevice::WriteOnly );
390 stream << d->m_host << d->m_port << d->m_user << d->m_passwd;
391 d->connection->send( CMD_HOST, data );
392}
393
394void Slave::resetHost()
395{
396 Q_D(Slave);
397 d->sslMetaData.clear();
398 d->m_host = "<reset>";
399}
400
401void Slave::setConfig(const MetaData &config)
402{
403 Q_D(Slave);
404 QByteArray data;
405 QDataStream stream( &data, QIODevice::WriteOnly );
406 stream << config;
407 d->connection->send( CMD_CONFIG, data );
408}
409
410Slave* Slave::createSlave( const QString &protocol, const KUrl& url, int& error, QString& error_text )
411{
412 kDebug(7002) << "createSlave" << protocol << "for" << url;
413 // Firstly take into account all special slaves
414 if (protocol == "data")
415 return new DataProtocol();
416 Slave *slave = new Slave(protocol);
417 QString slaveAddress = slave->d_func()->slaveconnserver->address();
418
419#ifdef Q_OS_UNIX
420 // In such case we start the slave via QProcess.
421 // It's possible to force this by setting the env. variable
422 // KDE_FORK_SLAVES, Clearcase seems to require this.
423 static bool bForkSlaves = !qgetenv("KDE_FORK_SLAVES").isEmpty();
424
425 if (!bForkSlaves)
426 {
427 // check the UID of klauncher
428 QDBusReply<uint> reply = QDBusConnection::sessionBus().interface()->serviceUid(KToolInvocation::klauncher()->service());
429 if (reply.isValid() && getuid() != reply)
430 bForkSlaves = true;
431 }
432
433 if (bForkSlaves)
434 {
435 QString _name = KProtocolInfo::exec(protocol);
436 if (_name.isEmpty())
437 {
438 error_text = i18n("Unknown protocol '%1'.", protocol);
439 error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
440 delete slave;
441 return 0;
442 }
443 KLibrary lib(_name, KGlobal::mainComponent());
444 QString lib_path = lib.fileName();
445 if (lib_path.isEmpty())
446 {
447 error_text = i18n("Can not find io-slave for protocol '%1'.", protocol);
448 error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
449 delete slave;
450 return 0;
451 }
452
453 const QStringList args = QStringList() << lib_path << protocol << "" << slaveAddress;
454 kDebug() << "kioslave" << ", " << lib_path << ", " << protocol << ", " << QString() << ", " << slaveAddress;
455
456 QProcess::startDetached( KStandardDirs::locate("exe", "kioslave"), args );
457
458 return slave;
459 }
460#endif
461
462 org::kde::KLauncher* klauncher = KToolInvocation::klauncher();
463 QString errorStr;
464 QDBusReply<int> reply = klauncher->requestSlave(protocol, url.host(), slaveAddress, errorStr);
465 if (!reply.isValid()) {
466 error_text = i18n("Cannot talk to klauncher: %1", klauncher->lastError().message() );
467 error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
468 delete slave;
469 return 0;
470 }
471 pid_t pid = reply;
472 if (!pid)
473 {
474 error_text = i18n("Unable to create io-slave:\nklauncher said: %1", errorStr);
475 error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
476 delete slave;
477 return 0;
478 }
479 slave->setPID(pid);
480 QTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, slave, SLOT(timeout()));
481 return slave;
482}
483
484Slave* Slave::holdSlave( const QString &protocol, const KUrl& url )
485{
486 //kDebug(7002) << "holdSlave" << protocol << "for" << url;
487 // Firstly take into account all special slaves
488 if (protocol == "data")
489 return 0;
490 Slave *slave = new Slave(protocol);
491 QString slaveAddress = slave->d_func()->slaveconnserver->address();
492 QDBusReply<int> reply = KToolInvocation::klauncher()->requestHoldSlave(url.url(), slaveAddress);
493 if (!reply.isValid()) {
494 delete slave;
495 return 0;
496 }
497 pid_t pid = reply;
498 if (!pid)
499 {
500 delete slave;
501 return 0;
502 }
503 slave->setPID(pid);
504 QTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, slave, SLOT(timeout()));
505 return slave;
506}
507
508bool Slave::checkForHeldSlave(const KUrl &url)
509{
510 return KToolInvocation::klauncher()->checkForHeldSlave(url.url());
511}
512
513#include "slave.moc"
KIO::DataProtocol
This kioslave provides support of data urls as specified by rfc 2397.
Definition: dataprotocol.h:63
KIO::MetaData
MetaData is a simple map of key/value strings.
Definition: global.h:397
KIO::SimpleJob
A simple job (one url and one command).
Definition: jobclasses.h:322
KIO::SlaveInterfacePrivate
Definition: slaveinterface_p.h:33
KIO::SlaveInterface
There are two classes that specifies the protocol between application ( KIO::Job) and kioslave.
Definition: slaveinterface.h:99
KIO::SlaveInterface::dispatch
virtual bool dispatch()
Definition: slaveinterface.cpp:80
KIO::SlaveInterface::metaData
void metaData(const KIO::MetaData &)
KIO::SlaveInterface::data
void data(const QByteArray &)
KIO::SlaveInterface::error
void error(int, const QString &)
KIO::Slave
Definition: slave.h:49
KIO::Slave::setPID
void setPID(pid_t)
Definition: slave.cpp:261
KIO::Slave::host
QString host()
Definition: slave.cpp:193
KIO::Slave::slave_pid
int slave_pid()
Definition: slave.cpp:267
KIO::Slave::holdSlave
static Slave * holdSlave(const QString &protocol, const KUrl &url)
Requests a slave on hold for ths url, from klauncher, if there is such a job.
Definition: slave.cpp:484
KIO::Slave::ref
void ref()
Definition: slave.cpp:235
KIO::Slave::job
KIO::SimpleJob * job() const
Definition: slave.cpp:282
KIO::Slave::suspended
virtual bool suspended()
Tells whether the kioslave is suspended.
Definition: slave.cpp:326
KIO::Slave::send
virtual void send(int cmd, const QByteArray &arr=QByteArray())
Sends the given command to the kioslave.
Definition: slave.cpp:332
KIO::Slave::hold
virtual void hold(const KUrl &url)
Puts the kioslave associated with url at halt, and return it to klauncher, in order to let another ap...
Definition: slave.cpp:294
KIO::Slave::setHost
virtual void setHost(const QString &host, quint16 port, const QString &user, const QString &passwd)
Set host for url.
Definition: slave.cpp:378
KIO::Slave::setJob
void setJob(KIO::SimpleJob *job)
Definition: slave.cpp:273
KIO::Slave::suspend
virtual void suspend()
Suspends the operation of the attached kioslave.
Definition: slave.cpp:314
KIO::Slave::checkForHeldSlave
static bool checkForHeldSlave(const KUrl &url)
Returns true if klauncher is holding a slave for url.
Definition: slave.cpp:508
KIO::Slave::slaveProtocol
QString slaveProtocol()
The actual protocol used to handle the request.
Definition: slave.cpp:187
KIO::Slave::accept
void accept()
Definition: slave.cpp:113
KIO::Slave::createSlave
static Slave * createSlave(const QString &protocol, const KUrl &url, int &error, QString &error_text)
Creates a new slave.
Definition: slave.cpp:410
KIO::Slave::kill
void kill()
Force termination.
Definition: slave.cpp:361
KIO::Slave::user
QString user()
Definition: slave.cpp:205
KIO::Slave::setConnected
void setConnected(bool c)
Definition: slave.cpp:229
KIO::Slave::gotInput
void gotInput()
Definition: slave.cpp:338
KIO::Slave::protocol
QString protocol()
The protocol this slave handles.
Definition: slave.cpp:175
KIO::Slave::Slave
Slave(const QString &protocol, QObject *parent=0)
Definition: slave.cpp:160
KIO::Slave::idleTime
time_t idleTime()
Definition: slave.cpp:252
KIO::Slave::setIdle
void setIdle()
Marks this slave as idle.
Definition: slave.cpp:217
KIO::Slave::isConnected
bool isConnected()
Definition: slave.cpp:223
KIO::Slave::~Slave
virtual ~Slave()
Definition: slave.cpp:169
KIO::Slave::passwd
QString passwd()
Definition: slave.cpp:211
KIO::Slave::port
quint16 port()
Definition: slave.cpp:199
KIO::Slave::slaveDied
void slaveDied(KIO::Slave *slave)
KIO::Slave::timeout
void timeout()
Definition: slave.cpp:123
KIO::Slave::deref
void deref()
Definition: slave.cpp:241
KIO::Slave::setProtocol
void setProtocol(const QString &protocol)
Definition: slave.cpp:181
KIO::Slave::resume
virtual void resume()
Resumes the operation of the attached kioslave.
Definition: slave.cpp:320
KIO::Slave::resetHost
void resetHost()
Clear host info.
Definition: slave.cpp:394
KIO::Slave::isAlive
bool isAlive()
Definition: slave.cpp:288
KIO::Slave::setConfig
virtual void setConfig(const MetaData &config)
Configure slave.
Definition: slave.cpp:401
KLibrary
KLibrary::fileName
QString fileName
KStandardDirs::locate
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
KToolInvocation::klauncher
static OrgKdeKLauncherInterface * klauncher()
KUrl
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
OrgKdeKLauncherInterface
OrgKdeKLauncherInterface::checkForHeldSlave
QDBusReply< bool > checkForHeldSlave(const QString &url)
OrgKdeKLauncherInterface::requestSlave
QDBusReply< int > requestSlave(const QString &protocol, const QString &host, const QString &app_socket, QString &error)
OrgKdeKLauncherInterface::waitForSlave
QDBusReply< void > waitForSlave(int pid)
OrgKdeKLauncherInterface::requestHoldSlave
QDBusReply< int > requestHoldSlave(const QString &url, const QString &app_socket)
QObject
connection.h
dataprotocol.h
global.h
kDebug
#define kDebug
kWarning
#define kWarning
kdebug.h
kglobal.h
klauncher_iface.h
klibrary.h
klocale.h
i18n
QString i18n(const char *text)
kprotocolinfo.h
kservice.h
kstandarddirs.h
ktoolinvocation.h
KGlobal::mainComponent
const KComponentData & mainComponent()
config
KSharedConfigPtr config()
KIO
A namespace for KIO globals.
Definition: kbookmarkmenu.h:55
KIO::CMD_HOST
@ CMD_HOST
Definition: global.h:151
KIO::CMD_CONFIG
@ CMD_CONFIG
Definition: global.h:177
KIO::CMD_SLAVE_HOLD
@ CMD_SLAVE_HOLD
Definition: global.h:156
KIO::ERR_SLAVE_DIED
@ ERR_SLAVE_DIED
Definition: global.h:238
KIO::ERR_CANNOT_LAUNCH_PROCESS
@ ERR_CANNOT_LAUNCH_PROCESS
Definition: global.h:197
SLAVE_CONNECTION_TIMEOUT_MIN
#define SLAVE_CONNECTION_TIMEOUT_MIN
Definition: slave.cpp:54
SLAVE_CONNECTION_TIMEOUT_MAX
#define SLAVE_CONNECTION_TIMEOUT_MAX
Definition: slave.cpp:63
slave.h
slaveinterface_p.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal