kio Library API Documentation

connection.cpp

00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2000 Stephan Kulow <coolo@kde.org>
00003                        David Faure <faure@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018     Boston, MA 02111-1307, USA.
00019 */
00020 
00021 // $Id$
00022 
00023 #include <config.h>
00024 
00025 #include <kde_file.h>
00026 #include <ksock.h>
00027 #include <qtimer.h>
00028 
00029 #include <sys/types.h>
00030 #include <sys/signal.h>
00031 #include <sys/time.h>
00032 
00033 #include <errno.h>
00034 #include <fcntl.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <signal.h>
00038 #include <string.h>
00039 #include <unistd.h>
00040 
00041 #include "kio/connection.h"
00042 
00043 #include <kdebug.h>
00044 #include <qsocketnotifier.h>
00045 
00046 using namespace KIO;
00047 
00048 Connection::Connection()
00049 {
00050     f_out = 0;
00051     fd_in = -1;
00052     socket = 0;
00053     notifier = 0;
00054     receiver = 0;
00055     member = 0;
00056     m_suspended = false;
00057     tasks.setAutoDelete(true);
00058 }
00059 
00060 Connection::~Connection()
00061 {
00062     close();
00063 }
00064 
00065 void Connection::suspend()
00066 {
00067     m_suspended = true;
00068     if (notifier)
00069        notifier->setEnabled(false);
00070 }
00071 
00072 void Connection::resume()
00073 {
00074     m_suspended = false;
00075     if (notifier)
00076        notifier->setEnabled(true);
00077 }
00078 
00079 void Connection::close()
00080 {
00081     delete notifier;
00082     notifier = 0;
00083     delete socket;
00084     socket = 0;
00085 
00086     // KSocket has already closed the file descriptor, but we need to
00087     // close the file-stream as well otherwise we leak memory. 
00088     // As a result we close the file descriptor twice, but that should
00089     // be harmless
00090     // KDE4: fix this
00091     if (f_out)
00092        fclose(f_out);
00093     f_out = 0;
00094     fd_in = -1;
00095     tasks.clear();
00096 }
00097 
00098 void Connection::send(int cmd, const QByteArray& data)
00099 {
00100     if (!inited() || tasks.count() > 0) {
00101     Task *task = new Task();
00102     task->cmd = cmd;
00103     task->data = data;
00104     tasks.append(task);
00105     } else {
00106     sendnow( cmd, data );
00107     }
00108 }
00109 
00110 void Connection::dequeue()
00111 {
00112     if (!inited())
00113     return;
00114 
00115     while (tasks.count())
00116     {
00117        tasks.first();
00118        Task *task = tasks.take();
00119        sendnow( task->cmd, task->data );
00120        delete task;
00121     }
00122 }
00123 
00124 void Connection::init(KSocket *sock)
00125 {
00126     delete notifier;
00127     notifier = 0;
00128 #ifdef Q_OS_UNIX //TODO: not yet available on WIN32
00129     delete socket;
00130     socket = sock;
00131     fd_in = socket->socket();
00132     f_out = KDE_fdopen( socket->socket(), "wb" );
00133 #endif
00134     if (receiver && ( fd_in != -1 )) {
00135     notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
00136     if ( m_suspended ) {
00137             suspend();
00138     }
00139     QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
00140     }
00141     dequeue();
00142 }
00143 
00144 void Connection::init(int _fd_in, int fd_out)
00145 {
00146     delete notifier;
00147     notifier = 0;
00148     fd_in = _fd_in;
00149     f_out = KDE_fdopen( fd_out, "wb" );
00150     if (receiver && ( fd_in != -1 )) {
00151     notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
00152     if ( m_suspended ) {
00153             suspend();
00154     }
00155     QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
00156     }
00157     dequeue();
00158 }
00159 
00160 
00161 void Connection::connect(QObject *_receiver, const char *_member)
00162 {
00163     receiver = _receiver;
00164     member = _member;
00165     delete notifier;
00166     notifier = 0;
00167     if (receiver && (fd_in != -1 )) {
00168     notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
00169         if ( m_suspended )
00170             suspend();
00171     QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
00172     }
00173 }
00174 
00175 bool Connection::sendnow( int _cmd, const QByteArray &data )
00176 {
00177     if (f_out == 0) {
00178     return false;
00179     }
00180 
00181     if (data.size() > 0xffffff)
00182         return false;
00183 
00184     static char buffer[ 64 ];
00185     sprintf( buffer, "%6x_%2x_", data.size(), _cmd );
00186 
00187     size_t n = fwrite( buffer, 1, 10, f_out );
00188 
00189     if ( n != 10 ) {
00190     kdError(7017) << "Could not send header" << endl;
00191     return false;
00192     }
00193 
00194     n = fwrite( data.data(), 1, data.size(), f_out );
00195 
00196     if ( n != data.size() ) {
00197     kdError(7017) << "Could not write data" << endl;
00198     return false;
00199     }
00200 
00201     fflush( f_out );
00202 
00203     return true;
00204 }
00205 
00206 int Connection::read( int* _cmd, QByteArray &data )
00207 {
00208     if (fd_in == -1 ) {
00209     kdError(7017) << "read: not yet inited" << endl;
00210     return -1;
00211     }
00212 
00213     static char buffer[ 10 ];
00214 
00215  again1:
00216     ssize_t n = ::read( fd_in, buffer, 10);
00217     if ( n == -1 && errno == EINTR )
00218     goto again1;
00219 
00220     if ( n == -1) {
00221     kdError(7017) << "Header read failed, errno=" << errno << endl;
00222     }
00223 
00224     if ( n != 10 ) {
00225       if ( n ) // 0 indicates end of file
00226         kdError(7017) << "Header has invalid size (" << n << ")" << endl;
00227       return -1;
00228     }
00229 
00230     buffer[ 6 ] = 0;
00231     buffer[ 9 ] = 0;
00232 
00233     char *p = buffer;
00234     while( *p == ' ' ) p++;
00235     long int len = strtol( p, 0L, 16 );
00236 
00237     p = buffer + 7;
00238     while( *p == ' ' ) p++;
00239     long int cmd = strtol( p, 0L, 16 );
00240 
00241     data.resize( len );
00242 
00243     if ( len > 0L ) {
00244     size_t bytesToGo = len;
00245     size_t bytesRead = 0;
00246     do {
00247         n = ::read(fd_in, data.data()+bytesRead, bytesToGo);
00248         if (n == -1) {
00249         if (errno == EINTR)
00250             continue;
00251 
00252         kdError(7017) << "Data read failed, errno=" << errno << endl;
00253         return -1;
00254         }
00255 
00256         bytesRead += n;
00257         bytesToGo -= n;
00258     }
00259     while(bytesToGo);
00260     }
00261 
00262     *_cmd = cmd;
00263     return len;
00264 }
00265 
00266 #include "connection.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Feb 8 08:02:20 2006 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003