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"