Index: net/socket/web_socket_server_socket.cc |
diff --git a/net/socket/web_socket_server_socket.cc b/net/socket/web_socket_server_socket.cc |
index 4bb7b9f074dc18684793993ba7c79cf1d7f39684..d79268981fb08f847e814a1f3d271617ef0c1a9b 100644 |
--- a/net/socket/web_socket_server_socket.cc |
+++ b/net/socket/web_socket_server_socket.cc |
@@ -135,8 +135,11 @@ class WebSocketServerSocketImpl : public net::WebSocketServerSocket { |
it->type == PendingReq::TYPE_READ && |
it->io_buf != NULL && |
it->io_buf->data() != NULL && |
- it->callback != 0) { |
- it->callback->Run(0); // Report EOF. |
+ (it->old_callback || !it->callback.is_null())) { |
+ if (it->old_callback) |
+ it->old_callback->Run(0); // Report EOF. |
+ else |
+ it->callback.Run(0); |
} |
} |
@@ -175,6 +178,26 @@ class WebSocketServerSocketImpl : public net::WebSocketServerSocket { |
net::OldCompletionCallback* callback) |
: type(type), |
io_buf(io_buf), |
+ old_callback(callback) { |
+ switch (type) { |
+ case PendingReq::TYPE_READ: |
+ case PendingReq::TYPE_WRITE: |
+ case PendingReq::TYPE_READ_METADATA: |
+ case PendingReq::TYPE_WRITE_METADATA: { |
+ DCHECK(io_buf); |
+ break; |
+ } |
+ default: { |
+ NOTREACHED(); |
+ break; |
+ } |
+ } |
+ } |
+ PendingReq(Type type, net::DrainableIOBuffer* io_buf, |
+ const net::CompletionCallback& callback) |
+ : type(type), |
+ io_buf(io_buf), |
+ old_callback(NULL), |
callback(callback) { |
switch (type) { |
case PendingReq::TYPE_READ: |
@@ -193,7 +216,8 @@ class WebSocketServerSocketImpl : public net::WebSocketServerSocket { |
Type type; |
scoped_refptr<net::DrainableIOBuffer> io_buf; |
- net::OldCompletionCallback* callback; |
+ net::OldCompletionCallback* old_callback; |
+ net::CompletionCallback callback; |
}; |
// Socket implementation. |
@@ -261,6 +285,70 @@ class WebSocketServerSocketImpl : public net::WebSocketServerSocket { |
} |
return net::ERR_IO_PENDING; |
} |
+ virtual int Read(net::IOBuffer* buf, int buf_len, |
+ const net::CompletionCallback& callback) OVERRIDE { |
+ if (buf_len == 0) |
+ return 0; |
+ if (buf == NULL || buf_len < 0) { |
+ NOTREACHED(); |
+ return net::ERR_INVALID_ARGUMENT; |
+ } |
+ while (int bytes_remaining = fill_handshake_buf_->BytesConsumed() - |
+ process_handshake_buf_->BytesConsumed()) { |
+ DCHECK(!is_transport_read_pending_); |
+ DCHECK(GetPendingReq(PendingReq::TYPE_READ) == pending_reqs_.end()); |
+ switch (phase_) { |
+ case PHASE_FRAME_OUTSIDE: |
+ case PHASE_FRAME_INSIDE: |
+ case PHASE_FRAME_LENGTH: |
+ case PHASE_FRAME_SKIP: { |
+ int n = std::min(bytes_remaining, buf_len); |
+ int rv = ProcessDataFrames( |
+ process_handshake_buf_->data(), n, buf->data(), buf_len); |
+ process_handshake_buf_->DidConsume(n); |
+ if (rv == 0) { |
+ // ProcessDataFrames may return zero for non-empty buffer if it |
+ // contains only frame delimiters without real data. In this case: |
+ // try again and do not just return zero (zero stands for EOF). |
+ continue; |
+ } |
+ return rv; |
+ } |
+ case PHASE_SHUT: { |
+ return 0; |
+ } |
+ case PHASE_NYMPH: |
+ case PHASE_HANDSHAKE: |
+ default: { |
+ NOTREACHED(); |
+ return net::ERR_UNEXPECTED; |
+ } |
+ } |
+ } |
+ switch (phase_) { |
+ case PHASE_FRAME_OUTSIDE: |
+ case PHASE_FRAME_INSIDE: |
+ case PHASE_FRAME_LENGTH: |
+ case PHASE_FRAME_SKIP: { |
+ pending_reqs_.push_back(PendingReq( |
+ PendingReq::TYPE_READ, |
+ new net::DrainableIOBuffer(buf, buf_len), |
+ callback)); |
+ ConsiderTransportRead(); |
+ break; |
+ } |
+ case PHASE_SHUT: { |
+ return 0; |
+ } |
+ case PHASE_NYMPH: |
+ case PHASE_HANDSHAKE: |
+ default: { |
+ NOTREACHED(); |
+ return net::ERR_UNEXPECTED; |
+ } |
+ } |
+ return net::ERR_IO_PENDING; |
+ } |
virtual int Write(net::IOBuffer* buf, int buf_len, |
net::OldCompletionCallback* callback) OVERRIDE { |
@@ -397,8 +485,10 @@ class WebSocketServerSocketImpl : public net::WebSocketServerSocket { |
if (result != 0) { |
while (!pending_reqs_.empty()) { |
PendingReq& req = pending_reqs_.front(); |
- if (req.callback) |
- req.callback->Run(result); |
+ if (req.old_callback) |
+ req.old_callback->Run(result); |
+ else if (!req.callback.is_null()) |
+ req.callback.Run(result); |
pending_reqs_.pop_front(); |
} |
transport_socket_.reset(); // terminate underlying connection. |
@@ -447,11 +537,15 @@ class WebSocketServerSocketImpl : public net::WebSocketServerSocket { |
if (rv > 0) { |
process_handshake_buf_->DidConsume(rv); |
phase_ = PHASE_FRAME_OUTSIDE; |
- net::OldCompletionCallback* cb = pending_reqs_.front().callback; |
+ net::OldCompletionCallback* old_cb = |
+ pending_reqs_.front().old_callback; |
+ net::CompletionCallback cb = pending_reqs_.front().callback; |
pending_reqs_.pop_front(); |
ConsiderTransportWrite(); // Schedule answer handshake. |
- if (cb) |
- cb->Run(0); |
+ if (old_cb) |
+ old_cb->Run(0); |
+ else if (!cb.is_null()) |
+ cb.Run(0); |
} else if (rv == net::ERR_IO_PENDING) { |
if (fill_handshake_buf_->BytesRemaining() < 1) |
Shut(net::ERR_LIMIT_VIOLATION); |
@@ -474,10 +568,13 @@ class WebSocketServerSocketImpl : public net::WebSocketServerSocket { |
return; |
} |
if (rv > 0 || phase_ == PHASE_SHUT) { |
- net::OldCompletionCallback* cb = it->callback; |
+ net::OldCompletionCallback* old_cb = it->old_callback; |
+ net::CompletionCallback cb = it->callback; |
pending_reqs_.erase(it); |
- if (cb) |
- cb->Run(rv); |
+ if (old_cb) |
+ old_cb->Run(rv); |
+ else if (!cb.is_null()) |
+ cb.Run(rv); |
} |
break; |
} |
@@ -515,12 +612,15 @@ class WebSocketServerSocketImpl : public net::WebSocketServerSocket { |
DCHECK_LE(result, it->io_buf->BytesRemaining()); |
it->io_buf->DidConsume(result); |
if (it->io_buf->BytesRemaining() == 0) { |
- net::OldCompletionCallback* cb = it->callback; |
+ net::OldCompletionCallback* old_cb = it->old_callback; |
+ net::CompletionCallback cb = it->callback; |
int bytes_written = it->io_buf->BytesConsumed(); |
DCHECK_GT(bytes_written, 0); |
pending_reqs_.erase(it); |
- if (cb) |
- cb->Run(bytes_written); |
+ if (old_cb) |
+ old_cb->Run(bytes_written); |
+ else if (!cb.is_null()) |
+ cb.Run(bytes_written); |
} |
ConsiderTransportWrite(); |
} |