diff options
Diffstat (limited to 'kopete/protocols/msn/transport.cpp')
-rw-r--r-- | kopete/protocols/msn/transport.cpp | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/kopete/protocols/msn/transport.cpp b/kopete/protocols/msn/transport.cpp new file mode 100644 index 00000000..492117b6 --- /dev/null +++ b/kopete/protocols/msn/transport.cpp @@ -0,0 +1,356 @@ +/* + transport.cpp - Peer to peer transport + + Copyright (c) 2005 by Gregg Edghill <gregg.edghill@gmail.com> + + Kopete (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + ************************************************************************* +*/ + +#include "transport.h" +#include "messageformatter.h" + +//BEGIN QT Includes +//END + +//BEGIN KDE Includes +#include <kclientsocketbase.h> +#include <kdebug.h> +#include <kstreamsocket.h> +//END + +//BEGIN Using Directives +using namespace KNetwork; +//END + +#include "msnswitchboardsocket.h" + +namespace PeerToPeer { + +Transport::Transport(QObject* parent, const char* name) + : QObject(parent, name) +{ + mFormatter = new PeerToPeer::MessageFormatter(this); +} + + +Transport::~Transport() +{ +} + +//BEGIN Public Methods + +TransportBridge* Transport::getBridge (const QString& to, Q_UINT16 port, TransportBridgeType type, const QString& identifier) +{ + TransportBridge *bridge = 0l; + KInetSocketAddress address; + if (mAddresses.contains(to)) + { + address = mAddresses[to]; + } + else + { + address = KInetSocketAddress(KIpAddress(to), port); + mAddresses[to] = address; + } + + if (PeerToPeer::Tcp == type){ + bridge = new TcpTransportBridge(address, mFormatter, this, identifier.ascii()); + } + + if (PeerToPeer::Udp == type){ +// TODO Add class UdpTransportBridge +// bridge = new UdpTransportBridge(address, this, mFormatter, identifier.ascii()); + } + + if (bridge != 0l) + { + QObject::connect(bridge, SIGNAL(readyRead(const QByteArray&)), SLOT(slotOnReceive(const QByteArray&))); + } + + return 0l; +} + +void Transport::setDefaultBridge(MSNSwitchBoardSocket* mss) +{ + mDefaultBridge = mss; + QObject::connect((MSNSwitchBoardSocket*)mDefaultBridge, SIGNAL(messageReceived(const QString&, const QByteArray&)), SLOT(slotOnReceive(const QString&, const QByteArray&))); +} + +//END + +//BEGIN Private Slot Methods + +// void Transport::slotOnReceive(Message& message) +// { +// } + +void Transport::slotOnReceive(const QString& contact, const QByteArray& bytes) +{ + kdDebug (14140) << k_funcinfo << " >> RECEIVED " << bytes.size() << " bytes." << endl; +// Message message = mFormatter->readMessage(bytes); +} + +//END + + + + +TransportBridge::TransportBridge(const KNetwork::KInetSocketAddress& to, MessageFormatter* formatter, QObject* parent, const char* name) +: QObject(parent, name) +{ + mAddress = to; + mFormatter = formatter; +} + +TransportBridge::TransportBridge(KNetwork::KClientSocketBase* socket, MessageFormatter* formatter, QObject* parent, const char* name) +: QObject(parent, name) +{ + mSocket = socket; + mAddress = mSocket->peerAddress(); +} + +TransportBridge::~TransportBridge() +{ +} + +//BEGIN Public Methods + +void TransportBridge::connect() +{ + slotOnConnect(); +} + +void TransportBridge::disconnect() +{ + slotOnDisconnect(); +} + +//END + +//BEGIN Protected Slot Methods + +void TransportBridge::slotOnConnect() +{ +} + +void TransportBridge::slotOnDisconnect() +{ +} + +void TransportBridge::slotOnError(int) +{ +} + +void TransportBridge::slotOnSocketClose() +{ +} + +void TransportBridge::slotOnSocketConnect() +{ +} + +void TransportBridge::slotOnSocketReceive() +{ +} + + +//END + + + +TcpTransportBridge::TcpTransportBridge(const KNetwork::KInetSocketAddress& to, MessageFormatter* formatter, QObject* parent, const char* name) +: TransportBridge(to, formatter, parent, name) +{ + mSocket = new KStreamSocket(mAddress.ipAddress().toString(), QString::number(mAddress.port()), this); + mSocket->setBlocking(false); + QObject::connect(mSocket, SIGNAL(connected(const KResolverEntry&)), SLOT(slotOnSocketConnect())); + QObject::connect(mSocket, SIGNAL(gotError(int)), SLOT(slotOnError(int))); + mConnected = false; +} + +TcpTransportBridge::TcpTransportBridge(KNetwork::KClientSocketBase* socket, MessageFormatter* formatter, QObject* parent, const char* name) +: TransportBridge(socket, formatter, parent, name) +{ + mConnected = (mSocket->state() == KStreamSocket::Open) ? true : false; + mSocket->setBlocking(false); +} + +TcpTransportBridge::~TcpTransportBridge() +{ +} + +//BEGIN Protected Slot Methods + +void TcpTransportBridge::slotOnConnect() +{ + if (mConnected) + { + kdDebug(14140) << k_funcinfo << "Bridge (" << name() << ") ALREADY CONNECTED " << mSocket->peerAddress().toString() << " <-> " << mSocket->localAddress().toString() << endl; + return; + } + + KStreamSocket *socket = static_cast<KStreamSocket*>(mSocket); + socket->setTimeout(5000); + QObject::connect(socket, SIGNAL(timeOut()), SLOT(slotOnSocketConnectTimeout())); + mSocket->connect(); +} + +void TcpTransportBridge::slotOnDisconnect() +{ + if (mConnected){ + mSocket->close(); + } +} + +void TcpTransportBridge::slotOnError(int errorCode) +{ + kdDebug(14140) << k_funcinfo << "Bridge (" << name() << ") ERROR occurred on {" << mSocket->localAddress().toString() << " <-> " << mSocket->peerAddress().toString() << "} - " << mSocket->errorString() << endl; + emit bridgeError(QString("Bridge ERROR %1: %2").arg(errorCode).arg(mSocket->errorString())); + if (mConnected){ + mSocket->disconnect(); + mConnected = false; + } + mSocket->deleteLater(); + mSocket = 0l; +} + +void TcpTransportBridge::slotOnSocketClose() +{ + mSocket->disconnect(); + kdDebug(14140) << k_funcinfo << "Bridge (" << name() << ") DISCONNECTED {" << mSocket->peerAddress().toString() << " <-> " << mSocket->localAddress().toString() << "}" << endl; + mConnected = false; + mSocket->deleteLater(); + mSocket = 0l; + + emit bridgeDisconnect(); +} + +void TcpTransportBridge::slotOnSocketConnect() +{ + kdDebug(14140) << k_funcinfo << "Bridge (" << name() << ") CONNECTED to " << mSocket->peerAddress().toString() << " from " + << mSocket->localAddress().toString() << endl; + mConnected = true; + + QObject::connect(mSocket, SIGNAL(readyRead()), SLOT(slotOnSocketReceive())); + QObject::connect(mSocket, SIGNAL(closed()), SLOT(slotOnSocketClose())); + + mVerified = true; + QString foo = "foo\0"; + mSocket->writeBlock(foo.ascii(), foo.length()); + foo = QString::null; + + emit bridgeConnect(); +} + +void TcpTransportBridge::slotOnSocketReceive() +{ + kdDebug (14140) << k_funcinfo << "Bridge (" << name() << ") RECEIVED " << mSocket->bytesAvailable() << " bytes." << endl; + + QByteArray bytes(mSocket->bytesAvailable()); + mSocket->readBlock(bytes.data(), bytes.size()); + // Write the data to the buffer. + mBuffer.write(bytes); + + if (mVerified == false && mBuffer.size() >= 4) + { + QByteArray foo = mBuffer.read(4); + if (QString(foo) == "foo"){ + kdDebug (14140) << k_funcinfo << "Bridge (" << name() << ") CONNECTION verified." << endl; + mVerified = true; + } + } + + while(mBuffer.size() > 0) + { + if (mBuffer.size() >= 4 && mLength == 0) + { + QByteArray array = mBuffer.read(4); + for (int i=0; i < 4; i++){ + ((char*)mLength)[i] = array[i]; + } + } + + if (mLength > 0 && mBuffer.size() >= mLength) + { + kdDebug (14140) << k_funcinfo << "Bridge (" << name() << ") read " << mLength << " bytes." << endl; + bytes = mBuffer.read(mLength); + mLength = 0; +// Message message = mFormatter->readMessage(bytes, true); +// emit messageReceived(message); + } + else + { + kdDebug (14140) << k_funcinfo << "Bridge (" << name() << ") waiting for " << mLength << " bytes." << endl; + break; + } + } +} + +//END + +//BEGIN Private Slot Methods + +void TcpTransportBridge::slotOnSocketConnectTimeout() +{ + kdDebug (14140) << k_funcinfo << "Bridge (" << name() << ") CONNECT timeout." << endl; + emit bridgeConnectTimeout(); + mSocket->deleteLater(); + mSocket = 0l; +} + +//END + + + + +TcpTransportBridge::Buffer::Buffer(Q_UINT32 length) +: QByteArray(length) +{ +} + +TcpTransportBridge::Buffer::~Buffer() +{ +} + +//BEGIN Public Methods + +void TcpTransportBridge::Buffer::write(const QByteArray& bytes) +{ + resize(size() + bytes.size()); + for (uint i=0; i < bytes.size(); i++){ + (*this)[size() + i] = bytes[i]; + } +} + +QByteArray TcpTransportBridge::Buffer::read(Q_UINT32 length) +{ + if (length >= size()) return QByteArray(); + + QByteArray buffer; + buffer.duplicate(data(), length); + + char *bytes = new char[size() - length]; + for(uint i=0; i < size() - length; i++){ + bytes[i] = data()[length + i]; + } + + duplicate(bytes, size() - length); + delete[] bytes; + + return buffer; +} + +//END + +} + +#include "transport.moc" + |