[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdenetwork/kopete/protocols/yahoo/libkyahoo
From:       Matt Rogers <mattr () kde ! org>
Date:       2009-03-20 13:01:23
Message-ID: 1237554083.707753.4887.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 941719 by mattr:

Yahoo File Transfer fixups by John Groszko

Recieving works, but sending doesn't so far.

From the review request:

I'm trying to get Yahoo File Transfers working again, but I've gotten to
a point where I need input from someone with a fresh set of eyes or more
brains than me.

Receiving files works, but sending files does not. About 10k into the
transfer I see an unknown error code 16, and wireshark shows a bunch of
TCP Duplicate ACKs. The error looks like this in the debug log:

kopete(6494)/kopete (yahoo - raw protocol) SendFileTask::transmitData:
read: 1024  written:  1024
kopete(6494)/kopete (yahoo)
YahooAccount::slotFileTransferBytesProcessed: Transfer:  2  Bytes: 10240
kopete(6494)/kopete (yahoo - raw protocol) SendFileTask::transmitData:
kopete(6494)/kopete (yahoo - raw protocol) SendFileTask::connectFailed:
16 :  "an unknown/unexpected error has happened"

Some input/insight would be awesome, since I'd like to get this working
again...

Thanks for the patch John!
CCBUG: 159584

 M  +4 -3      filetransfernotifiertask.cpp  
 M  +6 -7      logintask.cpp  
 M  +169 -25   sendfiletask.cpp  
 M  +16 -1     sendfiletask.h  
 M  +2 -2      yahootypes.h  
 M  +4 -0      ymsgprotocol.cpp  


--- trunk/KDE/kdenetwork/kopete/protocols/yahoo/libkyahoo/filetransfernotifiertask.cpp \
#941718:941719 @@ -62,9 +62,10 @@
 
 
 	if( t->service() == Yahoo::ServiceP2PFileXfer ||
-		t->service() == Yahoo::ServicePeerToPeer ||
-		t->service() == Yahoo::ServiceFileTransfer ||
-		t->service() == Yahoo::ServiceFileTransfer7
+	    t->service() == Yahoo::ServicePeerToPeer ||
+	    t->service() == Yahoo::ServiceFileTransfer ||
+	    (t->service() == Yahoo::ServiceFileTransfer7 &&
+	     t->firstParam(222).toInt() == 1)
 	)
 		return true;
 	else
--- trunk/KDE/kdenetwork/kopete/protocols/yahoo/libkyahoo/logintask.cpp \
#941718:941719 @@ -207,14 +207,13 @@
 	t->setId( sessionID );
 	t->setParam( 0 , sn.toLocal8Bit());
 	t->setParam( 2 , sn.toLocal8Bit());
+	t->setParam( 2, 1 ); // Both parameter 2s wind up in the packet
 	t->setParam( 6 , resp_6);
-	t->setParam( 96 , resp_96);
-// 	t->setParam( 59 , "B\\tfckeert1kk1nl&b=2" );	// ???
-	t->setParam( 135 , YMSG_PROGRAM_VERSION_STRING );	// Client version
-	t->setParam( 148 , -60 );
-	t->setParam( 192 , client()->pictureChecksum() );
-// 	t->setParam( 244 , 524223 );
-	t->setParam( 1 , sn.toLocal8Bit());
+	t->setParam( 1, sn.toLocal8Bit());
+	t->setParam( 244, 2097087 );
+	t->setParam( 135, YMSG_PROGRAM_VERSION_STRING );
+	t->setParam( 148, 480 );
+	t->setParam( 59 , "B\\tfckeert1kk1nl&b=2" );	// ???
 
 	if( !m_verificationWord.isEmpty() )
 	{
--- trunk/KDE/kdenetwork/kopete/protocols/yahoo/libkyahoo/sendfiletask.cpp \
#941718:941719 @@ -21,10 +21,12 @@
 #include "client.h"
 #include <qstring.h>
 #include <qtimer.h>
+#include <QTime>
 #include <kdebug.h>
 #include <klocale.h>
 #include <k3streamsocket.h>
 #include <kio/global.h>
+#include <krandom.h>
 
 using namespace KNetwork;
 
@@ -33,6 +35,9 @@
 	kDebug(YAHOO_RAW_DEBUG) ;
 	m_transmitted = 0;
 	m_socket = 0;
+
+	QTime epoch(0, 0, 0);
+	qsrand(epoch.secsTo(QTime::currentTime()));
 }
 
 SendFileTask::~SendFileTask()
@@ -41,27 +46,148 @@
 	m_socket = 0;
 }
 
