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