1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm>
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <limits>
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/websockets/websocket.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/host_resolver.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_handshake.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_handshake_draft75.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kClosingFrame[2] = {'\xff', '\x00'};
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int64 kClosingHandshakeTimeout = 1000;  // msec.
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottWebSocket::WebSocket(Request* request, WebSocketDelegate* delegate)
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : ready_state_(INITIALIZED),
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      request_(request),
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      handshake_(NULL),
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delegate_(delegate),
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      origin_loop_(MessageLoop::current()),
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      socket_stream_(NULL),
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      max_pending_send_allowed_(0),
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_read_buf_(NULL),
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_consumed_len_(0),
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      current_write_buf_(NULL),
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      server_closing_handshake_(false),
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_closing_handshake_(false),
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      closing_handshake_started_(false),
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      force_close_task_(NULL),
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      closing_handshake_timeout_(kClosingHandshakeTimeout) {
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(request_.get());
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(delegate_);
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(origin_loop_);
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottWebSocket::~WebSocket() {
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ready_state_ == INITIALIZED || !delegate_);
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!socket_stream_);
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!delegate_);
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::Connect() {
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ready_state_ == INITIALIZED);
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(request_.get());
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(delegate_);
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!socket_stream_);
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current() == origin_loop_);
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_stream_ = new SocketStream(request_->url(), this);
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_stream_->set_context(request_->context());
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_->host_resolver())
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    socket_stream_->SetHostResolver(request_->host_resolver());
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_->client_socket_factory())
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    socket_stream_->SetClientSocketFactory(request_->client_socket_factory());
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddRef();  // Release in DoClose().
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ready_state_ = CONNECTING;
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_stream_->Connect();
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::Send(const std::string& msg) {
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ready_state_ == CLOSING || ready_state_ == CLOSED) {
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (client_closing_handshake_) {
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We must not send any data after we start the WebSocket closing handshake.
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ready_state_ == OPEN);
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current() == origin_loop_);
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IOBufferWithSize* buf = new IOBufferWithSize(msg.size() + 2);
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char* p = buf->data();
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *p = '\0';
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(p + 1, msg.data(), msg.size());
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *(p + 1 + msg.size()) = '\xff';
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  pending_write_bufs_.push_back(make_scoped_refptr(buf));
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SendPending();
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::Close() {
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current() == origin_loop_);
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If connection has not yet started, do nothing.
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ready_state_ == INITIALIZED) {
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!socket_stream_);
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ready_state_ = CLOSED;
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the readyState attribute is in the CLOSING or CLOSED state, do nothing
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ready_state_ == CLOSING || ready_state_ == CLOSED)
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (request_->version() == DRAFT75) {
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(socket_stream_);
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    socket_stream_->Close();
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the WebSocket connection is not yet established, fail the WebSocket
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // connection and set the readyState attribute's value to CLOSING.
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ready_state_ == CONNECTING) {
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ready_state_ = CLOSING;
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    origin_loop_->PostTask(
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FROM_HERE,
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this, &WebSocket::FailConnection));
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the WebSocket closing handshake has not yet been started, start
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the WebSocket closing handshake and set the readyState attribute's value
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to CLOSING.
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!closing_handshake_started_) {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ready_state_ = CLOSING;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    origin_loop_->PostTask(
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FROM_HERE,
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this, &WebSocket::StartClosingHandshake));
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise, set the readyState attribute's value to CLOSING.
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ready_state_ = CLOSING;
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::DetachDelegate() {
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!delegate_)
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delegate_ = NULL;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ready_state_ == INITIALIZED) {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(!socket_stream_);
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ready_state_ = CLOSED;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ready_state_ != CLOSED) {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(socket_stream_);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    socket_stream_->Close();
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::OnConnected(SocketStream* socket_stream,
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            int max_pending_send_allowed) {
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(socket_stream == socket_stream_);
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  max_pending_send_allowed_ = max_pending_send_allowed;
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Use |max_pending_send_allowed| as hint for initial size of read buffer.
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  current_read_buf_ = new GrowableIOBuffer();
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  current_read_buf_->SetCapacity(max_pending_send_allowed_);
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_consumed_len_ = 0;
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!current_write_buf_);
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!handshake_.get());
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (request_->version()) {
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case DEFAULT_VERSION:
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      handshake_.reset(new WebSocketHandshake(
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          request_->url(), request_->origin(), request_->location(),
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          request_->protocol()));
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case DRAFT75:
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      handshake_.reset(new WebSocketHandshakeDraft75(
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          request_->url(), request_->origin(), request_->location(),
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          request_->protocol()));
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << "Unexpected protocol version:" << request_->version();
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string msg = handshake_->CreateClientHandshakeMessage();
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IOBufferWithSize* buf = new IOBufferWithSize(msg.size());
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(buf->data(), msg.data(), msg.size());
175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  pending_write_bufs_.push_back(make_scoped_refptr(buf));
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  origin_loop_->PostTask(FROM_HERE,
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         NewRunnableMethod(this, &WebSocket::SendPending));
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::OnSentData(SocketStream* socket_stream, int amount_sent) {
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(socket_stream == socket_stream_);
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(current_write_buf_);
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  current_write_buf_->DidConsume(amount_sent);
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GE(current_write_buf_->BytesRemaining(), 0);
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (current_write_buf_->BytesRemaining() == 0) {
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_write_buf_ = NULL;
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pending_write_bufs_.pop_front();
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  origin_loop_->PostTask(FROM_HERE,
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         NewRunnableMethod(this, &WebSocket::SendPending));
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::OnReceivedData(SocketStream* socket_stream,
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               const char* data, int len) {
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(socket_stream == socket_stream_);
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddToReadBuffer(data, len);
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  origin_loop_->PostTask(FROM_HERE,
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         NewRunnableMethod(this, &WebSocket::DoReceivedData));
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::OnClose(SocketStream* socket_stream) {
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  origin_loop_->PostTask(FROM_HERE,
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         NewRunnableMethod(this, &WebSocket::DoClose));
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::OnError(const SocketStream* socket_stream, int error) {
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  origin_loop_->PostTask(
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FROM_HERE, NewRunnableMethod(this, &WebSocket::DoSocketError, error));
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::SendPending() {
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current() == origin_loop_);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!socket_stream_) {
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(CLOSED, ready_state_);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!current_write_buf_) {
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (pending_write_bufs_.empty()) {
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (client_closing_handshake_) {
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Already sent 0xFF and 0x00 bytes.
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // *The WebSocket closing handshake has started.*
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        closing_handshake_started_ = true;
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (server_closing_handshake_) {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // 4.2 3-8-3 If the WebSocket connection is not already closed,
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // then close the WebSocket connection.
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // *The WebSocket closing handshake has finished*
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          socket_stream_->Close();
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // 5. Wait a user-agent-determined length of time, or until the
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // WebSocket connection is closed.
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          force_close_task_ =
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              NewRunnableMethod(this, &WebSocket::DoForceCloseConnection);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          origin_loop_->PostDelayedTask(
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              FROM_HERE, force_close_task_, closing_handshake_timeout_);
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_write_buf_ = new DrainableIOBuffer(
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pending_write_bufs_.front(), pending_write_bufs_.front()->size());
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(current_write_buf_->BytesRemaining(), 0);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool sent = socket_stream_->SendData(
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_write_buf_->data(),
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      std::min(current_write_buf_->BytesRemaining(),
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               max_pending_send_allowed_));
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(sent);
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::DoReceivedData() {
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current() == origin_loop_);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<WebSocket> protect(this);
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (ready_state_) {
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case CONNECTING:
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      {
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK(handshake_.get());
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK(current_read_buf_);
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        const char* data =
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            current_read_buf_->StartOfBuffer() + read_consumed_len_;
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        size_t len = current_read_buf_->offset() - read_consumed_len_;
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        int eoh = handshake_->ReadServerHandshake(data, len);
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (eoh < 0) {
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          // Not enough data,  Retry when more data is available.
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return;
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        SkipReadBuffer(eoh);
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (handshake_->mode() != WebSocketHandshake::MODE_CONNECTED) {
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Handshake failed.
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        socket_stream_->Close();
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ready_state_ = OPEN;
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (delegate_)
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        delegate_->OnOpen(this);
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (current_read_buf_->offset() == read_consumed_len_) {
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // No remaining data after handshake message.
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // FALL THROUGH
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case OPEN:
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case CLOSING:  // need to process closing-frame from server.
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ProcessFrameData();
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case CLOSED:
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Closed just after DoReceivedData is queued on |origin_loop_|.
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NOTREACHED();
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::ProcessFrameData() {
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(current_read_buf_);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (server_closing_handshake_) {
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Any data on the connection after the 0xFF frame is discarded.
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<WebSocket> protect(this);
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* start_frame =
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_read_buf_->StartOfBuffer() + read_consumed_len_;
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* next_frame = start_frame;
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* p = next_frame;
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* end =
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_read_buf_->StartOfBuffer() + current_read_buf_->offset();
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (p < end) {
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Let /error/ be false.
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool error = false;
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Handle the /frame type/ byte as follows.
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    unsigned char frame_byte = static_cast<unsigned char>(*p++);
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if ((frame_byte & 0x80) == 0x80) {
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int length = 0;
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      while (p < end) {
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (length > std::numeric_limits<int>::max() / 128) {
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          // frame length overflow.
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          socket_stream_->Close();
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return;
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        unsigned char c = static_cast<unsigned char>(*p);
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        length = length * 128 + (c & 0x7f);
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ++p;
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if ((c & 0x80) != 0x80)
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          break;
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Checks if the frame body hasn't been completely received yet.
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // It also checks the case the frame length bytes haven't been completely
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // received yet, because p == end and length > 0 in such case.
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (p + length < end) {
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        p += length;
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next_frame = p;
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (request_->version() != DRAFT75 &&
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            frame_byte == 0xFF && length == 0) {
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // 4.2 Data framing 3. Handle the /frame type/ byte.
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // 8. If the /frame type/ is 0xFF and the /length/ was 0, then
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // run the following substeps:
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // 1. If the WebSocket closing handshake has not yet started, then
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // start the WebSocket closing handshake.
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          server_closing_handshake_ = true;
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (!closing_handshake_started_) {
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            origin_loop_->PostTask(
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                FROM_HERE,
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                NewRunnableMethod(this, &WebSocket::StartClosingHandshake));
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          } else {
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            // If the WebSocket closing handshake has been started and
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            // the WebSocket connection is not already closed, then close
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            // the WebSocket connection.
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            socket_stream_->Close();
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          return;
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // 4.2 3-8 Otherwise, let /error/ be true.
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        error = true;
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Not enough data in buffer.
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const char* msg_start = p;
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      while (p < end && *p != '\xff')
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ++p;
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (p < end && *p == '\xff') {
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (frame_byte == 0x00) {
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (delegate_) {
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            delegate_->OnMessage(this, std::string(msg_start, p - msg_start));
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // Otherwise, discard the data and let /error/ to be true.
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          error = true;
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ++p;
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next_frame = p;
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If /error/ is true, then *a WebSocket error has been detected.*
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (error && delegate_)
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delegate_->OnError(this);
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SkipReadBuffer(next_frame - start_frame);
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::AddToReadBuffer(const char* data, int len) {
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(current_read_buf_);
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check if |current_read_buf_| has enough space to store |len| of |data|.
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (len >= current_read_buf_->RemainingCapacity()) {
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_read_buf_->SetCapacity(
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        current_read_buf_->offset() + len);
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(current_read_buf_->RemainingCapacity() >= len);
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(current_read_buf_->data(), data, len);
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  current_read_buf_->set_offset(current_read_buf_->offset() + len);
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::SkipReadBuffer(int len) {
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (len == 0)
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(len, 0);
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_consumed_len_ += len;
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int remaining = current_read_buf_->offset() - read_consumed_len_;
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GE(remaining, 0);
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (remaining < read_consumed_len_ &&
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_read_buf_->RemainingCapacity() < read_consumed_len_) {
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Pre compaction:
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // 0             v-read_consumed_len_  v-offset               v- capacity
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // |..processed..| .. remaining ..     | .. RemainingCapacity |
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    //
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memmove(current_read_buf_->StartOfBuffer(),
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            current_read_buf_->StartOfBuffer() + read_consumed_len_,
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            remaining);
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    read_consumed_len_ = 0;
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_read_buf_->set_offset(remaining);
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Post compaction:
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // 0read_consumed_len_  v- offset                             v- capacity
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // |.. remaining ..     | ..  RemainingCapacity  ...          |
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    //
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocket::StartClosingHandshake() {
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 4.2 *start the WebSocket closing handshake*.
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (closing_handshake_started_ || client_closing_handshake_) {
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // 1. If the WebSocket closing handshake has started, then abort these
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // steps.
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 2.,3. Send a 0xFF and 0x00 byte to the server.
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  client_closing_handshake_ = true;
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  IOBufferWithSize* buf = new IOBufferWithSize(2);
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  memcpy(buf->data(), kClosingFrame, 2);
433513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  pending_write_bufs_.push_back(make_scoped_refptr(buf));
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendPending();
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocket::DoForceCloseConnection() {
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 4.2 *start the WebSocket closing handshake*
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 6. If the WebSocket connection is not already closed, then close the
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WebSocket connection.  (If this happens, then the closing handshake
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // doesn't finish.)
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(MessageLoop::current() == origin_loop_);
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  force_close_task_ = NULL;
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FailConnection();
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocket::FailConnection() {
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(MessageLoop::current() == origin_loop_);
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 6.1 Client-initiated closure.
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // *fail the WebSocket connection*.
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the user agent must close the WebSocket connection, and may report the
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // problem to the user.
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!socket_stream_)
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  socket_stream_->Close();
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WebSocket::DoClose() {
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current() == origin_loop_);
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (force_close_task_) {
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // WebSocket connection is closed while waiting a user-agent-determined
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // length of time after *The WebSocket closing handshake has started*.
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    force_close_task_->Cancel();
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    force_close_task_ = NULL;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WebSocketDelegate* delegate = delegate_;
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delegate_ = NULL;
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ready_state_ = CLOSED;
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_stream_)
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_stream_ = NULL;
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate)
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delegate->OnClose(this,
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      server_closing_handshake_ && closing_handshake_started_);
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Release();
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebSocket::DoSocketError(int error) {
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current() == origin_loop_);
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_)
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delegate_->OnSocketError(this, error);
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
485