Remove RELEASE_ASSERT added in r230875.
[WebKit-https.git] / Source / WebCore / platform / network / SocketStreamHandleImpl.cpp
1 /*
2  * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "SocketStreamHandleImpl.h"
28
29 #include "CookieRequestHeaderFieldProxy.h"
30 #include "NetworkStorageSession.h"
31 #include "PlatformCookieJar.h"
32 #include "SocketStreamHandleClient.h"
33 #include <wtf/Function.h>
34
35 namespace WebCore {
36
37 void SocketStreamHandleImpl::platformSend(const uint8_t* data, size_t length, Function<void(bool)>&& completionHandler)
38 {
39     if (!m_buffer.isEmpty()) {
40         if (m_buffer.size() + length > maxBufferSize) {
41             // FIXME: report error to indicate that buffer has no more space.
42             return completionHandler(false);
43         }
44         m_buffer.append(data, length);
45         m_client.didUpdateBufferedAmount(*this, bufferedAmount());
46         return completionHandler(true);
47     }
48     size_t bytesWritten = 0;
49     if (m_state == Open) {
50         if (auto result = platformSendInternal(data, length))
51             bytesWritten = result.value();
52         else
53             return completionHandler(false);
54     }
55     if (m_buffer.size() + length - bytesWritten > maxBufferSize) {
56         // FIXME: report error to indicate that buffer has no more space.
57         return completionHandler(false);
58     }
59     if (bytesWritten < length) {
60         m_buffer.append(data + bytesWritten, length - bytesWritten);
61         m_client.didUpdateBufferedAmount(static_cast<SocketStreamHandle&>(*this), bufferedAmount());
62     }
63     return completionHandler(true);
64 }
65
66 static size_t removeTerminationCharacters(const uint8_t* data, size_t dataLength)
67 {
68 #ifndef NDEBUG
69     ASSERT(dataLength > 2);
70     ASSERT(data[dataLength - 2] == '\r');
71     ASSERT(data[dataLength - 1] == '\n');
72 #else
73     UNUSED_PARAM(data);
74 #endif
75
76     // Remove the terminating '\r\n'
77     return dataLength - 2;
78 }
79
80 static std::optional<std::pair<Vector<uint8_t>, bool>> cookieDataForHandshake(const CookieRequestHeaderFieldProxy& headerFieldProxy)
81 {
82     auto networkStorageSession = NetworkStorageSession::storageSession(headerFieldProxy.sessionID);
83     if (!networkStorageSession)
84         return std::nullopt;
85     
86     String cookieDataString;
87     bool secureCookiesAccessed = false;
88     std::tie(cookieDataString, secureCookiesAccessed) = WebCore::cookieRequestHeaderFieldValue(*networkStorageSession, headerFieldProxy);
89     if (cookieDataString.isEmpty())
90         return std::pair<Vector<uint8_t>, bool> { { }, secureCookiesAccessed };
91
92     CString cookieData = cookieDataString.utf8();
93
94     Vector<uint8_t> data = { 'C', 'o', 'o', 'k', 'i', 'e', ':', ' ' };
95     data.append(cookieData.data(), cookieData.length());
96     data.appendVector(Vector<uint8_t>({ '\r', '\n', '\r', '\n' }));
97
98     return std::pair<Vector<uint8_t>, bool> { data, secureCookiesAccessed };
99 }
100
101 void SocketStreamHandleImpl::platformSendHandshake(const uint8_t* data, size_t length, const std::optional<CookieRequestHeaderFieldProxy>& headerFieldProxy, Function<void(bool, bool)>&& completionHandler)
102 {
103     Vector<uint8_t> cookieData;
104     bool secureCookiesAccessed = false;
105
106     if (headerFieldProxy) {
107         auto cookieDataFromNetworkSession = cookieDataForHandshake(headerFieldProxy.value());
108         if (!cookieDataFromNetworkSession) {
109             completionHandler(false, false);
110             return;
111         }
112
113         std::tie(cookieData, secureCookiesAccessed) = *cookieDataFromNetworkSession;
114         if (cookieData.size())
115             length = removeTerminationCharacters(data, length);
116     }
117
118     if (!m_buffer.isEmpty()) {
119         if (m_buffer.size() + length + cookieData.size() > maxBufferSize) {
120             // FIXME: report error to indicate that buffer has no more space.
121             return completionHandler(false, secureCookiesAccessed);
122         }
123         m_buffer.append(data, length);
124         m_buffer.append(cookieData.data(), cookieData.size());
125         m_client.didUpdateBufferedAmount(*this, bufferedAmount());
126         return completionHandler(true, secureCookiesAccessed);
127     }
128     size_t bytesWritten = 0;
129     if (m_state == Open) {
130         // Unfortunately, we need to send the data in one buffer or else the handshake fails.
131         Vector<uint8_t> sendData;
132         sendData.reserveCapacity(length + cookieData.size());
133         sendData.append(data, length);
134         sendData.append(cookieData.data(), cookieData.size());
135
136         if (auto result = platformSendInternal(sendData.data(), sendData.size()))
137             bytesWritten = result.value();
138         else
139             return completionHandler(false, secureCookiesAccessed);
140     }
141     if (m_buffer.size() + length + cookieData.size() - bytesWritten > maxBufferSize) {
142         // FIXME: report error to indicate that buffer has no more space.
143         return completionHandler(false, secureCookiesAccessed);
144     }
145     if (bytesWritten < length + cookieData.size()) {
146         size_t cookieBytesWritten = 0;
147         if (bytesWritten < length)
148             m_buffer.append(data + bytesWritten, length - bytesWritten);
149         else
150             cookieBytesWritten = bytesWritten - length;
151         m_buffer.append(cookieData.data() + cookieBytesWritten, cookieData.size() - cookieBytesWritten);
152         m_client.didUpdateBufferedAmount(static_cast<SocketStreamHandle&>(*this), bufferedAmount());
153     }
154     return completionHandler(true, secureCookiesAccessed);
155 }
156
157 bool SocketStreamHandleImpl::sendPendingData()
158 {
159     if (m_state != Open && m_state != Closing)
160         return false;
161     if (m_buffer.isEmpty()) {
162         if (m_state == Open)
163             return false;
164         if (m_state == Closing) {
165             disconnect();
166             return false;
167         }
168     }
169     bool pending;
170     do {
171         auto result = platformSendInternal(m_buffer.firstBlockData(), m_buffer.firstBlockSize());
172         if (!result)
173             return false;
174         size_t bytesWritten = result.value();
175         if (!bytesWritten)
176             return false;
177         pending = bytesWritten != m_buffer.firstBlockSize();
178         ASSERT(m_buffer.size() - bytesWritten <= maxBufferSize);
179         m_buffer.consume(bytesWritten);
180     } while (!pending && !m_buffer.isEmpty());
181     m_client.didUpdateBufferedAmount(static_cast<SocketStreamHandle&>(*this), bufferedAmount());
182     return true;
183 }
184
185 size_t SocketStreamHandleImpl::bufferedAmount()
186 {
187     return m_buffer.size();
188 }
189
190 } // namespace WebCore