• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SocketStreamHandlePrivate(SocketStreamHandle * streamHandle,const KURL & url)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 
~SocketStreamHandlePrivate()77 SocketStreamHandlePrivate::~SocketStreamHandlePrivate()
78 {
79     Q_ASSERT(!(m_socket && m_socket->state() == QAbstractSocket::ConnectedState));
80 }
81 
socketConnected()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 
socketReadyRead()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 
send(const char * data,int len)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 
close()107 void SocketStreamHandlePrivate::close()
108 {
109     if (m_socket && m_socket->state() == QAbstractSocket::ConnectedState)
110         m_socket->close();
111 }
112 
socketSentdata()113 void SocketStreamHandlePrivate::socketSentdata()
114 {
115     if (m_streamHandle)
116         m_streamHandle->sendPendingData();
117 }
118 
socketClosed()119 void SocketStreamHandlePrivate::socketClosed()
120 {
121     QMetaObject::invokeMethod(this, "socketClosedCallback", Qt::QueuedConnection);
122 }
123 
socketError(QAbstractSocket::SocketError error)124 void SocketStreamHandlePrivate::socketError(QAbstractSocket::SocketError error)
125 {
126     QMetaObject::invokeMethod(this, "socketErrorCallback", Qt::QueuedConnection, Q_ARG(int, error));
127 }
128 
socketClosedCallback()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 
socketErrorCallback(int error)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
socketSslErrors(const QList<QSslError> &)151 void SocketStreamHandlePrivate::socketSslErrors(const QList<QSslError>&)
152 {
153     // FIXME: based on http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-68#page-15
154     // we should abort on certificate errors.
155     // We don't abort while this is still work in progress.
156     static_cast<QSslSocket*>(m_socket)->ignoreSslErrors();
157 }
158 #endif
159 
SocketStreamHandle(const KURL & url,SocketStreamHandleClient * client)160 SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient* client)
161     : SocketStreamHandleBase(url, client)
162 {
163     LOG(Network, "SocketStreamHandle %p new client %p", this, m_client);
164     m_p = new SocketStreamHandlePrivate(this, url);
165 }
166 
~SocketStreamHandle()167 SocketStreamHandle::~SocketStreamHandle()
168 {
169     LOG(Network, "SocketStreamHandle %p delete", this);
170     setClient(0);
171     delete m_p;
172 }
173 
platformSend(const char * data,int len)174 int SocketStreamHandle::platformSend(const char* data, int len)
175 {
176     LOG(Network, "SocketStreamHandle %p platformSend", this);
177     return m_p->send(data, len);
178 }
179 
platformClose()180 void SocketStreamHandle::platformClose()
181 {
182     LOG(Network, "SocketStreamHandle %p platformClose", this);
183     m_p->close();
184 }
185 
didReceiveAuthenticationChallenge(const AuthenticationChallenge &)186 void SocketStreamHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&)
187 {
188     notImplemented();
189 }
190 
receivedCredential(const AuthenticationChallenge &,const Credential &)191 void SocketStreamHandle::receivedCredential(const AuthenticationChallenge&, const Credential&)
192 {
193     notImplemented();
194 }
195 
receivedRequestToContinueWithoutCredential(const AuthenticationChallenge &)196 void SocketStreamHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&)
197 {
198     notImplemented();
199 }
200 
receivedCancellation(const AuthenticationChallenge &)201 void SocketStreamHandle::receivedCancellation(const AuthenticationChallenge&)
202 {
203     notImplemented();
204 }
205 
206 } // namespace WebCore
207 
208 #include "moc_SocketStreamHandlePrivate.cpp"
209