|
|
|
/*
|
|
|
|
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(TQObject* parent, const char* name)
|
|
|
|
: TQObject(parent, name)
|
|
|
|
{
|
|
|
|
mFormatter = new PeerToPeer::MessageFormatter(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Transport::~Transport()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//BEGIN Public Methods
|
|
|
|
|
|
|
|
TransportBridge* Transport::getBridge (const TQString& to, TQ_UINT16 port, TransportBridgeType type, const TQString& 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)
|
|
|
|
{
|
|
|
|
TQObject::connect(bridge, TQT_SIGNAL(readyRead(const TQByteArray&)), TQT_SLOT(slotOnReceive(const TQByteArray&)));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Transport::setDefaultBridge(MSNSwitchBoardSocket* mss)
|
|
|
|
{
|
|
|
|
mDefaultBridge = mss;
|
|
|
|
TQObject::connect((MSNSwitchBoardSocket*)mDefaultBridge, TQT_SIGNAL(messageReceived(const TQString&, const TQByteArray&)), TQT_SLOT(slotOnReceive(const TQString&, const TQByteArray&)));
|
|
|
|
}
|
|
|
|
|
|
|
|
//END
|
|
|
|
|
|
|
|
//BEGIN Private Slot Methods
|
|
|
|
|
|
|
|
// void Transport::slotOnReceive(Message& message)
|
|
|
|
// {
|
|
|
|
// }
|
|
|
|
|
|
|
|
void Transport::slotOnReceive(const TQString& contact, const TQByteArray& bytes)
|
|
|
|
{
|
|
|
|
kdDebug (14140) << k_funcinfo << " >> RECEIVED " << bytes.size() << " bytes." << endl;
|
|
|
|
// Message message = mFormatter->readMessage(bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
//END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TransportBridge::TransportBridge(const KNetwork::KInetSocketAddress& to, MessageFormatter* formatter, TQObject* parent, const char* name)
|
|
|
|
: TQObject(parent, name)
|
|
|
|
{
|
|
|
|
mAddress = to;
|
|
|
|
mFormatter = formatter;
|
|
|
|
}
|
|
|
|
|
|
|
|
TransportBridge::TransportBridge(KNetwork::KClientSocketBase* socket, MessageFormatter* formatter, TQObject* parent, const char* name)
|
|
|
|
: TQObject(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, TQObject* parent, const char* name)
|
|
|
|
: TransportBridge(to, formatter, parent, name)
|
|
|
|
{
|
|
|
|
mSocket = new KStreamSocket(mAddress.ipAddress().toString(), TQString::number(mAddress.port()), this);
|
|
|
|
mSocket->setBlocking(false);
|
|
|
|
TQObject::connect(mSocket, TQT_SIGNAL(connected(const KResolverEntry&)), TQT_SLOT(slotOnSocketConnect()));
|
|
|
|
TQObject::connect(mSocket, TQT_SIGNAL(gotError(int)), TQT_SLOT(slotOnError(int)));
|
|
|
|
mConnected = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
TcpTransportBridge::TcpTransportBridge(KNetwork::KClientSocketBase* socket, MessageFormatter* formatter, TQObject* 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);
|
|
|
|
TQObject::connect(socket, TQT_SIGNAL(timeOut()), TQT_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(TQString("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;
|
|
|
|
|
|
|
|
TQObject::connect(mSocket, TQT_SIGNAL(readyRead()), TQT_SLOT(slotOnSocketReceive()));
|
|
|
|
TQObject::connect(mSocket, TQT_SIGNAL(closed()), TQT_SLOT(slotOnSocketClose()));
|
|
|
|
|
|
|
|
mVerified = true;
|
|
|
|
TQString foo = "foo\0";
|
|
|
|
mSocket->writeBlock(foo.ascii(), foo.length());
|
|
|
|
foo = TQString();
|
|
|
|
|
|
|
|
emit bridgeConnect();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TcpTransportBridge::slotOnSocketReceive()
|
|
|
|
{
|
|
|
|
kdDebug (14140) << k_funcinfo << "Bridge (" << name() << ") RECEIVED " << mSocket->bytesAvailable() << " bytes." << endl;
|
|
|
|
|
|
|
|
TQByteArray bytes(mSocket->bytesAvailable());
|
|
|
|
mSocket->readBlock(bytes.data(), bytes.size());
|
|
|
|
// Write the data to the buffer.
|
|
|
|
mBuffer.write(bytes);
|
|
|
|
|
|
|
|
if (mVerified == false && mBuffer.size() >= 4)
|
|
|
|
{
|
|
|
|
TQByteArray foo = mBuffer.read(4);
|
|
|
|
if (TQString(foo) == "foo"){
|
|
|
|
kdDebug (14140) << k_funcinfo << "Bridge (" << name() << ") CONNECTION verified." << endl;
|
|
|
|
mVerified = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while(mBuffer.size() > 0)
|
|
|
|
{
|
|
|
|
if (mBuffer.size() >= 4 && mLength == 0)
|
|
|
|
{
|
|
|
|
TQByteArray 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(TQ_UINT32 length)
|
|
|
|
: TQByteArray(length)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TcpTransportBridge::Buffer::~Buffer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//BEGIN Public Methods
|
|
|
|
|
|
|
|
void TcpTransportBridge::Buffer::write(const TQByteArray& bytes)
|
|
|
|
{
|
|
|
|
resize(size() + bytes.size());
|
|
|
|
for (uint i=0; i < bytes.size(); i++){
|
|
|
|
(*this)[size() + i] = bytes[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQByteArray TcpTransportBridge::Buffer::read(TQ_UINT32 length)
|
|
|
|
{
|
|
|
|
if (length >= size()) return TQByteArray();
|
|
|
|
|
|
|
|
TQByteArray 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"
|
|
|
|
|