kio
connection.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00087
00088
00089
00090
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 if (fflush( f_out )) {
00202 kdError(7017) << "Could not write data" << endl;
00203 return false;
00204 }
00205
00206 return true;
00207 }
00208
00209 int Connection::read( int* _cmd, QByteArray &data )
00210 {
00211 if (fd_in == -1 ) {
00212 kdError(7017) << "read: not yet inited" << endl;
00213 return -1;
00214 }
00215
00216 static char buffer[ 10 ];
00217
00218 again1:
00219 ssize_t n = ::read( fd_in, buffer, 10);
00220 if ( n == -1 && errno == EINTR )
00221 goto again1;
00222
00223 if ( n == -1) {
00224 kdError(7017) << "Header read failed, errno=" << errno << endl;
00225 }
00226
00227 if ( n != 10 ) {
00228 if ( n )
00229 kdError(7017) << "Header has invalid size (" << n << ")" << endl;
00230 return -1;
00231 }
00232
00233 buffer[ 6 ] = 0;
00234 buffer[ 9 ] = 0;
00235
00236 char *p = buffer;
00237 while( *p == ' ' ) p++;
00238 long int len = strtol( p, 0L, 16 );
00239
00240 p = buffer + 7;
00241 while( *p == ' ' ) p++;
00242 long int cmd = strtol( p, 0L, 16 );
00243
00244 data.resize( len );
00245
00246 if ( len > 0L ) {
00247 size_t bytesToGo = len;
00248 size_t bytesRead = 0;
00249 do {
00250 n = ::read(fd_in, data.data()+bytesRead, bytesToGo);
00251 if (n == -1) {
00252 if (errno == EINTR)
00253 continue;
00254
00255 kdError(7017) << "Data read failed, errno=" << errno << endl;
00256 return -1;
00257 }
00258 if ( !n ) {
00259 kdError(7017) << "Connection ended unexpectedly (" << n << "/" << bytesToGo << ")" << endl;
00260 return -1;
00261 }
00262
00263 bytesRead += n;
00264 bytesToGo -= n;
00265 }
00266 while(bytesToGo);
00267 }
00268
00269 *_cmd = cmd;
00270 return len;
00271 }
00272
00273 #include "connection.moc"