31 #include <sys/types.h> 36 #include <dcopclient.h> 40 #include <kstandarddirs.h> 41 #include <kapplication.h> 42 #include <ktempfile.h> 45 #include <klibloader.h> 47 #include "kio/dataprotocol.h" 48 #include "kio/slave.h" 49 #include "kio/kservice.h" 50 #include <kio/global.h> 51 #include <kprotocolmanager.h> 52 #include <kprotocolinfo.h> 59 #define _PATH_TMP "/tmp" 64 #define SLAVE_CONNECTION_TIMEOUT_MIN 2 71 #define SLAVE_CONNECTION_TIMEOUT_MAX 10 73 #define SLAVE_CONNECTION_TIMEOUT_MAX 3600 86 SlavePrivate(
bool derived) : derived(derived) {}
90 void Slave::accept(KSocket *socket)
93 slaveconn.init(socket);
97 slaveconn.connect(
this, TQT_SLOT(gotInput()));
101 void Slave::unlinkSocket()
103 if (m_socket.isEmpty())
return;
104 TQCString filename = TQFile::encodeName(m_socket);
105 unlink(filename.data());
106 m_socket = TQString::null;
109 void Slave::timeout()
112 kdDebug(7002) <<
"slave failed to connect to application pid=" << m_pid <<
" protocol=" << m_protocol << endl;
113 if (m_pid && (::kill(m_pid, 0) == 0))
115 int delta_t = (int) difftime(time(0), contact_started);
116 kdDebug(7002) <<
"slave is slow... pid=" << m_pid <<
" t=" << delta_t << endl;
117 if (delta_t < SLAVE_CONNECTION_TIMEOUT_MAX)
119 TQTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN,
this, TQT_SLOT(timeout()));
123 kdDebug(7002) <<
"Houston, we lost our slave, pid=" << m_pid << endl;
128 TQString arg = m_protocol;
129 if (!m_host.isEmpty())
131 kdDebug(7002) <<
"slave died pid = " << m_pid << endl;
134 emit error(ERR_SLAVE_DIED, arg);
136 emit slaveDied(
this);
141 Slave::Slave(KServerSocket *socket,
const TQString &protocol,
const TQString &socketname)
143 d(new SlavePrivate(false))
146 m_protocol = protocol;
147 m_slaveProtocol = protocol;
148 m_socket = socketname;
150 contact_started = time(0);
151 idle_since = contact_started;
155 connect(serv, TQT_SIGNAL(accepted( KSocket* )),
156 TQT_SLOT(accept(KSocket*) ) );
161 const TQString &socketname)
163 d(new SlavePrivate(true))
169 m_socket = socketname;
171 contact_started = time(0);
172 idle_since = contact_started;
177 connect(serv, TQT_SIGNAL(accepted( KSocket* )),
178 TQT_SLOT(accept(KSocket*) ) );
196 void Slave::setProtocol(
const TQString & protocol)
203 idle_since = time(0);
208 return (time_t) difftime(time(0), idle_since);
211 void Slave::setPID(pid_t pid)
221 virtual_hook(VIRTUAL_HOLD, ¶ms);
228 TQDataStream stream( data, IO_WriteOnly );
230 slaveconn.
send( CMD_SLAVE_HOLD, data );
233 emit slaveDied(
this);
238 DCOPClient *client = kapp->dcopClient();
239 if (!client->isAttached())
242 TQByteArray params, reply;
244 TQDataStream stream(params, IO_WriteOnly);
248 TQCString launcher = KApplication::launcher();
249 client->call(launcher, launcher,
"waitForSlave(pid_t)",
250 params, replyType, reply);
257 virtual_hook(VIRTUAL_SUSPEND, 0);
267 virtual_hook(VIRTUAL_RESUME, 0);
277 SuspendedParams params;
278 virtual_hook(VIRTUAL_SUSPENDED, ¶ms);
279 return params.retval;
290 virtual_hook(VIRTUAL_SEND, ¶ms);
294 slaveconn.
send(cmd, arr);
297 void Slave::gotInput()
304 TQString arg = m_protocol;
305 if (!m_host.isEmpty())
307 kdDebug(7002) <<
"slave died pid = " << m_pid << endl;
309 emit error(ERR_SLAVE_DIED, arg);
311 emit slaveDied(
this);
320 kdDebug(7002) <<
"killing slave pid=" << m_pid <<
" (" << m_protocol <<
"://" 321 << m_host <<
")" << endl;
337 TQDataStream stream( data, IO_WriteOnly );
338 stream << m_host << m_port << m_user << m_passwd;
339 slaveconn.
send( CMD_HOST, data );
350 TQDataStream stream( data, IO_WriteOnly );
352 slaveconn.
send( CMD_CONFIG, data );
359 if (protocol ==
"data")
362 DCOPClient *client = kapp->dcopClient();
363 if (!client->isAttached())
366 TQString prefix = locateLocal(
"socket", KGlobal::instance()->instanceName());
367 KTempFile socketfile(prefix, TQString::fromLatin1(
".slave-socket"));
368 if ( socketfile.status() != 0 )
370 error_text = i18n(
"Unable to create io-slave: %1").arg(strerror(errno));
371 error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
380 KServerSocket *kss =
new KServerSocket(TQFile::encodeName(socketfile.name()).data());
382 Slave *slave =
new Slave(kss, protocol, socketfile.name());
394 static bool bForkSlaves = !TQCString(getenv(
"KDE_FORK_SLAVES")).isEmpty();
396 if (bForkSlaves || !client->isAttached() || client->isAttachedToForeignServer())
401 error_text = i18n(
"Unknown protocol '%1'.").arg(protocol);
402 error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
406 TQString lib_path = KLibLoader::findLibrary(_name.latin1());
407 if (lib_path.isEmpty())
409 error_text = i18n(
"Can not find io-slave for protocol '%1'.").arg(protocol);
410 error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
416 proc << locate(
"exe",
"kioslave") << lib_path << protocol <<
"" << socketfile.name();
417 kdDebug(7002) <<
"kioslave" <<
", " << lib_path <<
", " << protocol <<
", " << TQString::null <<
", " << socketfile.name() << endl;
419 proc.start(KProcess::DontCare);
422 slave->setPID(proc.pid());
423 TQTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, slave, TQT_SLOT(timeout()));
429 TQByteArray params, reply;
431 TQDataStream stream(params, IO_WriteOnly);
432 stream << protocol << url.host() << socketfile.name();
434 TQCString launcher = KApplication::launcher();
435 if (!client->call(launcher, launcher,
"requestSlave(TQString,TQString,TQString)",
436 params, replyType, reply)) {
437 error_text = i18n(
"Cannot talk to klauncher");
438 error = KIO::ERR_SLAVE_DEFINED;
442 TQDataStream stream2(reply, IO_ReadOnly);
445 stream2 >> pid >> errorStr;
448 error_text = i18n(
"Unable to create io-slave:\nklauncher said: %1").arg(errorStr);
449 error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
455 TQTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, slave, TQT_SLOT(timeout()));
460 Slave* Slave::holdSlave(
const TQString &protocol,
const KURL& url )
464 if (protocol ==
"data")
467 DCOPClient *client = kapp->dcopClient();
468 if (!client->isAttached())
471 TQString prefix = locateLocal(
"socket", KGlobal::instance()->instanceName());
472 KTempFile socketfile(prefix, TQString::fromLatin1(
".slave-socket"));
473 if ( socketfile.status() != 0 )
482 KServerSocket *kss =
new KServerSocket(TQFile::encodeName(socketfile.name()).data());
484 Slave *slave =
new Slave(kss, protocol, socketfile.name());
489 TQByteArray params, reply;
491 TQDataStream stream(params, IO_WriteOnly);
492 stream << url << socketfile.name();
494 TQCString launcher = KApplication::launcher();
495 if (!client->call(launcher, launcher,
"requestHoldSlave(KURL,TQString)",
496 params, replyType, reply)) {
500 TQDataStream stream2(reply, IO_ReadOnly);
510 TQTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, slave, TQT_SLOT(timeout()));
515 void Slave::virtual_hook(
int id,
void* data ) {
516 KIO::SlaveInterface::virtual_hook(
id, data );
void resume()
Resumes the operation of the attached kioslave.
void close()
Closes the connection.
A namespace for KIO globals.
void send(int cmd, const TQByteArray &data=TQByteArray())
Sends the given command to the kioslave.
There are two classes that specifies the protocol between application (KIO::Job) and kioslave...
void setHost(const TQString &host, int port, const TQString &user, const TQString &passwd)
Set host for url.
bool suspended()
Tells wether the kioslave is suspended.
static bool connect(const char *signal, const TQObject *receiver, const char *member)
Function to connect signals emitted by the scheduler.
void kill()
Force termination.
Attention developers: If you change the implementation of KIO::Slave, do not use connection() or slav...
void hold(const KURL &url)
Puts the kioslave associated with url at halt.
static TQString exec(const TQString &protocol)
Returns the library / executable to open for the protocol protocol Example : "kio_ftp", meaning either the executable "kio_ftp" or the library "kio_ftp.la" (recommended), whichever is available.
static Slave * createSlave(const TQString &protocol, const KURL &url, int &error, TQString &error_text)
Creates a new slave.
TQString protocol()
The protocol this slave handles.
void suspend()
Don't handle incoming data until resumed.
void resetHost()
Clear host info.
void resume()
Resume handling of incoming data.
void suspend()
Suspends the operation of the attached kioslave.
bool suspended() const
Returns status of connection.
void send(int cmd, const TQByteArray &arr=TQByteArray())
Sends/queues the given command to be sent.
void setConfig(const MetaData &config)
Configure slave.
void setIdle()
Marks this slave as idle.
Slave(bool derived, KServerSocket *unixdomain, const TQString &protocol, const TQString &socketname)
Use this constructor if you derive your own class from Slave derived must be true in any case...
This kioslave provides support of data urls as specified by rfc 2397.