kio Library API Documentation

slaveinterface.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 David Faure <faure@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00016 Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include "kio/slaveinterface.h" 00020 #include "kio/slavebase.h" 00021 #include "kio/connection.h" 00022 #include <errno.h> 00023 #include <assert.h> 00024 #include <kdebug.h> 00025 #include <stdlib.h> 00026 #include <sys/time.h> 00027 #include <unistd.h> 00028 #include <signal.h> 00029 #include <kio/observer.h> 00030 #include <kapplication.h> 00031 #include <dcopclient.h> 00032 #include <time.h> 00033 #include <qtimer.h> 00034 00035 using namespace KIO; 00036 00037 00038 QDataStream &operator <<(QDataStream &s, const KIO::UDSEntry &e ) 00039 { 00040 // On 32-bit platforms we send UDS_SIZE with UDS_SIZE_LARGE in front 00041 // of it to carry the 32 msb. We can't send a 64 bit UDS_SIZE because 00042 // that would break the compatibility of the wire-protocol with KDE 2. 00043 // On 64-bit platforms nothing has changed. 00044 if (sizeof(long) == 8) 00045 { 00046 s << (Q_UINT32)e.size(); 00047 KIO::UDSEntry::ConstIterator it = e.begin(); 00048 for( ; it != e.end(); ++it ) 00049 s << *it; 00050 return s; 00051 } 00052 00053 Q_UINT32 size = 0; 00054 KIO::UDSEntry::ConstIterator it = e.begin(); 00055 for( ; it != e.end(); ++it ) 00056 { 00057 size++; 00058 if ((*it).m_uds == KIO::UDS_SIZE) 00059 size++; 00060 } 00061 s << size; 00062 it = e.begin(); 00063 for( ; it != e.end(); ++it ) 00064 { 00065 if ((*it).m_uds == KIO::UDS_SIZE) 00066 { 00067 KIO::UDSAtom a; 00068 a.m_uds = KIO::UDS_SIZE_LARGE; 00069 a.m_long = (*it).m_long >> 32; 00070 s << a; 00071 } 00072 s << *it; 00073 } 00074 return s; 00075 } 00076 00077 QDataStream &operator >>(QDataStream &s, KIO::UDSEntry &e ) 00078 { 00079 e.clear(); 00080 Q_UINT32 size; 00081 s >> size; 00082 00083 // On 32-bit platforms we send UDS_SIZE with UDS_SIZE_LARGE in front 00084 // of it to carry the 32 msb. We can't send a 64 bit UDS_SIZE because 00085 // that would break the compatibility of the wire-protocol with KDE 2. 00086 // On 64-bit platforms nothing has changed. 00087 if (sizeof(long) == 8) 00088 { 00089 for(Q_UINT32 i = 0; i < size; i++) 00090 { 00091 KIO::UDSAtom a; 00092 s >> a; 00093 e.append(a); 00094 } 00095 } 00096 else 00097 { 00098 long long msb = 0; 00099 for(Q_UINT32 i = 0; i < size; i++) 00100 { 00101 KIO::UDSAtom a; 00102 s >> a; 00103 if (a.m_uds == KIO::UDS_SIZE_LARGE) 00104 { 00105 msb = a.m_long; 00106 } 00107 else 00108 { 00109 if (a.m_uds == KIO::UDS_SIZE) 00110 { 00111 if (a.m_long < 0) 00112 a.m_long += (long long) 1 << 32; 00113 a.m_long += msb << 32; 00114 } 00115 e.append(a); 00116 msb = 0; 00117 } 00118 } 00119 } 00120 return s; 00121 } 00122 00123 static const unsigned int max_nums = 8; 00124 00125 class KIO::SlaveInterfacePrivate 00126 { 00127 public: 00128 SlaveInterfacePrivate() { 00129 slave_calcs_speed = false; 00130 start_time.tv_sec = 0; 00131 start_time.tv_usec = 0; 00132 last_time = 0; 00133 nums = 0; 00134 filesize = 0; 00135 offset = 0; 00136 } 00137 bool slave_calcs_speed; 00138 struct timeval start_time; 00139 uint nums; 00140 long times[max_nums]; 00141 KIO::filesize_t sizes[max_nums]; 00142 size_t last_time; 00143 KIO::filesize_t filesize, offset; 00144 00145 QTimer speed_timer; 00146 }; 00147 00149 00150 SlaveInterface::SlaveInterface( Connection * connection ) 00151 { 00152 m_pConnection = connection; 00153 m_progressId = 0; 00154 00155 d = new SlaveInterfacePrivate; 00156 connect(&d->speed_timer, SIGNAL(timeout()), SLOT(calcSpeed())); 00157 } 00158 00159 SlaveInterface::~SlaveInterface() 00160 { 00161 // Note: no kdDebug() here (scheduler is deleted very late) 00162 m_pConnection = 0; // a bit like the "wasDeleted" of QObject... 00163 00164 delete d; 00165 } 00166 00167 static KIO::filesize_t readFilesize_t(QDataStream &stream) 00168 { 00169 KIO::filesize_t result; 00170 unsigned long ul; 00171 stream >> ul; 00172 result = ul; 00173 if (stream.atEnd()) 00174 return result; 00175 stream >> ul; 00176 result += ((KIO::filesize_t)ul) << 32; 00177 return result; 00178 } 00179 00180 00181 bool SlaveInterface::dispatch() 00182 { 00183 assert( m_pConnection ); 00184 00185 int cmd; 00186 QByteArray data; 00187 00188 if (m_pConnection->read( &cmd, data ) == -1) 00189 return false; 00190 00191 return dispatch( cmd, data ); 00192 } 00193 00194 void SlaveInterface::calcSpeed() 00195 { 00196 if (d->slave_calcs_speed) { 00197 d->speed_timer.stop(); 00198 return; 00199 } 00200 00201 struct timeval tv; 00202 gettimeofday(&tv, 0); 00203 00204 long diff = ((tv.tv_sec - d->start_time.tv_sec) * 1000000 + 00205 tv.tv_usec - d->start_time.tv_usec) / 1000; 00206 if (diff - d->last_time >= 900) { 00207 d->last_time = diff; 00208 if (d->nums == max_nums) { 00209 // let's hope gcc can optimize that well enough 00210 // otherwise I'd try memcpy :) 00211 for (unsigned int i = 1; i < max_nums; ++i) { 00212 d->times[i-1] = d->times[i]; 00213 d->sizes[i-1] = d->sizes[i]; 00214 } 00215 d->nums--; 00216 } 00217 d->times[d->nums] = diff; 00218 d->sizes[d->nums++] = d->filesize; 00219 00220 KIO::filesize_t lspeed = 1000 * (d->sizes[d->nums-1] - d->sizes[0]) / (d->times[d->nums-1] - d->times[0]); 00221 00222 // kdDebug() << "proceeed " << (long)d->filesize << " " << diff << " " << long(d->sizes[d->nums-1] - d->sizes[0]) << " " << d->times[d->nums-1] - d->times[0] << " " << long(lspeed) << " " << double(d->filesize) / diff << " " << convertSize(lspeed) << " " << convertSize(long(double(d->filesize) / diff) * 1000) << " " << endl ; 00223 00224 if (!lspeed) { 00225 d->nums = 1; 00226 d->times[0] = diff; 00227 d->sizes[0] = d->filesize; 00228 } 00229 emit speed(lspeed); 00230 } 00231 } 00232 00233 bool SlaveInterface::dispatch( int _cmd, const QByteArray &rawdata ) 00234 { 00235 //kdDebug(7007) << "dispatch " << _cmd << endl; 00236 00237 QDataStream stream( rawdata, IO_ReadOnly ); 00238 00239 QString str1; 00240 int i; 00241 Q_INT8 b; 00242 unsigned long ul; 00243 00244 switch( _cmd ) { 00245 case MSG_DATA: 00246 emit data( rawdata ); 00247 break; 00248 case MSG_DATA_REQ: 00249 emit dataReq(); 00250 break; 00251 case MSG_FINISHED: 00252 //kdDebug(7007) << "Finished [this = " << this << "]" << endl; 00253 d->offset = 0; 00254 d->speed_timer.stop(); 00255 emit finished(); 00256 break; 00257 case MSG_STAT_ENTRY: 00258 { 00259 UDSEntry entry; 00260 stream >> entry; 00261 emit statEntry(entry); 00262 } 00263 break; 00264 case MSG_LIST_ENTRIES: 00265 { 00266 uint count; 00267 stream >> count; 00268 00269 UDSEntryList list; 00270 UDSEntry entry; 00271 for (uint i = 0; i < count; i++) { 00272 stream >> entry; 00273 list.append(entry); 00274 } 00275 emit listEntries(list); 00276 00277 } 00278 break; 00279 case MSG_RESUME: // From the put job 00280 { 00281 KIO::filesize_t offset = readFilesize_t(stream); 00282 emit canResume( offset ); 00283 } 00284 break; 00285 case MSG_CANRESUME: // From the get job 00286 d->filesize = d->offset; 00287 emit canResume(0); // the arg doesn't matter 00288 break; 00289 case MSG_ERROR: 00290 stream >> i >> str1; 00291 kdDebug(7007) << "error " << i << " " << str1 << endl; 00292 emit error( i, str1 ); 00293 break; 00294 case MSG_SLAVE_STATUS: 00295 { 00296 pid_t pid; 00297 QCString protocol; 00298 stream >> pid >> protocol >> str1 >> b; 00299 emit slaveStatus(pid, protocol, str1, (b != 0)); 00300 } 00301 break; 00302 case MSG_CONNECTED: 00303 emit connected(); 00304 break; 00305 00306 case INF_TOTAL_SIZE: 00307 { 00308 KIO::filesize_t size = readFilesize_t(stream); 00309 gettimeofday(&d->start_time, 0); 00310 d->last_time = 0; 00311 d->filesize = d->offset; 00312 d->sizes[0] = d->filesize; 00313 d->times[0] = 0; 00314 d->nums = 1; 00315 d->speed_timer.start(1000); 00316 d->slave_calcs_speed = false; 00317 emit totalSize( size ); 00318 } 00319 break; 00320 case INF_PROCESSED_SIZE: 00321 { 00322 KIO::filesize_t size = readFilesize_t(stream); 00323 emit processedSize( size ); 00324 d->filesize = size; 00325 } 00326 break; 00327 case INF_SPEED: 00328 stream >> ul; 00329 d->slave_calcs_speed = true; 00330 d->speed_timer.stop(); 00331 00332 emit speed( ul ); 00333 break; 00334 case INF_GETTING_FILE: 00335 break; 00336 case INF_ERROR_PAGE: 00337 emit errorPage(); 00338 break; 00339 case INF_REDIRECTION: 00340 { 00341 KURL url; 00342 stream >> url; 00343 00344 emit redirection( url ); 00345 } 00346 break; 00347 case INF_MIME_TYPE: 00348 stream >> str1; 00349 00350 emit mimeType( str1 ); 00351 if (!m_pConnection->suspended()) 00352 m_pConnection->sendnow( CMD_NONE, QByteArray() ); 00353 break; 00354 case INF_WARNING: 00355 stream >> str1; 00356 00357 emit warning( str1 ); 00358 break; 00359 case INF_NEED_PASSWD: { 00360 AuthInfo info; 00361 stream >> info; 00362 openPassDlg( info ); 00363 break; 00364 } 00365 case INF_MESSAGEBOX: { 00366 kdDebug(7007) << "needs a msg box" << endl; 00367 QString text, caption, buttonYes, buttonNo; 00368 int type; 00369 stream >> type >> text >> caption >> buttonYes >> buttonNo; 00370 messageBox(type, text, caption, buttonYes, buttonNo); 00371 break; 00372 } 00373 case INF_INFOMESSAGE: { 00374 QString msg; 00375 stream >> msg; 00376 infoMessage(msg); 00377 break; 00378 } 00379 case INF_META_DATA: { 00380 MetaData meta_data; 00381 stream >> meta_data; 00382 metaData(meta_data); 00383 break; 00384 } 00385 case MSG_NET_REQUEST: { 00386 QString host; 00387 QString slaveid; 00388 stream >> host >> slaveid; 00389 requestNetwork(host, slaveid); 00390 break; 00391 } 00392 case MSG_NET_DROP: { 00393 QString host; 00394 QString slaveid; 00395 stream >> host >> slaveid; 00396 dropNetwork(host, slaveid); 00397 break; 00398 } 00399 case MSG_NEED_SUBURL_DATA: { 00400 emit needSubURLData(); 00401 break; 00402 } 00403 case MSG_AUTH_KEY: { 00404 bool keep; 00405 QCString key, group; 00406 stream >> key >> group >> keep; 00407 kdDebug(7007) << "Got auth-key: " << key << endl 00408 << " group-key: " << group << endl 00409 << " keep password: " << keep << endl; 00410 emit authorizationKey( key, group, keep ); 00411 break; 00412 } 00413 case MSG_DEL_AUTH_KEY: { 00414 QCString key; 00415 stream >> key; 00416 kdDebug(7007) << "Delete auth-key: " << key << endl; 00417 emit delAuthorization( key ); 00418 } 00419 default: 00420 kdWarning(7007) << "Slave sends unknown command (" << _cmd << "), dropping slave" << endl; 00421 return false; 00422 } 00423 return true; 00424 } 00425 00426 void SlaveInterface::setOffset( KIO::filesize_t o) 00427 { 00428 d->offset = o; 00429 } 00430 00431 KIO::filesize_t SlaveInterface::offset() const { return d->offset; } 00432 00433 void SlaveInterface::requestNetwork(const QString &host, const QString &slaveid) 00434 { 00435 kdDebug(7007) << "requestNetwork " << host << slaveid << endl; 00436 QByteArray packedArgs; 00437 QDataStream stream( packedArgs, IO_WriteOnly ); 00438 stream << true; 00439 m_pConnection->sendnow( INF_NETWORK_STATUS, packedArgs ); 00440 } 00441 00442 void SlaveInterface::dropNetwork(const QString &host, const QString &slaveid) 00443 { 00444 kdDebug(7007) << "dropNetwork " << host << slaveid << endl; 00445 } 00446 00447 void SlaveInterface::sendResumeAnswer( bool resume ) 00448 { 00449 kdDebug(7007) << "SlaveInterface::sendResumeAnswer ok for resuming :" << resume << endl; 00450 m_pConnection->sendnow( resume ? CMD_RESUMEANSWER : CMD_NONE, QByteArray() ); 00451 } 00452 00453 void SlaveInterface::openPassDlg( const QString& prompt, const QString& user, bool readOnly ) 00454 { 00455 AuthInfo info; 00456 info.prompt = prompt; 00457 info.username = user; 00458 info.readOnly = readOnly; 00459 openPassDlg( info ); 00460 } 00461 00462 void SlaveInterface::openPassDlg( const QString& prompt, const QString& user, 00463 const QString& caption, const QString& comment, 00464 const QString& label, bool readOnly ) 00465 { 00466 AuthInfo info; 00467 info.prompt = prompt; 00468 info.username = user; 00469 info.caption = caption; 00470 info.comment = comment; 00471 info.commentLabel = label; 00472 info.readOnly = readOnly; 00473 openPassDlg( info ); 00474 } 00475 00476 void SlaveInterface::openPassDlg( AuthInfo& info ) 00477 { 00478 kdDebug(7007) << "SlaveInterface::openPassDlg: " 00479 << "User= " << info.username 00480 << ", Message= " << info.prompt << endl; 00481 bool result = Observer::self()->openPassDlg( info ); 00482 if ( m_pConnection ) 00483 { 00484 QByteArray data; 00485 QDataStream stream( data, IO_WriteOnly ); 00486 if ( result ) 00487 { 00488 stream << info; 00489 kdDebug(7007) << "SlaveInterface:::openPassDlg got: " 00490 << "User= " << info.username 00491 << ", Password= [hidden]" << endl; 00492 m_pConnection->sendnow( CMD_USERPASS, data ); 00493 } 00494 else 00495 m_pConnection->sendnow( CMD_NONE, data ); 00496 } 00497 } 00498 00499 void SlaveInterface::messageBox( int type, const QString &text, const QString &_caption, 00500 const QString &buttonYes, const QString &buttonNo ) 00501 { 00502 kdDebug(7007) << "messageBox " << type << " " << text << " - " << _caption << endl; 00503 QByteArray packedArgs; 00504 QDataStream stream( packedArgs, IO_WriteOnly ); 00505 00506 QString caption( _caption ); 00507 if ( type == KIO::SlaveBase::SSLMessageBox ) 00508 caption = QString::fromUtf8(kapp->dcopClient()->appId()); // hack, see observer.cpp 00509 00510 emit needProgressId(); 00511 kdDebug(7007) << "SlaveInterface::messageBox m_progressId=" << m_progressId << endl; 00512 int result = Observer::/*self()->*/messageBox( m_progressId, type, text, caption, buttonYes, buttonNo ); 00513 if ( m_pConnection ) // Don't do anything if deleted meanwhile 00514 { 00515 kdDebug(7007) << this << " SlaveInterface result=" << result << endl; 00516 stream << result; 00517 m_pConnection->sendnow( CMD_MESSAGEBOXANSWER, packedArgs ); 00518 } 00519 } 00520 00521 // No longer used. 00522 // Remove in KDE 4.0 00523 void SlaveInterface::sigpipe_handler(int) 00524 { 00525 int saved_errno = errno; 00526 // Using kdDebug from a signal handler is not a good idea. 00527 #ifndef NDEBUG 00528 char msg[1000]; 00529 sprintf(msg, "*** SIGPIPE *** (ignored, pid = %ld)\n", (long) getpid()); 00530 write(2, msg, strlen(msg)); 00531 #endif 00532 00533 // Do nothing. 00534 // dispatch will return false and that will trigger ERR_SLAVE_DIED in slave.cpp 00535 errno = saved_errno; 00536 } 00537 00538 void SlaveInterface::virtual_hook( int, void* ) 00539 { /*BASE::virtual_hook( id, data );*/ } 00540 00541 #include "slaveinterface.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 20 09:49:17 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003