+bool SendFileTask::forMe( const Transfer *transfer ) const
+{
+	const YMSGTransfer *t = static_cast<const YMSGTransfer*>(transfer);
+
+	if(!t)
+		return false;
+
+	if((t->service() == Yahoo::ServiceFileTransfer7 ||
+	    t->service() == Yahoo::ServiceFileTransfer7Accept) &&
+	   t->firstParam(265) == m_yahooTransferId)
+	{
+		return true;
+	}
+
+	return false;
+}
+
+bool SendFileTask::take(Transfer* transfer)
+{
+	if( !forMe( transfer ) )
+		return false;
+
+	YMSGTransfer *t = static_cast<YMSGTransfer*>(transfer);
+
+	kDebug(YAHOO_RAW_DEBUG) << t->service();
+
+	if(t->service() == Yahoo::ServiceFileTransfer7)
+		parseFileTransfer(t);
+	else if(t->service() == Yahoo::ServiceFileTransfer7Accept)
+		parseTransferAccept(t);
+
+	return true;
+}
+
+void SendFileTask::parseFileTransfer( const Transfer *transfer )
+{
+	kDebug(YAHOO_RAW_DEBUG);
+
+	const YMSGTransfer *t = static_cast<const YMSGTransfer*>(transfer);
+
+	if(!t)
+		return;
+
+	if(t->firstParam(222).toInt() == 4)
+	{
+		emit declined();
+	}
+	else if(t->firstParam(222).toInt() == 3)
+	{
+		sendFileTransferInfo();
+	}
+	else
+	{
+		setError();
+		emit error(m_transferId, 0, i18n("Unknown error"));
+	}
+}
+
 void SendFileTask::onGo()
 {
 	kDebug(YAHOO_RAW_DEBUG) ;
 
-	QTimer::singleShot( 0, this, SLOT(initiateUpload()) );
+	m_file.setFileName( m_url.path() );
+
+	m_yahooTransferId = newYahooTransferId();
+
+	YMSGTransfer *t = new YMSGTransfer(Yahoo::ServiceFileTransfer7);
+	t->setId( client()->sessionID() );
+
+	t->setParam( 1, client()->userId().toLocal8Bit() );
+	t->setParam( 5, m_target.toLocal8Bit() );
+	t->setParam( 265,  m_yahooTransferId.toLocal8Bit() );
+	t->setParam( 222, 1 );
+	t->setParam( 266, 1 );
+	t->setParam( 302, 268 );
+	t->setParam( 300, 268 );
+	t->setParam( 27, m_url.fileName().toLocal8Bit() );
+	t->setParam( 28, m_file.size());
+	t->setParam( 301, 268 );
+	t->setParam( 303, 268 );
+
+	send( t );
 }
 
