~ubuntu-branches/ubuntu/quantal/transmission/quantal

« back to all changes in this revision

Viewing changes to qt/session.cc

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Klimonda
  • Date: 2010-07-24 23:31:01 UTC
  • mfrom: (1.1.37 upstream) (2.1.21 sid)
  • Revision ID: james.westby@ubuntu.com-20100724233101-s1w4xpfbt9g10vxo
Tags: 2.03-0ubuntu1
* New upstream release (LP: #599126) 
* Fixes bugs:
  - duplicate quit confirmation dialog on closing transmission (LP: #603426)
  - disk read/write scheduling (LP: #567181)

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 * This exemption does not extend to derived works not owned by
8
8
 * the Transmission project.
9
9
 *
10
 
 * $Id: session.cc 10738 2010-06-08 17:37:29Z Longinus00 $
 
10
 * $Id: session.cc 10868 2010-06-26 17:16:46Z Longinus00 $
11
11
 */
12
12
 
13
13
#include <cassert>
19
19
#include <QCoreApplication>
20
20
#include <QDesktopServices>
21
21
#include <QMessageBox>
 
22
#include <QNetworkReply>
 
23
#include <QNetworkRequest>
22
24
#include <QSet>
23
25
#include <QStyle>
24
26
#include <QTextStream>
167
169
            sessionSet( "seedRatioLimited", myPrefs.variant(key) );
168
170
            break;
169
171
 
 
172
        case Prefs :: ENCRYPTION:
 
173
            {
 
174
                const int i = myPrefs.variant(key).toInt();
 
175
                switch( i )
 
176
                {
 
177
                    case 0:
 
178
                        sessionSet( myPrefs.keyStr(key), "tolerated" );
 
179
                        break;
 
180
                    case 1:
 
181
                        sessionSet( myPrefs.keyStr(key), "preferred" );
 
182
                        break;
 
183
                    case 2:
 
184
                        sessionSet( myPrefs.keyStr(key), "required" );
 
185
                        break;
 
186
                }
 
187
                break;
 
188
            }
 
189
 
170
190
        case Prefs :: RPC_AUTH_REQUIRED:
171
191
            if( mySession )
172
192
                tr_sessionSetRPCEnabled( mySession, myPrefs.getBool(key) );
220
240
    myStats.secondsActive = 0;
221
241
    myCumulativeStats = myStats;
222
242
 
223
 
    connect( &myHttp, SIGNAL(requestStarted(int)), this, SLOT(onRequestStarted(int)));
224
 
    connect( &myHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(onRequestFinished(int,bool)));
225
 
    connect( &myHttp, SIGNAL(dataReadProgress(int,int)), this, SIGNAL(dataReadProgress()));
226
 
    connect( &myHttp, SIGNAL(dataSendProgress(int,int)), this, SIGNAL(dataSendProgress()));
227
 
    connect( &myHttp, SIGNAL(authenticationRequired(QString, quint16, QAuthenticator*)), this, SIGNAL(httpAuthenticationRequired()) );
 
243
    connect( &myNAM, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)) );
 
244
    connect( &myNAM, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SIGNAL(httpAuthenticationRequired()) );
228
245
    connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) );
229
 
 
230
 
    myBuffer.open( QIODevice::ReadWrite );
231
246
}
232
247
 
233
248
Session :: ~Session( )
242
257
void
243
258
Session :: stop( )
244
259
{
245
 
    myHttp.abort( );
 
260
    foreach( Reply myReply, myReplies )
 
261
        myReply.networkReply->abort();
246
262
    myUrl.clear( );
247
263
 
248
264
    if( mySession )
274
290
        url.setScheme( "http" );
275
291
        url.setHost( host );
276
292
        url.setPort( port );
 
293
        url.setPath( "/transmission/rpc" );
277
294
        if( auth ) {
278
295
            url.setUserName( user );
279
296
            url.setPassword( pass );
280
297
        }
281
298
        myUrl = url;
282
 
 
283
 
        myHttp.setHost( host, port );
284
 
        myHttp.setUser( user, pass );
285
299
    }
