41 class KIO::ConnectionPrivate
44 inline ConnectionPrivate()
45 : backend(0), suspended(false)
49 void commandReceived(
const Task &task);
53 QQueue<Task> outgoingTasks;
54 QQueue<Task> incomingTasks;
60 class KIO::ConnectionServerPrivate
63 inline ConnectionServerPrivate()
71 void ConnectionPrivate::dequeue()
73 if (!backend || suspended)
76 while (!outgoingTasks.isEmpty()) {
77 const Task task = outgoingTasks.dequeue();
78 q->sendnow(task.
cmd, task.
data);
81 if (!incomingTasks.isEmpty())
85 void ConnectionPrivate::commandReceived(
const Task &task)
88 if (!suspended && incomingTasks.isEmpty())
89 QMetaObject::invokeMethod(q,
"dequeue", Qt::QueuedConnection);
90 incomingTasks.enqueue(task);
93 void ConnectionPrivate::disconnected()
96 QMetaObject::invokeMethod(q,
"readyRead", Qt::QueuedConnection);
103 q->connect(backend, SIGNAL(commandReceived(
Task)), SLOT(commandReceived(
Task)));
104 q->connect(backend, SIGNAL(disconnected()), SLOT(disconnected()));
120 signalEmitted(false), mode(m)
142 socket->setReadBufferSize(1);
145 socket->setReadBufferSize(StandardBufferSize);
146 if (socket->bytesAvailable() >= HeaderSize) {
148 QMetaObject::invokeMethod(
this,
"socketReadyRead", Qt::QueuedConnection);
154 QByteArray data = socket->read(socket->bytesAvailable() + 1);
155 for (
int i = data.size(); --i >= 0; )
156 socket->ungetChar(data[i]);
173 if (url.
queryItem(QLatin1String(
"abstract")) == QLatin1String(
"1"))
180 socket->connectToHost(url.host(),url.port());
182 if (!socket->waitForConnected(1000)) {
184 kDebug() <<
"could not connect to " << url;
210 socketfile->
setSuffix(QLatin1String(
".slave-socket"));
211 if (!socketfile->open())
218 QString sockname = socketfile->fileName();
219 KUrl addressUrl(sockname);
235 tcpServer->listen(QHostAddress::LocalHost);
255 if (socket->state() != QAbstractSocket::ConnectedState) {
260 signalEmitted =
false;
261 if (socket->bytesAvailable())
270 while (socket->state() == QAbstractSocket::ConnectedState && !signalEmitted &&
271 (ms == -1 || timer.elapsed() < ms))
272 if (!socket->waitForReadyRead(ms == -1 ? -1 : ms - timer.elapsed()))
277 if (socket->state() != QAbstractSocket::ConnectedState)
287 static char buffer[HeaderSize + 2];
288 sprintf(buffer,
"%6x_%2x_", task.
data.size(), task.
cmd);
289 socket->write(buffer, HeaderSize);
290 socket->write(task.
data);
297 while (socket->bytesToWrite() > 0 && socket->state() == QAbstractSocket::ConnectedState)
298 socket->waitForBytesWritten(-1);
300 return socket->state() == QAbstractSocket::ConnectedState;
315 newSocket =
tcpServer->nextPendingConnection();
321 result->socket = newSocket;
322 newSocket->setParent(result);
323 connect(newSocket, SIGNAL(readyRead()), result, SLOT(
socketReadyRead()));
331 bool shouldReadAnother;
340 static char buffer[HeaderSize];
342 if (socket->bytesAvailable() < HeaderSize) {
346 socket->read(buffer,
sizeof buffer);
351 while( *p ==
' ' ) p++;
352 len = strtol( p, 0L, 16 );
355 while( *p ==
' ' ) p++;
356 cmd = strtol( p, 0L, 16 );
362 QPointer<SocketConnectionBackend> that =
this;
365 if (socket->bytesAvailable() >= len) {
369 task.
data = socket->read(len);
372 signalEmitted =
true;
374 }
else if (len > StandardBufferSize) {
375 kDebug(7017) <<
this <<
"Jumbo packet of" << len <<
"bytes";
376 socket->setReadBufferSize(len + 1);
385 shouldReadAnother = socket->bytesAvailable() >= HeaderSize;
387 shouldReadAnother = socket->bytesAvailable() >= len;
389 while (shouldReadAnother);
392 Connection::Connection(
QObject *parent)
393 :
QObject(parent), d(new ConnectionPrivate)
398 Connection::~Connection()
404 void Connection::suspend()
409 d->backend->setSuspended(
true);
412 void Connection::resume()
415 QMetaObject::invokeMethod(
this,
"dequeue", Qt::QueuedConnection);
418 d->suspended =
false;
420 d->backend->setSuspended(
false);
423 void Connection::close()
426 d->backend->disconnect(
this);
427 d->backend->deleteLater();
430 d->outgoingTasks.clear();
431 d->incomingTasks.clear();
434 bool Connection::isConnected()
const
439 bool Connection::inited()
const
444 bool Connection::suspended()
const
449 void Connection::connectToRemote(
const QString &address)
455 if (scheme == QLatin1String(
"local")) {
457 }
else if (scheme == QLatin1String(
"tcp")) {
460 kWarning(7017) <<
"Unknown requested KIO::Connection protocol='" << scheme
461 <<
"' (" << address <<
")";
467 if (!d->backend->connectToRemote(url)) {
477 QString Connection::errorString()
const
480 return d->backend->errorString;
484 bool Connection::send(
int cmd,
const QByteArray& data)
486 if (!inited() || !d->outgoingTasks.isEmpty()) {
490 d->outgoingTasks.enqueue(task);
493 return sendnow(cmd, data);
497 bool Connection::sendnow(
int _cmd,
const QByteArray &data)
499 if (data.size() > 0xffffff)
509 return d->backend->sendCommand(task);
512 bool Connection::hasTaskAvailable()
const
514 return !d->incomingTasks.isEmpty();
517 bool Connection::waitForIncomingTask(
int ms)
523 return d->backend->waitForIncomingTask(ms);
527 int Connection::read(
int* _cmd, QByteArray &data )
530 if (d->incomingTasks.isEmpty()) {
534 const Task task = d->incomingTasks.dequeue();
541 if (!d->suspended && !d->incomingTasks.isEmpty())
542 QMetaObject::invokeMethod(
this,
"dequeue", Qt::QueuedConnection);
547 ConnectionServer::ConnectionServer(
QObject *parent)
548 :
QObject(parent), d(new ConnectionServerPrivate)
553 ConnectionServer::~ConnectionServer()
558 void ConnectionServer::listenForRemote()
565 if (!d->backend->listenForRemote()) {
571 connect(d->backend, SIGNAL(newConnection()), SIGNAL(newConnection()));
572 kDebug(7017) <<
"Listening on " << d->backend->address;
575 QString ConnectionServer::address()
const
578 return d->backend->address;
582 bool ConnectionServer::isListening()
const
587 void ConnectionServer::close()
593 Connection *ConnectionServer::nextPendingConnection()
602 Connection *result =
new Connection;
603 result->d->setBackend(newBackend);
604 newBackend->setParent(result);
609 void ConnectionServer::setNextPendingConnection(Connection *conn)
612 Q_ASSERT(newBackend);
614 conn->d->backend = newBackend;
615 conn->d->setBackend(newBackend);
616 newBackend->setParent(conn);
621 #include "connection_p.moc"
622 #include "connection.moc"
QString i18n(const char *text)
~AbstractConnectionBackend()
void commandReceived(const Task &task)
void setPrefix(const QString &prefix)
virtual KLocalSocket * nextPendingConnection()
void setSuffix(const QString &suffix)
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
virtual void setSuspended(bool enable)=0
QString errorString() const
bool waitForIncomingTask(int ms)
void setProtocol(const QString &proto)
QString localPath() const
~SocketConnectionBackend()
KLocalSocket::LocalSocketType localSocketType() const
virtual AbstractConnectionBackend * nextPendingConnection()=0
void setSuspended(bool enable)
enum KIO::AbstractConnectionBackend::@0 state
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
KLocalSocketServer * localServer
static QString locateLocal(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
void connectToPath(const QString &path, OpenMode mode=ReadWrite)
SocketConnectionBackend(Mode m, QObject *parent=0)
const KComponentData & mainComponent()
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
bool sendCommand(const Task &task)
AbstractConnectionBackend(QObject *parent=0)
bool connectToRemote(const KUrl &url)
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
void socketDisconnected()
AbstractConnectionBackend * nextPendingConnection()
KAction * close(const QObject *recvr, const char *slot, QObject *parent)
QString queryItem(const QString &item) const
bool listen(const QString &path, KLocalSocket::LocalSocketType type=KLocalSocket::UnixSocket)
QString number(KIO::filesize_t size)
Converts a size to a string representation Not unlike QString::number(...)