-void SendFileTask::initiateUpload()
+void SendFileTask::sendFileTransferInfo()
+{
+	kDebug(YAHOO_RAW_DEBUG);
+
+	KResolverResults results = KResolver::resolve("relay.msg.yahoo.com", \
QString::number(80)); +	if(results.count() > 0)
+	{
+		m_relayHost = results.first().address().toString();
+		m_relayHost.chop(3); // Remove the :80 from the end
+	}
+	else
+	{
+		emit error(m_transferId, 0, i18n("Unable to connect to file transfer server"));
+		setError();
+		return;
+	}
+
+	YMSGTransfer *t = new YMSGTransfer(Yahoo::ServiceFileTransfer7Info);
+	t->setId( client()->sessionID() );
+
+	t->setParam( 1, client()->userId().toLocal8Bit() );
+	t->setParam( 5, m_target.toLocal8Bit() );
+	t->setParam( 265, m_yahooTransferId.toLocal8Bit() );
+	t->setParam( 27, m_url.fileName().toLocal8Bit() );
+	t->setParam( 249, 3 );
+	t->setParam( 250, m_relayHost.toLocal8Bit() );
+
+	send( t );
+}
+
+void SendFileTask::parseTransferAccept(const Transfer *transfer)
 {	
-	kDebug(YAHOO_RAW_DEBUG) ;
-	m_socket = new KStreamSocket( "filetransfer.msg.yahoo.com", QString::number(80) );
+	kDebug(YAHOO_RAW_DEBUG);
+
+	const YMSGTransfer *t = static_cast<const YMSGTransfer*>(transfer);
+
+	// Disconnected
+	if(t->status() == Yahoo::StatusDisconnected)
+	{
+		setError();
+		return;
+	}
+
+	m_token = t->firstParam(251);
+	kDebug(YAHOO_RAW_DEBUG) << "Token: " << m_token;
+
+	m_socket = new KStreamSocket( m_relayHost, QString::number(80) );
 	m_socket->setBlocking( true );
 	connect( m_socket, SIGNAL( connected( const KNetwork::KResolverEntry& ) ), this, \
SLOT( connectSucceeded() ) );  connect( m_socket, SIGNAL( gotError(int) ), this, \
SLOT( connectFailed(int) ) );  
 	m_socket->connect();
+
 }
 
 void SendFileTask::connectFailed( int i )
 {
-	QString err = m_socket->errorString();
+	QString err = KSocketBase::errorString(m_socket->error());
 	kDebug(YAHOO_RAW_DEBUG) << i << ": " << err;
 	emit error( m_transferId, i, err );
 	setError();
@@ -70,18 +196,8 @@
 void SendFileTask::connectSucceeded()
 {
 	kDebug(YAHOO_RAW_DEBUG) ;
-	YMSGTransfer t( Yahoo::ServiceFileTransfer );
 
-	m_file.setFileName( m_url.path() );
-
-	t.setId( client()->sessionID() );
-	t.setParam( 0, client()->userId().toLocal8Bit());
-	t.setParam( 5, m_target.toLocal8Bit());
-	t.setParam( 28, m_file.size() );	
-	t.setParam( 27, m_url.fileName().toLocal8Bit() );
-	t.setParam( 14, "" );
 	QByteArray buffer;
-	QByteArray paket;
 	QDataStream stream( &buffer, QIODevice::WriteOnly );
 
 	if ( m_file.open(QIODevice::ReadOnly ) )
@@ -96,17 +212,20 @@
 		return;
 	}
 
-	paket = t.serialize();
-	kDebug(YAHOO_RAW_DEBUG) << "Sizes: File (" << m_url << "): " << m_file.size() << " \
                - paket: " << paket.size();
-	QString header = QString::fromLatin1("POST \
                http://filetransfer.msg.yahoo.com:80/notifyft HTTP/1.1\r\n"
-			"Cookie: Y=%1; T=%2; C=%3 ;B=fckeert1kk1nl&b=2\r\n"
-			"User-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\n"
-			"Host: filetransfer.msg.yahoo.com:80\r\n"
-			"Content-length: %4\r\n"
-			"Cache-Control: no-cache\r\n\r\n").arg(client()->yCookie()).arg(client()->tCookie()).arg(client()->cCookie()).arg(m_file.size()+4+paket.size());
 +	kDebug(YAHOO_RAW_DEBUG) << "Sizes: File (" << m_url << "): " << m_file.size();
+	QString header = QString::fromLatin1("POST /relay?token=%1&sender=%2&recver=%3 \
HTTP/1.1\r\n" +					     "Cache-Control: no-cache\r\n"
+					     "Cookie: T=%4; Y=%5\r\n"
+					     "Host: %6\r\n"
+					     "Content-Length: %7\r\n"
+					     "User-Agent: Mozilla/5.0\r\n"
+					     "Connection: Close\r\n\r\n")
+		.arg(m_token).arg(client()->userId()).arg(m_target)
+		.arg(client()->tCookie()).arg(client()->yCookie())
+		.arg(m_relayHost)
+		.arg(QString::number(m_file.size()));
+	kDebug() << header;
 	stream.writeRawData( header.toLocal8Bit(), header.length() );
-	stream.writeRawData( paket.data(), paket.size() );
-	stream << (qint8)0x32 << (qint8)0x39 << (qint8)0xc0 << (qint8)0x80;
 
 	if( !m_socket->write( buffer ) )
 	{
@@ -186,5 +305,30 @@
 	setError();
 }
 
+QString SendFileTask::newYahooTransferId()
+{
+	// Adapted from libpurple/protocols/yahoo/yahoo_filexfer.c yahoo_xfer_new_xfer_id()
+
+	QString newId;
+
+	for(int i = 0; i < 22; i++)
+	{
+		char j = qrand() % 61;
+
+		if(j < 26)
+			newId += j + 'a';
+		else if(j < 52)
+			newId += j - 26 + 'A';
+		else
+			newId += j - 52 + '0';
+	}
+
+	newId += "$$";
+
+	kDebug() << "New Yahoo Transfer Id: " << newId;
+
+	return newId;
+}
+
 #include "sendfiletask.moc"
 
--- trunk/KDE/kdenetwork/kopete/protocols/yahoo/libkyahoo/sendfiletask.h \
#941718:941719 @@ -38,6 +38,8 @@
 	
 	virtual void onGo();
 	
+	bool take(Transfer *transfer);
+
 	void setTarget( const QString &to );
 	void setMessage( const QString &msg );
 	void setFileUrl( KUrl url );
@@ -48,8 +50,17 @@
 	void complete( unsigned int );
 	void error( unsigned int, int, const QString & );
 
+	void declined();
+
+protected:
+	bool forMe( const Transfer *transfer ) const;
+	void sendFileTransferInfo();
+	void parseFileTransfer( const Transfer *transfer );
+	void parseTransferAccept(const Transfer *transfer);
+
+	QString newYahooTransferId();
+
 private slots:
-	void initiateUpload();
 	void connectSucceeded();
 	void connectFailed( int );
 	void transmitData();
@@ -63,6 +74,10 @@
 	unsigned int m_transferId;
 	unsigned int m_transmitted;
 	KNetwork::KStreamSocket *m_socket;
+
+	QString m_relayHost;
+	QString m_token;
+	QString m_yahooTransferId;
 };
 
 #endif
