diff options
Diffstat (limited to 'kopete/protocols/msn/outgoingtransfer.cpp')
-rw-r--r-- | kopete/protocols/msn/outgoingtransfer.cpp | 432 |
1 files changed, 0 insertions, 432 deletions
diff --git a/kopete/protocols/msn/outgoingtransfer.cpp b/kopete/protocols/msn/outgoingtransfer.cpp deleted file mode 100644 index 5d66c495..00000000 --- a/kopete/protocols/msn/outgoingtransfer.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* - outgoingtransfer.cpp - msn p2p protocol - - Copyright (c) 2003-2005 by Olivier Goffart <ogoffart@ kde.org> - Copyright (c) 2005 by Gregg Edghill <gregg.edghill@gmail.com> - - ************************************************************************* - * * - * 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; either version 2 of the License, or * - * (at your option) any later version. * - * * - ************************************************************************* -*/ - -#include "outgoingtransfer.h" - -#include <stdlib.h> - -// Kde includes -#include <kbufferedsocket.h> -#include <kdebug.h> -#include <tdelocale.h> -#include <kmdcodec.h> -using namespace KNetwork; - -// TQt includes -#include <tqfile.h> -#include <tqregexp.h> -#include <tqtimer.h> - -// Kopete includes -#include <kopetetransfermanager.h> - -#include <netinet/in.h> // For htonl -using P2P::TransferContext; -using P2P::Dispatcher; -using P2P::OutgoingTransfer; -using P2P::Message; - -OutgoingTransfer::OutgoingTransfer(const TQString& to, P2P::Dispatcher *dispatcher, TQ_UINT32 sessionId) -: TransferContext(to,dispatcher,sessionId) -{ - m_direction = Outgoing; - m_handshake = 0x01; -} - -OutgoingTransfer::~OutgoingTransfer() -{ - kdDebug(14140) << k_funcinfo << endl; -} - -void OutgoingTransfer::sendImage(const TQByteArray& image) -{ - -// TODO TQByteArray base64 = KCodecs::base64Encode(image); -// -// TQCString body = "MIME-Version: 1.0\r\n" -// "Content-Type: image/gif\r\n" -// "\r\n" -// "base64:" + -// -// Message outbound; -// outbound.header.sessionId = m_sessionId; -// outbound.header.identifier = m_baseIdentifier; -// outbound.header.dataOffset = 0; -// outbound.header.totalDataSize = 4; -// outbound.header.dataSize = 4; -// outbound.header.flag = 0; -// outbound.header.ackSessionIdentifier = rand()%0x8FFFFFF0 + 4; -// outbound.header.ackUniqueIdentifier = 0; -// outbound.header.ackDataSize = 0l; -// TQByteArray bytes(4); -// bytes.fill('\0'); -// outbound.body = bytes; -// outbound.applicationIdentifier = 0; -// outbound.attachApplicationId = false; -// outbound.destination = m_recipient; -// -// sendMessage(outbound, body); -} - -void OutgoingTransfer::slotSendData() -{ - TQ_INT32 bytesRead = 0; - TQByteArray buffer(1202); - if(!m_file) - return; - - // Read a chunk from the source file. - bytesRead = m_file->readBlock(buffer.data(), buffer.size()); - - if (bytesRead < 0) { - m_file->close(); - // ### error handling - } - else { - - if(bytesRead < 1202){ - buffer.resize(bytesRead); - } - - kdDebug(14140) << k_funcinfo << TQString("Sending, %1 bytes").arg(bytesRead) << endl; - - if((m_offset + bytesRead) < m_file->size()) - { - sendData(buffer); - m_offset += bytesRead; - } - else - { - m_isComplete = true; - // Send the last chunk of the file. - sendData(buffer); - m_offset += buffer.size(); - // Close the file. - m_file->close(); - } - } - - if(m_transfer){ - m_transfer->slotProcessed(m_offset); - if(m_isComplete){ - // The transfer is complete. - m_transfer->slotComplete(); - } - } -} - -void OutgoingTransfer::acknowledged() -{ - kdDebug(14140) << k_funcinfo << endl; - - switch(m_state) - { - case Invitation: - { - if(m_type == UserDisplayIcon) - { - m_state = Negotiation; - // Send data preparation message. - sendDataPreparation(); - } - break; - } - - case Negotiation: - { - if(m_type == UserDisplayIcon) - { - // <<< Data preparation acknowledge message. - m_state = DataTransfer; - m_identifier++; - // Start sending data. - slotSendData(); - } - break; - } - - case DataTransfer: - // NOTE <<< Data acknowledged message. - // <<< Bye message should follow. - if(m_type == File) - { - if(m_handshake == 0x01) - { - // Data handshake acknowledge message. - // Start sending data. - slotSendData(); - } - else if(m_handshake == 0x02) - { - // Data acknowledge message. - // Send the recipient a BYE message. - m_state = Finished; - sendMessage(BYE, "\r\n"); - } - } - - break; - - case Finished: - if(m_type == File) - { - // BYE acknowledge message. - m_dispatcher->detach(this); - } - - break; - } -} - -void OutgoingTransfer::processMessage(const Message& message) -{ - TQString body = - TQCString(message.body.data(), message.header.dataSize); - kdDebug(14140) << k_funcinfo << "received, " << body << endl; - - if(body.startsWith("BYE")) - { - m_state = Finished; - // Send the recipient an acknowledge message. - acknowledge(message); - if(!m_isComplete) - { - // The peer cancelled the transfer. - if(m_transfer) - { - // Inform the user of the file transfer cancelation. - m_transfer->slotError(TDEIO::ERR_ABORTED, i18n("File transfer canceled.")); - } - } - // Dispose of this transfer context. - m_dispatcher->detach(this); - } - else if(body.startsWith("MSNSLP/1.0 200 OK")) - { - // Retrieve the message content type. - TQRegExp regex("Content-Type: ([A-Za-z0-9$!*/\\-]*)"); - regex.search(body); - TQString contentType = regex.cap(1); - - if(contentType == "application/x-msnmsgr-sessionreqbody") - { - // Recipient has accepted the file transfer. - // Acknowledge the recipient. - acknowledge(message); - - // Try to open the file for reading. - // If an error occurs, send an internal - // error message to the recipient. - if(!m_file->open(IO_ReadOnly)){ - error(); - return; - } - - // Retrieve the receiving client's contact. - Kopete::Contact *contact = m_dispatcher->getContactByAccountId(m_recipient); - if(contact == 0l) - { - error(); - return; - } - - m_transfer = - Kopete::TransferManager::transferManager()->addTransfer(contact, m_file->name(), m_file->size(), m_recipient, Kopete::FileTransferInfo::Outgoing); - - TQObject::connect(m_transfer , TQT_SIGNAL(transferCanceled()), this, TQT_SLOT(abort())); - - m_state = Negotiation; - - m_branch = P2P::Uid::createUid(); - - // Send the direct connection invitation message. - TQString content = "Bridges: TRUDPv1 TCPv1\r\n" + - TQString("NetID: %1\r\n").arg("-123657987") + - TQString("Conn-Type: %1\r\n").arg("Restrict-NAT") + - "UPnPNat: false\r\n" - "ICF: false\r\n" + - TQString("Hashed-Nonce: {%1}\r\n").arg(P2P::Uid::createUid()) + - "\r\n"; - sendMessage(INVITE, content); - } - else if(contentType == "application/x-msnmsgr-transrespbody") - { - // Determine whether the recipient created - // a listening endpoint. - regex = TQRegExp("Listening: ([^\r\n]+)\r\n"); - regex.search(body); - bool isListening = (regex.cap(1) == "true"); - - // Send the recipient an acknowledge message. - acknowledge(message); - - m_state = DataTransfer; - -#if 1 - isListening = false; // TODO complete direct connection. -#endif - if(isListening) - { - // Retrieve the hashed nonce for this direct connection instance. - regex = TQRegExp("Hashed-Nonce: \\{([0-9A-F\\-]*)\\}\r\n"); - regex.search(body); - m_nonce = regex.cap(1); - // Retrieve the listening endpoints of the receiving client. - regex = TQRegExp("IPv4Internal-Addrs: ([^\r\n]+)\r\n"); - regex.search(body); - m_peerEndpoints = TQStringList::split(" ", regex.cap(1)); - m_endpointIterator = m_peerEndpoints.begin(); - // Retrieve the listening port of the receiving client. - regex = TQRegExp("IPv4Internal-Port: ([^\r\n]+)\r\n"); - regex.search(body); - m_remotePort = regex.cap(1); - - // Try to connect to the receiving client's - // listening endpoint. - connectToEndpoint(*m_endpointIterator); - } - else - { - m_handshake = 0x02; - // Otherwise, send data through the already - // existing session. - slotSendData(); - } - } - } - else if(body.startsWith("MSNSLP/1.0 603 Decline")) - { - // File transfer has been cancelled remotely. - // Send an acknowledge message - acknowledge(message); - if(m_transfer) - { - // Inform the user of the file transfer cancelation. - m_transfer->slotError(TDEIO::ERR_ABORTED, i18n("File transfer canceled.")); - } - - if(m_file && m_file->isOpen()){ - // Close the file. - m_file->close(); - } - m_dispatcher->detach(this); - } -} - -void OutgoingTransfer::readyToSend() -{ - if(m_isComplete){ - // Ignore, do nothing. - return; - } - - slotSendData(); -} - -void OutgoingTransfer::connectToEndpoint(const TQString& hostName) -{ - m_socket = new TDEBufferedSocket(hostName, m_remotePort); - m_socket->setBlocking(false); - m_socket->enableRead(true); - // Disable write signal for now. Only enable - // when we are ready to sent data. - // NOTE readyWrite consumes too much cpu usage. - m_socket->enableWrite(false); - TQObject::connect(m_socket, TQT_SIGNAL(readyRead()), this, TQT_SLOT(slotRead())); - TQObject::connect(m_socket, TQT_SIGNAL(connected(const KResolverEntry&)), this, TQT_SLOT(slotConnected())); - TQObject::connect(m_socket, TQT_SIGNAL(gotError(int)), this, TQT_SLOT(slotSocketError(int))); - TQObject::connect(m_socket, TQT_SIGNAL(closed()), this, TQT_SLOT(slotSocketClosed())); - // Try to connect to the endpoint. - m_socket->connect(); -} - -void OutgoingTransfer::slotConnected() -{ - kdDebug(14140) << k_funcinfo << endl; - // Check if connection is ok. - TQ_UINT32 bytesWritten = m_socket->writeBlock(TQCString("foo").data(), 4); - if(bytesWritten != 4) - { - // Not all data was written, close the socket. - m_socket->closeNow(); - // Schedule the data to be sent through the existing session. - TQTimer::singleShot(2000, this, TQT_SLOT(slotSendData())); - return; - } - - // Send data handshake message. - P2P::Message handshake; - handshake.header.sessionId = 0; - handshake.header.identifier = ++m_identifier; - handshake.header.dataOffset = 0l; - handshake.header.totalDataSize = 0l; - handshake.header.dataSize = 0; - // Set the flag to indicate that this is - // a direct connection handshake message. - handshake.header.flag = 0x100; - TQString nonce = m_nonce.remove('-'); - handshake.header.ackSessionIdentifier = nonce.mid(0, 8).toUInt(0, 16); - handshake.header.ackUniqueIdentifier = - nonce.mid(8, 4).toUInt(0, 16) | (nonce.mid(12, 4).toUInt(0, 16) << 16); - const TQ_UINT32 lo = nonce.mid(16, 8).toUInt(0, 16); - const TQ_UINT32 hi = nonce.mid(24, 8).toUInt(0, 16); - handshake.header.ackDataSize = - ((TQ_INT64)htonl(lo)) | (((TQ_INT64)htonl(hi)) << 32); - - TQByteArray stream; - // Write the message to the memory stream. - m_messageFormatter.writeMessage(handshake, stream, true); - // Send the byte stream over the wire. - m_socket->writeBlock(stream.data(), stream.size()); -} - -void OutgoingTransfer::slotRead() -{ - TQ_INT32 bytesAvailable = m_socket->bytesAvailable(); - kdDebug(14140) << k_funcinfo << bytesAvailable << ", bytes available." << endl; -} - -void OutgoingTransfer::slotSocketError(int) -{ - kdDebug(14140) << k_funcinfo << m_socket->TDESocketBase::errorString() << endl; - // If an error has occurred, try to connect - // to another available peer endpoint. - // If there are no more available endpoints, - // send the data through the session. - m_socket->closeNow(); - - // Move to the next available endpoint. - m_endpointIterator++; - if(m_endpointIterator != m_peerEndpoints.end()){ - // Try to connect to the endpoint. - connectToEndpoint(*m_endpointIterator); - } - else - { - // Otherwise, send the data through the session. - m_identifier -= 1; - TQTimer::singleShot(2000, this, TQT_SLOT(slotSendData())); - } -} - -void OutgoingTransfer::slotSocketClosed() -{ - kdDebug(14140) << k_funcinfo << endl; - m_socket->deleteLater(); - m_socket = 0l; -} - -#include "outgoingtransfer.moc" |