connection.cpp
/* This file is part of the KDE libraries
Copyright (C) 2000 Stephan Kulow <coolo@kde.org>
David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
// $Id$
#include <config.h>
#include <kde_file.h>
#include <ksock.h>
#include <qtimer.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "kio/connection.h"
#include <kdebug.h>
#include <qsocketnotifier.h>
using namespace KIO;
Connection::Connection()
{
f_out = 0;
fd_in = -1;
socket = 0;
notifier = 0;
receiver = 0;
member = 0;
m_suspended = false;
tasks.setAutoDelete(true);
}
Connection::~Connection()
{
close();
}
void Connection::suspend()
{
m_suspended = true;
if (notifier)
notifier->setEnabled(false);
}
void Connection::resume()
{
m_suspended = false;
if (notifier)
notifier->setEnabled(true);
}
void Connection::close()
{
delete notifier;
notifier = 0;
delete socket;
socket = 0;
// KSocket has already closed the file descriptor, but we need to
// close the file-stream as well otherwise we leak memory.
// As a result we close the file descriptor twice, but that should
// be harmless
// KDE4: fix this
if (f_out)
fclose(f_out);
f_out = 0;
fd_in = -1;
tasks.clear();
}
void Connection::send(int cmd, const QByteArray& data)
{
if (!inited() || tasks.count() > 0) {
Task *task = new Task();
task->cmd = cmd;
task->data = data;
tasks.append(task);
} else {
sendnow( cmd, data );
}
}
void Connection::dequeue()
{
if (!inited())
return;
while (tasks.count())
{
tasks.first();
Task *task = tasks.take();
sendnow( task->cmd, task->data );
delete task;
}
}
void Connection::init(KSocket *sock)
{
delete notifier;
notifier = 0;
#ifdef Q_OS_UNIX //TODO: not yet available on WIN32
delete socket;
socket = sock;
fd_in = socket->socket();
f_out = KDE_fdopen( socket->socket(), "wb" );
#endif
if (receiver && ( fd_in != -1 )) {
notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
if ( m_suspended ) {
suspend();
}
QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
}
dequeue();
}
void Connection::init(int _fd_in, int fd_out)
{
delete notifier;
notifier = 0;
fd_in = _fd_in;
f_out = KDE_fdopen( fd_out, "wb" );
if (receiver && ( fd_in != -1 )) {
notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
if ( m_suspended ) {
suspend();
}
QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
}
dequeue();
}
void Connection::connect(QObject *_receiver, const char *_member)
{
receiver = _receiver;
member = _member;
delete notifier;
notifier = 0;
if (receiver && (fd_in != -1 )) {
notifier = new QSocketNotifier(fd_in, QSocketNotifier::Read);
if ( m_suspended )
suspend();
QObject::connect(notifier, SIGNAL(activated(int)), receiver, member);
}
}
bool Connection::sendnow( int _cmd, const QByteArray &data )
{
if (f_out == 0) {
return false;
}
if (data.size() > 0xffffff)
return false;
static char buffer[ 64 ];
sprintf( buffer, "%6x_%2x_", data.size(), _cmd );
size_t n = fwrite( buffer, 1, 10, f_out );
if ( n != 10 ) {
kdError(7017) << "Could not send header" << endl;
return false;
}
n = fwrite( data.data(), 1, data.size(), f_out );
if ( n != data.size() ) {
kdError(7017) << "Could not write data" << endl;
return false;
}
if (fflush( f_out )) {
kdError(7017) << "Could not write data" << endl;
return false;
}
return true;
}
int Connection::read( int* _cmd, QByteArray &data )
{
if (fd_in == -1 ) {
kdError(7017) << "read: not yet inited" << endl;
return -1;
}
static char buffer[ 10 ];
again1:
ssize_t n = ::read( fd_in, buffer, 10);
if ( n == -1 && errno == EINTR )
goto again1;
if ( n == -1) {
kdError(7017) << "Header read failed, errno=" << errno << endl;
}
if ( n != 10 ) {
if ( n ) // 0 indicates end of file
kdError(7017) << "Header has invalid size (" << n << ")" << endl;
return -1;
}
buffer[ 6 ] = 0;
buffer[ 9 ] = 0;
char *p = buffer;
while( *p == ' ' ) p++;
long int len = strtol( p, 0L, 16 );
p = buffer + 7;
while( *p == ' ' ) p++;
long int cmd = strtol( p, 0L, 16 );
data.resize( len );
if ( len > 0L ) {
size_t bytesToGo = len;
size_t bytesRead = 0;
do {
n = ::read(fd_in, data.data()+bytesRead, bytesToGo);
if (n == -1) {
if (errno == EINTR)
continue;
kdError(7017) << "Data read failed, errno=" << errno << endl;
return -1;
}
if ( !n ) { // 0 indicates end of file
kdError(7017) << "Connection ended unexpectedly (" << n << "/" << bytesToGo << ")" << endl;
return -1;
}
bytesRead += n;
bytesToGo -= n;
}
while(bytesToGo);
}
*_cmd = cmd;
return len;
}
#include "connection.moc"
KIO::Connection::sendnow
bool sendnow(int _cmd, const QByteArray &data)
Sends the given command immediately.
Definition: connection.cpp:175
KIO::Connection::close
void close()
Closes the connection.
Definition: connection.cpp:79
KIO::Connection::init
void init(KSocket *sock)
Initialize this connection to use the given socket.
Definition: connection.cpp:124
KIO::Connection::send
void send(int cmd, const QByteArray &arr=QByteArray())
Sends/queues the given command to be sent.
Definition: connection.cpp:98
KIO::Connection::suspend
void suspend()
Don't handle incoming data until resumed.
Definition: connection.cpp:65
KIO::Connection::resume
void resume()
Resume handling of incoming data.
Definition: connection.cpp:72
KIO::Connection::Connection
Connection()
Creates a new connection.
Definition: connection.cpp:48
KIO::Connection::inited
bool inited() const
Checks whether the connection has been initialized.
Definition: connection.h:94
KIO::Connection::read
int read(int *_cmd, QByteArray &data)
Receive data.
Definition: connection.cpp:209

KDE Home | KDE Accessibility Home | Description of Access Keys