| Index: runtime/bin/eventhandler_win.cc
|
| diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
|
| index f7f1f17d32cd914cc75cf64e06920644baceeaf8..1b1202894f72e150e591b13cc7e296075b3f58da 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));
|
| + 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);
|
| }
|
|
|
|
|