slaveinterface.cpp Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | 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     // 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     struct sigaction act;
    00153     m_pConnection = connection;
    00154     m_progressId = 0;
    00155     act.sa_handler = sigpipe_handler;
    00156     sigemptyset( &act.sa_mask );
    00157     act.sa_flags = 0;
    00158     sigaction( SIGPIPE, &act, 0 );
    00159
    00160     d = new SlaveInterfacePrivate;
    00161     connect(&d->speed_timer, SIGNAL(timeout()), SLOT(calcSpeed()));
    00162 }
    00163
    00164 SlaveInterface::~SlaveInterface()
    00165 {
    00166     // Note: no kdDebug() here (scheduler is deleted very late)
    00167     m_pConnection = 0; // a bit like the "wasDeleted" of QObject...
    00168
    00169     delete d;
    00170 }
    00171
    00172 static KIO::filesize_t readFilesize_t(QDataStream &stream)
    00173 {
    00174    KIO::filesize_t result;
    00175    unsigned long ul;
    00176    stream >> ul;
    00177    result = ul;
    00178    if (stream.atEnd())
    00179       return result;
    00180    stream >> ul;
    00181    result += ((KIO::filesize_t)ul) << 32;
    00182    return result;
    00183 }
    00184
    00185
    00186 bool SlaveInterface::dispatch()
    00187 {
    00188     assert( m_pConnection );
    00189
    00190     int cmd;
    00191     QByteArray data;
    00192
    00193     if (m_pConnection->read( &cmd, data ) == -1)
    00194       return false;
    00195
    00196     return dispatch( cmd, data );
    00197 }
    00198
    00199 void SlaveInterface::calcSpeed()
    00200 {
    00201   if (d->slave_calcs_speed) {
    00202     d->speed_timer.stop();
    00203     return;
    00204   }
    00205
    00206   struct timeval tv;
    00207   gettimeofday(&tv, 0);
    00208
    00209   long diff = ((tv.tv_sec - d->start_time.tv_sec) * 1000000 +
    00210                tv.tv_usec - d->start_time.tv_usec) / 1000;
    00211   if (diff - d->last_time >= 900) {
    00212     d->last_time = diff;
    00213     if (d->nums == max_nums) {
    00214       // let's hope gcc can optimize that well enough
    00215       // otherwise I'd try memcpy :)
    00216       for (unsigned int i = 1; i < max_nums; ++i) {
    00217         d->times[i-1] = d->times[i];
    00218         d->sizes[i-1] = d->sizes[i];
    00219       }
    00220       d->nums--;
    00221     }
    00222     d->times[d->nums] = diff;
    00223     d->sizes[d->nums++] = d->filesize;
    00224
    00225     KIO::filesize_t lspeed = 1000 * (d->sizes[d->nums-1] - d->sizes[0]) / (d->times[d->nums-1] - d->times[0]);
    00226
    00227     // 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 ;
    00228
    00229     if (!lspeed) {
    00230       d->nums = 1;
    00231       d->times[0] = diff;
    00232       d->sizes[0] = d->filesize;
    00233     }
    00234     emit speed(lspeed);
    00235   }
    00236 }
    00237
    00238 bool SlaveInterface::dispatch( int _cmd, const QByteArray &rawdata )
    00239 {
    00240     //kdDebug(7007) << "dispatch " << _cmd << endl;
    00241
    00242     QDataStream stream( rawdata, IO_ReadOnly );
    00243
    00244     QString str1;
    00245     int i;
    00246     Q_INT8 b;
    00247     unsigned long ul;
    00248
    00249     switch( _cmd ) {
    00250     case MSG_DATA:
    00251         emit data( rawdata );
    00252         break;
    00253     case MSG_DATA_REQ:
    00254         emit dataReq();
    00255         break;
    00256     case MSG_FINISHED:
    00257         //kdDebug(7007) << "Finished [this = " << this << "]" << endl;
    00258         d->offset = 0;
    00259         d->speed_timer.stop();
    00260         emit finished();
    00261         break;
    00262     case MSG_STAT_ENTRY:
    00263         {
    00264             UDSEntry entry;
    00265             stream >> entry;
    00266             emit statEntry(entry);
    00267         }
    00268         break;
    00269     case MSG_LIST_ENTRIES:
    00270         {
    00271             uint count;
    00272             stream >> count;
    00273
    00274             UDSEntryList list;
    00275             UDSEntry entry;
    00276             for (uint i = 0; i < count; i++) {
    00277                 stream >> entry;
    00278                 list.append(entry);
    00279             }
    00280             emit listEntries(list);
    00281
    00282         }
    00283         break;
    00284     case MSG_RESUME: // From the put job
    00285         {
    00286             KIO::filesize_t offset = readFilesize_t(stream);
    00287             emit canResume( offset );
    00288         }
    00289         break;
    00290     case MSG_CANRESUME: // From the get job
    00291         d->filesize = d->offset;
    00292         emit canResume(0); // the arg doesn't matter
    00293         break;
    00294     case MSG_ERROR:
    00295         stream >> i >> str1;
    00296         kdDebug(7007) << "error " << i << " " << str1 << endl;
    00297         emit error( i, str1 );
    00298         break;
    00299     case MSG_SLAVE_STATUS:
    00300         {
    00301            pid_t pid;
    00302            QCString protocol;
    00303            stream >> pid >> protocol >> str1 >> b;
    00304            emit slaveStatus(pid, protocol, str1, (b != 0));
    00305         }
    00306         break;
    00307     case MSG_CONNECTED:
    00308         emit connected();
    00309         break;
    00310
    00311     case INF_TOTAL_SIZE:
    00312         {
    00313             KIO::filesize_t size = readFilesize_t(stream);
    00314             gettimeofday(&d->start_time, 0);
    00315             d->last_time = 0;
    00316             d->filesize = d->offset;
    00317             d->sizes[0] = d->filesize;
    00318             d->times[0] = 0;
    00319             d->nums = 1;
    00320             d->speed_timer.start(1000);
    00321             d->slave_calcs_speed = false;
    00322             emit totalSize( size );
    00323         }
    00324         break;
    00325     case INF_PROCESSED_SIZE:
    00326         {
    00327             KIO::filesize_t size = readFilesize_t(stream);
    00328             emit processedSize( size );
    00329             d->filesize = size;
    00330         }
    00331         break;
    00332     case INF_SPEED:
    00333         stream >> ul;
    00334         d->slave_calcs_speed = true;
    00335         d->speed_timer.stop();
    00336
    00337         emit speed( ul );
    00338         break;
    00339     case INF_GETTING_FILE:
    00340         break;
    00341     case INF_ERROR_PAGE:
    00342         emit errorPage();
    00343         break;
    00344     case INF_REDIRECTION:
    00345       {
    00346         KURL url;
    00347         stream >> url;
    00348
    00349         emit redirection( url );
    00350       }
    00351       break;
    00352     case INF_MIME_TYPE:
    00353         stream >> str1;
    00354
    00355         emit mimeType( str1 );
    00356         if (!m_pConnection->suspended())
    00357             m_pConnection->sendnow( CMD_NONE, QByteArray() );
    00358         break;
    00359     case INF_WARNING:
    00360         stream >> str1;
    00361
    00362         emit warning( str1 );
    00363         break;
    00364     case INF_NEED_PASSWD: {
    00365         AuthInfo info;
    00366         stream >> info;
    00367         openPassDlg( info );
    00368         break;
    00369     }
    00370     case INF_MESSAGEBOX: {
    00371         kdDebug(7007) << "needs a msg box" << endl;
    00372         QString text, caption, buttonYes, buttonNo;
    00373         int type;
    00374         stream >> type >> text >> caption >> buttonYes >> buttonNo;
    00375         messageBox(type, text, caption, buttonYes, buttonNo);
    00376         break;
    00377     }
    00378     case INF_INFOMESSAGE: {
    00379         QString msg;
    00380         stream >> msg;
    00381         infoMessage(msg);
    00382         break;
    00383     }
    00384     case INF_META_DATA: {
    00385         MetaData meta_data;
    00386         stream >> meta_data;
    00387         metaData(meta_data);
    00388         break;
    00389     }
    00390     case MSG_NET_REQUEST: {
    00391         QString host;
    00392         QString slaveid;
    00393         stream >> host >> slaveid;
    00394         requestNetwork(host, slaveid);
    00395         break;
    00396     }
    00397     case MSG_NET_DROP: {
    00398         QString host;
    00399         QString slaveid;
    00400         stream >> host >> slaveid;
    00401         dropNetwork(host, slaveid);
    00402         break;
    00403     }
    00404     case MSG_NEED_SUBURL_DATA: {
    00405         emit needSubURLData();
    00406         break;
    00407     }
    00408     case MSG_AUTH_KEY: {
    00409         bool keep;
    00410         QCString key, group;
    00411         stream >> key >> group >> keep;
    00412         kdDebug(7007) << "Got auth-key:      " << key << endl
    00413                       << "    group-key:     " << group << endl
    00414                       << "    keep password: " << keep << endl;
    00415         emit authorizationKey( key, group, keep );
    00416         break;
    00417     }
    00418     case MSG_DEL_AUTH_KEY: {
    00419         QCString key;
    00420         stream >> key;
    00421         kdDebug(7007) << "Delete auth-key: " << key << endl;
    00422         emit delAuthorization( key );
    00423     }
    00424     default:
    00425         kdWarning(7007) << "Slave sends unknown command (" << _cmd << "), dropping slave" << endl;
    00426         return false;
    00427     }
    00428     return true;
    00429 }
    00430
    00431 void SlaveInterface::setOffset( KIO::filesize_t o)
    00432 {
    00433     d->offset = o;
    00434 }
    00435
    00436 KIO::filesize_t SlaveInterface::offset() const { return d->offset; }
    00437
    00438 void SlaveInterface::requestNetwork(const QString &host, const QString &slaveid)
    00439 {
    00440     kdDebug(7007) << "requestNetwork " << host << slaveid << endl;
    00441     QByteArray packedArgs;
    00442     QDataStream stream( packedArgs, IO_WriteOnly );
    00443     stream << true;
    00444     m_pConnection->sendnow( INF_NETWORK_STATUS, packedArgs );
    00445 }
    00446
    00447 void SlaveInterface::dropNetwork(const QString &host, const QString &slaveid)
    00448 {
    00449     kdDebug(7007) << "dropNetwork " << host << slaveid << endl;
    00450 }
    00451
    00452 void SlaveInterface::sendResumeAnswer( bool resume )
    00453 {
    00454     kdDebug(7007) << "SlaveInterface::sendResumeAnswer ok for resuming :" << resume << endl;
    00455     m_pConnection->sendnow( resume ? CMD_RESUMEANSWER : CMD_NONE, QByteArray() );
    00456 }
    00457
    00458 void SlaveInterface::openPassDlg( const QString& prompt, const QString& user, bool readOnly )
    00459 {
    00460     AuthInfo info;
    00461     info.prompt = prompt;
    00462     info.username = user;
    00463     info.readOnly = readOnly;
    00464     openPassDlg( info );
    00465 }
    00466
    00467 void SlaveInterface::openPassDlg( const QString& prompt, const QString& user,
    00468                                   const QString& caption, const QString& comment,
    00469                                   const QString& label, bool readOnly )
    00470 {
    00471     AuthInfo info;
    00472     info.prompt = prompt;
    00473     info.username = user;
    00474     info.caption = caption;
    00475     info.comment = comment;
    00476     info.commentLabel = label;
    00477     info.readOnly = readOnly;
    00478     openPassDlg( info );
    00479 }
    00480
    00481 void SlaveInterface::openPassDlg( AuthInfo& info )
    00482 {
    00483     kdDebug(7007) << "SlaveInterface::openPassDlg: "
    00484                   << "User= " << info.username
    00485                   << ", Message= " << info.prompt << endl;
    00486     bool result = Observer::self()->openPassDlg( info );
    00487     if ( m_pConnection )
    00488     {
    00489         QByteArray data;
    00490         QDataStream stream( data, IO_WriteOnly );
    00491         if ( result )
    00492         {
    00493             stream << info;
    00494             kdDebug(7007) << "SlaveInterface:::openPassDlg got: "
    00495                           << "User= " << info.username
    00496                           << ", Password= [hidden]" << endl;
    00497             m_pConnection->sendnow( CMD_USERPASS, data );
    00498         }
    00499         else
    00500             m_pConnection->sendnow( CMD_NONE, data );
    00501     }
    00502 }
    00503
    00504 void SlaveInterface::messageBox( int type, const QString &text, const QString &_caption,
    00505                                  const QString &buttonYes, const QString &buttonNo )
    00506 {
    00507     kdDebug(7007) << "messageBox " << type << " " << text << " - " << _caption << endl;
    00508     QByteArray packedArgs;
    00509     QDataStream stream( packedArgs, IO_WriteOnly );
    00510
    00511     QString caption( _caption );
    00512     if ( type == KIO::SlaveBase::SSLMessageBox )
    00513         caption = QString::fromUtf8(kapp->dcopClient()->appId()); // hack, see observer.cpp
    00514
    00515     emit needProgressId();
    00516     kdDebug(7007) << "SlaveInterface::messageBox m_progressId=" << m_progressId << endl;
    00517     int result = Observer::/*self()->*/messageBox( m_progressId, type, text, caption, buttonYes, buttonNo );
    00518     if ( m_pConnection ) // Don't do anything if deleted meanwhile
    00519     {
    00520         kdDebug(7007) << this << " SlaveInterface result=" << result << endl;
    00521         stream << result;
    00522         m_pConnection->sendnow( CMD_MESSAGEBOXANSWER, packedArgs );
    00523     }
    00524 }
    00525
    00526 void SlaveInterface::sigpipe_handler(int)
    00527 {
    00528     int saved_errno = errno;
    00529     // Using kdDebug from a signal handler is not a good idea.
    00530 #ifndef NDEBUG
    00531     char msg[1000];
    00532     sprintf(msg, "*** SIGPIPE *** (ignored, pid = %ld)\n", (long) getpid());
    00533     write(2, msg, strlen(msg));
    00534 #endif
    00535
    00536     // Do nothing.
    00537     // dispatch will return false and that will trigger ERR_SLAVE_DIED in slave.cpp
    00538     errno = saved_errno;
    00539 }
    00540
    00541 void SlaveInterface::virtual_hook( int, void* )
    00542 { /*BASE::virtual_hook( id, data );*/ }
    00543
    00544 #include "slaveinterface.moc"

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:14:40 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001