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 "SocketStreamError.h" 39#include "SocketStreamHandleClient.h" 40#include "SocketStreamHandlePrivate.h" 41 42namespace WebCore { 43 44SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamHandle, const KURL& url) 45{ 46 m_streamHandle = streamHandle; 47 m_socket = 0; 48 bool isSecure = url.protocolIs("wss"); 49 50 if (isSecure) { 51#ifndef QT_NO_OPENSSL 52 m_socket = new QSslSocket(this); 53#endif 54 } else 55 m_socket = new QTcpSocket(this); 56 57 if (!m_socket) 58 return; 59 60 initConnections(); 61 62 unsigned int port = url.hasPort() ? url.port() : (isSecure ? 443 : 80); 63 64 QString host = url.host(); 65 if (isSecure) { 66#ifndef QT_NO_OPENSSL 67 static_cast<QSslSocket*>(m_socket)->connectToHostEncrypted(host, port); 68#endif 69 } else 70 m_socket->connectToHost(host, port); 71} 72 73SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamHandle, QTcpSocket* socket) 74{ 75 m_streamHandle = streamHandle; 76 m_socket = socket; 77 initConnections(); 78} 79 80SocketStreamHandlePrivate::~SocketStreamHandlePrivate() 81{ 82 Q_ASSERT(!(m_socket && m_socket->state() == QAbstractSocket::ConnectedState)); 83} 84 85void SocketStreamHandlePrivate::initConnections() 86{ 87 connect(m_socket, SIGNAL(connected()), this, SLOT(socketConnected())); 88 connect(m_socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); 89 connect(m_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); 90 connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError))); 91#ifndef QT_NO_OPENSSL 92 if (qobject_cast<QSslSocket*>(m_socket)) 93 connect(m_socket, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(socketSslErrors(const QList<QSslError>&))); 94#endif 95 96 // Check for missed signals and call the slots asynchronously to allow a client to be set first. 97 if (m_socket->state() >= QAbstractSocket::ConnectedState) 98 QMetaObject::invokeMethod(this, "socketConnected", Qt::QueuedConnection); 99 if (m_socket->bytesAvailable()) 100 QMetaObject::invokeMethod(this, "socketReadyRead", Qt::QueuedConnection); 101} 102 103void SocketStreamHandlePrivate::socketConnected() 104{ 105 if (m_streamHandle && m_streamHandle->client()) { 106 m_streamHandle->m_state = SocketStreamHandleBase::Open; 107 m_streamHandle->client()->didOpenSocketStream(m_streamHandle); 108 } 109} 110 111void SocketStreamHandlePrivate::socketReadyRead() 112{ 113 if (m_streamHandle && m_streamHandle->client()) { 114 QByteArray data = m_socket->read(m_socket->bytesAvailable()); 115 m_streamHandle->client()->didReceiveSocketStreamData(m_streamHandle, data.constData(), data.size()); 116 } 117} 118 119int SocketStreamHandlePrivate::send(const char* data, int len) 120{ 121 if (!m_socket || m_socket->state() != QAbstractSocket::ConnectedState) 122 return 0; 123 quint64 sentSize = m_socket->write(data, len); 124 QMetaObject::invokeMethod(this, "socketSentData", Qt::QueuedConnection); 125 return sentSize; 126} 127 128void SocketStreamHandlePrivate::close() 129{ 130 if (m_streamHandle && m_streamHandle->m_state == SocketStreamHandleBase::Connecting) { 131 m_socket->abort(); 132 m_streamHandle->client()->didCloseSocketStream(m_streamHandle); 133 return; 134 } 135 if (m_socket && m_socket->state() == QAbstractSocket::ConnectedState) 136 m_socket->close(); 137} 138 139void SocketStreamHandlePrivate::socketSentData() 140{ 141 if (m_streamHandle) 142 m_streamHandle->sendPendingData(); 143} 144 145void SocketStreamHandlePrivate::socketClosed() 146{ 147 QMetaObject::invokeMethod(this, "socketClosedCallback", Qt::QueuedConnection); 148} 149 150void SocketStreamHandlePrivate::socketError(QAbstractSocket::SocketError error) 151{ 152 QMetaObject::invokeMethod(this, "socketErrorCallback", Qt::QueuedConnection, Q_ARG(int, error)); 153} 154 155void SocketStreamHandlePrivate::socketClosedCallback() 156{ 157 if (m_streamHandle && m_streamHandle->client()) { 158 SocketStreamHandle* streamHandle = m_streamHandle; 159 m_streamHandle = 0; 160 // This following call deletes _this_. Nothing should be after it. 161 streamHandle->client()->didCloseSocketStream(streamHandle); 162 } 163} 164 165void SocketStreamHandlePrivate::socketErrorCallback(int error) 166{ 167 // FIXME - in the future, we might not want to treat all errors as fatal. 168 if (m_streamHandle && m_streamHandle->client()) { 169 SocketStreamHandle* streamHandle = m_streamHandle; 170 m_streamHandle = 0; 171 172 streamHandle->client()->didFailSocketStream(streamHandle, SocketStreamError(error, m_socket->errorString())); 173 174 // This following call deletes _this_. Nothing should be after it. 175 streamHandle->client()->didCloseSocketStream(streamHandle); 176 } 177} 178 179#ifndef QT_NO_OPENSSL 180void SocketStreamHandlePrivate::socketSslErrors(const QList<QSslError>& error) 181{ 182 QMetaObject::invokeMethod(this, "socketErrorCallback", Qt::QueuedConnection, Q_ARG(int, error[0].error())); 183} 184#endif 185 186SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient* client) 187 : SocketStreamHandleBase(url, client) 188{ 189 LOG(Network, "SocketStreamHandle %p new client %p", this, m_client); 190 m_p = new SocketStreamHandlePrivate(this, url); 191} 192 193SocketStreamHandle::SocketStreamHandle(QTcpSocket* socket, SocketStreamHandleClient* client) 194 : SocketStreamHandleBase(KURL(), client) 195{ 196 LOG(Network, "SocketStreamHandle %p new client %p", this, m_client); 197 m_p = new SocketStreamHandlePrivate(this, socket); 198 if (socket->isOpen()) 199 m_state = Open; 200} 201 202SocketStreamHandle::~SocketStreamHandle() 203{ 204 LOG(Network, "SocketStreamHandle %p delete", this); 205 setClient(0); 206 delete m_p; 207} 208 209int SocketStreamHandle::platformSend(const char* data, int len) 210{ 211 LOG(Network, "SocketStreamHandle %p platformSend", this); 212 return m_p->send(data, len); 213} 214 215void SocketStreamHandle::platformClose() 216{ 217 LOG(Network, "SocketStreamHandle %p platformClose", this); 218 m_p->close(); 219} 220 221void SocketStreamHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&) 222{ 223 notImplemented(); 224} 225 226void SocketStreamHandle::receivedCredential(const AuthenticationChallenge&, const Credential&) 227{ 228 notImplemented(); 229} 230 231void SocketStreamHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) 232{ 233 notImplemented(); 234} 235 236void SocketStreamHandle::receivedCancellation(const AuthenticationChallenge&) 237{ 238 notImplemented(); 239} 240 241} // namespace WebCore 242 243#include "moc_SocketStreamHandlePrivate.cpp" 244