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.52 2004/10/29 11:24:38 waba Exp $ 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.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:20:18 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003