connection.cpp
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 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 )
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"
This file is part of the documentation for kio Library Version 3.4.2.