Chromium Code Reviews| Index: runtime/bin/eventhandler_win.cc |
| diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc |
| index f7f1f17d32cd914cc75cf64e06920644baceeaf8..532030a8312247faaece9e4f1fbebc309d244b0a 100644 |
| --- a/runtime/bin/eventhandler_win.cc |
| +++ b/runtime/bin/eventhandler_win.cc |
| @@ -342,19 +342,30 @@ bool ListenSocket::IssueAccept() { |
| void ListenSocket::AcceptComplete(IOBuffer* buffer, HANDLE completion_port) { |
| ScopedLock lock(this); |
| if (!closing_) { |
| - ClientSocket* client_socket = new ClientSocket(buffer->client(), 0); |
| - client_socket->CreateCompletionPort(completion_port); |
| - if (accepted_head_ == NULL) { |
| - accepted_head_ = client_socket; |
| - accepted_tail_ = client_socket; |
| + // Update the accepted socket to support the full range of API calls. |
| + SOCKET s = socket(); |
| + int rc = setsockopt(buffer->client(), |
| + SOL_SOCKET, |
| + SO_UPDATE_ACCEPT_CONTEXT, |
| + reinterpret_cast<char *>(&s), sizeof(s)); |
|
Mads Ager (google)
2011/11/04 12:21:36
char * -> char*
Søren Gjesse
2011/11/04 12:33:02
Done.
|
| + if (rc == NO_ERROR) { |
| + // Insert the accepted socket into the list. |
| + ClientSocket* client_socket = new ClientSocket(buffer->client(), 0); |
| + client_socket->CreateCompletionPort(completion_port); |
| + if (accepted_head_ == NULL) { |
| + accepted_head_ = client_socket; |
| + accepted_tail_ = client_socket; |
| + } else { |
| + ASSERT(accepted_tail_ != NULL); |
| + accepted_tail_->set_next(client_socket); |
| + accepted_tail_ = client_socket; |
| + } |
| } else { |
| - ASSERT(accepted_tail_ != NULL); |
| - accepted_tail_->set_next(client_socket); |
| - accepted_tail_ = client_socket; |
| + fprintf(stderr, "setsockopt failed: %d\n", WSAGetLastError()); |
| + closesocket(buffer->client()); |
| } |
| - } else { |
| - closesocket(buffer->client()); |
| } |
| + |
| pending_accept_count_--; |
| IOBuffer::DisposeBuffer(buffer); |
| } |
| @@ -366,6 +377,7 @@ ClientSocket* ListenSocket::Accept() { |
| ClientSocket* result = accepted_head_; |
| accepted_head_ = accepted_head_->next(); |
| if (accepted_head_ == NULL) accepted_tail_ = NULL; |
| + result->set_next(NULL); |
| return result; |
| } |
| @@ -433,6 +445,19 @@ int Handle::Write(const void* buffer, int num_bytes) { |
| return num_bytes; |
| } |
| +void ClientSocket::Shutdown(int how) { |
| + int rc = shutdown(socket(), how); |
| + if (rc == SOCKET_ERROR) { |
| + fprintf(stderr, "shutdown failed: %d %d\n", socket(), WSAGetLastError()); |
| + } |
| + if (how == SD_RECEIVE) MarkClosedRead(); |
| + if (how == SD_SEND) MarkClosedWrite(); |
| + if (how == SD_BOTH) { |
| + MarkClosedRead(); |
| + MarkClosedWrite(); |
| + } |
| +} |
| + |
| bool ClientSocket::IssueRead() { |
| ScopedLock lock(this); |
| @@ -554,14 +579,15 @@ void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) { |
| Handle::ScopedLock lock(client_socket); |
| - // If data available callback has been requested and data are |
| + // If the data available callback has been requested and data are |
| // available post it immediately. Otherwise make sure that a pending |
| - // read is issued. |
| + // read is issued unless the socket is already closed for read. |
| if ((msg->data & (1 << kInEvent)) != 0) { |
| if (client_socket->Available() > 0) { |
| int event_mask = (1 << kInEvent); |
| Dart_PostIntArray(client_socket->port(), 1, &event_mask); |
| - } else if (!client_socket->HasPendingRead()) { |
| + } else if (!client_socket->HasPendingRead() && |
| + !client_socket->IsClosedRead()) { |
| client_socket->IssueRead(); |
| } |
| } |
| @@ -575,6 +601,14 @@ void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) { |
| } |
| } |
| + if ((msg->data & (1 << kShutdownReadCommand)) != 0) { |
| + client_socket->Shutdown(SD_RECEIVE); |
| + } |
| + |
| + if ((msg->data & (1 << kShutdownWriteCommand)) != 0) { |
| + client_socket->Shutdown(SD_SEND); |
| + } |
| + |
| if ((msg->data & (1 << kCloseCommand)) != 0) { |
| client_socket->close(); |
| if (client_socket->IsClosed()) { |
| @@ -621,7 +655,6 @@ void EventHandlerImplementation::HandleRead(ClientSocket* client_socket, |
| IOBuffer* buffer) { |
| buffer->set_data_length(bytes); |
| client_socket->ReadComplete(buffer); |
| - |
| if (bytes > 0) { |
| if (!client_socket->is_closing()) { |
| int event_mask = 1 << kInEvent; |
| @@ -631,6 +664,7 @@ void EventHandlerImplementation::HandleRead(ClientSocket* client_socket, |
| } |
| } else { |
| ASSERT(bytes == 0); |
| + client_socket->MarkClosedRead(); |
| HandleClosed(client_socket); |
| } |