You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
6.4 KiB
280 lines
6.4 KiB
/* 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 <tqtimer.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 "tdeio/connection.h"
|
|
|
|
#include <kdebug.h>
|
|
#include <tqsocketnotifier.h>
|
|
|
|
#if defined(__OpenBSD__)
|
|
#define __progname getprogname()
|
|
#else
|
|
extern char *__progname;
|
|
#endif
|
|
|
|
using namespace TDEIO;
|
|
|
|
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;
|
|
|
|
// TDESocket 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 TQByteArray& 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(TDESocket *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 TQSocketNotifier(fd_in, TQSocketNotifier::Read);
|
|
if ( m_suspended ) {
|
|
suspend();
|
|
}
|
|
TQObject::connect(notifier, TQT_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 TQSocketNotifier(fd_in, TQSocketNotifier::Read);
|
|
if ( m_suspended ) {
|
|
suspend();
|
|
}
|
|
TQObject::connect(notifier, TQT_SIGNAL(activated(int)), receiver, member);
|
|
}
|
|
dequeue();
|
|
}
|
|
|
|
|
|
void Connection::connect(TQObject *_receiver, const char *_member)
|
|
{
|
|
receiver = _receiver;
|
|
member = _member;
|
|
delete notifier;
|
|
notifier = 0;
|
|
if (receiver && (fd_in != -1 )) {
|
|
notifier = new TQSocketNotifier(fd_in, TQSocketNotifier::Read);
|
|
if ( m_suspended )
|
|
suspend();
|
|
TQObject::connect(notifier, TQT_SIGNAL(activated(int)), receiver, member);
|
|
}
|
|
}
|
|
|
|
bool Connection::sendnow( int _cmd, const TQByteArray &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 (pid " << getpid() << " process \"" << __progname << "\")" << endl;
|
|
return false;
|
|
}
|
|
|
|
n = fwrite( data.data(), 1, data.size(), f_out );
|
|
|
|
if ( n != data.size() ) {
|
|
kdError(7017) << "Could not write data (pid " << getpid() << " process \"" << __progname << "\")" << endl;
|
|
return false;
|
|
}
|
|
|
|
if (fflush( f_out )) {
|
|
kdError(7017) << "Could not write data (pid " << getpid() << " process \"" << __progname << "\")" << endl;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int Connection::read( int* _cmd, TQByteArray &data )
|
|
{
|
|
if (fd_in == -1 ) {
|
|
kdError(7017) << "read: not yet inited (pid " << getpid() << " process \"" << __progname << "\")" << 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 << " (pid " << getpid() << " process \"" << __progname << "\")" << endl;
|
|
}
|
|
|
|
if ( n != 10 ) {
|
|
if ( n ) // 0 indicates end of file
|
|
kdError(7017) << "Header has invalid size (" << n << ") (pid " << getpid() << " process \"" << __progname << "\")" << 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 << " (pid " << getpid() << " process \"" << __progname << "\")" << endl;
|
|
return -1;
|
|
}
|
|
if ( !n ) { // 0 indicates end of file
|
|
kdError(7017) << "Connection ended unexpectedly (" << n << "/" << bytesToGo << ") (pid " << getpid() << " process \"" << __progname << "\")" << endl;
|
|
return -1;
|
|
}
|
|
|
|
bytesRead += n;
|
|
bytesToGo -= n;
|
|
}
|
|
while(bytesToGo);
|
|
}
|
|
|
|
*_cmd = cmd;
|
|
return len;
|
|
}
|
|
|
|
#include "connection.moc"
|