286
300
    else
287
301
    {
570
584
}
571
585
 
572
586
void
573
 
Session :: exec( const char * request )
 
587
Session :: exec( const char * json )
574
588
{
575
589
    if( mySession  )
576
590
    {
577
 
        tr_rpc_request_exec_json( mySession, request, strlen( request ), localSessionCallback, this );
 
591
        tr_rpc_request_exec_json( mySession, json, strlen( json ), localSessionCallback, this );
578
592
    }
579
593
    else if( !myUrl.isEmpty( ) )
580
594
    {
581
 
        static const QString path( "/transmission/rpc" );
582
 
        QHttpRequestHeader header( "POST", path );
583
 
        header.setValue( "User-Agent", QCoreApplication::instance()->applicationName() + "/" + LONG_VERSION_STRING );
584
 
        header.setValue( "Content-Type", "application/json; charset=UTF-8" );
 
595
        QNetworkRequest request;
 
596
        request.setUrl( myUrl );
 
597
        request.setRawHeader( "User-Agent", QString( QCoreApplication::instance()->applicationName() + "/" + LONG_VERSION_STRING ).toAscii() );
 
598
        request.setRawHeader( "Content-Type", "application/json; charset=UTF-8" );
585
599
        if( !mySessionId.isEmpty( ) )
586
 
            header.setValue( TR_RPC_SESSION_ID_HEADER, mySessionId );
 
600
            request.setRawHeader( TR_RPC_SESSION_ID_HEADER, mySessionId.toAscii() );
 
601
 
587
602
        QBuffer * reqbuf = new QBuffer;
588
 
        reqbuf->setData( QByteArray( request ) );
589
 
        myHttp.request( header, reqbuf, &myBuffer );
590
 
#ifdef DEBUG_HTTP
591
 
        std::cerr << "sending " << qPrintable(header.toString()) << "\nBody:\n" << request << std::endl;
592
 
#endif
593
 
    }
594
 
}
595
 
 
596
 
void
597
 
Session :: onRequestStarted( int id )
598
 
{
599
 
    Q_UNUSED( id );
600
 
 
601
 
    assert( myBuffer.atEnd( ) );
602
 
}
603
 
 
604
 
void
605
 
Session :: onRequestFinished( int id, bool error )
606
 
{
607
 
    Q_UNUSED( id );
608
 
    QIODevice * sourceDevice = myHttp.currentSourceDevice( );
609
 
 
610
 
    QHttpResponseHeader response = myHttp.lastResponse();
611
 
 
612
 
#ifdef DEBUG_HTTP
613
 
    std::cerr << "http request " << id << " ended.. response header: "
614
 
              << qPrintable( myHttp.lastResponse().toString() )
615
 
              << std::endl
616
 
              << "json: " << myBuffer.buffer( ).constData( )
617
 
              << std::endl;
618
 
#endif
619
 
 
620
 
    if( ( response.statusCode() == 409 ) && ( myBuffer.buffer().indexOf("invalid session-id") != -1 ) )
 
603
        reqbuf->setData( QByteArray( json ) );
 
604
 
 
605
        QNetworkReply * reply = myNAM.post( request, reqbuf );
 
606
        connect( reply, SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(dataReadProgress()));
 
607
        connect( reply, SIGNAL(uploadProgress(qint64,qint64)), this, SIGNAL(dataSendProgress()));
 
608
 
 
609
        Reply myReply;
 
610
        myReply.networkReply = reply;
 
611
        myReply.buffer = reqbuf;
 
612
        myReplies << myReply;
 
613
#ifdef DEBUG_HTTP
 
614
        std::cerr << "sending " << "POST " << qPrintable( myUrl.path() ) << std::endl;
 
615
        foreach( QByteArray b, request.rawHeaderList() )
 
616
            std::cerr << b.constData()
 
617
                      << ": "
 
618
                      << request.rawHeader( b ).constData()
 
619
                      << std::endl;
 
620
        std::cerr << "Body:\n" << json << std::endl;
 
621
#endif
 
622
    }
 
