From 32a4f1df10afc32a3a3425537b4fdacd854dbb0b Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Wed, 16 Jun 2010 02:58:44 +0000 Subject: [PATCH] (qt) #3147: qtr delayed to connect to remote session automatically --- qt/mainwin.cc | 2 +- qt/session.cc | 108 +++++++++++++++++++++++++++----------------------- qt/session.h | 18 ++++++--- 3 files changed, 72 insertions(+), 56 deletions(-) diff --git a/qt/mainwin.cc b/qt/mainwin.cc index de29d2512..cb1767188 100644 --- a/qt/mainwin.cc +++ b/qt/mainwin.cc @@ -709,7 +709,7 @@ TrMainWindow :: refreshTitle( ) QString title( "Transmission" ); const QUrl url( mySession.getRemoteUrl( ) ); if( !url.isEmpty() ) - title += tr( " - %1" ).arg( url.toString(QUrl::RemoveUserInfo) ); + title += tr( " - %1:%2" ).arg( url.host() ).arg( url.port() ); setWindowTitle( title ); } diff --git a/qt/session.cc b/qt/session.cc index 7413a0440..97318fc6d 100644 --- a/qt/session.cc +++ b/qt/session.cc @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -220,14 +222,9 @@ Session :: Session( const char * configDir, Prefs& prefs ): myStats.secondsActive = 0; myCumulativeStats = myStats; - connect( &myHttp, SIGNAL(requestStarted(int)), this, SLOT(onRequestStarted(int))); - connect( &myHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(onRequestFinished(int,bool))); - connect( &myHttp, SIGNAL(dataReadProgress(int,int)), this, SIGNAL(dataReadProgress())); - connect( &myHttp, SIGNAL(dataSendProgress(int,int)), this, SIGNAL(dataSendProgress())); - connect( &myHttp, SIGNAL(authenticationRequired(QString, quint16, QAuthenticator*)), this, SIGNAL(httpAuthenticationRequired()) ); + connect( &myNAM, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)) ); + connect( &myNAM, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SIGNAL(httpAuthenticationRequired()) ); connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) ); - - myBuffer.open( QIODevice::ReadWrite ); } Session :: ~Session( ) @@ -242,7 +239,8 @@ Session :: ~Session( ) void Session :: stop( ) { - myHttp.abort( ); + foreach( Reply myReply, myReplies ) + myReply.networkReply->abort(); myUrl.clear( ); if( mySession ) @@ -274,14 +272,12 @@ Session :: start( ) url.setScheme( "http" ); url.setHost( host ); url.setPort( port ); + url.setPath( "/transmission/rpc" ); if( auth ) { url.setUserName( user ); url.setPassword( pass ); } myUrl = url; - - myHttp.setHost( host, port ); - myHttp.setUser( user, pass ); } else { @@ -570,77 +566,91 @@ Session :: localSessionCallback( tr_session * session, const char * json, size_t } void -Session :: exec( const char * request ) +Session :: exec( const char * json ) { if( mySession ) { - tr_rpc_request_exec_json( mySession, request, strlen( request ), localSessionCallback, this ); + tr_rpc_request_exec_json( mySession, json, strlen( json ), localSessionCallback, this ); } else if( !myUrl.isEmpty( ) ) { - static const QString path( "/transmission/rpc" ); - QHttpRequestHeader header( "POST", path ); - header.setValue( "User-Agent", QCoreApplication::instance()->applicationName() + "/" + LONG_VERSION_STRING ); - header.setValue( "Content-Type", "application/json; charset=UTF-8" ); + QNetworkRequest request; + request.setUrl( myUrl ); + request.setRawHeader( "User-Agent", QString( QCoreApplication::instance()->applicationName() + "/" + LONG_VERSION_STRING ).toAscii() ); + request.setRawHeader( "Content-Type", "application/json; charset=UTF-8" ); if( !mySessionId.isEmpty( ) ) - header.setValue( TR_RPC_SESSION_ID_HEADER, mySessionId ); + request.setRawHeader( TR_RPC_SESSION_ID_HEADER, mySessionId.toAscii() ); + QBuffer * reqbuf = new QBuffer; - reqbuf->setData( QByteArray( request ) ); - myHttp.request( header, reqbuf, &myBuffer ); + reqbuf->setData( QByteArray( json ) ); + + QNetworkReply * reply = myNAM.post( request, reqbuf ); + connect( reply, SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(dataReadProgress())); + connect( reply, SIGNAL(uploadProgress(qint64,qint64)), this, SIGNAL(dataSendProgress())); + + Reply myReply; + myReply.networkReply = reply; + myReply.buffer = reqbuf; + myReplies << myReply; #ifdef DEBUG_HTTP - std::cerr << "sending " << qPrintable(header.toString()) << "\nBody:\n" << request << std::endl; + std::cerr << "sending " << "POST " << qPrintable( myUrl.path() ) << std::endl; + foreach( QByteArray b, request.rawHeaderList() ) + std::cerr << b.constData() + << ": " + << request.rawHeader( b ).constData() + << std::endl; + std::cerr << "Body:\n" << json << std::endl; #endif } } void -Session :: onRequestStarted( int id ) +Session :: onFinished( QNetworkReply * reply ) { - Q_UNUSED( id ); - - assert( myBuffer.atEnd( ) ); -} - -void -Session :: onRequestFinished( int id, bool error ) -{ - Q_UNUSED( id ); - QIODevice * sourceDevice = myHttp.currentSourceDevice( ); - - QHttpResponseHeader response = myHttp.lastResponse(); + QBuffer * buffer; + for( QList::iterator i = myReplies.begin(); i != myReplies.end(); ++i ) + { + if( reply == i->networkReply ) + { + buffer = i->buffer; + myReplies.erase( i ); + break; + } + } #ifdef DEBUG_HTTP - std::cerr << "http request " << id << " ended.. response header: " - << qPrintable( myHttp.lastResponse().toString() ) - << std::endl - << "json: " << myBuffer.buffer( ).constData( ) - << std::endl; + std::cerr << "http response header: " << std::endl; + foreach( QByteArray b, reply->rawHeaderList() ) + std::cerr << b.constData() + << ": " + << reply->rawHeader( b ).constData() + << std::endl; + std::cerr << "json:\n" << reply->peek( reply->bytesAvailable() ).constData() << std::endl; #endif - if( ( response.statusCode() == 409 ) && ( myBuffer.buffer().indexOf("invalid session-id") != -1 ) ) + if( ( reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt() == 409 ) + && ( reply->hasRawHeader( TR_RPC_SESSION_ID_HEADER ) ) ) { // we got a 409 telling us our session id has expired. // update it and resubmit the request. - mySessionId = response.value( TR_RPC_SESSION_ID_HEADER ); - exec( qobject_cast(sourceDevice)->buffer().constData() ); + mySessionId = QString( reply->rawHeader( TR_RPC_SESSION_ID_HEADER ) ); + exec( buffer->buffer().constData() ); } - else if( error ) + else if( reply->error() != QNetworkReply::NoError ) { - std::cerr << "http error: " << qPrintable(myHttp.errorString()) << std::endl; + std::cerr << "http error: " << qPrintable( reply->errorString() ) << std::endl; } else { - const QByteArray& response( myBuffer.buffer( ) ); + const QByteArray response( reply->readAll() ); const char * json( response.constData( ) ); int jsonLength( response.size( ) ); if( jsonLength>0 && json[jsonLength-1] == '\n' ) --jsonLength; parseResponse( json, jsonLength ); } - delete sourceDevice; - myBuffer.buffer( ).clear( ); - myBuffer.reset( ); - assert( myBuffer.bytesAvailable( ) < 1 ); + delete buffer; + reply->deleteLater(); } void diff --git a/qt/session.h b/qt/session.h index 685939a28..4065f0bda 100644 --- a/qt/session.h +++ b/qt/session.h @@ -17,8 +17,8 @@ #include #include #include +#include #include -#include #include #include @@ -32,6 +32,13 @@ extern "C" class Prefs; +struct Reply +{ + QNetworkReply * networkReply; + QBuffer * buffer; +}; +typedef QList ReplyList; + class Session: public QObject { Q_OBJECT @@ -75,7 +82,7 @@ class Session: public QObject static void localSessionCallback( tr_session *, const char *, size_t, void * ); public: - void exec( const char * request ); + void exec( const char * json ); void exec( const struct tr_benc * request ); public: @@ -116,8 +123,7 @@ class Session: public QObject void refreshExtraStats( const QSet& ids ); private slots: - void onRequestStarted( int id ); - void onRequestFinished( int id, bool error ); + void onFinished( QNetworkReply * reply ); signals: void executed( int64_t tag, const QString& result, struct tr_benc * arguments ); @@ -140,8 +146,8 @@ class Session: public QObject QString myConfigDir; QString mySessionId; QUrl myUrl; - QBuffer myBuffer; - QHttp myHttp; + QNetworkAccessManager myNAM; + ReplyList myReplies; struct tr_session_stats myStats; struct tr_session_stats myCumulativeStats; QString mySessionVersion;