--- trunk/KDE/kdenetwork/kopete/protocols/yahoo/libkyahoo/yahootypes.h #941718:941719
@@ -99,8 +99,8 @@
 		ServiceChatSession = 0xd4,	
 		ServiceAuthorization = 0xd6,	/* YMSG13 */
 		ServiceFileTransfer7 = 0xdc,	/* YMSG13 */
-		ServiceFileTransfer7Info,	/* YMSG13 */
-		ServiceFileTransfer7Accept,	/* YMSG13 */
+		ServiceFileTransfer7Info = 0xdd,	/* YMSG13 */
+		ServiceFileTransfer7Accept = 0xde,	/* YMSG13 */
 		ServiceBuddyChangeGroup = 0xe7,	/* YMSG13 */
 		ServiceBuddyStatus = 0xf0,
 		ServiceBuddyList = 0xf1
--- trunk/KDE/kdenetwork/kopete/protocols/yahoo/libkyahoo/ymsgprotocol.cpp \
#941718:941719 @@ -238,6 +238,10 @@
 			kDebug(YAHOO_RAW_DEBUG) << " Parsed packet service -  This means \
ServiceFileTransfer7Info " << servicenum;  service = Yahoo::ServiceFileTransfer7Info;
 		break;
+		case (Yahoo::ServiceFileTransfer7Accept) :
+			kDebug(YAHOO_RAW_DEBUG) << " Parsed packet service -  This means \
ServiceFileTransfer7Accept " << servicenum; +			service = \
Yahoo::ServiceFileTransfer7Accept; +		break;
 		case (Yahoo::ServicePeerToPeer) :
 			kDebug(YAHOO_RAW_DEBUG) << " Parsed packet service -  This means \
ServicePeerToPeer " << servicenum;  service = Yahoo::ServicePeerToPeer;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic