blob: 450ce3248aa6aacbe0abb8684fbc43d746e41c65 [file] [log] [blame]
[email protected]473282d2013-07-02 11:57:071// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/websockets/websocket_stream.h"
6
7#include "base/logging.h"
[email protected]efa9e732013-11-29 02:55:058#include "base/memory/scoped_ptr.h"
9#include "net/http/http_request_headers.h"
10#include "net/http/http_status_code.h"
11#include "net/url_request/url_request.h"
12#include "net/url_request/url_request_context.h"
13#include "net/websockets/websocket_errors.h"
14#include "net/websockets/websocket_handshake_constants.h"
15#include "net/websockets/websocket_handshake_stream_base.h"
16#include "net/websockets/websocket_handshake_stream_create_helper.h"
17#include "net/websockets/websocket_test_util.h"
18#include "url/gurl.h"
[email protected]473282d2013-07-02 11:57:0719
20namespace net {
[email protected]efa9e732013-11-29 02:55:0521namespace {
22
23class StreamRequestImpl;
24
25class Delegate : public URLRequest::Delegate {
26 public:
27 explicit Delegate(StreamRequestImpl* owner) : owner_(owner) {}
28 virtual ~Delegate() {}
29
30 // Implementation of URLRequest::Delegate methods.
31 virtual void OnResponseStarted(URLRequest* request) OVERRIDE;
32
33 virtual void OnAuthRequired(URLRequest* request,
34 AuthChallengeInfo* auth_info) OVERRIDE;
35
36 virtual void OnCertificateRequested(URLRequest* request,
37 SSLCertRequestInfo* cert_request_info)
38 OVERRIDE;
39
40 virtual void OnSSLCertificateError(URLRequest* request,
41 const SSLInfo& ssl_info,
42 bool fatal) OVERRIDE;
43
44 virtual void OnReadCompleted(URLRequest* request, int bytes_read) OVERRIDE;
45
46 private:
47 StreamRequestImpl* owner_;
48};
49
50class StreamRequestImpl : public WebSocketStreamRequest {
51 public:
52 StreamRequestImpl(
53 const GURL& url,
54 const URLRequestContext* context,
55 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
56 WebSocketHandshakeStreamCreateHelper* create_helper)
57 : delegate_(new Delegate(this)),
58 url_request_(url, DEFAULT_PRIORITY, delegate_.get(), context),
59 connect_delegate_(connect_delegate.Pass()),
60 create_helper_(create_helper) {}
61
62 // Destroying this object destroys the URLRequest, which cancels the request
63 // and so terminates the handshake if it is incomplete.
64 virtual ~StreamRequestImpl() {}
65
66 URLRequest* url_request() { return &url_request_; }
67
68 void PerformUpgrade() {
69 connect_delegate_->OnSuccess(create_helper_->stream()->Upgrade());
70 }
71
72 void ReportFailure() {
[email protected]96868202014-01-09 10:38:0473 std::string failure_message;
74 if (create_helper_->stream()) {
75 failure_message = create_helper_->stream()->GetFailureMessage();
76 } else {
77 switch (url_request_.status().status()) {
78 case URLRequestStatus::SUCCESS:
79 case URLRequestStatus::IO_PENDING:
80 break;
81 case URLRequestStatus::CANCELED:
82 failure_message = "WebSocket opening handshake was canceled";
83 break;
84 case URLRequestStatus::FAILED:
85 failure_message =
86 std::string("Error in connection establishment: ") +
87 ErrorToString(url_request_.status().error());
88 break;
89 }
90 }
91 connect_delegate_->OnFailure(failure_message);
[email protected]efa9e732013-11-29 02:55:0592 }
93
94 private:
95 // |delegate_| needs to be declared before |url_request_| so that it gets
96 // initialised first.
97 scoped_ptr<Delegate> delegate_;
98
99 // Deleting the StreamRequestImpl object deletes this URLRequest object,
100 // cancelling the whole connection.
101 URLRequest url_request_;
102
103 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate_;
104
105 // Owned by the URLRequest.
106 WebSocketHandshakeStreamCreateHelper* create_helper_;
107};
108
109void Delegate::OnResponseStarted(URLRequest* request) {
110 switch (request->GetResponseCode()) {
111 case HTTP_SWITCHING_PROTOCOLS:
112 owner_->PerformUpgrade();
113 return;
114
115 case HTTP_UNAUTHORIZED:
116 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
117 return;
118
119 default:
120 owner_->ReportFailure();
121 }
122}
123
124void Delegate::OnAuthRequired(URLRequest* request,
125 AuthChallengeInfo* auth_info) {
126 request->CancelAuth();
127}
128
129void Delegate::OnCertificateRequested(URLRequest* request,
130 SSLCertRequestInfo* cert_request_info) {
131 request->ContinueWithCertificate(NULL);
132}
133
134void Delegate::OnSSLCertificateError(URLRequest* request,
135 const SSLInfo& ssl_info,
136 bool fatal) {
137 request->Cancel();
138}
139
140void Delegate::OnReadCompleted(URLRequest* request, int bytes_read) {
141 NOTREACHED();
142}
143
144// Internal implementation of CreateAndConnectStream and
145// CreateAndConnectStreamForTesting.
146scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamWithCreateHelper(
147 const GURL& socket_url,
148 scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
149 const GURL& origin,
150 URLRequestContext* url_request_context,
151 const BoundNetLog& net_log,
152 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
153 scoped_ptr<StreamRequestImpl> request(
154 new StreamRequestImpl(socket_url,
155 url_request_context,
156 connect_delegate.Pass(),
157 create_helper.get()));
158 HttpRequestHeaders headers;
159 headers.SetHeader(websockets::kUpgrade, websockets::kWebSocketLowercase);
160 headers.SetHeader(HttpRequestHeaders::kConnection, websockets::kUpgrade);
161 headers.SetHeader(HttpRequestHeaders::kOrigin, origin.spec());
162 // TODO(ricea): Move the version number to websocket_handshake_constants.h
[email protected]d998825a2013-12-02 03:33:02163 headers.SetHeader(websockets::kSecWebSocketVersion,
164 websockets::kSupportedVersion);
[email protected]efa9e732013-11-29 02:55:05165 request->url_request()->SetExtraRequestHeaders(headers);
166 request->url_request()->SetUserData(
167 WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
168 create_helper.release());
169 request->url_request()->SetLoadFlags(LOAD_DISABLE_CACHE |
170 LOAD_DO_NOT_PROMPT_FOR_LOGIN);
171 request->url_request()->Start();
172 return request.PassAs<WebSocketStreamRequest>();
173}
174
175} // namespace
[email protected]473282d2013-07-02 11:57:07176
177WebSocketStreamRequest::~WebSocketStreamRequest() {}
178
179WebSocketStream::WebSocketStream() {}
180WebSocketStream::~WebSocketStream() {}
181
182WebSocketStream::ConnectDelegate::~ConnectDelegate() {}
183
[email protected]473282d2013-07-02 11:57:07184scoped_ptr<WebSocketStreamRequest> WebSocketStream::CreateAndConnectStream(
185 const GURL& socket_url,
186 const std::vector<std::string>& requested_subprotocols,
187 const GURL& origin,
188 URLRequestContext* url_request_context,
189 const BoundNetLog& net_log,
190 scoped_ptr<ConnectDelegate> connect_delegate) {
[email protected]efa9e732013-11-29 02:55:05191 scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper(
192 new WebSocketHandshakeStreamCreateHelper(requested_subprotocols));
193 return CreateAndConnectStreamWithCreateHelper(socket_url,
194 create_helper.Pass(),
195 origin,
196 url_request_context,
197 net_log,
198 connect_delegate.Pass());
199}
200
201// This is declared in websocket_test_util.h.
202scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamForTesting(
203 const GURL& socket_url,
204 scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
205 const GURL& origin,
206 URLRequestContext* url_request_context,
207 const BoundNetLog& net_log,
208 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
209 return CreateAndConnectStreamWithCreateHelper(socket_url,
210 create_helper.Pass(),
211 origin,
212 url_request_context,
213 net_log,
214 connect_delegate.Pass());
[email protected]473282d2013-07-02 11:57:07215}
216
[email protected]473282d2013-07-02 11:57:07217} // namespace net