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"