• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

  • tdeio
  • tdeio
slave.cpp
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 * $Id$
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License version 2 as published by the Free Software Foundation.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 **/
22
23#include <config.h>
24
25#include <time.h>
26#include <errno.h>
27#include <unistd.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <signal.h>
31#include <sys/types.h>
32
33#include <tqfile.h>
34#include <tqtimer.h>
35
36#include <dcopclient.h>
37#include <kdebug.h>
38#include <tdelocale.h>
39#include <tdeglobal.h>
40#include <tdestandarddirs.h>
41#include <tdeapplication.h>
42#include <tdetempfile.h>
43#include <ksock.h>
44#include <tdeprocess.h>
45#include <klibloader.h>
46
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>
53
54#ifdef HAVE_PATHS_H
55#include <paths.h>
56#endif
57
58#ifndef _PATH_TMP
59#define _PATH_TMP "/tmp"
60#endif
61
62using namespace TDEIO;
63
64#define SLAVE_CONNECTION_TIMEOUT_MIN 2
65
66// Without debug info we consider it an error if the slave doesn't connect
67// within 10 seconds.
68// With debug info we give the slave an hour so that developers have a chance
69// to debug their slave.
70#ifdef NDEBUG
71#define SLAVE_CONNECTION_TIMEOUT_MAX 10
72#else
73#define SLAVE_CONNECTION_TIMEOUT_MAX 3600
74#endif
75
76namespace TDEIO {
77
81 class SlavePrivate {
82 public:
83 bool derived; // true if this instance of Slave is actually an
84 // instance of a derived class.
85
86 SlavePrivate(bool derived) : derived(derived) {}
87 };
88}
89
90void Slave::accept(TDESocket *socket)
91{
92#ifndef TQ_WS_WIN
93 slaveconn.init(socket);
94#endif
95 delete serv;
96 serv = 0;
97 slaveconn.connect(this, TQ_SLOT(gotInput()));
98 unlinkSocket();
99}
100
101void Slave::unlinkSocket()
102{
103 if (m_socket.isEmpty()) return;
104 TQCString filename = TQFile::encodeName(m_socket);
105 unlink(filename.data());
106 m_socket = TQString::null;
107}
108
109void Slave::timeout()
110{
111 if (!serv) return;
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))
114 {
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)
118 {
119 TQTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, this, TQ_SLOT(timeout()));
120 return;
121 }
122 }
123 kdDebug(7002) << "Houston, we lost our slave, pid=" << m_pid << endl;
124 delete serv;
125 serv = 0;
126 unlinkSocket();
127 dead = true;
128 TQString arg = m_protocol;
129 if (!m_host.isEmpty())
130 arg += "://"+m_host;
131 kdDebug(7002) << "slave died pid = " << m_pid << endl;
132 ref();
133 // Tell the job about the problem.
134 emit error(ERR_SLAVE_DIED, arg);
135 // Tell the scheduler about the problem.
136 emit slaveDied(this);
137 // After the above signal we're dead!!
138 deref();
139}
140
141Slave::Slave(TDEServerSocket *socket, const TQString &protocol, const TQString &socketname)
142 : SlaveInterface(&slaveconn), serv(socket), contacted(false),
143 d(new SlavePrivate(false))
144{
145 m_refCount = 1;
146 m_protocol = protocol;
147 m_slaveProtocol = protocol;
148 m_socket = socketname;
149 dead = false;
150 contact_started = time(0);
151 idle_since = contact_started;
152 m_pid = 0;
153 m_port = 0;
154#ifndef TQ_WS_WIN
155 connect(serv, TQ_SIGNAL(accepted( TDESocket* )),
156 TQ_SLOT(accept(TDESocket*) ) );
157#endif
158}
159
160Slave::Slave(bool /*derived*/, TDEServerSocket *socket, const TQString &protocol,
161 const TQString &socketname)
162 : SlaveInterface(&slaveconn), serv(socket), contacted(false),
163 d(new SlavePrivate(true))
164{
165 // FIXME: hmm, duplicating code here from public ctor, no good (LS)
166 m_refCount = 1;
167 m_protocol = protocol;
168 m_slaveProtocol = protocol;
169 m_socket = socketname;
170 dead = false;
171 contact_started = time(0);
172 idle_since = contact_started;
173 m_pid = 0;
174 m_port = 0;
175 if (serv != 0) {
176#ifndef TQ_WS_WIN
177 connect(serv, TQ_SIGNAL(accepted( TDESocket* )),
178 TQ_SLOT(accept(TDESocket*) ) );
179#endif
180 }
181}
182
183Slave::~Slave()
184{
185 // kdDebug(7002) << "destructing slave object pid = " << m_pid << endl;
186 if (serv != 0) {
187 delete serv;
188 serv = 0;
189 }
190 unlinkSocket();
191 m_pid = 99999;
192 delete d;
193 d = 0;
194}
195
196void Slave::setProtocol(const TQString & protocol)
197{
198 m_protocol = protocol;
199}
200
201void Slave::setIdle()
202{
203 idle_since = time(0);
204}
205
206time_t Slave::idleTime()
207{
208 return (time_t) difftime(time(0), idle_since);
209}
210
211void Slave::setPID(pid_t pid)
212{
213 m_pid = pid;
214}
215
216void Slave::hold(const KURL &url)
217{
218 if (d->derived) { // TODO: clean up before KDE 4
219 HoldParams params;
220 params.url = &url;
221 virtual_hook(VIRTUAL_HOLD, &params);
222 return;
223 }/*end if*/
224
225 ref();
226 {
227 TQByteArray data;
228 TQDataStream stream( data, IO_WriteOnly );
229 stream << url;
230 slaveconn.send( CMD_SLAVE_HOLD, data );
231 slaveconn.close();
232 dead = true;
233 emit slaveDied(this);
234 }
235 deref();
236 // Call TDELauncher::waitForSlave(pid);
237 {
238 DCOPClient *client = tdeApp->dcopClient();
239 if (!client->isAttached())
240 client->attach();
241
242 TQByteArray params, reply;
243 TQCString replyType;
244 TQDataStream stream(params, IO_WriteOnly);
245 pid_t pid = m_pid;
246 stream << pid;
247
248 TQCString launcher = TDEApplication::launcher();
249 client->call(launcher, launcher, "waitForSlave(pid_t)",
250 params, replyType, reply);
251 }
252}
253
254void Slave::suspend()
255{
256 if (d->derived) { // TODO: clean up before KDE 4
257 virtual_hook(VIRTUAL_SUSPEND, 0);
258 return;
259 }/*end if*/
260
261 slaveconn.suspend();
262}
263
264void Slave::resume()
265{
266 if (d->derived) { // TODO: clean up before KDE 4
267 virtual_hook(VIRTUAL_RESUME, 0);
268 return;
269 }/*end if*/
270
271 slaveconn.resume();
272}
273
274bool Slave::suspended()
275{
276 if (d->derived) { // TODO: clean up before KDE 4
277 SuspendedParams params;
278 virtual_hook(VIRTUAL_SUSPENDED, &params);
279 return params.retval;
280 }/*end if*/
281
282 return slaveconn.suspended();
283}
284
285void Slave::send(int cmd, const TQByteArray &arr) {
286 if (d->derived) { // TODO: clean up before KDE 4
287 SendParams params;
288 params.cmd = cmd;
289 params.arr = &arr;
290 virtual_hook(VIRTUAL_SEND, &params);
291 return;
292 }/*end if*/
293
294 slaveconn.send(cmd, arr);
295}
296
297void Slave::gotInput()
298{
299 ref();
300 if (!dispatch())
301 {
302 slaveconn.close();
303 dead = true;
304 TQString arg = m_protocol;
305 if (!m_host.isEmpty())
306 arg += "://"+m_host;
307 kdDebug(7002) << "slave died pid = " << m_pid << endl;
308 // Tell the job about the problem.
309 emit error(ERR_SLAVE_DIED, arg);
310 // Tell the scheduler about the problem.
311 emit slaveDied(this);
312 }
313 deref();
314 // Here we might be dead!!
315}
316
317void Slave::kill()
318{
319 dead = true; // OO can be such simple.
320 kdDebug(7002) << "killing slave pid=" << m_pid << " (" << m_protocol << "://"
321 << m_host << ")" << endl;
322 if (m_pid)
323 {
324 ::kill(m_pid, SIGTERM);
325 }
326}
327
328void Slave::setHost( const TQString &host, int port,
329 const TQString &user, const TQString &passwd)
330{
331 m_host = host;
332 m_port = port;
333 m_user = user;
334 m_passwd = passwd;
335
336 TQByteArray data;
337 TQDataStream stream( data, IO_WriteOnly );
338 stream << m_host << m_port << m_user << m_passwd;
339 slaveconn.send( CMD_HOST, data );
340}
341
342void Slave::resetHost()
343{
344 m_host = "<reset>";
345}
346
347void Slave::setConfig(const MetaData &config)
348{
349 TQByteArray data;
350 TQDataStream stream( data, IO_WriteOnly );
351 stream << config;
352 slaveconn.send( CMD_CONFIG, data );
353}
354
355Slave* Slave::createSlave( const TQString &protocol, const KURL& url, int& error, TQString& error_text )
356{
357 //kdDebug(7002) << "createSlave '" << protocol << "' for " << url.prettyURL() << endl;
358 // Firstly take into account all special slaves
359 if (protocol == "data")
360 return new DataProtocol();
361
362 DCOPClient *client = tdeApp->dcopClient();
363 if (!client->isAttached())
364 client->attach();
365
366 TQString prefix = locateLocal("socket", TDEGlobal::instance()->instanceName());
367 KTempFile socketfile(prefix, TQString::fromLatin1(".slave-socket"));
368 if ( socketfile.status() != 0 )
369 {
370 error_text = i18n("Unable to create io-slave: %1").arg(strerror(errno));
371 error = TDEIO::ERR_CANNOT_LAUNCH_PROCESS;
372 return 0;
373 }
374
375#ifdef __CYGWIN__
376 socketfile.close();
377#endif
378
379#ifndef TQ_WS_WIN
380 TDEServerSocket *kss = new TDEServerSocket(TQFile::encodeName(socketfile.name()).data());
381
382 Slave *slave = new Slave(kss, protocol, socketfile.name());
383#else
384 Slave *slave = 0;
385#endif
386
387 // WABA: if the dcopserver is running under another uid we don't ask
388 // tdelauncher for a slave, because the slave might have that other uid
389 // as well, which might either be a) undesired or b) make it impossible
390 // for the slave to connect to the application.
391 // In such case we start the slave via TDEProcess.
392 // It's possible to force this by setting the env. variable
393 // TDE_FORK_SLAVES, Clearcase seems to require this.
394 static bool bForkSlaves = !TQCString(getenv("TDE_FORK_SLAVES")).isEmpty();
395
396 if (bForkSlaves || !client->isAttached() || client->isAttachedToForeignServer())
397 {
398 TQString _name = KProtocolInfo::exec(protocol);
399 if (_name.isEmpty())
400 {
401 error_text = i18n("Unknown protocol '%1'.").arg(protocol);
402 error = TDEIO::ERR_CANNOT_LAUNCH_PROCESS;
403 delete slave;
404 return 0;
405 }
406 TQString lib_path = KLibLoader::findLibrary(_name.latin1());
407 if (lib_path.isEmpty())
408 {
409 error_text = i18n("Can not find io-slave for protocol '%1'.").arg(protocol);
410 error = TDEIO::ERR_CANNOT_LAUNCH_PROCESS;
411 return 0;
412 }
413
414 TDEProcess proc;
415
416 proc << locate("exe", "tdeioslave") << lib_path << protocol << "" << socketfile.name();
417 kdDebug(7002) << "tdeioslave" << ", " << lib_path << ", " << protocol << ", " << TQString::null << ", " << socketfile.name() << endl;
418
419 proc.start(TDEProcess::DontCare);
420
421#ifndef TQ_WS_WIN
422 slave->setPID(proc.pid());
423 TQTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, slave, TQ_SLOT(timeout()));
424#endif
425 return slave;
426 }
427
428
429 TQByteArray params, reply;
430 TQCString replyType;
431 TQDataStream stream(params, IO_WriteOnly);
432 stream << protocol << url.host() << socketfile.name();
433
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;
439 delete slave;
440 return 0;
441 }
442 TQDataStream stream2(reply, IO_ReadOnly);
443 TQString errorStr;
444 pid_t pid;
445 stream2 >> pid >> errorStr;
446 if (!pid)
447 {
448 error_text = i18n("Unable to create io-slave:\ntdelauncher said: %1").arg(errorStr);
449 error = TDEIO::ERR_CANNOT_LAUNCH_PROCESS;
450 delete slave;
451 return 0;
452 }
453#ifndef TQ_WS_WIN
454 slave->setPID(pid);
455 TQTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, slave, TQ_SLOT(timeout()));
456#endif
457 return slave;
458}
459
460Slave* Slave::holdSlave( const TQString &protocol, const KURL& url )
461{
462 //kdDebug(7002) << "holdSlave '" << protocol << "' for " << url.prettyURL() << endl;
463 // Firstly take into account all special slaves
464 if (protocol == "data")
465 return 0;
466
467 DCOPClient *client = tdeApp->dcopClient();
468 if (!client->isAttached())
469 client->attach();
470
471 TQString prefix = locateLocal("socket", TDEGlobal::instance()->instanceName());
472 KTempFile socketfile(prefix, TQString::fromLatin1(".slave-socket"));
473 if ( socketfile.status() != 0 )
474 return 0;
475
476#ifdef __CYGWIN__
477 socketfile.close();
478 socketfile.unlink();
479#endif
480
481#ifndef TQ_WS_WIN
482 TDEServerSocket *kss = new TDEServerSocket(TQFile::encodeName(socketfile.name()).data());
483
484 Slave *slave = new Slave(kss, protocol, socketfile.name());
485#else
486 Slave *slave = 0;
487#endif
488
489 TQByteArray params, reply;
490 TQCString replyType;
491 TQDataStream stream(params, IO_WriteOnly);
492 stream << url << socketfile.name();
493
494 TQCString launcher = TDEApplication::launcher();
495 if (!client->call(launcher, launcher, "requestHoldSlave(KURL,TQString)",
496 params, replyType, reply)) {
497 delete slave;
498 return 0;
499 }
500 TQDataStream stream2(reply, IO_ReadOnly);
501 pid_t pid;
502 stream2 >> pid;
503 if (!pid)
504 {
505 delete slave;
506 return 0;
507 }
508#ifndef TQ_WS_WIN
509 slave->setPID(pid);
510 TQTimer::singleShot(1000*SLAVE_CONNECTION_TIMEOUT_MIN, slave, TQ_SLOT(timeout()));
511#endif
512 return slave;
513}
514
515void Slave::virtual_hook( int id, void* data ) {
516 TDEIO::SlaveInterface::virtual_hook( id, data );
517}
518
519#include "slave.moc"
KProtocolInfo::exec
static TQString exec(const TQString &protocol)
Returns the library / executable to open for the protocol protocol Example : "tdeio_ftp",...
TDEIO::Connection::resume
void resume()
Resume handling of incoming data.
Definition: connection.cpp:79
TDEIO::Connection::send
void send(int cmd, const TQByteArray &arr=TQByteArray())
Sends/queues the given command to be sent.
Definition: connection.cpp:105
TDEIO::Connection::init
void init(TDESocket *sock)
Initialize this connection to use the given socket.
Definition: connection.cpp:131
TDEIO::Connection::suspend
void suspend()
Don't handle incoming data until resumed.
Definition: connection.cpp:72
TDEIO::Connection::suspended
bool suspended() const
Definition: connection.h:134
TDEIO::Connection::close
void close()
Closes the connection.
Definition: connection.cpp:86
TDEIO::DataProtocol
This tdeioslave provides support of data urls as specified by rfc 2397.
Definition: dataprotocol.h:51
TDEIO::MetaData
MetaData is a simple map of key/value strings.
Definition: global.h:516
TDEIO::SlaveInterface
There are two classes that specifies the protocol between application (TDEIO::Job) and tdeioslave.
Definition: slaveinterface.h:94
TDEIO::Slave
Attention developers: If you change the implementation of TDEIO::Slave, do not use connection() or sl...
Definition: slave.h:44
TDEIO::Slave::passwd
TQString passwd()
Definition: slave.h:138
TDEIO::Slave::suspended
bool suspended()
Tells wether the tdeioslave is suspended.
Definition: slave.cpp:274
TDEIO::Slave::Slave
Slave(bool derived, TDEServerSocket *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.
Definition: slave.cpp:160
TDEIO::Slave::createSlave
static Slave * createSlave(const TQString &protocol, const KURL &url, int &error, TQString &error_text)
Creates a new slave.
Definition: slave.cpp:355
TDEIO::Slave::port
int port()
Definition: slave.h:128
TDEIO::Slave::suspend
void suspend()
Suspends the operation of the attached tdeioslave.
Definition: slave.cpp:254
TDEIO::Slave::user
TQString user()
Definition: slave.h:133
TDEIO::Slave::kill
void kill()
Force termination.
Definition: slave.cpp:317
TDEIO::Slave::idleTime
time_t idleTime()
Definition: slave.cpp:206
TDEIO::Slave::setIdle
void setIdle()
Marks this slave as idle.
Definition: slave.cpp:201
TDEIO::Slave::host
TQString host()
Definition: slave.h:123
TDEIO::Slave::protocol
TQString protocol()
The protocol this slave handles.
Definition: slave.h:103
TDEIO::Slave::setHost
void setHost(const TQString &host, int port, const TQString &user, const TQString &passwd)
Set host for url.
Definition: slave.cpp:328
TDEIO::Slave::hold
void hold(const KURL &url)
Puts the tdeioslave associated with url at halt.
Definition: slave.cpp:216
TDEIO::Slave::send
void send(int cmd, const TQByteArray &data=TQByteArray())
Sends the given command to the tdeioslave.
Definition: slave.cpp:285
TDEIO::Slave::resume
void resume()
Resumes the operation of the attached tdeioslave.
Definition: slave.cpp:264
TDEIO::Slave::resetHost
void resetHost()
Clear host info.
Definition: slave.cpp:342
TDEIO::Slave::setConfig
void setConfig(const MetaData &config)
Configure slave.
Definition: slave.cpp:347
TDEIO
A namespace for TDEIO globals.
Definition: authinfo.h:29

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.9.4
This website is maintained by Timothy Pearson.