kio Library: slaveinterface.cpp Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

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

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:24:07 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003