Home | History | Annotate | Download | only in qt
      1 /*
      2  * Copyright (C) 2010 Nokia Inc. All rights reserved.
      3  * Copyright (C) 2009 Google Inc.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include "config.h"
     33 #include "SocketStreamHandle.h"
     34 
     35 #include "KURL.h"
     36 #include "Logging.h"
     37 #include "NotImplemented.h"
     38 #include "SocketStreamHandleClient.h"
     39 #include "SocketStreamHandlePrivate.h"
     40 
     41 namespace WebCore {
     42 
     43 SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamHandle, const KURL& url) : QObject()
     44 {
     45     m_streamHandle = streamHandle;
     46     m_socket = 0;
     47     bool isSecure = url.protocolIs("wss");
     48 
     49     if (isSecure) {
     50 #ifndef QT_NO_OPENSSL
     51         m_socket = new QSslSocket(this);
     52 #endif
     53     } else
     54         m_socket = new QTcpSocket(this);
     55 
     56     if (!m_socket)
     57         return;
     58 
     59     connect(m_socket, SIGNAL(connected()), this, SLOT(socketConnected()));
     60     connect(m_socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
     61     connect(m_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
     62     connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
     63     if (isSecure)
     64         connect(m_socket, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(socketSslErrors(const QList<QSslError>&)));
     65 
     66     unsigned int port = url.hasPort() ? url.port() : (isSecure ? 443 : 80);
     67 
     68     QString host = url.host();
     69     if (isSecure) {
     70 #ifndef QT_NO_OPENSSL
     71         static_cast<QSslSocket*>(m_socket)->connectToHostEncrypted(host, port);
     72 #endif
     73     } else
     74         m_socket->connectToHost(host, port);
     75 }
     76 
     77 SocketStreamHandlePrivate::~SocketStreamHandlePrivate()
     78 {
     79     Q_ASSERT(!(m_socket && m_socket->state() == QAbstractSocket::ConnectedState));
     80 }
     81 
     82 void SocketStreamHandlePrivate::socketConnected()
     83 {
     84     if (m_streamHandle && m_streamHandle->client()) {
     85         m_streamHandle->m_state = SocketStreamHandleBase::Open;
     86         m_streamHandle->client()->didOpen(m_streamHandle);
     87     }
     88 }
     89 
     90 void SocketStreamHandlePrivate::socketReadyRead()
     91 {
     92     if (m_streamHandle && m_streamHandle->client()) {
     93         QByteArray data = m_socket->read(m_socket->bytesAvailable());
     94         m_streamHandle->client()->didReceiveData(m_streamHandle, data.constData(), data.size());
     95     }
     96 }
     97 
     98 int SocketStreamHandlePrivate::send(const char* data, int len)
     99 {
    100     if (!m_socket || m_socket->state() != QAbstractSocket::ConnectedState)
    101         return 0;
    102     quint64 sentSize = m_socket->write(data, len);
    103     QMetaObject::invokeMethod(this, "socketSentData", Qt::QueuedConnection);
    104     return sentSize;
    105 }
    106 
    107 void SocketStreamHandlePrivate::close()
    108 {
    109     if (m_socket && m_socket->state() == QAbstractSocket::ConnectedState)
    110         m_socket->close();
    111 }
    112 
    113 void SocketStreamHandlePrivate::socketSentData()
    114 {
    115     if (m_streamHandle)
    116         m_streamHandle->sendPendingData();
    117 }
    118 
    119 void SocketStreamHandlePrivate::socketClosed()
    120 {
    121     QMetaObject::invokeMethod(this, "socketClosedCallback", Qt::QueuedConnection);
    122 }
    123 
    124 void SocketStreamHandlePrivate::socketError(QAbstractSocket::SocketError error)
    125 {
    126     QMetaObject::invokeMethod(this, "socketErrorCallback", Qt::QueuedConnection, Q_ARG(int, error));
    127 }
    128 
    129 void SocketStreamHandlePrivate::socketClosedCallback()
    130 {
    131     if (m_streamHandle && m_streamHandle->client()) {
    132         SocketStreamHandle* streamHandle = m_streamHandle;
    133         m_streamHandle = 0;
    134         // This following call deletes _this_. Nothing should be after it.
    135         streamHandle->client()->didClose(streamHandle);
    136     }
    137 }
    138 
    139 void SocketStreamHandlePrivate::socketErrorCallback(int error)
    140 {
    141     // FIXME - in the future, we might not want to treat all errors as fatal.
    142     if (m_streamHandle && m_streamHandle->client()) {
    143         SocketStreamHandle* streamHandle = m_streamHandle;
    144         m_streamHandle = 0;
    145         // This following call deletes _this_. Nothing should be after it.
    146         streamHandle->client()->didClose(streamHandle);
    147     }
    148 }
    149 
    150 #ifndef QT_NO_OPENSSL
    151 void SocketStreamHandlePrivate::socketSslErrors(const QList<QSslError>& error)
    152 {
    153     QMetaObject::invokeMethod(this, "socketErrorCallback", Qt::QueuedConnection, Q_ARG(int, error[0].error()));
    154 }
    155 #endif
    156 
    157 SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient* client)
    158     : SocketStreamHandleBase(url, client)
    159 {
    160     LOG(Network, "SocketStreamHandle %p new client %p", this, m_client);
    161     m_p = new SocketStreamHandlePrivate(this, url);
    162 }
    163 
    164 SocketStreamHandle::~SocketStreamHandle()
    165 {
    166     LOG(Network, "SocketStreamHandle %p delete", this);
    167     setClient(0);
    168     delete m_p;
    169 }
    170 
    171 int SocketStreamHandle::platformSend(const char* data, int len)
    172 {
    173     LOG(Network, "SocketStreamHandle %p platformSend", this);
    174     return m_p->send(data, len);
    175 }
    176 
    177 void SocketStreamHandle::platformClose()
    178 {
    179     LOG(Network, "SocketStreamHandle %p platformClose", this);
    180     m_p->close();
    181 }
    182 
    183 void SocketStreamHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&)
    184 {
    185     notImplemented();
    186 }
    187 
    188 void SocketStreamHandle::receivedCredential(const AuthenticationChallenge&, const Credential&)
    189 {
    190     notImplemented();
    191 }
    192 
    193 void SocketStreamHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&)
    194 {
    195     notImplemented();
    196 }
    197 
    198 void SocketStreamHandle::receivedCancellation(const AuthenticationChallenge&)
    199 {
    200     notImplemented();
    201 }
    202 
    203 } // namespace WebCore
    204 
    205 #include "moc_SocketStreamHandlePrivate.cpp"
    206