31 #include <sys/types.h>
36 #include <dcopclient.h>
38 #include <tdelocale.h>
39 #include <tdeglobal.h>
40 #include <kstandarddirs.h>
41 #include <tdeapplication.h>
42 #include <tdetempfile.h>
45 #include <klibloader.h>
47 #include "tdeio/dataprotocol.h"
48 #include "tdeio/slave.h"
49 #include "tdeio/kservice.h"
50 #include <tdeio/global.h>
51 #include <tdeprotocolmanager.h>
52 #include <kprotocolinfo.h>
59 #define _PATH_TMP "/tmp"
62 using namespace TDEIO;
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(TDESocket *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(TDEServerSocket *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( TDESocket* )),
156 TQT_SLOT(accept(TDESocket*) ) );
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( TDESocket* )),
178 TQT_SLOT(accept(TDESocket*) ) );
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 = TDEApplication::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;
329 const TQString &user,
const TQString &passwd)
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", TDEGlobal::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 = TDEIO::ERR_CANNOT_LAUNCH_PROCESS;
380 TDEServerSocket *kss =
new TDEServerSocket(TQFile::encodeName(socketfile.name()).data());
382 Slave *slave =
new Slave(kss, protocol, socketfile.name());
394 static bool bForkSlaves = !TQCString(getenv(
"TDE_FORK_SLAVES")).isEmpty();
396 if (bForkSlaves || !client->isAttached() || client->isAttachedToForeignServer())
401 error_text = i18n(
"Unknown protocol '%1'.").arg(protocol);
402 error = TDEIO::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 = TDEIO::ERR_CANNOT_LAUNCH_PROCESS;
416 proc << locate(
"exe",
"tdeioslave") << lib_path << protocol <<
"" << socketfile.name();
417 kdDebug(7002) <<
"tdeioslave" <<
", " << lib_path <<
", " << protocol <<
", " << TQString::null <<
", " << socketfile.name() << endl;
419 proc.start(TDEProcess::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 = TDEApplication::launcher();
435 if (!client->call(launcher, launcher,
"requestSlave(TQString,TQString,TQString)",
436 params, replyType, reply)) {
437 error_text = i18n(
"Cannot talk to tdelauncher");
438 error = TDEIO::ERR_SLAVE_DEFINED;
442 TQDataStream stream2(reply, IO_ReadOnly);
445 stream2 >> pid >> errorStr;
448 error_text = i18n(
"Unable to create io-slave:\ntdelauncher said: %1").arg(errorStr);
449 error = TDEIO::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", TDEGlobal::instance()->instanceName());
472 KTempFile socketfile(prefix, TQString::fromLatin1(
".slave-socket"));
473 if ( socketfile.status() != 0 )
482 TDEServerSocket *kss =
new TDEServerSocket(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 = TDEApplication::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 TDEIO::SlaveInterface::virtual_hook(
id, data );