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: connection.cpp,v 1.47.2.1 2003/02/12 00:43:57 pfeiffer Exp $
00022 
00023 #include <config.h>
00024 
00025 #include <ksock.h>
00026 #include <qtimer.h>
00027 
00028 #include <sys/types.h>
00029 #include <sys/signal.h>
00030 #include <sys/time.h>
00031 
00032 #include <errno.h>
00033 #include <fcntl.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <signal.h>
00037 #include <string.h>
00038 #include <unistd.h>
00039 
00040 #include "kio/connection.h"
00041 
00042 #include <kdebug.h>
00043 #include <qsocketnotifier.h>
00044 
00045 using namespace KIO;
00046 
00047 Connection::Connection()
00048 {
00049     f_out = 0;
00050     fd_in = -1;
00051     socket = 0;
00052     notifier = 0;
00053     receiver = 0;
00054     member = 0;
00055     m_suspended = false;
00056     tasks.setAutoDelete(true);
00057 }
00058 
00059 Connection::~Connection()
00060 {
00061     close();
00062 }
00063 
00064 void Connection::suspend()
00065 {
00066     m_suspended = true;
00067     if (notifier)
00068        notifier->setEnabled(false);
00069 }
00070 
00071 void Connection::resume()
00072 {
00073     m_suspended = false;
00074     if (notifier)
00075        notifier->setEnabled(true);
00076 }
00077 
00078 void Connection::close()
00079 {
00080     delete notifier;
00081     notifier = 0;
00082     delete socket;
00083     socket = 0;
00084 //    if (f_out) // causes double close, as KSocket already closed it for us
00085 //       fclose(f_out);
00086     f_out = 0;
00087     fd_in = -1;
00088     tasks.clear();
00089 }
00090 
00091 void Connection::send(int cmd, const QByteArray& data)
00092 {
00093     if (!inited() || tasks.count() > 0) {
00094     Task *task = new Task();
00095     task->cmd = cmd;
00096     task->data = data;
00097     tasks.append(task);
00098     } else {
00099     sendnow( cmd, data );
00100     }
00101 }
00102 
00103 void Connection::dequeue()
00104 {
00105     if (!inited())
00106     return;
00107 
00108     while (tasks.count())
00109     {
00110        tasks.first();
00111        Task *task = tasks.take();
00112        sendnow( task->cmd, task->data );
00113        delete task;
00114     }
00115 }
00116 
00117 void Connection::init(KSocket *sock)
00118 {
00119     delete notifier;
00120     notifier = 0;
00121     delete socket;
00122     socket = sock;
00123     fd_in = socket->socket();
00124     f_out = fdopen( socket->socket(), "wb" );
00125     if (receiver && ( fd_in != -1 )) {
00126     notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
00127     if ( m_suspended ) {
00128             suspend();
00129     }
00130     QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
00131     }
00132     dequeue();
00133 }
00134 
00135 void Connection::init(int _fd_in, int fd_out)
00136 {
00137     delete notifier;
00138     notifier = 0;
00139     fd_in = _fd_in;
00140     f_out = fdopen( fd_out, "wb" );
00141     if (receiver && ( fd_in != -1 )) {
00142     notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
00143     if ( m_suspended ) {
00144             suspend();
00145     }
00146     QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
00147     }
00148     dequeue();
00149 }
00150 
00151 
00152 void Connection::connect(QObject *_receiver, const char *_member)
00153 {
00154     receiver = _receiver;
00155     member = _member;
00156     delete notifier;
00157     notifier = 0;
00158     if (receiver && (fd_in != -1 )) {
00159     notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
00160         if ( m_suspended )
00161             suspend();
00162     QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
00163     }
00164 }
00165 
00166 bool Connection::sendnow( int _cmd, const QByteArray &data )
00167 {
00168     if (f_out == 0) {
00169     return false;
00170     }
00171 
00172     if (data.size() > 0xffffff)
00173         return false;
00174 
00175     static char buffer[ 64 ];
00176     sprintf( buffer, "%6x_%2x_", data.size(), _cmd );
00177 
00178     size_t n = fwrite( buffer, 1, 10, f_out );
00179 
00180     if ( n != 10 ) {
00181     kdError(7017) << "Could not send header" << endl;
00182     return false;
00183     }
00184 
00185     n = fwrite( data.data(), 1, data.size(), f_out );
00186 
00187     if ( n != data.size() ) {
00188     kdError(7017) << "Could not write data" << endl;
00189     return false;
00190     }
00191 
00192     fflush( f_out );
00193 
00194     return true;
00195 }
00196 
00197 int Connection::read( int* _cmd, QByteArray &data )
00198 {
00199     if (fd_in == -1 ) {
00200     kdError(7017) << "read: not yet inited" << endl;
00201     return -1;
00202     }
00203 
00204     static char buffer[ 10 ];
00205 
00206  again1:
00207     ssize_t n = ::read( fd_in, buffer, 10);
00208     if ( n == -1 && errno == EINTR )
00209     goto again1;
00210 
00211     if ( n == -1) {
00212     kdError(7017) << "Header read failed, errno=" << errno << endl;
00213     }
00214 
00215     if ( n != 10 ) {
00216       if ( n ) // 0 indicates end of file
00217         kdError(7017) << "Header has invalid size (" << n << ")" << endl;
00218       return -1;
00219     }
00220 
00221     buffer[ 6 ] = 0;
00222     buffer[ 9 ] = 0;
00223 
00224     char *p = buffer;
00225     while( *p == ' ' ) p++;
00226     long int len = strtol( p, 0L, 16 );
00227 
00228     p = buffer + 7;
00229     while( *p == ' ' ) p++;
00230     long int cmd = strtol( p, 0L, 16 );
00231 
00232     data.resize( len );
00233 
00234     if ( len > 0L ) {
00235     size_t bytesToGo = len;
00236     size_t bytesRead = 0;
00237     do {
00238         n = ::read(fd_in, data.data()+bytesRead, bytesToGo);
00239         if (n == -1) {
00240         if (errno == EINTR)
00241             continue;
00242 
00243         kdError(7017) << "Data read failed, errno=" << errno << endl;
00244         return -1;
00245         }
00246 
00247         bytesRead += n;
00248         bytesToGo -= n;
00249     }
00250     while(bytesToGo);
00251     }
00252 
00253     *_cmd = cmd;
00254     return len;
00255 }
00256 
00257 #include "connection.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:15:28 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001