Changeset 561 for trunk/src/network


Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
127 edited
16 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/network/access/access.pri

    r2 r561  
    33HEADERS += access/qftp.h \
    44           access/qhttp.h \
     5           access/qhttpnetworkheader_p.h \
     6           access/qhttpnetworkrequest_p.h \
     7           access/qhttpnetworkreply_p.h \
    58           access/qhttpnetworkconnection_p.h \
     9           access/qhttpnetworkconnectionchannel_p.h \
     10           access/qfilenetworkreply_p.h \
    611           access/qnetworkaccessmanager.h \
    712           access/qnetworkaccessmanager_p.h \
     
    1621           access/qnetworkcookie.h \
    1722           access/qnetworkcookie_p.h \
     23           access/qnetworkcookiejar.h \
     24           access/qnetworkcookiejar_p.h \
    1825           access/qnetworkrequest.h \
    1926           access/qnetworkrequest_p.h \
     
    2835SOURCES += access/qftp.cpp \
    2936           access/qhttp.cpp \
     37           access/qhttpnetworkheader.cpp \
     38           access/qhttpnetworkrequest.cpp \
     39           access/qhttpnetworkreply.cpp \
    3040           access/qhttpnetworkconnection.cpp \
     41           access/qhttpnetworkconnectionchannel.cpp \
     42           access/qfilenetworkreply.cpp \
    3143           access/qnetworkaccessmanager.cpp \
    3244           access/qnetworkaccesscache.cpp \
     
    3951           access/qnetworkaccesshttpbackend.cpp \
    4052           access/qnetworkcookie.cpp \
     53           access/qnetworkcookiejar.cpp \
    4154           access/qnetworkrequest.cpp \
    4255           access/qnetworkreply.cpp \
     
    4962   INCLUDEPATH += ../3rdparty/zlib
    5063} else:!contains(QT_CONFIG, no-zlib) {
    51    unix:LIBS += -lz
     64   unix:LIBS_PRIVATE += -lz
    5265#  win32:LIBS += libz.lib
    5366}
  • trunk/src/network/access/qabstractnetworkcache.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    284284
    285285/*!
     286    \since 4.6
     287
    286288    Returns all the attributes stored with this cache item.
    287289
     
    294296
    295297/*!
     298    \since 4.6
     299
    296300    Sets all attributes of this cache item to be the map \a attributes.
    297301
  • trunk/src/network/access/qabstractnetworkcache.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/access/qabstractnetworkcache_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/access/qftp.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    315315    bytesFromSocket.clear();
    316316
    317     if (socket)
     317    if (socket) {
    318318        delete socket;
     319        socket = 0;
     320    }
    319321    socket = new QTcpSocket(this);
    320322    socket->setObjectName(QLatin1String("QFtpDTP Passive state socket"));
     
    870872//    qDebug("QFtpPI state: %d [connected()]", state);
    871873#endif
     874    // try to improve performance by setting TCP_NODELAY
     875    commandSocket.setSocketOption(QAbstractSocket::LowDelayOption, 1);
     876
    872877    emit connectState(QFtp::Connected);
    873878}
     
    12921297    \brief The QFtp class provides an implementation of the client side of FTP protocol.
    12931298
    1294     \ingroup io
     1299    \ingroup network
    12951300    \inmodule QtNetwork
    1296     \mainclass
     1301
    12971302
    12981303    This class provides a direct interface to FTP that allows you to
     
    13411346    their results.
    13421347
    1343     Example: If you want to download the INSTALL file from Trolltech's
     1348    Example: If you want to download the INSTALL file from the Qt
    13441349    FTP server, you would write this:
    13451350
     
    13861391    non-Unix FTP servers.
    13871392
    1388     \sa QHttp, QNetworkAccessManager, QNetworkRequest, QNetworkReply,
     1393    \sa QNetworkAccessManager, QNetworkRequest, QNetworkReply,
    13891394        {FTP Example}
    13901395*/
     
    16591664int QFtp::connectToHost(const QString &host, quint16 port)
    16601665{
    1661     d_func()->pi.transferConnectionExtended = true;
    16621666    QStringList cmds;
    16631667    cmds << host;
    16641668    cmds << QString::number((uint)port);
    1665     return d_func()->addCommand(new QFtpCommand(ConnectToHost, cmds));
     1669    int id = d_func()->addCommand(new QFtpCommand(ConnectToHost, cmds));
     1670    d_func()->pi.transferConnectionExtended = true;
     1671    return id;
    16661672}
    16671673
     
    17221728int QFtp::setTransferMode(TransferMode mode)
    17231729{
     1730    int id = d_func()->addCommand(new QFtpCommand(SetTransferMode, QStringList()));
    17241731    d_func()->pi.transferConnectionExtended = true;
    17251732    d_func()->transferMode = mode;
    1726     return d_func()->addCommand(new QFtpCommand(SetTransferMode, QStringList()));
     1733    return id;
    17271734}
    17281735
     
    17311738    port. Calling this function with \a host empty disables proxying.
    17321739
    1733     QFtp does not support FTP-over-HTTP proxy servers. Use QHttp for
    1734     this.
     1740    QFtp does not support FTP-over-HTTP proxy servers. Use
     1741    QNetworkAccessManager for this.
    17351742*/
    17361743int QFtp::setProxy(const QString &host, quint16 port)
  • trunk/src/network/access/qftp.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/access/qhttp.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6565#endif
    6666
     67#ifndef QT_NO_HTTP
     68
    6769QT_BEGIN_NAMESPACE
    68 
    69 #ifndef QT_NO_HTTP
    7070
    7171class QHttpNormalRequest;
     
    122122    void _q_slotClosed();
    123123    void _q_slotBytesWritten(qint64 numBytes);
     124#ifndef QT_NO_OPENSSL
     125    void _q_slotEncryptedBytesWritten(qint64 numBytes);
     126#endif
    124127    void _q_slotDoFinished();
    125128    void _q_slotSendRequest();
     
    135138    void closeConn();
    136139    void setSock(QTcpSocket *sock);
     140
     141    void postMoreData();
    137142
    138143    QTcpSocket *socket;
     
    514519/*!
    515520    \class QHttpHeader
     521    \obsolete
    516522    \brief The QHttpHeader class contains header information for HTTP.
    517523
    518     \ingroup io
     524    \ingroup network
    519525    \inmodule QtNetwork
    520526
     
    625631QHttpHeader::~QHttpHeader()
    626632{
    627     delete d_ptr;
    628633}
    629634
     
    951956
    952957/*!
    953     Returns true if the header has an entry for the the special HTTP
     958    Returns true if the header has an entry for the special HTTP
    954959    header field \c content-type; otherwise returns false.
    955960
     
    10081013/*!
    10091014    \class QHttpResponseHeader
     1015    \obsolete
    10101016    \brief The QHttpResponseHeader class contains response header information for HTTP.
    10111017
    1012     \ingroup io
     1018    \ingroup network
    10131019    \inmodule QtNetwork
    10141020
     
    11531159}
    11541160
    1155 /*! \reimp
     1161/*! \internal
    11561162*/
    11571163bool QHttpResponseHeader::parseLine(const QString &line, int number)
     
    12121218/*!
    12131219    \class QHttpRequestHeader
     1220    \obsolete
    12141221    \brief The QHttpRequestHeader class contains request header information for HTTP.
    12151222
    1216     \ingroup io
     1223    \ingroup network
    12171224    \inmodule QtNetwork
    12181225
     
    13671374}
    13681375
    1369 /*! \reimp
     1376/*! \internal
    13701377*/
    13711378bool QHttpRequestHeader::parseLine(const QString &line, int number)
     
    14141421/*!
    14151422    \class QHttp
     1423    \obsolete
    14161424    \reentrant
    14171425
    14181426    \brief The QHttp class provides an implementation of the HTTP protocol.
    14191427
    1420     \ingroup io
     1428    \ingroup network
    14211429    \inmodule QtNetwork
    1422     \mainclass
     1430
    14231431
    14241432    This class provides a direct interface to HTTP that allows you to
    1425     have more control over the requests and that allows you to access
    1426     the response header fields. However, for new applications, it is
     1433    download and upload data with the HTTP protocol.
     1434    However, for new applications, it is
    14271435    recommended to use QNetworkAccessManager and QNetworkReply, as
    1428     those classes possess a simpler, yet more powerful API.
     1436    those classes possess a simpler, yet more powerful API
     1437    and a more modern protocol implementation.
    14291438
    14301439    The class works asynchronously, so there are no blocking
     
    14471456
    14481457    To make an HTTP request you must set up suitable HTTP headers. The
    1449     following example demonstrates, how to request the main HTML page
    1450     from the Trolltech home page (i.e., the URL
    1451     \c http://qtsoftware.com/index.html):
     1458    following example demonstrates how to request the main HTML page
     1459    from the Qt website (i.e., the URL \c http://qt.nokia.com/index.html):
    14521460
    14531461    \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 2
     
    15931601    This enum is used to specify the mode of connection to use:
    15941602
    1595     \value ConnectionModeHttp The connection is a regular Http connection to the server
    1596     \value ConnectionModeHttps The Https protocol is used and the connection is encrypted using SSL.
    1597 
    1598     When using the Https mode, care should be taken to connect to the sslErrors signal, and
    1599     handle possible Ssl errors.
     1603    \value ConnectionModeHttp The connection is a regular HTTP connection to the server
     1604    \value ConnectionModeHttps The HTTPS protocol is used and the connection is encrypted using SSL.
     1605
     1606    When using the HTTPS mode, care should be taken to connect to the sslErrors signal, and
     1607    handle possible SSL errors.
    16001608
    16011609    \sa QSslSocket
     
    20352043
    20362044    If port is 0, it will use the default port for the \a mode used
    2037     (80 for Http and 443 fopr Https).
     2045    (80 for HTTP and 443 for HTTPS).
    20382046
    20392047    The function does not block; instead, it returns immediately. The request
     
    21622170
    21632171    \a path must be a absolute path like \c /index.html or an
    2164     absolute URI like \c http://qtsoftware.com/index.html and
     2172    absolute URI like \c http://example.com/index.html and
    21652173    must be encoded with either QUrl::toPercentEncoding() or
    21662174    QUrl::encodedPath().
     
    22012209
    22022210    \a path must be an absolute path like \c /index.html or an
    2203     absolute URI like \c http://qtsoftware.com/index.html and
     2211    absolute URI like \c http://example.com/index.html and
    22042212    must be encoded with either QUrl::toPercentEncoding() or
    22052213    QUrl::encodedPath().
     
    22522260
    22532261    \a path must be an absolute path like \c /index.html or an
    2254     absolute URI like \c http://qtsoftware.com/index.html.
     2262    absolute URI like \c http://example.com/index.html.
    22552263
    22562264    The function does not block; instead, it returns immediately. The request
     
    26572665}
    26582666
     2667#ifndef QT_NO_OPENSSL
     2668void QHttpPrivate::_q_slotEncryptedBytesWritten(qint64 written)
     2669{
     2670    Q_UNUSED(written);
     2671    postMoreData();
     2672}
     2673#endif
     2674
    26592675void QHttpPrivate::_q_slotBytesWritten(qint64 written)
    26602676{
     
    26622678    bytesDone += written;
    26632679    emit q->dataSendProgress(bytesDone, bytesTotal);
    2664 
     2680    postMoreData();
     2681}
     2682
     2683// Send the POST data
     2684void QHttpPrivate::postMoreData()
     2685{
    26652686    if (pendingPost)
    26662687        return;
     
    26692690        return;
    26702691
     2692    // the following is backported code from Qt 4.6 QNetworkAccessManager.
     2693    // We also have to check the encryptedBytesToWrite() if it is an SSL socket.
     2694#ifndef QT_NO_OPENSSL
     2695    QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
     2696    // if it is really an ssl socket, check more than just bytesToWrite()
     2697    if ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0)) == 0) {
     2698#else
    26712699    if (socket->bytesToWrite() == 0) {
     2700#endif
    26722701        int max = qMin<qint64>(4096, postDevice->size() - postDevice->pos());
    26732702        QByteArray arr;
     
    30873116                     q, SLOT(_q_slotBytesWritten(qint64)));
    30883117#ifndef QT_NO_NETWORKPROXY
    3089     QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),
    3090                      q, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
     3118    QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
     3119                     q, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
    30913120#endif
    30923121
    30933122#ifndef QT_NO_OPENSSL
    30943123    if (qobject_cast<QSslSocket *>(socket)) {
    3095         QObject::connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)),
    3096                          q, SIGNAL(sslErrors(const QList<QSslError> &)));
     3124        QObject::connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
     3125                         q, SIGNAL(sslErrors(QList<QSslError>)));
     3126        QObject::connect(socket, SIGNAL(encryptedBytesWritten(qint64)),
     3127                         q, SLOT(_q_slotEncryptedBytesWritten(qint64)));
    30973128    }
    30983129#endif
  • trunk/src/network/access/qhttp.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747#include <QtCore/qmap.h>
    4848#include <QtCore/qpair.h>
     49#include <QtCore/qscopedpointer.h>
    4950
    5051QT_BEGIN_HEADER
     
    109110    QHttpHeader(QHttpHeaderPrivate &dd, const QString &str = QString());
    110111    QHttpHeader(QHttpHeaderPrivate &dd, const QHttpHeader &header);
    111     QHttpHeaderPrivate *d_ptr;
     112    QScopedPointer<QHttpHeaderPrivate> d_ptr;
    112113
    113114private:
     
    290291    Q_PRIVATE_SLOT(d_func(), void _q_slotClosed())
    291292    Q_PRIVATE_SLOT(d_func(), void _q_slotBytesWritten(qint64 numBytes))
     293#ifndef QT_NO_OPENSSL
     294    Q_PRIVATE_SLOT(d_func(), void _q_slotEncryptedBytesWritten(qint64 numBytes))
     295#endif
    292296    Q_PRIVATE_SLOT(d_func(), void _q_slotDoFinished())
    293297    Q_PRIVATE_SLOT(d_func(), void _q_slotSendRequest())
  • trunk/src/network/access/qhttpnetworkconnection.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4141
    4242#include "qhttpnetworkconnection_p.h"
     43#include "qhttpnetworkconnectionchannel_p.h"
     44#include "private/qnoncontiguousbytedevice_p.h"
    4345#include <private/qnetworkrequest_p.h>
    4446#include <private/qobject_p.h>
     
    4648#include <qnetworkproxy.h>
    4749#include <qauthenticator.h>
    48 #include <qbytearraymatcher.h>
     50
    4951#include <qbuffer.h>
    5052#include <qpair.h>
     
    6062#endif
    6163
    62 #ifndef QT_NO_COMPRESS
    63 #    include <zlib.h>
    64 static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header
    65 // gzip flag byte
    66 #define HEAD_CRC     0x02 // bit 1 set: header CRC present
    67 #define EXTRA_FIELD  0x04 // bit 2 set: extra field present
    68 #define ORIG_NAME    0x08 // bit 3 set: original file name present
    69 #define COMMENT      0x10 // bit 4 set: file comment present
    70 #define RESERVED     0xE0 // bits 5..7: reserved
    71 #define CHUNK 16384
     64
     65
     66QT_BEGIN_NAMESPACE
     67
     68#ifdef Q_OS_SYMBIAN
     69const int QHttpNetworkConnectionPrivate::defaultChannelCount = 3;
     70#else
     71const int QHttpNetworkConnectionPrivate::defaultChannelCount = 6;
    7272#endif
    7373
    74 QT_BEGIN_NAMESPACE
    75 
    76 class QHttpNetworkHeaderPrivate : public QSharedData
    77 {
    78 public:
    79     QUrl url;
    80     QList<QPair<QByteArray, QByteArray> > fields;
    81 
    82     QHttpNetworkHeaderPrivate(const QUrl &newUrl = QUrl());
    83     QHttpNetworkHeaderPrivate(const QHttpNetworkHeaderPrivate &other);
    84     inline qint64 contentLength() const;
    85     inline void setContentLength(qint64 length);
    86 
    87     inline QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const;
    88     inline QList<QByteArray> headerFieldValues(const QByteArray &name) const;
    89     inline void setHeaderField(const QByteArray &name, const QByteArray &data);
    90     bool operator==(const QHttpNetworkHeaderPrivate &other) const;
    91 
    92 };
    93 
    94 QHttpNetworkHeaderPrivate::QHttpNetworkHeaderPrivate(const QUrl &newUrl)
    95     :url(newUrl)
    96 {
    97 }
    98 
    99 QHttpNetworkHeaderPrivate::QHttpNetworkHeaderPrivate(const QHttpNetworkHeaderPrivate &other)
    100     :QSharedData(other)
    101 {
    102     url = other.url;
    103     fields = other.fields;
    104 }
    105 
    106 qint64 QHttpNetworkHeaderPrivate::contentLength() const
    107 {
    108     bool ok = false;
    109     QByteArray value = headerField("content-length");
    110     qint64 length = value.toULongLong(&ok);
    111     if (ok)
    112         return length;
    113     return -1; // the header field is not set
    114 }
    115 
    116 void QHttpNetworkHeaderPrivate::setContentLength(qint64 length)
    117 {
    118     setHeaderField("Content-Length", QByteArray::number(length));
    119 }
    120 
    121 QByteArray QHttpNetworkHeaderPrivate::headerField(const QByteArray &name, const QByteArray &defaultValue) const
    122 {
    123     QList<QByteArray> allValues = headerFieldValues(name);
    124     if (allValues.isEmpty())
    125         return defaultValue;
    126 
    127     QByteArray result;
    128     bool first = true;
    129     foreach (QByteArray value, allValues) {
    130         if (!first)
    131             result += ", ";
    132         first = false;
    133         result += value;
    134     }
    135     return result;
    136 }
    137 
    138 QList<QByteArray> QHttpNetworkHeaderPrivate::headerFieldValues(const QByteArray &name) const
    139 {
    140     QList<QByteArray> result;
    141     QByteArray lowerName = name.toLower();
    142     QList<QPair<QByteArray, QByteArray> >::ConstIterator it = fields.constBegin(),
    143                                                         end = fields.constEnd();
    144     for ( ; it != end; ++it)
    145         if (lowerName == it->first.toLower())
    146             result += it->second;
    147 
    148     return result;
    149 }
    150 
    151 void QHttpNetworkHeaderPrivate::setHeaderField(const QByteArray &name, const QByteArray &data)
    152 {
    153     QByteArray lowerName = name.toLower();
    154     QList<QPair<QByteArray, QByteArray> >::Iterator it = fields.begin();
    155     while (it != fields.end()) {
    156         if (lowerName == it->first.toLower())
    157             it = fields.erase(it);
    158         else
    159             ++it;
    160     }
    161     fields.append(qMakePair(name, data));
    162 }
    163 
    164 bool QHttpNetworkHeaderPrivate::operator==(const QHttpNetworkHeaderPrivate &other) const
    165 {
    166    return (url == other.url);
    167 }
    168 
    169 // QHttpNetworkRequestPrivate
    170 class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate
    171 {
    172 public:
    173     QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
    174         QHttpNetworkRequest::Priority pri, const QUrl &newUrl = QUrl());
    175     QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other);
    176     ~QHttpNetworkRequestPrivate();
    177     bool operator==(const QHttpNetworkRequestPrivate &other) const;
    178     QByteArray methodName() const;
    179     QByteArray uri(bool throughProxy) const;
    180 
    181     static QByteArray header(const QHttpNetworkRequest &request, bool throughProxy);
    182 
    183     QHttpNetworkRequest::Operation operation;
    184     QHttpNetworkRequest::Priority priority;
    185     mutable QIODevice *data;
    186     bool autoDecompress;
    187 };
    188 
    189 QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
    190         QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
    191     : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), data(0),
    192       autoDecompress(false)
    193 {
    194 }
    195 
    196 QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other)
    197     : QHttpNetworkHeaderPrivate(other)
    198 {
    199     operation = other.operation;
    200     priority = other.priority;
    201     data = other.data;
    202     autoDecompress = other.autoDecompress;
    203 }
    204 
    205 QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate()
    206 {
    207 }
    208 
    209 bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &other) const
    210 {
    211     return QHttpNetworkHeaderPrivate::operator==(other)
    212         && (operation == other.operation)
    213         && (data == other.data);
    214 }
    215 
    216 QByteArray QHttpNetworkRequestPrivate::methodName() const
    217 {
    218     QByteArray ba;
    219     switch (operation) {
    220     case QHttpNetworkRequest::Options:
    221         ba += "OPTIONS";
    222         break;
    223     case QHttpNetworkRequest::Get:
    224         ba += "GET";
    225         break;
    226     case QHttpNetworkRequest::Head:
    227         ba += "HEAD";
    228         break;
    229     case QHttpNetworkRequest::Post:
    230         ba += "POST";
    231         break;
    232     case QHttpNetworkRequest::Put:
    233         ba += "PUT";
    234         break;
    235     case QHttpNetworkRequest::Delete:
    236         ba += "DELETE";
    237         break;
    238     case QHttpNetworkRequest::Trace:
    239         ba += "TRACE";
    240         break;
    241     case QHttpNetworkRequest::Connect:
    242         ba += "CONNECT";
    243         break;
    244     default:
    245         break;
    246     }
    247     return ba;
    248 }
    249 
    250 QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const
    251 {
    252     QUrl::FormattingOptions format(QUrl::RemoveFragment);
    253 
    254     // for POST, query data is send as content
    255     if (operation == QHttpNetworkRequest::Post && !data)
    256         format |= QUrl::RemoveQuery;
    257     // for requests through proxy, the Request-URI contains full url
    258     if (throughProxy)
    259         format |= QUrl::RemoveUserInfo;
    260     else
    261         format |= QUrl::RemoveScheme | QUrl::RemoveAuthority;
    262     QByteArray uri = url.toEncoded(format);
    263     if (uri.isEmpty() || (throughProxy && url.path().isEmpty()))
    264         uri += '/';
    265     return uri;
    266 }
    267 
    268 QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request, bool throughProxy)
    269 {
    270     QByteArray ba = request.d->methodName();
    271     QByteArray uri = request.d->uri(throughProxy);
    272     ba += " " + uri;
    273 
    274     QString majorVersion = QString::number(request.majorVersion());
    275     QString minorVersion = QString::number(request.minorVersion());
    276     ba += " HTTP/" + majorVersion.toLatin1() + "." + minorVersion.toLatin1() + "\r\n";
    277 
    278     QList<QPair<QByteArray, QByteArray> > fields = request.header();
    279     QList<QPair<QByteArray, QByteArray> >::const_iterator it = fields.constBegin();
    280     for (; it != fields.constEnd(); ++it)
    281         ba += it->first + ": " + it->second + "\r\n";
    282     if (request.d->operation == QHttpNetworkRequest::Post) {
    283         // add content type, if not set in the request
    284         if (request.headerField("content-type").isEmpty())
    285             ba += "Content-Type: application/x-www-form-urlencoded\r\n";
    286         if (!request.d->data && request.d->url.hasQuery()) {
    287             QByteArray query = request.d->url.encodedQuery();
    288             ba += "Content-Length: "+ QByteArray::number(query.size()) + "\r\n";
    289             ba += "\r\n";
    290             ba += query;
    291         } else {
    292             ba += "\r\n";
    293         }
    294     } else {
    295         ba += "\r\n";
    296     }
    297      return ba;
    298 }
    299 
    300 class QHttpNetworkReplyPrivate : public QObjectPrivate, public QHttpNetworkHeaderPrivate
    301 {
    302 public:
    303     QHttpNetworkReplyPrivate(const QUrl &newUrl = QUrl());
    304     ~QHttpNetworkReplyPrivate();
    305     qint64 readStatus(QAbstractSocket *socket);
    306     void parseStatus(const QByteArray &status);
    307     qint64 readHeader(QAbstractSocket *socket);
    308     void parseHeader(const QByteArray &header);
    309     qint64 readBody(QAbstractSocket *socket, QIODevice *out);
    310     bool findChallenge(bool forProxy, QByteArray &challenge) const;
    311     QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const;
    312     void clear();
    313 
    314     qint64 transferRaw(QIODevice *in, QIODevice *out, qint64 size);
    315     qint64 transferChunked(QIODevice *in, QIODevice *out);
    316     qint64 getChunkSize(QIODevice *in, qint64 *chunkSize);
    317 
    318     qint64 bytesAvailable() const;
    319     bool isChunked();
    320     bool connectionCloseEnabled();
    321     bool isGzipped();
    322 #ifndef QT_NO_COMPRESS
    323     bool gzipCheckHeader(QByteArray &content, int &pos);
    324     int gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated);
    325 #endif
    326     void removeAutoDecompressHeader();
    327 
    328     enum ReplyState {
    329         NothingDoneState,
    330         ReadingStatusState,
    331         ReadingHeaderState,
    332         ReadingDataState,
    333         AllDoneState
    334     } state;
    335 
    336     QHttpNetworkRequest request;
    337     int statusCode;
    338     int majorVersion;
    339     int minorVersion;
    340     QString errorString;
    341     QString reasonPhrase;
    342     qint64 bodyLength;
    343     qint64 contentRead;
    344     qint64 totalProgress;
    345     QByteArray fragment;
    346     qint64 currentChunkSize;
    347     qint64 currentChunkRead;
    348     QPointer<QHttpNetworkConnection> connection;
    349     bool initInflate;
    350     bool streamEnd;
    351 #ifndef QT_NO_COMPRESS
    352     z_stream inflateStrm;
    353 #endif
    354     bool autoDecompress;
    355 
    356     QByteArray responseData; // uncompressed body
    357     QByteArray compressedData; // compressed body (temporary)
    358     QBuffer requestDataBuffer;
    359     bool requestIsBuffering;
    360     bool requestIsPrepared;
    361 };
    362 
    363 QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
    364     : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100),
    365       majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0),
    366       currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false),
    367       autoDecompress(false), requestIsBuffering(false), requestIsPrepared(false)
    368 {
    369 }
    370 
    371 QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate()
    372 {
    373 }
    374 
    375 void QHttpNetworkReplyPrivate::clear()
    376 {
    377     state = NothingDoneState;
    378     statusCode = 100;
    379     bodyLength = 0;
    380     contentRead = 0;
    381     totalProgress = 0;
    382     currentChunkSize = 0;
    383     currentChunkRead = 0;
    384     connection = 0;
    385 #ifndef QT_NO_COMPRESS
    386     if (initInflate)
    387         inflateEnd(&inflateStrm);
    388 #endif
    389     initInflate = false;
    390     streamEnd = false;
    391     autoDecompress = false;
    392     fields.clear();
    393 }
    394 
    395 // QHttpNetworkReplyPrivate
    396 qint64 QHttpNetworkReplyPrivate::bytesAvailable() const
    397 {
    398     return (state != ReadingDataState ? 0 : fragment.size());
    399 }
    400 
    401 bool QHttpNetworkReplyPrivate::isGzipped()
    402 {
    403     QByteArray encoding = headerField("content-encoding");
    404     return encoding.toLower() == "gzip";
    405 }
    406 
    407 void QHttpNetworkReplyPrivate::removeAutoDecompressHeader()
    408 {
    409     // The header "Content-Encoding  = gzip" is retained.
    410     // Content-Length is removed since the actual one send by the server is for compressed data
    411     QByteArray name("content-length");
    412     QByteArray lowerName = name.toLower();
    413     QList<QPair<QByteArray, QByteArray> >::Iterator it = fields.begin(),
    414                                                    end = fields.end();
    415     while (it != end) {
    416         if (name == it->first.toLower()) {
    417             fields.erase(it);
    418             break;
    419         }
    420         ++it;
    421     }
    422 
    423 }
    424 
    425 bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const
    426 {
    427     challenge.clear();
    428     // find out the type of authentication protocol requested.
    429     QByteArray header = forProxy ? "proxy-authenticate" : "www-authenticate";
    430     // pick the best protocol (has to match parsing in QAuthenticatorPrivate)
    431     QList<QByteArray> challenges = headerFieldValues(header);
    432     for (int i = 0; i<challenges.size(); i++) {
    433         QByteArray line = challenges.at(i);
    434         if (!line.toLower().startsWith("negotiate"))
    435             challenge = line;
    436     }
    437     return !challenge.isEmpty();
    438 }
    439 
    440 QAuthenticatorPrivate::Method QHttpNetworkReplyPrivate::authenticationMethod(bool isProxy) const
    441 {
    442     // The logic is same as the one used in void QAuthenticatorPrivate::parseHttpResponse()
    443     QAuthenticatorPrivate::Method method = QAuthenticatorPrivate::None;
    444     QByteArray header = isProxy ? "proxy-authenticate" : "www-authenticate";
    445     QList<QByteArray> challenges = headerFieldValues(header);
    446     for (int i = 0; i<challenges.size(); i++) {
    447         QByteArray line = challenges.at(i).trimmed().toLower();
    448         if (method < QAuthenticatorPrivate::Basic
    449             && line.startsWith("basic")) {
    450             method = QAuthenticatorPrivate::Basic;
    451         } else if (method < QAuthenticatorPrivate::Ntlm
    452             && line.startsWith("ntlm")) {
    453             method = QAuthenticatorPrivate::Ntlm;
    454         } else if (method < QAuthenticatorPrivate::DigestMd5
    455             && line.startsWith("digest")) {
    456             method = QAuthenticatorPrivate::DigestMd5;
    457         }
    458     }
    459     return method;
    460 }
    461 
    462 #ifndef QT_NO_COMPRESS
    463 bool QHttpNetworkReplyPrivate::gzipCheckHeader(QByteArray &content, int &pos)
    464 {
    465     int method = 0; // method byte
    466     int flags = 0;  // flags byte
    467     bool ret = false;
    468 
    469     // Assure two bytes in the buffer so we can peek ahead -- handle case
    470     // where first byte of header is at the end of the buffer after the last
    471     // gzip segment
    472     pos = -1;
    473     QByteArray &body = content;
    474     int maxPos = body.size()-1;
    475     if (maxPos < 1) {
    476         return ret;
    477     }
    478 
    479     // Peek ahead to check the gzip magic header
    480     if (body[0] != char(gz_magic[0]) ||
    481         body[1] != char(gz_magic[1])) {
    482         return ret;
    483     }
    484     pos += 2;
    485     // Check the rest of the gzip header
    486     if (++pos <= maxPos)
    487         method = body[pos];
    488     if (pos++ <= maxPos)
    489         flags = body[pos];
    490     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
    491         return ret;
    492     }
    493 
    494     // Discard time, xflags and OS code:
    495     pos += 6;
    496     if (pos > maxPos)
    497         return ret;
    498     if ((flags & EXTRA_FIELD) && ((pos+2) <= maxPos)) { // skip the extra field
    499         unsigned len =  (unsigned)body[++pos];
    500         len += ((unsigned)body[++pos])<<8;
    501         pos += len;
    502         if (pos > maxPos)
    503             return ret;
    504     }
    505     if ((flags & ORIG_NAME) != 0) { // skip the original file name
    506         while(++pos <= maxPos && body[pos]) {}
    507     }
    508     if ((flags & COMMENT) != 0) {   // skip the .gz file comment
    509         while(++pos <= maxPos && body[pos]) {}
    510     }
    511     if ((flags & HEAD_CRC) != 0) {  // skip the header crc
    512         pos += 2;
    513         if (pos > maxPos)
    514             return ret;
    515     }
    516     ret = (pos < maxPos); // return failed, if no more bytes left
    517     return ret;
    518 }
    519 
    520 int QHttpNetworkReplyPrivate::gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated)
    521 {
    522     int ret = Z_DATA_ERROR;
    523     unsigned have;
    524     unsigned char out[CHUNK];
    525     int pos = -1;
    526 
    527     if (!initInflate) {
    528         // check the header
    529         if (!gzipCheckHeader(compressed, pos))
    530             return ret;
    531         // allocate inflate state
    532         inflateStrm.zalloc = Z_NULL;
    533         inflateStrm.zfree = Z_NULL;
    534         inflateStrm.opaque = Z_NULL;
    535         inflateStrm.avail_in = 0;
    536         inflateStrm.next_in = Z_NULL;
    537         ret = inflateInit2(&inflateStrm, -MAX_WBITS);
    538         if (ret != Z_OK)
    539             return ret;
    540         initInflate = true;
    541         streamEnd = false;
    542     }
    543 
    544     //remove the header.
    545     compressed.remove(0, pos+1);
    546     // expand until deflate stream ends
    547     inflateStrm.next_in = (unsigned char *)compressed.data();
    548     inflateStrm.avail_in = compressed.size();
    549     do {
    550         inflateStrm.avail_out = sizeof(out);
    551         inflateStrm.next_out = out;
    552         ret = inflate(&inflateStrm, Z_NO_FLUSH);
    553         switch (ret) {
    554         case Z_NEED_DICT:
    555             ret = Z_DATA_ERROR;
    556             // and fall through
    557         case Z_DATA_ERROR:
    558         case Z_MEM_ERROR:
    559             inflateEnd(&inflateStrm);
    560             initInflate = false;
    561             return ret;
    562         }
    563         have = sizeof(out) - inflateStrm.avail_out;
    564         inflated.append(QByteArray((const char *)out, have));
    565      } while (inflateStrm.avail_out == 0);
    566     // clean up and return
    567     if (ret <= Z_ERRNO || ret == Z_STREAM_END) {
    568         inflateEnd(&inflateStrm);
    569         initInflate = false;
    570     }
    571     streamEnd = (ret == Z_STREAM_END);
    572     return ret;
    573 }
    574 #endif
    575 
    576 qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
    577 {
    578     qint64 bytes = 0;
    579     char c;
    580 
    581     while (socket->bytesAvailable()) {
    582         // allow both CRLF & LF (only) line endings
    583         if (socket->peek(&c, 1) == 1 && c == '\n') {
    584             bytes += socket->read(&c, 1); // read the "n"
    585             // remove the CR at the end
    586             if (fragment.endsWith('\r')) {
    587                 fragment.truncate(fragment.length()-1);
    588             }
    589             parseStatus(fragment);
    590             state = ReadingHeaderState;
    591             fragment.clear(); // next fragment
    592             break;
    593         } else {
    594             c = 0;
    595             bytes += socket->read(&c, 1);
    596             fragment.append(c);
    597         }
    598     }
    599     return bytes;
    600 }
    601 
    602 void QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status)
    603 {
    604     const QByteArrayMatcher sp(" ");
    605     int i = sp.indexIn(status);
    606     const QByteArray version = status.mid(0, i);
    607     int j = sp.indexIn(status, i + 1);
    608     const QByteArray code = status.mid(i + 1, j - i - 1);
    609     const QByteArray reason = status.mid(j + 1, status.count() - j);
    610 
    611     const QByteArrayMatcher slash("/");
    612     int k = slash.indexIn(version);
    613     const QByteArrayMatcher dot(".");
    614     int l = dot.indexIn(version, k);
    615     const QByteArray major = version.mid(k + 1, l - k - 1);
    616     const QByteArray minor = version.mid(l + 1, version.count() - l);
    617 
    618     majorVersion = QString::fromAscii(major.constData()).toInt();
    619     minorVersion = QString::fromAscii(minor.constData()).toInt();
    620     statusCode = QString::fromAscii(code.constData()).toInt();
    621     reasonPhrase = QString::fromAscii(reason.constData());
    622 }
    623 
    624 qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket)
    625 {
    626     qint64 bytes = 0;
    627     char crlfcrlf[5];
    628     crlfcrlf[4] = '\0';
    629     char c = 0;
    630     bool allHeaders = false;
    631     while (!allHeaders && socket->bytesAvailable()) {
    632         if (socket->peek(&c, 1) == 1 && c == '\n') {
    633             // check for possible header endings. As per HTTP rfc,
    634             // the header endings will be marked by CRLFCRLF. But
    635             // we will allow CRLFLF, LFLF & CRLFCRLF
    636             if (fragment.endsWith("\n\r") || fragment.endsWith('\n'))
    637                 allHeaders = true;
    638         }
    639         bytes += socket->read(&c, 1);
    640         fragment.append(c);
    641     }
    642     // we received all headers now parse them
    643     if (allHeaders) {
    644         parseHeader(fragment);
    645         state = ReadingDataState;
    646         fragment.clear(); // next fragment
    647         bodyLength = contentLength(); // cache the length
    648     }
    649     return bytes;
    650 }
    651 
    652 void QHttpNetworkReplyPrivate::parseHeader(const QByteArray &header)
    653 {
    654     // see rfc2616, sec 4 for information about HTTP/1.1 headers.
    655     // allows relaxed parsing here, accepts both CRLF & LF line endings
    656     const QByteArrayMatcher lf("\n");
    657     const QByteArrayMatcher colon(":");
    658     int i = 0;
    659     while (i < header.count()) {
    660         int j = colon.indexIn(header, i); // field-name
    661         if (j == -1)
    662             break;
    663         const QByteArray field = header.mid(i, j - i).trimmed();
    664         j++;
    665         // any number of LWS is allowed before and after the value
    666         QByteArray value;
    667         do {
    668             i = lf.indexIn(header, j);
    669             if (i == -1)
    670                 break;
    671             if (!value.isEmpty())
    672                 value += ' ';
    673             // check if we have CRLF or only LF
    674             bool hasCR = (i && header[i-1] == '\r');
    675             int length = i -(hasCR ? 1: 0) - j;
    676             value += header.mid(j, length).trimmed();
    677             j = ++i;
    678         } while (i < header.count() && (header.at(i) == ' ' || header.at(i) == '\t'));
    679         if (i == -1)
    680             break; // something is wrong
    681 
    682         fields.append(qMakePair(field, value));
    683     }
    684 }
    685 
    686 bool QHttpNetworkReplyPrivate::isChunked()
    687 {
    688     return headerField("transfer-encoding").toLower().contains("chunked");
    689 }
    690 
    691 bool QHttpNetworkReplyPrivate::connectionCloseEnabled()
    692 {
    693     return (headerField("connection").toLower().contains("close") ||
    694             headerField("proxy-connection").toLower().contains("close"));
    695 }
    696 
    697 qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *out)
    698 {
    699     qint64 bytes = 0;
    700     if (isChunked()) {
    701         bytes += transferChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6)
    702     } else if (bodyLength > 0) { // we have a Content-Length
    703         bytes += transferRaw(socket, out, bodyLength - contentRead);
    704         if (contentRead + bytes == bodyLength)
    705             state = AllDoneState;
    706     } else {
    707         bytes += transferRaw(socket, out, socket->bytesAvailable());
    708     }
    709     if (state == AllDoneState)
    710         socket->readAll(); // Read the rest to clean (CRLF)
    711     contentRead += bytes;
    712     return bytes;
    713 }
    714 
    715 qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint64 size)
    716 {
    717     qint64 bytes = 0;
    718     Q_ASSERT(in);
    719     Q_ASSERT(out);
    720 
    721     int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable()));
    722     QByteArray raw(toBeRead, 0);
    723     while (size > 0) {
    724         qint64 read = in->read(raw.data(), raw.size());
    725         if (read == 0)
    726             return bytes;
    727         // ### error checking here
    728         qint64 written = out->write(raw.data(), read);
    729         if (written == 0)
    730             return bytes;
    731         if (read != written)
    732             qDebug() << "### read" << read << "written" << written;
    733         bytes += read;
    734         size -= read;
    735         out->waitForBytesWritten(-1); // throttle
    736     }
    737     return bytes;
    738 
    739 }
    740 
    741 qint64 QHttpNetworkReplyPrivate::transferChunked(QIODevice *in, QIODevice *out)
    742 {
    743     qint64 bytes = 0;
    744     while (in->bytesAvailable()) { // while we can read from input
    745         // if we are done with the current chunk, get the size of the new chunk
    746         if (currentChunkRead >= currentChunkSize) {
    747             currentChunkSize = 0;
    748             currentChunkRead = 0;
    749             if (bytes) {
    750                 char crlf[2];
    751                 bytes += in->read(crlf, 2); // read the "\r\n" after the chunk
    752             }
    753             bytes += getChunkSize(in, &currentChunkSize);
    754             if (currentChunkSize == -1)
    755                 break;
    756         }
    757         // if the chunk size is 0, end of the stream
    758         if (currentChunkSize == 0) {
    759             state = AllDoneState;
    760             break;
    761         }
    762         // otherwise, read data
    763         qint64 readSize = qMin(in->bytesAvailable(), currentChunkSize - currentChunkRead);
    764         QByteArray buffer(readSize, 0);
    765         qint64 read = in->read(buffer.data(), readSize);
    766         bytes += read;
    767         currentChunkRead += read;
    768         qint64 written = out->write(buffer);
    769         Q_UNUSED(written); // Avoid compile warning when building release
    770         Q_ASSERT(read == written);
    771         // ### error checking here
    772         out->waitForBytesWritten(-1);
    773     }
    774     return bytes;
    775 }
    776 
    777 qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize)
    778 {
    779     qint64 bytes = 0;
    780     char crlf[2];
    781     *chunkSize = -1;
    782     int bytesAvailable = in->bytesAvailable();
    783     while (bytesAvailable > bytes) {
    784         qint64 sniffedBytes =  in->peek(crlf, 2);
    785         int fragmentSize = fragment.size();
    786         // check the next two bytes for a "\r\n", skip blank lines
    787         if ((fragmentSize && sniffedBytes == 2 && crlf[0] == '\r' && crlf[1] == '\n')
    788            ||(fragmentSize > 1 && fragment.endsWith('\r')  && crlf[0] == '\n'))
    789         {
    790             bytes += in->read(crlf, 1);     // read the \r or \n
    791             if (crlf[0] == '\r')
    792                 bytes += in->read(crlf, 1); // read the \n
    793             bool ok = false;
    794             // ignore the chunk-extension
    795             fragment = fragment.mid(0, fragment.indexOf(';')).trimmed();
    796             *chunkSize = fragment.toLong(&ok, 16);
    797             fragment.clear();
    798             break; // size done
    799         } else {
    800             // read the fragment to the buffer
    801             char c = 0;
    802             bytes += in->read(&c, 1);
    803             fragment.append(c);
    804         }
    805     }
    806     return bytes;
    807 }
    808 
    809 // QHttpNetworkConnectionPrivate
    810 
    811 typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
    812 
    813 class QHttpNetworkConnectionPrivate : public QObjectPrivate
    814 {
    815     Q_DECLARE_PUBLIC(QHttpNetworkConnection)
    816 public:
    817     QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt);
    818     ~QHttpNetworkConnectionPrivate();
    819     void init();
    820     void connectSignals(QAbstractSocket *socket);
    821 
    822     enum SocketState {
    823         IdleState = 0,          // ready to send request
    824         ConnectingState = 1,    // connecting to host
    825         WritingState = 2,       // writing the data
    826         WaitingState = 4,       // waiting for reply
    827         ReadingState = 8,       // reading the reply
    828         Wait4AuthState = 0x10,  // blocked for send till the current authentication slot is done
    829         BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|Wait4AuthState)
    830     };
    831 
    832     enum { ChunkSize = 4096 };
    833 
    834     int indexOf(QAbstractSocket *socket) const;
    835     bool isSocketBusy(QAbstractSocket *socket) const;
    836     bool isSocketWriting(QAbstractSocket *socket) const;
    837     bool isSocketWaiting(QAbstractSocket *socket) const;
    838     bool isSocketReading(QAbstractSocket *socket) const;
    839 
    840     QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request);
    841     void unqueueRequest(QAbstractSocket *socket);
    842     void prepareRequest(HttpMessagePair &request);
    843     bool sendRequest(QAbstractSocket *socket);
    844     void receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply);
    845     void resendCurrentRequest(QAbstractSocket *socket);
    846     void closeChannel(int channel);
    847     void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy);
    848 
    849     // private slots
    850     void _q_bytesWritten(qint64 bytes); // proceed sending
    851     void _q_readyRead(); // pending data to read
    852     void _q_disconnected(); // disconnected from host
    853     void _q_startNextRequest(); // send the next request from the queue
    854     void _q_restartPendingRequest(); // send the currently blocked request
    855     void _q_connected(); // start sending request
    856     void _q_error(QAbstractSocket::SocketError); // error from socket
    857 #ifndef QT_NO_NETWORKPROXY
    858     void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy
    859 #endif
    860     void _q_dataReadyReadNoBuffer();
    861     void _q_dataReadyReadBuffer();
    862 
    863     void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
    864     bool ensureConnection(QAbstractSocket *socket);
    865     QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket);
    866     void eraseData(QHttpNetworkReply *reply);
    867 #ifndef QT_NO_COMPRESS
    868     bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete);
    869 #endif
    870     void bufferData(HttpMessagePair &request);
    871     void removeReply(QHttpNetworkReply *reply);
    872 
    873     QString hostName;
    874     quint16 port;
    875     bool encrypt;
    876 
    877     struct Channel {
    878         QAbstractSocket *socket;
    879         SocketState state;
    880         QHttpNetworkRequest request; // current request
    881         QHttpNetworkReply *reply; // current reply for this request
    882         qint64 written;
    883         qint64 bytesTotal;
    884         bool resendCurrent;
    885         int lastStatus; // last status received on this channel
    886         bool pendingEncrypt; // for https (send after encrypted)
    887         int reconnectAttempts; // maximum 2 reconnection attempts
    888         QAuthenticatorPrivate::Method authMehtod;
    889         QAuthenticatorPrivate::Method proxyAuthMehtod;
    890         QAuthenticator authenticator;
    891         QAuthenticator proxyAuthenticator;
    892 #ifndef QT_NO_OPENSSL
    893         bool ignoreSSLErrors;
    894 #endif
    895         Channel() :state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false), reconnectAttempts(2),
    896             authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None)
    897 #ifndef QT_NO_OPENSSL
    898             , ignoreSSLErrors(false)
    899 #endif
    900         {}
    901     };
    902     static const int channelCount;
    903     Channel channels[2]; // maximum of 2 socket connections to the server
    904     bool pendingAuthSignal; // there is an incomplete authentication signal
    905     bool pendingProxyAuthSignal; // there is an incomplete proxy authentication signal
    906 
    907     void appendData(QHttpNetworkReply &reply, const QByteArray &fragment, bool compressed);
    908     qint64 bytesAvailable(const QHttpNetworkReply &reply, bool compressed = false) const;
    909     qint64 read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize, bool compressed);
    910     void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode);
    911     bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend);
    912     void allDone(QAbstractSocket *socket, QHttpNetworkReply *reply);
    913     void handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply);
    914     inline bool emitSignals(QHttpNetworkReply *reply);
    915     inline bool expectContent(QHttpNetworkReply *reply);
    916 
    917 #ifndef QT_NO_OPENSSL
    918     void _q_encrypted(); // start sending request (https)
    919     void _q_sslErrors(const QList<QSslError> &errors); // ssl errors from the socket
    920     QSslConfiguration sslConfiguration(const QHttpNetworkReply &reply) const;
    921 #endif
    922 
    923 #ifndef QT_NO_NETWORKPROXY
    924     QNetworkProxy networkProxy;
    925 #endif
    926 
    927     //The request queues
    928     QList<HttpMessagePair> highPriorityQueue;
    929     QList<HttpMessagePair> lowPriorityQueue;
    930 };
    931 
    932 const int QHttpNetworkConnectionPrivate::channelCount = 2;
     74// the maximum amount of requests that might be pipelined into a socket
     75// from what was suggested, 3 seems to be OK
     76const int QHttpNetworkConnectionPrivate::defaultPipelineLength = 3;
     77
    93378
    93479QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt)
    93580: hostName(hostName), port(port), encrypt(encrypt),
     81  channelCount(defaultChannelCount),
    93682  pendingAuthSignal(false), pendingProxyAuthSignal(false)
    93783#ifndef QT_NO_NETWORKPROXY
     
    93985#endif
    94086{
    941 }
     87    channels = new QHttpNetworkConnectionChannel[channelCount];
     88}
     89
     90QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt)
     91: hostName(hostName), port(port), encrypt(encrypt),
     92  channelCount(channelCount),
     93  pendingAuthSignal(false), pendingProxyAuthSignal(false)
     94#ifndef QT_NO_NETWORKPROXY
     95  , networkProxy(QNetworkProxy::NoProxy)
     96#endif
     97{
     98    channels = new QHttpNetworkConnectionChannel[channelCount];
     99}
     100
     101
    942102
    943103QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
    944104{
    945105    for (int i = 0; i < channelCount; ++i) {
    946         channels[i].socket->close();
    947         delete channels[i].socket;
    948     }
    949 }
    950 
    951 void QHttpNetworkConnectionPrivate::connectSignals(QAbstractSocket *socket)
    952 {
    953     Q_Q(QHttpNetworkConnection);
    954 
    955     QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
    956                q, SLOT(_q_bytesWritten(qint64)),
    957                Qt::DirectConnection);
    958     QObject::connect(socket, SIGNAL(connected()),
    959                q, SLOT(_q_connected()),
    960                Qt::DirectConnection);
    961     QObject::connect(socket, SIGNAL(readyRead()),
    962                q, SLOT(_q_readyRead()),
    963                Qt::DirectConnection);
    964     QObject::connect(socket, SIGNAL(disconnected()),
    965                q, SLOT(_q_disconnected()),
    966                Qt::DirectConnection);
    967     QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
    968                q, SLOT(_q_error(QAbstractSocket::SocketError)),
    969                Qt::DirectConnection);
    970 #ifndef QT_NO_NETWORKPROXY
    971     QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
    972                q, SLOT(_q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
    973                Qt::DirectConnection);
    974 #endif
    975 
    976 #ifndef QT_NO_OPENSSL
    977     QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
    978     QObject::connect(sslSocket, SIGNAL(encrypted()),
    979                      q, SLOT(_q_encrypted()),
    980                      Qt::DirectConnection);
    981     QObject::connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError>&)),
    982                q, SLOT(_q_sslErrors(const QList<QSslError>&)),
    983                Qt::DirectConnection);
    984 #endif
     106        if (channels[i].socket) {
     107            channels[i].socket->close();
     108            delete channels[i].socket;
     109        }
     110    }
     111    delete []channels;
    985112}
    986113
    987114void QHttpNetworkConnectionPrivate::init()
    988115{
    989     for (int i = 0; i < channelCount; ++i) {
    990 #ifndef QT_NO_OPENSSL
    991         channels[i].socket = new QSslSocket;
    992 #else
    993         channels[i].socket = new QTcpSocket;
    994 #endif
    995         connectSignals(channels[i].socket);
     116    for (int i = 0; i < channelCount; i++) {
     117        channels[i].setConnection(this->q_func());
     118        channels[i].init();
    996119    }
    997120}
     
    1002125        if (channels[i].socket == socket)
    1003126            return i;
    1004     return -1;
    1005 }
    1006 
    1007 bool QHttpNetworkConnectionPrivate::isSocketBusy(QAbstractSocket *socket) const
    1008 {
    1009     int i = indexOf(socket);
    1010     return (channels[i].state & BusyState);
    1011 }
    1012 
    1013 bool QHttpNetworkConnectionPrivate::isSocketWriting(QAbstractSocket *socket) const
    1014 {
    1015     int i = indexOf(socket);
    1016     return (i != -1 && (channels[i].state & WritingState));
    1017 }
    1018 
    1019 bool QHttpNetworkConnectionPrivate::isSocketWaiting(QAbstractSocket *socket) const
    1020 {
    1021     int i = indexOf(socket);
    1022     return (i != -1 && (channels[i].state & WaitingState));
    1023 }
    1024 
    1025 bool QHttpNetworkConnectionPrivate::isSocketReading(QAbstractSocket *socket) const
    1026 {
    1027     int i = indexOf(socket);
    1028     return (i != -1 && (channels[i].state & ReadingState));
    1029 }
    1030 
    1031 
    1032 void QHttpNetworkConnectionPrivate::appendData(QHttpNetworkReply &reply, const QByteArray &fragment, bool compressed)
    1033 {
    1034     QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData;
    1035     ba->append(fragment);
    1036     return;
    1037 }
    1038 
    1039 qint64 QHttpNetworkConnectionPrivate::bytesAvailable(const QHttpNetworkReply &reply, bool compressed) const
    1040 {
    1041     const QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData;
    1042     return ba->size();
    1043 }
    1044 
    1045 qint64 QHttpNetworkConnectionPrivate::read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize, bool compressed)
    1046 {
    1047     QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData;
    1048     if (maxSize == -1 || maxSize >= ba->size()) {
    1049         // read the whole data
    1050         data = *ba;
    1051         ba->clear();
    1052     } else {
    1053         // read only the requested length
    1054         data = ba->mid(0, maxSize);
    1055         ba->remove(0, maxSize);
    1056     }
    1057     return data.size();
    1058 }
    1059 
    1060 void QHttpNetworkConnectionPrivate::eraseData(QHttpNetworkReply *reply)
    1061 {
    1062     reply->d_func()->compressedData.clear();
    1063     reply->d_func()->responseData.clear();
     127
     128    qFatal("Called with unknown socket object.");
     129    return 0;
     130}
     131
     132qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailable(const QHttpNetworkReply &reply) const
     133{
     134    return reply.d_func()->responseData.byteAmount();
     135}
     136
     137qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const
     138{
     139    return reply.d_func()->responseData.sizeNextBlock();
    1064140}
    1065141
     
    1072148    QByteArray value;
    1073149    // check if Content-Length is provided
    1074     QIODevice *data = request.data();
    1075     if (data && request.contentLength() == -1) {
    1076         if (!data->isSequential())
    1077             request.setContentLength(data->size());
    1078         else
    1079             bufferData(messagePair); // ### or do chunked upload
     150    QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
     151    if (uploadByteDevice) {
     152        if (request.contentLength() != -1 && uploadByteDevice->size() != -1) {
     153            // both values known, take the smaller one.
     154            request.setContentLength(qMin(uploadByteDevice->size(), request.contentLength()));
     155        } else if (request.contentLength() == -1 && uploadByteDevice->size() != -1) {
     156            // content length not supplied by user, but the upload device knows it
     157            request.setContentLength(uploadByteDevice->size());
     158        } else if (request.contentLength() != -1 && uploadByteDevice->size() == -1) {
     159            // everything OK, the user supplied us the contentLength
     160        } else if (request.contentLength() == -1 && uploadByteDevice->size() == -1) {
     161            qFatal("QHttpNetworkConnectionPrivate: Neither content-length nor upload device size were given");
     162        }
    1080163    }
    1081164    // set the Connection/Proxy-Connection: Keep-Alive headers
     
    1093176    }
    1094177#endif
    1095     // set the gzip header
     178
     179    // If the request had a accept-encoding set, we better not mess
     180    // with it. If it was not set, we announce that we understand gzip
     181    // and remember this fact in request.d->autoDecompress so that
     182    // we can later decompress the HTTP reply if it has such an
     183    // encoding.
    1096184    value = request.headerField("accept-encoding");
    1097185    if (value.isEmpty()) {
     
    1104192#endif
    1105193    }
     194
     195    // some websites mandate an accept-language header and fail
     196    // if it is not sent. This is a problem with the website and
     197    // not with us, but we work around this by setting
     198    // one always.
     199    value = request.headerField("accept-language");
     200    if (value.isEmpty()) {
     201        QString systemLocale = QLocale::system().name().replace(QChar::fromAscii('_'),QChar::fromAscii('-'));
     202        QString acceptLanguage;
     203        if (systemLocale == QLatin1String("C"))
     204            acceptLanguage = QString::fromAscii("en,*");
     205        else if (systemLocale.startsWith(QLatin1String("en-")))
     206            acceptLanguage = QString::fromAscii("%1,*").arg(systemLocale);
     207        else
     208            acceptLanguage = QString::fromAscii("%1,en,*").arg(systemLocale);
     209        request.setHeaderField("Accept-Language", acceptLanguage.toAscii());
     210    }
     211
    1106212    // set the User Agent
    1107213    value = request.headerField("user-agent");
     
    1125231}
    1126232
    1127 bool QHttpNetworkConnectionPrivate::ensureConnection(QAbstractSocket *socket)
    1128 {
    1129     // make sure that this socket is in a connected state, if not initiate
    1130     // connection to the host.
    1131     if (socket->state() != QAbstractSocket::ConnectedState) {
    1132         // connect to the host if not already connected.
    1133         int index = indexOf(socket);
    1134         channels[index].state = ConnectingState;
    1135         channels[index].pendingEncrypt = encrypt;
    1136 
    1137         // This workaround is needed since we use QAuthenticator for NTLM authentication. The "phase == Done"
    1138         // is the usual criteria for emitting authentication signals. The "phase" is set to "Done" when the
    1139         // last header for Authorization is generated by the QAuthenticator. Basic & Digest logic does not
    1140         // check the "phase" for generating the Authorization header. NTLM authentication is a two stage
    1141         // process & needs the "phase". To make sure the QAuthenticator uses the current username/password
    1142         // the phase is reset to Start.
    1143         QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[index].authenticator);
    1144         if (priv && priv->phase == QAuthenticatorPrivate::Done)
    1145             priv->phase = QAuthenticatorPrivate::Start;
    1146         priv = QAuthenticatorPrivate::getPrivate(channels[index].proxyAuthenticator);
    1147         if (priv && priv->phase == QAuthenticatorPrivate::Done)
    1148             priv->phase = QAuthenticatorPrivate::Start;
    1149 
    1150         QString connectHost = hostName;
    1151         qint16 connectPort = port;
    1152 
    1153 #ifndef QT_NO_NETWORKPROXY
    1154         // HTTPS always use transparent proxy.
    1155         if (networkProxy.type() != QNetworkProxy::NoProxy && !encrypt) {
    1156             connectHost = networkProxy.hostName();
    1157             connectPort = networkProxy.port();
    1158         }
    1159 #endif
    1160         if (encrypt) {
    1161 #ifndef QT_NO_OPENSSL
    1162             QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
    1163             sslSocket->connectToHostEncrypted(connectHost, connectPort);
    1164             if (channels[index].ignoreSSLErrors)
    1165                 sslSocket->ignoreSslErrors();
    1166 #else
    1167             emitReplyError(socket, channels[index].reply, QNetworkReply::ProtocolUnknownError);
    1168 #endif
    1169         } else {
    1170             socket->connectToHost(connectHost, connectPort);
    1171         }
    1172         return false;
    1173     }
    1174     return true;
    1175 }
    1176 
    1177 
    1178 bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket)
    1179 {
    1180     Q_Q(QHttpNetworkConnection);
    1181 
    1182     int i = indexOf(socket);
    1183     switch (channels[i].state) {
    1184     case IdleState: { // write the header
    1185         if (!ensureConnection(socket)) {
    1186             // wait for the connection (and encryption) to be done
    1187             // sendRequest will be called again from either
    1188             // _q_connected or _q_encrypted
    1189             return false;
    1190         }
    1191         channels[i].written = 0; // excluding the header
    1192         channels[i].bytesTotal = 0;
    1193         if (channels[i].reply) {
    1194             channels[i].reply->d_func()->clear();
    1195             channels[i].reply->d_func()->connection = q;
    1196             channels[i].reply->d_func()->autoDecompress = channels[i].request.d->autoDecompress;
    1197         }
    1198         channels[i].state = WritingState;
    1199         channels[i].pendingEncrypt = false;
    1200         // if the url contains authentication parameters, use the new ones
    1201         // both channels will use the new authentication parameters
    1202         if (!channels[i].request.url().userInfo().isEmpty()) {
    1203             QUrl url = channels[i].request.url();
    1204             QAuthenticator &auth = channels[i].authenticator;
    1205             if (url.userName() != auth.user()
    1206                 || (!url.password().isEmpty() && url.password() != auth.password())) {
    1207                 auth.setUser(url.userName());
    1208                 auth.setPassword(url.password());
    1209                 copyCredentials(i, &auth, false);
    1210             }
    1211             // clear the userinfo,  since we use the same request for resending
    1212             // userinfo in url can conflict with the one in the authenticator
    1213             url.setUserInfo(QString());
    1214             channels[i].request.setUrl(url);
    1215         }
    1216         createAuthorization(socket, channels[i].request);
    1217 #ifndef QT_NO_NETWORKPROXY
    1218         QByteArray header = QHttpNetworkRequestPrivate::header(channels[i].request,
    1219             (networkProxy.type() != QNetworkProxy::NoProxy));
    1220 #else
    1221         QByteArray header = QHttpNetworkRequestPrivate::header(channels[i].request,
    1222             false);
    1223 #endif
    1224         socket->write(header);
    1225         QIODevice *data = channels[i].request.d->data;
    1226         QHttpNetworkReply *reply = channels[i].reply;
    1227         if (reply && reply->d_func()->requestDataBuffer.size())
    1228             data = &channels[i].reply->d_func()->requestDataBuffer;
    1229         if (data && (data->isOpen() || data->open(QIODevice::ReadOnly))) {
    1230             if (data->isSequential()) {
    1231                 channels[i].bytesTotal = -1;
    1232                 QObject::connect(data, SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadNoBuffer()));
    1233                 QObject::connect(data, SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadNoBuffer()));
    1234             } else {
    1235                 channels[i].bytesTotal = data->size();
    1236             }
    1237         } else {
    1238             channels[i].state = WaitingState;
    1239             break;
    1240         }
    1241         // write the initial chunk together with the headers
    1242         // fall through
    1243     }
    1244     case WritingState: { // write the data
    1245         QIODevice *data = channels[i].request.d->data;
    1246         if (channels[i].reply->d_func()->requestDataBuffer.size())
    1247             data = &channels[i].reply->d_func()->requestDataBuffer;
    1248         if (!data || channels[i].bytesTotal == channels[i].written) {
    1249             channels[i].state = WaitingState; // now wait for response
    1250             break;
    1251         }
    1252 
    1253         QByteArray chunk;
    1254         chunk.resize(ChunkSize);
    1255         qint64 readSize = data->read(chunk.data(), ChunkSize);
    1256         if (readSize == -1) {
    1257             // source has reached EOF
    1258             channels[i].state = WaitingState; // now wait for response
    1259         } else if (readSize > 0) {
    1260             // source gave us something useful
    1261             channels[i].written += socket->write(chunk.data(), readSize);
    1262             if (channels[i].reply)
    1263                 emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal);
    1264         }
    1265         break;
    1266     }
    1267     case WaitingState:
    1268     case ReadingState:
    1269     case Wait4AuthState:
    1270         // ignore _q_bytesWritten in these states
    1271         // fall through
    1272     default:
    1273         break;
    1274     }
    1275     return true;
    1276 }
    1277 
    1278 bool QHttpNetworkConnectionPrivate::emitSignals(QHttpNetworkReply *reply)
    1279 {
    1280     // for 401 & 407 don't emit the data signals. Content along with these
    1281     // responses are send only if the authentication fails.
    1282     return (reply && reply->d_func()->statusCode != 401 && reply->d_func()->statusCode != 407);
    1283 }
    1284 
    1285 bool QHttpNetworkConnectionPrivate::expectContent(QHttpNetworkReply *reply)
    1286 {
    1287     // check whether we can expect content after the headers (rfc 2616, sec4.4)
    1288     if (!reply)
    1289         return false;
    1290     if ((reply->d_func()->statusCode >= 100 && reply->d_func()->statusCode < 200)
    1291         || reply->d_func()->statusCode == 204 || reply->d_func()->statusCode == 304)
    1292         return false;
    1293     if (reply->d_func()->request.operation() == QHttpNetworkRequest::Head)
    1294         return !emitSignals(reply);
    1295     if (reply->d_func()->contentLength() == 0)
    1296         return false;
    1297     return true;
    1298 }
     233
     234
    1299235
    1300236void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket,
     
    1309245        int i = indexOf(socket);
    1310246        // remove the corrupt data if any
    1311         eraseData(channels[i].reply);
    1312         closeChannel(i);
     247        reply->d_func()->eraseData();
     248        channels[i].close();
    1313249        // send the next request
    1314         QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
    1315     }
    1316 }
    1317 
    1318 #ifndef QT_NO_COMPRESS
    1319 bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete)
    1320 {
    1321     Q_ASSERT(socket);
    1322     Q_ASSERT(reply);
    1323 
    1324     qint64 total = bytesAvailable(*reply, true);
    1325     if (total >= CHUNK || dataComplete) {
    1326         int i = indexOf(socket);
    1327          // uncompress the data
    1328         QByteArray content, inflated;
    1329         read(*reply, content, -1, true);
    1330         int ret = Z_OK;
    1331         if (content.size())
    1332             ret = reply->d_func()->gunzipBodyPartially(content, inflated);
    1333         int retCheck = (dataComplete) ? Z_STREAM_END : Z_OK;
    1334         if (ret >= retCheck) {
    1335             if (inflated.size()) {
    1336                 reply->d_func()->totalProgress += inflated.size();
    1337                 appendData(*reply, inflated, false);
    1338                 if (emitSignals(reply)) {
    1339                     emit reply->readyRead();
    1340                     // make sure that the reply is valid
    1341                     if (channels[i].reply != reply)
    1342                         return true;
    1343                     emit reply->dataReadProgress(reply->d_func()->totalProgress, 0);
    1344                     // make sure that the reply is valid
    1345                     if (channels[i].reply != reply)
    1346                         return true;
    1347 
    1348                 }
    1349             }
    1350         } else {
    1351             emitReplyError(socket, reply, QNetworkReply::ProtocolFailure);
    1352             return false;
    1353         }
    1354     }
    1355     return true;
    1356 }
    1357 #endif
    1358 
    1359 void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply)
    1360 {
    1361     Q_ASSERT(socket);
    1362 
    1363     Q_Q(QHttpNetworkConnection);
    1364     qint64 bytes = 0;
    1365     QAbstractSocket::SocketState state = socket->state();
    1366     int i = indexOf(socket);
    1367 
    1368     // connection might be closed to signal the end of data
    1369     if (state == QAbstractSocket::UnconnectedState) {
    1370         if (!socket->bytesAvailable()) {
    1371             if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
    1372                 reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
    1373                 channels[i].state = IdleState;
    1374                 allDone(socket, reply);
    1375             } else {
    1376                 // try to reconnect/resend before sending an error.
    1377                 if (channels[i].reconnectAttempts-- > 0) {
    1378                     resendCurrentRequest(socket);
    1379                 } else {
    1380                     reply->d_func()->errorString = errorDetail(QNetworkReply::RemoteHostClosedError, socket);
    1381                     emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString);
    1382                     QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
    1383                 }
    1384             }
    1385         }
    1386     }
    1387 
    1388     // read loop for the response
    1389     while (socket->bytesAvailable()) {
    1390         QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState;
    1391         switch (state) {
    1392         case QHttpNetworkReplyPrivate::NothingDoneState:
    1393         case QHttpNetworkReplyPrivate::ReadingStatusState:
    1394             bytes += reply->d_func()->readStatus(socket);
    1395             channels[i].lastStatus = reply->d_func()->statusCode;
    1396             break;
    1397         case QHttpNetworkReplyPrivate::ReadingHeaderState:
    1398             bytes += reply->d_func()->readHeader(socket);
    1399             if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
    1400                 if (reply->d_func()->isGzipped() && reply->d_func()->autoDecompress) {
    1401                     // remove the Content-Length from header
    1402                     reply->d_func()->removeAutoDecompressHeader();
    1403                 } else {
    1404                     reply->d_func()->autoDecompress = false;
    1405                 }
    1406                 if (reply && reply->d_func()->statusCode == 100) {
    1407                     reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState;
    1408                     break; // ignore
    1409                 }
    1410                 if (emitSignals(reply))
    1411                     emit reply->headerChanged();
    1412                 if (!expectContent(reply)) {
    1413                     reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
    1414                     channels[i].state = IdleState;
    1415                     allDone(socket, reply);
    1416                     return;
    1417                 }
    1418             }
    1419             break;
    1420         case QHttpNetworkReplyPrivate::ReadingDataState: {
    1421             QBuffer fragment;
    1422             fragment.open(QIODevice::WriteOnly);
    1423             bytes = reply->d_func()->readBody(socket, &fragment);
    1424             if (bytes) {
    1425                 appendData(*reply, fragment.data(), reply->d_func()->autoDecompress);
    1426                 if (!reply->d_func()->autoDecompress) {
    1427                     reply->d_func()->totalProgress += fragment.size();
    1428                     if (emitSignals(reply)) {
    1429                         emit reply->readyRead();
    1430                         // make sure that the reply is valid
    1431                         if (channels[i].reply != reply)
    1432                             return;
    1433                         emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength);
    1434                         // make sure that the reply is valid
    1435                         if (channels[i].reply != reply)
    1436                             return;
    1437                     }
    1438                 }
    1439 #ifndef QT_NO_COMPRESS
    1440                 else if (!expand(socket, reply, false)) { // expand a chunk if possible
    1441                     return; // ### expand failed
    1442                 }
    1443 #endif
    1444             }
    1445             if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState)
    1446                 break;
    1447             // everything done, fall through
    1448             }
    1449       case QHttpNetworkReplyPrivate::AllDoneState:
    1450             channels[i].state = IdleState;
    1451             allDone(socket, reply);
    1452             break;
    1453         default:
    1454             break;
    1455         }
    1456     }
    1457 }
    1458 
    1459 void QHttpNetworkConnectionPrivate::allDone(QAbstractSocket *socket, QHttpNetworkReply *reply)
    1460 {
    1461 #ifndef QT_NO_COMPRESS
    1462     // expand the whole data.
    1463     if (expectContent(reply) && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd)
    1464         expand(socket, reply, true); // ### if expand returns false, its an error
    1465 #endif
    1466     // while handling 401 & 407, we might reset the status code, so save this.
    1467     bool emitFinished = emitSignals(reply);
    1468     handleStatus(socket, reply);
    1469     // ### at this point there should be no more data on the socket
    1470     // close if server requested
    1471     int i = indexOf(socket);
    1472     if (reply->d_func()->connectionCloseEnabled())
    1473         closeChannel(i);
    1474     // queue the finished signal, this is required since we might send new requests from
    1475     // slot connected to it. The socket will not fire readyRead signal, if we are already
    1476     // in the slot connected to readyRead
    1477     if (emitFinished)
    1478         QMetaObject::invokeMethod(reply, "finished", Qt::QueuedConnection);
    1479     // reset the reconnection attempts after we receive a complete reply.
    1480     // in case of failures, each channel will attempt two reconnects before emitting error.
    1481     channels[i].reconnectAttempts = 2;
    1482 }
    1483 
    1484 void QHttpNetworkConnectionPrivate::handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply)
    1485 {
    1486     Q_ASSERT(socket);
    1487     Q_ASSERT(reply);
    1488 
    1489     Q_Q(QHttpNetworkConnection);
    1490 
    1491     int statusCode = reply->statusCode();
    1492     bool resend = false;
    1493 
    1494     switch (statusCode) {
    1495     case 401:
    1496     case 407:
    1497         handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend);
    1498         if (resend) {
    1499             eraseData(reply);
    1500             sendRequest(socket);
    1501         }
    1502         break;
    1503     default:
    1504250        QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
    1505251    }
     
    1528274
    1529275
     276// handles the authentication for one channel and eventually re-starts the other channels
    1530277bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply,
    1531278                                                                bool isProxy, bool &resend)
     
    1567314            if ((isProxy && pendingProxyAuthSignal) ||(!isProxy && pendingAuthSignal)) {
    1568315                // drop the request
    1569                 eraseData(channels[i].reply);
    1570                 closeChannel(i);
     316                reply->d_func()->eraseData();
     317                channels[i].close();
    1571318                channels[i].lastStatus = 0;
    1572                 channels[i].state =  Wait4AuthState;
     319                channels[i].state =  QHttpNetworkConnectionChannel::Wait4AuthState;
    1573320                return false;
    1574321            }
    1575322            // cannot use this socket until the slot returns
    1576             channels[i].state = WaitingState;
     323            channels[i].state = QHttpNetworkConnectionChannel::WaitingState;
    1577324            socket->blockSignals(true);
    1578325            if (!isProxy) {
     
    1589336            socket->blockSignals(false);
    1590337            // socket free to use
    1591             channels[i].state = IdleState;
     338            channels[i].state = QHttpNetworkConnectionChannel::IdleState;
    1592339            if (priv->phase != QAuthenticatorPrivate::Done) {
    1593340                // send any pending requests
    1594341                copyCredentials(i,  auth, isProxy);
    1595                 QMetaObject::invokeMethod(q, "_q_restartPendingRequest", Qt::QueuedConnection);
     342                QMetaObject::invokeMethod(q, "_q_restartAuthPendingRequests", Qt::QueuedConnection);
    1596343            }
    1597344        }
     
    1601348            emit channels[i].reply->headerChanged();
    1602349            emit channels[i].reply->readyRead();
    1603             emit channels[i].reply->finished();
    1604350            QNetworkReply::NetworkError errorCode =
    1605351                isProxy
     
    1613359            // remove pending request on the other channels
    1614360            for (int j = 0; j < channelCount; ++j) {
    1615                 if (j != i && channels[j].state ==  Wait4AuthState)
    1616                     channels[j].state = IdleState;
     361                if (j != i && channels[j].state ==  QHttpNetworkConnectionChannel::Wait4AuthState)
     362                    channels[j].state = QHttpNetworkConnectionChannel::IdleState;
    1617363            }
    1618364            return true;
     
    1630376
    1631377    int i = indexOf(socket);
     378
    1632379    if (channels[i].authMehtod != QAuthenticatorPrivate::None) {
    1633380        if (!(channels[i].authMehtod == QAuthenticatorPrivate::Ntlm && channels[i].lastStatus != 401)) {
     
    1635382            if (priv && priv->method != QAuthenticatorPrivate::None) {
    1636383                QByteArray response = priv->calculateResponse(request.d->methodName(), request.d->uri(false));
    1637                 request.setHeaderField("authorization", response);
     384                request.setHeaderField("Authorization", response);
    1638385            }
    1639386        }
     
    1644391            if (priv && priv->method != QAuthenticatorPrivate::None) {
    1645392                QByteArray response = priv->calculateResponse(request.d->methodName(), request.d->uri(false));
    1646                 request.setHeaderField("proxy-authorization", response);
     393                request.setHeaderField("Proxy-Authorization", response);
    1647394            }
    1648395        }
     
    1673420}
    1674421
    1675 void QHttpNetworkConnectionPrivate::unqueueRequest(QAbstractSocket *socket)
     422void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair)
     423{
     424    Q_Q(QHttpNetworkConnection);
     425
     426    QHttpNetworkRequest request = pair.first;
     427    switch (request.priority()) {
     428    case QHttpNetworkRequest::HighPriority:
     429        highPriorityQueue.prepend(pair);
     430        break;
     431    case QHttpNetworkRequest::NormalPriority:
     432    case QHttpNetworkRequest::LowPriority:
     433        lowPriorityQueue.prepend(pair);
     434        break;
     435    }
     436    QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
     437}
     438
     439void QHttpNetworkConnectionPrivate::dequeueAndSendRequest(QAbstractSocket *socket)
    1676440{
    1677441    Q_ASSERT(socket);
     
    1680444
    1681445    if (!highPriorityQueue.isEmpty()) {
    1682         for (int j = highPriorityQueue.count() - 1; j >= 0; --j) {
    1683             HttpMessagePair &messagePair = highPriorityQueue[j];
    1684             if (!messagePair.second->d_func()->requestIsPrepared)
    1685                 prepareRequest(messagePair);
    1686             if (!messagePair.second->d_func()->requestIsBuffering) {
    1687                 channels[i].request = messagePair.first;
    1688                 channels[i].reply = messagePair.second;
    1689                 sendRequest(socket);
    1690                 highPriorityQueue.removeAt(j);
    1691                 return;
    1692             }
    1693         }
     446        // remove from queue before sendRequest! else we might pipeline the same request again
     447        HttpMessagePair messagePair = highPriorityQueue.takeLast();
     448        if (!messagePair.second->d_func()->requestIsPrepared)
     449            prepareRequest(messagePair);
     450        channels[i].request = messagePair.first;
     451        channels[i].reply = messagePair.second;
     452        channels[i].sendRequest();
     453        return;
    1694454    }
    1695455
    1696456    if (!lowPriorityQueue.isEmpty()) {
    1697         for (int j = lowPriorityQueue.count() - 1; j >= 0; --j) {
    1698             HttpMessagePair &messagePair = lowPriorityQueue[j];
    1699             if (!messagePair.second->d_func()->requestIsPrepared)
    1700                 prepareRequest(messagePair);
    1701             if (!messagePair.second->d_func()->requestIsBuffering) {
    1702                 channels[i].request = messagePair.first;
    1703                 channels[i].reply = messagePair.second;
    1704                 sendRequest(socket);
    1705                 lowPriorityQueue.removeAt(j);
    1706                 return;
    1707             }
    1708         }
    1709     }
    1710 }
    1711 
    1712 void QHttpNetworkConnectionPrivate::closeChannel(int channel)
    1713 {
    1714     QAbstractSocket *socket = channels[channel].socket;
    1715     socket->blockSignals(true);
    1716     socket->close();
    1717     socket->blockSignals(false);
    1718     channels[channel].state = IdleState;
    1719 }
    1720 
    1721 void QHttpNetworkConnectionPrivate::resendCurrentRequest(QAbstractSocket *socket)
    1722 {
    1723     Q_Q(QHttpNetworkConnection);
    1724     Q_ASSERT(socket);
     457        // remove from queue before sendRequest! else we might pipeline the same request again
     458        HttpMessagePair messagePair = lowPriorityQueue.takeLast();
     459        if (!messagePair.second->d_func()->requestIsPrepared)
     460            prepareRequest(messagePair);
     461        channels[i].request = messagePair.first;
     462        channels[i].reply = messagePair.second;
     463        channels[i].sendRequest();
     464        return;
     465    }
     466}
     467
     468// this is called from _q_startNextRequest and when a request has been sent down a socket from the channel
     469void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket)
     470{
     471    // return fast if there is nothing to pipeline
     472    if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
     473        return;
     474
    1725475    int i = indexOf(socket);
    1726     closeChannel(i);
    1727     channels[i].resendCurrent = true;
    1728     QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
    1729 }
     476
     477    bool highPriorityQueueProcessingDone = false;
     478    bool lowPriorityQueueProcessingDone = false;
     479
     480    while (!highPriorityQueueProcessingDone && !lowPriorityQueueProcessingDone) {
     481        // this loop runs once per request we intend to pipeline in.
     482
     483        if (channels[i].pipeliningSupported != QHttpNetworkConnectionChannel::PipeliningProbablySupported)
     484            return;
     485
     486        // the current request that is in must already support pipelining
     487        if (!channels[i].request.isPipeliningAllowed())
     488            return;
     489
     490        // the current request must be a idempotent (right now we only check GET)
     491        if (channels[i].request.operation() != QHttpNetworkRequest::Get)
     492            return;
     493
     494        // check if socket is connected
     495        if (socket->state() != QAbstractSocket::ConnectedState)
     496            return;
     497
     498        // check for resendCurrent
     499        if (channels[i].resendCurrent)
     500            return;
     501
     502        // we do not like authentication stuff
     503        // ### make sure to be OK with this in later releases
     504        if (!channels[i].authenticator.isNull() || !channels[i].authenticator.user().isEmpty())
     505            return;
     506        if (!channels[i].proxyAuthenticator.isNull() || !channels[i].proxyAuthenticator.user().isEmpty())
     507            return;
     508
     509        // check for pipeline length
     510        if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength)
     511            return;
     512
     513        // must be in ReadingState or WaitingState
     514        if (! (channels[i].state == QHttpNetworkConnectionChannel::WaitingState
     515               || channels[i].state == QHttpNetworkConnectionChannel::ReadingState))
     516            return;
     517
     518        highPriorityQueueProcessingDone = fillPipeline(highPriorityQueue, channels[i]);
     519        // not finished with highPriorityQueue? then loop again
     520        if (!highPriorityQueueProcessingDone)
     521            continue;
     522        // highPriorityQueue was processed, now deal with the lowPriorityQueue
     523        lowPriorityQueueProcessingDone = fillPipeline(lowPriorityQueue, channels[i]);
     524    }
     525}
     526
     527// returns true when the processing of a queue has been done
     528bool QHttpNetworkConnectionPrivate::fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel)
     529{
     530    if (queue.isEmpty())
     531        return true;
     532
     533    for (int i = queue.count() - 1; i >= 0; --i) {
     534        HttpMessagePair messagePair = queue.at(i);
     535        const QHttpNetworkRequest &request = messagePair.first;
     536
     537        // we currently do not support pipelining if HTTP authentication is used
     538        if (!request.url().userInfo().isEmpty())
     539            continue;
     540
     541        // take only GET requests
     542        if (request.operation() != QHttpNetworkRequest::Get)
     543            continue;
     544
     545        if (!request.isPipeliningAllowed())
     546            continue;
     547
     548        // remove it from the queue
     549        queue.takeAt(i);
     550        // we modify the queue we iterate over here, but since we return from the function
     551        // afterwards this is fine.
     552
     553        // actually send it
     554        if (!messagePair.second->d_func()->requestIsPrepared)
     555            prepareRequest(messagePair);
     556        channel.pipelineInto(messagePair);
     557
     558        // return false because we processed something and need to process again
     559        return false;
     560    }
     561
     562    // return true, the queue has been processed and not changed
     563    return true;
     564}
     565
    1730566
    1731567QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket)
     
    1771607}
    1772608
     609// this is called from the destructor of QHttpNetworkReply. It is called when
     610// the reply was finished correctly or when it was aborted.
    1773611void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
    1774612{
    1775613    Q_Q(QHttpNetworkConnection);
    1776614
    1777     // remove the from active list.
     615    // check if the reply is currently being processed or it is pipelined in
    1778616    for (int i = 0; i < channelCount; ++i) {
     617        // is the reply associated the currently processing of this channel?
    1779618        if (channels[i].reply == reply) {
    1780619            channels[i].reply = 0;
    1781             closeChannel(i);
     620
     621            if (!reply->isFinished() && !channels[i].alreadyPipelinedRequests.isEmpty()) {
     622                // the reply had to be prematurely removed, e.g. it was not finished
     623                // therefore we have to requeue the already pipelined requests.
     624                channels[i].requeueCurrentlyPipelinedRequests();
     625            }
     626
     627            // if HTTP mandates we should close
     628            // or the reply is not finished yet, e.g. it was aborted
     629            // we have to close that connection
     630            if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished())
     631                channels[i].close();
     632
    1782633            QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
    1783634            return;
     635        }
     636
     637        // is the reply inside the pipeline of this channel already?
     638        for (int j = 0; j < channels[i].alreadyPipelinedRequests.length(); j++) {
     639            if (channels[i].alreadyPipelinedRequests.at(j).second == reply) {
     640               // Remove that HttpMessagePair
     641               channels[i].alreadyPipelinedRequests.removeAt(j);
     642
     643               channels[i].requeueCurrentlyPipelinedRequests();
     644
     645               // Since some requests had already been pipelined, but we removed
     646               // one and re-queued the others
     647               // we must force a connection close after the request that is
     648               // currently in processing has been finished.
     649               if (channels[i].reply)
     650                   channels[i].reply->d_func()->forceConnectionCloseEnabled = true;
     651
     652               QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
     653               return;
     654            }
    1784655        }
    1785656    }
     
    1809680
    1810681
    1811 //private slots
    1812 void QHttpNetworkConnectionPrivate::_q_readyRead()
    1813 {
    1814     Q_Q(QHttpNetworkConnection);
    1815     QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
    1816     if (!socket)
    1817         return; // ### error
    1818     if (isSocketWaiting(socket) || isSocketReading(socket)) {
    1819         int i = indexOf(socket);
    1820         channels[i].state = ReadingState;
    1821         if (channels[i].reply)
    1822             receiveReply(socket, channels[i].reply);
    1823     }
    1824     // ### error
    1825 }
    1826 
    1827 void QHttpNetworkConnectionPrivate::_q_bytesWritten(qint64 bytes)
    1828 {
    1829     Q_UNUSED(bytes);
    1830     Q_Q(QHttpNetworkConnection);
    1831     QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
    1832     if (!socket)
    1833         return; // ### error
    1834     if (isSocketWriting(socket))
    1835         sendRequest(socket);
    1836     // otherwise we do nothing
    1837 }
    1838 
    1839 void QHttpNetworkConnectionPrivate::_q_disconnected()
    1840 {
    1841     Q_Q(QHttpNetworkConnection);
    1842     QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
    1843     if (!socket)
    1844         return; // ### error
    1845     // read the available data before closing
    1846     int i = indexOf(socket);
    1847     if (isSocketWaiting(socket) || isSocketReading(socket)) {
    1848         channels[i].state = ReadingState;
    1849         if (channels[i].reply)
    1850             receiveReply(socket, channels[i].reply);
    1851     }
    1852     channels[i].state = IdleState;
    1853 }
    1854682
    1855683void QHttpNetworkConnectionPrivate::_q_startNextRequest()
    1856684{
    1857     // send the current request again
    1858     if (channels[0].resendCurrent || channels[1].resendCurrent) {
    1859         int i = channels[0].resendCurrent ? 0:1;
    1860         QAbstractSocket *socket = channels[i].socket;
    1861         channels[i].resendCurrent = false;
    1862         channels[i].state = IdleState;
    1863         if (channels[i].reply)
    1864             sendRequest(socket);
     685    //resend the necessary ones.
     686    for (int i = 0; i < channelCount; ++i) {
     687        if (channels[i].resendCurrent) {
     688            channels[i].resendCurrent = false;
     689            channels[i].state = QHttpNetworkConnectionChannel::IdleState;
     690            if (channels[i].reply)
     691                channels[i].sendRequest();
     692        }
     693    }
     694    QAbstractSocket *socket = 0;
     695    for (int i = 0; i < channelCount; ++i) {
     696        QAbstractSocket *chSocket = channels[i].socket;
     697        // send the request using the idle socket
     698        if (!channels[i].isSocketBusy()) {
     699            socket = chSocket;
     700            break;
     701        }
     702    }
     703
     704    // this socket is free,
     705    if (socket)
     706        dequeueAndSendRequest(socket);
     707
     708    // try to push more into all sockets
     709    // ### FIXME we should move this to the beginning of the function
     710    // as soon as QtWebkit is properly using the pipelining
     711    // (e.g. not for XMLHttpRequest or the first page load)
     712    // ### FIXME we should also divide the requests more even
     713    // on the connected sockets
     714    //tryToFillPipeline(socket);
     715    // return fast if there is nothing to pipeline
     716    if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
    1865717        return;
    1866     }
    1867     // send the request using the idle socket
    1868     QAbstractSocket *socket = channels[0].socket;
    1869     if (isSocketBusy(socket)) {
    1870         socket = (isSocketBusy(channels[1].socket) ? 0 :channels[1].socket);
    1871     }
    1872 
    1873     if (!socket) {
    1874         return; // this will be called after finishing current request.
    1875     }
    1876     unqueueRequest(socket);
    1877 }
    1878 
    1879 void QHttpNetworkConnectionPrivate::_q_restartPendingRequest()
     718    for (int j = 0; j < channelCount; j++)
     719        fillPipeline(channels[j].socket);
     720}
     721
     722void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests()
    1880723{
    1881724    // send the request using the idle socket
    1882725    for (int i = 0 ; i < channelCount; ++i) {
    1883         QAbstractSocket *socket = channels[i].socket;
    1884         if (channels[i].state ==  Wait4AuthState) {
    1885             channels[i].state = IdleState;
     726        if (channels[i].state ==  QHttpNetworkConnectionChannel::Wait4AuthState) {
     727            channels[i].state = QHttpNetworkConnectionChannel::IdleState;
    1886728            if (channels[i].reply)
    1887                 sendRequest(socket);
    1888         }
    1889     }
    1890 }
    1891 
    1892 void QHttpNetworkConnectionPrivate::_q_connected()
    1893 {
    1894     Q_Q(QHttpNetworkConnection);
    1895     QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
    1896     if (!socket)
    1897         return; // ### error
    1898     int i = indexOf(socket);
    1899     // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
    1900     //channels[i].reconnectAttempts = 2;
    1901     if (!channels[i].pendingEncrypt) {
    1902         channels[i].state = IdleState;
    1903         if (channels[i].reply)
    1904             sendRequest(socket);
    1905         else
    1906             closeChannel(i);
    1907     }
    1908 }
    1909 
    1910 
    1911 void QHttpNetworkConnectionPrivate::_q_error(QAbstractSocket::SocketError socketError)
    1912 {
    1913     Q_Q(QHttpNetworkConnection);
    1914     QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
    1915     if (!socket)
    1916         return;
    1917     bool send2Reply = false;
    1918     int i = indexOf(socket);
    1919     QNetworkReply::NetworkError errorCode = QNetworkReply::UnknownNetworkError;
    1920 
    1921     switch (socketError) {
    1922     case QAbstractSocket::HostNotFoundError:
    1923         errorCode = QNetworkReply::HostNotFoundError;
    1924         break;
    1925     case QAbstractSocket::ConnectionRefusedError:
    1926         errorCode = QNetworkReply::ConnectionRefusedError;
    1927         break;
    1928     case QAbstractSocket::RemoteHostClosedError:
    1929         // try to reconnect/resend before sending an error.
    1930         // while "Reading" the _q_disconnected() will handle this.
    1931         if (channels[i].state != IdleState && channels[i].state != ReadingState) {
    1932             if (channels[i].reconnectAttempts-- > 0) {
    1933                 resendCurrentRequest(socket);
    1934                 return;
    1935             } else {
    1936                 send2Reply = true;
    1937                 errorCode = QNetworkReply::RemoteHostClosedError;
    1938             }
    1939         } else {
    1940             return;
    1941         }
    1942         break;
    1943     case QAbstractSocket::SocketTimeoutError:
    1944         // try to reconnect/resend before sending an error.
    1945         if (channels[i].state == WritingState &&  (channels[i].reconnectAttempts-- > 0)) {
    1946             resendCurrentRequest(socket);
    1947             return;
    1948         }
    1949         send2Reply = true;
    1950         errorCode = QNetworkReply::TimeoutError;
    1951         break;
    1952     case QAbstractSocket::ProxyAuthenticationRequiredError:
    1953         errorCode = QNetworkReply::ProxyAuthenticationRequiredError;
    1954         break;
    1955     case QAbstractSocket::SslHandshakeFailedError:
    1956         errorCode = QNetworkReply::SslHandshakeFailedError;
    1957         break;
    1958     default:
    1959         // all other errors are treated as NetworkError
    1960         errorCode = QNetworkReply::UnknownNetworkError;
    1961         break;
    1962     }
    1963     QPointer<QObject> that = q;
    1964     QString errorString = errorDetail(errorCode, socket);
    1965     if (send2Reply) {
    1966         if (channels[i].reply) {
    1967             channels[i].reply->d_func()->errorString = errorString;
    1968             // this error matters only to this reply
    1969             emit channels[i].reply->finishedWithError(errorCode, errorString);
    1970         }
    1971         // send the next request
    1972         QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection);
    1973     } else {
    1974         // the failure affects all requests.
    1975         emit q->error(errorCode, errorString);
    1976     }
    1977     if (that) //signals make enter the event loop
    1978         closeChannel(i);
    1979 }
    1980 
    1981 #ifndef QT_NO_NETWORKPROXY
    1982 void QHttpNetworkConnectionPrivate::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth)
    1983 {
    1984     Q_Q(QHttpNetworkConnection);
    1985     emit q->proxyAuthenticationRequired(proxy, auth, q);
    1986 }
    1987 #endif
    1988 
    1989 void QHttpNetworkConnectionPrivate::_q_dataReadyReadNoBuffer()
    1990 {
    1991     Q_Q(QHttpNetworkConnection);
    1992     // data emitted either readyRead()
    1993     // find out which channel it is for
    1994     QIODevice *sender = qobject_cast<QIODevice *>(q->sender());
    1995 
    1996     // won't match anything if the qobject_cast above failed
    1997     for (int i = 0; i < channelCount; ++i) {
    1998         if (sender == channels[i].request.data()) {
    1999             sendRequest(channels[i].socket);
    2000             break;
    2001         }
    2002     }
    2003 }
    2004 
    2005 void QHttpNetworkConnectionPrivate::_q_dataReadyReadBuffer()
    2006 {
    2007     Q_Q(QHttpNetworkConnection);
    2008     QIODevice *sender = qobject_cast<QIODevice *>(q->sender());
    2009     HttpMessagePair *thePair = 0;
    2010     for (int i = 0; !thePair && i < lowPriorityQueue.size(); ++i)
    2011         if (lowPriorityQueue.at(i).first.data() == sender)
    2012             thePair = &lowPriorityQueue[i];
    2013 
    2014     for (int i = 0; !thePair && i < highPriorityQueue.size(); ++i)
    2015         if (highPriorityQueue.at(i).first.data() == sender)
    2016             thePair = &highPriorityQueue[i];
    2017 
    2018     if (thePair) {
    2019         bufferData(*thePair);
    2020 
    2021         // are we finished buffering?
    2022         if (!thePair->second->d_func()->requestIsBuffering)
    2023             _q_startNextRequest();
    2024     }
    2025 }
    2026 
    2027 void QHttpNetworkConnectionPrivate::bufferData(HttpMessagePair &messagePair)
    2028 {
    2029     Q_Q(QHttpNetworkConnection);
    2030     QHttpNetworkRequest &request = messagePair.first;
    2031     QHttpNetworkReply *reply = messagePair.second;
    2032     Q_ASSERT(request.data());
    2033     if (!reply->d_func()->requestIsBuffering) { // first time
    2034         QObject::connect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer()));
    2035         QObject::connect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer()));
    2036         reply->d_func()->requestIsBuffering = true;
    2037         reply->d_func()->requestDataBuffer.open(QIODevice::ReadWrite);
    2038     }
    2039 
    2040     // always try to read at least one byte
    2041     // ### FIXME! use a QRingBuffer
    2042     qint64 bytesToRead = qMax<qint64>(1, request.data()->bytesAvailable());
    2043     QByteArray newData;
    2044     newData.resize(bytesToRead);
    2045     qint64 bytesActuallyRead = request.data()->read(newData.data(), bytesToRead);
    2046 
    2047     if (bytesActuallyRead > 0) {
    2048         // we read something
    2049         newData.chop(bytesToRead - bytesActuallyRead);
    2050         reply->d_func()->requestDataBuffer.write(newData);
    2051     } else if (bytesActuallyRead == -1) { // last time
    2052         QObject::disconnect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer()));
    2053         QObject::disconnect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer()));
    2054 
    2055         request.setContentLength(reply->d_func()->requestDataBuffer.size());
    2056         reply->d_func()->requestDataBuffer.seek(0);
    2057         reply->d_func()->requestIsBuffering = false;
    2058     }
    2059 }
    2060 
    2061 // QHttpNetworkConnection
     729                channels[i].sendRequest();
     730        }
     731    }
     732}
     733
    2062734
    2063735QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent)
    2064736    : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent)
     737{
     738    Q_D(QHttpNetworkConnection);
     739    d->init();
     740}
     741
     742QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt, QObject *parent)
     743     : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt)), parent)
    2065744{
    2066745    Q_D(QHttpNetworkConnection);
     
    2151830#endif
    2152831
    2153 // QHttpNetworkRequest
    2154 
    2155 QHttpNetworkRequest::QHttpNetworkRequest(const QUrl &url, Operation operation, Priority priority)
    2156     : d(new QHttpNetworkRequestPrivate(operation, priority, url))
    2157 {
    2158 }
    2159 
    2160 QHttpNetworkRequest::QHttpNetworkRequest(const QHttpNetworkRequest &other)
    2161     : QHttpNetworkHeader(other), d(other.d)
    2162 {
    2163 }
    2164 
    2165 QHttpNetworkRequest::~QHttpNetworkRequest()
    2166 {
    2167 }
    2168 
    2169 QUrl QHttpNetworkRequest::url() const
    2170 {
    2171     return d->url;
    2172 }
    2173 void QHttpNetworkRequest::setUrl(const QUrl &url)
    2174 {
    2175     d->url = url;
    2176 }
    2177 
    2178 qint64 QHttpNetworkRequest::contentLength() const
    2179 {
    2180     return d->contentLength();
    2181 }
    2182 
    2183 void QHttpNetworkRequest::setContentLength(qint64 length)
    2184 {
    2185     d->setContentLength(length);
    2186 }
    2187 
    2188 QList<QPair<QByteArray, QByteArray> > QHttpNetworkRequest::header() const
    2189 {
    2190     return d->fields;
    2191 }
    2192 
    2193 QByteArray QHttpNetworkRequest::headerField(const QByteArray &name, const QByteArray &defaultValue) const
    2194 {
    2195     return d->headerField(name, defaultValue);
    2196 }
    2197 
    2198 void QHttpNetworkRequest::setHeaderField(const QByteArray &name, const QByteArray &data)
    2199 {
    2200     d->setHeaderField(name, data);
    2201 }
    2202 
    2203 QHttpNetworkRequest &QHttpNetworkRequest::operator=(const QHttpNetworkRequest &other)
    2204 {
    2205     d = other.d;
    2206     return *this;
    2207 }
    2208 
    2209 bool QHttpNetworkRequest::operator==(const QHttpNetworkRequest &other) const
    2210 {
    2211     return d->operator==(*other.d);
    2212 }
    2213 
    2214 QHttpNetworkRequest::Operation QHttpNetworkRequest::operation() const
    2215 {
    2216     return d->operation;
    2217 }
    2218 
    2219 void QHttpNetworkRequest::setOperation(Operation operation)
    2220 {
    2221     d->operation = operation;
    2222 }
    2223 
    2224 QHttpNetworkRequest::Priority QHttpNetworkRequest::priority() const
    2225 {
    2226     return d->priority;
    2227 }
    2228 
    2229 void QHttpNetworkRequest::setPriority(Priority priority)
    2230 {
    2231     d->priority = priority;
    2232 }
    2233 
    2234 QIODevice *QHttpNetworkRequest::data() const
    2235 {
    2236     return d->data;
    2237 }
    2238 
    2239 void QHttpNetworkRequest::setData(QIODevice *data)
    2240 {
    2241     d->data = data;
    2242 }
    2243 
    2244 int QHttpNetworkRequest::majorVersion() const
    2245 {
    2246     return 1;
    2247 }
    2248 
    2249 int QHttpNetworkRequest::minorVersion() const
    2250 {
    2251     return 1;
    2252 }
    2253 
    2254 // QHttpNetworkReply
    2255 
    2256 QHttpNetworkReply::QHttpNetworkReply(const QUrl &url, QObject *parent)
    2257     : QObject(*new QHttpNetworkReplyPrivate(url), parent)
    2258 {
    2259 }
    2260 
    2261 QHttpNetworkReply::~QHttpNetworkReply()
    2262 {
    2263     Q_D(QHttpNetworkReply);
    2264     if (d->connection) {
    2265         d->connection->d_func()->removeReply(this);
    2266     }
    2267 }
    2268 
    2269 QUrl QHttpNetworkReply::url() const
    2270 {
    2271     return d_func()->url;
    2272 }
    2273 void QHttpNetworkReply::setUrl(const QUrl &url)
    2274 {
    2275     Q_D(QHttpNetworkReply);
    2276     d->url = url;
    2277 }
    2278 
    2279 qint64 QHttpNetworkReply::contentLength() const
    2280 {
    2281     return d_func()->contentLength();
    2282 }
    2283 
    2284 void QHttpNetworkReply::setContentLength(qint64 length)
    2285 {
    2286     Q_D(QHttpNetworkReply);
    2287     d->setContentLength(length);
    2288 }
    2289 
    2290 QList<QPair<QByteArray, QByteArray> > QHttpNetworkReply::header() const
    2291 {
    2292     return d_func()->fields;
    2293 }
    2294 
    2295 QByteArray QHttpNetworkReply::headerField(const QByteArray &name, const QByteArray &defaultValue) const
    2296 {
    2297     return d_func()->headerField(name, defaultValue);
    2298 }
    2299 
    2300 void QHttpNetworkReply::setHeaderField(const QByteArray &name, const QByteArray &data)
    2301 {
    2302     Q_D(QHttpNetworkReply);
    2303     d->setHeaderField(name, data);
    2304 }
    2305 
    2306 void QHttpNetworkReply::parseHeader(const QByteArray &header)
    2307 {
    2308     Q_D(QHttpNetworkReply);
    2309     d->parseHeader(header);
    2310 }
    2311 
    2312 QHttpNetworkRequest QHttpNetworkReply::request() const
    2313 {
    2314     return d_func()->request;
    2315 }
    2316 
    2317 void QHttpNetworkReply::setRequest(const QHttpNetworkRequest &request)
    2318 {
    2319     Q_D(QHttpNetworkReply);
    2320     d->request = request;
    2321 }
    2322 
    2323 int QHttpNetworkReply::statusCode() const
    2324 {
    2325     return d_func()->statusCode;
    2326 }
    2327 
    2328 void QHttpNetworkReply::setStatusCode(int code)
    2329 {
    2330     Q_D(QHttpNetworkReply);
    2331     d->statusCode = code;
    2332 }
    2333 
    2334 QString QHttpNetworkReply::errorString() const
    2335 {
    2336     return d_func()->errorString;
    2337 }
    2338 
    2339 QString QHttpNetworkReply::reasonPhrase() const
    2340 {
    2341     return d_func()->reasonPhrase;
    2342 }
    2343 
    2344 void QHttpNetworkReply::setErrorString(const QString &error)
    2345 {
    2346     Q_D(QHttpNetworkReply);
    2347     d->errorString = error;
    2348 }
    2349 
    2350 int QHttpNetworkReply::majorVersion() const
    2351 {
    2352     return d_func()->majorVersion;
    2353 }
    2354 
    2355 int QHttpNetworkReply::minorVersion() const
    2356 {
    2357     return d_func()->minorVersion;
    2358 }
    2359 
    2360 qint64 QHttpNetworkReply::bytesAvailable() const
    2361 {
    2362     Q_D(const QHttpNetworkReply);
    2363     if (d->connection)
    2364         return d->connection->d_func()->bytesAvailable(*this);
    2365     else
    2366         return -1;
    2367 }
    2368 
    2369 QByteArray QHttpNetworkReply::read(qint64 maxSize)
    2370 {
    2371     Q_D(QHttpNetworkReply);
    2372     QByteArray data;
    2373     if (d->connection)
    2374         d->connection->d_func()->read(*this, data, maxSize, false);
    2375     return data;
    2376 }
    2377 
    2378 bool QHttpNetworkReply::isFinished() const
    2379 {
    2380     return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState;
    2381 }
    2382832
    2383833// SSL support below
    2384834#ifndef QT_NO_OPENSSL
    2385 void QHttpNetworkConnectionPrivate::_q_encrypted()
    2386 {
    2387     Q_Q(QHttpNetworkConnection);
    2388     QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
    2389     if (!socket)
    2390         return; // ### error
    2391     channels[indexOf(socket)].state = IdleState;
    2392     sendRequest(socket);
    2393 }
    2394 
    2395 void QHttpNetworkConnectionPrivate::_q_sslErrors(const QList<QSslError> &errors)
    2396 {
    2397     Q_Q(QHttpNetworkConnection);
    2398     QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
    2399     if (!socket)
    2400         return;
    2401     //QNetworkReply::NetworkError errorCode = QNetworkReply::ProtocolFailure;
    2402     emit q->sslErrors(errors);
    2403 }
    2404 
    2405835QSslConfiguration QHttpNetworkConnectionPrivate::sslConfiguration(const QHttpNetworkReply &reply) const
    2406836{
     837    if (!encrypt)
     838        return QSslConfiguration();
     839
    2407840    for (int i = 0; i < channelCount; ++i)
    2408841        if (channels[i].reply == &reply)
     
    2414847{
    2415848    Q_D(QHttpNetworkConnection);
     849    if (!d->encrypt)
     850        return;
     851
    2416852    // set the config on all channels
    2417853    for (int i = 0; i < d->channelCount; ++i)
     
    2422858{
    2423859    Q_D(QHttpNetworkConnection);
     860    if (!d->encrypt)
     861        return;
     862
    2424863    if (channel == -1) { // ignore for all channels
    2425864        for (int i = 0; i < d->channelCount; ++i) {
    2426865            static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors();
    2427             d->channels[i].ignoreSSLErrors = true;
     866            d->channels[i].ignoreAllSslErrors = true;
    2428867        }
    2429868
    2430869    } else {
    2431870        static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors();
    2432         d->channels[channel].ignoreSSLErrors = true;
    2433     }
    2434 }
    2435 
    2436 QSslConfiguration QHttpNetworkReply::sslConfiguration() const
    2437 {
    2438     Q_D(const QHttpNetworkReply);
    2439     if (d->connection)
    2440         return d->connection->d_func()->sslConfiguration(*this);
    2441     return QSslConfiguration();
    2442 }
    2443 
    2444 void QHttpNetworkReply::setSslConfiguration(const QSslConfiguration &config)
    2445 {
    2446     Q_D(QHttpNetworkReply);
    2447     if (d->connection)
    2448         d->connection->setSslConfiguration(config);
    2449 }
    2450 
    2451 void QHttpNetworkReply::ignoreSslErrors()
    2452 {
    2453     Q_D(QHttpNetworkReply);
    2454     if (d->connection)
    2455         d->connection->ignoreSslErrors();
    2456 }
     871        d->channels[channel].ignoreAllSslErrors = true;
     872    }
     873}
     874
     875void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int channel)
     876{
     877    Q_D(QHttpNetworkConnection);
     878    if (!d->encrypt)
     879        return;
     880
     881    if (channel == -1) { // ignore for all channels
     882        for (int i = 0; i < d->channelCount; ++i) {
     883            static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors(errors);
     884            d->channels[i].ignoreSslErrorsList = errors;
     885        }
     886
     887    } else {
     888        static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors(errors);
     889        d->channels[channel].ignoreSslErrorsList = errors;
     890    }
     891}
     892
    2457893#endif //QT_NO_OPENSSL
    2458894
     895#ifndef QT_NO_NETWORKPROXY
     896// only called from QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired, not
     897// from QHttpNetworkConnectionChannel::handleAuthenticationChallenge
     898// e.g. it is for SOCKS proxies which require authentication.
     899void QHttpNetworkConnectionPrivate::emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator* auth)
     900{
     901    Q_Q(QHttpNetworkConnection);
     902    emit q->proxyAuthenticationRequired(proxy, auth, q);
     903    int i = indexOf(chan->socket);
     904    copyCredentials(i, auth, true);
     905}
     906#endif
     907
    2459908
    2460909QT_END_NAMESPACE
  • trunk/src/network/access/qhttpnetworkconnection_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5656#include <QtNetwork/qnetworkreply.h>
    5757#include <QtNetwork/qabstractsocket.h>
     58
     59#include <private/qobject_p.h>
     60#include <qauthenticator.h>
     61#include <qnetworkproxy.h>
     62#include <qbuffer.h>
     63
     64#include <private/qhttpnetworkheader_p.h>
     65#include <private/qhttpnetworkrequest_p.h>
     66#include <private/qhttpnetworkreply_p.h>
     67
     68#include <private/qhttpnetworkconnectionchannel_p.h>
    5869
    5970#ifndef QT_NO_HTTP
     
    7081class QHttpNetworkRequest;
    7182class QHttpNetworkReply;
     83class QByteArray;
    7284
    7385class QHttpNetworkConnectionPrivate;
     
    7890
    7991    QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0);
     92    QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0);
    8093    ~QHttpNetworkConnection();
    8194
     
    107120    void setSslConfiguration(const QSslConfiguration &config);
    108121    void ignoreSslErrors(int channel = -1);
     122    void ignoreSslErrors(const QList<QSslError> &errors, int channel = -1);
    109123
    110124Q_SIGNALS:
     
    126140    Q_DISABLE_COPY(QHttpNetworkConnection)
    127141    friend class QHttpNetworkReply;
    128 
    129     Q_PRIVATE_SLOT(d_func(), void _q_bytesWritten(qint64))
    130     Q_PRIVATE_SLOT(d_func(), void _q_readyRead())
    131     Q_PRIVATE_SLOT(d_func(), void _q_disconnected())
     142    friend class QHttpNetworkConnectionChannel;
     143
    132144    Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
    133     Q_PRIVATE_SLOT(d_func(), void _q_restartPendingRequest())
    134     Q_PRIVATE_SLOT(d_func(), void _q_connected())
    135     Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError))
     145    Q_PRIVATE_SLOT(d_func(), void _q_restartAuthPendingRequests())
     146};
     147
     148
     149// private classes
     150typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
     151
     152
     153class QHttpNetworkConnectionPrivate : public QObjectPrivate
     154{
     155    Q_DECLARE_PUBLIC(QHttpNetworkConnection)
     156public:
     157    static const int defaultChannelCount;
     158    static const int defaultPipelineLength;
     159
     160    QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt);
     161    QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt);
     162    ~QHttpNetworkConnectionPrivate();
     163    void init();
     164
     165    enum { ChunkSize = 4096 };
     166
     167    int indexOf(QAbstractSocket *socket) const;
     168
     169    QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request);
     170    void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke
     171    void dequeueAndSendRequest(QAbstractSocket *socket);
     172    void prepareRequest(HttpMessagePair &request);
     173
     174    void fillPipeline(QAbstractSocket *socket);
     175    bool fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel);
     176
     177    void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy);
     178
     179    // private slots
     180    void _q_startNextRequest(); // send the next request from the queue
     181    void _q_restartAuthPendingRequests(); // send the currently blocked request
     182
     183    void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
     184
     185    QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket);
     186
     187#ifndef QT_NO_COMPRESS
     188    bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete);
     189#endif
     190    void removeReply(QHttpNetworkReply *reply);
     191
     192    QString hostName;
     193    quint16 port;
     194    bool encrypt;
     195
     196    const int channelCount;
     197    QHttpNetworkConnectionChannel *channels; // parallel connections to the server
     198
     199    bool pendingAuthSignal; // there is an incomplete authentication signal
     200    bool pendingProxyAuthSignal; // there is an incomplete proxy authentication signal
     201
     202    qint64 uncompressedBytesAvailable(const QHttpNetworkReply &reply) const;
     203    qint64 uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const;
     204
     205
     206    void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode);
     207    bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend);
     208
     209
     210#ifndef QT_NO_OPENSSL
     211    QSslConfiguration sslConfiguration(const QHttpNetworkReply &reply) const;
     212#endif
     213
    136214#ifndef QT_NO_NETWORKPROXY
    137     Q_PRIVATE_SLOT(d_func(), void _q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*))
    138 #endif
    139     Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadBuffer())
    140     Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadNoBuffer())
    141 
    142 #ifndef QT_NO_OPENSSL
    143     Q_PRIVATE_SLOT(d_func(), void _q_encrypted())
    144     Q_PRIVATE_SLOT(d_func(), void _q_sslErrors(const QList<QSslError>&))
    145 #endif
     215    QNetworkProxy networkProxy;
     216    void emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator* auth);
     217#endif
     218
     219    //The request queues
     220    QList<HttpMessagePair> highPriorityQueue;
     221    QList<HttpMessagePair> lowPriorityQueue;
     222
     223    friend class QHttpNetworkConnectionChannel;
    146224};
    147225
    148 class Q_AUTOTEST_EXPORT QHttpNetworkHeader
    149 {
    150 public:
    151     virtual ~QHttpNetworkHeader() {};
    152     virtual QUrl url() const = 0;
    153     virtual void setUrl(const QUrl &url) = 0;
    154 
    155     virtual int majorVersion() const = 0;
    156     virtual int minorVersion() const = 0;
    157 
    158     virtual qint64 contentLength() const = 0;
    159     virtual void setContentLength(qint64 length) = 0;
    160 
    161     virtual QList<QPair<QByteArray, QByteArray> > header() const = 0;
    162     virtual QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const = 0;
    163     virtual void setHeaderField(const QByteArray &name, const QByteArray &data) = 0;
    164 };
    165 
    166 class QHttpNetworkRequestPrivate;
    167 class Q_AUTOTEST_EXPORT QHttpNetworkRequest: public QHttpNetworkHeader
    168 {
    169 public:
    170     enum Operation {
    171         Options,
    172         Get,
    173         Head,
    174         Post,
    175         Put,
    176         Delete,
    177         Trace,
    178         Connect
    179     };
    180 
    181     enum Priority {
    182         HighPriority,
    183         NormalPriority,
    184         LowPriority
    185     };
    186 
    187     QHttpNetworkRequest(const QUrl &url = QUrl(), Operation operation = Get, Priority priority = NormalPriority);
    188     QHttpNetworkRequest(const QHttpNetworkRequest &other);
    189     virtual ~QHttpNetworkRequest();
    190     QHttpNetworkRequest &operator=(const QHttpNetworkRequest &other);
    191     bool operator==(const QHttpNetworkRequest &other) const;
    192 
    193     QUrl url() const;
    194     void setUrl(const QUrl &url);
    195 
    196     int majorVersion() const;
    197     int minorVersion() const;
    198 
    199     qint64 contentLength() const;
    200     void setContentLength(qint64 length);
    201 
    202     QList<QPair<QByteArray, QByteArray> > header() const;
    203     QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const;
    204     void setHeaderField(const QByteArray &name, const QByteArray &data);
    205 
    206     Operation operation() const;
    207     void setOperation(Operation operation);
    208 
    209     Priority priority() const;
    210     void setPriority(Priority priority);
    211 
    212     QIODevice *data() const;
    213     void setData(QIODevice *data);
    214 
    215 private:
    216     QSharedDataPointer<QHttpNetworkRequestPrivate> d;
    217     friend class QHttpNetworkRequestPrivate;
    218     friend class QHttpNetworkConnectionPrivate;
    219 };
    220 
    221 class QHttpNetworkReplyPrivate;
    222 class Q_AUTOTEST_EXPORT QHttpNetworkReply : public QObject, public QHttpNetworkHeader
    223 {
    224     Q_OBJECT
    225 public:
    226 
    227     explicit QHttpNetworkReply(const QUrl &url = QUrl(), QObject *parent = 0);
    228     virtual ~QHttpNetworkReply();
    229 
    230     QUrl url() const;
    231     void setUrl(const QUrl &url);
    232 
    233     int majorVersion() const;
    234     int minorVersion() const;
    235 
    236     qint64 contentLength() const;
    237     void setContentLength(qint64 length);
    238 
    239     QList<QPair<QByteArray, QByteArray> > header() const;
    240     QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const;
    241     void setHeaderField(const QByteArray &name, const QByteArray &data);
    242     void parseHeader(const QByteArray &header); // mainly for testing
    243 
    244     QHttpNetworkRequest request() const;
    245     void setRequest(const QHttpNetworkRequest &request);
    246 
    247     int statusCode() const;
    248     void setStatusCode(int code);
    249 
    250     QString errorString() const;
    251     void setErrorString(const QString &error);
    252 
    253     QString reasonPhrase() const;
    254 
    255     qint64 bytesAvailable() const;
    256     QByteArray read(qint64 maxSize = -1);
    257 
    258     bool isFinished() const;
    259 
    260 #ifndef QT_NO_OPENSSL
    261     QSslConfiguration sslConfiguration() const;
    262     void setSslConfiguration(const QSslConfiguration &config);
    263     void ignoreSslErrors();
    264 
    265 Q_SIGNALS:
    266     void sslErrors(const QList<QSslError> &errors);
    267 #endif
    268 
    269 Q_SIGNALS:
    270     void readyRead();
    271     void finished();
    272     void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString());
    273     void headerChanged();
    274     void dataReadProgress(int done, int total);
    275     void dataSendProgress(int done, int total);
    276 
    277 private:
    278     Q_DECLARE_PRIVATE(QHttpNetworkReply)
    279     friend class QHttpNetworkConnection;
    280     friend class QHttpNetworkConnectionPrivate;
    281 };
     226
    282227
    283228QT_END_NAMESPACE
    284229
    285 Q_DECLARE_METATYPE(QHttpNetworkRequest)
    286 //Q_DECLARE_METATYPE(QHttpNetworkReply)
    287 
    288230#endif // QT_NO_HTTP
    289231
  • trunk/src/network/access/qnetworkaccessbackend.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5151#include "qabstractnetworkcache.h"
    5252
     53#include "private/qnoncontiguousbytedevice_p.h"
     54
    5355QT_BEGIN_NAMESPACE
    5456
     
    9193    if (mode == QNetworkRequest::AlwaysCache
    9294        && (op == QNetworkAccessManager::GetOperation
    93         || op == QNetworkAccessManager::HeadOperation))
    94         return new QNetworkAccessCacheBackend;
     95        || op == QNetworkAccessManager::HeadOperation)) {
     96        QNetworkAccessBackend *backend = new QNetworkAccessCacheBackend;
     97        backend->manager = this;
     98        return backend;
     99    }
    95100
    96101    if (!factoryDataShutdown) {
     
    110115}
    111116
     117QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice()
     118{
     119    QNonContiguousByteDevice* device = 0;
     120
     121    if (reply->outgoingDataBuffer)
     122        device = QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer);
     123    else
     124        device = QNonContiguousByteDeviceFactory::create(reply->outgoingData);
     125
     126    bool bufferDisallowed =
     127            reply->request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
     128                          QVariant(false)) == QVariant(true);
     129    if (bufferDisallowed)
     130        device->disableReset();
     131
     132    // make sure we delete this later
     133    device->setParent(this);
     134
     135    connect(device, SIGNAL(readProgress(qint64,qint64)), this, SLOT(emitReplyUploadProgress(qint64,qint64)));
     136
     137    return device;
     138}
     139
     140// need to have this function since the reply is a private member variable
     141// and the special backends need to access this.
     142void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal)
     143{
     144    if (reply->isFinished())
     145        return;
     146    reply->emitUploadProgress(bytesSent, bytesTotal);
     147}
     148
    112149QNetworkAccessBackend::QNetworkAccessBackend()
     150    : manager(0)
     151    , reply(0)
    113152{
    114153}
     
    118157}
    119158
    120 void QNetworkAccessBackend::upstreamReadyRead()
    121 {
    122     // do nothing
    123 }
    124 
    125159void QNetworkAccessBackend::downstreamReadyWrite()
    126160{
     
    135169void QNetworkAccessBackend::ignoreSslErrors()
    136170{
     171    // do nothing
     172}
     173
     174void QNetworkAccessBackend::ignoreSslErrors(const QList<QSslError> &errors)
     175{
     176    Q_UNUSED(errors);
    137177    // do nothing
    138178}
     
    172212QAbstractNetworkCache *QNetworkAccessBackend::networkCache() const
    173213{
    174     return reply->networkCache; // should be the same as manager->networkCache
     214    if (!manager)
     215        return 0;
     216    return manager->networkCache;
    175217}
    176218
     
    185227}
    186228
    187 qint64 QNetworkAccessBackend::upstreamBytesAvailable() const
    188 {
    189     return reply->writeBuffer.size();
    190 }
    191 
    192 void QNetworkAccessBackend::upstreamBytesConsumed(qint64 count)
    193 {
    194     // remove count bytes from the write buffer
    195     reply->consume(count);
    196 }
    197 
    198 QByteArray QNetworkAccessBackend::readUpstream()
    199 {
    200     // ### this is expensive. Consider making QRingBuffer::peekAll keep the buffer it returns
    201     return reply->writeBuffer.peek(upstreamBytesAvailable());
    202 }
    203 
    204229qint64 QNetworkAccessBackend::nextDownstreamBlockSize() const
    205230{
     
    207232}
    208233
    209 qint64 QNetworkAccessBackend::downstreamBytesToConsume() const
    210 {
    211     return reply->writeBuffer.size();
    212 }
    213 
    214 void QNetworkAccessBackend::writeDownstreamData(const QByteArray &data)
    215 {
    216     reply->feed(data);
     234void QNetworkAccessBackend::writeDownstreamData(QByteDataBuffer &list)
     235{
     236    reply->appendDownstreamData(list);
    217237}
    218238
    219239void QNetworkAccessBackend::writeDownstreamData(QIODevice *data)
    220240{
    221     reply->feed(data);
     241    reply->appendDownstreamData(data);
    222242}
    223243
  • trunk/src/network/access/qnetworkaccessbackend_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7171class QAbstractNetworkCache;
    7272class QNetworkCacheMetaData;
     73class QNetworkAccessBackendUploadIODevice;
     74class QNonContiguousByteDevice;
    7375
    7476// Should support direct file upload from disk or download to disk.
     
    8789    //
    8890    // - Upstream:
    89     //   Upstream is data that is being written into this connection,
    90     //   from the user. Upstream operates in a "pull" mechanism: the
    91     //   connection will be notified that there is more data available
    92     //   by a call to "upstreamReadyRead". The number of bytes
    93     //   available is given by upstreamBytesAvailable(). A call to
    94     //   readUpstream() always yields the entire upstream buffer. When
    95     //   the connection has processed a certain amount of bytes from
    96     //   that buffer, it should call upstreamBytesConsumed().
     91    //   The upstream uses a QNonContiguousByteDevice provided
     92    //   by the backend. This device emits the usual readyRead()
     93    //   signal when the backend has data available for the connection
     94    //   to write. The different backends can listen on this signal
     95    //   and then pull upload data from the QNonContiguousByteDevice and
     96    //   deal with it.
     97    //
    9798    //
    9899    // - Downstream:
     
    112113    virtual void open() = 0;
    113114    virtual void closeDownstreamChannel() = 0;
    114     virtual void closeUpstreamChannel() = 0;
    115115    virtual bool waitForDownstreamReadyRead(int msecs) = 0;
    116     virtual bool waitForUpstreamBytesWritten(int msecs) = 0;
    117116
    118117    // slot-like:
    119     virtual void upstreamReadyRead();
    120118    virtual void downstreamReadyWrite();
    121119    virtual void copyFinished(QIODevice *);
    122120    virtual void ignoreSslErrors();
     121    virtual void ignoreSslErrors(const QList<QSslError> &errors);
    123122
    124123    virtual void fetchSslConfiguration(QSslConfiguration &configuration) const;
     
    156155    void setAttribute(QNetworkRequest::Attribute code, const QVariant &value);
    157156
     157    // return true if the QNonContiguousByteDevice of the upload
     158    // data needs to support reset(). Currently needed for HTTP.
     159    // This will possibly enable buffering of the upload data.
     160    virtual bool needsResetableUploadData() { return false; }
     161
    158162protected:
    159     // these functions control the upstream mechanism
    160     // that is, data coming into the backend and out via the connection
    161     qint64 upstreamBytesAvailable() const;
    162     void upstreamBytesConsumed(qint64 count);
    163     QByteArray readUpstream();
     163    // Create the device used for reading the upload data
     164    QNonContiguousByteDevice* createUploadByteDevice();
     165
    164166
    165167    // these functions control the downstream mechanism
    166168    // that is, data that has come via the connection and is going out the backend
    167169    qint64 nextDownstreamBlockSize() const;
    168     qint64 downstreamBytesToConsume() const;
    169     void writeDownstreamData(const QByteArray &data);
     170    void writeDownstreamData(QByteDataBuffer &list);
     171
     172public slots:
     173    // for task 251801, needs to be a slot to be called asynchronously
    170174    void writeDownstreamData(QIODevice *data);
    171175
     
    180184    void redirectionRequested(const QUrl &destination);
    181185    void sslErrors(const QList<QSslError> &errors);
     186    void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal);
    182187
    183188private:
    184189    friend class QNetworkAccessManager;
    185190    friend class QNetworkAccessManagerPrivate;
     191    friend class QNetworkAccessBackendUploadIODevice;
    186192    QNetworkAccessManagerPrivate *manager;
    187193    QNetworkReplyImplPrivate *reply;
  • trunk/src/network/access/qnetworkaccesscache.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/access/qnetworkaccesscache_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6565class QUrl;
    6666
     67// this class is not about caching files but about
     68// caching objects used by QNetworkAccessManager, e.g. existing TCP connections
     69// or credentials.
    6770class QNetworkAccessCache: public QObject
    6871{
  • trunk/src/network/access/qnetworkaccesscachebackend.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5353QNetworkAccessCacheBackend::QNetworkAccessCacheBackend()
    5454    : QNetworkAccessBackend()
     55    , device(0)
    5556{
    5657}
     
    8687    setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute));
    8788    setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true);
     89
     90    // set the raw headers
     91    QNetworkCacheMetaData::RawHeaderList rawHeaders = item.rawHeaders();
     92    QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(),
     93                                                       end = rawHeaders.constEnd();
     94    for ( ; it != end; ++it)
     95        setRawHeader(it->first, it->second);
     96
     97    // handle a possible redirect
     98    QVariant redirectionTarget = attributes.value(QNetworkRequest::RedirectionTargetAttribute);
     99    if (redirectionTarget.isValid()) {
     100        setAttribute(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget);
     101        redirectionRequested(redirectionTarget.toUrl());
     102    }
    88103
    89104    // signal we're open
  • trunk/src/network/access/qnetworkaccesscachebackend_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/access/qnetworkaccessdatabackend.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    118118            emit metaDataChanged();
    119119
    120             writeDownstreamData(payload);
     120            QByteDataBuffer list;
     121            list.append(payload);
     122            payload.clear(); // important because of implicit sharing!
     123            writeDownstreamData(list);
     124
    121125            finished();
    122126            return;
  • trunk/src/network/access/qnetworkaccessdatabackend_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/access/qnetworkaccessdebugpipebackend.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4242#include "qnetworkaccessdebugpipebackend_p.h"
    4343#include "QtCore/qdatastream.h"
     44#include <QCoreApplication>
     45#include "private/qnoncontiguousbytedevice_p.h"
    4446
    4547QT_BEGIN_NAMESPACE
     
    5052    ReadBufferSize = 16384,
    5153    WriteBufferSize = ReadBufferSize
    52 };
    53 
    54 struct QNetworkAccessDebugPipeBackend::DataPacket
    55 {
    56     QList<QPair<QByteArray, QByteArray> > headers;
    57     QByteArray data;
    5854};
    5955
     
    8076
    8177QNetworkAccessDebugPipeBackend::QNetworkAccessDebugPipeBackend()
    82     : incomingPacketSize(0), bareProtocol(false)
     78    : bareProtocol(false), hasUploadFinished(false), hasDownloadFinished(false),
     79    hasEverythingFinished(false), bytesDownloaded(0), bytesUploaded(0)
    8380{
    8481}
     
    8683QNetworkAccessDebugPipeBackend::~QNetworkAccessDebugPipeBackend()
    8784{
     85    // this is signals disconnect, not network!
    8886    socket.disconnect(this);    // we're not interested in the signals at this point
    8987}
     
    9391    socket.connectToHost(url().host(), url().port(12345));
    9492    socket.setReadBufferSize(ReadBufferSize);
     93
     94    // socket ready read -> we can push from socket to downstream
    9595    connect(&socket, SIGNAL(readyRead()), SLOT(socketReadyRead()));
    96     connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64)));
    9796    connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError()));
    9897    connect(&socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
     98    connect(&socket, SIGNAL(connected()), SLOT(socketConnected()));
     99    // socket bytes written -> we can push more from upstream to socket
     100    connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64)));
    99101
    100102    bareProtocol = url().queryItemValue(QLatin1String("bare")) == QLatin1String("1");
    101103
    102     if (!bareProtocol) {
    103         // "Handshake":
    104         // send outgoing metadata and the URL being requested
    105         DataPacket packet;
    106         //packet.metaData = request().metaData();
    107         packet.data = url().toEncoded();
    108         send(packet);
    109     }
     104    if (operation() == QNetworkAccessManager::PutOperation) {
     105        uploadByteDevice = createUploadByteDevice();
     106        QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
     107        QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
     108    }
     109}
     110
     111void QNetworkAccessDebugPipeBackend::socketReadyRead()
     112{
     113    pushFromSocketToDownstream();
     114}
     115
     116void QNetworkAccessDebugPipeBackend::downstreamReadyWrite()
     117{
     118    pushFromSocketToDownstream();
     119}
     120
     121void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64)
     122{
     123    pushFromUpstreamToSocket();
     124}
     125
     126void QNetworkAccessDebugPipeBackend::uploadReadyReadSlot()
     127{
     128    pushFromUpstreamToSocket();
     129}
     130
     131void QNetworkAccessDebugPipeBackend::pushFromSocketToDownstream()
     132{
     133    QByteArray buffer;
     134
     135    if (socket.state() == QAbstractSocket::ConnectingState) {
     136        return;
     137    }
     138
     139    forever {
     140        if (hasDownloadFinished)
     141            return;
     142
     143        buffer.resize(ReadBufferSize);
     144        qint64 haveRead = socket.read(buffer.data(), ReadBufferSize);
     145       
     146        if (haveRead == -1) {
     147            hasDownloadFinished = true;
     148            // this ensures a good last downloadProgress is emitted
     149            setHeader(QNetworkRequest::ContentLengthHeader, QVariant());
     150            possiblyFinish();
     151            break;
     152        } else if (haveRead == 0) {
     153            break;
     154        } else {
     155            // have read something
     156            buffer.resize(haveRead);
     157            bytesDownloaded += haveRead;
     158
     159            QByteDataBuffer list;
     160            list.append(buffer);
     161            buffer.clear(); // important because of implicit sharing!
     162            writeDownstreamData(list);
     163        }
     164    }
     165}
     166
     167void QNetworkAccessDebugPipeBackend::pushFromUpstreamToSocket()
     168{
     169    // FIXME
     170    if (operation() == QNetworkAccessManager::PutOperation) {
     171        if (hasUploadFinished)
     172            return;
     173
     174        forever {
     175            if (socket.bytesToWrite() >= WriteBufferSize)
     176                return;
     177
     178            qint64 haveRead;
     179            const char *readPointer = uploadByteDevice->readPointer(WriteBufferSize, haveRead);
     180            if (haveRead == -1) {
     181                // EOF
     182                hasUploadFinished = true;
     183                emitReplyUploadProgress(bytesUploaded, bytesUploaded);
     184                possiblyFinish();
     185                break;
     186            } else if (haveRead == 0 || readPointer == 0) {
     187                // nothing to read right now, we will be called again later
     188                break;
     189            } else {
     190                qint64 haveWritten;
     191                haveWritten = socket.write(readPointer, haveRead);
     192
     193                if (haveWritten < 0) {
     194                    // write error!
     195                    QString msg = QCoreApplication::translate("QNetworkAccessDebugPipeBackend", "Write error writing to %1: %2")
     196                                  .arg(url().toString(), socket.errorString());
     197                    error(QNetworkReply::ProtocolFailure, msg);
     198                    finished();
     199                    return;
     200                } else {
     201                    uploadByteDevice->advanceReadPointer(haveWritten);
     202                    bytesUploaded += haveWritten;
     203                    emitReplyUploadProgress(bytesUploaded, -1);
     204                }
     205
     206                //QCoreApplication::processEvents();
     207
     208            }
     209        }
     210    }
     211}
     212
     213void QNetworkAccessDebugPipeBackend::possiblyFinish()
     214{
     215    if (hasEverythingFinished)
     216        return;
     217    hasEverythingFinished = true;
     218
     219    if ((operation() == QNetworkAccessManager::GetOperation) && hasDownloadFinished) {
     220        socket.close();
     221        finished();
     222    } else if ((operation() == QNetworkAccessManager::PutOperation) && hasUploadFinished) {
     223        socket.close();
     224        finished();
     225    }
     226
     227
    110228}
    111229
    112230void QNetworkAccessDebugPipeBackend::closeDownstreamChannel()
    113231{
    114     if (operation() == QNetworkAccessManager::GetOperation)
    115         socket.disconnectFromHost();
    116 }
    117 
    118 void QNetworkAccessDebugPipeBackend::closeUpstreamChannel()
    119 {
    120     if (operation() == QNetworkAccessManager::PutOperation)
    121         socket.disconnectFromHost();
    122     else if (operation() == QNetworkAccessManager::PostOperation) {
    123         send(DataPacket());
    124     }
    125 }
    126 
    127 bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms)
    128 {
    129     readyReadEmitted = false;
    130     if (socket.bytesAvailable()) {
    131         socketReadyRead();
    132         if (readyReadEmitted)
    133             return true;
    134     }
    135     socket.waitForReadyRead(ms);
    136     return readyReadEmitted;
    137 }
    138 
    139 bool QNetworkAccessDebugPipeBackend::waitForUpstreamBytesWritten(int ms)
    140 {
    141     bytesWrittenEmitted = false;
    142     upstreamReadyRead();
    143     if (bytesWrittenEmitted)
    144         return true;
    145 
    146     socket.waitForBytesWritten(ms);
    147     return bytesWrittenEmitted;
    148 }
    149 
    150 void QNetworkAccessDebugPipeBackend::upstreamReadyRead()
    151 {
    152     int maxWrite = WriteBufferSize - socket.bytesToWrite();
    153     if (maxWrite <= 0)
    154         return;                 // can't write yet, wait for the socket to write
    155 
    156     if (bareProtocol) {
    157         QByteArray data = readUpstream();
    158         if (data.isEmpty())
    159             return;
    160 
    161         socket.write(data);
    162         upstreamBytesConsumed(data.size());
    163         bytesWrittenEmitted = true;
    164         return;
    165     }
    166 
    167     DataPacket packet;
    168     packet.data = readUpstream();
    169     if (packet.data.isEmpty())
    170         return;                 // we'll be called again when there's data
    171     if (packet.data.size() > maxWrite)
    172         packet.data.truncate(maxWrite);
    173 
    174     if (!send(packet)) {
    175         QString msg = QObject::tr("Write error writing to %1: %2")
    176                       .arg(url().toString(), socket.errorString());
    177         error(QNetworkReply::ProtocolFailure, msg);
    178 
    179         finished();
    180         return;
    181     }
    182     upstreamBytesConsumed(packet.data.size());
    183     bytesWrittenEmitted = true;
    184 }
    185 
    186 void QNetworkAccessDebugPipeBackend::downstreamReadyWrite()
    187 {
    188     socketReadyRead();
    189 }
    190 
    191 void QNetworkAccessDebugPipeBackend::socketReadyRead()
    192 {
    193     if (bareProtocol) {
    194         qint64 bytesToRead = socket.bytesAvailable();
    195         if (bytesToRead) {
    196             QByteArray buffer;
    197             buffer.resize(bytesToRead);
    198             qint64 bytesRead = socket.read(buffer.data(), bytesToRead);
    199             if (bytesRead < bytesToRead)
    200                 buffer.truncate(bytesRead);
    201             writeDownstreamData(buffer);
    202             readyReadEmitted = true;
    203         }
    204         return;
    205     }
    206 
    207     while (canReceive() &&
    208            (socket.state() == QAbstractSocket::UnconnectedState || nextDownstreamBlockSize())) {
    209         DataPacket packet;
    210         if (receive(packet)) {
    211             if (!packet.headers.isEmpty()) {
    212                 QList<QPair<QByteArray, QByteArray> >::ConstIterator
    213                     it = packet.headers.constBegin(),
    214                     end = packet.headers.constEnd();
    215                 for ( ; it != end; ++it)
    216                     setRawHeader(it->first, it->second);
    217                 metaDataChanged();
    218             }
    219 
    220             if (!packet.data.isEmpty()) {
    221                 writeDownstreamData(packet.data);
    222                 readyReadEmitted = true;
    223             }
    224 
    225             if (packet.headers.isEmpty() && packet.data.isEmpty()) {
    226                 // it's an eof
    227                 socket.close();
    228                 readyReadEmitted = true;
    229             }
    230         } else {
    231             // got an error
    232             QString msg = QObject::tr("Read error reading from %1: %2")
    233                           .arg(url().toString(), socket.errorString());
    234             error(QNetworkReply::ProtocolFailure, msg);
    235 
    236             finished();
    237             return;
    238         }
    239     }
    240 }
    241 
    242 void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64)
    243 {
    244     upstreamReadyRead();
    245 }
     232    qWarning("QNetworkAccessDebugPipeBackend::closeDownstreamChannel() %d",operation());;
     233    //if (operation() == QNetworkAccessManager::GetOperation)
     234    //    socket.disconnectFromHost();
     235}
     236
    246237
    247238void QNetworkAccessDebugPipeBackend::socketError()
    248239{
     240    qWarning("QNetworkAccessDebugPipeBackend::socketError() %d",socket.error());
    249241    QNetworkReply::NetworkError code;
    250242    switch (socket.error()) {
     
    270262void QNetworkAccessDebugPipeBackend::socketDisconnected()
    271263{
    272     socketReadyRead();
    273     if (incomingPacketSize == 0 && socket.bytesToWrite() == 0) {
     264    pushFromSocketToDownstream();
     265
     266    if (socket.bytesToWrite() == 0) {
    274267        // normal close
    275         finished();
    276268    } else {
    277269        // abnormal close
     
    279271                             .arg(url().toString());
    280272        error(QNetworkReply::RemoteHostClosedError, msg);
    281 
    282273        finished();
    283274    }
    284275}
    285276
    286 bool QNetworkAccessDebugPipeBackend::send(const DataPacket &packet)
    287 {
    288     QByteArray ba;
    289     {
    290         QDataStream stream(&ba, QIODevice::WriteOnly);
    291         stream.setVersion(QDataStream::Qt_4_4);
    292 
    293         stream << packet.headers << packet.data;
    294     }
    295 
    296     qint32 outgoingPacketSize = ba.size();
    297     qint64 written = socket.write((const char*)&outgoingPacketSize, sizeof outgoingPacketSize);
    298     written += socket.write(ba);
    299     return quint64(written) == (outgoingPacketSize + sizeof outgoingPacketSize);
    300 }
    301 
    302 bool QNetworkAccessDebugPipeBackend::receive(DataPacket &packet)
    303 {
    304     if (!canReceive())
    305         return false;
    306 
    307     // canReceive() does the setting up for us
    308     Q_ASSERT(socket.bytesAvailable() >= incomingPacketSize);
    309     QByteArray incomingPacket = socket.read(incomingPacketSize);
    310     QDataStream stream(&incomingPacket, QIODevice::ReadOnly);
    311     stream.setVersion(QDataStream::Qt_4_4);
    312     stream >> packet.headers >> packet.data;
    313 
    314     // reset for next packet:
    315     incomingPacketSize = 0;
    316     socket.setReadBufferSize(ReadBufferSize);
    317     return true;
    318 }
    319 
    320 bool QNetworkAccessDebugPipeBackend::canReceive()
    321 {
    322     if (incomingPacketSize == 0) {
    323         // read the packet size
    324         if (quint64(socket.bytesAvailable()) >= sizeof incomingPacketSize)
    325             socket.read((char*)&incomingPacketSize, sizeof incomingPacketSize);
    326         else
    327             return false;
    328     }
    329 
    330     if (incomingPacketSize == 0) {
    331         QString msg = QObject::tr("Protocol error: packet of size 0 received");
    332         error(QNetworkReply::ProtocolFailure, msg);
    333         finished();
    334 
    335         socket.blockSignals(true);
    336         socket.abort();
    337         socket.blockSignals(false);
    338         return false;
    339     }
    340 
    341     return socket.bytesAvailable() >= incomingPacketSize;
     277void QNetworkAccessDebugPipeBackend::socketConnected()
     278{
     279}
     280
     281bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms)
     282{
     283    Q_UNUSED(ms);
     284    qCritical("QNetworkAccess: Debug pipe backend does not support waitForReadyRead()");
     285    return false;
    342286}
    343287
  • trunk/src/network/access/qnetworkaccessdebugpipebackend_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6767    Q_OBJECT
    6868public:
    69     struct DataPacket;
    7069    QNetworkAccessDebugPipeBackend();
    7170    virtual ~QNetworkAccessDebugPipeBackend();
     
    7372    virtual void open();
    7473    virtual void closeDownstreamChannel();
    75     virtual void closeUpstreamChannel();
    7674    virtual bool waitForDownstreamReadyRead(int msecs);
    77     virtual bool waitForUpstreamBytesWritten(int msecs);
    7875
    79     virtual void upstreamReadyRead();
    8076    virtual void downstreamReadyWrite();
    8177
     78protected:
     79    void pushFromSocketToDownstream();
     80    void pushFromUpstreamToSocket();
     81    void possiblyFinish();
     82    QNonContiguousByteDevice *uploadByteDevice;
     83
    8284private slots:
     85    void uploadReadyReadSlot();
    8386    void socketReadyRead();
    8487    void socketBytesWritten(qint64 bytes);
    8588    void socketError();
    8689    void socketDisconnected();
     90    void socketConnected();
    8791
    8892private:
    8993    QTcpSocket socket;
    90     qint32 incomingPacketSize;
    91     bool readyReadEmitted;
    92     bool bytesWrittenEmitted;
    9394    bool bareProtocol;
     95    bool hasUploadFinished;
     96    bool hasDownloadFinished;
     97    bool hasEverythingFinished;
    9498
    95     bool send(const DataPacket &packet);
    96     bool canReceive();
    97     bool receive(DataPacket &packet);
     99    qint64 bytesDownloaded;
     100    qint64 bytesUploaded;
    98101};
    99102
  • trunk/src/network/access/qnetworkaccessfilebackend.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444#include "qurlinfo.h"
    4545#include "qdir.h"
     46#include "private/qnoncontiguousbytedevice_p.h"
    4647
    4748#include <QtCore/QCoreApplication>
     
    7879
    7980QNetworkAccessFileBackend::QNetworkAccessFileBackend()
    80     : totalBytes(0)
     81    : uploadByteDevice(0), totalBytes(0), hasUploadFinished(false)
    8182{
    8283}
     
    109110    if (fileName.isEmpty()) {
    110111        if (url.scheme() == QLatin1String("qrc"))
    111             fileName = QLatin1String(":") + url.path();
     112            fileName = QLatin1Char(':') + url.path();
    112113        else
    113114            fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery);
     
    127128    case QNetworkAccessManager::PutOperation:
    128129        mode = QIODevice::WriteOnly | QIODevice::Truncate;
     130        uploadByteDevice = createUploadByteDevice();
     131        QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
     132        QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
    129133        break;
    130134    default:
     
    153157}
    154158
     159void QNetworkAccessFileBackend::uploadReadyReadSlot()
     160{
     161    if (hasUploadFinished)
     162        return;
     163
     164    forever {
     165        qint64 haveRead;
     166        const char *readPointer = uploadByteDevice->readPointer(-1, haveRead);
     167        if (haveRead == -1) {
     168            // EOF
     169            hasUploadFinished = true;
     170            file.flush();
     171            file.close();
     172            finished();
     173            break;
     174        } else if (haveRead == 0 || readPointer == 0) {
     175            // nothing to read right now, we will be called again later
     176            break;
     177        } else {
     178            qint64 haveWritten;
     179            haveWritten = file.write(readPointer, haveRead);
     180
     181            if (haveWritten < 0) {
     182                // write error!
     183                QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2")
     184                              .arg(url().toString(), file.errorString());
     185                error(QNetworkReply::ProtocolFailure, msg);
     186
     187                finished();
     188                return;
     189            } else {
     190                uploadByteDevice->advanceReadPointer(haveWritten);
     191            }
     192
     193
     194            file.flush();
     195        }
     196    }
     197}
     198
    155199void QNetworkAccessFileBackend::closeDownstreamChannel()
    156200{
    157201    if (operation() == QNetworkAccessManager::GetOperation) {
    158202        file.close();
    159         //downstreamChannelClosed();
    160     }
    161 }
    162 
    163 void QNetworkAccessFileBackend::closeUpstreamChannel()
    164 {
    165     if (operation() == QNetworkAccessManager::PutOperation) {
    166         file.close();
    167         finished();
    168203    }
    169204}
     
    173208    Q_ASSERT(operation() == QNetworkAccessManager::GetOperation);
    174209    return readMoreFromFile();
    175 }
    176 
    177 bool QNetworkAccessFileBackend::waitForUpstreamBytesWritten(int)
    178 {
    179     Q_ASSERT_X(false, "QNetworkAccessFileBackend::waitForUpstreamBytesWritten",
    180                "This function should never have been called, since there is never anything "
    181                "left to be written!");
    182     return false;
    183 }
    184 
    185 void QNetworkAccessFileBackend::upstreamReadyRead()
    186 {
    187     Q_ASSERT_X(operation() == QNetworkAccessManager::PutOperation, "QNetworkAccessFileBackend",
    188                "We're being told to upload data but operation isn't PUT!");
    189 
    190     // there's more data to be written to the file
    191     while (upstreamBytesAvailable()) {
    192         // write everything and let QFile handle it
    193         int written = file.write(readUpstream());
    194 
    195         if (written < 0) {
    196             // write error!
    197             QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2")
    198                                                     .arg(url().toString(), file.errorString());
    199             error(QNetworkReply::ProtocolFailure, msg);
    200 
    201             finished();
    202             return;
    203         }
    204 
    205         // successful write
    206         file.flush();
    207         upstreamBytesConsumed(written);
    208     }
    209210}
    210211
     
    263264        data.resize(actuallyRead);
    264265        totalBytes += actuallyRead;
    265         writeDownstreamData(data);
     266
     267        QByteDataBuffer list;
     268        list.append(data);
     269        data.clear(); // important because of implicit sharing!
     270        writeDownstreamData(list);
    266271    }
    267272    return true;
  • trunk/src/network/access/qnetworkaccessfilebackend_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6363class QNetworkAccessFileBackend: public QNetworkAccessBackend
    6464{
     65    Q_OBJECT
    6566public:
    6667    QNetworkAccessFileBackend();
     
    6970    virtual void open();
    7071    virtual void closeDownstreamChannel();
    71     virtual void closeUpstreamChannel();
    7272    virtual bool waitForDownstreamReadyRead(int msecs);
    73     virtual bool waitForUpstreamBytesWritten(int msecs);
    7473
    75     virtual void upstreamReadyRead();
    7674    virtual void downstreamReadyWrite();
    7775
     76public slots:
     77    void uploadReadyReadSlot();
     78protected:
     79    QNonContiguousByteDevice *uploadByteDevice;
    7880private:
    7981    QFile file;
    8082    qint64 totalBytes;
     83    bool hasUploadFinished;
    8184
    8285    bool loadFileInfo();
  • trunk/src/network/access/qnetworkaccessftpbackend.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4343#include "qnetworkaccessmanager_p.h"
    4444#include "QtNetwork/qauthenticator.h"
     45#include "private/qnoncontiguousbytedevice_p.h"
    4546
    4647#ifndef QT_NO_FTP
     
    8283}
    8384
    84 class QNetworkAccessFtpIODevice: public QIODevice
    85 {
    86     //Q_OBJECT
    87 public:
    88     QNetworkAccessFtpBackend *backend;
    89     bool eof;
    90 
    91     inline QNetworkAccessFtpIODevice(QNetworkAccessFtpBackend *parent)
    92         : QIODevice(parent), backend(parent), eof(false)
    93         { open(ReadOnly); }
    94 
    95     bool isSequential() const { return true; }
    96     bool atEnd() const { return backend->upstreamBytesAvailable() == 0; }
    97 
    98     qint64 bytesAvailable() const { return backend->upstreamBytesAvailable(); }
    99     qint64 bytesToWrite() const { return backend->downstreamBytesToConsume(); }
    100 protected:
    101     qint64 readData(char *data, qint64 maxlen)
    102     {
    103         const QByteArray toSend = backend->readUpstream();
    104         maxlen = qMin<qint64>(maxlen, toSend.size());
    105         if (!maxlen)
    106             return eof ? -1 : 0;
    107 
    108         backend->upstreamBytesConsumed(maxlen);
    109         memcpy(data, toSend.constData(), maxlen);
    110         return maxlen;
    111     }
    112 
    113     qint64 writeData(const char *, qint64)
    114     { return -1; }
    115 
    116     friend class QNetworkAccessFtpBackend;
    117 };
    118 
    119 class QNetworkAccessFtpFtp: public QFtp, public QNetworkAccessCache::CacheableObject
     85class QNetworkAccessCachedFtpConnection: public QFtp, public QNetworkAccessCache::CacheableObject
    12086{
    12187    // Q_OBJECT
    12288public:
    123     QNetworkAccessFtpFtp()
     89    QNetworkAccessCachedFtpConnection()
    12490    {
    12591        setExpires(true);
     
    183149    state = LoggingIn;
    184150
    185     QNetworkAccessCache* cache = QNetworkAccessManagerPrivate::getCache(this);
     151    QNetworkAccessCache* objectCache = QNetworkAccessManagerPrivate::getObjectCache(this);
    186152    QByteArray cacheKey = makeCacheKey(url);
    187     if (!cache->requestEntry(cacheKey, this,
     153    if (!objectCache->requestEntry(cacheKey, this,
    188154                             SLOT(ftpConnectionReady(QNetworkAccessCache::CacheableObject*)))) {
    189         ftp = new QNetworkAccessFtpFtp;
     155        ftp = new QNetworkAccessCachedFtpConnection;
    190156#ifndef QT_NO_NETWORKPROXY
    191157        if (proxy.type() == QNetworkProxy::FtpCachingProxy)
     
    195161        ftp->login(url.userName(), url.password());
    196162
    197         cache->addEntry(cacheKey, ftp);
     163        objectCache->addEntry(cacheKey, ftp);
    198164        ftpConnectionReady(ftp);
    199165    }
    200166
    201     uploadDevice = new QNetworkAccessFtpIODevice(this);
     167    // Put operation
     168    if (operation() == QNetworkAccessManager::PutOperation) {
     169        uploadDevice = QNonContiguousByteDeviceFactory::wrap(createUploadByteDevice());
     170        uploadDevice->setParent(this);
     171    }
    202172}
    203173
     
    213183}
    214184
    215 void QNetworkAccessFtpBackend::closeUpstreamChannel()
    216 {
    217     if (operation() == QNetworkAccessManager::PutOperation) {
    218         Q_ASSERT(uploadDevice);
    219         uploadDevice->eof = true;
    220         if (!upstreamBytesAvailable())
    221             emit uploadDevice->readyRead();
    222     }
    223 }
    224 
    225185bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms)
    226186{
     
    240200}
    241201
    242 bool QNetworkAccessFtpBackend::waitForUpstreamBytesWritten(int ms)
    243 {
    244     Q_UNUSED(ms);
    245     qCritical("QNetworkAccess: FTP backend does not support waitForBytesWritten()");
    246     return false;
    247 }
    248 
    249 void QNetworkAccessFtpBackend::upstreamReadyRead()
    250 {
    251     // uh... how does QFtp operate?
    252 }
    253 
    254202void QNetworkAccessFtpBackend::downstreamReadyWrite()
    255203{
     
    260208void QNetworkAccessFtpBackend::ftpConnectionReady(QNetworkAccessCache::CacheableObject *o)
    261209{
    262     ftp = static_cast<QNetworkAccessFtpFtp *>(o);
     210    ftp = static_cast<QNetworkAccessCachedFtpConnection *>(o);
    263211    connect(ftp, SIGNAL(done(bool)), SLOT(ftpDone()));
    264212    connect(ftp, SIGNAL(rawCommandReply(int,QString)), SLOT(ftpRawCommandReply(int,QString)));
     
    280228
    281229        QByteArray key = makeCacheKey(url());
    282         QNetworkAccessManagerPrivate::getCache(this)->releaseEntry(key);
     230        QNetworkAccessManagerPrivate::getObjectCache(this)->releaseEntry(key);
    283231
    284232        ftp = 0;
     
    331279        // we're not connected, so remove the cache entry:
    332280        QByteArray key = makeCacheKey(url());
    333         QNetworkAccessManagerPrivate::getCache(this)->removeEntry(key);
     281        QNetworkAccessManagerPrivate::getObjectCache(this)->removeEntry(key);
    334282
    335283        disconnect(ftp, 0, this, 0);
     
    408356void QNetworkAccessFtpBackend::ftpReadyRead()
    409357{
    410     writeDownstreamData(ftp->readAll());
     358    QByteArray data = ftp->readAll();
     359    QByteDataBuffer list;
     360    list.append(data);
     361    data.clear(); // important because of implicit sharing!
     362    writeDownstreamData(list);
    411363}
    412364
  • trunk/src/network/access/qnetworkaccessftpbackend_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6767
    6868class QNetworkAccessFtpIODevice;
    69 class QNetworkAccessFtpFtp;
     69class QNetworkAccessCachedFtpConnection;
    7070
    7171class QNetworkAccessFtpBackend: public QNetworkAccessBackend
     
    8888    virtual void open();
    8989    virtual void closeDownstreamChannel();
    90     virtual void closeUpstreamChannel();
    9190    virtual bool waitForDownstreamReadyRead(int msecs);
    92     virtual bool waitForUpstreamBytesWritten(int msecs);
    9391
    94     virtual void upstreamReadyRead();
    9592    virtual void downstreamReadyWrite();
    9693
     
    105102private:
    106103    friend class QNetworkAccessFtpIODevice;
    107     QPointer<QNetworkAccessFtpFtp> ftp;
    108     QNetworkAccessFtpIODevice *uploadDevice;
     104    QPointer<QNetworkAccessCachedFtpConnection> ftp;
     105    QIODevice *uploadDevice;
    109106    qint64 totalBytes;
    110107    int helpId, sizeId, mdtmId;
  • trunk/src/network/access/qnetworkaccesshttpbackend.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    213213    case QNetworkAccessManager::HeadOperation:
    214214    case QNetworkAccessManager::PutOperation:
     215    case QNetworkAccessManager::DeleteOperation:
    215216        break;
    216217
     
    243244    case 404:               // Not Found
    244245        code = QNetworkReply::ContentNotFoundError;
     246        break;
     247
     248    case 405:               // Method Not Allowed
     249        code = QNetworkReply::ContentOperationNotPermittedError;
    245250        break;
    246251
     
    266271}
    267272
    268 class QNetworkAccessHttpBackendCache: public QHttpNetworkConnection,
     273class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection,
    269274                                      public QNetworkAccessCache::CacheableObject
    270275{
    271276    // Q_OBJECT
    272277public:
    273     QNetworkAccessHttpBackendCache(const QString &hostName, quint16 port, bool encrypt)
     278    QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt)
    274279        : QHttpNetworkConnection(hostName, port, encrypt)
    275280    {
     
    287292};
    288293
    289 class QNetworkAccessHttpBackendIODevice: public QIODevice
    290 {
    291     // Q_OBJECT
    292 public:
    293     bool eof;
    294     QNetworkAccessHttpBackendIODevice(QNetworkAccessHttpBackend *parent)
    295         : QIODevice(parent), eof(false)
    296     {
    297         setOpenMode(ReadOnly);
    298     }
    299     bool isSequential() const { return true; }
    300     qint64 bytesAvailable() const
    301     { return static_cast<QNetworkAccessHttpBackend *>(parent())->upstreamBytesAvailable(); }
    302 
    303 protected:
    304     virtual qint64 readData(char *buffer, qint64 maxlen)
    305     {
    306         qint64 ret = static_cast<QNetworkAccessHttpBackend *>(parent())->deviceReadData(buffer, maxlen);
    307         if (!ret && eof)
    308             return -1;
    309         return ret;
    310     }
    311 
    312     virtual qint64 writeData(const char *, qint64)
    313     {
    314         return -1;              // cannot write
    315     }
    316 
    317     friend class QNetworkAccessHttpBackend;
    318 };
    319 
    320294QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
    321295    : QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0)
    322296#ifndef QT_NO_OPENSSL
    323     , pendingSslConfiguration(0), pendingIgnoreSslErrors(false)
     297    , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
    324298#endif
    325299{
     
    338312{
    339313    if (http) {
     314        // This is abut disconnecting signals, not about disconnecting TCP connections
    340315        disconnect(http, 0, this, 0);
    341         QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getCache(this);
     316
     317        // Get the object cache that stores our QHttpNetworkConnection objects
     318        QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this);
    342319        cache->releaseEntry(cacheKey);
    343320    }
    344321
     322    // This is abut disconnecting signals, not about disconnecting TCP connections
    345323    if (httpReply)
    346324        disconnect(httpReply, 0, this, 0);
     
    508486        invalidateCache();
    509487        httpRequest.setOperation(QHttpNetworkRequest::Post);
    510         uploadDevice = new QNetworkAccessHttpBackendIODevice(this);
     488        httpRequest.setUploadByteDevice(createUploadByteDevice());
    511489        break;
    512490
     
    514492        invalidateCache();
    515493        httpRequest.setOperation(QHttpNetworkRequest::Put);
    516         uploadDevice = new QNetworkAccessHttpBackendIODevice(this);
     494        httpRequest.setUploadByteDevice(createUploadByteDevice());
     495        break;
     496
     497    case QNetworkAccessManager::DeleteOperation:
     498        invalidateCache();
     499        httpRequest.setOperation(QHttpNetworkRequest::Delete);
    517500        break;
    518501
     
    521504    }
    522505
    523     httpRequest.setData(uploadDevice);
    524506    httpRequest.setUrl(url());
    525507
     
    529511
    530512    if (loadedFromCache) {
    531         QNetworkAccessBackend::finished();
     513        // commented this out since it will be called later anyway
     514        // by copyFinished()
     515        //QNetworkAccessBackend::finished();
    532516        return;    // no need to send the request! :)
    533517    }
     518
     519    if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
     520        httpRequest.setPipeliningAllowed(true);
    534521
    535522    httpReply = http->sendRequest(httpRequest);
     
    538525    if (pendingSslConfiguration)
    539526        httpReply->setSslConfiguration(*pendingSslConfiguration);
    540     if (pendingIgnoreSslErrors)
     527    if (pendingIgnoreAllSslErrors)
    541528        httpReply->ignoreSslErrors();
     529    httpReply->ignoreSslErrors(pendingIgnoreSslErrorsList);
    542530#endif
    543531
     
    603591    // check if we have an open connection to this host
    604592    cacheKey = makeCacheKey(this, theProxy);
    605     QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getCache(this);
    606     if ((http = static_cast<QNetworkAccessHttpBackendCache *>(cache->requestEntryNow(cacheKey))) == 0) {
     593    QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this);
     594    // the http object is actually a QHttpNetworkConnection
     595    http = static_cast<QNetworkAccessCachedHttpConnection *>(cache->requestEntryNow(cacheKey));
     596    if (http == 0) {
    607597        // no entry in cache; create an object
    608         http = new QNetworkAccessHttpBackendCache(url.host(), url.port(), encrypt);
     598        // the http object is actually a QHttpNetworkConnection
     599        http = new QNetworkAccessCachedHttpConnection(url.host(), url.port(), encrypt);
    609600
    610601#ifndef QT_NO_NETWORKPROXY
     
    613604#endif
    614605
     606        // cache the QHttpNetworkConnection corresponding to this cache key
    615607        cache->addEntry(cacheKey, http);
    616608    }
     
    623615{
    624616    // this indicates that the user closed the stream while the reply isn't finished yet
    625 }
    626 
    627 void QNetworkAccessHttpBackend::closeUpstreamChannel()
    628 {
    629     // this indicates that the user finished uploading the data for POST
    630     Q_ASSERT(uploadDevice);
    631     uploadDevice->eof = true;
    632     emit uploadDevice->readChannelFinished();
    633617}
    634618
     
    652636}
    653637
    654 bool QNetworkAccessHttpBackend::waitForUpstreamBytesWritten(int msecs)
    655 {
    656 
    657     // ### FIXME: not implemented in QHttpNetworkAccess
    658     Q_UNUSED(msecs);
    659     qCritical("QNetworkAccess: HTTP backend does not support waitForBytesWritten()");
    660     return false;
    661 }
    662 
    663 void QNetworkAccessHttpBackend::upstreamReadyRead()
    664 {
    665     // There is more data available from the user to be uploaded
    666     // QHttpNetworkAccess implements the upload rate control:
    667     //  we simply tell QHttpNetworkAccess that there is more data available
    668     //  it'll pull from us when it can (through uploadDevice)
    669 
    670     Q_ASSERT(uploadDevice);
    671     emit uploadDevice->readyRead();
    672 }
    673 
    674 qint64 QNetworkAccessHttpBackend::deviceReadData(char *buffer, qint64 maxlen)
    675 {
    676     QByteArray toBeUploaded = readUpstream();
    677     if (toBeUploaded.isEmpty())
    678         return 0;               // nothing to be uploaded
    679 
    680     maxlen = qMin<qint64>(maxlen, toBeUploaded.length());
    681 
    682     memcpy(buffer, toBeUploaded.constData(), maxlen);
    683     upstreamBytesConsumed(maxlen);
    684     return maxlen;
    685 }
    686638
    687639void QNetworkAccessHttpBackend::downstreamReadyWrite()
     
    702654        return;
    703655
    704     // We implement the download rate control
    705     // Don't read from QHttpNetworkAccess more than QNetworkAccessBackend wants
    706     // One of the two functions above will be called when we can read again
    707 
    708     qint64 bytesToRead = qBound<qint64>(0, httpReply->bytesAvailable(), nextDownstreamBlockSize());
    709     if (!bytesToRead)
    710         return;
    711 
    712     QByteArray data = httpReply->read(bytesToRead);
    713     writeDownstreamData(data);
     656    // We read possibly more than nextDownstreamBlockSize(), but
     657    // this is not a critical thing since it is already in the
     658    // memory anyway
     659
     660    QByteDataBuffer list;
     661
     662    while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0 && nextDownstreamBlockSize() > list.byteAmount()) {
     663        QByteArray data = httpReply->readAny();
     664        list.append(data);
     665    }
     666
     667    if (!list.isEmpty())
     668      writeDownstreamData(list);
    714669}
    715670
     
    733688    // once we call finished(), we won't have access to httpReply anymore
    734689    QSslConfiguration sslConfig = httpReply->sslConfiguration();
    735     if (pendingSslConfiguration)
     690    if (pendingSslConfiguration) {
    736691        *pendingSslConfiguration = sslConfig;
    737     else if (!sslConfig.isNull())
    738         pendingSslConfiguration = new QSslConfiguration(sslConfig);
     692    } else if (!sslConfig.isNull()) {
     693        QT_TRY {
     694            pendingSslConfiguration = new QSslConfiguration(sslConfig);
     695        } QT_CATCH(...) {
     696            qWarning("QNetworkAccess: could not allocate a QSslConfiguration object for a SSL connection.");
     697        }
     698    }
    739699#endif
    740700
     
    762722void QNetworkAccessHttpBackend::replyHeaderChanged()
    763723{
     724    setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, httpReply->isPipeliningUsed());
     725
    764726    // reconstruct the HTTP header
    765727    QList<QPair<QByteArray, QByteArray> > headerMap = httpReply->header();
     
    771733        QByteArray value = rawHeader(it->first);
    772734        if (!value.isEmpty()) {
    773             if (it->first.toLower() == "set-cookie")
     735            if (qstricmp(it->first.constData(), "set-cookie") == 0)
    774736                value += "\n";
    775737            else
     
    905867    checkForRedirect(status);
    906868
    907     writeDownstreamData(contents);
     869    emit metaDataChanged();
     870
     871    // invoke this asynchronously, else Arora/QtDemoBrowser don't like cached downloads
     872    // see task 250221 / 251801
     873    qRegisterMetaType<QIODevice*>("QIODevice*");
     874    QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents));
     875
     876
    908877#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
    909878    qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes";
     
    926895        httpReply->ignoreSslErrors();
    927896    else
    928         pendingIgnoreSslErrors = true;
     897        pendingIgnoreAllSslErrors = true;
     898}
     899
     900void QNetworkAccessHttpBackend::ignoreSslErrors(const QList<QSslError> &errors)
     901{
     902    if (httpReply) {
     903        httpReply->ignoreSslErrors(errors);
     904    } else {
     905        // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
     906        // is called before QNetworkAccessManager::get() (or post(), etc.)
     907        pendingIgnoreSslErrorsList = errors;
     908    }
    929909}
    930910
     
    972952            continue;
    973953
     954        // for 4.6.0, we were planning to not store the date header in the
     955        // cached resource; through that we planned to reduce the number
     956        // of writes to disk when using a QNetworkDiskCache (i.e. don't
     957        // write to disk when only the date changes).
     958        // However, without the date we cannot calculate the age of the page
     959        // anymore. Consider a proper fix of that problem for 4.6.1.
     960        //if (header == "date")
     961            //continue;
     962
    974963        // Don't store Warning 1xx headers
    975964        if (header == "warning") {
     
    10371026        metaData.setLastModified(QNetworkHeadersPrivate::fromHttpDate(it->second));
    10381027
    1039     bool canDiskCache = true; // Everything defaults to being cacheable on disk
    1040 
    1041     // 14.32
    1042     // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client
    1043     // had sent "Cache-Control: no-cache".
    1044     it = cacheHeaders.findRawHeader("pragma");
    1045     if (it != cacheHeaders.rawHeaders.constEnd()
    1046         && it->second == "no-cache")
     1028    bool canDiskCache;
     1029    // only cache GET replies by default, all other replies (POST, PUT, DELETE)
     1030    //  are not cacheable by default (according to RFC 2616 section 9)
     1031    if (httpReply->request().operation() == QHttpNetworkRequest::Get) {
     1032
     1033        canDiskCache = true;
     1034        // 14.32
     1035        // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client
     1036        // had sent "Cache-Control: no-cache".
     1037        it = cacheHeaders.findRawHeader("pragma");
     1038        if (it != cacheHeaders.rawHeaders.constEnd()
     1039            && it->second == "no-cache")
     1040            canDiskCache = false;
     1041
     1042        // HTTP/1.1. Check the Cache-Control header
     1043        if (cacheControl.contains("no-cache"))
     1044            canDiskCache = false;
     1045        else if (cacheControl.contains("no-store"))
     1046            canDiskCache = false;
     1047
     1048    // responses to POST might be cacheable
     1049    } else if (httpReply->request().operation() == QHttpNetworkRequest::Post) {
     1050
    10471051        canDiskCache = false;
    1048 
    1049     // HTTP/1.1. Check the Cache-Control header
    1050     if (cacheControl.contains("no-cache"))
     1052        // some pages contain "expires:" and "cache-control: no-cache" field,
     1053        // so we only might cache POST requests if we get "cache-control: max-age ..."
     1054        if (cacheControl.contains("max-age"))
     1055            canDiskCache = true;
     1056
     1057    // responses to PUT and DELETE are not cacheable
     1058    } else {
    10511059        canDiskCache = false;
    1052     else if (cacheControl.contains("no-store"))
    1053         canDiskCache = false;
     1060    }
    10541061
    10551062    metaData.setSaveToDisk(canDiskCache);
  • trunk/src/network/access/qnetworkaccesshttpbackend_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6767QT_BEGIN_NAMESPACE
    6868
    69 class QNetworkAccessHttpBackendCache;
     69class QNetworkAccessCachedHttpConnection;
    7070
    7171class QNetworkAccessHttpBackendIODevice;
     
    8080    virtual void open();
    8181    virtual void closeDownstreamChannel();
    82     virtual void closeUpstreamChannel();
    8382    virtual bool waitForDownstreamReadyRead(int msecs);
    84     virtual bool waitForUpstreamBytesWritten(int msecs);
    8583
    86     virtual void upstreamReadyRead();
    8784    virtual void downstreamReadyWrite();
    8885    virtual void copyFinished(QIODevice *);
    8986#ifndef QT_NO_OPENSSL
    9087    virtual void ignoreSslErrors();
     88    virtual void ignoreSslErrors(const QList<QSslError> &errors);
    9189
    9290    virtual void fetchSslConfiguration(QSslConfiguration &configuration) const;
     
    9694
    9795    qint64 deviceReadData(char *buffer, qint64 maxlen);
     96
     97    // we return true since HTTP needs to send PUT/POST data again after having authenticated
     98    bool needsResetableUploadData() { return true; }
    9899
    99100private slots:
     
    107108private:
    108109    QHttpNetworkReply *httpReply;
    109     QPointer<QNetworkAccessHttpBackendCache> http;
     110    QPointer<QNetworkAccessCachedHttpConnection> http;
    110111    QByteArray cacheKey;
    111     QNetworkAccessHttpBackendIODevice *uploadDevice;
     112    QNetworkAccessBackendUploadIODevice *uploadDevice;
     113
    112114#ifndef QT_NO_OPENSSL
    113115    QSslConfiguration *pendingSslConfiguration;
    114     bool pendingIgnoreSslErrors;
     116    bool pendingIgnoreAllSslErrors;
     117    QList<QSslError> pendingIgnoreSslErrorsList;
    115118#endif
    116119
     
    123126    void readFromHttp();
    124127    void checkForRedirect(const int statusCode);
    125 
    126     friend class QNetworkAccessHttpBackendIODevice;
    127128};
    128129
  • trunk/src/network/access/qnetworkaccessmanager.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5353#include "qnetworkaccessdatabackend_p.h"
    5454#include "qnetworkaccessdebugpipebackend_p.h"
     55#include "qfilenetworkreply_p.h"
    5556
    5657#include "QtCore/qbuffer.h"
     
    9697    \class QNetworkAccessManager
    9798    \brief The QNetworkAccessManager class allows the application to
    98     post network requests and receive replies
     99    send network requests and receive replies
    99100    \since 4.4
    100101
     102    \ingroup network
    101103    \inmodule QtNetwork
    102104    \reentrant
     
    113115    QNetworkReply object. The returned object is used to obtain any data
    114116    returned in response to the corresponding request.
    115     the reply to is where most of the signals as well
    116     as the downloaded data are posted.
    117117
    118118    A simple download off the network could be accomplished with:
     
    123123    as well as meta-data (headers, etc.).
    124124
    125     \note The slot is responsible for deleting the object at that point.
     125    \note After the request has finished, it is the responsibility of the user
     126    to delete the QNetworkReply object at an appropriate time. Do not directly
     127    delete it inside the slot connected to finished(). You can use the
     128    deleteLater() function.
    126129
    127130    A more involved example, assuming the manager is already existent,
     
    148151    \value PostOperation        send the contents of an HTML form for
    149152    processing via HTTP POST (created with post())
     153
     154    \value DeleteOperation      delete contents operation (created with
     155    deleteResource())
    150156
    151157    \omitvalue UnknownOperation
     
    200206    See QNetworkReply::finished() for information on the status that
    201207    the object will be in.
     208
     209    \note Do not delete the \a reply object in the slot connected to this
     210    signal. Use deleteLater().
    202211
    203212    \sa QNetworkReply::finished(), QNetworkReply::error()
     
    300309    case QNetworkProxy::FtpCachingProxy:
    301310        key.setScheme(QLatin1String("proxy-ftp"));
     311        break;
    302312
    303313    case QNetworkProxy::DefaultProxy:
     
    478488        delete d->networkCache;
    479489        d->networkCache = cache;
    480         d->networkCache->setParent(this);
     490        if (d->networkCache)
     491            d->networkCache->setParent(this);
    481492    }
    482493}
     
    538549
    539550/*!
    540     This function is used to post a request to obtain the network
    541     headers for \a request. It takes its name after the HTTP request
    542     associated (HEAD). It returns a new QNetworkReply object which
    543     will contain such headers.
     551    Posts a request to obtain the network headers for \a request
     552    and returns a new QNetworkReply object which will contain such headers
     553
     554    The function is named after the HTTP request associated (HEAD).
    544555*/
    545556QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
     
    549560
    550561/*!
    551     This function is used to post a request to obtain the contents of
    552     the target \a request. It will cause the contents to be
    553     downloaded, along with the headers associated with it. It returns
    554     a new QNetworkReply object opened for reading which emits its
    555     QIODevice::readyRead() signal whenever new data arrives.
    556 
    557     \sa post(), put()
     562    Posts a request to obtain the contents of the target \a request
     563    and returns a new QNetworkReply object opened for reading which emits the
     564    \l{QIODevice::readyRead()}{readyRead()} signal whenever new data
     565    arrives.
     566
     567    The contents as well as associated headers will be downloaded.
     568
     569    \sa post(), put(), deleteResource()
    558570*/
    559571QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
     
    563575
    564576/*!
    565     This function is used to send an HTTP POST request to the
    566     destination specified by \a request. The contents of the \a data
     577    Sends an HTTP POST request to the destination specified by \a request
     578    and returns a new QNetworkReply object opened for reading that will
     579    contain the reply sent by the server. The contents of  the \a data
    567580    device will be uploaded to the server.
     581
     582    \a data must be open for reading and must remain valid until the
     583    finished() signal is emitted for this reply.
     584
     585    \note Sending a POST request on protocols other than HTTP and
     586    HTTPS is undefined and will probably fail.
     587
     588    \sa get(), put(), deleteResource()
     589*/
     590QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
     591{
     592    return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
     593}
     594
     595/*!
     596    \overload
     597
     598    Sends the contents of the \a data byte array to the destination
     599    specified by \a request.
     600*/
     601QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
     602{
     603    QBuffer *buffer = new QBuffer;
     604    buffer->setData(data);
     605    buffer->open(QIODevice::ReadOnly);
     606
     607    QNetworkReply *reply = post(request, buffer);
     608    buffer->setParent(reply);
     609    return reply;
     610}
     611
     612/*!
     613    Uploads the contents of \a data to the destination \a request and
     614    returnes a new QNetworkReply object that will be open for reply.
    568615
    569616    \a data must be opened for reading when this function is called
     
    571618    this reply.
    572619
    573     The returned QNetworkReply object will be open for reading and
    574     will contain the reply sent by the server to the POST request.
    575 
    576     Note: sending a POST request on protocols other than HTTP and
    577     HTTPS is undefined and will probably fail.
    578 
    579     \sa get(), put()
    580 */
    581 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
    582 {
    583     return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
     620    Whether anything will be available for reading from the returned
     621    object is protocol dependent. For HTTP, the server may send a
     622    small HTML page indicating the upload was successful (or not).
     623    Other protocols will probably have content in their replies.
     624
     625    \note For HTTP, this request will send a PUT request, which most servers
     626    do not allow. Form upload mechanisms, including that of uploading
     627    files through HTML forms, use the POST mechanism.
     628
     629    \sa get(), post()
     630*/
     631QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
     632{
     633    return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
    584634}
    585635
    586636/*!
    587637    \overload
    588     This function sends the contents of the \a data byte array to the
    589     destination specified by \a request.
    590 */
    591 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
     638    Sends the contents of the \a data byte array to the destination
     639    specified by \a request.
     640*/
     641QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
    592642{
    593643    QBuffer *buffer = new QBuffer;
     
    595645    buffer->open(QIODevice::ReadOnly);
    596646
    597     QNetworkReply *reply = post(request, buffer);
    598     buffer->setParent(reply);
    599     return reply;
    600 }
    601 
    602 /*!
    603     This function is used to upload the contents of \a data to the
    604     destination \a request.
    605 
    606     \a data must be opened for reading when this function is called
    607     and must remain valid until the finished() signal is emitted for
    608     this reply.
    609 
    610     The returned QNetworkReply object will be open for reply, but
    611     whether anything will be available for reading is protocol
    612     dependent. For HTTP, the server may send a small HTML page
    613     indicating the upload was successful (or not). Other protocols
    614     will probably have content in their replies.
    615 
    616     For HTTP, this request will send a PUT request, which most servers
    617     do not allow. Form upload mechanisms, including that of uploading
    618     files through HTML forms, use the POST mechanism.
    619 
    620     \sa get(), post()
    621 */
    622 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
    623 {
    624     return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
    625 }
    626 
    627 /*!
    628     \overload
    629     This function sends the contents of the \a data byte array to the
    630     destination specified by \a request.
    631 */
    632 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
    633 {
    634     QBuffer *buffer = new QBuffer;
    635     buffer->setData(data);
    636     buffer->open(QIODevice::ReadOnly);
    637 
    638647    QNetworkReply *reply = put(request, buffer);
    639648    buffer->setParent(reply);
    640649    return reply;
     650}
     651
     652/*!
     653    \since 4.6
     654
     655    Sends a request to delete the resource identified by the URL of \a request.
     656
     657    \note This feature is currently available for HTTP only, performing an
     658    HTTP DELETE request.
     659
     660    \sa get(), post(), put()
     661*/
     662QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
     663{
     664    return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
    641665}
    642666
     
    659683{
    660684    Q_D(QNetworkAccessManager);
     685
     686    // fast path for GET on file:// URLs
     687    // Also if the scheme is empty we consider it a file.
     688    // The QNetworkAccessFileBackend will right now only be used
     689    // for PUT or qrc://
     690    if (op == QNetworkAccessManager::GetOperation
     691         && (req.url().scheme() == QLatin1String("file")
     692             || req.url().scheme().isEmpty())) {
     693        return new QFileNetworkReply(this, req);
     694    }
     695
    661696    QNetworkRequest request = req;
    662697    if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() &&
     
    686721    }
    687722
    688     // third step: setup the reply
     723    // third step: find a backend
     724    priv->backend = d->findBackend(op, request);
     725
     726    // fourth step: setup the reply
    689727    priv->setup(op, request, outgoingData);
    690     if (request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt() !=
    691         QNetworkRequest::AlwaysNetwork)
    692         priv->setNetworkCache(d->networkCache);
    693728#ifndef QT_NO_NETWORKPROXY
    694729    QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url()));
    695730    priv->proxyList = proxyList;
    696731#endif
    697 
    698     // fourth step: find a backend
    699     priv->backend = d->findBackend(op, request);
    700732    if (priv->backend) {
    701733        priv->backend->setParent(reply);
     
    748780        // keep the ugly hack in here
    749781        QNetworkAccessManagerPrivate *that = const_cast<QNetworkAccessManagerPrivate *>(this);
     782        that->cookieJar = new QNetworkCookieJar(that->q_func());
    750783        that->cookieJarCreated = true;
    751         that->cookieJar = new QNetworkCookieJar(that->q_func());
    752784    }
    753785}
     
    784816{
    785817    Q_Q(QNetworkAccessManager);
    786 
     818    // ### FIXME Tracking of successful authentications
     819    // This code is a bit broken right now for SOCKS authentication
     820    // first request: proxyAuthenticationRequired gets emitted, credentials gets saved
     821    // second request: (proxy != backend->reply->lastProxyAuthentication) does not evaluate to true,
     822    //      proxyAuthenticationRequired gets emitted again
     823    // possible solution: some tracking inside the authenticator
     824    //      or a new function proxyAuthenticationSucceeded(true|false)
    787825    if (proxy != backend->reply->lastProxyAuthentication) {
    788826        QNetworkAuthenticationCredential *cred = fetchCachedCredentials(proxy);
     
    819857            QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache;
    820858            auth->insert(QString(), authenticator->user(), authenticator->password());
    821             cache.addEntry(cacheKey, auth); // replace the existing one, if there's any
     859            objectCache.addEntry(cacheKey, auth); // replace the existing one, if there's any
    822860
    823861            if (realm.isEmpty()) {
     
    853891    if (cacheKey.isEmpty())
    854892        return 0;
    855     if (!cache.hasEntry(cacheKey))
     893    if (!objectCache.hasEntry(cacheKey))
    856894        return 0;
    857895
    858896    QNetworkAuthenticationCache *auth =
    859         static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey));
     897        static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
    860898    QNetworkAuthenticationCredential *cred = auth->findClosestMatch(QString());
    861     cache.releaseEntry(cacheKey);
     899    objectCache.releaseEntry(cacheKey);
    862900
    863901    // proxy cache credentials always have exactly one item
     
    900938    do {
    901939        QByteArray cacheKey = authenticationKey(copy, realm);
    902         if (cache.hasEntry(cacheKey)) {
     940        if (objectCache.hasEntry(cacheKey)) {
    903941            QNetworkAuthenticationCache *auth =
    904                 static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey));
     942                static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
    905943            auth->insert(domain, authenticator->user(), authenticator->password());
    906             cache.releaseEntry(cacheKey);
     944            objectCache.releaseEntry(cacheKey);
    907945        } else {
    908946            QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache;
    909947            auth->insert(domain, authenticator->user(), authenticator->password());
    910             cache.addEntry(cacheKey, auth);
     948            objectCache.addEntry(cacheKey, auth);
    911949        }
    912950
     
    942980
    943981    QByteArray cacheKey = authenticationKey(url, realm);
    944     if (!cache.hasEntry(cacheKey))
     982    if (!objectCache.hasEntry(cacheKey))
    945983        return 0;
    946984
    947985    QNetworkAuthenticationCache *auth =
    948         static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey));
     986        static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
    949987    QNetworkAuthenticationCredential *cred = auth->findClosestMatch(url.path());
    950     cache.releaseEntry(cacheKey);
     988    objectCache.releaseEntry(cacheKey);
    951989    return cred;
    952990}
     
    954992void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager)
    955993{
    956     manager->d_func()->cache.clear();
     994    manager->d_func()->objectCache.clear();
     995}
     996
     997QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
     998{
    957999}
    9581000
  • trunk/src/network/access/qnetworkaccessmanager.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7575        PutOperation,
    7676        PostOperation,
     77        DeleteOperation,
    7778
    7879        UnknownOperation = 0
     
    101102    QNetworkReply *put(const QNetworkRequest &request, QIODevice *data);
    102103    QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data);
     104    QNetworkReply *deleteResource(const QNetworkRequest &request);
    103105
    104106Q_SIGNALS:
  • trunk/src/network/access/qnetworkaccessmanager_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7777          cookieJarCreated(false)
    7878    { }
     79    ~QNetworkAccessManagerPrivate();
    7980
    8081    void _q_replyFinished();
     
    99100    QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request);
    100101
     102    // this is the cache for storing downloaded files
    101103    QAbstractNetworkCache *networkCache;
     104
    102105    QNetworkCookieJar *cookieJar;
    103106
    104     QNetworkAccessCache cache;
     107
    105108#ifndef QT_NO_NETWORKPROXY
    106109    QNetworkProxy proxy;
     
    110113    bool cookieJarCreated;
    111114
    112     static inline QNetworkAccessCache *getCache(QNetworkAccessBackend *backend)
    113     { return &backend->manager->cache; }
     115
     116    // this cache can be used by individual backends to cache e.g. their TCP connections to a server
     117    // and use the connections for multiple requests.
     118    QNetworkAccessCache objectCache;
     119    static inline QNetworkAccessCache *getObjectCache(QNetworkAccessBackend *backend)
     120    { return &backend->manager->objectCache; }
    114121    Q_AUTOTEST_EXPORT static void clearCache(QNetworkAccessManager *manager);
    115122
  • trunk/src/network/access/qnetworkcookie.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    505505        if (!d->domain.isEmpty()) {
    506506            result += "; domain=";
    507             result += QUrl::toAce(d->domain);
     507            QString domainNoDot = d->domain;
     508            if (domainNoDot.startsWith(QLatin1Char('.'))) {
     509                result += '.';
     510                domainNoDot = domainNoDot.mid(1);
     511            }
     512            result += QUrl::toAce(domainNoDot);
    508513        }
    509514        if (!d->path.isEmpty()) {
     
    914919QList<QNetworkCookie> QNetworkCookie::parseCookies(const QByteArray &cookieString)
    915920{
     921    // cookieString can be a number of set-cookie header strings joined together
     922    // by \n, parse each line separately.
     923    QList<QNetworkCookie> cookies;
     924    QList<QByteArray> list = cookieString.split('\n');
     925    for (int a = 0; a < list.size(); a++)
     926        cookies += QNetworkCookiePrivate::parseSetCookieHeaderLine(list.at(a));
     927    return cookies;
     928}
     929
     930QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByteArray &cookieString)
     931{
    916932    // According to http://wp.netscape.com/newsref/std/cookie_spec.html,<
    917933    // the Set-Cookie response header is of the format:
     
    931947        QNetworkCookie cookie;
    932948
    933         // When there are multiple SetCookie headers they are join with a new line
    934         // \n will always be the start of a new cookie
    935         int endOfSetCookie = cookieString.indexOf('\n', position);
    936         if (endOfSetCookie == -1)
    937             endOfSetCookie = length;
    938 
    939949        // The first part is always the "NAME=VALUE" part
    940950        QPair<QByteArray,QByteArray> field = nextField(cookieString, position);
     
    947957        position = nextNonWhitespace(cookieString, position);
    948958        bool endOfCookie = false;
    949         while (!endOfCookie && position < endOfSetCookie)
     959        while (!endOfCookie && position < length) {
    950960            switch (cookieString.at(position++)) {
    951961            case ',':
     
    970980                    QDateTime dt = parseDateString(dateString.toLower());
    971981                    if (!dt.isValid()) {
    972                         cookie = QNetworkCookie();
    973                         endOfCookie = true;
    974                         continue;
     982                        return result;
    975983                    }
    976984                    cookie.setExpirationDate(dt);
     
    989997                    int secs = field.second.toInt(&ok);
    990998                    if (!ok)
    991                         // invalid cookie string
    992                         return QList<QNetworkCookie>();
     999                        return result;
    9931000                    cookie.setExpirationDate(now.addSecs(secs));
    9941001                } else if (field.first == "path") {
     
    10041011                    if (field.second != "1") {
    10051012                        // oops, we don't know how to handle this cookie
    1006                         cookie = QNetworkCookie();
    1007                         endOfCookie = true;
    1008                         continue;
     1013                        return result;
    10091014                    }
    10101015                } else {
     
    10141019
    10151020                position = nextNonWhitespace(cookieString, position);
    1016                 if (position > endOfSetCookie)
    1017                     endOfCookie = true;
    10181021            }
     1022        }
    10191023
    10201024        if (!cookie.name().isEmpty())
     
    10281032QDebug operator<<(QDebug s, const QNetworkCookie &cookie)
    10291033{
    1030     s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ")";
     1034    s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ')';
    10311035    return s.space();
    10321036}
    10331037#endif
    10341038
    1035 
    1036 
    1037 class QNetworkCookieJarPrivate: public QObjectPrivate
    1038 {
    1039 public:
    1040     QList<QNetworkCookie> allCookies;
    1041 
    1042     Q_DECLARE_PUBLIC(QNetworkCookieJar)
    1043 };
    1044 
    1045 /*!
    1046     \class QNetworkCookieJar
    1047     \brief The QNetworkCookieJar class implements a simple jar of QNetworkCookie objects
    1048     \since 4.4
    1049 
    1050     Cookies are small bits of information that stateless protocols
    1051     like HTTP use to maintain some persistent information across
    1052     requests.
    1053 
    1054     A cookie is set by a remote server when it replies to a request
    1055     and it expects the same cookie to be sent back when further
    1056     requests are sent.
    1057 
    1058     The cookie jar is the object that holds all cookies set in
    1059     previous requests. Web browsers save their cookie jars to disk in
    1060     order to conserve permanent cookies across invocations of the
    1061     application.
    1062 
    1063     QNetworkCookieJar does not implement permanent storage: it only
    1064     keeps the cookies in memory. Once the QNetworkCookieJar object is
    1065     deleted, all cookies it held will be discarded as well. If you
    1066     want to save the cookies, you should derive from this class and
    1067     implement the saving to disk to your own storage format.
    1068 
    1069     This class implements only the basic security recommended by the
    1070     cookie specifications and does not implement any cookie acceptance
    1071     policy (it accepts all cookies set by any requests). In order to
    1072     override those rules, you should reimplement the
    1073     cookiesForUrl() and setCookiesFromUrl() virtual
    1074     functions. They are called by QNetworkReply and
    1075     QNetworkAccessManager when they detect new cookies and when they
    1076     require cookies.
    1077 
    1078     \sa QNetworkCookie, QNetworkAccessManager, QNetworkReply,
    1079     QNetworkRequest, QNetworkAccessManager::setCookieJar()
    1080 */
    1081 
    1082 /*!
    1083     Creates a QNetworkCookieJar object and sets the parent object to
    1084     be \a parent.
    1085 
    1086     The cookie jar is initialized to empty.
    1087 */
    1088 QNetworkCookieJar::QNetworkCookieJar(QObject *parent)
    1089     : QObject(*new QNetworkCookieJarPrivate, parent)
    1090 {
    1091 }
    1092 
    1093 /*!
    1094     Destroys this cookie jar object and discards all cookies stored in
    1095     it. Cookies are not saved to disk in the QNetworkCookieJar default
    1096     implementation.
    1097 
    1098     If you need to save the cookies to disk, you have to derive from
    1099     QNetworkCookieJar and save the cookies to disk yourself.
    1100 */
    1101 QNetworkCookieJar::~QNetworkCookieJar()
    1102 {
    1103 }
    1104 
    1105 /*!
    1106     Returns all cookies stored in this cookie jar. This function is
    1107     suitable for derived classes to save cookies to disk, as well as
    1108     to implement cookie expiration and other policies.
    1109 
    1110     \sa setAllCookies(), cookiesForUrl()
    1111 */
    1112 QList<QNetworkCookie> QNetworkCookieJar::allCookies() const
    1113 {
    1114     return d_func()->allCookies;
    1115 }
    1116 
    1117 /*!
    1118     Sets the internal list of cookies held by this cookie jar to be \a
    1119     cookieList. This function is suitable for derived classes to
    1120     implement loading cookies from permanent storage, or their own
    1121     cookie acceptance policies by reimplementing
    1122     setCookiesFromUrl().
    1123 
    1124     \sa allCookies(), setCookiesFromUrl()
    1125 */
    1126 void QNetworkCookieJar::setAllCookies(const QList<QNetworkCookie> &cookieList)
    1127 {
    1128     Q_D(QNetworkCookieJar);
    1129     d->allCookies = cookieList;
    1130 }
    1131 
    1132 static inline bool isParentPath(QString path, QString reference)
    1133 {
    1134     if (!path.endsWith(QLatin1Char('/')))
    1135         path += QLatin1Char('/');
    1136     if (!reference.endsWith(QLatin1Char('/')))
    1137         reference += QLatin1Char('/');
    1138     return path.startsWith(reference);
    1139 }
    1140 
    1141 static inline bool isParentDomain(QString domain, QString reference)
    1142 {
    1143     if (!reference.startsWith(QLatin1Char('.')))
    1144         return domain == reference;
    1145 
    1146     return domain.endsWith(reference) || domain == reference.mid(1);
    1147 }
    1148 
    1149 /*!
    1150     Adds the cookies in the list \a cookieList to this cookie
    1151     jar. Default values for path and domain are taken from the \a
    1152     url object.
    1153 
    1154     Returns true if one or more cookes are set for url otherwise false.
    1155 
    1156     If a cookie already exists in the cookie jar, it will be
    1157     overridden by those in \a cookieList.
    1158 
    1159     The default QNetworkCookieJar class implements only a very basic
    1160     security policy (it makes sure that the cookies' domain and path
    1161     match the reply's). To enhance the security policy with your own
    1162     algorithms, override setCookiesFromUrl().
    1163 
    1164     Also, QNetworkCookieJar does not have a maximum cookie jar
    1165     size. Reimplement this function to discard older cookies to create
    1166     room for new ones.
    1167 
    1168     \sa cookiesForUrl(), QNetworkAccessManager::setCookieJar()
    1169 */
    1170 bool QNetworkCookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList,
    1171                                           const QUrl &url)
    1172 {
    1173     Q_D(QNetworkCookieJar);
    1174     QString defaultDomain = url.host();
    1175     QString pathAndFileName = url.path();
    1176     QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(QLatin1Char('/'))+1);
    1177     if (defaultPath.isEmpty())
    1178         defaultPath = QLatin1Char('/');
    1179 
    1180     int added = 0;
    1181     QDateTime now = QDateTime::currentDateTime();
    1182     foreach (QNetworkCookie cookie, cookieList) {
    1183         bool isDeletion = !cookie.isSessionCookie() &&
    1184                           cookie.expirationDate() < now;
    1185 
    1186         // validate the cookie & set the defaults if unset
    1187         // (RFC 2965: "The request-URI MUST path-match the Path attribute of the cookie.")
    1188         if (cookie.path().isEmpty())
    1189             cookie.setPath(defaultPath);
    1190         else if (!isParentPath(pathAndFileName, cookie.path()))
    1191             continue;           // not accepted
    1192 
    1193         if (cookie.domain().isEmpty()) {
    1194             cookie.setDomain(defaultDomain);
    1195         } else {
    1196             QString domain = cookie.domain();
    1197             if (!(isParentDomain(domain, defaultDomain)
    1198                 || isParentDomain(defaultDomain, domain))) {
    1199                     continue;           // not accepted
    1200             }
    1201         }
    1202 
    1203         QList<QNetworkCookie>::Iterator it = d->allCookies.begin(),
    1204                                        end = d->allCookies.end();
    1205         for ( ; it != end; ++it)
    1206             // does this cookie already exist?
    1207             if (cookie.name() == it->name() &&
    1208                 cookie.domain() == it->domain() &&
    1209                 cookie.path() == it->path()) {
    1210                 // found a match
    1211                 d->allCookies.erase(it);
    1212                 break;
    1213             }
    1214 
    1215         // did not find a match
    1216         if (!isDeletion) {
    1217             d->allCookies += cookie;
    1218             ++added;
    1219         }
    1220     }
    1221     return (added > 0);
    1222 }
    1223 
    1224 /*!
    1225     Returns the cookies to be added to when a request is sent to
    1226     \a url. This function is called by the default
    1227     QNetworkAccessManager::createRequest(), which adds the
    1228     cookies returned by this function to the request being sent.
    1229 
    1230     If more than one cookie with the same name is found, but with
    1231     differing paths, the one with longer path is returned before the
    1232     one with shorter path. In other words, this function returns
    1233     cookies sorted by path length.
    1234 
    1235     The default QNetworkCookieJar class implements only a very basic
    1236     security policy (it makes sure that the cookies' domain and path
    1237     match the reply's). To enhance the security policy with your own
    1238     algorithms, override cookiesForUrl().
    1239 
    1240     \sa setCookiesFromUrl(), QNetworkAccessManager::setCookieJar()
    1241 */
    1242 QList<QNetworkCookie> QNetworkCookieJar::cookiesForUrl(const QUrl &url) const
    1243 {
    1244 //     \b Warning! This is only a dumb implementation!
    1245 //     It does NOT follow all of the recommendations from
    1246 //     http://wp.netscape.com/newsref/std/cookie_spec.html
    1247 //     It does not implement a very good cross-domain verification yet.
    1248 
    1249     Q_D(const QNetworkCookieJar);
    1250     QDateTime now = QDateTime::currentDateTime();
    1251     QList<QNetworkCookie> result;
    1252 
    1253     // scan our cookies for something that matches
    1254     QList<QNetworkCookie>::ConstIterator it = d->allCookies.constBegin(),
    1255                                         end = d->allCookies.constEnd();
    1256     for ( ; it != end; ++it) {
    1257         if (!isParentDomain(url.host(), it->domain()))
    1258             continue;
    1259         if (!isParentPath(url.path(), it->path()))
    1260             continue;
    1261         if (!(*it).isSessionCookie() && (*it).expirationDate() < now)
    1262             continue;
    1263 
    1264         // insert this cookie into result, sorted by path
    1265         QList<QNetworkCookie>::Iterator insertIt = result.begin();
    1266         while (insertIt != result.end()) {
    1267             if (insertIt->path().length() < it->path().length()) {
    1268                 // insert here
    1269                 insertIt = result.insert(insertIt, *it);
    1270                 break;
    1271             } else {
    1272                 ++insertIt;
    1273             }
    1274         }
    1275 
    1276         // this is the shortest path yet, just append
    1277         if (insertIt == result.end())
    1278             result += *it;
    1279     }
    1280 
    1281     return result;
    1282 }
    1283 
    12841039QT_END_NAMESPACE
  • trunk/src/network/access/qnetworkcookie.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    107107Q_DECLARE_TYPEINFO(QNetworkCookie, Q_MOVABLE_TYPE);
    108108
    109 class QNetworkCookieJarPrivate;
    110 class Q_NETWORK_EXPORT QNetworkCookieJar: public QObject
    111 {
    112     Q_OBJECT
    113 public:
    114     QNetworkCookieJar(QObject *parent = 0);
    115     virtual ~QNetworkCookieJar();
    116 
    117     virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
    118     virtual bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
    119 
    120 protected:
    121     QList<QNetworkCookie> allCookies() const;
    122     void setAllCookies(const QList<QNetworkCookie> &cookieList);
    123 
    124 private:
    125     Q_DECLARE_PRIVATE(QNetworkCookieJar)
    126     Q_DISABLE_COPY(QNetworkCookieJar)
    127 };
    128 
    129109#ifndef QT_NO_DEBUG_STREAM
    130110class QDebug;
     
    134114QT_END_NAMESPACE
    135115
     116// ### Qt5 remove this include
     117#include "qnetworkcookiejar.h"
     118
    136119Q_DECLARE_METATYPE(QNetworkCookie)
    137120Q_DECLARE_METATYPE(QList<QNetworkCookie>)
  • trunk/src/network/access/qnetworkcookie_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6262public:
    6363    inline QNetworkCookiePrivate() : secure(false), httpOnly(false) { }
     64    static QList<QNetworkCookie> parseSetCookieHeaderLine(const QByteArray &cookieString);
    6465
    6566    QDateTime expirationDate;
  • trunk/src/network/access/qnetworkdiskcache.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4141
    4242//#define QNETWORKDISKCACHE_DEBUG
     43
     44#ifndef QT_NO_NETWORKDISKCACHE
    4345
    4446#include "qnetworkdiskcache.h"
    4547#include "qnetworkdiskcache_p.h"
     48#include "QtCore/qscopedpointer.h"
    4649
    4750#include <qfile.h>
     
    8083
    8184    Note you have to set the cache directory before it will work.
     85
     86    A network disk cache can be enabled by:
     87
     88    \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 0
     89
     90    When sending requests, to control the preference of when to use the cache
     91    and when to use the network, consider the following:
     92
     93    \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 1
     94
     95    To check whether the response came from the cache or from the network, the
     96    following can be applied:
     97
     98    \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 2
    8299*/
    83100
     
    181198        }
    182199    }
    183 
    184     QCacheItem *cacheItem = new QCacheItem;
     200    QScopedPointer<QCacheItem> cacheItem(new QCacheItem);
    185201    cacheItem->metaData = metaData;
    186202
     
    191207    } else {
    192208        QString templateName = d->tmpCacheFileName();
    193         cacheItem->file = new QTemporaryFile(templateName, &cacheItem->data);
    194         cacheItem->file->open();
     209        QT_TRY {
     210            cacheItem->file = new QTemporaryFile(templateName, &cacheItem->data);
     211        } QT_CATCH(...) {
     212            cacheItem->file = 0;
     213        }
     214        if (!cacheItem->file || !cacheItem->file->open()) {
     215            qWarning() << "QNetworkDiskCache::prepare() unable to open temporary file";
     216            cacheItem.reset();
     217            return 0;
     218        }
    195219        cacheItem->writeHeader(cacheItem->file);
    196220        device = cacheItem->file;
    197221    }
    198     d->inserting[device] = cacheItem;
     222    d->inserting[device] = cacheItem.take();
    199223    return device;
    200224}
     
    230254    if (QFile::exists(fileName)) {
    231255        if (!QFile::remove(fileName)) {
    232             qWarning() << "QNetworkDiskCache: could't remove the cache file " << fileName;
     256            qWarning() << "QNetworkDiskCache: couldn't remove the cache file " << fileName;
    233257            return;
    234258        }
     
    355379#endif
    356380    Q_D(QNetworkDiskCache);
    357     QBuffer *buffer = 0;
     381    QScopedPointer<QBuffer> buffer;
    358382    if (!url.isValid())
    359         return buffer;
     383        return 0;
    360384    if (d->lastItem.metaData.url() == url && d->lastItem.data.isOpen()) {
    361         buffer = new QBuffer;
     385        buffer.reset(new QBuffer);
    362386        buffer->setData(d->lastItem.data.data());
    363387    } else {
    364         QFile *file = new QFile(d->cacheFileName(url));
    365         if (!file->open(QFile::ReadOnly | QIODevice::Unbuffered)) {
    366             delete file;
     388        QScopedPointer<QFile> file(new QFile(d->cacheFileName(url)));
     389        if (!file->open(QFile::ReadOnly | QIODevice::Unbuffered))
    367390            return 0;
    368         }
    369         if (!d->lastItem.read(file, true)) {
     391
     392        if (!d->lastItem.read(file.data(), true)) {
    370393            file->close();
    371394            remove(url);
    372             delete file;
    373395            return 0;
    374396        }
    375397        if (d->lastItem.data.isOpen()) {
    376398            // compressed
    377             buffer = new QBuffer;
     399            buffer.reset(new QBuffer);
    378400            buffer->setData(d->lastItem.data.data());
    379             delete file;
    380401        } else {
    381             buffer = new QBuffer;
     402            buffer.reset(new QBuffer);
    382403            // ### verify that QFile uses the fd size and not the file name
    383404            qint64 size = file->size() - file->pos();
     
    387408#endif
    388409            if (p) {
    389                 file->setParent(buffer);
    390410                buffer->setData((const char *)p, size);
     411                file.take()->setParent(buffer.data());
    391412            } else {
    392413                buffer->setData(file->readAll());
    393                 delete file;
    394414            }
    395415        }
    396416    }
    397417    buffer->open(QBuffer::ReadOnly);
    398     return buffer;
     418    return buffer.take();
    399419}
    400420
     
    463483    Returns the current size of the cache.
    464484
    465     When the current size of the cache is greater then the maximumCacheSize()
     485    When the current size of the cache is greater than the maximumCacheSize()
    466486    older cache files are removed until the total size is less then 90% of
    467487    maximumCacheSize() starting with the oldest ones first using the file
     
    491511    QDirIterator it(cacheDirectory(), filters, QDirIterator::Subdirectories);
    492512
    493     QMap<QDateTime, QString> cacheItems;
     513    QMultiMap<QDateTime, QString> cacheItems;
    494514    qint64 totalSize = 0;
    495515    while (it.hasNext()) {
     
    498518        QString fileName = info.fileName();
    499519        if (fileName.endsWith(CACHE_POSTFIX) && fileName.startsWith(CACHE_PREFIX)) {
    500             cacheItems[info.created()] = path;
     520            cacheItems.insert(info.created(), path);
    501521            totalSize += info.size();
    502522        }
     
    505525    int removedFiles = 0;
    506526    qint64 goal = (maximumCacheSize() * 9) / 10;
    507     QMap<QDateTime, QString>::const_iterator i = cacheItems.constBegin();
     527    QMultiMap<QDateTime, QString>::const_iterator i = cacheItems.constBegin();
    508528    while (i != cacheItems.constEnd()) {
    509529        if (totalSize < goal)
     
    666686
    667687QT_END_NAMESPACE
     688
     689#endif // QT_NO_NETWORKDISKCACHE
  • trunk/src/network/access/qnetworkdiskcache.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5050
    5151QT_MODULE(Network)
     52
     53#ifndef QT_NO_NETWORKDISKCACHE
    5254
    5355class QNetworkDiskCachePrivate;
     
    8789};
    8890
     91#endif // QT_NO_NETWORKDISKCACHE
     92
    8993QT_END_NAMESPACE
    9094
     
    9296
    9397#endif // QNETWORKDISKCACHE_H
    94 
  • trunk/src/network/access/qnetworkdiskcache_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/access/qnetworkreply.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6060    \since 4.4
    6161    \brief The QNetworkReply class contains the data and headers for a request
    62     posted with QNetworkAccessManager
     62    sent with QNetworkAccessManager
    6363
    6464    \reentrant
     65    \ingroup network
    6566    \inmodule QtNetwork
    6667
     
    8889    content.
    8990
     91    \note Do not delete the object in the slot connected to the
     92    error() or finished() signal. Use deleteLater().
     93
    9094    \sa QNetworkRequest, QNetworkAccessManager
    9195*/
     
    152156    were not accepted (if any)
    153157
     158    \value ContentReSendError          the request needed to be sent
     159    again, but this failed for example because the upload data
     160    could not be read a second time.
     161
    154162    \value ProtocolUnknownError         the Network Access API cannot
    155163    honor the request because the protocol is not known
     
    164172    was detected
    165173
    166     \value UnknownContentError          an unknonwn error related to
     174    \value UnknownContentError          an unknown error related to
    167175    the remote content was detected
    168176
     
    229237    parameter is this object.
    230238
     239    \note Do not delete the object in the slot connected to this
     240    signal. Use deleteLater().
     241
    231242    \sa QNetworkAccessManager::finished()
    232243*/
     
    242253    detected. Call errorString() to obtain a textual representation of
    243254    the error condition.
     255
     256    \note Do not delete the object in the slot connected to this
     257    signal. Use deleteLater().
    244258
    245259    \sa error(), errorString()
     
    436450{
    437451    return d_func()->errorCode;
     452}
     453
     454/*!
     455    \since 4.6
     456
     457    Returns true when the reply has finished or was aborted.
     458
     459    \sa isRunning()
     460*/
     461bool QNetworkReply::isFinished() const
     462{
     463    return d_func()->isFinished();
     464}
     465
     466/*!
     467    \since 4.6
     468
     469    Returns true when the request is still processing and the
     470    reply has not finished or was aborted yet.
     471
     472    \sa isFinished()
     473*/
     474bool QNetworkReply::isRunning() const
     475{
     476    return !isFinished();
    438477}
    439478
     
    556595    }
    557596}
     597
     598/*!
     599    \overload
     600    \since 4.6
     601
     602    If this function is called, the SSL errors given in \a errors
     603    will be ignored.
     604
     605    Note that you can set the expected certificate in the SSL error:
     606    If, for instance, you want to issue a request to a server that uses
     607    a self-signed certificate, consider the following snippet:
     608
     609    \snippet doc/src/snippets/code/src_network_access_qnetworkreply.cpp 0
     610
     611    Multiple calls to this function will replace the list of errors that
     612    were passed in previous calls.
     613    You can clear the list of errors you want to ignore by calling this
     614    function with an empty list.
     615
     616    \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
     617*/
     618void QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
     619{
     620    // do this cryptic trick, because we could not add a virtual method to this class later on
     621    // since that breaks binary compatibility
     622    int id = metaObject()->indexOfMethod("ignoreSslErrorsImplementation(QList<QSslError>)");
     623    if (id != -1) {
     624        QList<QSslError> copy(errors);
     625        void *arr[] = { 0, &copy };
     626        qt_metacall(QMetaObject::InvokeMetaMethod, id, arr);
     627    }
     628}
    558629#endif
    559630
     
    570641    found.
    571642
    572     \sa sslConfiguration(), sslErrors()
     643    \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
    573644*/
    574645void QNetworkReply::ignoreSslErrors()
  • trunk/src/network/access/qnetworkreply.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    9393        ContentNotFoundError,
    9494        AuthenticationRequiredError,
     95        ContentReSendError,
    9596        UnknownContentError = 299,
    9697
     
    116117    QNetworkRequest request() const;
    117118    NetworkError error() const;
     119    bool isFinished() const;
     120    bool isRunning() const;
    118121    QUrl url() const;
    119122
     
    132135    QSslConfiguration sslConfiguration() const;
    133136    void setSslConfiguration(const QSslConfiguration &configuration);
     137    void ignoreSslErrors(const QList<QSslError> &errors);
    134138#endif
    135139
  • trunk/src/network/access/qnetworkreply_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7676    { reply->d_func()->manager = manager; }
    7777
     78    virtual bool isFinished() const { return false; }
     79
    7880    Q_DECLARE_PUBLIC(QNetworkReply)
    7981};
  • trunk/src/network/access/qnetworkreplyimpl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747#include "QtCore/qdatetime.h"
    4848#include "QtNetwork/qsslconfiguration.h"
     49#include "qnetworkaccesshttpbackend_p.h"
    4950
    5051#include <QtCore/QCoreApplication>
     
    5354
    5455inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate()
    55     : copyDevice(0), networkCache(0),
     56    : backend(0), outgoingData(0), outgoingDataBuffer(0),
     57      copyDevice(0),
    5658      cacheEnabled(false), cacheSaveDevice(0),
     59      notificationHandlingPaused(false),
    5760      bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1),
     61      httpStatusCode(0),
    5862      state(Idle)
    5963{
     
    6266void QNetworkReplyImplPrivate::_q_startOperation()
    6367{
    64     // This function is called exactly once
     68    // ensure this function is only being called once
     69    if (state == Working) {
     70        qDebug("QNetworkReplyImpl::_q_startOperation was called more than once");
     71        return;
     72    }
    6573    state = Working;
     74
    6675    if (!backend) {
    6776        error(QNetworkReplyImpl::ProtocolUnknownError,
     
    7584        if (operation == QNetworkAccessManager::GetOperation)
    7685            pendingNotifications.append(NotifyDownstreamReadyWrite);
    77         if (outgoingData) {
    78             _q_sourceReadyRead();
    79 #if 0 // ### FIXME
    80             if (outgoingData->atEndOfStream() && writeBuffer.isEmpty())
    81                 // empty upload
    82                 emit q->uploadProgress(0, 0);
    83 #endif
    84         }
    8586
    8687        handleNotifications();
     
    8889}
    8990
    90 void QNetworkReplyImplPrivate::_q_sourceReadyRead()
    91 {
    92     // read data from the outgoingData QIODevice into our internal buffer
    93     enum { DesiredBufferSize = 32 * 1024 };
    94 
    95     if (writeBuffer.size() >= DesiredBufferSize)
    96         return;                 // don't grow the buffer too much
    97 
    98     // read as many bytes are available or up until we fill up the buffer
    99     // but always read at least one byte
    100     qint64 bytesToRead = qBound<qint64>(1, outgoingData->bytesAvailable(),
    101                                         DesiredBufferSize - writeBuffer.size());
    102     char *ptr = writeBuffer.reserve(bytesToRead);
    103     qint64 bytesActuallyRead = outgoingData->read(ptr, bytesToRead);
    104     if (bytesActuallyRead == -1) {
    105         // EOF
    106         writeBuffer.chop(bytesToRead);
    107         backendNotify(NotifyCloseUpstreamChannel);
    108         return;
    109     }
    110 
    111     if (bytesActuallyRead < bytesToRead)
    112         writeBuffer.chop(bytesToRead - bytesActuallyRead);
    113 
    114     // if we did read anything, let the backend know and handle it
    115     if (bytesActuallyRead)
    116         backendNotify(NotifyUpstreamReadyRead);
    117 
    118     // check for EOF again
    119     if (!outgoingData->isSequential() && outgoingData->atEnd())
    120         backendNotify(NotifyCloseUpstreamChannel);
    121 }
    122 
    123 void QNetworkReplyImplPrivate::_q_sourceReadChannelFinished()
    124 {
    125     _q_sourceReadyRead();
    126 }
    127 
    12891void QNetworkReplyImplPrivate::_q_copyReadyRead()
    12992{
    13093    Q_Q(QNetworkReplyImpl);
    131     if (!copyDevice && !q->isOpen())
    132         return;
    133 
    134     qint64 bytesToRead = nextDownstreamBlockSize();
    135     if (bytesToRead == 0)
    136         // we'll be called again, eventually
    137         return;
    138 
    139     bytesToRead = qBound<qint64>(1, bytesToRead, copyDevice->bytesAvailable());
    140     char *ptr = readBuffer.reserve(bytesToRead);
    141     qint64 bytesActuallyRead = copyDevice->read(ptr, bytesToRead);
    142     if (bytesActuallyRead == -1) {
    143         readBuffer.chop(bytesToRead);
    144         backendNotify(NotifyCopyFinished);
    145         return;
    146     }
    147 
    148     if (bytesActuallyRead != bytesToRead)
    149         readBuffer.chop(bytesToRead - bytesActuallyRead);
    150 
    151     if (!copyDevice->isSequential() && copyDevice->atEnd())
    152         backendNotify(NotifyCopyFinished);
    153 
    154     bytesDownloaded += bytesActuallyRead;
     94    if (state != Working)
     95        return;
     96    if (!copyDevice || !q->isOpen())
     97        return;
     98
     99    forever {
     100        qint64 bytesToRead = nextDownstreamBlockSize();
     101        if (bytesToRead == 0)
     102            // we'll be called again, eventually
     103            break;
     104
     105        bytesToRead = qBound<qint64>(1, bytesToRead, copyDevice->bytesAvailable());
     106        QByteArray byteData;
     107        byteData.resize(bytesToRead);
     108        qint64 bytesActuallyRead = copyDevice->read(byteData.data(), byteData.size());
     109        if (bytesActuallyRead == -1) {
     110            byteData.clear();
     111            backendNotify(NotifyCopyFinished);
     112            break;
     113        }
     114
     115        byteData.resize(bytesActuallyRead);
     116        readBuffer.append(byteData);
     117
     118        if (!copyDevice->isSequential() && copyDevice->atEnd()) {
     119            backendNotify(NotifyCopyFinished);
     120            bytesDownloaded += bytesActuallyRead;
     121            break;
     122        }
     123
     124        bytesDownloaded += bytesActuallyRead;
     125    }
     126
     127    if (bytesDownloaded == lastBytesDownloaded) {
     128        // we didn't read anything
     129        return;
     130    }
     131
    155132    lastBytesDownloaded = bytesDownloaded;
    156133    QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
     134    pauseNotificationHandling();
    157135    emit q->downloadProgress(bytesDownloaded,
    158136                             totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
    159137    emit q->readyRead();
     138    resumeNotificationHandling();
    160139}
    161140
     
    164143    _q_copyReadyRead();
    165144}
     145
     146void QNetworkReplyImplPrivate::_q_bufferOutgoingDataFinished()
     147{
     148    Q_Q(QNetworkReplyImpl);
     149
     150    // make sure this is only called once, ever.
     151    //_q_bufferOutgoingData may call it or the readChannelFinished emission
     152    if (state != Buffering)
     153        return;
     154
     155    // disconnect signals
     156    QObject::disconnect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
     157    QObject::disconnect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
     158
     159    // finally, start the request
     160    QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
     161}
     162
     163void QNetworkReplyImplPrivate::_q_bufferOutgoingData()
     164{
     165    Q_Q(QNetworkReplyImpl);
     166
     167    if (!outgoingDataBuffer) {
     168        // first call, create our buffer
     169        outgoingDataBuffer = new QRingBuffer();
     170
     171        QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
     172        QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
     173    }
     174
     175    qint64 bytesBuffered = 0;
     176    qint64 bytesToBuffer = 0;
     177
     178    // read data into our buffer
     179    forever {
     180        bytesToBuffer = outgoingData->bytesAvailable();
     181        // unknown? just try 2 kB, this also ensures we always try to read the EOF
     182        if (bytesToBuffer <= 0)
     183            bytesToBuffer = 2*1024;
     184
     185        char *dst = outgoingDataBuffer->reserve(bytesToBuffer);
     186        bytesBuffered = outgoingData->read(dst, bytesToBuffer);
     187
     188        if (bytesBuffered == -1) {
     189            // EOF has been reached.
     190            outgoingDataBuffer->chop(bytesToBuffer);
     191
     192            _q_bufferOutgoingDataFinished();
     193            break;
     194        } else if (bytesBuffered == 0) {
     195            // nothing read right now, just wait until we get called again
     196            outgoingDataBuffer->chop(bytesToBuffer);
     197
     198            break;
     199        } else {
     200            // don't break, try to read() again
     201            outgoingDataBuffer->chop(bytesToBuffer - bytesBuffered);
     202        }
     203    }
     204}
     205
    166206
    167207void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req,
     
    175215    operation = op;
    176216
    177     if (outgoingData) {
    178         q->connect(outgoingData, SIGNAL(readyRead()), SLOT(_q_sourceReadyRead()));
    179         q->connect(outgoingData, SIGNAL(readChannelFinished()), SLOT(_q_sourceReadChannelFinished()));
     217    if (outgoingData && backend) {
     218        // there is data to be uploaded, e.g. HTTP POST.
     219
     220        if (!backend->needsResetableUploadData() || !outgoingData->isSequential()) {
     221            // backend does not need upload buffering or
     222            // fixed size non-sequential
     223            // just start the operation
     224            QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
     225        } else {
     226            bool bufferingDisallowed =
     227                    req.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
     228                                             false).toBool();
     229
     230            if (bufferingDisallowed) {
     231                // if a valid content-length header for the request was supplied, we can disable buffering
     232                // if not, we will buffer anyway
     233                if (req.header(QNetworkRequest::ContentLengthHeader).isValid()) {
     234                    QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
     235                } else {
     236                    state = Buffering;
     237                    QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection);
     238                }
     239            } else {
     240                // _q_startOperation will be called when the buffering has finished.
     241                state = Buffering;
     242                QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection);
     243            }
     244        }
     245    } else {
     246        // No outgoing data (e.g. HTTP GET request)
     247        // or no backend
     248        // if no backend, _q_startOperation will handle the error of this
     249        QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
    180250    }
    181251
    182252    q->QIODevice::open(QIODevice::ReadOnly);
    183     QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
    184 }
    185 
    186 void QNetworkReplyImplPrivate::setNetworkCache(QAbstractNetworkCache *nc)
    187 {
    188     networkCache = nc;
    189253}
    190254
     
    201265void QNetworkReplyImplPrivate::handleNotifications()
    202266{
     267    if (notificationHandlingPaused)
     268        return;
     269
    203270    NotificationQueue current = pendingNotifications;
    204271    pendingNotifications.clear();
     
    207274        return;
    208275
    209     while (!current.isEmpty()) {
     276    while (state == Working && !current.isEmpty()) {
    210277        InternalNotifications notification = current.dequeue();
    211278        switch (notification) {
     
    217284            break;
    218285
    219         case NotifyUpstreamReadyRead:
    220             backend->upstreamReadyRead();
    221             break;
    222 
    223286        case NotifyCloseDownstreamChannel:
    224287            backend->closeDownstreamChannel();
    225             break;
    226 
    227         case NotifyCloseUpstreamChannel:
    228             backend->closeUpstreamChannel();
    229288            break;
    230289
     
    239298}
    240299
     300// Do not handle the notifications while we are emitting downloadProgress
     301// or readyRead
     302void QNetworkReplyImplPrivate::pauseNotificationHandling()
     303{
     304    notificationHandlingPaused = true;
     305}
     306
     307// Resume notification handling
     308void QNetworkReplyImplPrivate::resumeNotificationHandling()
     309{
     310    Q_Q(QNetworkReplyImpl);
     311    notificationHandlingPaused = false;
     312    if (pendingNotifications.size() >= 1)
     313        QCoreApplication::postEvent(q, new QEvent(QEvent::NetworkReplyUpdated));
     314}
     315
     316QAbstractNetworkCache *QNetworkReplyImplPrivate::networkCache() const
     317{
     318    if (!backend)
     319        return 0;
     320    return backend->networkCache();
     321}
     322
    241323void QNetworkReplyImplPrivate::createCache()
    242324{
    243325    // check if we can save and if we're allowed to
    244     if (!networkCache || !request.attribute(QNetworkRequest::CacheSaveControlAttribute, true).toBool())
     326    if (!networkCache()
     327        || !request.attribute(QNetworkRequest::CacheSaveControlAttribute, true).toBool()
     328        || request.attribute(QNetworkRequest::CacheLoadControlAttribute,
     329                             QNetworkRequest::PreferNetwork).toInt()
     330            == QNetworkRequest::AlwaysNetwork)
    245331        return;
    246332    cacheEnabled = true;
     
    249335bool QNetworkReplyImplPrivate::isCachingEnabled() const
    250336{
    251     return (cacheEnabled && networkCache != 0);
     337    return (cacheEnabled && networkCache() != 0);
    252338}
    253339
     
    273359               "backend %s probably needs to be fixed",
    274360               backend->metaObject()->className());
    275         networkCache->remove(url);
     361        networkCache()->remove(url);
    276362        cacheSaveDevice = 0;
    277363        cacheEnabled = false;
     
    282368{
    283369    if (cacheEnabled && errorCode != QNetworkReplyImpl::NoError) {
    284         networkCache->remove(url);
     370        networkCache()->remove(url);
    285371    } else if (cacheEnabled && cacheSaveDevice) {
    286         networkCache->insert(cacheSaveDevice);
     372        networkCache()->insert(cacheSaveDevice);
    287373    }
    288374    cacheSaveDevice = 0;
     
    290376}
    291377
    292 void QNetworkReplyImplPrivate::consume(qint64 count)
    293 {
    294     Q_Q(QNetworkReplyImpl);
    295     if (count <= 0) {
    296         qWarning("QNetworkConnection: backend signalled that it consumed %ld bytes", long(count));
    297         return;
    298     }
    299 
    300     if (outgoingData)
    301         // schedule another read from the source
    302         QMetaObject::invokeMethod(q_func(), "_q_sourceReadyRead", Qt::QueuedConnection);
    303 
    304     writeBuffer.skip(count);
    305     if (bytesUploaded == -1)
    306         bytesUploaded = count;
    307     else
    308         bytesUploaded += count;
    309 
    310     QVariant totalSize = request.header(QNetworkRequest::ContentLengthHeader);
    311     emit q->uploadProgress(bytesUploaded,
    312                            totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
    313 }
     378void QNetworkReplyImplPrivate::emitUploadProgress(qint64 bytesSent, qint64 bytesTotal)
     379{
     380    Q_Q(QNetworkReplyImpl);
     381    bytesUploaded = bytesSent;
     382    pauseNotificationHandling();
     383    emit q->uploadProgress(bytesSent, bytesTotal);
     384    resumeNotificationHandling();
     385}
     386
    314387
    315388qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const
     
    319392        return DesiredBufferSize;
    320393
    321     return qMax<qint64>(0, readBufferMaxSize - readBuffer.size());
    322 }
    323 
    324 void QNetworkReplyImplPrivate::feed(const QByteArray &data)
     394    return qMax<qint64>(0, readBufferMaxSize - readBuffer.byteAmount());
     395}
     396
     397// we received downstream data and send this to the cache
     398// and to our readBuffer (which in turn gets read by the user of QNetworkReply)
     399void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data)
    325400{
    326401    Q_Q(QNetworkReplyImpl);
    327402    if (!q->isOpen())
    328403        return;
    329 
    330     char *ptr = readBuffer.reserve(data.size());
    331     memcpy(ptr, data.constData(), data.size());
    332404
    333405    if (cacheEnabled && !cacheSaveDevice) {
     
    336408        metaData.setUrl(url);
    337409        metaData = backend->fetchCacheMetaData(metaData);
    338         cacheSaveDevice = networkCache->prepare(metaData);
     410
     411        // save the redirect request also in the cache
     412        QVariant redirectionTarget = q->attribute(QNetworkRequest::RedirectionTargetAttribute);
     413        if (redirectionTarget.isValid()) {
     414            QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes();
     415            attributes.insert(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget);
     416            metaData.setAttributes(attributes);
     417        }
     418
     419        cacheSaveDevice = networkCache()->prepare(metaData);
     420
    339421        if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) {
    340422            if (cacheSaveDevice && !cacheSaveDevice->isOpen())
    341423                qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- "
    342424                      "class %s probably needs to be fixed",
    343                       networkCache->metaObject()->className());
    344 
    345             networkCache->remove(url);
     425                      networkCache()->metaObject()->className());
     426
     427            networkCache()->remove(url);
    346428            cacheSaveDevice = 0;
    347429            cacheEnabled = false;
     
    349431    }
    350432
    351     if (cacheSaveDevice)
    352         cacheSaveDevice->write(data);
    353 
    354     bytesDownloaded += data.size();
     433    qint64 bytesWritten = 0;
     434    for (int i = 0; i < data.bufferCount(); i++) {
     435        QByteArray item = data[i];
     436
     437        if (cacheSaveDevice)
     438            cacheSaveDevice->write(item.constData(), item.size());
     439        readBuffer.append(item);
     440
     441        bytesWritten += item.size();
     442    }
     443    data.clear();
     444
     445    bytesDownloaded += bytesWritten;
    355446    lastBytesDownloaded = bytesDownloaded;
    356447
     
    358449
    359450    QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
     451    pauseNotificationHandling();
    360452    emit q->downloadProgress(bytesDownloaded,
    361453                             totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
     454    // important: At the point of this readyRead(), the data parameter list must be empty,
     455    // else implicit sharing will trigger memcpy when the user is reading data!
    362456    emit q->readyRead();
    363457
    364458    // hopefully we haven't been deleted here
    365459    if (!qq.isNull()) {
     460        resumeNotificationHandling();
    366461        // do we still have room in the buffer?
    367462        if (nextDownstreamBlockSize() > 0)
     
    370465}
    371466
    372 void QNetworkReplyImplPrivate::feed(QIODevice *data)
    373 {
    374     Q_Q(QNetworkReplyImpl);
    375     Q_ASSERT(q->isOpen());
     467// this is used when it was fetched from the cache, right?
     468void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data)
     469{
     470    Q_Q(QNetworkReplyImpl);
     471    if (!q->isOpen())
     472        return;
    376473
    377474    // read until EOF from data
     
    393490{
    394491    Q_Q(QNetworkReplyImpl);
    395     Q_ASSERT_X(state != Finished, "QNetworkReplyImpl",
    396                "Backend called finished/finishedWithError more than once");
     492    if (state == Finished || state == Aborted)
     493        return;
    397494
    398495    state = Finished;
    399496    pendingNotifications.clear();
    400497
     498    pauseNotificationHandling();
    401499    QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
    402     if (bytesDownloaded != lastBytesDownloaded || totalSize.isNull())
     500    if (totalSize.isNull() || totalSize == -1) {
    403501        emit q->downloadProgress(bytesDownloaded, bytesDownloaded);
    404     if (bytesUploaded == -1 && outgoingData)
     502    }
     503
     504    if (bytesUploaded == -1 && (outgoingData || outgoingDataBuffer))
    405505        emit q->uploadProgress(0, 0);
     506    resumeNotificationHandling();
    406507
    407508    completeCacheSave();
     
    410511    // which would delete the backend too...
    411512    // maybe we should protect the backend
     513    pauseNotificationHandling();
    412514    emit q->readChannelFinished();
    413515    emit q->finished();
     516    resumeNotificationHandling();
    414517}
    415518
     
    456559}
    457560
     561bool QNetworkReplyImplPrivate::isFinished() const
     562{
     563    return (state == Finished || state == Aborted);
     564}
     565
    458566QNetworkReplyImpl::QNetworkReplyImpl(QObject *parent)
    459567    : QNetworkReply(*new QNetworkReplyImplPrivate, parent)
     
    465573    Q_D(QNetworkReplyImpl);
    466574    if (d->isCachingEnabled())
    467         d->networkCache->remove(url());
     575        d->networkCache()->remove(url());
     576    if (d->outgoingDataBuffer)
     577        delete d->outgoingDataBuffer;
    468578}
    469579
     
    471581{
    472582    Q_D(QNetworkReplyImpl);
    473     if (d->state == QNetworkReplyImplPrivate::Aborted)
     583    if (d->state == QNetworkReplyImplPrivate::Finished || d->state == QNetworkReplyImplPrivate::Aborted)
    474584        return;
    475585
    476586    // stop both upload and download
    477     if (d->backend) {
    478         d->backend->deleteLater();
    479         d->backend = 0;
    480     }
    481587    if (d->outgoingData)
    482588        disconnect(d->outgoingData, 0, this, 0);
     
    492598    }
    493599    d->state = QNetworkReplyImplPrivate::Aborted;
     600
     601    // finished may access the backend
     602    if (d->backend) {
     603        d->backend->deleteLater();
     604        d->backend = 0;
     605    }
    494606}
    495607
     
    521633qint64 QNetworkReplyImpl::bytesAvailable() const
    522634{
    523     return QNetworkReply::bytesAvailable() + d_func()->readBuffer.size();
     635    return QNetworkReply::bytesAvailable() + d_func()->readBuffer.byteAmount();
    524636}
    525637
     
    528640    Q_D(QNetworkReplyImpl);
    529641    if (size > d->readBufferMaxSize &&
    530         size == d->readBuffer.size())
     642        size > d->readBuffer.byteAmount())
    531643        d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite);
    532644
     
    558670}
    559671
     672void QNetworkReplyImpl::ignoreSslErrorsImplementation(const QList<QSslError> &errors)
     673{
     674    Q_D(QNetworkReplyImpl);
     675    if (d->backend)
     676        d->backend->ignoreSslErrors(errors);
     677}
    560678#endif  // QT_NO_OPENSSL
    561679
     
    576694    }
    577695
    578     maxlen = qMin<qint64>(maxlen, d->readBuffer.size());
     696    maxlen = qMin<qint64>(maxlen, d->readBuffer.byteAmount());
    579697    return d->readBuffer.read(data, maxlen);
    580698}
  • trunk/src/network/access/qnetworkreplyimpl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6060#include "QtCore/qmap.h"
    6161#include "QtCore/qqueue.h"
     62#include "QtCore/qbuffer.h"
    6263#include "private/qringbuffer_p.h"
     64#include "private/qbytedata_p.h"
    6365
    6466QT_BEGIN_NAMESPACE
     
    8890    Q_INVOKABLE void setSslConfigurationImplementation(const QSslConfiguration &configuration);
    8991    virtual void ignoreSslErrors();
     92    Q_INVOKABLE virtual void ignoreSslErrorsImplementation(const QList<QSslError> &errors);
    9093#endif
    9194
    9295    Q_DECLARE_PRIVATE(QNetworkReplyImpl)
    9396    Q_PRIVATE_SLOT(d_func(), void _q_startOperation())
    94     Q_PRIVATE_SLOT(d_func(), void _q_sourceReadyRead())
    95     Q_PRIVATE_SLOT(d_func(), void _q_sourceReadChannelFinished())
    9697    Q_PRIVATE_SLOT(d_func(), void _q_copyReadyRead())
    9798    Q_PRIVATE_SLOT(d_func(), void _q_copyReadChannelFinished())
     99    Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
     100    Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
    98101};
    99102
     
    103106    enum InternalNotifications {
    104107        NotifyDownstreamReadyWrite,
    105         NotifyUpstreamReadyRead,
    106108        NotifyCloseDownstreamChannel,
    107         NotifyCloseUpstreamChannel,
    108109        NotifyCopyFinished
    109110    };
     
    111112    enum State {
    112113        Idle,
    113         Opening,
     114        Buffering,
    114115        Working,
    115116        Finished,
     
    126127    void _q_copyReadyRead();
    127128    void _q_copyReadChannelFinished();
     129    void _q_bufferOutgoingData();
     130    void _q_bufferOutgoingDataFinished();
    128131
    129132    void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
    130133               QIODevice *outgoingData);
    131     void setNetworkCache(QAbstractNetworkCache *networkCache);
     134
     135    void pauseNotificationHandling();
     136    void resumeNotificationHandling();
    132137    void backendNotify(InternalNotifications notification);
    133138    void handleNotifications();
     
    139144    bool isCachingEnabled() const;
    140145    void consume(qint64 count);
     146    void emitUploadProgress(qint64 bytesSent, qint64 bytesTotal);
    141147    qint64 nextDownstreamBlockSize() const;
    142     void feed(const QByteArray &data);
    143     void feed(QIODevice *data);
     148    void appendDownstreamData(QByteDataBuffer &data);
     149    void appendDownstreamData(QIODevice *data);
    144150    void finished();
    145151    void error(QNetworkReply::NetworkError code, const QString &errorString);
     
    148154    void sslErrors(const QList<QSslError> &errors);
    149155
     156    bool isFinished() const;
     157
    150158    QNetworkAccessBackend *backend;
    151159    QIODevice *outgoingData;
     160    QRingBuffer *outgoingDataBuffer;
    152161    QIODevice *copyDevice;
    153     QAbstractNetworkCache *networkCache;
     162    QAbstractNetworkCache *networkCache() const;
    154163
    155164    bool cacheEnabled;
     
    157166
    158167    NotificationQueue pendingNotifications;
     168    bool notificationHandlingPaused;
     169
    159170    QUrl urlForLastAuthentication;
    160171#ifndef QT_NO_NETWORKPROXY
     
    163174#endif
    164175
    165     QRingBuffer readBuffer;
    166     QRingBuffer writeBuffer;
     176    QByteDataBuffer readBuffer;
    167177    qint64 bytesDownloaded;
    168178    qint64 lastBytesDownloaded;
  • trunk/src/network/access/qnetworkrequest.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4949#include "QtCore/qdatetime.h"
    5050
     51#include <ctype.h>
     52#ifndef QT_NO_DATESTRING
     53# include <stdio.h>
     54#endif
     55
    5156QT_BEGIN_NAMESPACE
    5257
    5358/*!
    5459    \class QNetworkRequest
    55     \brief The QNetworkRequest class holds one request to be sent with the Network Access API.
     60    \brief The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
    5661    \since 4.4
    5762
    58     \ingroup io
     63    \ingroup network
    5964    \inmodule QtNetwork
    6065
     
    154159        be automatically cached. If true, data may be cached, provided
    155160        it is cacheable (what is cacheable depends on the protocol
    156         being used). Note that the default QNetworkAccessManager
    157         implementation does not support caching, so it will ignore
    158         this attribute.
     161        being used).
    159162
    160163    \value SourceIsFromCacheAttribute
     
    162165        Indicates whether the data was obtained from cache
    163166        or not.
     167
     168    \value DoNotBufferUploadDataAttribute
     169        Requests only, type: QVariant::Bool (default: false)
     170        Indicates whether the QNetworkAccessManager code is
     171        allowed to buffer the upload data, e.g. when doing a HTTP POST.
     172        When using this flag with sequential upload data, the ContentLengthHeader
     173        header must be set.
     174
     175     \value HttpPipeliningAllowedAttribute
     176        Requests only, type: QVariant::Bool (default: false)
     177        Indicates whether the QNetworkAccessManager code is
     178        allowed to use HTTP pipelining with this request.
     179
     180     \value HttpPipeliningWasUsedAttribute
     181        Replies only, type: QVariant::Bool
     182        Indicates whether the HTTP pipelining was used for receiving
     183        this reply.
    164184
    165185    \value User
     
    217237
    218238#ifndef QT_NO_OPENSSL
     239        sslConfiguration = 0;
    219240        if (other.sslConfiguration)
    220241            sslConfiguration = new QSslConfiguration(*other.sslConfiguration);
    221         else
    222             sslConfiguration = 0;
    223242#endif
    224243    }
     
    467486}
    468487#endif
     488
     489/*!
     490    \since 4.6
     491
     492    Allows setting a reference to the \a object initiating
     493    the request.
     494
     495    For example QtWebKit sets the originating object to the
     496    QWebFrame that initiated the request.
     497
     498    \sa originatingObject()
     499*/
     500void QNetworkRequest::setOriginatingObject(QObject *object)
     501{
     502    d->originatingObject = object;
     503}
     504
     505/*!
     506    \since 4.6
     507
     508    Returns a reference to the object that initiated this
     509    network request; returns 0 if not set or the object has
     510    been destroyed.
     511
     512    \sa setOriginatingObject()
     513*/
     514QObject *QNetworkRequest::originatingObject() const
     515{
     516    return d->originatingObject.data();
     517}
    469518
    470519static QByteArray headerName(QNetworkRequest::KnownHeaders header)
     
    563612    // headerName is not empty here
    564613
    565     QByteArray lower = headerName.toLower();
    566     switch (lower.at(0)) {
     614    switch (tolower(headerName.at(0))) {
    567615    case 'c':
    568         if (lower == "content-type")
     616        if (qstricmp(headerName.constData(), "content-type") == 0)
    569617            return QNetworkRequest::ContentTypeHeader;
    570         else if (lower == "content-length")
     618        else if (qstricmp(headerName.constData(), "content-length") == 0)
    571619            return QNetworkRequest::ContentLengthHeader;
    572         else if (lower == "cookie")
     620        else if (qstricmp(headerName.constData(), "cookie") == 0)
    573621            return QNetworkRequest::CookieHeader;
    574622        break;
    575623
    576624    case 'l':
    577         if (lower == "location")
     625        if (qstricmp(headerName.constData(), "location") == 0)
    578626            return QNetworkRequest::LocationHeader;
    579         else if (lower == "last-modified")
     627        else if (qstricmp(headerName.constData(), "last-modified") == 0)
    580628            return QNetworkRequest::LastModifiedHeader;
    581629        break;
    582630
    583631    case 's':
    584         if (lower == "set-cookie")
     632        if (qstricmp(headerName.constData(), "set-cookie") == 0)
    585633            return QNetworkRequest::SetCookieHeader;
    586634        break;
     
    654702QNetworkHeadersPrivate::findRawHeader(const QByteArray &key) const
    655703{
    656     QByteArray lowerKey = key.toLower();
    657704    RawHeadersList::ConstIterator it = rawHeaders.constBegin();
    658705    RawHeadersList::ConstIterator end = rawHeaders.constEnd();
    659706    for ( ; it != end; ++it)
    660         if (it->first.toLower() == lowerKey)
     707        if (qstricmp(it->first.constData(), key.constData()) == 0)
    661708            return it;
    662709
     
    732779void QNetworkHeadersPrivate::setRawHeaderInternal(const QByteArray &key, const QByteArray &value)
    733780{
    734     QByteArray lowerKey = key.toLower();
    735781    RawHeadersList::Iterator it = rawHeaders.begin();
    736782    while (it != rawHeaders.end()) {
    737         if (it->first.toLower() == lowerKey)
     783        if (qstricmp(it->first.constData(), key.constData()) == 0)
    738784            it = rawHeaders.erase(it);
    739785        else
     
    762808}
    763809
     810// Fast month string to int conversion. This code
     811// assumes that the Month name is correct and that
     812// the string is at least three chars long.
     813static int name_to_month(const char* month_str)
     814{
     815    switch (month_str[0]) {
     816    case 'J':
     817        switch (month_str[1]) {
     818        case 'a':
     819            return 1;
     820            break;
     821        case 'u':
     822            switch (month_str[2] ) {
     823            case 'n':
     824                return 6;
     825                break;
     826            case 'l':
     827                return 7;
     828                break;
     829            }
     830        }
     831        break;
     832    case 'F':
     833        return 2;
     834        break;
     835    case 'M':
     836        switch (month_str[2] ) {
     837        case 'r':
     838            return 3;
     839            break;
     840        case 'y':
     841            return 5;
     842            break;
     843        }
     844        break;
     845    case 'A':
     846        switch (month_str[1]) {
     847        case 'p':
     848            return 4;
     849            break;
     850        case 'u':
     851            return 8;
     852            break;
     853        }
     854        break;
     855    case 'O':
     856        return 10;
     857        break;
     858    case 'S':
     859        return 9;
     860        break;
     861    case 'N':
     862        return 11;
     863        break;
     864    case 'D':
     865        return 12;
     866        break;
     867    }
     868
     869    return 0;
     870}
     871
    764872QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value)
    765873{
     
    777885        dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
    778886    } else {
    779         // eat the weekday, the comma and the space following it
    780         QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
    781 
    782         QLocale c = QLocale::c();
    783         if (pos == 3)
    784             // must be RFC 1123 date
    785             dt = c.toDateTime(sansWeekday, QLatin1String("dd MMM yyyy hh:mm:ss 'GMT"));
    786         else
     887        // Use sscanf over QLocal/QDateTimeParser for speed reasons. See the
     888        // QtWebKit performance benchmarks to get an idea.
     889        if (pos == 3) {
     890            char month_name[4];
     891            int day, year, hour, minute, second;
     892            if (sscanf(value.constData(), "%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
     893                dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
     894        } else {
     895            QLocale c = QLocale::c();
     896            // eat the weekday, the comma and the space following it
     897            QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
    787898            // must be RFC 850 date
    788899            dt = c.toDateTime(sansWeekday, QLatin1String("dd-MMM-yy hh:mm:ss 'GMT'"));
     900        }
    789901    }
    790902#endif // QT_NO_DATESTRING
  • trunk/src/network/access/qnetworkrequest.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7676        CacheSaveControlAttribute,
    7777        SourceIsFromCacheAttribute,
     78        DoNotBufferUploadDataAttribute,
     79        HttpPipeliningAllowedAttribute,
     80        HttpPipeliningWasUsedAttribute,
    7881
    7982        User = 1000,
     
    118121#endif
    119122
     123    void setOriginatingObject(QObject *object);
     124    QObject *originatingObject() const;
     125
    120126private:
    121127    QSharedDataPointer<QNetworkRequestPrivate> d;
  • trunk/src/network/access/qnetworkrequest_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5959#include "QtCore/qhash.h"
    6060#include "QtCore/qshareddata.h"
     61#include "QtCore/qsharedpointer.h"
    6162
    6263QT_BEGIN_NAMESPACE
     
    7475    CookedHeadersMap cookedHeaders;
    7576    AttributesMap attributes;
     77    QWeakPointer<QObject> originatingObject;
    7678
    7779    RawHeadersList::ConstIterator findRawHeader(const QByteArray &key) const;
  • trunk/src/network/kernel/kernel.pri

    r160 r561  
    2121           kernel/qnetworkinterface.cpp
    2222
    23 unix:SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
     23symbian: SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_symbian.cpp
     24unix:!symbian:SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
    2425win32:SOURCES += kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp
    2526os2:SOURCES += kernel/qhostinfo_os2.cpp kernel/qnetworkinterface_os2.cpp
    2627
    27 mac:LIBS+= -framework SystemConfiguration
     28mac:LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation
    2829mac:SOURCES += kernel/qnetworkproxy_mac.cpp
    2930else:win32:SOURCES += kernel/qnetworkproxy_win.cpp
  • trunk/src/network/kernel/qauthenticator.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747#include <qcryptographichash.h>
    4848#include <qhttp.h>
     49#include <qiodevice.h>
    4950#include <qdatastream.h>
    5051#include <qendian.h>
     
    6465
    6566  \reentrant
    66   \ingroup io
     67  \ingroup network
    6768  \inmodule QtNetwork
    6869
    6970  The QAuthenticator class is usually used in the
    70   \l{QHttp::}{authenticationRequired()} and
    71   \l{QHttp::}{proxyAuthenticationRequired()} signals of QHttp and
     71  \l{QNetworkAccessManager::}{authenticationRequired()} and
     72  \l{QNetworkAccessManager::}{proxyAuthenticationRequired()} signals of QNetworkAccessManager and
    7273  QAbstractSocket. The class provides a way to pass back the required
    7374  authentication information to the socket when accessing services that
    7475  require authentication.
     76
     77  QAuthenticator supports the following authentication methods:
     78  \list
     79    \o Basic
     80    \o NTLM version 1
     81    \o Digest-MD5
     82  \endlist
     83
     84  Note that, in particular, NTLM version 2 is not supported.
    7585
    7686  \sa QSslSocket
     
    503513    if (!opaque.isEmpty())
    504514        credentials += "opaque=\"" + opaque + "\", ";
    505     credentials += "response=\"" + response + "\"";
     515    credentials += "response=\"" + response + '\"';
    506516    if (!options.value("algorithm").isEmpty())
    507517        credentials += ", algorithm=" + options.value("algorithm");
     
    509519        credentials += ", qop=" + qop + ", ";
    510520        credentials += "nc=" + nonceCountString + ", ";
    511         credentials += "cnonce=\"" + cnonce + "\"";
     521        credentials += "cnonce=\"" + cnonce + '\"';
    512522    }
    513523
  • trunk/src/network/kernel/qauthenticator.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/kernel/qauthenticator_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/kernel/qhostaddress.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    420420    \class QHostAddress
    421421    \brief The QHostAddress class provides an IP address.
    422     \ingroup io
     422    \ingroup network
    423423    \inmodule QtNetwork
    424424
     
    432432    using isIPv4Address() or isIPv6Address(), and retrieved with
    433433    toIPv4Address(), toIPv6Address(), or toString().
     434
     435    \note Please note that QHostAddress does not do DNS lookups.
     436    QHostInfo is needed for that.
    434437
    435438    The class also supports common predefined addresses: \l Null, \l
     
    524527*/
    525528QHostAddress::QHostAddress(const QHostAddress &address)
    526     : d(new QHostAddressPrivate(*address.d))
     529    : d(new QHostAddressPrivate(*address.d.data()))
    527530{
    528531}
     
    560563QHostAddress::~QHostAddress()
    561564{
    562     delete d;
    563565}
    564566
     
    569571QHostAddress &QHostAddress::operator=(const QHostAddress &address)
    570572{
    571     *d = *address.d;
     573    *d.data() = *address.d.data();
    572574    return *this;
    573575}
     
    10791081QDebug operator<<(QDebug d, const QHostAddress &address)
    10801082{
    1081     d.maybeSpace() << "QHostAddress(" << address.toString() << ")";
     1083    d.maybeSpace() << "QHostAddress(" << address.toString() << ')';
    10821084    return d.space();
    10831085}
  • trunk/src/network/kernel/qhostaddress.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4545#include <QtCore/qpair.h>
    4646#include <QtCore/qstring.h>
     47#include <QtCore/qscopedpointer.h>
    4748#include <QtNetwork/qabstractsocket.h>
    4849
     
    131132
    132133protected:
    133     QHostAddressPrivate *d;
     134    QScopedPointer<QHostAddressPrivate> d;
    134135};
    135136
  • trunk/src/network/kernel/qhostaddress_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/kernel/qhostinfo.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4343#include "qhostinfo_p.h"
    4444
     45#include "QtCore/qscopedpointer.h"
    4546#include <qabstracteventdispatcher.h>
    4647#include <private/qunicodetables_p.h>
     
    6061QT_BEGIN_NAMESPACE
    6162
    62 Q_GLOBAL_STATIC(QHostInfoAgent, theAgent)
    63 void QHostInfoAgent::staticCleanup()
    64 {
    65     theAgent()->cleanup();
    66 }
     63#ifndef QT_NO_THREAD
     64Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager)
     65#endif
    6766
    6867//#define QHOSTINFO_DEBUG
     
    7473    \reentrant
    7574    \inmodule QtNetwork
    76     \ingroup io
     75    \ingroup network
    7776
    7877    QHostInfo uses the lookup mechanisms provided by the operating
     
    142141
    143142    \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 4
     143
     144    \note There is no guarantee on the order the signals will be emitted
     145    if you start multiple requests with lookupHost().
    144146
    145147    \sa abortHostLookup(), addresses(), error(), fromName()
     
    159161    qRegisterMetaType<QHostInfo>("QHostInfo");
    160162
    161 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
    162     QWindowsSockInit bust; // makes sure WSAStartup was callled
     163    int id = theIdCounter.fetchAndAddRelaxed(1); // generate unique ID
     164
     165    if (name.isEmpty()) {
     166        QHostInfo hostInfo(id);
     167        hostInfo.setError(QHostInfo::HostNotFound);
     168        hostInfo.setErrorString(QObject::tr("No host name given"));
     169        QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
     170        QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
     171                         receiver, member, Qt::QueuedConnection);
     172        result.data()->emitResultsReady(hostInfo);
     173        return id;
     174    }
     175
     176#ifdef QT_NO_THREAD
     177    QHostInfo hostInfo = QHostInfoAgent::fromName(name);
     178    hostInfo.setLookupId(id);
     179    QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
     180    QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
     181                     receiver, member, Qt::QueuedConnection);
     182    result.data()->emitResultsReady(hostInfo);
     183#else
     184    QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id);
     185    QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection);
     186    theHostInfoLookupManager()->scheduleLookup(runnable);
    163187#endif
    164188
    165     // Support for IDNA
    166     QString lookup = QString::fromLatin1(QUrl::toAce(name));
    167 
    168     QHostInfoResult *result = new QHostInfoResult;
    169     result->autoDelete = false;
    170     QObject::connect(result, SIGNAL(resultsReady(QHostInfo)),
    171                      receiver, member);
    172     int id = result->lookupId = theIdCounter.fetchAndAddRelaxed(1);
    173 
    174     if (lookup.isEmpty()) {
    175         QHostInfo info(id);
    176         info.setError(QHostInfo::HostNotFound);
    177         info.setErrorString(QObject::tr("No host name given"));
    178         QMetaObject::invokeMethod(result, "emitResultsReady", Qt::QueuedConnection,
    179                                   Q_ARG(QHostInfo, info));
    180         result->autoDelete = true;
    181         return id;
    182     }
    183 
    184     QHostInfoAgent *agent = theAgent();
    185     agent->addHostName(lookup, result);
    186 
    187 #if !defined QT_NO_THREAD
    188     if (!agent->isRunning())
    189         agent->start();
     189    return id;
     190}
     191
     192/*!
     193    Aborts the host lookup with the ID \a id, as returned by lookupHost().
     194
     195    \sa lookupHost(), lookupId()
     196*/
     197void QHostInfo::abortHostLookup(int id)
     198{
     199#ifndef QT_NO_THREAD
     200    theHostInfoLookupManager()->abortLookup(id);
    190201#else
    191 //    if (!agent->isRunning())
    192         agent->run();
    193 //    else
    194 //      agent->wakeOne();
     202    // we cannot abort if it was non threaded.. the result signal has already been posted
     203    Q_UNUSED(id);
    195204#endif
    196     return id;
    197 }
    198 
    199 /*!
    200     Aborts the host lookup with the ID \a id, as returned by lookupHost().
    201 
    202     \sa lookupHost(), lookupId()
    203 */
    204 void QHostInfo::abortHostLookup(int id)
    205 {
    206     QHostInfoAgent *agent = theAgent();
    207     agent->abortLookup(id);
    208205}
    209206
     
    227224#endif
    228225
    229     if (!name.isEmpty())
    230         return QHostInfoAgent::fromName(QLatin1String(QUrl::toAce(name)));
    231 
    232     QHostInfo retval;
    233     retval.d->err = HostNotFound;
    234     retval.d->errorStr = QObject::tr("No host name given");
    235     return retval;
    236 }
    237 
    238 /*!
    239     \internal
    240     Pops a query off the queries list, performs a blocking call to
    241     QHostInfoAgent::lookupHost(), and emits the resultsReady()
    242     signal. This process repeats until the queries list is empty.
    243 */
    244 void QHostInfoAgent::run()
    245 {
    246 #ifndef QT_NO_THREAD
    247     // Dont' allow thread termination during event delivery, but allow it
    248     // during the actual blocking host lookup stage.
    249     setTerminationEnabled(false);
    250     forever
    251 #endif
    252     {
    253         QHostInfoQuery *query;
    254         {
    255 #ifndef QT_NO_THREAD
    256             // the queries list is shared between threads. lock all
    257             // access to it.
    258             QMutexLocker locker(&mutex);
    259             if (!quit && queries.isEmpty())
    260                 cond.wait(&mutex);
    261             if (quit) {
    262                 // Reset the quit variable in case QCoreApplication is
    263                 // destroyed and recreated.
    264                 quit = false;
    265                 break;
    266             }
    267             if (queries.isEmpty())
    268                 continue;
    269 #else
    270             if (queries.isEmpty())
    271                 return;
    272 #endif
    273             query = queries.takeFirst();
    274             pendingQueryId = query->object->lookupId;
    275         }
    276 
    277 #if defined(QHOSTINFO_DEBUG)
    278         qDebug("QHostInfoAgent::run(%p): looking up \"%s\"", this,
    279                query->hostName.toLatin1().constData());
    280 #endif
    281 
    282 #ifndef QT_NO_THREAD
    283         // Start query - allow termination at this point, but not outside. We
    284         // don't want to all termination during event delivery, but we don't
    285         // want the lookup to prevent the app from quitting (the agent
    286         // destructor terminates the thread).
    287         setTerminationEnabled(true);
    288 #endif
    289         QHostInfo info = fromName(query->hostName);
    290 #ifndef QT_NO_THREAD
    291         setTerminationEnabled(false);
    292 #endif
    293 
    294         int id = query->object->lookupId;
    295         info.setLookupId(id);
    296         if (pendingQueryId == id)
    297             query->object->emitResultsReady(info);
    298         delete query;
    299     }
     226    return QHostInfoAgent::fromName(name);
    300227}
    301228
     
    328255*/
    329256QHostInfo::QHostInfo(const QHostInfo &other)
    330     : d(new QHostInfoPrivate(*other.d))
     257    : d(new QHostInfoPrivate(*other.d.data()))
    331258{
    332259}
     
    338265QHostInfo &QHostInfo::operator=(const QHostInfo &other)
    339266{
    340     *d = *other.d;
     267    *d.data() = *other.d.data();
    341268    return *this;
    342269}
     
    347274QHostInfo::~QHostInfo()
    348275{
    349     delete d;
    350276}
    351277
     
    477403*/
    478404
     405#ifndef QT_NO_THREAD
     406QHostInfoRunnable::QHostInfoRunnable(QString hn, int i) : toBeLookedUp(hn), id(i)
     407{
     408    setAutoDelete(true);
     409}
     410
     411// the QHostInfoLookupManager will at some point call this via a QThreadPool
     412void QHostInfoRunnable::run()
     413{
     414    QHostInfoLookupManager *manager = theHostInfoLookupManager();
     415    // check aborted
     416    if (manager->wasAborted(id)) {
     417        manager->lookupFinished(this);
     418        return;
     419    }
     420
     421    // check cache
     422    // FIXME
     423
     424    // if not in cache: OS lookup
     425    QHostInfo hostInfo = QHostInfoAgent::fromName(toBeLookedUp);
     426
     427    // save to cache
     428    // FIXME
     429
     430    // check aborted again
     431    if (manager->wasAborted(id)) {
     432        manager->lookupFinished(this);
     433        return;
     434    }
     435
     436    // signal emission
     437    hostInfo.setLookupId(id);
     438    resultEmitter.emitResultsReady(hostInfo);
     439
     440    manager->lookupFinished(this);
     441
     442    // thread goes back to QThreadPool
     443}
     444
     445QHostInfoLookupManager::QHostInfoLookupManager() : mutex(QMutex::Recursive), wasDeleted(false)
     446{
     447    moveToThread(QCoreApplicationPrivate::mainThread());
     448    threadPool.setMaxThreadCount(5); // do 5 DNS lookups in parallel
     449}
     450
     451QHostInfoLookupManager::~QHostInfoLookupManager()
     452{
     453    wasDeleted = true;
     454}
     455
     456void QHostInfoLookupManager::work()
     457{
     458    if (wasDeleted)
     459        return;
     460
     461    // goals of this function:
     462    //  - launch new lookups via the thread pool
     463    //  - make sure only one lookup per host/IP is in progress
     464
     465    QMutexLocker locker(&mutex);
     466
     467    if (!finishedLookups.isEmpty()) {
     468        // remove ID from aborted if it is in there
     469        for (int i = 0; i < finishedLookups.length(); i++) {
     470           abortedLookups.removeAll(finishedLookups.at(i)->id);
     471        }
     472
     473        finishedLookups.clear();
     474    }
     475
     476    if (!postponedLookups.isEmpty()) {
     477        // try to start the postponed ones
     478
     479        QMutableListIterator<QHostInfoRunnable*> iterator(postponedLookups);
     480        while (iterator.hasNext()) {
     481            QHostInfoRunnable* postponed = iterator.next();
     482
     483            // check if none of the postponed hostnames is currently running
     484            bool alreadyRunning = false;
     485            for (int i = 0; i < currentLookups.length(); i++) {
     486                if (currentLookups.at(i)->toBeLookedUp == postponed->toBeLookedUp) {
     487                    alreadyRunning = true;
     488                    break;
     489                }
     490            }
     491            if (!alreadyRunning) {
     492                iterator.remove();
     493                scheduledLookups.prepend(postponed); // prepend! we want to finish it ASAP
     494            }
     495        }
     496    }
     497
     498    if (!scheduledLookups.isEmpty()) {
     499        // try to start the new ones
     500        QMutableListIterator<QHostInfoRunnable*> iterator(scheduledLookups);
     501        while (iterator.hasNext()) {
     502            QHostInfoRunnable *scheduled = iterator.next();
     503
     504            // check if a lookup for this host is already running, then postpone
     505            for (int i = 0; i < currentLookups.size(); i++) {
     506                if (currentLookups.at(i)->toBeLookedUp == scheduled->toBeLookedUp) {
     507                    iterator.remove();
     508                    postponedLookups.append(scheduled);
     509                    scheduled = 0;
     510                    break;
     511                }
     512            }
     513
     514            if (scheduled && threadPool.tryStart(scheduled)) {
     515                // runnable now running in new thread, track this in currentLookups
     516                iterator.remove();
     517                currentLookups.append(scheduled);
     518            } else if (scheduled) {
     519                // wanted to start, but could not because thread pool is busy
     520                break;
     521            } else {
     522                // was postponed, continue iterating
     523                continue;
     524            }
     525        };
     526    }
     527}
     528
     529// called by QHostInfo
     530void QHostInfoLookupManager::scheduleLookup(QHostInfoRunnable *r)
     531{
     532    if (wasDeleted)
     533        return;
     534
     535    QMutexLocker locker(&this->mutex);
     536    scheduledLookups.enqueue(r);
     537    work();
     538}
     539
     540// called by QHostInfo
     541void QHostInfoLookupManager::abortLookup(int id)
     542{
     543    if (wasDeleted)
     544        return;
     545
     546    QMutexLocker locker(&this->mutex);
     547    if (!abortedLookups.contains(id))
     548        abortedLookups.append(id);
     549}
     550
     551// called from QHostInfoRunnable
     552bool QHostInfoLookupManager::wasAborted(int id)
     553{
     554    if (wasDeleted)
     555        return true;
     556
     557    QMutexLocker locker(&this->mutex);
     558    return abortedLookups.contains(id);
     559}
     560
     561// called from QHostInfoRunnable
     562void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r)
     563{
     564    if (wasDeleted)
     565        return;
     566
     567    QMutexLocker locker(&this->mutex);
     568    currentLookups.removeOne(r);
     569    finishedLookups.append(r);
     570    work();
     571}
     572
     573#endif // QT_NO_THREAD
     574
    479575QT_END_NAMESPACE
  • trunk/src/network/kernel/qhostinfo.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444
    4545#include <QtCore/qlist.h>
     46#include <QtCore/qscopedpointer.h>
    4647#include <QtNetwork/qhostaddress.h>
    4748
     
    9293
    9394private:
    94     QHostInfoPrivate *d;
     95    QScopedPointer<QHostInfoPrivate> d;
    9596};
    9697
  • trunk/src/network/kernel/qhostinfo_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of the QLibrary class.  This header file may change from
     50// of the QHostInfo class.  This header file may change from
    5151// version to version without notice, or even be removed.
    5252//
     
    6262#include "QtCore/qpointer.h"
    6363
    64 #if !defined QT_NO_THREAD
     64#ifndef QT_NO_THREAD
    6565#include "QtCore/qthread.h"
    66 #    define QHostInfoAgentBase QThread
    67 #else
    68 #    define QHostInfoAgentBase QObject
     66#include "QtCore/qthreadpool.h"
     67#include "QtCore/qmutex.h"
     68#include "QtCore/qrunnable.h"
     69#include "QtCore/qlist.h"
     70#include "QtCore/qqueue.h"
    6971#endif
    7072
    7173QT_BEGIN_NAMESPACE
    72 
    73 static const int QHOSTINFO_THREAD_WAIT = 250; // ms
    7474
    7575class QHostInfoResult : public QObject
     
    8080    {
    8181        emit resultsReady(info);
    82         if (autoDelete)
    83             delete this;
    8482    }
    8583
    8684Q_SIGNALS:
    87     void resultsReady(const QHostInfo &info);
    88 
    89 public:
    90     int lookupId;
    91     bool autoDelete;
     85    void resultsReady(const QHostInfo info);
    9286};
    9387
    94 struct QHostInfoQuery
    95 {
    96     inline QHostInfoQuery() : object(0) {}
    97     inline ~QHostInfoQuery() { delete object; }
    98     inline QHostInfoQuery(const QString &name, QHostInfoResult *result)
    99         : hostName(name), object(result) {}
    100 
    101     QString hostName;
    102     QHostInfoResult *object;
    103 };
    104 
    105 class QHostInfoAgent : public QHostInfoAgentBase
     88// needs to be QObject because fromName calls tr()
     89class QHostInfoAgent : public QObject
    10690{
    10791    Q_OBJECT
    10892public:
    109     inline QHostInfoAgent()
    110     {
    111         // There is a chance that there will be two instances of
    112         // QHostInfoAgent if two threads try to get Q_GLOBAL_STATIC
    113         // object at the same time. The second object will be deleted
    114         // immediately before anyone uses it, but we need to be
    115         // careful about what we do in the constructor.
    116         static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);
    117         if (done.testAndSetRelaxed(0, 1))
    118             qAddPostRoutine(staticCleanup);
    119         moveToThread(QCoreApplicationPrivate::mainThread());
    120         quit = false;
    121         pendingQueryId = -1;
    122     }
    123     inline ~QHostInfoAgent()
    124     { cleanup(); }
    125 
    126     void run();
    12793    static QHostInfo fromName(const QString &hostName);
    128 
    129     inline void addHostName(const QString &name, QHostInfoResult *result)
    130     {
    131         QMutexLocker locker(&mutex);
    132         queries << new QHostInfoQuery(name, result);
    133         cond.wakeOne();
    134     }
    135 
    136     inline void abortLookup(int id)
    137     {
    138         QMutexLocker locker(&mutex);
    139         for (int i = 0; i < queries.size(); ++i) {
    140             QHostInfoResult *result = queries.at(i)->object;
    141             if (result->lookupId == id) {
    142                 result->disconnect();
    143                 delete queries.takeAt(i);
    144                 return;
    145             }
    146         }
    147         if (pendingQueryId == id)
    148             pendingQueryId = -1;
    149     }
    150 
    151     static void staticCleanup();
    152 
    153 public Q_SLOTS:
    154     inline void cleanup()
    155     {
    156         {
    157             QMutexLocker locker(&mutex);
    158             qDeleteAll(queries);
    159             queries.clear();
    160             quit = true;
    161             cond.wakeOne();
    162         }
    163 #ifndef QT_NO_THREAD
    164         if (!wait(QHOSTINFO_THREAD_WAIT))
    165             terminate();
    166         wait();
    167 #endif
    168     }
    169 
    170 private:
    171     QList<QHostInfoQuery *> queries;
    172     QMutex mutex;
    173     QWaitCondition cond;
    174     volatile bool quit;
    175     int pendingQueryId;
    17694};
    17795
     
    18199    inline QHostInfoPrivate()
    182100        : err(QHostInfo::NoError),
    183           errorStr(QLatin1String(QT_TRANSLATE_NOOP("QHostInfo", "Unknown error")))
     101          errorStr(QLatin1String(QT_TRANSLATE_NOOP("QHostInfo", "Unknown error"))),
     102          lookupId(0)
    184103    {
    185104    }
     
    192111};
    193112
     113#ifndef QT_NO_THREAD
     114// the following classes are used for the (normal) case: We use multiple threads to lookup DNS
     115
     116class QHostInfoRunnable : public QRunnable
     117{
     118public:
     119    QHostInfoRunnable (QString hn, int i);
     120    void run();
     121
     122    QString toBeLookedUp;
     123    int id;
     124    QHostInfoResult resultEmitter;
     125};
     126
     127class QHostInfoLookupManager : public QObject
     128{
     129    Q_OBJECT
     130public:
     131    QHostInfoLookupManager();
     132    ~QHostInfoLookupManager();
     133
     134    void work();
     135
     136    // called from QHostInfo
     137    void scheduleLookup(QHostInfoRunnable *r);
     138    void abortLookup(int id);
     139
     140    // called from QHostInfoRunnable
     141    void lookupFinished(QHostInfoRunnable *r);
     142    bool wasAborted(int id);
     143
     144protected:
     145    QList<QHostInfoRunnable*> currentLookups; // in progress
     146    QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host
     147    QQueue<QHostInfoRunnable*> scheduledLookups; // not yet started
     148    QList<QHostInfoRunnable*> finishedLookups; // recently finished
     149    QList<int> abortedLookups; // ids of aborted lookups
     150
     151    QThreadPool threadPool;
     152
     153    QMutex mutex;
     154
     155    bool wasDeleted;
     156};
     157#endif
     158
    194159QT_END_NAMESPACE
    195160
  • trunk/src/network/kernel/qhostinfo_unix.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4141
    4242//#define QHOSTINFO_DEBUG
    43 
    44 static const int RESOLVER_TIMEOUT = 2000;
    4543
    4644#include "qplatformdefs.h"
     
    5351#include <qfile.h>
    5452#include <private/qmutexpool_p.h>
    55 
    56 extern "C" {
     53#include <private/qnet_unix_p.h>
     54
    5755#include <sys/types.h>
    5856#include <netdb.h>
    5957#include <arpa/inet.h>
    60 #include <resolv.h>
    61 }
     58#if defined(Q_OS_VXWORKS)
     59#  include <hostLib.h>
     60#else
     61#  include <resolv.h>
     62#endif
    6263
    6364#if defined (QT_NO_GETADDRINFO)
     
    122123{
    123124    QHostInfo results;
    124     results.setHostName(hostName);
    125125
    126126#if defined(QHOSTINFO_DEBUG)
     
    149149        // Reverse lookup
    150150// Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead.
    151 #if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN)
     151#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) && !defined (Q_OS_SYMBIAN)
    152152        sockaddr_in sa4;
    153153#ifndef QT_NO_IPV6
     
    174174
    175175        char hbuf[NI_MAXHOST];
    176         if (!sa || getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) != 0) {
    177             results.setError(QHostInfo::HostNotFound);
    178             results.setErrorString(tr("Host not found"));
    179             return results;
    180         }
    181         results.setHostName(QString::fromLatin1(hbuf));
     176        if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0)
     177            results.setHostName(QString::fromLatin1(hbuf));
    182178#else
    183         in_addr_t inetaddr = inet_addr(hostName.toLatin1().constData());
     179        in_addr_t inetaddr = qt_safe_inet_addr(hostName.toLatin1().constData());
    184180        struct hostent *ent = gethostbyaddr((const char *)&inetaddr, sizeof(inetaddr), AF_INET);
    185         if (!ent) {
    186             results.setError(QHostInfo::HostNotFound);
    187             results.setErrorString(tr("Host not found"));
    188             return results;
    189         }
    190         results.setHostName(QString::fromLatin1(ent->h_name));
    191 #endif
     181        if (ent)
     182            results.setHostName(QString::fromLatin1(ent->h_name));
     183#endif
     184
     185        if (results.hostName().isEmpty())
     186            results.setHostName(address.toString());
     187        results.setAddresses(QList<QHostAddress>() << address);
     188        return results;
     189    }
     190
     191    // IDN support
     192    QByteArray aceHostname = QUrl::toAce(hostName);
     193    results.setHostName(hostName);
     194    if (aceHostname.isEmpty()) {
     195        results.setError(QHostInfo::HostNotFound);
     196        results.setErrorString(hostName.isEmpty() ? QObject::tr("No host name given") : QObject::tr("Invalid hostname"));
     197        return results;
    192198    }
    193199
     
    203209#endif
    204210
    205     int result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res);
     211    int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res);
    206212# ifdef Q_ADDRCONFIG
    207213    if (result == EAI_BADFLAGS) {
    208214        // if the lookup failed with AI_ADDRCONFIG set, try again without it
    209215        hints.ai_flags = 0;
    210         result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res);
     216        result = getaddrinfo(aceHostname.constData(), 0, &hints, &res);
    211217    }
    212218# endif
     
    262268    // must be provided.
    263269    QMutexLocker locker(::getHostByNameMutex());
    264     hostent *result = gethostbyname(hostName.toLatin1().constData());
     270    hostent *result = gethostbyname(aceHostname.constData());
    265271    if (result) {
    266272        if (result->h_addrtype == AF_INET) {
     
    277283            results.setErrorString(tr("Unknown address type"));
    278284        }
     285#if !defined(Q_OS_VXWORKS)
    279286    } else if (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA
    280287               || h_errno == NO_ADDRESS) {
    281288        results.setError(QHostInfo::HostNotFound);
    282289        results.setErrorString(tr("Host not found"));
     290#endif
    283291    } else {
    284292        results.setError(QHostInfo::UnknownError);
     
    317325QString QHostInfo::localDomainName()
    318326{
     327#if !defined(Q_OS_VXWORKS)
    319328    resolveLibrary();
    320329    if (local_res_ninit) {
    321330        // using thread-safe version
    322331        res_state_ptr state = res_state_ptr(qMalloc(sizeof(*state)));
     332        Q_CHECK_PTR(state);
    323333        memset(state, 0, sizeof(*state));
    324334        local_res_ninit(state);
     
    346356        return domainName;
    347357    }
    348 
     358#endif
    349359    // nothing worked, try doing it by ourselves:
    350360    QFile resolvconf;
  • trunk/src/network/kernel/qhostinfo_win.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5353#include <qtimer.h>
    5454#include <qmutex.h>
     55#include <qurl.h>
    5556#include <private/qmutexpool_p.h>
    5657
     
    7172    sockaddr *ai_addr;
    7273    qt_addrinfo *ai_next;
    73 };
    74 
    75 // sockaddr_in6 size changed between old and new SDK
    76 // Only the new version is the correct one, so always
    77 // use this structure.
    78 struct qt_in6_addr {
    79     uchar qt_s6_addr[16];
    80 };
    81 
    82 struct qt_sockaddr_in6 {
    83     short   sin6_family;            /* AF_INET6 */
    84     u_short sin6_port;              /* Transport level port number */
    85     u_long  sin6_flowinfo;          /* IPv6 flow information */
    86     struct  qt_in6_addr sin6_addr;  /* IPv6 address */
    87     u_long  sin6_scope_id;          /* set of interfaces for a scope */
    8874};
    8975
     
    120106QMutex qPrivCEMutex;
    121107#endif
    122 /*
    123     Performs a blocking call to gethostbyname or getaddrinfo, stores
    124     the results in a QHostInfo structure and emits the
    125     resultsReady() signal.
    126 */
     108
    127109QHostInfo QHostInfoAgent::fromName(const QString &hostName)
    128110{
     
    145127
    146128    QHostInfo results;
    147     results.setHostName(hostName);
    148129
    149130#if defined(QHOSTINFO_DEBUG)
     
    176157
    177158            char hbuf[NI_MAXHOST];
    178             if (local_getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) != 0) {
    179                 results.setError(QHostInfo::HostNotFound);
    180                 results.setErrorString(tr("Host not found"));
    181                 return results;
    182             }
    183             results.setHostName(QString::fromLatin1(hbuf));
     159            if (local_getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0)
     160                results.setHostName(QString::fromLatin1(hbuf));
    184161        } else {
    185162            unsigned long addr = inet_addr(hostName.toLatin1().constData());
    186163            struct hostent *ent = gethostbyaddr((const char*)&addr, sizeof(addr), AF_INET);
    187             if (!ent) {
    188                 results.setError(QHostInfo::HostNotFound);
    189                 results.setErrorString(tr("Host not found"));
    190                 return results;
    191             }
    192             results.setHostName(QString::fromLatin1(ent->h_name));
    193         }
     164            if (ent)
     165                results.setHostName(QString::fromLatin1(ent->h_name));
     166        }
     167
     168        if (results.hostName().isEmpty())
     169            results.setHostName(address.toString());
     170        results.setAddresses(QList<QHostAddress>() << address);
     171        return results;
     172    }
     173
     174    // IDN support
     175    QByteArray aceHostname = QUrl::toAce(hostName);
     176    results.setHostName(hostName);
     177    if (aceHostname.isEmpty()) {
     178        results.setError(QHostInfo::HostNotFound);
     179        results.setErrorString(hostName.isEmpty() ? tr("No host name given") : tr("Invalid hostname"));
     180        return results;
    194181    }
    195182
     
    199186        // results.
    200187        qt_addrinfo *res;
    201         int err = local_getaddrinfo(hostName.toLatin1().constData(), 0, 0, &res);
     188        int err = local_getaddrinfo(aceHostname.constData(), 0, 0, &res);
    202189        if (err == 0) {
    203190            QList<QHostAddress> addresses;
     
    234221    } else {
    235222        // Fall back to gethostbyname, which only supports IPv4.
    236         hostent *ent = gethostbyname(hostName.toLatin1().constData());
     223        hostent *ent = gethostbyname(aceHostname.constData());
    237224        if (ent) {
    238225            char **p;
  • trunk/src/network/kernel/qnetworkinterface.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    129129        if (i)
    130130            result += QLatin1Char(':');
    131        
     131
    132132        char buf[3];
    133133#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
     
    149149    \since 4.2
    150150    \reentrant
    151     \ingroup io
     151    \ingroup network
    152152
    153153    Each network interface can contain zero or more IP addresses, which
     
    171171*/
    172172QNetworkAddressEntry::QNetworkAddressEntry(const QNetworkAddressEntry &other)
    173     : d(new QNetworkAddressEntryPrivate(*other.d))
     173    : d(new QNetworkAddressEntryPrivate(*other.d.data()))
    174174{
    175175}
     
    180180QNetworkAddressEntry &QNetworkAddressEntry::operator=(const QNetworkAddressEntry &other)
    181181{
    182     *d = *other.d;
     182    *d.data() = *other.d.data();
    183183    return *this;
    184184}
     
    189189QNetworkAddressEntry::~QNetworkAddressEntry()
    190190{
    191     delete d;
    192191}
    193192
     
    334333    \since 4.2
    335334    \reentrant
    336     \ingroup io
     335    \ingroup network
    337336
    338337    QNetworkInterface represents one network interface attached to the
     
    398397
    399398/*!
    400     Creates a copy of the the QNetworkInterface object contained in \a
     399    Creates a copy of the QNetworkInterface object contained in \a
    401400    other.
    402401*/
     
    595594    if (!entry.broadcast().isNull())
    596595        debug.nospace() << ", broadcast = " << entry.broadcast();
    597     debug.nospace() << ")";
     596    debug.nospace() << ')';
    598597    return debug.space();
    599598}
     
    605604                    << ", flags = ";
    606605    flagsDebug(debug, networkInterface.flags());
     606#if defined(Q_CC_RVCT)
     607    // RVCT gets confused with << networkInterface.addressEntries(), reason unknown.
     608    debug.nospace() << ")\n";
     609#else
    607610    debug.nospace() << ", entries = " << networkInterface.addressEntries()
    608611                    << ")\n";
     612#endif
    609613    return debug.space();
    610614}
  • trunk/src/network/kernel/qnetworkinterface.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444
    4545#include <QtCore/qshareddata.h>
     46#include <QtCore/qscopedpointer.h>
    4647#include <QtNetwork/qhostaddress.h>
    4748
     
    8081
    8182private:
    82     QNetworkAddressEntryPrivate *d;
     83    QScopedPointer<QNetworkAddressEntryPrivate> d;
    8384};
    8485
  • trunk/src/network/kernel/qnetworkinterface_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/kernel/qnetworkinterface_unix.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444#include "qnetworkinterface_p.h"
    4545#include "qalgorithms.h"
     46#include "private/qnet_unix_p.h"
    4647
    4748#ifndef QT_NO_NETWORKINTERFACE
     
    124125
    125126        // get the interface list
    126         if (::ioctl(socket, SIOCGIFCONF, &interfaceList) >= 0) {
     127        if (qt_safe_ioctl(socket, SIOCGIFCONF, &interfaceList) >= 0) {
    127128            if (int(interfaceList.ifc_len + sizeof(ifreq) + 64) < storageBuffer.size()) {
    128129                // if the buffer was big enough, break
     
    199200        // Get the canonical name
    200201        QByteArray oldName = req.ifr_name;
    201         if (::ioctl(socket, SIOCGIFNAME, &req) >= 0) {
     202        if (qt_safe_ioctl(socket, SIOCGIFNAME, &req) >= 0) {
    202203            iface->name = QString::fromLatin1(req.ifr_name);
    203204
     
    212213
    213214        // Get interface flags
    214         if (::ioctl(socket, SIOCGIFFLAGS, &req) >= 0) {
     215        if (qt_safe_ioctl(socket, SIOCGIFFLAGS, &req) >= 0) {
    215216            iface->flags = convertFlags(req.ifr_flags);
    216217        }
     
    218219#ifdef SIOCGIFHWADDR
    219220        // Get the HW address
    220         if (::ioctl(socket, SIOCGIFHWADDR, &req) >= 0) {
     221        if (qt_safe_ioctl(socket, SIOCGIFHWADDR, &req) >= 0) {
    221222            uchar *addr = (uchar *)&req.ifr_addr;
    222223            iface->hardwareAddress = iface->makeHwAddress(6, addr);
     
    233234
    234235    int socket;
    235     if ((socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
     236    if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
    236237        return interfaces;      // error
    237238
     
    248249        QNetworkAddressEntry entry;
    249250        if (iface->flags & QNetworkInterface::CanBroadcast) {
    250             if (::ioctl(socket, SIOCGIFBRDADDR, &req) >= 0) {
     251            if (qt_safe_ioctl(socket, SIOCGIFBRDADDR, &req) >= 0) {
    251252                sockaddr *sa = &req.ifr_addr;
    252253                if (sa->sa_family == AF_INET)
     
    256257
    257258        // Get the interface netmask
    258         if (::ioctl(socket, SIOCGIFNETMASK, &req) >= 0) {
     259        if (qt_safe_ioctl(socket, SIOCGIFNETMASK, &req) >= 0) {
    259260            sockaddr *sa = &req.ifr_addr;
    260261            entry.setNetmask(addressFromSockaddr(sa));
     
    262263
    263264        // Get the address of the interface
    264         if (::ioctl(socket, SIOCGIFADDR, &req) >= 0) {
     265        if (qt_safe_ioctl(socket, SIOCGIFADDR, &req) >= 0) {
    265266            sockaddr *sa = &req.ifr_addr;
    266267            entry.setIp(addressFromSockaddr(sa));
     
    393394
    394395    int socket;
    395     if ((socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
     396    if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
    396397        return interfaces;      // error
    397398
  • trunk/src/network/kernel/qnetworkinterface_win.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6767        done = true;
    6868
    69         HINSTANCE iphlpapiHnd;
    70         QT_WA({
    71                 iphlpapiHnd = LoadLibraryW(L"iphlpapi");
    72             }, {
    73                 iphlpapiHnd = LoadLibraryA("iphlpapi");
    74             });
     69        HINSTANCE iphlpapiHnd = LoadLibrary(L"iphlpapi");
    7570        if (iphlpapiHnd == NULL)
    76             return;             // failed to load, probably Windows 95
     71            return;
    7772
    7873#if defined(Q_OS_WINCE)
    79         ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddressW(iphlpapiHnd, L"GetAdaptersInfo");
    80         ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddressW(iphlpapiHnd, L"GetAdaptersAddresses");
    81         ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddressW(iphlpapiHnd, L"GetNetworkParams");
     74        ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, L"GetAdaptersInfo");
     75        ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, L"GetAdaptersAddresses");
     76        ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, L"GetNetworkParams");
    8277#else
    8378        ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, "GetAdaptersInfo");
     
    116111        // need more memory
    117112        pAdapter = (IP_ADAPTER_INFO *)qMalloc(bufSize);
     113        if (!pAdapter)
     114            return ipv4netmasks;
    118115        // try again
    119116        if (ptrGetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) {
     
    157154        // need more memory
    158155        pAdapter = (IP_ADAPTER_ADDRESSES *)qMalloc(bufSize);
    159 
     156        if (!pAdapter)
     157            return interfaces;
    160158        // try again
    161159        if (ptrGetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize) != ERROR_SUCCESS) {
     
    237235        // need more memory
    238236        pAdapter = (IP_ADAPTER_INFO *)qMalloc(bufSize);
    239 
     237        if (!pAdapter)
     238            return interfaces;
    240239        // try again
    241240        if (ptrGetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) {
     
    307306    if (ptrGetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) {
    308307        pinfo = (FIXED_INFO *)qMalloc(bufSize);
    309 
     308        if (!pinfo)
     309            return QString();
    310310        // try again
    311311        if (ptrGetNetworkParams(pinfo, &bufSize) != ERROR_SUCCESS) {
  • trunk/src/network/kernel/qnetworkinterface_win_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5555
    5656#include <winsock2.h>
    57 #include <windows.h>
     57#include <qt_windows.h>
    5858#include <time.h>
    5959
  • trunk/src/network/kernel/qnetworkproxy.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4949
    5050    \reentrant
    51     \ingroup io
     51    \ingroup network
    5252    \inmodule QtNetwork
    5353
     
    5555    proxy support to the Qt network classes. The currently supported
    5656    classes are QAbstractSocket, QTcpSocket, QUdpSocket, QTcpServer,
    57     QHttp and QFtp. The proxy support is designed to be as transparent
    58     as possible. This means that existing network-enabled applications
    59     that you have written should automatically support network proxy
    60     using the following code.
     57    QNetworkAccessManager and QFtp. The proxy support is designed to
     58    be as transparent as possible. This means that existing
     59    network-enabled applications that you have written should
     60    automatically support network proxy using the following code.
    6161
    6262    \snippet doc/src/snippets/code/src_network_kernel_qnetworkproxy.cpp 0
     
    8787    The supported authentication methods are no authentication and
    8888    username/password authentication.  Both IPv4 and IPv6 are
    89     supported, but domain name resolution via the SOCKS server is not
    90     supported; i.e. all domain names are resolved locally. There are
    91     several things to remember when using SOCKS5 with QUdpSocket and
    92     QTcpServer:
     89    supported. Domain names are resolved through the SOCKS5 server if
     90    the QNetworkProxy::HostNameLookupCapability is enabled, otherwise
     91    they are resolved locally and the IP address is sent to the
     92    server. There are several things to remember when using SOCKS5
     93    with QUdpSocket and QTcpServer:
    9394
    9495    With QUdpSocket, a call to \l {QUdpSocket::bind()}{bind()} may fail
     
    160161        \o Caching-only HTTP
    161162        \o Implemented using normal HTTP commands, it is useful only
    162            in the context of HTTP requests (see QHttp,
    163            QNetworkAccessManager)
     163           in the context of HTTP requests (see QNetworkAccessManager)
    164164        \o CachingCapability, HostNameLookupCapability
    165165
     
    221221#ifndef QT_NO_NETWORKPROXY
    222222
     223#include "private/qnetworkproxy_p.h"
    223224#include "private/qsocks5socketengine_p.h"
    224225#include "private/qhttpsocketengine_p.h"
     
    324325}
    325326
    326 Q_GLOBAL_STATIC(QGlobalNetworkProxy, globalNetworkProxy);
     327Q_GLOBAL_STATIC(QGlobalNetworkProxy, globalNetworkProxy)
    327328
    328329namespace {
     
    366367    };
    367368
    368     Q_ASSERT(int(type) >= 0 && int(type) <= int(QNetworkProxy::FtpCachingProxy));
     369    if (int(type) < 0 || int(type) > int(QNetworkProxy::FtpCachingProxy))
     370        type = QNetworkProxy::DefaultProxy;
    369371    return QNetworkProxy::Capabilities(defaults[int(type)]);
    370372}
     
    379381    quint16 port;
    380382    QNetworkProxy::ProxyType type;
     383    bool capabilitiesSet;
    381384
    382385    inline QNetworkProxyPrivate(QNetworkProxy::ProxyType t = QNetworkProxy::DefaultProxy,
     
    388391          capabilities(defaultCapabilitiesForType(t)),
    389392          port(p),
    390           type(t)
     393          type(t),
     394          capabilitiesSet(false)
    391395    { }
    392396
     
    491495
    492496    Note that changing the type of a proxy does not change
    493     the set of capabilities this QNetworkProxy object holds.
     497    the set of capabilities this QNetworkProxy object holds if any
     498    capabilities have been set with setCapabilities().
    494499
    495500    \sa type(), setCapabilities()
     
    498503{
    499504    d->type = type;
     505    if (!d->capabilitiesSet)
     506        d->capabilities = defaultCapabilitiesForType(type);
    500507}
    501508
     
    520527{
    521528    d->capabilities = capabilities;
     529    d->capabilitiesSet = true;
    522530}
    523531
     
    11121120    \since 4.5
    11131121
    1114     \ingroup io
     1122    \ingroup network
    11151123    \inmodule QtNetwork
    11161124
     
    11481156QNetworkProxyFactory::~QNetworkProxyFactory()
    11491157{
     1158}
     1159
     1160
     1161/*!
     1162    Enables the use of the platform-specific proxy settings, and only those.
     1163    See systemProxyForQuery() for more information.
     1164
     1165    Internally, this method (when called with \a enable set to true)
     1166    sets an application-wide proxy factory. For this reason, this method
     1167    is mutually exclusive with setApplicationProxyFactory: calling
     1168    setApplicationProxyFactory overrides the use of the system-wide proxy,
     1169    and calling setUseSystemConfiguration overrides any
     1170    application proxy or proxy factory that was previously set.
     1171
     1172    \since 4.6
     1173*/
     1174void QNetworkProxyFactory::setUseSystemConfiguration(bool enable)
     1175{
     1176    if (enable) {
     1177        setApplicationProxyFactory(new QSystemConfigurationProxyFactory);
     1178    } else {
     1179        setApplicationProxyFactory(0);
     1180    }
    11501181}
    11511182
     
    12511282}
    12521283
     1284QT_END_NAMESPACE
     1285
    12531286#endif // QT_NO_NETWORKPROXY
    1254 
    1255 QT_END_NAMESPACE
  • trunk/src/network/kernel/qnetworkproxy.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    172172    virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery()) = 0;
    173173
     174    static void setUseSystemConfiguration(bool enable);
    174175    static void setApplicationProxyFactory(QNetworkProxyFactory *factory);
    175176    static QList<QNetworkProxy> proxyForQuery(const QNetworkProxyQuery &query);
  • trunk/src/network/kernel/qnetworkproxy_generic.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/kernel/qnetworkproxy_mac.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    171171            QString url = QCFString::toQString(pacUrl);
    172172
    173             // ### Use PAC somehow
    174             qDebug("Mac system proxy: found PAC script at \"%s\"", qPrintable(url));
     173            // ### TODO: Use PAC somehow
    175174        }
    176175    }
  • trunk/src/network/kernel/qnetworkproxy_win.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4343
    4444#ifndef QT_NO_NETWORKPROXY
    45 
    46 #if defined(UNICODE)
    4745
    4846#include <qmutex.h>
     
    5250
    5351#include <string.h>
    54 #include <windows.h>
     52#include <qt_windows.h>
    5553#include <wininet.h>
    5654
     
    270268        return;
    271269    initialized = true;
    272     if (QSysInfo::windowsVersion() & QSysInfo::WV_DOS_based)
    273         return;                 // no point, this library is only available on 2k, XP and up
    274270
    275271#ifdef Q_OS_WINCE
     
    278274#else
    279275    // load the winhttp.dll library
    280     HINSTANCE winhttpHnd = LoadLibraryW(L"winhttp");
     276    HINSTANCE winhttpHnd = LoadLibrary(L"winhttp");
    281277    if (!winhttpHnd)
    282278        return;                 // failed to load
     
    296292        }
    297293        if (ieProxyConfig.lpszProxy) {
    298             proxyServerList << QString::fromWCharArray(ieProxyConfig.lpszProxy);
     294            // http://msdn.microsoft.com/en-us/library/aa384250%28VS.85%29.aspx speaks only about a "proxy URL",
     295            // not multiple URLs. However we tested this and it can return multiple URLs. So we use splitSpaceSemicolon
     296            // on it.
     297            proxyServerList = splitSpaceSemicolon(QString::fromWCharArray(ieProxyConfig.lpszProxy));
    299298            GlobalFree(ieProxyConfig.lpszProxy);
    300299        }
     
    368367        WINHTTP_PROXY_INFO proxyInfo;
    369368
    370         // try to get the proxy config for the URL, if we have a URL
     369        // try to get the proxy config for the URL
    371370        QUrl url = query.url();
     371        // url could be empty, e.g. from QNetworkProxy::applicationProxy(), that's fine,
     372        // we'll still ask for the proxy.
     373        // But for a file url, we know we don't need one.
     374        if (url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("qrc"))
     375            return sp->defaultResult;
    372376        if (query.queryType() != QNetworkProxyQuery::UrlRequest) {
    373377            // change the scheme to https, maybe it'll work
     
    399403        return sp->defaultResult;
    400404
    401     return parseServerList(query, sp->proxyServerList);
    402 }
    403 
    404 #else  // !UNICODE
    405 
    406 QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &)
    407 {
    408     return QList<QNetworkProxy>() << QNetworkProxy::NoProxy;
    409 }
     405    QList<QNetworkProxy> result = parseServerList(query, sp->proxyServerList);
     406    // In some cases, this was empty. See SF task 00062670
     407    if (result.isEmpty())
     408        return sp->defaultResult;
     409
     410    return result;
     411}
     412
     413QT_END_NAMESPACE
    410414
    411415#endif
    412 
    413 QT_END_NAMESPACE
    414 
    415 #endif
  • trunk/src/network/kernel/qurlinfo.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    8686
    8787    \ingroup io
    88     \ingroup misc
     88    \ingroup network
    8989
    9090    The information about a URL that can be retrieved includes name(),
     
    216216/*!
    217217    Sets the name of the URL to \a name. The name is the full text,
    218     for example, "http://doc.trolltech.com/qurlinfo.html".
     218    for example, "http://qt.nokia.com/doc/qurlinfo.html".
    219219
    220220    If you call this function for an invalid URL info, this function
     
    727727}
    728728
     729QT_END_NAMESPACE
     730
    729731#endif // QT_NO_URLINFO
    730 
    731 QT_END_NAMESPACE
  • trunk/src/network/kernel/qurlinfo.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/network.pro

    r160 r561  
    77QPRO_PWD = $$PWD
    88DEFINES += QT_BUILD_NETWORK_LIB QT_NO_USING_NAMESPACE
     9#DEFINES += QLOCALSERVER_DEBUG QLOCALSOCKET_DEBUG
     10#DEFINES += QNETWORKDISKCACHE_DEBUG
     11#DEFINES += QSSLSOCKET_DEBUG
     12#DEFINES += QHOSTINFO_DEBUG
     13#DEFINES += QABSTRACTSOCKET_DEBUG QNATIVESOCKETENGINE_DEBUG
     14#DEFINES += QTCPSOCKETENGINE_DEBUG QTCPSOCKET_DEBUG QTCPSERVER_DEBUG QSSLSOCKET_DEBUG
     15#DEFINES += QUDPSOCKET_DEBUG QUDPSERVER_DEBUG
    916QT = core
    1017win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x64000000
     
    1926
    2027QMAKE_LIBS += $$QMAKE_LIBS_NETWORK
     28
     29
     30symbian {
     31   TARGET.UID3=0x2001B2DE
     32   LIBS += -lesock -linsock
     33}
  • trunk/src/network/socket/qabstractsocket.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4949
    5050    \reentrant
    51     \ingroup io
     51    \ingroup network
    5252    \inmodule QtNetwork
    5353
     
    100100    write buffer size. You can monitor its size by listening to this
    101101    signal.
    102    
     102
    103103    The readyRead() signal is emitted every time a new chunk of data
    104104    has arrived. bytesAvailable() then returns the number of bytes
     
    161161    is available before attempting to read it using operator>>().
    162162
    163     \sa QFtp, QHttp, QTcpServer
     163    \sa QFtp, QNetworkAccessManager, QTcpServer
    164164*/
    165165
     
    200200
    201201    QAbstractSocket::SocketError is not a registered metatype, so for queued
    202     connections, you will have to register it with Q_REGISTER_METATYPE.
    203 
    204     \sa error(), errorString()
     202    connections, you will have to register it with Q_DECLARE_METATYPE() and
     203    qRegisterMetaType().
     204
     205    \sa error(), errorString(), {Creating Custom Qt Types}
    205206*/
    206207
     
    212213
    213214    QAbstractSocket::SocketState is not a registered metatype, so for queued
    214     connections, you will have to register it with Q_REGISTER_METATYPE.
    215 
    216     \sa state()
     215    connections, you will have to register it with Q_REGISTER_METATYPE() and
     216    qRegisterMetaType().
     217
     218    \sa state(), {Creating Custom Qt Types}
    217219*/
    218220
     
    331333*/
    332334
     335/*!
     336    \enum QAbstractSocket::SocketOption
     337    \since 4.6
     338
     339    This enum represents the options that can be set on a socket.
     340    If desired, they can be set after having received the connected() signal from
     341    the socket or after having received a new socket from a QTcpServer.
     342
     343    \value LowDelayOption Try to optimize the socket for low latency. For a QTcpSocket
     344    this would set the TCP_NODELAY option and disable Nagle's algorithm. Set this to 1
     345    to enable.
     346    \value KeepAliveOption Set this to 1 to enable the SO_KEEPALIVE socket option
     347
     348    \sa QAbstractSocket::setSocketOption(), QAbstractSocket::socketOption()
     349*/
     350
    333351#include "qabstractsocket.h"
    334352#include "qabstractsocket_p.h"
     
    436454      socketEngine(0),
    437455      cachedSocketDescriptor(-1),
     456#ifdef Q_OS_LINUX
     457      addToBytesAvailable(0),
     458#endif
    438459      readBufferMaxSize(0),
    439460      readBuffer(QABSTRACTSOCKET_BUFFERSIZE),
     
    442463      blockingTimeout(30000),
    443464      connectTimer(0),
     465      disconnectTimer(0),
    444466      connectTimeElapsed(0),
    445467      hostLookupId(-1),
     468      socketType(QAbstractSocket::UnknownSocketType),
    446469      state(QAbstractSocket::UnconnectedState),
    447470      socketError(QAbstractSocket::UnknownSocketError)
     
    476499        cachedSocketDescriptor = -1;
    477500    }
    478     if (connectTimer) {
     501    if (connectTimer)
    479502        connectTimer->stop();
    480     }
     503    if (disconnectTimer)
     504        disconnectTimer->stop();
    481505}
    482506
     
    648672    if (socketEngine) {
    649673#if defined (Q_OS_WIN)
    650         if (!writeBuffer.isEmpty())
    651             socketEngine->setWriteNotificationEnabled(true);
     674        if (!writeBuffer.isEmpty())
     675            socketEngine->setWriteNotificationEnabled(true);
    652676#else
    653         if (writeBuffer.isEmpty())
    654             socketEngine->setWriteNotificationEnabled(false);
     677        if (writeBuffer.isEmpty() && socketEngine->bytesToWrite() == 0)
     678            socketEngine->setWriteNotificationEnabled(false);
    655679#endif
    656680    }
     
    689713{
    690714    Q_Q(QAbstractSocket);
    691     if (!socketEngine || !socketEngine->isValid() || writeBuffer.isEmpty()) {
     715    if (!socketEngine || !socketEngine->isValid() || (writeBuffer.isEmpty()
     716        && socketEngine->bytesToWrite() == 0)) {
    692717#if defined (QABSTRACTSOCKET_DEBUG)
    693718    qDebug("QAbstractSocketPrivate::flush() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s",
    694719           socketEngine->isValid() ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no");
    695720#endif
     721
     722        // this covers the case when the buffer was empty, but we had to wait for the socket engine to finish
     723        if (state == QAbstractSocket::ClosingState)
     724            q->disconnectFromHost();
     725
    696726        return false;
    697727    }
     
    730760    }
    731761
    732     if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled())
     762    if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled()
     763        && !socketEngine->bytesToWrite())
    733764        socketEngine->setWriteNotificationEnabled(false);
    734765    if (state == QAbstractSocket::ClosingState)
     
    851882        s += addresses.at(i).toString();
    852883    }
    853     s += "}";
     884    s += '}';
    854885    qDebug("QAbstractSocketPrivate::_q_startConnecting(hostInfo == %s)", s.toLatin1().constData());
    855886#endif
     
    10521083    if (socketEngine)
    10531084        socketEngine->setWriteNotificationEnabled(false);
     1085
    10541086    connectTimer->stop();
    10551087
     
    10621094    } else {
    10631095        _q_connectToNextAddress();
     1096    }
     1097}
     1098
     1099void QAbstractSocketPrivate::_q_forceDisconnect()
     1100{
     1101    Q_Q(QAbstractSocket);
     1102    if (socketEngine && socketEngine->isValid() && state == QAbstractSocket::ClosingState) {
     1103        socketEngine->close();
     1104        q->disconnectFromHost();
    10641105    }
    10651106}
     
    11281169/*! \internal
    11291170
    1130     Sets up the the internal state after the connection has succeeded.
     1171    Sets up the internal state after the connection has succeeded.
    11311172*/
    11321173void QAbstractSocketPrivate::fetchConnectionParameters()
     
    12321273    \a hostName may be an IP address in string form (e.g.,
    12331274    "43.195.83.32"), or it may be a host name (e.g.,
    1234     "qtsoftware.com"). QAbstractSocket will do a lookup only if
     1275    "example.com"). QAbstractSocket will do a lookup only if
    12351276    required. \a port is in native byte order.
    12361277
     
    12641305#endif
    12651306
    1266     if (d->state == ConnectedState || d->state == ConnectingState) {
    1267         qWarning("QAbstractSocket::connectToHost() called when already connecting/connected to \"%s\"", qPrintable(hostName));
     1307    if (d->state == ConnectedState || d->state == ConnectingState
     1308        || d->state == ClosingState || d->state == HostLookupState) {
     1309        qWarning("QAbstractSocket::connectToHost() called when already looking up or connecting/connected to \"%s\"", qPrintable(hostName));
    12681310        return;
    12691311    }
     
    15471589}
    15481590
     1591/*!
     1592    \since 4.6
     1593    Sets the given \a option to the value described by \a value.
     1594
     1595    \sa socketOption()
     1596*/
     1597void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
     1598{
     1599#ifndef QT_NO_OPENSSL
     1600    if (QSslSocket *sslSocket = qobject_cast<QSslSocket*>(this)) {
     1601        sslSocket->setSocketOption(option, value);
     1602        return;
     1603    }
     1604#endif
     1605
     1606    if (!d_func()->socketEngine)
     1607        return;
     1608
     1609    switch (option) {
     1610        case LowDelayOption:
     1611            d_func()->socketEngine->setOption(QAbstractSocketEngine::LowDelayOption, value.toInt());
     1612            break;
     1613
     1614        case KeepAliveOption:
     1615            d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveOption, value.toInt());
     1616            break;
     1617    }
     1618}
     1619
     1620/*!
     1621    \since 4.6
     1622    Returns the value of the \a option option.
     1623
     1624    \sa setSocketOption()
     1625*/
     1626QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option)
     1627{
     1628#ifndef QT_NO_OPENSSL
     1629    if (QSslSocket *sslSocket = qobject_cast<QSslSocket*>(this)) {
     1630        return sslSocket->socketOption(option);
     1631    }
     1632#endif
     1633
     1634    if (!d_func()->socketEngine)
     1635        return QVariant();
     1636
     1637    int ret = -1;
     1638    switch (option) {
     1639        case LowDelayOption:
     1640            ret = d_func()->socketEngine->option(QAbstractSocketEngine::LowDelayOption);
     1641            break;
     1642
     1643        case KeepAliveOption:
     1644            ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveOption);
     1645            break;
     1646    }
     1647    if (ret == -1)
     1648        return QVariant();
     1649    else
     1650        return QVariant(ret);
     1651}
     1652
     1653
    15491654/*
    15501655   Returns the difference between msecs and elapsed. If msecs is -1,
     
    16571762
    16581763/*!
    1659     This function blocks until data is available for reading and the
     1764    This function blocks until new data is available for reading and the
    16601765    \l{QIODevice::}{readyRead()} signal has been emitted. The function
    16611766    will timeout after \a msecs milliseconds; the default timeout is
     
    16631768
    16641769    The function returns true if the readyRead() signal is emitted and
    1665     there is data available for reading; otherwise it returns false
     1770    there is new data available for reading; otherwise it returns false
    16661771    (if an error occurred or the operation timed out).
    16671772
     
    18651970
    18661971/*!
    1867     Aborts the current connection and resets the socket. Unlike
    1868     disconnectFromHost(), this function immediately closes the socket, discarding
    1869     any pending data in the write buffer.
     1972    Aborts the current connection and resets the socket. Unlike disconnectFromHost(),
     1973    this function immediately closes the socket, discarding any pending data in the
     1974    write buffer.
    18701975
    18711976    \sa disconnectFromHost(), close()
     
    21642269
    21652270/*!
    2166     Disconnects the socket's connection with the host.
     2271    Closes the I/O device for the socket, disconnects the socket's connection with the
     2272    host, closes the socket, and resets the name, address, port number and underlying
     2273    socket descriptor.
     2274
     2275    See QIODevice::close() for a description of the actions that occur when an I/O
     2276    device is closed.
    21672277
    21682278    \sa abort()
     
    22562366
    22572367        // Wait for pending data to be written.
    2258         if (d->socketEngine && d->socketEngine->isValid() && d->writeBuffer.size() > 0) {
     2368        if (d->socketEngine && d->socketEngine->isValid() && (d->writeBuffer.size() > 0
     2369            || d->socketEngine->bytesToWrite() > 0)) {
     2370            // hack: when we are waiting for the socket engine to write bytes (only
     2371            // possible when using Socks5 or HTTP socket engine), then close
     2372            // anyway after 2 seconds. This is to prevent a timeout on Mac, where we
     2373            // sometimes just did not get the write notifier from the underlying
     2374            // CFSocket and no progress was made.
     2375            if (d->writeBuffer.size() == 0 && d->socketEngine->bytesToWrite() > 0) {
     2376                if (!d->disconnectTimer) {
     2377                    d->disconnectTimer = new QTimer(this);
     2378                    connect(d->disconnectTimer, SIGNAL(timeout()), this,
     2379                            SLOT(_q_forceDisconnect()), Qt::DirectConnection);
     2380                }
     2381                if (!d->disconnectTimer->isActive())
     2382                    d->disconnectTimer->start(2000);
     2383            }
    22592384            d->socketEngine->setWriteNotificationEnabled(true);
    22602385
     
    24572582
    24582583#ifdef QT3_SUPPORT
    2459 /*! \enum QAbstractSocket::Error
     2584/*!
     2585    \enum QAbstractSocket::Error
    24602586    \compat
    24612587
     
    25892715        break;
    25902716    default:
    2591         debug << "QAbstractSocket::SocketError(" << int(error) << ")";
     2717        debug << "QAbstractSocket::SocketError(" << int(error) << ')';
    25922718        break;
    25932719    }
     
    26202746        break;
    26212747    default:
    2622         debug << "QAbstractSocket::SocketState(" << int(state) << ")";
     2748        debug << "QAbstractSocket::SocketState(" << int(state) << ')';
    26232749        break;
    26242750    }
  • trunk/src/network/socket/qabstractsocket.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    117117#endif
    118118    };
     119    enum SocketOption {
     120        LowDelayOption, // TCP_NODELAY
     121        KeepAliveOption // SO_KEEPALIVE
     122    };
    119123
    120124    QAbstractSocket(SocketType socketType, QObject *parent);
     
    149153    bool setSocketDescriptor(int socketDescriptor, SocketState state = ConnectedState,
    150154                             OpenMode openMode = ReadWrite);
     155
     156    // ### Qt 5: Make virtual?
     157    void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value);
     158    QVariant socketOption(QAbstractSocket::SocketOption option);
    151159
    152160    SocketType socketType() const;
     
    209217    Q_PRIVATE_SLOT(d_func(), void _q_abortConnectionAttempt())
    210218    Q_PRIVATE_SLOT(d_func(), void _q_testConnection())
     219    Q_PRIVATE_SLOT(d_func(), void _q_forceDisconnect())
    211220
    212221#ifdef QT3_SUPPORT
  • trunk/src/network/socket/qabstractsocket_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of the QLibrary class.  This header file may change from
     50// of the QAbstractSocket class.  This header file may change from
    5151// version to version without notice, or even be removed.
    5252//
     
    9494    void _q_testConnection();
    9595    void _q_abortConnectionAttempt();
     96    void _q_forceDisconnect();
    9697
    9798    bool readSocketNotifierCalled;
     
    149150
    150151    QTimer *connectTimer;
     152    QTimer *disconnectTimer;
    151153    int connectTimeElapsed;
    152154
  • trunk/src/network/socket/qabstractsocketengine.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/socket/qabstractsocketengine_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    9393        AddressReusable,
    9494        BindExclusively,
    95         ReceiveOutOfBandData
     95        ReceiveOutOfBandData,
     96        LowDelayOption,
     97        KeepAliveOption
    9698    };
    9799
     
    124126    virtual qint64 pendingDatagramSize() const = 0;
    125127#endif
     128
     129    virtual qint64 bytesToWrite() const = 0;
    126130
    127131    virtual int option(SocketOption option) const = 0;
  • trunk/src/network/socket/qhttpsocketengine.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    277277#endif // QT_NO_UDPSOCKET
    278278
    279 int QHttpSocketEngine::option(SocketOption) const
    280 {
     279qint64 QHttpSocketEngine::bytesToWrite() const
     280{
     281    Q_D(const QHttpSocketEngine);
     282    if (d->socket) {
     283        return d->socket->bytesToWrite();
     284    } else {
     285        return 0;
     286    }
     287}
     288
     289int QHttpSocketEngine::option(SocketOption option) const
     290{
     291    Q_D(const QHttpSocketEngine);
     292    if (d->socket) {
     293        // convert the enum and call the real socket
     294        if (option == QAbstractSocketEngine::LowDelayOption)
     295            return d->socket->socketOption(QAbstractSocket::LowDelayOption).toInt();
     296        if (option == QAbstractSocketEngine::KeepAliveOption)
     297            return d->socket->socketOption(QAbstractSocket::KeepAliveOption).toInt();
     298    }
    281299    return -1;
    282300}
    283301
    284 bool QHttpSocketEngine::setOption(SocketOption, int)
    285 {
     302bool QHttpSocketEngine::setOption(SocketOption option, int value)
     303{
     304    Q_D(QHttpSocketEngine);
     305    if (d->socket) {
     306        // convert the enum and call the real socket
     307        if (option == QAbstractSocketEngine::LowDelayOption)
     308            d->socket->setSocketOption(QAbstractSocket::LowDelayOption, value);
     309        if (option == QAbstractSocketEngine::KeepAliveOption)
     310            d->socket->setSocketOption(QAbstractSocket::KeepAliveOption, value);
     311        return true;
     312    }
    286313    return false;
    287314}
     
    455482    data += " HTTP/1.1\r\n";
    456483    data += "Proxy-Connection: keep-alive\r\n"
     484            "User-Agent: Mozilla/5.0\r\n"
    457485            "Host: " + peerAddress + "\r\n";
    458486    QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(d->authenticator);
     
    735763    , writeNotificationPending(false)
    736764    , connectionNotificationPending(false)
     765    , pendingResponseData(0)
    737766{
    738767    socket = 0;
     
    769798}
    770799
     800QT_END_NAMESPACE
     801
    771802#endif
    772 
    773 QT_END_NAMESPACE
  • trunk/src/network/socket/qhttpsocketengine_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    110110    qint64 pendingDatagramSize() const;
    111111#endif // QT_NO_UDPSOCKET
     112
     113    qint64 bytesToWrite() const;
    112114
    113115    int option(SocketOption option) const;
  • trunk/src/network/socket/qlocalserver.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7878    to use it without one. In that case, you must use waitForNewConnection(),
    7979    which blocks until either a connection is available or a timeout expires.
    80 
    81     Note that this feature is not supported on Windows 9x.
    8280
    8381    \sa QLocalSocket, QTcpServer
     
    277275        return 0;
    278276    QLocalSocket *nextSocket = d->pendingConnections.dequeue();
     277#ifdef Q_OS_SYMBIAN
     278    if(!d->socketNotifier)
     279        return nextSocket;
     280#endif
     281#ifndef QT_LOCALSOCKET_TCP
     282    if (d->pendingConnections.size() <= d->maxPendingConnections)
    279283#ifndef Q_OS_WIN
    280     d->socketNotifier->setEnabled(d->pendingConnections.size()
    281                                    <= d->maxPendingConnections);
     284        d->socketNotifier->setEnabled(true);
     285#else
     286        d->connectionEventNotifier->setEnabled(true);
     287#endif
    282288#endif
    283289    return nextSocket;
  • trunk/src/network/socket/qlocalserver.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    8787private:
    8888    Q_DISABLE_COPY(QLocalServer)
    89 #if defined(QT_LOCALSOCKET_TCP)
    9089    Q_PRIVATE_SLOT(d_func(), void _q_onNewConnection())
    91 #elif defined(Q_OS_WIN)
    92     Q_PRIVATE_SLOT(d_func(), void _q_openSocket(HANDLE handle))
    93     Q_PRIVATE_SLOT(d_func(), void _q_stoppedListening())
    94     Q_PRIVATE_SLOT(d_func(), void _q_setError(QAbstractSocket::SocketError error, const QString &errorString))
    95 #else
    96     Q_PRIVATE_SLOT(d_func(), void _q_socketActivated())
    97 #endif
    9890};
    9991
  • trunk/src/network/socket/qlocalserver_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6464#elif defined(Q_OS_WIN)
    6565#   include <qt_windows.h>
    66 #   include <qthread.h>
     66#   include <private/qwineventnotifier_p.h>
    6767#else
    6868#   include <private/qnativesocketengine_p.h>
     
    7272QT_BEGIN_NAMESPACE
    7373
    74 #if defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
    75 
    76 /*!
    77     \internal
    78     QLocalServerThread exists because Windows does not have a
    79     way to provide notifications when there is a new connections to
    80     the server.
    81   */
    82 class QLocalServerThread : public QThread
    83 {
    84     Q_OBJECT
    85 
    86 Q_SIGNALS:
    87     void connected(HANDLE newSocket);
    88     void error(QAbstractSocket::SocketError error, const QString &errorString);
    89 
    90 public:
    91     QLocalServerThread(QObject *parent = 0);
    92     ~QLocalServerThread();
    93     void closeServer();
    94 
    95 public:
    96     QString setName(const QString &name);
    97     void run();
    98     void stop();
    99     bool makeHandle();
    100 
    101     HANDLE gotConnectionEvent;
    102     QQueue<HANDLE> pendingHandles;
    103     int maxPendingConnections;
    104 private:
    105     HANDLE stopEvent;
    106     QString fullServerName;
    107 };
    108 
    109 #endif
    110 
    11174class QLocalServerPrivate : public QObjectPrivate
    11275{
     
    11578public:
    11679    QLocalServerPrivate() :
    117 #if defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
    118             inWaitingFunction(false),
    119 #elif !defined(QT_LOCALSOCKET_TCP)
     80#if !defined(QT_LOCALSOCKET_TCP) && !defined(Q_OS_WIN)
    12081            listenSocket(-1), socketNotifier(0),
    12182#endif
     
    12990    void closeServer();
    13091    void waitForNewConnection(int msec, bool *timedOut);
     92    void _q_onNewConnection();
    13193
    13294#if defined(QT_LOCALSOCKET_TCP)
    133     void _q_onNewConnection();
    13495
    13596    QTcpServer tcpServer;
    13697    QMap<quintptr, QTcpSocket*> socketMap;
    13798#elif defined(Q_OS_WIN)
    138     void _q_openSocket(HANDLE socket);
    139     void _q_stoppedListening();
    140     void _q_setError(QAbstractSocket::SocketError error, const QString &errorString);
     99    struct Listener {
     100        HANDLE handle;
     101        OVERLAPPED overlapped;
     102    };
    141103
    142     QLocalServerThread waitForConnection;
    143     bool inWaitingFunction;
     104    void setError(const QString &function);
     105    bool addListener();
     106
     107    QList<Listener> listeners;
     108    HANDLE eventHandle;
     109    QWinEventNotifier *connectionEventNotifier;
    144110#else
    145111    void setError(const QString &function);
    146     void _q_socketActivated();
    147112
    148113    int listenSocket;
  • trunk/src/network/socket/qlocalserver_tcp.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    9393    if (pendingConnections.isEmpty())
    9494        tcpServer.waitForNewConnection(msec, timedOut);
    95     else
     95    else if (timedOut)
    9696        *timedOut = false;
    9797}
  • trunk/src/network/socket/qlocalserver_unix.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444#include "qlocalsocket.h"
    4545#include "qlocalsocket_p.h"
     46#include "qnet_unix_p.h"
    4647
    4748#ifndef QT_NO_LOCALSERVER
     
    5354#include <qdir.h>
    5455#include <qdatetime.h>
     56
     57#ifdef Q_OS_VXWORKS
     58#  include <selectLib.h>
     59#endif
    5560
    5661QT_BEGIN_NAMESPACE
     
    8994
    9095    // create the unix socket
    91     listenSocket = qSocket(PF_UNIX, SOCK_STREAM, 0);
     96    listenSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0);
    9297    if (-1 == listenSocket) {
    9398        setError(QLatin1String("QLocalServer::listen"));
     
    107112             fullServerName.toLatin1().size() + 1);
    108113
     114#ifdef Q_OS_SYMBIAN
     115    // In SYMBIAN OS it can currently happen that accept is called twice,
     116    // once from waitForNewConnection and once via QSocketNotfier activity
     117    //
     118    // As an workaround, we set the socket to non blocking so possible
     119    // subsequent call to accept will not block in any case
     120    //
     121    // This change can be removed once more generic fix to select thread
     122    // syncronization problem is implemented.
     123    int flags = fcntl(listenSocket, F_GETFL, 0);
     124    if (-1 == flags
     125        || -1 == (fcntl(listenSocket, F_SETFL, flags | O_NONBLOCK))) {
     126        setError(QLatin1String("QLocalServer::listen"));
     127        closeServer();
     128        return false;
     129    }
     130#endif
     131
    109132    // bind
    110     if(-1 == qBind(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
     133    if(-1 == QT_SOCKET_BIND(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
    111134        setError(QLatin1String("QLocalServer::listen"));
    112135        // if address is in use already, just close the socket, but do not delete the file
     
    121144
    122145    // listen for connections
    123     if (-1 == qListen(listenSocket, 50)) {
     146    if (-1 == qt_safe_listen(listenSocket, 50)) {
    124147        setError(QLatin1String("QLocalServer::listen"));
    125148        closeServer();
     
    133156                                         QSocketNotifier::Read, q);
    134157    q->connect(socketNotifier, SIGNAL(activated(int)),
    135                q, SLOT(_q_socketActivated()));
     158               q, SLOT(_q_onNewConnection()));
    136159    socketNotifier->setEnabled(maxPendingConnections > 0);
    137160    return true;
     
    149172    listenSocket = -1;
    150173
    151     if (socketNotifier)
     174    if (socketNotifier) {
     175        socketNotifier->setEnabled(false); // Otherwise, closed socket is checked before deleter runs
    152176        socketNotifier->deleteLater();
    153     socketNotifier = 0;
     177        socketNotifier = 0;
     178    }
    154179
    155180    if (!fullServerName.isEmpty())
     
    163188    Accept the new socket.
    164189 */
    165 void QLocalServerPrivate::_q_socketActivated()
     190void QLocalServerPrivate::_q_onNewConnection()
    166191{
    167192    Q_Q(QLocalServer);
     
    171196    ::sockaddr_un addr;
    172197    QT_SOCKLEN_T length = sizeof(sockaddr_un);
    173     int connectedSocket = qAccept(listenSocket, (sockaddr *)&addr, &length);
     198    int connectedSocket = qt_safe_accept(listenSocket, (sockaddr *)&addr, &length);
    174199    if(-1 == connectedSocket) {
    175200        setError(QLatin1String("QLocalSocket::activated"));
     
    192217    timeout.tv_usec = (msec % 1000) * 1000;
    193218
    194     // timeout can not be 0 or else select will return an error.
    195     if (0 == msec)
    196         timeout.tv_usec = 1000;
    197 
    198219    int result = -1;
    199     // on Linux timeout will be updated by select, but _not_ on other systems.
    200     QTime timer;
    201     timer.start();
    202     while (pendingConnections.isEmpty() && (-1 == msec || timer.elapsed() < msec)) {
    203         result = ::select(listenSocket + 1, &readfds, 0, 0, &timeout);
    204         if (-1 == result && errno != EINTR) {
    205             setError(QLatin1String("QLocalServer::waitForNewConnection"));
    206             closeServer();
    207             break;
    208         }
    209         if (result > 0)
    210             _q_socketActivated();
    211     }
     220    result = qt_safe_select(listenSocket + 1, &readfds, 0, 0, (msec == -1) ? 0 : &timeout);
     221    if (-1 == result) {
     222        setError(QLatin1String("QLocalServer::waitForNewConnection"));
     223        closeServer();
     224    }
     225    if (result > 0)
     226        _q_onNewConnection();
    212227    if (timedOut)
    213228        *timedOut = (result == 0);
  • trunk/src/network/socket/qlocalserver_win.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4545
    4646#include <qdebug.h>
    47 #include <qdatetime.h>
    48 #include <qcoreapplication.h>
    49 #include <QMetaType>
    5047
    5148// The buffer size need to be 0 otherwise data could be
     
    5451#define BUFSIZE 0
    5552
     53// ###: This should be a property. Should replace the insane 50 on unix as well.
     54#define SYSTEM_MAX_PENDING_SOCKETS 8
     55
    5656QT_BEGIN_NAMESPACE
    5757
    58 QLocalServerThread::QLocalServerThread(QObject *parent) : QThread(parent),
    59     maxPendingConnections(1)
    60 {
    61     stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    62     gotConnectionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    63 }
    64 
    65 QLocalServerThread::~QLocalServerThread()
    66 {
    67     stop();
    68     closeServer();
    69     CloseHandle(stopEvent);
    70     CloseHandle(gotConnectionEvent);
    71 }
    72 
    73 void QLocalServerThread::stop()
    74 {
    75     if (isRunning()) {
    76         SetEvent(stopEvent);
    77         wait();
    78         ResetEvent(stopEvent);
    79     }
    80 }
    81 
    82 void QLocalServerThread::closeServer()
    83 {
    84     while (!pendingHandles.isEmpty())
    85         CloseHandle(pendingHandles.dequeue());
    86 }
    87 
    88 QString QLocalServerThread::setName(const QString &name)
    89 {
    90     QString pipePath = QLatin1String("\\\\.\\pipe\\");
    91     if (name.startsWith(pipePath))
    92         fullServerName = name;
    93     else
    94         fullServerName = pipePath + name;
    95     for (int i = pendingHandles.count(); i < maxPendingConnections; ++i)
    96         if (!makeHandle())
    97             break;
    98     return fullServerName;
    99 }
    100 
    101 bool QLocalServerThread::makeHandle()
    102 {
    103     if (pendingHandles.count() >= maxPendingConnections)
    104         return false;
    105 
    106     HANDLE handle = INVALID_HANDLE_VALUE;
    107     QT_WA({
    108     handle = CreateNamedPipeW(
    109                  (TCHAR*)fullServerName.utf16(), // pipe name
     58bool QLocalServerPrivate::addListener()
     59{
     60    // The object must not change its address once the
     61    // contained OVERLAPPED struct is passed to Windows.
     62    listeners << Listener();
     63    Listener &listener = listeners.last();
     64
     65    listener.handle = CreateNamedPipe(
     66                 (const wchar_t *)fullServerName.utf16(), // pipe name
    11067                 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,       // read/write access
    11168                 PIPE_TYPE_MESSAGE |       // message type pipe
     
    11774                 3000,                     // client time-out
    11875                 NULL);
    119     }, {
    120     handle = CreateNamedPipeA(
    121                  fullServerName.toLocal8Bit().constData(), // pipe name
    122                  PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,       // read/write access
    123                  PIPE_TYPE_MESSAGE |       // message type pipe
    124                  PIPE_READMODE_MESSAGE |   // message-read mode
    125                  PIPE_WAIT,                // blocking mode
    126                  PIPE_UNLIMITED_INSTANCES, // max. instances
    127                  BUFSIZE,                  // output buffer size
    128                  BUFSIZE,                  // input buffer size
    129                  3000,                     // client time-out
    130                  NULL);
    131     });
    132 
    133     if (INVALID_HANDLE_VALUE == handle) {
     76
     77    if (listener.handle == INVALID_HANDLE_VALUE) {
     78        setError(QLatin1String("QLocalServerPrivate::addListener"));
     79        listeners.removeLast();
    13480        return false;
    13581    }
    136     pendingHandles.enqueue(handle);
     82
     83    memset(&listener.overlapped, 0, sizeof(listener.overlapped));
     84    listener.overlapped.hEvent = eventHandle;
     85    if (!ConnectNamedPipe(listener.handle, &listener.overlapped)) {
     86        switch (GetLastError()) {
     87        case ERROR_IO_PENDING:
     88            break;
     89        case ERROR_PIPE_CONNECTED:
     90            SetEvent(eventHandle);
     91            break;
     92        default:
     93            CloseHandle(listener.handle);
     94            setError(QLatin1String("QLocalServerPrivate::addListener"));
     95            listeners.removeLast();
     96            return false;
     97        }
     98    } else {
     99        Q_ASSERT_X(false, "QLocalServerPrivate::addListener", "The impossible happened");
     100        SetEvent(eventHandle);
     101    }
    137102    return true;
    138103}
    139104
    140 void QLocalServerThread::run()
    141 {
    142     OVERLAPPED  op;
    143     HANDLE      handleArray[2];
    144     memset(&op, 0, sizeof(op));
    145     handleArray[0] = op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    146     handleArray[1] = stopEvent;
    147     HANDLE handle = INVALID_HANDLE_VALUE;
    148 
    149     forever {
    150         if (INVALID_HANDLE_VALUE == handle) {
    151             makeHandle();
    152             if (!pendingHandles.isEmpty())
    153                 handle = pendingHandles.dequeue();
    154         }
    155         if (INVALID_HANDLE_VALUE == handle) {
    156             int windowsError = GetLastError();
    157             QString function = QLatin1String("QLocalServer::run");
    158             QString errorString = QLocalServer::tr("%1: Unknown error %2").arg(function).arg(windowsError);
    159             emit error(QAbstractSocket::UnknownSocketError, errorString);
    160             CloseHandle(handleArray[0]);
    161             SetEvent(gotConnectionEvent);
    162             return;
    163         }
    164 
    165         BOOL isConnected = ConnectNamedPipe(handle, &op) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
    166         if (!isConnected) {
    167             switch (WaitForMultipleObjects(2, handleArray, FALSE, INFINITE))
    168             {
    169             case WAIT_OBJECT_0 + 1:
    170                 CloseHandle(handle);
    171                 CloseHandle(handleArray[0]);
     105void QLocalServerPrivate::setError(const QString &function)
     106{
     107    int windowsError = GetLastError();
     108    errorString = QString::fromLatin1("%1: %2").arg(function).arg(qt_error_string(windowsError));
     109    error = QAbstractSocket::UnknownSocketError;
     110}
     111
     112void QLocalServerPrivate::init()
     113{
     114}
     115
     116bool QLocalServerPrivate::removeServer(const QString &name)
     117{
     118    Q_UNUSED(name);
     119    return true;
     120}
     121
     122bool QLocalServerPrivate::listen(const QString &name)
     123{
     124    Q_Q(QLocalServer);
     125
     126    QString pipePath = QLatin1String("\\\\.\\pipe\\");
     127    if (name.startsWith(pipePath))
     128        fullServerName = name;
     129    else
     130        fullServerName = pipePath + name;
     131
     132    // Use only one event for all listeners of one socket.
     133    // The idea is that listener events are rare, so polling all listeners once in a while is
     134    // cheap compared to waiting for N additional events in each iteration of the main loop.
     135    eventHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
     136    connectionEventNotifier = new QWinEventNotifier(eventHandle , q);
     137    q->connect(connectionEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onNewConnection()));
     138
     139    for (int i = 0; i < SYSTEM_MAX_PENDING_SOCKETS; ++i)
     140        if (!addListener())
     141            return false;
     142    return true;
     143}
     144
     145void QLocalServerPrivate::_q_onNewConnection()
     146{
     147    Q_Q(QLocalServer);
     148    DWORD dummy;
     149
     150    // Reset first, otherwise we could reset an event which was asserted
     151    // immediately after we checked the conn status.
     152    ResetEvent(eventHandle);
     153
     154    // Testing shows that there is indeed absolutely no guarantee which listener gets
     155    // a client connection first, so there is no way around polling all of them.
     156    for (int i = 0; i < listeners.size(); ) {
     157        HANDLE handle = listeners[i].handle;
     158        if (GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) {
     159            listeners.removeAt(i);
     160
     161            addListener();
     162
     163            if (pendingConnections.size() > maxPendingConnections)
     164                connectionEventNotifier->setEnabled(false);
     165
     166            // Make this the last thing so connected slots can wreak the least havoc
     167            q->incomingConnection((quintptr)handle);
     168        } else {
     169            if (GetLastError() != ERROR_IO_INCOMPLETE) {
     170                setError(QLatin1String("QLocalServerPrivate::_q_onNewConnection"));
     171                closeServer();
    172172                return;
    173173            }
     174
     175            ++i;
    174176        }
    175         emit connected(handle);
    176         handle = INVALID_HANDLE_VALUE;
    177         ResetEvent(handleArray[0]);
    178         SetEvent(gotConnectionEvent);
    179     }
    180 }
    181 
    182 void QLocalServerPrivate::init()
    183 {
    184     Q_Q(QLocalServer);
    185     qRegisterMetaType<HANDLE>("HANDLE");
    186     q->connect(&waitForConnection, SIGNAL(connected(HANDLE)),
    187                q, SLOT(_q_openSocket(HANDLE)), Qt::QueuedConnection);
    188     q->connect(&waitForConnection, SIGNAL(finished()),
    189                q, SLOT(_q_stoppedListening()), Qt::QueuedConnection);
    190     q->connect(&waitForConnection, SIGNAL(terminated()),
    191                q, SLOT(_q_stoppedListening()), Qt::QueuedConnection);
    192     q->connect(&waitForConnection, SIGNAL(error(QAbstractSocket::SocketError, const QString &)),
    193                q, SLOT(_q_setError(QAbstractSocket::SocketError, const QString &)));
    194 }
    195 
    196 bool QLocalServerPrivate::removeServer(const QString &name)
    197 {
    198     Q_UNUSED(name);
    199     return true;
    200 }
    201 
    202 bool QLocalServerPrivate::listen(const QString &name)
    203 {
    204     fullServerName = waitForConnection.setName(name);
    205     serverName = name;
    206     waitForConnection.start();
    207     return true;
    208 }
    209 
    210 void QLocalServerPrivate::_q_setError(QAbstractSocket::SocketError e, const QString &eString)
    211 {
    212     error = e;
    213     errorString = eString;
    214 }
    215 
    216 void QLocalServerPrivate::_q_stoppedListening()
    217 {
    218     Q_Q(QLocalServer);
    219     if (!inWaitingFunction)
    220         q->close();
    221 }
    222 
    223 void QLocalServerPrivate::_q_openSocket(HANDLE handle)
    224 {
    225     Q_Q(QLocalServer);
    226     q->incomingConnection((int)handle);
     177    }
    227178}
    228179
    229180void QLocalServerPrivate::closeServer()
    230181{
    231     waitForConnection.stop();
    232     waitForConnection.closeServer();
     182    connectionEventNotifier->setEnabled(false); // Otherwise, closed handle is checked before deleter runs
     183    connectionEventNotifier->deleteLater();
     184    connectionEventNotifier = 0;
     185    CloseHandle(eventHandle);
     186    for (int i = 0; i < listeners.size(); ++i)
     187        CloseHandle(listeners[i].handle);
     188    listeners.clear();
    233189}
    234190
     
    239195        return;
    240196
    241     DWORD result = WaitForSingleObject(waitForConnection.gotConnectionEvent,
    242                                        (msecs == -1) ? INFINITE : msecs);
     197    DWORD result = WaitForSingleObject(eventHandle, (msecs == -1) ? INFINITE : msecs);
    243198    if (result == WAIT_TIMEOUT) {
    244199        if (timedOut)
    245200            *timedOut = true;
    246201    } else {
    247         ResetEvent(waitForConnection.gotConnectionEvent);
    248         QCoreApplication::instance()->processEvents();
     202        _q_onNewConnection();
    249203    }
    250204}
  • trunk/src/network/socket/qlocalsocket.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6464    which blocks until the operation is complete or the timeout expires.
    6565
    66     Note that this feature is not supported on Window 9x.
     66    Note that this feature is not supported on versions of Windows earlier than
     67    Windows XP.
    6768
    6869    \sa QLocalServer
     
    103104    specified by \a socketState.
    104105
    105     Note: It is not possible to initialize two local sockets with the same
     106    \note It is not possible to initialize two local sockets with the same
    106107    native socket descriptor.
    107108
     
    208209    returns false.
    209210
    210     Note: The socket's state must be ConnectedState before reading
     211    \note The socket's state must be ConnectedState before reading
    211212    and writing can occur.
    212213
    213     \sa state()
     214    \sa state(), connectToServer()
    214215*/
    215216
     
    244245
    245246/*!
    246     \fn bool QLocalSocket::waitForConnected(int msec)
    247 
    248     Waits until the socket is connected, up to \a msec milliseconds. If the
     247    \fn bool QLocalSocket::waitForConnected(int msecs)
     248
     249    Waits until the socket is connected, up to \a msecs milliseconds. If the
    249250    connection has been established, this function returns true; otherwise
    250251    it returns false. In the case where it returns false, you can call
     
    256257    \snippet doc/src/snippets/code/src_network_socket_qlocalsocket_unix.cpp 0
    257258
    258     If msecs is -1, this function will not time out.
     259    If \a msecs is -1, this function will not time out.
    259260
    260261    \sa connectToServer(), connected()
     
    275276    \snippet doc/src/snippets/code/src_network_socket_qlocalsocket_unix.cpp 1
    276277
    277     If msecs is -1, this function will not time out.
     278    If \a msecs is -1, this function will not time out.
    278279
    279280    \sa disconnectFromServer(), close()
     
    310311
    311312    QLocalSocket::LocalSocketError is not a registered metatype, so for queued
    312     connections, you will have to register it with Q_DECLARE_METATYPE.
    313 
    314     \sa error(), errorString()
     313    connections, you will have to register it with Q_DECLARE_METATYPE() and
     314    qRegisterMetaType().
     315
     316    \sa error(), errorString(), {Creating Custom Qt Types}
    315317*/
    316318
     
    322324
    323325    QLocalSocket::SocketState is not a registered metatype, so for queued
    324     connections, you will have to register it with Q_DECLARE_METATYPE.
    325 
    326     \sa state()
     326    connections, you will have to register it with Q_DECLARE_METATYPE() and
     327    qRegisterMetaType().
     328
     329    \sa state(), {Creating Custom Qt Types}
    327330*/
    328331
     
    366369    Returns the server path that the socket is connected to.
    367370
    368     Note: This is platform specific
     371    \note The return value of this function is platform specific.
    369372
    370373    \sa connectToServer(), serverName()
     
    469472        break;
    470473    default:
    471         debug << "QLocalSocket::SocketError(" << int(error) << ")";
     474        debug << "QLocalSocket::SocketError(" << int(error) << ')';
    472475        break;
    473476    }
     
    491494        break;
    492495    default:
    493         debug << "QLocalSocket::SocketState(" << int(state) << ")";
     496        debug << "QLocalSocket::SocketState(" << int(state) << ')';
    494497        break;
    495498    }
  • trunk/src/network/socket/qlocalsocket.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    135135    Q_PRIVATE_SLOT(d_func(), void _q_canWrite())
    136136    Q_PRIVATE_SLOT(d_func(), void _q_pipeClosed())
     137    Q_PRIVATE_SLOT(d_func(), void _q_emitReadyRead())
    137138#else
    138139    Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QAbstractSocket::SocketState))
  • trunk/src/network/socket/qlocalsocket_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6666#   include "private/qwindowspipewriter_p.h"
    6767#   include "private/qringbuffer_p.h"
     68#   include <private/qwineventnotifier_p.h>
    6869#else
    6970#   include "private/qnativesocketengine_p.h"
     
    7475
    7576QT_BEGIN_NAMESPACE
    76 
    77 #if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
    78 static inline int qSocket(int af, int socketype, int proto)
    79 {
    80     int ret;
    81     while((ret = qt_socket_socket(af, socketype, proto)) == -1 && errno == EINTR){}
    82     return ret;
    83 }
    84 
    85 static inline int qBind(int fd, const sockaddr *sa, int len)
    86 {
    87     int ret;
    88     while((ret = QT_SOCKET_BIND(fd, (sockaddr*)sa, len)) == -1 && errno == EINTR){}
    89     return ret;
    90 }
    91 
    92 static inline int qConnect(int fd, const sockaddr *sa, int len)
    93 {
    94     int ret;
    95     while((ret = QT_SOCKET_CONNECT(fd, (sockaddr*)sa, len)) == -1 && errno == EINTR){}
    96     return ret;
    97 }
    98 
    99 static inline int qListen(int fd, int backlog)
    100 {
    101     int ret;
    102     while((ret = qt_socket_listen(fd, backlog)) == -1 && errno == EINTR){}
    103     return ret;
    104 }
    105 
    106 static inline int qAccept(int fd, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
    107 {
    108     int ret;
    109     while((ret = qt_socket_accept(fd, addr, addrlen)) == -1 && errno == EINTR){}
    110     return ret;
    111 }
    112 #endif //#if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
    11377
    11478#if !defined(Q_OS_WIN) || defined(QT_LOCALSOCKET_TCP)
     
    173137    void _q_canWrite();
    174138    void _q_pipeClosed();
    175     qint64 readData(char *data, qint64 maxSize);
    176     qint64 bytesAvailable();
    177     bool readFromSocket();
     139    void _q_emitReadyRead();
     140    DWORD bytesAvailable();
     141    void startAsyncRead();
     142    bool completeAsyncRead();
     143    void checkReadyRead();
    178144    HANDLE handle;
    179145    OVERLAPPED overlapped;
     
    181147    qint64 readBufferMaxSize;
    182148    QRingBuffer readBuffer;
    183     QTimer dataNotifier;
     149    int actualReadBufferSize;
     150    QWinEventNotifier *dataReadNotifier;
    184151    QLocalSocket::LocalSocketError error;
    185     bool readyReadEmitted;
     152    bool readSequenceStarted;
     153    bool pendingReadyRead;
    186154    bool pipeClosed;
     155    static const qint64 initialReadBufferSize = 4096;
    187156#else
    188157    QLocalUnixSocket unixSocket;
     
    193162    void _q_connectToSocket();
    194163    void _q_abortConnectionAttempt();
     164    void cancelDelayedConnect();
    195165    QSocketNotifier *delayConnect;
    196166    QTimer *connectTimer;
  • trunk/src/network/socket/qlocalsocket_tcp.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/socket/qlocalsocket_unix.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4242#include "qlocalsocket.h"
    4343#include "qlocalsocket_p.h"
     44#include "qnet_unix_p.h"
    4445
    4546#ifndef QT_NO_LOCALSOCKET
     
    5556#include <qdir.h>
    5657#include <qdebug.h>
     58
     59#ifdef Q_OS_VXWORKS
     60#  include <selectLib.h>
     61#endif
    5762
    5863#define QT_CONNECT_TIMEOUT 30000
     
    233238
    234239    // create the socket
    235     if (-1 == (d->connectingSocket = qSocket(PF_UNIX, SOCK_STREAM, 0))) {
     240    if (-1 == (d->connectingSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0))) {
    236241        d->errorOccurred(UnsupportedSocketOperationError,
    237242                        QLatin1String("QLocalSocket::connectToServer"));
    238243        return;
    239244    }
    240 
     245#ifndef Q_OS_SYMBIAN
    241246    // set non blocking so we can try to connect and it wont wait
    242247    int flags = fcntl(d->connectingSocket, F_GETFL, 0);
     
    247252        return;
    248253    }
     254#endif
    249255
    250256    // _q_connectToSocket does the actual connecting
     
    283289    ::memcpy(name.sun_path, connectingPathName.toLatin1().data(),
    284290             connectingPathName.toLatin1().size() + 1);
    285     if (-1 == qConnect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
     291    if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
    286292        QString function = QLatin1String("QLocalSocket::connectToServer");
    287293        switch (errno)
     
    304310            // Try again later, all of the sockets listening are full
    305311            if (!delayConnect) {
    306                 delayConnect = new QSocketNotifier(connectingSocket, QSocketNotifier::Write);
     312                delayConnect = new QSocketNotifier(connectingSocket, QSocketNotifier::Write, q);
    307313                q->connect(delayConnect, SIGNAL(activated(int)), q, SLOT(_q_connectToSocket()));
    308314            }
     
    323329
    324330    // connected!
    325     if (delayConnect) {
    326         delayConnect->setEnabled(false);
    327         delete delayConnect;
    328         delayConnect = 0;
    329     }
     331    cancelDelayedConnect();
     332
    330333    serverName = connectingName;
    331334    fullServerName = connectingPathName;
     
    374377}
    375378
     379void QLocalSocketPrivate::cancelDelayedConnect()
     380{
     381    if (delayConnect) {
     382        delayConnect->setEnabled(false);
     383        delete delayConnect;
     384        delayConnect = 0;
     385        connectTimer->stop();
     386        delete connectTimer;
     387        connectTimer = 0;
     388    }
     389}
     390
    376391quintptr QLocalSocket::socketDescriptor() const
    377392{
     
    420435    Q_D(QLocalSocket);
    421436    d->unixSocket.close();
    422     if (d->delayConnect) {
    423         d->delayConnect->setEnabled(false);
    424         delete d->delayConnect;
    425         d->delayConnect = 0;
    426         d->connectTimer->stop();
    427         delete d->connectTimer;
    428         d->connectTimer = 0;
    429     }
     437    d->cancelDelayedConnect();
    430438    if (d->connectingSocket != -1)
    431439        ::close(d->connectingSocket);
     
    513521        return (state() == ConnectedState);
    514522
    515     fd_set readfds;
    516     FD_ZERO(&readfds);
    517     FD_SET(d->connectingSocket, &readfds);
     523    fd_set fds;
     524    FD_ZERO(&fds);
     525    FD_SET(d->connectingSocket, &fds);
    518526
    519527    timeval timeout;
     
    531539    while (state() == ConnectingState
    532540           && (-1 == msec || timer.elapsed() < msec)) {
    533         result = ::select(d->connectingSocket + 1, &readfds, 0, 0, &timeout);
     541#ifdef Q_OS_SYMBIAN
     542        // On Symbian, ready-to-write is signaled when non-blocking socket
     543        // connect is finised. Is ready-to-read really used on other
     544        // UNIX paltforms when using non-blocking AF_UNIX socket?
     545        result = ::select(d->connectingSocket + 1, 0, &fds, 0, &timeout);
     546#else
     547        result = ::select(d->connectingSocket + 1, &fds, 0, 0, &timeout);
     548#endif
    534549        if (-1 == result && errno != EINTR) {
    535550            d->errorOccurred( QLocalSocket::UnknownSocketError,
  • trunk/src/network/socket/qlocalsocket_win.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4949QT_BEGIN_NAMESPACE
    5050
    51 #define NOTIFYTIMEOUT 100
    52 
    5351void QLocalSocketPrivate::init()
    5452{
    5553    Q_Q(QLocalSocket);
    56     QObject::connect(&dataNotifier, SIGNAL(timeout()), q, SLOT(_q_notified()));
     54    memset(&overlapped, 0, sizeof(overlapped));
    5755    overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
     56    dataReadNotifier = new QWinEventNotifier(overlapped.hEvent, q);
     57    q->connect(dataReadNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_notified()));
    5858}
    5959
     
    102102       pipeWriter(0),
    103103       readBufferMaxSize(0),
     104       actualReadBufferSize(0),
    104105       error(QLocalSocket::UnknownSocketError),
    105        readyReadEmitted(false),
     106       readSequenceStarted(false),
     107       pendingReadyRead(false),
    106108       pipeClosed(false),
    107109       state(QLocalSocket::UnconnectedState)
     
    138140        DWORD permissions = (openMode & QIODevice::ReadOnly) ? GENERIC_READ : 0;
    139141        permissions |= (openMode & QIODevice::WriteOnly) ? GENERIC_WRITE : 0;
    140         QT_WA({
    141         localSocket = CreateFileW(
    142                        (TCHAR*)d->fullServerName.utf16(),   // pipe name
    143                        permissions,
    144                        0,              // no sharing
    145                        NULL,           // default security attributes
    146                        OPEN_EXISTING,  // opens existing pipe
    147                        0,              // default attributes
    148                        NULL);          // no template file
    149         }, {
    150         localSocket = CreateFileA(
    151                        d->fullServerName.toLocal8Bit().constData(), // pipe name
    152                        permissions,
    153                        0,              // no sharing
    154                        NULL,           // default security attributes
    155                        OPEN_EXISTING,  // opens existing pipe
    156                        0,              // default attributes
    157                        NULL);          // no template file
    158         });
     142        localSocket = CreateFile((const wchar_t *)d->fullServerName.utf16(),   // pipe name
     143                                 permissions,
     144                                 0,              // no sharing
     145                                 NULL,           // default security attributes
     146                                 OPEN_EXISTING,  // opens existing pipe
     147                                 FILE_FLAG_OVERLAPPED,
     148                                 NULL);          // no template file
     149
    159150        if (localSocket != INVALID_HANDLE_VALUE)
    160151            break;
     
    166157
    167158        // All pipe instances are busy, so wait until connected or up to 5 seconds.
    168         QT_WA({
    169             if (!WaitNamedPipeW((TCHAR*)d->fullServerName.utf16(), 5000))
    170                 break;
    171         }, {
    172             if (!WaitNamedPipeA(d->fullServerName.toLocal8Bit().constData(), 5000))
    173                 break;
    174         });
     159        if (!WaitNamedPipe((const wchar_t *)d->fullServerName.utf16(), 5000))
     160            break;
    175161    }
    176162
     
    183169    // we have a valid handle
    184170    d->serverName = name;
    185     if (setSocketDescriptor((quintptr)localSocket), openMode) {
     171    if (setSocketDescriptor((quintptr)localSocket, ConnectedState, openMode)) {
    186172        d->handle = localSocket;
    187173        emit connected();
     
    193179{
    194180    Q_D(QLocalSocket);
    195     if (d->readBuffer.isEmpty()) {
    196         if (!d->readFromSocket()) {
    197             if (d->pipeClosed)
    198                 return -1;
    199             return 0;
    200         }
    201     }
    202 
    203     if (!d->dataNotifier.isActive() && d->threadData->eventDispatcher)
    204         d->dataNotifier.start(NOTIFYTIMEOUT);
    205 
    206     if (d->readBuffer.isEmpty())
    207         return qint64(0);
    208 
    209     // If readFromSocket() read data, copy it to its destination.
    210     if (maxSize == 1) {
     181
     182    qint64 readSoFar;
     183    // If startAsyncRead() read data, copy it to its destination.
     184    if (maxSize == 1 && d->actualReadBufferSize > 0) {
    211185        *data = d->readBuffer.getChar();
    212         return 1;
    213     }
    214 
    215     qint64 bytesToRead = qMin(qint64(d->readBuffer.size()), maxSize);
    216     qint64 readSoFar = 0;
    217     while (readSoFar < bytesToRead) {
    218         const char *ptr = d->readBuffer.readPointer();
    219         int bytesToReadFromThisBlock = qMin(int(bytesToRead - readSoFar),
    220                                             d->readBuffer.nextDataBlockSize());
    221         memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
    222         readSoFar += bytesToReadFromThisBlock;
    223         d->readBuffer.free(bytesToReadFromThisBlock);
    224     }
     186        d->actualReadBufferSize--;
     187        readSoFar = 1;
     188    } else {
     189        qint64 bytesToRead = qMin(qint64(d->actualReadBufferSize), maxSize);
     190        readSoFar = 0;
     191        while (readSoFar < bytesToRead) {
     192            const char *ptr = d->readBuffer.readPointer();
     193            int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
     194                                                qint64(d->readBuffer.nextDataBlockSize()));
     195            memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
     196            readSoFar += bytesToReadFromThisBlock;
     197            d->readBuffer.free(bytesToReadFromThisBlock);
     198            d->actualReadBufferSize -= bytesToReadFromThisBlock;
     199        }
     200    }
     201
     202    if (d->pipeClosed) {
     203        if (readSoFar == 0) {
     204            QTimer::singleShot(0, this, SLOT(_q_pipeClosed()));
     205            return -1;  // signal EOF
     206        }
     207    } else {
     208        if (!d->readSequenceStarted)
     209            d->startAsyncRead();
     210        d->checkReadyRead();
     211    }
     212
    225213    return readSoFar;
    226214}
     
    228216/*!
    229217    \internal
    230     read from the socket
     218    Schedules or cancels a readyRead() emission depending on actual data availability
    231219 */
    232 qint64 QLocalSocketPrivate::readData(char *data, qint64 maxSize)
    233 {
    234     DWORD bytesRead = 0;
    235     overlapped.Offset = 0;
    236     overlapped.OffsetHigh = 0;
    237     bool success = ReadFile(handle, data, maxSize, &bytesRead, &overlapped);
    238     if (!success && GetLastError() == ERROR_IO_PENDING)
    239         if (GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE))
    240             success = true;
    241     if (!success) {
    242         setErrorString(QLatin1String("QLocalSocket::readData"));
    243         return 0;
    244     }
    245     return bytesRead;
     220void QLocalSocketPrivate::checkReadyRead()
     221{
     222    if (actualReadBufferSize > 0) {
     223        if (!pendingReadyRead) {
     224            Q_Q(QLocalSocket);
     225            QTimer::singleShot(0, q, SLOT(_q_emitReadyRead()));
     226            pendingReadyRead = true;
     227        }
     228    } else {
     229        pendingReadyRead = false;
     230    }
    246231}
    247232
     
    250235    Reads data from the socket into the readbuffer
    251236 */
    252 bool QLocalSocketPrivate::readFromSocket()
    253 {
    254     qint64 bytesToRead = bytesAvailable();
    255     if (bytesToRead == 0)
     237void QLocalSocketPrivate::startAsyncRead()
     238{
     239    do {
     240        DWORD bytesToRead = bytesAvailable();
     241        if (bytesToRead == 0) {
     242            // There are no bytes in the pipe but we need to
     243            // start the overlapped read with some buffer size.
     244            bytesToRead = initialReadBufferSize;
     245        }
     246
     247        if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
     248            bytesToRead = readBufferMaxSize - readBuffer.size();
     249            if (bytesToRead == 0) {
     250                // Buffer is full. User must read data from the buffer
     251                // before we can read more from the pipe.
     252                return;
     253            }
     254        }
     255
     256        char *ptr = readBuffer.reserve(bytesToRead);
     257
     258        readSequenceStarted = true;
     259        if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
     260            completeAsyncRead();
     261        } else {
     262            switch (GetLastError()) {
     263                case ERROR_IO_PENDING:
     264                    // This is not an error. We're getting notified, when data arrives.
     265                    return;
     266                case ERROR_PIPE_NOT_CONNECTED:
     267                    {
     268                        // It may happen, that the other side closes the connection directly
     269                        // after writing data. Then we must set the appropriate socket state.
     270                        pipeClosed = true;
     271                        Q_Q(QLocalSocket);
     272                        emit q->readChannelFinished();
     273                        return;
     274                    }
     275                default:
     276                    setErrorString(QLatin1String("QLocalSocketPrivate::startAsyncRead"));
     277                    return;
     278            }
     279        }
     280    } while (!readSequenceStarted);
     281}
     282
     283/*!
     284    \internal
     285    Sets the correct size of the read buffer after a read operation.
     286    Returns false, if an error occured or the connection dropped.
     287 */
     288bool QLocalSocketPrivate::completeAsyncRead()
     289{
     290    ResetEvent(overlapped.hEvent);
     291    readSequenceStarted = false;
     292
     293    DWORD bytesRead;
     294    if (!GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE)) {
     295        if (GetLastError() != ERROR_PIPE_NOT_CONNECTED)
     296            setErrorString(QLatin1String("QLocalSocketPrivate::completeAsyncRead"));
    256297        return false;
    257 
    258     if (readBufferMaxSize && bytesToRead
    259                      > (readBufferMaxSize - readBuffer.size()))
    260         bytesToRead = readBufferMaxSize - readBuffer.size();
    261 
    262     char *ptr = readBuffer.reserve(bytesToRead);
    263     qint64 readBytes = readData(ptr, bytesToRead);
    264     if (readBytes == 0) {
    265         readBuffer.chop(bytesToRead);
    266         return false;
    267     }
    268     readyReadEmitted = false;
    269     readBuffer.chop(int(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes)));
     298    }
     299
     300    actualReadBufferSize += bytesRead;
     301    readBuffer.truncate(actualReadBufferSize);
    270302    return true;
    271303}
     
    276308    if (!d->pipeWriter) {
    277309        d->pipeWriter = new QWindowsPipeWriter(d->handle, this);
     310        connect(d->pipeWriter, SIGNAL(canWrite()), this, SLOT(_q_canWrite()));
     311        connect(d->pipeWriter, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64)));
    278312        d->pipeWriter->start();
    279         connect(d->pipeWriter, SIGNAL(canWrite()), this, SLOT(_q_canWrite()));
    280313    }
    281314    return d->pipeWriter->write(data, maxSize);
     
    290323    The number of bytes available from the pipe
    291324  */
    292 qint64 QLocalSocketPrivate::bytesAvailable()
     325DWORD QLocalSocketPrivate::bytesAvailable()
    293326{
    294327    Q_Q(QLocalSocket);
    295     if (q->state() != QLocalSocket::ConnectedState)
    296         return 0;
    297328    DWORD bytes;
    298329    if (PeekNamedPipe(handle, NULL, 0, NULL, &bytes, NULL)) {
    299330        return bytes;
    300331    } else {
    301         if (ERROR_BROKEN_PIPE == GetLastError() && !pipeClosed) {
     332        if (!pipeClosed) {
    302333            pipeClosed = true;
     334            emit q->readChannelFinished();
    303335            QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
    304336        }
     
    317349    Q_D(const QLocalSocket);
    318350    qint64 available = QIODevice::bytesAvailable();
    319     available += (qint64) d->readBuffer.size();
     351    available += (qint64) d->actualReadBufferSize;
    320352    return available;
    321353}
     
    332364    if (state() != ConnectedState)
    333365        return false;
    334     return (d->readBuffer.indexOf('\n') != -1 || QIODevice::canReadLine());
     366    return (QIODevice::canReadLine()
     367            || d->readBuffer.indexOf('\n', d->actualReadBufferSize) != -1);
    335368}
    336369
     
    344377    d->state = ClosingState;
    345378    emit stateChanged(d->state);
    346     d->readyReadEmitted = false;
    347     emit readChannelFinished();
     379    if (!d->pipeClosed)
     380        emit readChannelFinished();
    348381    d->serverName = QString();
    349382    d->fullServerName = QString();
     
    353386        return;
    354387    }
     388    d->readSequenceStarted = false;
     389    d->pendingReadyRead = false;
    355390    d->pipeClosed = false;
    356391    DisconnectNamedPipe(d->handle);
    357392    CloseHandle(d->handle);
    358393    d->handle = INVALID_HANDLE_VALUE;
     394    ResetEvent(d->overlapped.hEvent);
    359395    d->state = UnconnectedState;
    360396    emit stateChanged(d->state);
     
    364400        d->pipeWriter = 0;
    365401    }
    366     d->dataNotifier.stop();
    367402}
    368403
     
    398433    Q_D(QLocalSocket);
    399434    d->readBuffer.clear();
     435    d->actualReadBufferSize = 0;
    400436    QIODevice::open(openMode);
    401437    d->handle = (int*)socketDescriptor;
    402438    d->state = socketState;
    403439    emit stateChanged(d->state);
    404     if (d->threadData->eventDispatcher)
    405         d->dataNotifier.start(NOTIFYTIMEOUT);
     440    if (d->state == ConnectedState && openMode.testFlag(QIODevice::ReadOnly)) {
     441        d->startAsyncRead();
     442        d->checkReadyRead();
     443    }
    406444    return true;
    407445}
     
    417455{
    418456    Q_Q(QLocalSocket);
    419     if (0 != bytesAvailable()) {
    420         if (readBufferMaxSize == 0 || readBuffer.size() < readBufferMaxSize) {
    421             if (!readFromSocket()) {
    422                 return;
    423             }
    424             // wait until buffer is cleared before starting again
    425             if (readBufferMaxSize && readBuffer.size() == readBufferMaxSize) {
    426                 dataNotifier.stop();
    427             }
    428         }
    429         if (!readyReadEmitted) {
    430             readyReadEmitted = true;
    431             q->emit readyRead();
    432         }
     457    if (!completeAsyncRead()) {
     458        pipeClosed = true;
     459        emit q->readChannelFinished();
     460        return;
     461    }
     462    startAsyncRead();
     463    pendingReadyRead = false;
     464    emit q->readyRead();
     465}
     466
     467void QLocalSocketPrivate::_q_emitReadyRead()
     468{
     469    if (pendingReadyRead) {
     470        Q_Q(QLocalSocket);
     471        pendingReadyRead = false;
     472        emit q->readyRead();
    433473    }
    434474}
     
    463503    if (state() == UnconnectedState)
    464504        return false;
     505    if (!openMode().testFlag(QIODevice::ReadOnly)) {
     506        qWarning("QLocalSocket::waitForDisconnected isn't supported for write only pipes.");
     507        return false;
     508    }
    465509    QIncrementalSleepTimer timer(msecs);
    466510    forever {
    467         d->_q_notified();
    468         if (d->pipeClosed)
    469             close();
     511        d->bytesAvailable();    // to check if PeekNamedPipe fails
     512        if (d->pipeClosed)
     513            close();
    470514        if (state() == UnconnectedState)
    471515            return true;
     
    487531{
    488532    Q_D(QLocalSocket);
    489     QIncrementalSleepTimer timer(msecs);
    490     forever {
    491         d->_q_notified();
    492         if (bytesAvailable() > 0) {
    493             if (!d->readyReadEmitted) {
    494                 d->readyReadEmitted = true;
    495                 emit readyRead();
    496             }
     533
     534    if (bytesAvailable() > 0)
     535        return true;
     536
     537    if (d->state != QLocalSocket::ConnectedState)
     538        return false;
     539
     540    Q_ASSERT(d->readSequenceStarted);
     541    DWORD result = WaitForSingleObject(d->overlapped.hEvent, msecs == -1 ? INFINITE : msecs);
     542    switch (result) {
     543        case WAIT_OBJECT_0:
     544            d->_q_notified();
    497545            return true;
    498         }
    499 
    500         Sleep(timer.nextSleepTime());
    501         if (timer.hasTimedOut())
    502             break;
    503     }
    504 
     546        case WAIT_TIMEOUT:
     547            return false;
     548    }
     549
     550    qWarning("QLocalSocket::waitForReadyRead WaitForSingleObject failed with error code %d.", int(GetLastError()));
    505551    return false;
    506552}
     
    512558        return false;
    513559
    514     QIncrementalSleepTimer timer(msecs);
    515     forever {
    516         if (d->pipeWriter->hadWritten())
    517             return true;
    518 
    519         if (d->pipeWriter->bytesToWrite() == 0)
    520             return false;
    521 
    522         // Wait for the pipe writer to acknowledge that it has
    523         // written. This will succeed if either the pipe writer has
    524         // already written the data, or if it manages to write data
    525         // within the given timeout.
    526         if (d->pipeWriter->waitForWrite(0))
    527             return true;
    528 
    529         Sleep(timer.nextSleepTime());
    530         if (timer.hasTimedOut())
    531             break;
    532     }
    533 
    534     return false;
     560    // Wait for the pipe writer to acknowledge that it has
     561    // written. This will succeed if either the pipe writer has
     562    // already written the data, or if it manages to write data
     563    // within the given timeout.
     564    return d->pipeWriter->waitForWrite(msecs);
    535565}
    536566
  • trunk/src/network/socket/qnativesocketengine.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4848
    4949    \reentrant
    50     \ingroup io
     50    \ingroup network
    5151    \inmodule QtNetwork
    5252
     
    195195    switch (errorString) {
    196196    case NonBlockingInitFailedErrorString:
    197         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Unable to initialize non-blocking socket"));
     197        socketErrorString = QNativeSocketEngine::tr("Unable to initialize non-blocking socket");
    198198        break;
    199199    case BroadcastingInitFailedErrorString:
    200         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Unable to initialize broadcast socket"));
     200        socketErrorString = QNativeSocketEngine::tr("Unable to initialize broadcast socket");
    201201        break;
    202202    case NoIpV6ErrorString:
    203         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Attempt to use IPv6 socket on a platform with no IPv6 support"));
     203        socketErrorString = QNativeSocketEngine::tr("Attempt to use IPv6 socket on a platform with no IPv6 support");
    204204        break;
    205205    case RemoteHostClosedErrorString:
    206         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "The remote host closed the connection"));
     206        socketErrorString = QNativeSocketEngine::tr("The remote host closed the connection");
    207207        break;
    208208    case TimeOutErrorString:
    209         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Network operation timed out"));
     209        socketErrorString = QNativeSocketEngine::tr("Network operation timed out");
    210210        break;
    211211    case ResourceErrorString:
    212         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Out of resources"));
     212        socketErrorString = QNativeSocketEngine::tr("Out of resources");
    213213        break;
    214214    case OperationUnsupportedErrorString:
    215         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Unsupported socket operation"));
     215        socketErrorString = QNativeSocketEngine::tr("Unsupported socket operation");
    216216        break;
    217217    case ProtocolUnsupportedErrorString:
    218         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Protocol type not supported"));
     218        socketErrorString = QNativeSocketEngine::tr("Protocol type not supported");
    219219        break;
    220220    case InvalidSocketErrorString:
    221         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Invalid socket descriptor"));
     221        socketErrorString = QNativeSocketEngine::tr("Invalid socket descriptor");
    222222        break;
    223223    case HostUnreachableErrorString:
    224         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Host unreachable"));
     224        socketErrorString = QNativeSocketEngine::tr("Host unreachable");
    225225        break;
    226226    case NetworkUnreachableErrorString:
    227         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Network unreachable"));
     227        socketErrorString = QNativeSocketEngine::tr("Network unreachable");
    228228        break;
    229229    case AccessErrorString:
    230         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Permission denied"));
     230        socketErrorString = QNativeSocketEngine::tr("Permission denied");
    231231        break;
    232232    case ConnectionTimeOutErrorString:
    233         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Connection timed out"));
     233        socketErrorString = QNativeSocketEngine::tr("Connection timed out");
    234234        break;
    235235    case ConnectionRefusedErrorString:
    236         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Connection refused"));
     236        socketErrorString = QNativeSocketEngine::tr("Connection refused");
    237237        break;
    238238    case AddressInuseErrorString:
    239         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "The bound address is already in use"));
     239        socketErrorString = QNativeSocketEngine::tr("The bound address is already in use");
    240240        break;
    241241    case AddressNotAvailableErrorString:
    242         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "The address is not available"));
     242        socketErrorString = QNativeSocketEngine::tr("The address is not available");
    243243        break;
    244244    case AddressProtectedErrorString:
    245         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "The address is protected"));
     245        socketErrorString = QNativeSocketEngine::tr("The address is protected");
    246246        break;
    247247    case DatagramTooLargeErrorString:
    248         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Datagram was too large to send"));
     248        socketErrorString = QNativeSocketEngine::tr("Datagram was too large to send");
    249249        break;
    250250    case SendDatagramErrorString:
    251         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Unable to send a message"));
     251        socketErrorString = QNativeSocketEngine::tr("Unable to send a message");
    252252        break;
    253253    case ReceiveDatagramErrorString:
    254         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Unable to receive a message"));
     254        socketErrorString = QNativeSocketEngine::tr("Unable to receive a message");
    255255        break;
    256256    case WriteErrorString:
    257         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Unable to write"));
     257        socketErrorString = QNativeSocketEngine::tr("Unable to write");
    258258        break;
    259259    case ReadErrorString:
    260         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Network error"));
     260        socketErrorString = QNativeSocketEngine::tr("Network error");
    261261        break;
    262262    case PortInuseErrorString:
    263         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Another socket is already listening on the same port"));
     263        socketErrorString = QNativeSocketEngine::tr("Another socket is already listening on the same port");
    264264        break;
    265265    case NotSocketErrorString:
    266         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Operation on non-socket"));
     266        socketErrorString = QNativeSocketEngine::tr("Operation on non-socket");
    267267        break;
    268268    case InvalidProxyTypeString:
    269         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "The proxy type is invalid for this operation"));
     269        socketErrorString = QNativeSocketEngine::tr("The proxy type is invalid for this operation");
    270270        break;
    271271    case UnknownSocketErrorString:
    272         socketErrorString = QLatin1String(QT_TRANSLATE_NOOP("QNativeSocketEngine", "Unknown error"));
     272        socketErrorString = QNativeSocketEngine::tr("Unknown error");
    273273        break;
    274274    }
     
    382382    }
    383383
     384
    384385    // Make sure we receive out-of-band data
     386    // On Symbian OS this works only with native IP stack, not with WinSock
    385387    if (socketType == QAbstractSocket::TcpSocket
    386388        && !setOption(ReceiveOutOfBandData, 1)) {
     
    388390    }
    389391
    390     // Set the send and receive buffer sizes to a magic size, found
    391     // most optimal for our platforms.
    392     setReceiveBufferSize(49152);
    393     setSendBufferSize(49152);
     392    // Before Qt 4.6, we always set the send and receive buffer size to 49152 as
     393    // this was found to be an optimal value. However, modern OS
     394    // all have some kind of auto tuning for this and we therefore don't set
     395    // this explictly anymore.
     396    // If it introduces any performance regressions for Qt 4.6.x (x > 0) then
     397    // it will be put back in.
     398    //
     399    // You can use tests/manual/qhttpnetworkconnection to test HTTP download speed
     400    // with this.
     401    //
     402    // pre-4.6:
     403    // setReceiveBufferSize(49152);
     404    // setSendBufferSize(49152);
    394405
    395406    d->socketType = socketType;
     
    744755}
    745756
     757
     758qint64 QNativeSocketEngine::bytesToWrite() const
     759{
     760    return 0;
     761}
     762
    746763/*!
    747764    Reads up to \a maxSize bytes into \a data from the socket.
     
    860877bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
    861878{
    862     Q_D(const QNativeSocketEngine);
     879    Q_D(QNativeSocketEngine);
    863880    Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false);
    864881    Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForWrite(),
     
    877894        d_func()->fetchConnectionParameters();
    878895        return true;
     896    } else {
     897        int value = 0;
     898        int valueSize = sizeof(value);
     899        if (::getsockopt(d->socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
     900            if (value == WSAECONNREFUSED) {
     901                d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
     902                d->socketState = QAbstractSocket::UnconnectedState;
     903                return false;
     904            } else if (value == WSAETIMEDOUT) {
     905                d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
     906                d->socketState = QAbstractSocket::UnconnectedState;
     907                return false;
     908            } else if (value == WSAEHOSTUNREACH) {
     909                d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
     910                d->socketState = QAbstractSocket::UnconnectedState;
     911                return false;
     912            }
     913        }
    879914    }
    880915#endif
     
    897932                                      int msecs, bool *timedOut)
    898933{
    899     Q_D(const QNativeSocketEngine);
     934    Q_D(QNativeSocketEngine);
    900935    Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false);
    901936    Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(),
     
    911946        d_func()->fetchConnectionParameters();
    912947        return true;
    913     }
    914 #endif   
     948    } else {
     949        int value = 0;
     950        int valueSize = sizeof(value);
     951        if (::getsockopt(d->socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
     952            if (value == WSAECONNREFUSED) {
     953                d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
     954                d->socketState = QAbstractSocket::UnconnectedState;
     955                return false;
     956            } else if (value == WSAETIMEDOUT) {
     957                d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
     958                d->socketState = QAbstractSocket::UnconnectedState;
     959                return false;
     960            } else if (value == WSAEHOSTUNREACH) {
     961                d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
     962                d->socketState = QAbstractSocket::UnconnectedState;
     963                return false;
     964            }
     965        }
     966    }
     967#endif
    915968    if (ret == 0) {
    916969        if (timedOut)
     
    10871140{
    10881141    if (e->type() == QEvent::SockAct) {
    1089         engine->exceptionNotification();
     1142        if (engine->state() == QAbstractSocket::ConnectingState)
     1143            engine->connectionNotification();
     1144        else
     1145            engine->exceptionNotification();
    10901146        return true;
    10911147    }
  • trunk/src/network/socket/qnativesocketengine_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5353// We mean it.
    5454//
    55 
    5655#include "QtNetwork/qhostaddress.h"
    5756#include "private/qabstractsocketengine_p.h"
    5857#ifndef Q_OS_WIN
    59 #include "qplatformdefs.h"
     58#  include "qplatformdefs.h"
     59#else
     60#  include <winsock2.h>
     61#endif
     62
     63#ifdef Q_OS_SYMBIAN
     64#include <private/qeventdispatcher_symbian_p.h>
     65#include <unistd.h>
    6066#endif
    6167
    6268QT_BEGIN_NAMESPACE
    6369
    64 #ifndef Q_OS_WIN
    65 // Almost always the same. If not, specify in qplatformdefs.h.
    66 #if !defined(QT_SOCKOPTLEN_T)
    67 # define QT_SOCKOPTLEN_T QT_SOCKLEN_T
    68 #endif
    69 
    70 // Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED
    71 static inline int qt_socket_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
    72 { return ::accept(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen)); }
    73 #if defined(accept)
    74 # undef accept
    75 #endif
    76 
    77 // UnixWare 7 redefines listen -> _listen
    78 static inline int qt_socket_listen(int s, int backlog)
    79 { return ::listen(s, backlog); }
    80 #if defined(listen)
    81 # undef listen
    82 #endif
    83 
    84 // UnixWare 7 redefines socket -> _socket
    85 static inline int qt_socket_socket(int domain, int type, int protocol)
    86 { return ::socket(domain, type, protocol); }
    87 #if defined(socket)
    88 # undef socket
    89 #endif
    90 
    91 #endif
     70// Use our own defines and structs which we know are correct
     71#  define QT_SS_MAXSIZE 128
     72#  define QT_SS_ALIGNSIZE (sizeof(qint64))
     73#  define QT_SS_PAD1SIZE (QT_SS_ALIGNSIZE - sizeof (short))
     74#  define QT_SS_PAD2SIZE (QT_SS_MAXSIZE - (sizeof (short) + QT_SS_PAD1SIZE + QT_SS_ALIGNSIZE))
     75struct qt_sockaddr_storage {
     76      short ss_family;
     77      char __ss_pad1[QT_SS_PAD1SIZE];
     78      qint64 __ss_align;
     79      char __ss_pad2[QT_SS_PAD2SIZE];
     80};
     81
     82// sockaddr_in6 size changed between old and new SDK
     83// Only the new version is the correct one, so always
     84// use this structure.
     85struct qt_in6_addr {
     86    quint8 qt_s6_addr[16];
     87};
     88struct qt_sockaddr_in6 {
     89    short   sin6_family;            /* AF_INET6 */
     90    quint16 sin6_port;              /* Transport level port number */
     91    quint32 sin6_flowinfo;          /* IPv6 flow information */
     92    struct  qt_in6_addr sin6_addr;  /* IPv6 address */
     93    quint32 sin6_scope_id;          /* set of interfaces for a scope */
     94};
     95
     96union qt_sockaddr {
     97    sockaddr a;
     98    sockaddr_in a4;
     99    qt_sockaddr_in6 a6;
     100    qt_sockaddr_storage storage;
     101};
    92102
    93103class QNativeSocketEnginePrivate;
     
    125135    bool hasPendingDatagrams() const;
    126136    qint64 pendingDatagramSize() const;
     137
     138    qint64 bytesToWrite() const;
    127139
    128140    qint64 receiveBufferSize() const;
  • trunk/src/network/socket/qnativesocketengine_unix.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4141
    4242//#define QNATIVESOCKETENGINE_DEBUG
    43 
    4443#include "qnativesocketengine_p.h"
     44#include "private/qnet_unix_p.h"
    4545#include "qiodevice.h"
    4646#include "qhostaddress.h"
     
    6363#include <qstring.h>
    6464#include <ctype.h>
     65#endif
     66
     67#ifdef Q_OS_SYMBIAN // ### TODO: Are these headers right?
     68#include <sys/socket.h>
     69#include <netinet/in.h>
     70#else
     71#include <netinet/tcp.h>
    6572#endif
    6673
     
    101108static void qt_ignore_sigpipe()
    102109{
     110#ifndef Q_NO_POSIX_SIGNALS
    103111    // Set to ignore SIGPIPE once only.
    104112    static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
     
    109117        ::sigaction(SIGPIPE, &noaction, 0);
    110118    }
     119#else
     120    // Posix signals are not supported by the underlying platform
     121    // so we don't need to ignore sigpipe signal explicitly
     122#endif
    111123}
    112124
     
    115127    \a port and \a addr if they are non-null.
    116128*/
    117 static inline void qt_socket_getPortAndAddress(struct sockaddr *sa, quint16 *port, QHostAddress *addr)
     129static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *port, QHostAddress *addr)
    118130{
    119131#if !defined(QT_NO_IPV6)
    120     if (sa->sa_family == AF_INET6) {
    121         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
     132    if (s->a.sa_family == AF_INET6) {
    122133        Q_IPV6ADDR tmp;
    123         memcpy(&tmp, &sa6->sin6_addr.s6_addr, sizeof(tmp));
     134        memcpy(&tmp, &s->a6.sin6_addr, sizeof(tmp));
    124135        if (addr) {
    125136            QHostAddress tmpAddress;
     
    128139#ifndef QT_NO_IPV6IFNAME
    129140            char scopeid[IFNAMSIZ];
    130             if (::if_indextoname(sa6->sin6_scope_id, scopeid) > 0) {
     141            if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) {
    131142                addr->setScopeId(QLatin1String(scopeid));
    132143            } else
    133144#endif
    134             addr->setScopeId(QString::number(sa6->sin6_scope_id));
     145            addr->setScopeId(QString::number(s->a6.sin6_scope_id));
    135146        }
    136147        if (port)
    137             *port = ntohs(sa6->sin6_port);
     148            *port = ntohs(s->a6.sin6_port);
    138149        return;
    139150    }
    140151#endif
    141     struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
    142152    if (port)
    143         *port = ntohs(sa4->sin_port);
     153        *port = ntohs(s->a4.sin_port);
    144154    if (addr) {
    145155        QHostAddress tmpAddress;
    146         tmpAddress.setAddress(ntohl(sa4->sin_addr.s_addr));
     156        tmpAddress.setAddress(ntohl(s->a4.sin_addr.s_addr));
    147157        *addr = tmpAddress;
    148158    }
     
    164174#endif
    165175    int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
    166     int socket = qt_socket_socket(protocol, type, 0);
     176#ifdef Q_OS_SYMBIAN
     177    int socket = ::socket(protocol, type, 0);
     178#else
     179        int socket = qt_safe_socket(protocol, type, 0);
     180#endif
    167181
    168182    if (socket <= 0) {
     
    191205    // Ensure that the socket is closed on exec*().
    192206    ::fcntl(socket, F_SETFD, FD_CLOEXEC);
     207
    193208    socketDescriptor = socket;
    194209    return true;
     
    205220
    206221    int n = -1;
     222    int level = SOL_SOCKET; // default
     223
    207224    switch (opt) {
    208225    case QNativeSocketEngine::ReceiveBufferSocketOption:
     
    224241        n = SO_OOBINLINE;
    225242        break;
     243    case QNativeSocketEngine::LowDelayOption:
     244        level = IPPROTO_TCP;
     245        n = TCP_NODELAY;
     246        break;
     247    case QNativeSocketEngine::KeepAliveOption:
     248        n = SO_KEEPALIVE;
     249        break;
    226250    }
    227251
    228252    int v = -1;
    229253    QT_SOCKOPTLEN_T len = sizeof(v);
    230     if (getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1)
     254    if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
    231255        return v;
     256
    232257    return -1;
    233258}
     
    244269
    245270    int n = 0;
     271    int level = SOL_SOCKET; // default
     272
    246273    switch (opt) {
    247274    case QNativeSocketEngine::ReceiveBufferSocketOption:
     
    256283    case QNativeSocketEngine::NonBlockingSocketOption: {
    257284        // Make the socket nonblocking.
     285#if !defined(Q_OS_VXWORKS)
    258286        int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
    259287        if (flags == -1) {
     
    269297            return false;
    270298        }
    271 
     299#else // Q_OS_VXWORKS
     300        int onoff = 1;
     301#ifdef Q_OS_SYMBIAN
     302        if (::ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
     303#else
     304        if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
     305#endif
     306#ifdef QNATIVESOCKETENGINE_DEBUG
     307            perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
     308#endif
     309            return false;
     310        }
     311#endif // Q_OS_VXWORKS
    272312        return true;
    273313    }
    274314    case QNativeSocketEngine::AddressReusable:
    275 #ifdef SO_REUSEPORT
     315#if defined(SO_REUSEPORT) && !defined(Q_OS_SYMBIAN)
    276316        n = SO_REUSEPORT;
    277317#else
     
    284324        n = SO_OOBINLINE;
    285325        break;
    286     }
    287 
    288     return ::setsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, sizeof(v)) == 0;
     326    case QNativeSocketEngine::LowDelayOption:
     327        level = IPPROTO_TCP;
     328        n = TCP_NODELAY;
     329        break;
     330    case QNativeSocketEngine::KeepAliveOption:
     331        n = SO_KEEPALIVE;
     332        break;
     333    }
     334
     335    return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0;
    289336}
    290337
    291338bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port)
    292339{
     340#ifdef QNATIVESOCKETENGINE_DEBUG
     341    qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor);
     342#endif
     343
    293344    struct sockaddr_in sockAddrIPv4;
    294345    struct sockaddr *sockAddrPtr = 0;
     
    328379        // unreachable
    329380    }
    330 
    331     int connectResult = QT_SOCKET_CONNECT(socketDescriptor, sockAddrPtr, sockAddrSize);
     381#ifdef Q_OS_SYMBIAN
     382    int connectResult = ::connect(socketDescriptor, sockAddrPtr, sockAddrSize);
     383#else
     384    int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
     385#endif
    332386    if (connectResult == -1) {
    333387        switch (errno) {
     
    433487
    434488    int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
     489
    435490    if (bindResult < 0) {
    436491        switch(errno) {
     
    469524bool QNativeSocketEnginePrivate::nativeListen(int backlog)
    470525{
    471     if (qt_socket_listen(socketDescriptor, backlog) < 0) {
     526#ifdef Q_OS_SYMBIAN
     527    if (::listen(socketDescriptor, backlog) < 0) {
     528#else
     529    if (qt_safe_listen(socketDescriptor, backlog) < 0) {
     530#endif
    472531        switch (errno) {
    473532        case EADDRINUSE:
     
    496555int QNativeSocketEnginePrivate::nativeAccept()
    497556{
    498     int acceptedDescriptor = qt_socket_accept(socketDescriptor, 0, 0);
    499 #if defined (QNATIVESOCKETENGINE_DEBUG)
    500     qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
    501 #endif
    502     // Ensure that the socket is closed on exec*()
    503     ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC);
     557#ifdef Q_OS_SYMBIAN
     558    int acceptedDescriptor = ::accept(socketDescriptor, 0, 0);
     559#else
     560    int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
     561#endif
     562    //check if we have vaild descriptor at all
     563    if(acceptedDescriptor > 0) {
     564        // Ensure that the socket is closed on exec*()
     565        ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC);
     566    }
     567#ifdef Q_OS_SYMBIAN
     568    else {
     569        qWarning("QNativeSocketEnginePrivate::nativeAccept() - acceptedDescriptor <= 0");
     570    }
     571#endif
     572
    504573    return acceptedDescriptor;
    505574}
     
    507576qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
    508577{
    509     /*
    510       Apparently, there is not consistency among different operating
    511       systems on how to use FIONREAD.
    512 
    513       FreeBSD, Linux and Solaris all expect the 3rd argument to
    514       ioctl() to be an int, which is normally 32-bit even on 64-bit
    515       machines.
    516 
    517       IRIX, on the other hand, expects a size_t, which is 64-bit on
    518       64-bit machines.
    519 
    520       So, the solution is to use size_t initialized to zero to make
    521       sure all bits are set to zero, preventing underflow with the
    522       FreeBSD/Linux/Solaris ioctls.
    523     */
    524     size_t nbytes = 0;
     578    int nbytes = 0;
    525579    // gives shorter than true amounts on Unix domain sockets.
    526580    qint64 available = 0;
    527     if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
    528         available = (qint64) *((int *) &nbytes);
     581#ifdef Q_OS_SYMBIAN
     582        if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
     583#else
     584    if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
     585#endif
     586        available = (qint64) nbytes;
    529587
    530588#if defined (QNATIVESOCKETENGINE_DEBUG)
     
    537595{
    538596    // Create a sockaddr struct and reset its port number.
    539 #if !defined(QT_NO_IPV6)
    540     struct sockaddr_storage storage;
    541     sockaddr_in6 *storagePtrIPv6 = reinterpret_cast<sockaddr_in6 *>(&storage);
    542     storagePtrIPv6->sin6_port = 0;
    543 #else
    544     struct sockaddr storage;
    545 #endif
    546     sockaddr *storagePtr = reinterpret_cast<sockaddr *>(&storage);
    547     storagePtr->sa_family = 0;
    548 
    549     sockaddr_in *storagePtrIPv4 = reinterpret_cast<sockaddr_in *>(&storage);
    550     storagePtrIPv4->sin_port = 0;
     597    qt_sockaddr storage;
    551598    QT_SOCKLEN_T storageSize = sizeof(storage);
     599    memset(&storage, 0, storageSize);
    552600
    553601    // Peek 0 bytes into the next message. The size of the message may
     
    556604    do {
    557605        char c;
    558         readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, storagePtr, &storageSize);
     606        readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize);
    559607    } while (readBytes == -1 && errno == EINTR);
    560608
     
    570618}
    571619
     620#ifdef Q_OS_SYMBIAN
     621qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
     622{
     623    size_t nbytes = 0;
     624    ::ioctl(socketDescriptor, E32IONREAD, (char *) &nbytes);
     625    return qint64(nbytes-28);
     626}
     627#else
    572628qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
    573629{
    574630    QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192);
    575631    ssize_t recvResult = -1;
     632
    576633    for (;;) {
    577634        // the data written to udpMessagePeekBuffer is discarded, so
     
    579636        // so.
    580637        recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(),
    581                             udpMessagePeekBuffer.size(), MSG_PEEK);
     638            udpMessagePeekBuffer.size(), MSG_PEEK);
    582639        if (recvResult == -1 && errno == EINTR)
    583640            continue;
     
    595652    return qint64(recvResult);
    596653}
    597 
     654#endif
    598655qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
    599656                                                    QHostAddress *address, quint16 *port)
    600657{
    601 #if !defined(QT_NO_IPV6)
    602     struct sockaddr_storage aa;
    603 #else
    604     struct sockaddr_in aa;
    605 #endif
     658    qt_sockaddr aa;
    606659    memset(&aa, 0, sizeof(aa));
    607660    QT_SOCKLEN_T sz;
     
    612665        char c;
    613666        recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
    614                                     0, (struct sockaddr *)&aa, &sz);
     667                                    0, &aa.a, &sz);
    615668    } while (recvFromResult == -1 && errno == EINTR);
    616669
     
    618671        setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
    619672    } else if (port || address) {
    620         qt_socket_getPortAndAddress((struct sockaddr *) &aa, port, address);
     673        qt_socket_getPortAndAddress(&aa, port, address);
    621674    }
    622675
     
    641694    struct sockaddr_in6 sockAddrIPv6;
    642695    if (host.protocol() == QAbstractSocket::IPv6Protocol) {
    643         memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
    644         sockAddrIPv6.sin6_family = AF_INET6;
    645         sockAddrIPv6.sin6_port = htons(port);
    646 
    647         Q_IPV6ADDR tmp = host.toIPv6Address();
    648         memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
    649         sockAddrSize = sizeof(sockAddrIPv6);
    650         sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
     696    memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
     697    sockAddrIPv6.sin6_family = AF_INET6;
     698    sockAddrIPv6.sin6_port = htons(port);
     699
     700    Q_IPV6ADDR tmp = host.toIPv6Address();
     701    memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
     702    sockAddrSize = sizeof(sockAddrIPv6);
     703    sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
    651704    } else
    652705#endif
    653706    if (host.protocol() == QAbstractSocket::IPv4Protocol) {
    654         memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
    655         sockAddrIPv4.sin_family = AF_INET;
    656         sockAddrIPv4.sin_port = htons(port);
    657         sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
    658         sockAddrSize = sizeof(sockAddrIPv4);
    659         sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
     707    memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
     708    sockAddrIPv4.sin_family = AF_INET;
     709    sockAddrIPv4.sin_port = htons(port);
     710    sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
     711    sockAddrSize = sizeof(sockAddrIPv4);
     712    sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
    660713    }
    661714
    662715    // ignore the SIGPIPE signal
    663716    qt_ignore_sigpipe();
    664 
    665     ssize_t sentBytes;
    666     do {
    667         sentBytes = ::sendto(socketDescriptor, data, len,
    668                              0, sockAddrPtr, sockAddrSize);
    669     } while (sentBytes == -1 && errno == EINTR);
     717#ifdef Q_OS_SYMBIAN
     718    ssize_t sentBytes = ::sendto(socketDescriptor, data, len,
     719                                       0, sockAddrPtr, sockAddrSize);
     720#else
     721    ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
     722                                       0, sockAddrPtr, sockAddrSize);
     723#endif
    670724
    671725    if (sentBytes < 0) {
     
    698752        return false;
    699753
    700 #if !defined(QT_NO_IPV6)
    701     struct sockaddr_storage sa;
    702 #else
    703     struct sockaddr_in sa;
    704 #endif
    705     struct sockaddr *sockAddrPtr = (struct sockaddr *) &sa;
     754    qt_sockaddr sa;
    706755    QT_SOCKLEN_T sockAddrSize = sizeof(sa);
    707756
    708757    // Determine local address
    709758    memset(&sa, 0, sizeof(sa));
    710     if (::getsockname(socketDescriptor, sockAddrPtr, &sockAddrSize) == 0) {
    711         qt_socket_getPortAndAddress(sockAddrPtr, &localPort, &localAddress);
     759    if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
     760        qt_socket_getPortAndAddress(&sa, &localPort, &localAddress);
    712761
    713762        // Determine protocol family
    714         switch (sockAddrPtr->sa_family) {
     763        switch (sa.a.sa_family) {
    715764        case AF_INET:
    716765            socketProtocol = QAbstractSocket::IPv4Protocol;
     
    732781
    733782    // Determine the remote address
    734     if (!::getpeername(socketDescriptor, sockAddrPtr, &sockAddrSize))
    735         qt_socket_getPortAndAddress(sockAddrPtr, &peerPort, &peerAddress);
     783    if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize))
     784        qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
    736785
    737786    // Determine the socket type (UDP/TCP)
     
    769818    qDebug("QNativeSocketEngine::nativeClose()");
    770819#endif
     820
     821#ifdef Q_OS_SYMBIAN
    771822    ::close(socketDescriptor);
     823#else
     824        qt_safe_close(socketDescriptor);
     825#endif
    772826}
    773827
     
    783837    ssize_t writtenBytes;
    784838    do {
    785         writtenBytes = ::write(socketDescriptor, data, len);
     839#ifdef Q_OS_SYMBIAN
     840            writtenBytes = ::write(socketDescriptor, data, len);
     841#else
     842        writtenBytes = qt_safe_write(socketDescriptor, data, len);
     843#endif
     844        // writtenBytes = QT_WRITE(socketDescriptor, data, len); ### TODO S60: Should this line be removed or the one above it?
    786845    } while (writtenBytes < 0 && errno == EINTR);
    787846
     
    825884    ssize_t r = 0;
    826885    do {
     886#ifdef Q_OS_SYMBIAN
    827887        r = ::read(socketDescriptor, data, maxSize);
     888#else
     889        r = qt_safe_read(socketDescriptor, data, maxSize);
     890#endif
    828891    } while (r == -1 && errno == EINTR);
    829892
     
    843906            setError(QAbstractSocket::NetworkError, ReadErrorString);
    844907            break;
     908#ifdef Q_OS_SYMBIAN
     909        case EPIPE:
     910#endif
    845911        case ECONNRESET:
     912#if defined(Q_OS_VXWORKS)
     913        case ESHUTDOWN:
     914#endif
    846915            r = 0;
    847916            break;
     
    870939    tv.tv_usec = (timeout % 1000) * 1000;
    871940
    872     QTime timer;
    873     timer.start();
     941#ifdef Q_OS_SYMBIAN
     942    fd_set fdexception;
     943    FD_ZERO(&fdexception);
     944    FD_SET(socketDescriptor, &fdexception);
     945#endif
    874946
    875947    int retval;
    876     do {
    877         if (selectForRead)
    878             retval = select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
    879         else
    880             retval = select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
    881 
    882         if (retval != -1 || errno != EINTR)
    883             break;
    884 
    885         if (timeout > 0) {
    886             // recalculate the timeout
    887             int t = timeout - timer.elapsed();
    888             if (t < 0) {
    889                 // oops, timeout turned negative?
    890                 retval = -1;
    891                 break;
     948    if (selectForRead)
     949#ifdef Q_OS_SYMBIAN
     950        retval = ::select(socketDescriptor + 1, &fds, 0, &fdexception, timeout < 0 ? 0 : &tv);
     951#else
     952        retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
     953#endif
     954    else
     955#ifdef Q_OS_SYMBIAN
     956        retval = ::select(socketDescriptor + 1, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
     957#else
     958        retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
     959#endif
     960
     961
     962#ifdef Q_OS_SYMBIAN
     963        bool selectForExec = false;
     964        if(retval != 0) {
     965            if(retval < 0) {
     966                qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor);
    892967            }
    893 
    894             tv.tv_sec = t / 1000;
    895             tv.tv_usec = (t % 1000) * 1000;
    896         }
    897     } while (true);
     968            selectForExec = FD_ISSET(socketDescriptor, &fdexception);
     969        }
     970        if(selectForExec) {
     971            qWarning("nativeSelect (selectForRead %d, retVal %d, errno %d) Unexpected exception for fd %d",
     972                    selectForRead, retval, errno, socketDescriptor);
     973            }
     974#endif
    898975
    899976    return retval;
     
    901978
    902979int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
    903                                       bool *selectForRead, bool *selectForWrite) const
     980                       bool *selectForRead, bool *selectForWrite) const
    904981{
    905982    fd_set fdread;
     
    913990        FD_SET(socketDescriptor, &fdwrite);
    914991
     992#ifdef Q_OS_SYMBIAN
     993    fd_set fdexception;
     994    FD_ZERO(&fdexception);
     995    FD_SET(socketDescriptor, &fdexception);
     996#endif
     997
    915998    struct timeval tv;
    916999    tv.tv_sec = timeout / 1000;
    9171000    tv.tv_usec = (timeout % 1000) * 1000;
    9181001
     1002    int ret;
     1003#ifndef Q_OS_SYMBIAN
     1004    ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
     1005#else
    9191006    QTime timer;
    9201007    timer.start();
    9211008
    922     int ret;
    9231009    do {
    924         ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
    925         if (ret != -1 || errno != EINTR)
    926             break;
     1010        ret = ::select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
     1011        bool selectForExec = false;
     1012        if(ret != 0) {
     1013            if(ret < 0) {
     1014                qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor);
     1015            }
     1016            selectForExec = FD_ISSET(socketDescriptor, &fdexception);
     1017        }
     1018        if(selectForExec) {
     1019            qWarning("nativeSelect (checkRead %d, checkWrite %d, ret %d, errno %d): Unexpected expectfds ready in fd %d",
     1020                    checkRead, checkWrite, ret, errno, socketDescriptor);
     1021            if (checkWrite){
     1022                FD_CLR(socketDescriptor, &fdread);
     1023                FD_SET(socketDescriptor, &fdwrite);
     1024            } else if (checkRead)
     1025                FD_SET(socketDescriptor, &fdread);
     1026
     1027
     1028            if ((ret == -1) && ( errno == ECONNREFUSED || errno == EPIPE ))
     1029                ret = 1;
     1030
     1031        }
     1032
     1033        if (ret != -1 || errno != EINTR) {
     1034            break;
     1035        }
    9271036
    9281037        if (timeout > 0) {
     
    9391048        }
    9401049    } while (true);
     1050#endif
     1051
    9411052    if (ret <= 0)
    9421053        return ret;
    943 
    9441054    *selectForRead = FD_ISSET(socketDescriptor, &fdread);
    9451055    *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
     1056
    9461057    return ret;
    9471058}
  • trunk/src/network/socket/qnativesocketengine_win.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    150150#endif
    151151
    152 #if !defined (QT_NO_IPV6)
    153 
    154 // Use our own defines and structs which we know are correct
    155 #  define QT_SS_MAXSIZE 128
    156 #  define QT_SS_ALIGNSIZE (sizeof(__int64))
    157 #  define QT_SS_PAD1SIZE (QT_SS_ALIGNSIZE - sizeof (short))
    158 #  define QT_SS_PAD2SIZE (QT_SS_MAXSIZE - (sizeof (short) + QT_SS_PAD1SIZE + QT_SS_ALIGNSIZE))
    159 struct qt_sockaddr_storage {
    160       short ss_family;
    161       char __ss_pad1[QT_SS_PAD1SIZE];
    162       __int64 __ss_align;
    163       char __ss_pad2[QT_SS_PAD2SIZE];
    164 };
    165 
    166 // sockaddr_in6 size changed between old and new SDK
    167 // Only the new version is the correct one, so always
    168 // use this structure.
    169 struct qt_in6_addr {
    170     u_char qt_s6_addr[16];
    171 };
    172 typedef struct {
    173     short   sin6_family;            /* AF_INET6 */
    174     u_short sin6_port;              /* Transport level port number */
    175     u_long  sin6_flowinfo;          /* IPv6 flow information */
    176     struct  qt_in6_addr sin6_addr;  /* IPv6 address */
    177     u_long  sin6_scope_id;          /* set of interfaces for a scope */
    178 } qt_sockaddr_in6;
    179 
    180 #else
    181 
    182 typedef void * qt_sockaddr_in6 ;
    183 
    184 
    185 #endif
    186 
    187152#ifndef AF_INET6
    188153#define AF_INET6        23              /* Internetwork Version 6 */
     
    202167    \a port and \a addr if they are non-null.
    203168*/
    204 static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, struct sockaddr *sa, quint16 *port, QHostAddress *address)
     169static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
    205170{
    206171#if !defined (QT_NO_IPV6)
    207     if (sa->sa_family == AF_INET6) {
    208         qt_sockaddr_in6 *sa6 = (qt_sockaddr_in6 *)sa;
     172    if (sa->a.sa_family == AF_INET6) {
     173        const qt_sockaddr_in6 *sa6 = &sa->a6;
    209174        Q_IPV6ADDR tmp;
    210175        for (int i = 0; i < 16; ++i)
     
    218183    } else
    219184#endif
    220     if (sa->sa_family == AF_INET) {
    221         struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
     185    if (sa->a.sa_family == AF_INET) {
     186        const sockaddr_in *sa4 = &sa->a4;
    222187        unsigned long addr;
    223188        WSANtohl(socketDescriptor, sa4->sin_addr.s_addr, &addr);
     
    398363
    399364    int n = -1;
     365    int level = SOL_SOCKET; // default
     366
    400367    switch (opt) {
    401368    case QNativeSocketEngine::ReceiveBufferSocketOption:
     
    425392        n = SO_OOBINLINE;
    426393        break;
     394    case QNativeSocketEngine::LowDelayOption:
     395        level = IPPROTO_TCP;
     396        n = TCP_NODELAY;
     397        break;
     398    case QNativeSocketEngine::KeepAliveOption:
     399        n = SO_KEEPALIVE;
     400        break;
    427401    }
    428402
    429403    int v = -1;
    430404    QT_SOCKOPTLEN_T len = sizeof(v);
    431     if (getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1)
     405    if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
    432406        return v;
    433407    return -1;
     
    445419
    446420    int n = 0;
     421    int level = SOL_SOCKET; // default
     422
    447423    switch (opt) {
    448424    case QNativeSocketEngine::ReceiveBufferSocketOption:
     
    476452        n = SO_OOBINLINE;
    477453        break;
    478     }
    479 
    480     if (::setsockopt(socketDescriptor, SOL_SOCKET, n, (char*)&v, sizeof(v)) != 0) {
     454    case QNativeSocketEngine::LowDelayOption:
     455        level = IPPROTO_TCP;
     456        n = TCP_NODELAY;
     457        break;
     458    case QNativeSocketEngine::KeepAliveOption:
     459        n = SO_KEEPALIVE;
     460        break;
     461    }
     462
     463    if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
    481464        WS_ERROR_DEBUG(WSAGetLastError());
    482465        return false;
     
    499482       return false;
    500483
    501 #if !defined (QT_NO_IPV6)
    502     struct qt_sockaddr_storage sa;
    503 #else
    504     struct sockaddr_in sa;
    505 #endif
    506     struct sockaddr *pSa = (struct sockaddr *) &sa;
    507 
    508     QT_SOCKLEN_T sz = sizeof(sa);
    509 
     484    qt_sockaddr sa;
     485    QT_SOCKLEN_T sockAddrSize = sizeof(sa);
     486
     487    // Determine local address
    510488    memset(&sa, 0, sizeof(sa));
    511     if (::getsockname(socketDescriptor, pSa, &sz) == 0) {
    512         qt_socket_getPortAndAddress(socketDescriptor, pSa, &localPort, &localAddress);
     489    if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
     490        qt_socket_getPortAndAddress(socketDescriptor, &sa, &localPort, &localAddress);
    513491        // Determine protocol family
    514         switch (pSa->sa_family) {
     492        switch (sa.a.sa_family) {
    515493        case AF_INET:
    516494            socketProtocol = QAbstractSocket::IPv4Protocol;
     
    536514
    537515    memset(&sa, 0, sizeof(sa));
    538     if (::getpeername(socketDescriptor, pSa, &sz) == 0) {
    539         qt_socket_getPortAndAddress(socketDescriptor, pSa, &peerPort, &peerAddress);
     516    if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
     517        qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
    540518    } else {
    541519        WS_ERROR_DEBUG(WSAGetLastError());
     
    569547    struct sockaddr_in sockAddrIPv4;
    570548    qt_sockaddr_in6 sockAddrIPv6;
    571     struct sockaddr *sockAddrPtr;
    572     QT_SOCKLEN_T sockAddrSize;
     549    struct sockaddr *sockAddrPtr = 0;
     550    QT_SOCKLEN_T sockAddrSize = 0;
    573551
    574552    qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
     
    606584                        break;
    607585                    }
     586                    if (value == WSAEHOSTUNREACH) {
     587                        setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
     588                        socketState = QAbstractSocket::UnconnectedState;
     589                        break;
     590                    }
    608591                }
    609592                // fall through
     
    669652    struct sockaddr_in sockAddrIPv4;
    670653    qt_sockaddr_in6 sockAddrIPv6;
    671     struct sockaddr *sockAddrPtr;
    672     QT_SOCKLEN_T sockAddrSize;
     654    struct sockaddr *sockAddrPtr = 0;
     655    QT_SOCKLEN_T sockAddrSize = 0;
    673656
    674657    qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
     
    797780#if !defined(Q_OS_WINCE)
    798781    // Create a sockaddr struct and reset its port number.
    799 #if !defined(QT_NO_IPV6)
    800     qt_sockaddr_in6 storage;
    801     qt_sockaddr_in6 *storagePtrIPv6 = reinterpret_cast<qt_sockaddr_in6 *>(&storage);
    802     storagePtrIPv6->sin6_port = 0;
    803 #else
    804     struct sockaddr storage;
    805 #endif
    806     sockaddr *storagePtr = reinterpret_cast<sockaddr *>(&storage);
    807     storagePtr->sa_family = 0;
    808 
    809     sockaddr_in *storagePtrIPv4 = reinterpret_cast<sockaddr_in *>(&storage);
    810     storagePtrIPv4->sin_port = 0;
     782    qt_sockaddr storage;
    811783    QT_SOCKLEN_T storageSize = sizeof(storage);
    812 
     784    memset(&storage, 0, storageSize);
    813785
    814786    bool result = false;
     
    822794    DWORD available = 0;
    823795    DWORD flags = MSG_PEEK;
    824     int ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, storagePtr, &storageSize,0,0);
     796    int ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, &storage.a, &storageSize,0,0);
    825797    int err = WSAGetLastError();
    826798    if (ret == SOCKET_ERROR && err !=  WSAEMSGSIZE) {
     
    832804            flags = 0;
    833805            ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
    834                           storagePtr, &storageSize, 0, 0);
     806                          &storage.a, &storageSize, 0, 0);
    835807        }
    836808    } else {
     
    924896    qint64 ret = 0;
    925897
    926 #if !defined(QT_NO_IPV6)
    927     qt_sockaddr_storage aa;
    928 #else
    929     struct sockaddr_in aa;
    930 #endif
     898    qt_sockaddr aa;
    931899    memset(&aa, 0, sizeof(aa));
    932900    QT_SOCKLEN_T sz;
    933901    sz = sizeof(aa);
     902
    934903    WSABUF buf;
    935904    buf.buf = data;
     
    946915    DWORD flags = 0;
    947916    DWORD bytesRead = 0;
    948     int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, (struct sockaddr *) &aa, &sz,0,0);
     917    int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, &aa.a, &sz,0,0);
    949918    if (wsaRet == SOCKET_ERROR) {
    950919        int err = WSAGetLastError();
    951920        if (err == WSAEMSGSIZE) {
    952921            // it is ok the buffer was to small if bytesRead is larger than
    953             // maxLength (win 9x) then assume bytes read is really maxLenth
     922            // maxLength then assume bytes read is really maxLenth
    954923            ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead);
    955924        } else {
     
    962931    }
    963932
    964     qt_socket_getPortAndAddress(socketDescriptor, (struct sockaddr *) &aa, port, address);
     933    qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address);
    965934
    966935#if defined (QNATIVESOCKETENGINE_DEBUG)
     
    981950    struct sockaddr_in sockAddrIPv4;
    982951    qt_sockaddr_in6 sockAddrIPv6;
    983     struct sockaddr *sockAddrPtr;
    984     QT_SOCKLEN_T sockAddrSize;
     952    struct sockaddr *sockAddrPtr = 0;
     953    QT_SOCKLEN_T sockAddrSize = 0;
    985954
    986955    qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
    987956
    988     if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based && len > qint64(qt_socket_getMaxMsgSize(socketDescriptor))) {
    989         // WSAEMSGSIZE is not reliable enough (win 9x) so we check max size our self.
    990         setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
     957    WSABUF buf;
     958#if !defined(Q_OS_WINCE)
     959    buf.buf = len ? (char*)data : 0;
     960#else
     961    char tmp;
     962    buf.buf = len ? (char*)data : &tmp;
     963#endif
     964    buf.len = len;
     965    DWORD flags = 0;
     966    DWORD bytesSent = 0;
     967    if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) ==  SOCKET_ERROR) {
     968        int err = WSAGetLastError();
     969        WS_ERROR_DEBUG(err);
     970        switch (err) {
     971        case WSAEMSGSIZE:
     972            setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
     973            break;
     974        default:
     975            setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
     976            break;
     977        }
     978        ret = -1;
    991979    } else {
    992         WSABUF buf;
    993 #if !defined(Q_OS_WINCE)
    994         buf.buf = len ? (char*)data : 0;
    995 #else
    996         char tmp;
    997         buf.buf = len ? (char*)data : &tmp;
    998 #endif
    999         buf.len = len;
    1000         DWORD flags = 0;
    1001         DWORD bytesSent = 0;
    1002         if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) ==  SOCKET_ERROR) {
    1003             int err = WSAGetLastError();
    1004             WS_ERROR_DEBUG(err);
    1005             switch (err) {
    1006             case WSAEMSGSIZE:
    1007                 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
    1008                 break;
    1009             default:
    1010                 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
    1011                 break;
    1012             }
    1013             ret = -1;
    1014         } else {
    1015             ret = qint64(bytesSent);
    1016         }
    1017     }
     980        ret = qint64(bytesSent);
     981    }
     982
    1018983#if defined (QNATIVESOCKETENGINE_DEBUG)
    1019984    qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data,
     
    11431108    tv.tv_usec = (timeout % 1000) * 1000;
    11441109
    1145     if (selectForRead)
     1110    if (selectForRead) {
    11461111        ret = select(0, &fds, 0, 0, timeout < 0 ? 0 : &tv);
    1147     else
    1148         ret = select(0, 0, &fds, 0, timeout < 0 ? 0 : &tv);
     1112    } else {
     1113        // select for write
     1114
     1115        // Windows needs this to report errors when connecting a socket ...
     1116        fd_set fdexception;
     1117        FD_ZERO(&fdexception);
     1118        FD_SET(socketDescriptor, &fdexception);
     1119
     1120        ret = select(0, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
     1121
     1122        // ... but if it is actually set, pretend it did not happen
     1123        if (ret > 0 && FD_ISSET(socketDescriptor, &fdexception))
     1124            ret--;
     1125    }
    11491126
    11501127    if (readEnabled)
     
    11611138    if (readEnabled)
    11621139        readNotifier->setEnabled(false);
    1163    
     1140
    11641141    fd_set fdread;
    11651142    fd_set fdwrite;
     1143    fd_set fdexception;
    11661144
    11671145    int ret = 0;
     
    11731151    }
    11741152    memset(&fdwrite, 0, sizeof(fd_set));
     1153    FD_ZERO(&fdexception);
    11751154    if (checkWrite) {
    11761155        fdwrite.fd_count = 1;
    11771156        fdwrite.fd_array[0] = socketDescriptor;
     1157
     1158        // Windows needs this to report errors when connecting a socket
     1159        FD_SET(socketDescriptor, &fdexception);
    11781160    }
    11791161
     
    11831165
    11841166#if !defined(Q_OS_WINCE)
    1185     ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
     1167    ret = select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
    11861168#else
    1187     ret = select(1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
    1188 #endif
     1169    ret = select(1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
     1170#endif
     1171
     1172     //... but if it is actually set, pretend it did not happen
     1173    if (ret > 0 && FD_ISSET(socketDescriptor, &fdexception))
     1174        ret--;
     1175
    11891176    if (readEnabled)
    11901177        readNotifier->setEnabled(true);
  • trunk/src/network/socket/qsocks5socketengine.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6060QT_BEGIN_NAMESPACE
    6161
     62#ifdef Q_OS_SYMBIAN
     63static const int MaxWriteBufferSize = 4*1024;
     64#else
    6265static const int MaxWriteBufferSize = 128*1024;
     66#endif
    6367
    6468//#define QSOCKS5SOCKETLAYER_DEBUG
     
    154158static bool qt_socks5_set_host_address_and_port(const QHostAddress &address, quint16 port, QByteArray *pBuf)
    155159{
    156     QSOCKS5_DEBUG << "setting [" << address << ":" << port << "]";
     160    QSOCKS5_DEBUG << "setting [" << address << ':' << port << ']';
    157161
    158162    union {
     
    187191static bool qt_socks5_set_host_name_and_port(const QString &hostname, quint16 port, QByteArray *pBuf)
    188192{
    189     QSOCKS5_DEBUG << "setting [" << hostname << ":" << port << "]";
     193    QSOCKS5_DEBUG << "setting [" << hostname << ':' << port << ']';
    190194
    191195    QByteArray encodedHostName = QUrl::toAce(hostname);
     
    266270
    267271    if (ret) {
    268         QSOCKS5_DEBUG << "got [" << address << ":" << port << "]";
     272        QSOCKS5_DEBUG << "got [" << address << ':' << port << ']';
    269273        *pAddress = address;
    270274        *pPort = port;
     
    11251129{
    11261130    Q_D(QSocks5SocketEngine);
    1127     QSOCKS5_DEBUG << "connectToHost" << address << ":" << port;
     1131    QSOCKS5_DEBUG << "connectToHost" << address << ':' << port;
    11281132
    11291133    setPeerAddress(address);
     
    12321236            connectData->readBuffer.clear();
    12331237        emitReadNotification();
     1238        data->controlSocket->close();
     1239        // cause a disconnect in the outer socket
     1240        emitWriteNotification();
    12341241    } else if (socks5State == Uninitialized
    12351242               || socks5State == AuthenticationMethodsSent
     
    12421249        q_func()->setError(data->controlSocket->error(), data->controlSocket->errorString());
    12431250        emitReadNotification();
     1251        emitWriteNotification();
    12441252    }
    12451253}
     
    13801388            return false;
    13811389        }
    1382         QSOCKS5_DEBUG << "udp actual address and port" << d->localAddress << ":" << d->localPort;
     1390        QSOCKS5_DEBUG << "udp actual address and port" << d->localAddress << ':' << d->localPort;
    13831391        return true;
    13841392#endif // QT_NO_UDPSOCKET
     
    14791487{
    14801488    Q_D(QSocks5SocketEngine);
    1481     QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ")";
     1489    QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ')';
    14821490    if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) {
    14831491        if (d->connectData->readBuffer.size() == 0) {
     
    16201628#endif // QT_NO_UDPSOCKET
    16211629
     1630qint64 QSocks5SocketEngine::bytesToWrite() const
     1631{
     1632    Q_D(const QSocks5SocketEngine);
     1633    if (d->data && d->data->controlSocket) {
     1634        return d->data->controlSocket->bytesToWrite();
     1635    } else {
     1636        return 0;
     1637    }
     1638}
     1639
    16221640int QSocks5SocketEngine::option(SocketOption option) const
    16231641{
    1624     Q_UNUSED(option);
     1642    Q_D(const QSocks5SocketEngine);
     1643    if (d->data && d->data->controlSocket) {
     1644        // convert the enum and call the real socket
     1645        if (option == QAbstractSocketEngine::LowDelayOption)
     1646            return d->data->controlSocket->socketOption(QAbstractSocket::LowDelayOption).toInt();
     1647        if (option == QAbstractSocketEngine::KeepAliveOption)
     1648            return d->data->controlSocket->socketOption(QAbstractSocket::KeepAliveOption).toInt();
     1649    }
    16251650    return -1;
    16261651}
     
    16281653bool QSocks5SocketEngine::setOption(SocketOption option, int value)
    16291654{
    1630     Q_UNUSED(option);
    1631     Q_UNUSED(value);
     1655    Q_D(QSocks5SocketEngine);
     1656    if (d->data && d->data->controlSocket) {
     1657        // convert the enum and call the real socket
     1658        if (option == QAbstractSocketEngine::LowDelayOption)
     1659            d->data->controlSocket->setSocketOption(QAbstractSocket::LowDelayOption, value);
     1660        if (option == QAbstractSocketEngine::KeepAliveOption)
     1661            d->data->controlSocket->setSocketOption(QAbstractSocket::KeepAliveOption, value);
     1662        return true;
     1663    }
    16321664    return false;
    16331665}
     
    17671799    Q_D(QSocks5SocketEngine);
    17681800
    1769     QSOCKS5_Q_DEBUG << "setReadNotificationEnabled(" << enable << ")";
     1801    QSOCKS5_Q_DEBUG << "setReadNotificationEnabled(" << enable << ')';
    17701802
    17711803    bool emitSignal = false;
     
    18311863        return 0;
    18321864    }
    1833     QSocks5SocketEngine *engine = new QSocks5SocketEngine(parent);
     1865    QScopedPointer<QSocks5SocketEngine> engine(new QSocks5SocketEngine(parent));
    18341866    engine->setProxy(proxy);
    1835     return engine;
     1867    return engine.take();
    18361868}
    18371869
  • trunk/src/network/socket/qsocks5socketengine_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    100100    qint64 pendingDatagramSize() const;
    101101#endif // QT_NO_UDPSOCKET
     102
     103    qint64 bytesToWrite() const;
    102104
    103105    int option(SocketOption option) const;
  • trunk/src/network/socket/qtcpserver.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747
    4848    \reentrant
    49     \ingroup io
     49    \ingroup network
    5050    \inmodule QtNetwork
    5151
     
    355355    if (d->socketEngine) {
    356356        d->socketEngine->close();
    357         d->socketEngine->deleteLater();
     357        QT_TRY {
     358            d->socketEngine->deleteLater();
     359        } QT_CATCH(const std::bad_alloc &) {
     360            // in out of memory situations, the socketEngine
     361            // will be deleted in ~QTcpServer (it's a child-object of this)
     362        }
    358363        d->socketEngine = 0;
    359364    }
  • trunk/src/network/socket/qtcpserver.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/socket/qtcpsocket.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4848
    4949    \reentrant
    50     \ingroup io
     50    \ingroup network
    5151    \inmodule QtNetwork
    5252
     
    6161    \bold{Note:} TCP sockets cannot be opened in QIODevice::Unbuffered mode.
    6262
    63     \sa QTcpServer, QUdpSocket, QFtp, QHttp, {Fortune Server Example},
    64         {Fortune Client Example}, {Threaded Fortune Server Example},
    65         {Blocking Fortune Client Example}, {Loopback Example},
    66         {Torrent Example}
     63    \sa QTcpServer, QUdpSocket, QFtp, QNetworkAccessManager,
     64    {Fortune Server Example}, {Fortune Client Example},
     65    {Threaded Fortune Server Example}, {Blocking Fortune Client Example},
     66    {Loopback Example}, {Torrent Example}
    6767*/
    6868
  • trunk/src/network/socket/qtcpsocket.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444
    4545#include <QtNetwork/qabstractsocket.h>
     46#include <QtCore/qvariant.h>
    4647
    4748QT_BEGIN_HEADER
  • trunk/src/network/socket/qtcpsocket_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/socket/qudpsocket.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747    \brief The QUdpSocket class provides a UDP socket.
    4848
    49     \ingroup io
     49    \ingroup network
    5050    \inmodule QtNetwork
    5151
     
    7171    datagram, and readDatagram() to read it.
    7272
     73    \note An incoming datagram should be read when you receive the readyRead()
     74    signal, otherwise this signal will not be emitted for the next datagram.
     75
    7376    Example:
    7477
     
    9295    This enum describes the different flags you can pass to modify the
    9396    behavior of QUdpSocket::bind().
     97
     98    \note On Symbian OS bind flags behaviour depends on process capabilties.
     99    If process has NetworkControl capability, the bind attempt with
     100    ReuseAddressHint will always succeed even if the address and port is already
     101    bound by another socket with any flags. If process does not have
     102    NetworkControl capability, the bind attempt to address and port already
     103    bound by another socket will always fail.
    94104
    95105    \value ShareAddress Allow other services to bind to the same address
     
    348358    destination.
    349359
     360    \warning In S60 5.0 and earlier versions, the writeDatagram return
     361    value is not reliable for large datagrams.
     362
    350363    \warning Calling this function on a connected UDP socket may
    351364    result in an error and no packet being sent. If you are using a
     
    366379
    367380    qint64 sent = d->socketEngine->writeDatagram(data, size, address, port);
     381#ifdef Q_OS_SYMBIAN
     382    if( QSysInfo::s60Version() <= QSysInfo::SV_S60_5_0 ) {
     383        // This is evil hack, but for some reason native RSocket::SendTo returns 0,
     384        // for large datagrams (such as 600 bytes). Based on comments from Open C team
     385        // this should happen only in platforms <= S60 5.0.
     386        // As an workaround, we just set sent = size
     387        if( sent == 0 )
     388            sent = size;
     389    }
     390#endif
    368391    d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
    369392
     
    378401}
    379402
    380 /*! 
     403/*!
    381404    \fn qint64 QUdpSocket::writeDatagram(const QByteArray &datagram,
    382405                                             const QHostAddress &host, quint16 port)
  • trunk/src/network/socket/qudpsocket.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/socket/socket.pri

    r157 r561  
    2929                socket/qlocalsocket_unix.cpp \
    3030                socket/qlocalserver_unix.cpp
    31 
     31unix:HEADERS += \
     32                socket/qnet_unix_p.h
    3233
    3334win32:SOURCES += socket/qnativesocketengine_win.cpp \
     
    4748    DEFINES += QT_LOCALSOCKET_TCP
    4849}
    49 
    50 
  • trunk/src/network/ssl/qssl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5050    \since 4.3
    5151
    52     \ingroup io
     52    \ingroup network
     53    \ingroup ssl
    5354    \inmodule QtNetwork
    5455*/
  • trunk/src/network/ssl/qssl.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/ssl/qsslcertificate.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747
    4848    \reentrant
    49     \ingroup io
     49    \ingroup network
    5050    \ingroup ssl
    5151    \inmodule QtNetwork
     
    7272    certificate, its subject, and its issuer, by calling one of the
    7373    many accessor functions, including version(), serialNumber(),
    74     issuerInfo() and subjectInfo(). You can call notValidBefore() and
    75     notValidAfter() to check when the certificate was issued, and when
    76     it expires. The publicKey() function returns the certificate
     74    issuerInfo() and subjectInfo(). You can call effectiveDate() and
     75    expiryDate() to check when the certificate starts being
     76    effective and when it expires.
     77    The publicKey() function returns the certificate
    7778    subject's public key as a QSslKey. You can call issuerInfo() or
    7879    subjectInfo() to get detailed information about the certificate
     
    126127QT_BEGIN_NAMESPACE
    127128
     129// forward declaration
     130static QMap<QString, QString> _q_mapFromOnelineName(char *name);
     131
    128132/*!
    129133    Constructs a QSslCertificate by reading \a format encoded data
     
    158162QSslCertificate::QSslCertificate(const QSslCertificate &other) : d(other.d)
    159163{
    160     d->ref.ref();
    161164}
    162165
     
    166169QSslCertificate::~QSslCertificate()
    167170{
    168     if (!d->ref.deref())
    169         delete d;
    170171}
    171172
     
    176177QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other)
    177178{
    178     qAtomicAssign(d, other.d);
     179    d = other.d;
    179180    return *this;
    180181}
     
    242243    if (isNull())
    243244        return;
    244     if (d->ref == 1)
    245         delete d;
    246     else
    247         d->ref.deref();
    248 
    249245    d = new QSslCertificatePrivate;
    250246}
     
    255251QByteArray QSslCertificate::version() const
    256252{
     253    if (d->versionString.isEmpty() && d->x509)
     254        d->versionString =
     255            QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
     256
    257257    return d->versionString;
    258258}
    259259
    260260/*!
    261     Returns the certificate's serial number string.
     261    Returns the certificate's serial number string in decimal format.
    262262*/
    263263QByteArray QSslCertificate::serialNumber() const
    264264{
     265    if (d->serialNumberString.isEmpty() && d->x509)
     266        d->serialNumberString =
     267            QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->serialNumber)));
     268
    265269    return d->serialNumberString;
    266270}
     
    268272/*!
    269273    Returns a cryptographic digest of this certificate. By default,
    270     and MD5 digest will be generated, but you can also specify a
     274    an MD5 digest will be generated, but you can also specify a
    271275    custom \a algorithm.
    272276*/
     
    301305QString QSslCertificate::issuerInfo(SubjectInfo info) const
    302306{
     307    if (d->issuerInfo.isEmpty() && d->x509)
     308        d->issuerInfo =
     309                _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_issuer_name(d->x509), 0, 0));
     310
    303311    return d->issuerInfo.value(_q_SubjectInfoToString(info));
    304312}
     
    328336QString QSslCertificate::subjectInfo(SubjectInfo info) const
    329337{
     338    if (d->subjectInfo.isEmpty() && d->x509)
     339        d->subjectInfo =
     340                _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_subject_name(d->x509), 0, 0));
     341
    330342    return d->subjectInfo.value(_q_SubjectInfoToString(info));
    331343}
     
    363375        return result;
    364376
    365     STACK *altNames = (STACK *)q_X509_get_ext_d2i(d->x509, NID_subject_alt_name, 0, 0);
     377    STACK_OF(GENERAL_NAME) *altNames = (STACK_OF(GENERAL_NAME)*)q_X509_get_ext_d2i(d->x509, NID_subject_alt_name, 0, 0);
    366378
    367379    if (altNames) {
     
    378390
    379391            const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(genName->d.ia5));
    380             const QString altName = QLatin1String(QByteArray(altNameStr, len));
     392            const QString altName = QString::fromLatin1(altNameStr, len);
    381393            if (genName->type == GEN_DNS)
    382394                result.insert(QSsl::DnsEntry, altName);
     
    384396                result.insert(QSsl::EmailEntry, altName);
    385397        }
    386         q_sk_free(altNames);
     398        q_sk_pop_free((STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_sk_free));
    387399    }
    388400
     
    611623    array = array.toBase64();
    612624    QByteArray tmp;
    613     for (int i = 0; i < array.size() - 64; i += 64) {
     625    for (int i = 0; i <= array.size() - 64; i += 64) {
    614626        tmp += QByteArray::fromRawData(array.data() + i, 64);
    615627        tmp += "\n";
     
    662674    if (!x509 || !QSslSocket::supportsSsl())
    663675        return certificate;
    664 
    665     certificate.d->issuerInfo =
    666         _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_issuer_name(x509), 0, 0));
    667     certificate.d->subjectInfo =
    668         _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_subject_name(x509), 0, 0));
    669676
    670677    ASN1_TIME *nbef = q_X509_get_notBefore(x509);
     
    687694
    688695    if (ch == '\n') {
    689         *offset++;
     696        *offset += 1;
    690697        return true;
    691698    }
     
    767774    debug << "QSslCertificate("
    768775          << certificate.version()
    769           << "," << certificate.serialNumber()
    770           << "," << certificate.digest().toBase64()
    771           << "," << certificate.issuerInfo(QSslCertificate::Organization)
    772           << "," << certificate.subjectInfo(QSslCertificate::Organization)
    773           << "," << certificate.alternateSubjectNames()
     776          << ',' << certificate.serialNumber()
     777          << ',' << certificate.digest().toBase64()
     778          << ',' << certificate.issuerInfo(QSslCertificate::Organization)
     779          << ',' << certificate.subjectInfo(QSslCertificate::Organization)
     780          << ',' << certificate.alternateSubjectNames()
    774781#ifndef QT_NO_TEXTSTREAM
    775           << "," << certificate.effectiveDate()
    776           << "," << certificate.expiryDate()
     782          << ',' << certificate.effectiveDate()
     783          << ',' << certificate.expiryDate()
    777784#endif
    778           << ")";
     785          << ')';
    779786    return debug;
    780787}
  • trunk/src/network/ssl/qsslcertificate.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4848#include <QtCore/qcryptographichash.h>
    4949#include <QtCore/qregexp.h>
     50#include <QtCore/qsharedpointer.h>
    5051#include <QtNetwork/qssl.h>
    5152
     
    119120
    120121private:
    121     QSslCertificatePrivate *d;
     122    QExplicitlySharedDataPointer<QSslCertificatePrivate> d;
    122123    friend class QSslCertificatePrivate;
    123124    friend class QSslSocketBackendPrivate;
  • trunk/src/network/ssl/qsslcertificate_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7272    {
    7373        QSslSocketPrivate::ensureInitialized();
    74         ref = 1;
    7574    }
    7675
  • trunk/src/network/ssl/qsslcipher.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747
    4848    \reentrant
    49     \ingroup io
     49    \ingroup network
    5050    \ingroup ssl
    5151    \inmodule QtNetwork
     
    6565#ifndef QT_NO_DEBUG_STREAM
    6666#include <QtCore/qdebug.h>
     67#endif
    6768
    6869QT_BEGIN_NAMESPACE
    69 #endif
    7070
    7171/*!
     
    104104    : d(new QSslCipherPrivate)
    105105{
    106     *d = *other.d;
     106    *d.data() = *other.d.data();
    107107}
    108108
     
    112112QSslCipher::~QSslCipher()
    113113{
    114     delete d;
    115114}
    116115
     
    121120QSslCipher &QSslCipher::operator=(const QSslCipher &other)
    122121{
    123     *d = *other.d;
     122    *d.data() = *other.d.data();
    124123    return *this;
    125124}
     
    232231          << ", bits=" << cipher.usedBits()
    233232          << ", proto=" << qPrintable(cipher.protocolString())
    234           << ")";
     233          << ')';
    235234    return debug;
    236235}
  • trunk/src/network/ssl/qsslcipher.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4545
    4646#include <QtCore/qstring.h>
     47#include <QtCore/qscopedpointer.h>
    4748#include <QtNetwork/qssl.h>
    4849
     
    7980
    8081private:
    81     QSslCipherPrivate *d;
     82    QScopedPointer<QSslCipherPrivate> d;
    8283    friend class QSslSocketBackendPrivate;
    8384};
  • trunk/src/network/ssl/qsslcipher_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/network/ssl/qsslconfiguration.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6767    \reentrant
    6868    \inmodule QtNetwork
    69     \ingroup io
     69    \ingroup network
    7070    \ingroup ssl
    7171
  • trunk/src/network/ssl/qsslconfiguration.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4242/****************************************************************************
    4343**
    44 ** In addition, as a special exception, Trolltech gives permission to link
     44** In addition, as a special exception, Nokia gives permission to link
    4545** the code of its release of Qt with the OpenSSL project's "OpenSSL" library
    4646** (or modified versions of the "OpenSSL" library that use the same license
  • trunk/src/network/ssl/qsslconfiguration_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4242/****************************************************************************
    4343**
    44 ** In addition, as a special exception, Trolltech gives permission to link
     44** In addition, as a special exception, Nokia gives permission to link
    4545** the code of its release of Qt with the OpenSSL project's "OpenSSL" library
    4646** (or modified versions of the "OpenSSL" library that use the same license
  • trunk/src/network/ssl/qsslerror.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747
    4848    \reentrant
    49     \ingroup io
     49    \ingroup network
    5050    \ingroup ssl
    5151    \inmodule QtNetwork
     
    9292
    9393#include "qsslerror.h"
     94#include "qsslsocket.h"
    9495#ifndef QT_NO_DEBUG_STREAM
    9596#include <QtCore/qdebug.h>
     
    106107
    107108/*!
    108     Constructs a QSslError object. The two optional arguments specify the \a
     109    Constructs a QSslError object with no error and default certificate.
     110
     111*/
     112
     113// RVCT compiler in debug build does not like about default values in const-
     114// So as an workaround we define all constructor overloads here explicitly
     115QSslError::QSslError()
     116    : d(new QSslErrorPrivate)
     117{
     118    d->error = QSslError::NoError;
     119    d->certificate = QSslCertificate();
     120}
     121
     122/*!
     123    Constructs a QSslError object. The argument specifies the \a
     124    error that occurred.
     125
     126*/
     127QSslError::QSslError(SslError error)
     128    : d(new QSslErrorPrivate)
     129{
     130    d->error = error;
     131    d->certificate = QSslCertificate();
     132}
     133
     134/*!
     135    Constructs a QSslError object. The two arguments specify the \a
    109136    error that occurred, and which \a certificate the error relates to.
    110137
     
    124151    : d(new QSslErrorPrivate)
    125152{
    126     *d = *other.d;
     153    *d.data() = *other.d.data();
    127154}
    128155
     
    132159QSslError::~QSslError()
    133160{
    134     delete d;
    135161}
    136162
     
    142168QSslError &QSslError::operator=(const QSslError &other)
    143169{
    144     *d = *other.d;
     170    *d.data() = *other.d.data();
    145171    return *this;
    146172}
     
    185211    switch (d->error) {
    186212    case NoError:
    187         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "No error"));
     213        errStr = QSslSocket::tr("No error");
    188214        break;
    189215    case UnableToGetIssuerCertificate:
    190         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The issuer certificate could not be found"));
     216        errStr = QSslSocket::tr("The issuer certificate could not be found");
    191217        break;
    192218    case UnableToDecryptCertificateSignature:
    193         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The certificate signature could not be decrypted"));
     219        errStr = QSslSocket::tr("The certificate signature could not be decrypted");
    194220        break;
    195221    case UnableToDecodeIssuerPublicKey:
    196         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The public key in the certificate could not be read"));
     222        errStr = QSslSocket::tr("The public key in the certificate could not be read");
    197223        break;
    198224    case CertificateSignatureFailed:
    199         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The signature of the certificate is invalid"));
     225        errStr = QSslSocket::tr("The signature of the certificate is invalid");
    200226        break;
    201227    case CertificateNotYetValid:
    202         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The certificate is not yet valid"));
     228        errStr = QSslSocket::tr("The certificate is not yet valid");
    203229        break;
    204230    case CertificateExpired:
    205         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The certificate has expired"));
     231        errStr = QSslSocket::tr("The certificate has expired");
    206232        break;
    207233    case InvalidNotBeforeField:
    208         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The certificate's notBefore field contains an invalid time"));
     234        errStr = QSslSocket::tr("The certificate's notBefore field contains an invalid time");
    209235        break;
    210236    case InvalidNotAfterField:
    211         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The certificate's notAfter field contains an invalid time"));
     237        errStr = QSslSocket::tr("The certificate's notAfter field contains an invalid time");
    212238        break;
    213239    case SelfSignedCertificate:
    214         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The certificate is self-signed, and untrusted"));
     240        errStr = QSslSocket::tr("The certificate is self-signed, and untrusted");
    215241        break;
    216242    case SelfSignedCertificateInChain:
    217         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The root certificate of the certificate chain is self-signed, and untrusted"));
     243        errStr = QSslSocket::tr("The root certificate of the certificate chain is self-signed, and untrusted");
    218244        break;
    219245    case UnableToGetLocalIssuerCertificate:
    220         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The issuer certificate of a locally looked up certificate could not be found"));
     246        errStr = QSslSocket::tr("The issuer certificate of a locally looked up certificate could not be found");
    221247        break;
    222248    case UnableToVerifyFirstCertificate:
    223         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "No certificates could be verified"));
     249        errStr = QSslSocket::tr("No certificates could be verified");
    224250        break;
    225251    case InvalidCaCertificate:
    226         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "One of the CA certificates is invalid"));
     252        errStr = QSslSocket::tr("One of the CA certificates is invalid");
    227253        break;
    228254    case PathLengthExceeded:
    229         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The basicConstraints pathlength parameter has been exceeded"));
     255        errStr = QSslSocket::tr("The basicConstraints path length parameter has been exceeded");
    230256        break;
    231257    case InvalidPurpose:
    232         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The supplied certificate is unsuited for this purpose"));
     258        errStr = QSslSocket::tr("The supplied certificate is unsuitable for this purpose");
    233259        break;
    234260    case CertificateUntrusted:
    235         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The root CA certificate is not trusted for this purpose"));
     261        errStr = QSslSocket::tr("The root CA certificate is not trusted for this purpose");
    236262        break;
    237263    case CertificateRejected:
    238         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The root CA certificate is marked to reject the specified purpose"));
     264        errStr = QSslSocket::tr("The root CA certificate is marked to reject the specified purpose");
    239265        break;
    240266    case SubjectIssuerMismatch: // hostname mismatch
    241         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError,
    242                                                "The current candidate issuer certificate was rejected because its"
    243                                                " subject name did not match the issuer name of the current certificate"));
     267        errStr = QSslSocket::tr("The current candidate issuer certificate was rejected because its"
     268                                " subject name did not match the issuer name of the current certificate");
    244269        break;
    245270    case AuthorityIssuerSerialNumberMismatch:
    246         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The current candidate issuer certificate was rejected because"
    247                                                " its issuer name and serial number was present and did not match the"
    248                                                " authority key identifier of the current certificate"));
     271        errStr = QSslSocket::tr("The current candidate issuer certificate was rejected because"
     272                             " its issuer name and serial number was present and did not match the"
     273                             " authority key identifier of the current certificate");
    249274        break;
    250275    case NoPeerCertificate:
    251         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "The peer did not present any certificate"));
     276        errStr = QSslSocket::tr("The peer did not present any certificate");
    252277        break;
    253278    case HostNameMismatch:
    254         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError,
    255                                                "The host name did not match any of the valid hosts"
    256                                                " for this certificate"));
     279        errStr = QSslSocket::tr("The host name did not match any of the valid hosts"
     280                             " for this certificate");
    257281        break;
    258282    case NoSslSupport:
    259283        break;
    260284    default:
    261         errStr = QObject::tr(QT_TRANSLATE_NOOP(QSslError, "Unknown error"));
     285        errStr = QSslSocket::tr("Unknown error");
    262286        break;
    263287    }
  • trunk/src/network/ssl/qsslerror.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    8787    };
    8888
    89     QSslError(SslError error = NoError, const QSslCertificate &certificate = QSslCertificate());
     89    // RVCT compiler in debug build does not like about default values in const-
     90    // So as an workaround we define all constructor overloads here explicitly
     91    QSslError();
     92    QSslError(SslError error);
     93    QSslError(SslError error, const QSslCertificate &certificate);
     94
    9095    QSslError(const QSslError &other);
     96
    9197    ~QSslError();
    9298    QSslError &operator=(const QSslError &other);
     
    100106   
    101107private:
    102     QSslErrorPrivate *d;
     108    QScopedPointer<QSslErrorPrivate> d;
    103109};
    104110
  • trunk/src/network/ssl/qsslkey.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4747
    4848    \reentrant
    49     \ingroup io
     49    \ingroup network
    5050    \ingroup ssl
    5151    \inmodule QtNetwork
     
    272272QSslKey::QSslKey(const QSslKey &other) : d(other.d)
    273273{
    274     d->ref.ref();
    275274}
    276275
     
    280279QSslKey::~QSslKey()
    281280{
    282     if (!d->ref.deref())
    283         delete d;
    284281}
    285282
     
    292289QSslKey &QSslKey::operator=(const QSslKey &other)
    293290{
    294     qAtomicAssign(d, other.d);
     291    d = other.d;
    295292    return *this;
    296293}
     
    313310void QSslKey::clear()
    314311{
    315     if (!d->ref.deref()) {
    316         delete d;
    317         d = new QSslKeyPrivate;
    318     }
     312    d = new QSslKeyPrivate;
    319313}
    320314
     
    461455          << ", " << (key.algorithm() == QSsl::Rsa ? "RSA" : "DSA")
    462456          << ", " << key.length()
    463           << ")";
     457          << ')';
    464458    return debug;
    465459}
  • trunk/src/network/ssl/qsslkey.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4646#include <QtCore/qnamespace.h>
    4747#include <QtCore/qbytearray.h>
     48#include <QtCore/qsharedpointer.h>
    4849#include <QtNetwork/qssl.h>
    4950
     
    5960
    6061class QIODevice;
    61    
     62
    6263class QSslKeyPrivate;
    6364class Q_NETWORK_EXPORT QSslKey
     
    9394
    9495private:
    95     QSslKeyPrivate *d;
     96    QExplicitlySharedDataPointer<QSslKeyPrivate> d;
    9697    friend class QSslCertificate;
    9798};
  • trunk/src/network/ssl/qsslkey_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7070    {
    7171        clear();
    72         ref = 1;
    7372    }
    7473
     
    9291
    9392    QAtomicInt ref;
     93
     94private:
     95    Q_DISABLE_COPY(QSslKeyPrivate)
    9496};
    9597
  • trunk/src/network/ssl/qsslsocket.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5050
    5151    \reentrant
    52     \ingroup io
     52    \ingroup network
    5353    \ingroup ssl
    5454    \inmodule QtNetwork
     
    114114    internal buffer, and you can call write() or putChar() to write
    115115    data back to the peer. QSslSocket will automatically encrypt the
    116     written data for you, and emit bytesWritten() once the data has
    117     been written to the peer.
     116    written data for you, and emit encryptedBytesWritten() once
     117    the data has been written to the peer.
    118118
    119119    As a convenience, QSslSocket supports QTcpSocket's blocking
     
    150150    for use in the OpenSSL Toolkit (\l{http://www.openssl.org/}).
    151151
     152    \note Be aware of the difference between the bytesWritten() signal and
     153    the encryptedBytesWritten() signal. For a QTcpSocket, bytesWritten()
     154    will get emitted as soon as data has been written to the TCP socket.
     155    For a QSslSocket, bytesWritten() will get emitted when the data
     156    is being encrypted and encryptedBytesWritten()
     157    will get emitted as soon as data has been written to the TCP socket.
     158
    152159    \sa QSslCertificate, QSslCipher, QSslError
    153160*/
     
    357364    ignoreSslErrors(), either from inside a slot function connected to
    358365    the sslErrors() signal, or prior to entering encrypted mode. If
    359     ignoreSslErrors is not called, the connection is dropped, signal
     366    ignoreSslErrors() is not called, the connection is dropped, signal
    360367    disconnected() is emitted, and QSslSocket returns to the
    361368    UnconnectedState.
     
    398405
    399406/*!
     407    \since 4.6
     408    \overload
     409
     410    In addition to the original behaviour of connectToHostEncrypted,
     411    this overloaded method enables the usage of a different hostname
     412    (\a sslPeerName) for the certificate validation instead of
     413    the one used for the TCP connection (\a hostName).
     414
     415    \sa connectToHostEncrypted()
     416*/
     417void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port,
     418                                        const QString &sslPeerName, OpenMode mode)
     419{
     420    Q_D(QSslSocket);
     421    if (d->state == ConnectedState || d->state == ConnectingState) {
     422        qWarning("QSslSocket::connectToHostEncrypted() called when already connecting/connected");
     423        return;
     424    }
     425
     426    d->init();
     427    d->autoStartHandshake = true;
     428    d->initialized = true;
     429    d->verificationPeerName = sslPeerName;
     430
     431    // Note: When connecting to localhost, some platforms (e.g., HP-UX and some BSDs)
     432    // establish the connection immediately (i.e., first attempt).
     433    connectToHost(hostName, port, mode);
     434}
     435
     436/*!
    400437    Initializes QSslSocket with the native socket descriptor \a
    401438    socketDescriptor. Returns true if \a socketDescriptor is accepted
     
    413450    Q_D(QSslSocket);
    414451#ifdef QSSLSOCKET_DEBUG
    415     qDebug() << "QSslSocket::setSocketDescriptor(" << socketDescriptor << ","
    416              << state << "," << openMode << ")";
     452    qDebug() << "QSslSocket::setSocketDescriptor(" << socketDescriptor << ','
     453             << state << ',' << openMode << ')';
    417454#endif
    418455    if (!d->plainSocket)
     
    432469
    433470/*!
     471    \since 4.6
     472    Sets the given \a option to the value described by \a value.
     473
     474    \sa socketOption()
     475*/
     476void QSslSocket::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
     477{
     478    Q_D(QSslSocket);
     479    if (d->plainSocket)
     480        d->plainSocket->setSocketOption(option, value);
     481}
     482
     483/*!
     484    \since 4.6
     485    Returns the value of the \a option option.
     486
     487    \sa setSocketOption()
     488*/
     489QVariant QSslSocket::socketOption(QAbstractSocket::SocketOption option)
     490{
     491    Q_D(QSslSocket);
     492    if (d->plainSocket)
     493        return d->plainSocket->socketOption(option);
     494    else
     495        return QVariant();
     496}
     497
     498/*!
    434499    Returns the current mode for the socket; either UnencryptedMode, where
    435500    QSslSocket behaves identially to QTcpSocket, or one of SslClientMode or
     
    451516
    452517    An encrypted socket encrypts all data that is written by calling write()
    453     or putChar() before the data is written to the network, and descrypts all
     518    or putChar() before the data is written to the network, and decrypts all
    454519    incoming data as the data is received from the network, before you call
    455520    read(), readLine() or getChar().
     
    654719    qDebug() << "QSslSocket::close()";
    655720#endif
     721    Q_D(QSslSocket);
     722    if (d->plainSocket)
     723        d->plainSocket->close();
    656724    QTcpSocket::close();
     725
     726    // must be cleared, reading/writing not possible on closed socket:
     727    d->readBuffer.clear();
     728    d->writeBuffer.clear();
     729    // for QTcpSocket this is already done because it uses the readBuffer/writeBuffer
     730    // if the QIODevice it is based on
     731    // ### FIXME QSslSocket should probably do similar instead of having
     732    // its own readBuffer/writeBuffer
    657733}
    658734
     
    12591335
    12601336/*!
    1261     Returns the system default CA certificate database for your
    1262     system. This database is normally found in a standard place for
    1263     your system. If it is not found there, Qt will provide its own
    1264     default CA certificate database. The CA certificate database
     1337    This function provides a default CA certificate database
     1338    shipped together with Qt. The CA certificate database
    12651339    returned by this function is used to initialize the database
    12661340    returned by defaultCaCertificates(). You can replace that database
     
    15281602    Q_D(QSslSocket);
    15291603    if (d->mode != UnencryptedMode) {
    1530         qWarning("QSslSocket::startClientEncryption: cannot start handshake on non-plain connection");
     1604        qWarning("QSslSocket::startServerEncryption: cannot start handshake on non-plain connection");
    15311605        return;
    15321606    }
     
    15631637{
    15641638    Q_D(QSslSocket);
    1565     d->ignoreSslErrors = true;
     1639    d->ignoreAllSslErrors = true;
     1640}
     1641
     1642/*!
     1643    \overload
     1644    \since 4.6
     1645
     1646    This method tells QSslSocket to ignore only the errors given in \a
     1647    errors.
     1648
     1649    Note that you can set the expected certificate in the SSL error:
     1650    If, for instance, you want to connect to a server that uses
     1651    a self-signed certificate, consider the following snippet:
     1652
     1653    \snippet doc/src/snippets/code/src_network_ssl_qsslsocket.cpp 6
     1654
     1655    Multiple calls to this function will replace the list of errors that
     1656    were passed in previous calls.
     1657    You can clear the list of errors you want to ignore by calling this
     1658    function with an empty list.
     1659
     1660    \sa sslErrors()
     1661*/
     1662void QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
     1663{
     1664    Q_D(QSslSocket);
     1665    d->ignoreErrorsList = errors;
    15661666}
    15671667
     
    15791679#ifdef QSSLSOCKET_DEBUG
    15801680    qDebug() << "QSslSocket::connectToHostImplementation("
    1581              << hostName << "," << port << "," << openMode << ")";
     1681             << hostName << ',' << port << ',' << openMode << ')';
    15821682#endif
    15831683    if (!d->plainSocket) {
     
    16531753    }
    16541754#ifdef QSSLSOCKET_DEBUG
    1655     qDebug() << "QSslSocket::readData(" << (void *)data << "," << maxlen << ") ==" << readBytes;
     1755    qDebug() << "QSslSocket::readData(" << (void *)data << ',' << maxlen << ") ==" << readBytes;
    16561756#endif
     1757
     1758    // possibly trigger another transmit() to decrypt more data from the socket
     1759    if (d->readBuffer.isEmpty() && d->plainSocket->bytesAvailable())
     1760        QMetaObject::invokeMethod(this, "_q_flushReadBuffer", Qt::QueuedConnection);
     1761
    16571762    return readBytes;
    16581763}
     
    16651770    Q_D(QSslSocket);
    16661771#ifdef QSSLSOCKET_DEBUG
    1667     qDebug() << "QSslSocket::writeData(" << (void *)data << "," << len << ")";
     1772    qDebug() << "QSslSocket::writeData(" << (void *)data << ',' << len << ')';
    16681773#endif
    16691774    if (d->mode == UnencryptedMode && !d->autoStartHandshake)
     
    16831788*/
    16841789QSslSocketPrivate::QSslSocketPrivate()
    1685     : initialized(false), readyReadEmittedPointer(0), plainSocket(0)
     1790    : initialized(false)
     1791    , mode(QSslSocket::UnencryptedMode)
     1792    , autoStartHandshake(false)
     1793    , connectionEncrypted(false)
     1794    , ignoreAllSslErrors(false)
     1795    , readyReadEmittedPointer(0)
     1796    , plainSocket(0)
    16861797{
    16871798    QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
     
    17031814    autoStartHandshake = false;
    17041815    connectionEncrypted = false;
    1705     ignoreSslErrors = false;
     1816    ignoreAllSslErrors = false;
     1817
     1818    // we don't want to clear the ignoreErrorsList, so
     1819    // that it is possible setting it before connecting
     1820//    ignoreErrorsList.clear();
    17061821
    17071822    readBuffer.clear();
     
    19702085    Q_Q(QSslSocket);
    19712086#ifdef QSSLSOCKET_DEBUG
    1972     qDebug() << "QSslSocket::_q_stateChangedSlot(" << state << ")";
     2087    qDebug() << "QSslSocket::_q_stateChangedSlot(" << state << ')';
    19732088#endif
    19742089    q->setSocketState(state);
     
    19832098    Q_Q(QSslSocket);
    19842099#ifdef QSSLSOCKET_DEBUG
    1985     qDebug() << "QSslSocket::_q_errorSlot(" << error << ")";
     2100    qDebug() << "QSslSocket::_q_errorSlot(" << error << ')';
    19862101    qDebug() << "\tstate =" << q->state();
    19872102    qDebug() << "\terrorString =" << q->errorString();
     
    20182133    Q_Q(QSslSocket);
    20192134#ifdef QSSLSOCKET_DEBUG
    2020     qDebug() << "QSslSocket::_q_bytesWrittenSlot(" << written << ")";
     2135    qDebug() << "QSslSocket::_q_bytesWrittenSlot(" << written << ')';
    20212136#endif
    20222137
     
    20392154}
    20402155
     2156/*!
     2157    \internal
     2158*/
     2159void QSslSocketPrivate::_q_flushReadBuffer()
     2160{
     2161    // trigger a read from the plainSocket into SSL
     2162    if (mode != QSslSocket::UnencryptedMode)
     2163        transmit();
     2164}
     2165
    20412166QT_END_NAMESPACE
    20422167
  • trunk/src/network/ssl/qsslsocket.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    8787    // Autostarting the SSL client handshake.
    8888    void connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode mode = ReadWrite);
     89    void connectToHostEncrypted(const QString &hostName, quint16 port, const QString &sslPeerName, OpenMode mode = ReadWrite);
    8990    bool setSocketDescriptor(int socketDescriptor, SocketState state = ConnectedState,
    9091                             OpenMode openMode = ReadWrite);
     92
     93    // ### Qt 5: Make virtual
     94    void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value);
     95    QVariant socketOption(QAbstractSocket::SocketOption option);
    9196
    9297    SslMode mode() const;
     
    169174
    170175    static bool supportsSsl();
     176    void ignoreSslErrors(const QList<QSslError> &errors);
    171177
    172178public Q_SLOTS:
     
    202208    Q_PRIVATE_SLOT(d_func(), void _q_bytesWrittenSlot(qint64))
    203209    Q_PRIVATE_SLOT(d_func(), void _q_flushWriteBuffer())
     210    Q_PRIVATE_SLOT(d_func(), void _q_flushReadBuffer())
    204211    friend class QSslSocketBackendPrivate;
    205212};
  • trunk/src/network/ssl/qsslsocket_openssl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    277277            first = false;
    278278        else
    279             cipherString.append(":");
     279            cipherString.append(':');
    280280        cipherString.append(cipher.name().toLatin1());
    281281    }
     
    325325        // Check if the certificate matches the private key.
    326326        if (!q_SSL_CTX_check_private_key(ctx)) {
    327             q->setErrorString(QSslSocket::tr("Private key does not certificate public key, %1").arg(SSL_ERRORSTR()));
     327            q->setErrorString(QSslSocket::tr("Private key does not certify public key, %1").arg(SSL_ERRORSTR()));
    328328            emit q->error(QAbstractSocket::UnknownSocketError);
    329329            return false;
     
    483483QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
    484484{
    485 #ifdef QQ_OS_UNIX
    486     // Check known locations for the system's default bundle.  ### On Windows,
    487     // we should use CAPI to find the bundle, and not rely on default unix
    488     // locations.
    489     const char *standardLocations[] = {"/etc/ssl/certs/",
    490 #if 0
    491                                        // KDE uses KConfig for its SSL store,
    492                                        // but it also stores the bundle at
    493                                        // this location
    494                                        "$HOME/.kde/share/apps/kssl/ca-bundle.crt",
    495 #endif
    496                                        0};
    497     const char **it = standardLocations;
    498     QStringList nameFilter;
    499     nameFilter << QLatin1String("*.pem") << QLatin1String("*.crt");
    500     while (*it) {
    501         if (QDirIterator(QLatin1String(*it), nameFilter).hasNext())
    502             return certificatesFromPath(QLatin1String(*it));
    503         ++it;
    504     }
    505 #endif
    506 
    507     // Qt provides a default bundle when we cannot detect the system's default
    508     // bundle.
     485    // Qt provides a default bundle of certificates
    509486    QFile caBundle(QLatin1String(":/trolltech/network/ssl/qt-ca-bundle.crt"));
    510487    if (caBundle.open(QIODevice::ReadOnly | QIODevice::Text))
     
    524501    // Start connecting. This will place outgoing data in the BIO, so we
    525502    // follow up with calling transmit().
    526     testConnection();
     503    startHandshake();
    527504    transmit();
    528505}
     
    537514    // Start connecting. This will place outgoing data in the BIO, so we
    538515    // follow up with calling transmit().
    539     testConnection();
     516    startHandshake();
    540517    transmit();
    541518}
     
    625602            qDebug() << "QSslSocketBackendPrivate::transmit: testing encryption";
    626603#endif
    627             if (testConnection()) {
     604            if (startHandshake()) {
    628605#ifdef QSSLSOCKET_DEBUG
    629606                qDebug() << "QSslSocketBackendPrivate::transmit: encryption established";
     
    644621
    645622        // If the request is small and the remote host closes the transmission
    646         // after sending, there's a chance that testConnection() will already
     623        // after sending, there's a chance that startHandshake() will already
    647624        // have triggered a shutdown.
    648625        if (!ssl)
     
    744721}
    745722
    746 bool QSslSocketBackendPrivate::testConnection()
     723bool QSslSocketBackendPrivate::startHandshake()
    747724{
    748725    Q_Q(QSslSocket);
     
    785762            q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
    786763#ifdef QSSLSOCKET_DEBUG
    787             qDebug() << "QSslSocketBackendPrivate::testConnection: error!" << q->errorString();
     764            qDebug() << "QSslSocketBackendPrivate::startHandshake: error!" << q->errorString();
    788765#endif
    789766            emit q->error(QAbstractSocket::SslHandshakeFailedError);
     
    816793        // if we're the server, don't check CN
    817794        if (mode == QSslSocket::SslClientMode) {
    818             QString peerName = q->peerName();
     795            QString peerName = (verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
    819796            QString commonName = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName);
    820797
     
    863840        sslErrors = errors;
    864841        emit q->sslErrors(errors);
    865         if (doVerifyPeer && !ignoreSslErrors) {
     842
     843        bool doEmitSslError;
     844        if (!ignoreErrorsList.empty()) {
     845            // check whether the errors we got are all in the list of expected errors
     846            // (applies only if the method QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
     847            // was called)
     848            doEmitSslError = false;
     849            for (int a = 0; a < errors.count(); a++) {
     850                if (!ignoreErrorsList.contains(errors.at(a))) {
     851                    doEmitSslError = true;
     852                    break;
     853                }
     854            }
     855        } else {
     856            // if QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) was not called and
     857            // we get an SSL error, emit a signal unless we ignored all errors (by calling
     858            // QSslSocket::ignoreSslErrors() )
     859            doEmitSslError = !ignoreAllSslErrors;
     860        }
     861        // check whether we need to emit an SSL handshake error
     862        if (doVerifyPeer && doEmitSslError) {
    866863            q->setErrorString(sslErrors.first().errorString());
    867864            q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
     
    912909    if (!ssl || !ctx)
    913910        return QSslCipher();
     911#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     912    // FIXME This is fairly evil, but needed to keep source level compatibility
     913    // with the OpenSSL 0.9.x implementation at maximum -- some other functions
     914    // don't take a const SSL_CIPHER* when they should
     915    SSL_CIPHER *sessionCipher = const_cast<SSL_CIPHER *>(q_SSL_get_current_cipher(ssl));
     916#else
    914917    SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
     918#endif
    915919    return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
    916920}
  • trunk/src/network/ssl/qsslsocket_openssl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5858
    5959#ifdef Q_OS_WIN
    60 #include <windows.h>
     60#include <qt_windows.h>
    6161#if defined(OCSP_RESPONSE)
    6262#undef OCSP_RESPONSE
     
    7878#include <openssl/x509v3.h>
    7979#include <openssl/x509_vfy.h>
     80#include <openssl/dsa.h>
     81#include <openssl/rsa.h>
     82
     83#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     84typedef _STACK STACK;
     85#endif
    8086
    8187QT_BEGIN_NAMESPACE
     
    103109    void startServerEncryption();
    104110    void transmit();
    105     bool testConnection();
     111    bool startHandshake();
    106112    void disconnectFromHost();
    107113    void disconnected();
  • trunk/src/network/ssl/qsslsocket_openssl_symbols.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    9595DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return)
    9696#endif
     97DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
    9798DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
    9899DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
     
    143144DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
    144145DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
     146DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
     147DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
     148#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     149DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
     150DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
     151#else
    145152DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
    146 DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
    147153DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
     154#endif
    148155DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return)
    149156DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return)
     
    158165DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
    159166DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG)
     167#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     168DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return 0, return)
     169#else
    160170DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return 0, return)
     171#endif
    161172DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return)
    162173DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return)
     
    175186DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, SSL *a, a, return 0, return)
    176187#endif
     188#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     189DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
     190#else
    177191DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
     192#endif
    178193DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
    179194DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return)
     
    193208DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG)
    194209DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return)
     210#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     211DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
     212DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
     213DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
     214DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
     215DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
     216DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
     217DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
     218DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
     219#else
    195220DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
    196221DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
     
    201226DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
    202227DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
     228#endif
    203229DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return)
    204230DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return)
     
    232258DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
    233259
     260#ifdef Q_OS_SYMBIAN
     261#define RESOLVEFUNC(func, ordinal, lib) \
     262    if (!(_q_##func = _q_PTR_##func(lib->resolve(#ordinal)))) \
     263        qWarning("QSslSocket: cannot resolve "#func);
     264#else
    234265#define RESOLVEFUNC(func) \
    235266    if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func)))     \
    236267        && !(_q_##func = _q_PTR_##func(libs.second->resolve(#func)))) \
    237268        qWarning("QSslSocket: cannot resolve "#func);
     269#endif
    238270
    239271#if !defined QT_LINKED_OPENSSL
     
    336368    pair.second = libeay32;
    337369    return pair;
    338 
     370# elif defined(Q_OS_SYMBIAN)
     371     QLibrary *libssl = new QLibrary(QLatin1String("libssl"));
     372    if (!libssl->load()) {
     373        // Cannot find ssleay32.dll
     374        delete libssl;
     375        return pair;
     376    }
     377
     378    QLibrary *libcrypto = new QLibrary(QLatin1String("libcrypto"));
     379    if (!libcrypto->load()) {
     380        delete libcrypto;
     381        delete libssl;
     382        return pair;
     383    }
     384
     385    pair.first = libssl;
     386    pair.second = libcrypto;
     387    return pair;
    339388# elif defined(Q_OS_UNIX)
    340389    QLibrary *&libssl = pair.first;
     
    365414    // paths. See the man page for dlopen(3) on your system for more information.
    366415
     416#ifdef Q_OS_OPENBSD
     417    libcrypto->setLoadHints(QLibrary::ExportExternalSymbolsHint);
     418#endif
    367419#ifdef SHLIB_VERSION_NUMBER
    368420    // first attempt: the canonical name is libssl.so.<SHLIB_VERSION_NUMBER>
    369421    libssl->setFileNameAndVersion(QLatin1String("ssl"), QLatin1String(SHLIB_VERSION_NUMBER));
    370422    libcrypto->setFileNameAndVersion(QLatin1String("crypto"), QLatin1String(SHLIB_VERSION_NUMBER));
    371     if (libssl->load() && libcrypto->load()) {
     423    if (libcrypto->load() && libssl->load()) {
    372424        // libssl.so.<SHLIB_VERSION_NUMBER> and libcrypto.so.<SHLIB_VERSION_NUMBER> found
    373425        return pair;
     
    381433    libssl->setFileNameAndVersion(QLatin1String("ssl"), -1);
    382434    libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1);
    383     if (libssl->load() && libcrypto->load()) {
     435    if (libcrypto->load() && libssl->load()) {
    384436        // libssl.so.0 and libcrypto.so.0 found
    385437        return pair;
     
    396448        libssl->setFileNameAndVersion(ssl, -1);
    397449        libcrypto->setFileNameAndVersion(crypto, -1);
    398         if (libssl->load() && libcrypto->load()) {
     450        if (libcrypto->load() && libssl->load()) {
    399451            // libssl.so.0 and libcrypto.so.0 found
    400452            return pair;
     
    435487        return false;
    436488
     489#ifdef Q_OS_SYMBIAN
     490#ifdef SSLEAY_MACROS
     491    RESOLVEFUNC(ASN1_dup, 125, libs.second )
     492#endif
     493    RESOLVEFUNC(ASN1_INTEGER_get, 48, libs.second )
     494    RESOLVEFUNC(ASN1_STRING_data, 71, libs.second )
     495    RESOLVEFUNC(ASN1_STRING_length, 76, libs.second )
     496    RESOLVEFUNC(BIO_ctrl, 184, libs.second )
     497    RESOLVEFUNC(BIO_free, 209, libs.second )
     498    RESOLVEFUNC(BIO_new, 222, libs.second )
     499    RESOLVEFUNC(BIO_new_mem_buf, 230, libs.second )
     500    RESOLVEFUNC(BIO_read, 244, libs.second )
     501    RESOLVEFUNC(BIO_s_mem, 251, libs.second )
     502    RESOLVEFUNC(BIO_write, 269, libs.second )
     503    RESOLVEFUNC(BN_num_bits, 387, libs.second )
     504    RESOLVEFUNC(CRYPTO_free, 469, libs.second )
     505    RESOLVEFUNC(CRYPTO_num_locks, 500, libs.second )
     506    RESOLVEFUNC(CRYPTO_set_id_callback, 513, libs.second )
     507    RESOLVEFUNC(CRYPTO_set_locking_callback, 516, libs.second )
     508    RESOLVEFUNC(DSA_free, 594, libs.second )
     509    RESOLVEFUNC(ERR_error_string, 744, libs.second )
     510    RESOLVEFUNC(ERR_get_error, 749, libs.second )
     511    RESOLVEFUNC(EVP_des_ede3_cbc, 919, libs.second )
     512    RESOLVEFUNC(EVP_PKEY_assign, 859, libs.second )
     513    RESOLVEFUNC(EVP_PKEY_free, 867, libs.second )
     514    RESOLVEFUNC(EVP_PKEY_get1_DSA, 869, libs.second )
     515    RESOLVEFUNC(EVP_PKEY_get1_RSA, 870, libs.second )
     516    RESOLVEFUNC(EVP_PKEY_new, 876, libs.second )
     517    RESOLVEFUNC(EVP_PKEY_type, 882, libs.second )
     518    RESOLVEFUNC(OBJ_nid2sn, 1036, libs.second )
     519    RESOLVEFUNC(OBJ_obj2nid, 1037, libs.second )
     520#ifdef SSLEAY_MACROS // ### verify
     521    RESOLVEFUNC(PEM_ASN1_read_bio, 1180, libs.second )
     522#else
     523    RESOLVEFUNC(PEM_read_bio_DSAPrivateKey, 1219, libs.second )
     524    RESOLVEFUNC(PEM_read_bio_RSAPrivateKey, 1228, libs.second )
     525    RESOLVEFUNC(PEM_write_bio_DSAPrivateKey, 1260, libs.second )
     526    RESOLVEFUNC(PEM_write_bio_RSAPrivateKey, 1271, libs.second )
     527#endif
     528    RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY, 1220, libs.second )
     529    RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY, 1230, libs.second )
     530    RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY, 1261, libs.second )
     531    RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY, 1273, libs.second )
     532    RESOLVEFUNC(RAND_seed, 1426, libs.second )
     533    RESOLVEFUNC(RAND_status, 1429, libs.second )
     534    RESOLVEFUNC(RSA_free, 1450, libs.second )
     535    RESOLVEFUNC(sk_free, 2571, libs.second )
     536    RESOLVEFUNC(sk_num, 2576, libs.second )
     537    RESOLVEFUNC(sk_pop_free, 2578, libs.second )   
     538    RESOLVEFUNC(sk_value, 2585, libs.second )
     539    RESOLVEFUNC(SSL_CIPHER_description, 11, libs.first )
     540    RESOLVEFUNC(SSL_CTX_check_private_key, 21, libs.first )
     541    RESOLVEFUNC(SSL_CTX_ctrl, 22, libs.first )
     542    RESOLVEFUNC(SSL_CTX_free, 24, libs.first )
     543    RESOLVEFUNC(SSL_CTX_new, 35, libs.first )
     544    RESOLVEFUNC(SSL_CTX_set_cipher_list, 40, libs.first )
     545    RESOLVEFUNC(SSL_CTX_set_default_verify_paths, 44, libs.first )
     546    RESOLVEFUNC(SSL_CTX_set_verify, 56, libs.first )
     547    RESOLVEFUNC(SSL_CTX_set_verify_depth, 57, libs.first )
     548    RESOLVEFUNC(SSL_CTX_use_certificate, 64, libs.first )
     549    RESOLVEFUNC(SSL_CTX_use_certificate_file, 67, libs.first )
     550    RESOLVEFUNC(SSL_CTX_use_PrivateKey, 58, libs.first )
     551    RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey, 61, libs.first )
     552    RESOLVEFUNC(SSL_CTX_use_PrivateKey_file, 60, libs.first )
     553    RESOLVEFUNC(SSL_accept, 82, libs.first )
     554    RESOLVEFUNC(SSL_clear, 92, libs.first )
     555    RESOLVEFUNC(SSL_connect, 93, libs.first )
     556    RESOLVEFUNC(SSL_free, 99, libs.first )
     557    RESOLVEFUNC(SSL_get_ciphers, 104, libs.first )
     558    RESOLVEFUNC(SSL_get_current_cipher, 106, libs.first )
     559    RESOLVEFUNC(SSL_get_error, 110, libs.first )
     560    RESOLVEFUNC(SSL_get_peer_cert_chain, 117, libs.first )
     561    RESOLVEFUNC(SSL_get_peer_certificate, 118, libs.first )
     562    RESOLVEFUNC(SSL_get_verify_result, 132, libs.first )
     563    RESOLVEFUNC(SSL_library_init, 137, libs.first )
     564    RESOLVEFUNC(SSL_load_error_strings, 139, libs.first )
     565    RESOLVEFUNC(SSL_new, 140, libs.first )
     566    RESOLVEFUNC(SSL_read, 143, libs.first )
     567    RESOLVEFUNC(SSL_set_accept_state, 148, libs.first )
     568    RESOLVEFUNC(SSL_set_bio, 149, libs.first )
     569    RESOLVEFUNC(SSL_set_connect_state, 152, libs.first )
     570    RESOLVEFUNC(SSL_shutdown, 173, libs.first )
     571    RESOLVEFUNC(SSL_write, 188, libs.first )
     572    RESOLVEFUNC(SSLv2_client_method, 192, libs.first )
     573    RESOLVEFUNC(SSLv3_client_method, 195, libs.first )
     574    RESOLVEFUNC(SSLv23_client_method, 189, libs.first )
     575    RESOLVEFUNC(TLSv1_client_method, 198, libs.first )
     576    RESOLVEFUNC(SSLv2_server_method, 194, libs.first )
     577    RESOLVEFUNC(SSLv3_server_method, 197, libs.first )
     578    RESOLVEFUNC(SSLv23_server_method, 191, libs.first )
     579    RESOLVEFUNC(TLSv1_server_method, 200, libs.first )
     580    RESOLVEFUNC(X509_NAME_oneline, 1830, libs.second )
     581    RESOLVEFUNC(X509_PUBKEY_get, 1844, libs.second )
     582    RESOLVEFUNC(X509_STORE_free, 1939, libs.second )
     583    RESOLVEFUNC(X509_STORE_new, 1942, libs.second )
     584    RESOLVEFUNC(X509_STORE_add_cert, 1936, libs.second )
     585    RESOLVEFUNC(X509_STORE_CTX_free, 1907, libs.second )
     586    RESOLVEFUNC(X509_STORE_CTX_init, 1919, libs.second )
     587    RESOLVEFUNC(X509_STORE_CTX_new, 1920, libs.second )
     588    RESOLVEFUNC(X509_STORE_CTX_set_purpose, 1931, libs.second )
     589    RESOLVEFUNC(X509_cmp, 1992, libs.second )
     590#ifndef SSLEAY_MACROS
     591    RESOLVEFUNC(X509_dup, 1997, libs.second )
     592#endif
     593    RESOLVEFUNC(X509_EXTENSION_get_object, 1785, libs.second )
     594    RESOLVEFUNC(X509_free, 2001, libs.second )
     595    RESOLVEFUNC(X509_get_ext, 2012, libs.second )
     596    RESOLVEFUNC(X509_get_ext_count, 2016, libs.second )
     597    RESOLVEFUNC(X509_get_ext_d2i, 2017, libs.second )
     598    RESOLVEFUNC(X509_get_issuer_name, 2018, libs.second )
     599    RESOLVEFUNC(X509_get_subject_name, 2022, libs.second )
     600    RESOLVEFUNC(X509_verify_cert, 2069, libs.second )
     601    RESOLVEFUNC(d2i_X509, 2309, libs.second )
     602    RESOLVEFUNC(i2d_X509, 2489, libs.second )
     603#ifdef SSLEAY_MACROS
     604    RESOLVEFUNC(i2d_DSAPrivateKey, 2395, libs.second )
     605    RESOLVEFUNC(i2d_RSAPrivateKey, 2476, libs.second )
     606    RESOLVEFUNC(d2i_DSAPrivateKey, 2220, libs.second )
     607    RESOLVEFUNC(d2i_RSAPrivateKey, 2296, libs.second )
     608#endif
     609    RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf, 1153, libs.second )
     610    RESOLVEFUNC(OPENSSL_add_all_algorithms_conf, 1152, libs.second )
     611#else // Q_OS_SYMBIAN
    437612#ifdef SSLEAY_MACROS
    438613    RESOLVEFUNC(ASN1_dup)
    439614#endif
     615    RESOLVEFUNC(ASN1_INTEGER_get)
    440616    RESOLVEFUNC(ASN1_STRING_data)
    441617    RESOLVEFUNC(ASN1_STRING_length)
     
    481657    RESOLVEFUNC(sk_free)
    482658    RESOLVEFUNC(sk_num)
     659    RESOLVEFUNC(sk_pop_free)
    483660    RESOLVEFUNC(sk_value)
    484661    RESOLVEFUNC(SSL_CIPHER_description)
     
    554731    RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
    555732    RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
     733#endif // Q_OS_SYMBIAN
    556734    symbolsResolved = true;
    557735    delete libs.first;
  • trunk/src/network/ssl/qsslsocket_openssl_symbols_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    202202
    203203bool q_resolveOpenSslSymbols();
     204long q_ASN1_INTEGER_get(ASN1_INTEGER *a);
    204205unsigned char * q_ASN1_STRING_data(ASN1_STRING *a);
    205206int q_ASN1_STRING_length(ASN1_STRING *a);
     
    255256int q_RAND_status();
    256257void q_RSA_free(RSA *a);
     258int q_sk_num(STACK *a);
     259void q_sk_pop_free(STACK *a, void (*b)(void *));
     260#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     261void q_sk_free(_STACK *a);
     262void * q_sk_value(STACK *a, int b);
     263#else
    257264void q_sk_free(STACK *a);
    258 int q_sk_num(STACK *a);
    259265char * q_sk_value(STACK *a, int b);
     266#endif
    260267int q_SSL_accept(SSL *a);
    261268int q_SSL_clear(SSL *a);
     
    270277long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d);
    271278void q_SSL_CTX_free(SSL_CTX *a);
     279#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     280SSL_CTX *q_SSL_CTX_new(const SSL_METHOD *a);
     281#else
    272282SSL_CTX *q_SSL_CTX_new(SSL_METHOD *a);
     283#endif
    273284int q_SSL_CTX_set_cipher_list(SSL_CTX *a, const char *b);
    274285int q_SSL_CTX_set_default_verify_paths(SSL_CTX *a);
     
    287298STACK_OF(SSL_CIPHER) *q_SSL_get_ciphers(SSL *a);
    288299#endif
     300#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     301const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
     302#else
    289303SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
     304#endif
    290305int q_SSL_get_error(SSL *a, int b);
    291306STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
     
    305320void q_SSL_set_connect_state(SSL *a);
    306321int q_SSL_shutdown(SSL *a);
     322#if OPENSSL_VERSION_NUMBER >= 0x10000000L
     323const SSL_METHOD *q_SSLv2_client_method();
     324const SSL_METHOD *q_SSLv3_client_method();
     325const SSL_METHOD *q_SSLv23_client_method();
     326const SSL_METHOD *q_TLSv1_client_method();
     327const SSL_METHOD *q_SSLv2_server_method();
     328const SSL_METHOD *q_SSLv3_server_method();
     329const SSL_METHOD *q_SSLv23_server_method();
     330const SSL_METHOD *q_TLSv1_server_method();
     331#else
    307332SSL_METHOD *q_SSLv2_client_method();
    308333SSL_METHOD *q_SSLv3_client_method();
     
    313338SSL_METHOD *q_SSLv23_server_method();
    314339SSL_METHOD *q_TLSv1_server_method();
     340#endif
    315341int q_SSL_write(SSL *a, const void *b, int c);
    316342int q_X509_cmp(X509 *a, X509 *b);
  • trunk/src/network/ssl/qsslsocket_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtNetwork module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    8080    bool autoStartHandshake;
    8181    bool connectionEncrypted;
    82     bool ignoreSslErrors;
     82    bool ignoreAllSslErrors;
     83    QList<QSslError> ignoreErrorsList;
    8384    bool* readyReadEmittedPointer;
    8485
     
    8889    QSslConfigurationPrivate configuration;
    8990    QList<QSslError> sslErrors;
     91
     92    // if set, this hostname is used for certificate validation instead of the hostname
     93    // that was used for connecting to.
     94    QString verificationPeerName;
    9095
    9196    static bool ensureInitialized();
     
    116121    void _q_bytesWrittenSlot(qint64);
    117122    void _q_flushWriteBuffer();
     123    void _q_flushReadBuffer();
    118124
    119125    // Platform specific functions
  • trunk/src/network/ssl/ssl.pri

    r2 r561  
    11# OpenSSL support; compile in QSslSocket.
    22contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
    3     include($$QT_SOURCE_TREE/config.tests/unix/openssl/openssl.pri)
     3
     4
     5symbian {
     6        INCLUDEPATH *= $$OS_LAYER_SSL_SYSTEMINCLUDE
     7} else {
     8        include($$QT_SOURCE_TREE/config.tests/unix/openssl/openssl.pri)
     9}
    410
    511    HEADERS += ssl/qssl.h \
     
    3036
    3137    # Add optional SSL libs
    32     LIBS += $$OPENSSL_LIBS
     38    LIBS_PRIVATE += $$OPENSSL_LIBS
    3339}
Note: See TracChangeset for help on using the changeset viewer.