623
}
 
624
 
 
625
void
 
626
Session :: onFinished( QNetworkReply * reply )
 
627
{
 
628
    QBuffer * buffer;
 
629
    for( QList<Reply>::iterator i = myReplies.begin(); i != myReplies.end(); ++i )
 
630
    {
 
631
        if( reply == i->networkReply )
 
632
        {
 
633
            buffer = i->buffer;
 
634
            myReplies.erase( i );
 
635
            break;
 
636
        }
 
637
    }
 
638
 
 
639
#ifdef DEBUG_HTTP
 
640
    std::cerr << "http response header: " << std::endl;
 
641
    foreach( QByteArray b, reply->rawHeaderList() )
 
642
        std::cerr << b.constData()
 
643
                  << ": "
 
644
                  << reply->rawHeader( b ).constData()
 
645
                  << std::endl;
 
646
    std::cerr << "json:\n" << reply->peek( reply->bytesAvailable() ).constData() << std::endl;
 
647
#endif
 
648
 
 
649
    if( ( reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt() == 409 )
 
650
        && ( reply->hasRawHeader( TR_RPC_SESSION_ID_HEADER ) ) )
621
651
    {
622
652
        // we got a 409 telling us our session id has expired.
623
653
        // update it and resubmit the request.
624
 
        mySessionId = response.value( TR_RPC_SESSION_ID_HEADER );
625
 
        exec( qobject_cast<QBuffer*>(sourceDevice)->buffer().constData() );
 
654
        mySessionId = QString( reply->rawHeader( TR_RPC_SESSION_ID_HEADER ) );
 
655
        exec( buffer->buffer().constData() );
626
656
    }
627
 
    else if( error )
 
657
    else if( reply->error() != QNetworkReply::NoError )
628
658
    {
629
 
        std::cerr << "http error: " << qPrintable(myHttp.errorString()) << std::endl;
 
659
        std::cerr << "http error: " << qPrintable( reply->errorString() ) << std::endl;
630
660
    }
631
661
    else
632
662
    {
633
 
        const QByteArray& response( myBuffer.buffer( ) );
 
663
        const QByteArray response( reply->readAll() );
634
664
        const char * json( response.constData( ) );
635
665
        int jsonLength( response.size( ) );
636
666
        if( jsonLength>0 && json[jsonLength-1] == '\n' ) --jsonLength;
637
667
        parseResponse( json, jsonLength );
638
668
    }
639
669
 
640
 
    delete sourceDevice;
641
 
    myBuffer.buffer( ).clear( );
642
 
    myBuffer.reset( );
643
 
    assert( myBuffer.bytesAvailable( ) < 1 );
 
670
    delete buffer;
 
671
    reply->deleteLater();
644
672
}
645
673
 
646
674
void
791
819
        if( !b )
792
820
            continue;
793
821
 
 
822
        if( i == Prefs :: ENCRYPTION )
 
823
        {
 
824
            const char * val;
 
825
            if( tr_bencGetStr( b, &val ) )
 
826
            {
 
827
                if( !qstrcmp( val , "required" ) )
 
828
                    myPrefs.set( i, 2 );
 
829
                else if( !qstrcmp( val , "preferred" ) )
 
830
                    myPrefs.set( i, 1 );
 
831
                else if( !qstrcmp( val , "tolerated" ) )
 
832
                    myPrefs.set( i, 0 );
 
833
            }
 
834
            continue;
 
835
        }
 
836
 
794
837
        switch( myPrefs.type( i ) )
795
838
        {
796
839
            case QVariant :: Int: {