| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
| 6 #if defined(TARGET_OS_WINDOWS) | 6 #if defined(TARGET_OS_WINDOWS) |
| 7 | 7 |
| 8 #include "bin/eventhandler.h" | 8 #include "bin/eventhandler.h" |
| 9 | 9 |
| 10 #include <process.h> // NOLINT | 10 #include <process.h> // NOLINT |
| 11 #include <winsock2.h> // NOLINT | 11 #include <winsock2.h> // NOLINT |
| 12 #include <ws2tcpip.h> // NOLINT | 12 #include <ws2tcpip.h> // NOLINT |
| 13 #include <mswsock.h> // NOLINT | 13 #include <mswsock.h> // NOLINT |
| 14 | 14 |
| 15 #include "bin/builtin.h" | 15 #include "bin/builtin.h" |
| 16 #include "bin/dartutils.h" | 16 #include "bin/dartutils.h" |
| 17 #include "bin/log.h" | 17 #include "bin/log.h" |
| 18 #include "bin/socket.h" | 18 #include "bin/socket.h" |
| 19 #include "bin/utils.h" | 19 #include "bin/utils.h" |
| 20 #include "platform/thread.h" | 20 #include "platform/thread.h" |
| 21 | 21 |
| 22 | 22 |
| 23 static const int kInfinityTimeout = -1; | 23 static const int kInfinityTimeout = -1; |
| 24 static const int kTimeoutId = -1; | 24 static const int kTimeoutId = -1; |
| 25 static const int kShutdownId = -2; | 25 static const int kShutdownId = -2; |
| 26 | 26 |
| 27 | |
| 28 IOBuffer* IOBuffer::AllocateBuffer(int buffer_size, Operation operation) { | 27 IOBuffer* IOBuffer::AllocateBuffer(int buffer_size, Operation operation) { |
| 29 IOBuffer* buffer = new(buffer_size) IOBuffer(buffer_size, operation); | 28 IOBuffer* buffer = new(buffer_size) IOBuffer(buffer_size, operation); |
| 30 return buffer; | 29 return buffer; |
| 31 } | 30 } |
| 32 | 31 |
| 33 | 32 |
| 34 IOBuffer* IOBuffer::AllocateAcceptBuffer(int buffer_size) { | 33 IOBuffer* IOBuffer::AllocateAcceptBuffer(int buffer_size) { |
| 35 IOBuffer* buffer = AllocateBuffer(buffer_size, kAccept); | 34 IOBuffer* buffer = AllocateBuffer(buffer_size, kAccept); |
| 36 return buffer; | 35 return buffer; |
| 37 } | 36 } |
| 38 | 37 |
| 39 | 38 |
| 40 IOBuffer* IOBuffer::AllocateReadBuffer(int buffer_size) { | 39 IOBuffer* IOBuffer::AllocateReadBuffer(int buffer_size) { |
| 41 return AllocateBuffer(buffer_size, kRead); | 40 return AllocateBuffer(buffer_size, kRead); |
| 42 } | 41 } |
| 43 | 42 |
| 44 | 43 |
| 45 IOBuffer* IOBuffer::AllocateWriteBuffer(int buffer_size) { | 44 IOBuffer* IOBuffer::AllocateWriteBuffer(int buffer_size) { |
| 46 return AllocateBuffer(buffer_size, kWrite); | 45 return AllocateBuffer(buffer_size, kWrite); |
| 47 } | 46 } |
| 48 | 47 |
| 49 | 48 |
| 49 IOBuffer* IOBuffer::AllocateDisconnectBuffer() { |
| 50 return AllocateBuffer(0, kDisconnect); |
| 51 } |
| 52 |
| 53 |
| 50 void IOBuffer::DisposeBuffer(IOBuffer* buffer) { | 54 void IOBuffer::DisposeBuffer(IOBuffer* buffer) { |
| 51 delete buffer; | 55 delete buffer; |
| 52 } | 56 } |
| 53 | 57 |
| 54 | 58 |
| 55 IOBuffer* IOBuffer::GetFromOverlapped(OVERLAPPED* overlapped) { | 59 IOBuffer* IOBuffer::GetFromOverlapped(OVERLAPPED* overlapped) { |
| 56 IOBuffer* buffer = CONTAINING_RECORD(overlapped, IOBuffer, overlapped_); | 60 IOBuffer* buffer = CONTAINING_RECORD(overlapped, IOBuffer, overlapped_); |
| 57 return buffer; | 61 return buffer; |
| 58 } | 62 } |
| 59 | 63 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 reinterpret_cast<ULONG_PTR>(this), | 137 reinterpret_cast<ULONG_PTR>(this), |
| 134 0); | 138 0); |
| 135 if (completion_port_ == NULL) { | 139 if (completion_port_ == NULL) { |
| 136 Log::PrintErr("Error CreateIoCompletionPort: %d\n", GetLastError()); | 140 Log::PrintErr("Error CreateIoCompletionPort: %d\n", GetLastError()); |
| 137 return false; | 141 return false; |
| 138 } | 142 } |
| 139 return true; | 143 return true; |
| 140 } | 144 } |
| 141 | 145 |
| 142 | 146 |
| 143 void Handle::close() { | 147 void Handle::Close() { |
| 144 ScopedLock lock(this); | 148 ScopedLock lock(this); |
| 145 if (!IsClosing()) { | 149 if (!IsClosing()) { |
| 146 // Close the socket and set the closing state. This close method can be | 150 // Close the socket and set the closing state. This close method can be |
| 147 // called again if this socket has pending IO operations in flight. | 151 // called again if this socket has pending IO operations in flight. |
| 148 ASSERT(handle_ != INVALID_HANDLE_VALUE); | 152 ASSERT(handle_ != INVALID_HANDLE_VALUE); |
| 149 MarkClosing(); | 153 MarkClosing(); |
| 150 // According to the documentation from Microsoft socket handles should | 154 // Perform handle type specific closing. |
| 151 // not be closed using CloseHandle but using closesocket. | 155 DoClose(); |
| 152 if (is_socket()) { | |
| 153 closesocket(reinterpret_cast<SOCKET>(handle_)); | |
| 154 } else { | |
| 155 CloseHandle(handle_); | |
| 156 } | |
| 157 handle_ = INVALID_HANDLE_VALUE; | |
| 158 } | 156 } |
| 159 | |
| 160 // Perform socket type specific close handling. | |
| 161 AfterClose(); | |
| 162 } | 157 } |
| 163 | 158 |
| 164 | 159 |
| 160 void Handle::DoClose() { |
| 161 CloseHandle(handle_); |
| 162 handle_ = INVALID_HANDLE_VALUE; |
| 163 } |
| 164 |
| 165 |
| 165 bool Handle::HasPendingRead() { | 166 bool Handle::HasPendingRead() { |
| 166 ScopedLock lock(this); | 167 ScopedLock lock(this); |
| 167 return pending_read_ != NULL; | 168 return pending_read_ != NULL; |
| 168 } | 169 } |
| 169 | 170 |
| 170 | 171 |
| 171 bool Handle::HasPendingWrite() { | 172 bool Handle::HasPendingWrite() { |
| 172 ScopedLock lock(this); | 173 ScopedLock lock(this); |
| 173 return pending_write_ != NULL; | 174 return pending_write_ != NULL; |
| 174 } | 175 } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 CreateCompletionPort(event_handler_->completion_port()); | 307 CreateCompletionPort(event_handler_->completion_port()); |
| 307 } | 308 } |
| 308 } | 309 } |
| 309 | 310 |
| 310 | 311 |
| 311 bool FileHandle::IsClosed() { | 312 bool FileHandle::IsClosed() { |
| 312 return false; | 313 return false; |
| 313 } | 314 } |
| 314 | 315 |
| 315 | 316 |
| 316 void FileHandle::AfterClose() { | |
| 317 } | |
| 318 | |
| 319 | |
| 320 void SocketHandle::HandleIssueError() { | 317 void SocketHandle::HandleIssueError() { |
| 321 int error = WSAGetLastError(); | 318 int error = WSAGetLastError(); |
| 322 if (error == WSAECONNRESET) { | 319 if (error == WSAECONNRESET) { |
| 323 event_handler_->HandleClosed(this); | 320 event_handler_->HandleClosed(this); |
| 324 } else { | 321 } else { |
| 325 event_handler_->HandleError(this); | 322 event_handler_->HandleError(this); |
| 326 } | 323 } |
| 327 WSASetLastError(error); | 324 WSASetLastError(error); |
| 328 } | 325 } |
| 329 | 326 |
| 330 | 327 |
| 331 bool ListenSocket::LoadAcceptEx() { | 328 bool ListenSocket::LoadAcceptEx() { |
| 332 // Load the AcceptEx function into memory using WSAIoctl. | 329 // Load the AcceptEx function into memory using WSAIoctl. |
| 333 // The WSAIoctl function is an extension of the ioctlsocket() | |
| 334 // function that can use overlapped I/O. The function's 3rd | |
| 335 // through 6th parameters are input and output buffers where | |
| 336 // we pass the pointer to our AcceptEx function. This is used | |
| 337 // so that we can call the AcceptEx function directly, rather | |
| 338 // than refer to the Mswsock.lib library. | |
| 339 GUID guid_accept_ex = WSAID_ACCEPTEX; | 330 GUID guid_accept_ex = WSAID_ACCEPTEX; |
| 340 DWORD bytes; | 331 DWORD bytes; |
| 341 int status = WSAIoctl(socket(), | 332 int status = WSAIoctl(socket(), |
| 342 SIO_GET_EXTENSION_FUNCTION_POINTER, | 333 SIO_GET_EXTENSION_FUNCTION_POINTER, |
| 343 &guid_accept_ex, | 334 &guid_accept_ex, |
| 344 sizeof(guid_accept_ex), | 335 sizeof(guid_accept_ex), |
| 345 &AcceptEx_, | 336 &AcceptEx_, |
| 346 sizeof(AcceptEx_), | 337 sizeof(AcceptEx_), |
| 347 &bytes, | 338 &bytes, |
| 348 NULL, | 339 NULL, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 void ListenSocket::AcceptComplete(IOBuffer* buffer, HANDLE completion_port) { | 387 void ListenSocket::AcceptComplete(IOBuffer* buffer, HANDLE completion_port) { |
| 397 ScopedLock lock(this); | 388 ScopedLock lock(this); |
| 398 if (!IsClosing()) { | 389 if (!IsClosing()) { |
| 399 // Update the accepted socket to support the full range of API calls. | 390 // Update the accepted socket to support the full range of API calls. |
| 400 SOCKET s = socket(); | 391 SOCKET s = socket(); |
| 401 int rc = setsockopt(buffer->client(), | 392 int rc = setsockopt(buffer->client(), |
| 402 SOL_SOCKET, | 393 SOL_SOCKET, |
| 403 SO_UPDATE_ACCEPT_CONTEXT, | 394 SO_UPDATE_ACCEPT_CONTEXT, |
| 404 reinterpret_cast<char*>(&s), sizeof(s)); | 395 reinterpret_cast<char*>(&s), sizeof(s)); |
| 405 if (rc == NO_ERROR) { | 396 if (rc == NO_ERROR) { |
| 406 linger l; | |
| 407 l.l_onoff = 1; | |
| 408 l.l_linger = 10; | |
| 409 int status = setsockopt(buffer->client(), | |
| 410 SOL_SOCKET, | |
| 411 SO_LINGER, | |
| 412 reinterpret_cast<char*>(&l), | |
| 413 sizeof(l)); | |
| 414 if (status != NO_ERROR) { | |
| 415 FATAL("Failed setting SO_LINGER on socket"); | |
| 416 } | |
| 417 // Insert the accepted socket into the list. | 397 // Insert the accepted socket into the list. |
| 418 ClientSocket* client_socket = new ClientSocket(buffer->client(), 0); | 398 ClientSocket* client_socket = new ClientSocket(buffer->client(), 0); |
| 419 client_socket->CreateCompletionPort(completion_port); | 399 client_socket->CreateCompletionPort(completion_port); |
| 420 if (accepted_head_ == NULL) { | 400 if (accepted_head_ == NULL) { |
| 421 accepted_head_ = client_socket; | 401 accepted_head_ = client_socket; |
| 422 accepted_tail_ = client_socket; | 402 accepted_tail_ = client_socket; |
| 423 } else { | 403 } else { |
| 424 ASSERT(accepted_tail_ != NULL); | 404 ASSERT(accepted_tail_ != NULL); |
| 425 accepted_tail_->set_next(client_socket); | 405 accepted_tail_->set_next(client_socket); |
| 426 accepted_tail_ = client_socket; | 406 accepted_tail_ = client_socket; |
| 427 } | 407 } |
| 428 } else { | 408 } else { |
| 429 Log::PrintErr("setsockopt failed: %d\n", WSAGetLastError()); | 409 Log::PrintErr("setsockopt failed: %d\n", WSAGetLastError()); |
| 430 closesocket(buffer->client()); | 410 closesocket(buffer->client()); |
| 431 } | 411 } |
| 432 } | 412 } |
| 433 | 413 |
| 434 pending_accept_count_--; | 414 pending_accept_count_--; |
| 435 IOBuffer::DisposeBuffer(buffer); | 415 IOBuffer::DisposeBuffer(buffer); |
| 436 } | 416 } |
| 437 | 417 |
| 438 | 418 |
| 419 void ListenSocket::DoClose() { |
| 420 closesocket(socket()); |
| 421 handle_ = INVALID_HANDLE_VALUE; |
| 422 while (CanAccept()) { |
| 423 // Get rid of connections already accepted. |
| 424 ClientSocket *client = Accept(); |
| 425 if (client != NULL) { |
| 426 client->Close(); |
| 427 } else { |
| 428 break; |
| 429 } |
| 430 } |
| 431 } |
| 432 |
| 433 |
| 434 bool ListenSocket::CanAccept() { |
| 435 ScopedLock lock(this); |
| 436 return accepted_head_ != NULL; |
| 437 } |
| 438 |
| 439 |
| 439 ClientSocket* ListenSocket::Accept() { | 440 ClientSocket* ListenSocket::Accept() { |
| 440 ScopedLock lock(this); | 441 ScopedLock lock(this); |
| 441 if (accepted_head_ == NULL) return NULL; | 442 if (accepted_head_ == NULL) return NULL; |
| 442 ClientSocket* result = accepted_head_; | 443 ClientSocket* result = accepted_head_; |
| 443 accepted_head_ = accepted_head_->next(); | 444 accepted_head_ = accepted_head_->next(); |
| 444 if (accepted_head_ == NULL) accepted_tail_ = NULL; | 445 if (accepted_head_ == NULL) accepted_tail_ = NULL; |
| 445 result->set_next(NULL); | 446 result->set_next(NULL); |
| 446 return result; | 447 return result; |
| 447 } | 448 } |
| 448 | 449 |
| 449 | 450 |
| 450 void ListenSocket::EnsureInitialized( | 451 void ListenSocket::EnsureInitialized( |
| 451 EventHandlerImplementation* event_handler) { | 452 EventHandlerImplementation* event_handler) { |
| 452 ScopedLock lock(this); | 453 ScopedLock lock(this); |
| 453 if (AcceptEx_ == NULL) { | 454 if (AcceptEx_ == NULL) { |
| 454 ASSERT(completion_port_ == INVALID_HANDLE_VALUE); | 455 ASSERT(completion_port_ == INVALID_HANDLE_VALUE); |
| 455 ASSERT(event_handler_ == NULL); | 456 ASSERT(event_handler_ == NULL); |
| 456 event_handler_ = event_handler; | 457 event_handler_ = event_handler; |
| 457 CreateCompletionPort(event_handler_->completion_port()); | 458 CreateCompletionPort(event_handler_->completion_port()); |
| 458 LoadAcceptEx(); | 459 LoadAcceptEx(); |
| 459 } | 460 } |
| 460 } | 461 } |
| 461 | 462 |
| 462 | 463 |
| 463 void ListenSocket::AfterClose() { | |
| 464 ScopedLock lock(this); | |
| 465 while (true) { | |
| 466 // Get rid of connections already accepted. | |
| 467 ClientSocket *client = Accept(); | |
| 468 if (client != NULL) { | |
| 469 client->close(); | |
| 470 } else { | |
| 471 break; | |
| 472 } | |
| 473 } | |
| 474 } | |
| 475 | |
| 476 | |
| 477 bool ListenSocket::IsClosed() { | 464 bool ListenSocket::IsClosed() { |
| 478 return IsClosing() && !HasPendingAccept(); | 465 return IsClosing() && !HasPendingAccept(); |
| 479 } | 466 } |
| 480 | 467 |
| 481 | 468 |
| 482 int Handle::Available() { | 469 int Handle::Available() { |
| 483 ScopedLock lock(this); | 470 ScopedLock lock(this); |
| 484 if (data_ready_ == NULL) return 0; | 471 if (data_ready_ == NULL) return 0; |
| 485 ASSERT(!data_ready_->IsEmpty()); | 472 ASSERT(!data_ready_->IsEmpty()); |
| 486 return data_ready_->GetRemainingLength(); | 473 return data_ready_->GetRemainingLength(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 if (GetLastError() != ERROR_BROKEN_PIPE) { | 507 if (GetLastError() != ERROR_BROKEN_PIPE) { |
| 521 Log::PrintErr("WriteFile failed: %d\n", GetLastError()); | 508 Log::PrintErr("WriteFile failed: %d\n", GetLastError()); |
| 522 } | 509 } |
| 523 event_handler_->HandleClosed(this); | 510 event_handler_->HandleClosed(this); |
| 524 } | 511 } |
| 525 return bytes_written; | 512 return bytes_written; |
| 526 } | 513 } |
| 527 } | 514 } |
| 528 | 515 |
| 529 | 516 |
| 517 bool ClientSocket::LoadDisconnectEx() { |
| 518 // Load the DisconnectEx function into memory using WSAIoctl. |
| 519 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; |
| 520 DWORD bytes; |
| 521 int status = WSAIoctl(socket(), |
| 522 SIO_GET_EXTENSION_FUNCTION_POINTER, |
| 523 &guid_disconnect_ex, |
| 524 sizeof(guid_disconnect_ex), |
| 525 &DisconnectEx_, |
| 526 sizeof(DisconnectEx_), |
| 527 &bytes, |
| 528 NULL, |
| 529 NULL); |
| 530 if (status == SOCKET_ERROR) { |
| 531 Log::PrintErr("Error WSAIoctl failed: %d\n", WSAGetLastError()); |
| 532 return false; |
| 533 } |
| 534 return true; |
| 535 } |
| 536 |
| 537 |
| 530 void ClientSocket::Shutdown(int how) { | 538 void ClientSocket::Shutdown(int how) { |
| 531 int rc = shutdown(socket(), how); | 539 int rc = shutdown(socket(), how); |
| 532 if (rc == SOCKET_ERROR) { | |
| 533 Log::PrintErr("shutdown failed: %d %d\n", socket(), WSAGetLastError()); | |
| 534 } | |
| 535 if (how == SD_RECEIVE) MarkClosedRead(); | 540 if (how == SD_RECEIVE) MarkClosedRead(); |
| 536 if (how == SD_SEND) MarkClosedWrite(); | 541 if (how == SD_SEND) MarkClosedWrite(); |
| 537 if (how == SD_BOTH) { | 542 if (how == SD_BOTH) { |
| 538 MarkClosedRead(); | 543 MarkClosedRead(); |
| 539 MarkClosedWrite(); | 544 MarkClosedWrite(); |
| 540 } | 545 } |
| 541 } | 546 } |
| 542 | 547 |
| 543 | 548 |
| 549 void ClientSocket::DoClose() { |
| 550 // Always do a suhtdown before initiating a disconnect. |
| 551 shutdown(socket(), SD_BOTH); |
| 552 IssueDisconnect(); |
| 553 } |
| 554 |
| 555 |
| 544 bool ClientSocket::IssueRead() { | 556 bool ClientSocket::IssueRead() { |
| 545 ScopedLock lock(this); | 557 ScopedLock lock(this); |
| 546 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); | 558 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); |
| 547 ASSERT(pending_read_ == NULL); | 559 ASSERT(pending_read_ == NULL); |
| 548 | 560 |
| 549 IOBuffer* buffer = IOBuffer::AllocateReadBuffer(1024); | 561 IOBuffer* buffer = IOBuffer::AllocateReadBuffer(1024); |
| 550 | 562 |
| 551 DWORD flags; | 563 DWORD flags; |
| 552 flags = 0; | 564 flags = 0; |
| 553 int rc = WSARecv(socket(), | 565 int rc = WSARecv(socket(), |
| (...skipping 30 matching lines...) Expand all Loading... |
| 584 if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) { | 596 if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) { |
| 585 return true; | 597 return true; |
| 586 } | 598 } |
| 587 IOBuffer::DisposeBuffer(pending_write_); | 599 IOBuffer::DisposeBuffer(pending_write_); |
| 588 pending_write_ = NULL; | 600 pending_write_ = NULL; |
| 589 HandleIssueError(); | 601 HandleIssueError(); |
| 590 return false; | 602 return false; |
| 591 } | 603 } |
| 592 | 604 |
| 593 | 605 |
| 606 void ClientSocket::IssueDisconnect() { |
| 607 IOBuffer* buffer = IOBuffer::AllocateDisconnectBuffer(); |
| 608 BOOL ok = DisconnectEx_( |
| 609 socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0); |
| 610 if (!ok && WSAGetLastError() != WSA_IO_PENDING) { |
| 611 DisconnectComplete(buffer); |
| 612 } |
| 613 } |
| 614 |
| 615 |
| 616 void ClientSocket::DisconnectComplete(IOBuffer* buffer) { |
| 617 IOBuffer::DisposeBuffer(buffer); |
| 618 closesocket(socket()); |
| 619 if (data_ready_ != NULL) { |
| 620 IOBuffer::DisposeBuffer(data_ready_); |
| 621 } |
| 622 // When disconnect is complete get rid of the object. |
| 623 delete this; |
| 624 } |
| 625 |
| 626 |
| 594 void ClientSocket::EnsureInitialized( | 627 void ClientSocket::EnsureInitialized( |
| 595 EventHandlerImplementation* event_handler) { | 628 EventHandlerImplementation* event_handler) { |
| 596 ScopedLock lock(this); | 629 ScopedLock lock(this); |
| 597 if (completion_port_ == INVALID_HANDLE_VALUE) { | 630 if (completion_port_ == INVALID_HANDLE_VALUE) { |
| 598 ASSERT(event_handler_ == NULL); | 631 ASSERT(event_handler_ == NULL); |
| 599 event_handler_ = event_handler; | 632 event_handler_ = event_handler; |
| 600 CreateCompletionPort(event_handler_->completion_port()); | 633 CreateCompletionPort(event_handler_->completion_port()); |
| 601 } | 634 } |
| 602 } | 635 } |
| 603 | 636 |
| 604 | 637 |
| 605 void ClientSocket::AfterClose() { | |
| 606 ScopedLock lock(this); | |
| 607 if (data_ready_ != NULL) { | |
| 608 IOBuffer::DisposeBuffer(data_ready_); | |
| 609 data_ready_ = NULL; | |
| 610 } | |
| 611 } | |
| 612 | |
| 613 | |
| 614 bool ClientSocket::IsClosed() { | 638 bool ClientSocket::IsClosed() { |
| 615 return IsClosing() && !HasPendingRead() && !HasPendingWrite(); | 639 return false; |
| 616 } | 640 } |
| 617 | 641 |
| 618 | 642 |
| 619 void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) { | 643 void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) { |
| 620 if (msg->id == kTimeoutId) { | 644 if (msg->id == kTimeoutId) { |
| 621 // Change of timeout request. Just set the new timeout and port as the | 645 // Change of timeout request. Just set the new timeout and port as the |
| 622 // completion thread will use the new timeout value for its next wait. | 646 // completion thread will use the new timeout value for its next wait. |
| 623 timeout_ = msg->data; | 647 timeout_ = msg->data; |
| 624 timeout_port_ = msg->dart_port; | 648 timeout_port_ = msg->dart_port; |
| 625 } else if (msg->id == kShutdownId) { | 649 } else if (msg->id == kShutdownId) { |
| 626 shutdown_ = true; | 650 shutdown_ = true; |
| 627 } else { | 651 } else { |
| 628 bool delete_handle = false; | 652 bool delete_handle = false; |
| 629 Handle* handle = reinterpret_cast<Handle*>(msg->id); | 653 Handle* handle = reinterpret_cast<Handle*>(msg->id); |
| 630 ASSERT(handle != NULL); | 654 ASSERT(handle != NULL); |
| 631 if (handle->is_listen_socket()) { | 655 if (handle->is_listen_socket()) { |
| 632 ListenSocket* listen_socket = | 656 ListenSocket* listen_socket = |
| 633 reinterpret_cast<ListenSocket*>(handle); | 657 reinterpret_cast<ListenSocket*>(handle); |
| 634 listen_socket->EnsureInitialized(this); | 658 listen_socket->EnsureInitialized(this); |
| 635 listen_socket->SetPortAndMask(msg->dart_port, msg->data); | 659 listen_socket->SetPortAndMask(msg->dart_port, msg->data); |
| 636 | 660 |
| 637 Handle::ScopedLock lock(listen_socket); | 661 Handle::ScopedLock lock(listen_socket); |
| 638 | 662 |
| 639 // If incomming connections are requested make sure that pending accepts | 663 // If incomming connections are requested make sure to post already |
| 640 // are issued. | 664 // accepted connections. |
| 641 if ((msg->data & (1 << kInEvent)) != 0) { | 665 if ((msg->data & (1 << kInEvent)) != 0) { |
| 666 if (listen_socket->CanAccept()) { |
| 667 int event_mask = (1 << kInEvent); |
| 668 handle->set_mask(handle->mask() & ~event_mask); |
| 669 DartUtils::PostInt32(handle->port(), event_mask); |
| 670 } |
| 671 // Always keep 5 outstanding accepts going, to enhance performance. |
| 642 while (listen_socket->pending_accept_count() < 5) { | 672 while (listen_socket->pending_accept_count() < 5) { |
| 643 listen_socket->IssueAccept(); | 673 listen_socket->IssueAccept(); |
| 644 } | 674 } |
| 645 } | 675 } |
| 646 | 676 |
| 647 if ((msg->data & (1 << kCloseCommand)) != 0) { | 677 if ((msg->data & (1 << kCloseCommand)) != 0) { |
| 648 listen_socket->close(); | 678 listen_socket->Close(); |
| 649 if (listen_socket->IsClosed()) { | 679 if (listen_socket->IsClosed()) { |
| 650 delete_handle = true; | 680 delete_handle = true; |
| 651 } | 681 } |
| 652 } | 682 } |
| 653 } else { | 683 } else { |
| 654 handle->SetPortAndMask(msg->dart_port, msg->data); | |
| 655 handle->EnsureInitialized(this); | 684 handle->EnsureInitialized(this); |
| 656 | 685 |
| 657 Handle::ScopedLock lock(handle); | 686 Handle::ScopedLock lock(handle); |
| 658 | 687 |
| 659 if (!handle->IsError()) { | 688 if (!handle->IsError()) { |
| 660 // If in events (data available events) have been requested, and data | 689 if ((msg->data & ((1 << kInEvent) | (1 << kOutEvent))) != 0) { |
| 661 // is available, post an in event immediately. Otherwise make sure | 690 // Only set mask if we turned on kInEvent or kOutEvent. |
| 662 // that a pending read is issued, unless the socket is already closed | 691 handle->SetPortAndMask(msg->dart_port, msg->data); |
| 663 // for read. | 692 |
| 664 if ((msg->data & (1 << kInEvent)) != 0) { | 693 // If in events (data available events) have been requested, and data |
| 665 if (handle->Available() > 0) { | 694 // is available, post an in event immediately. Otherwise make sure |
| 666 int event_mask = (1 << kInEvent); | 695 // that a pending read is issued, unless the socket is already closed |
| 667 handle->set_mask(handle->mask() & ~event_mask); | 696 // for read. |
| 668 DartUtils::PostInt32(handle->port(), event_mask); | 697 if ((msg->data & (1 << kInEvent)) != 0) { |
| 669 } else if (!handle->HasPendingRead() && | 698 if (handle->Available() > 0) { |
| 670 !handle->IsClosedRead()) { | 699 int event_mask = (1 << kInEvent); |
| 671 handle->IssueRead(); | 700 handle->set_mask(handle->mask() & ~event_mask); |
| 701 DartUtils::PostInt32(handle->port(), event_mask); |
| 702 } else if (handle->IsClosedRead()) { |
| 703 int event_mask = (1 << kCloseEvent); |
| 704 DartUtils::PostInt32(handle->port(), event_mask); |
| 705 } else if (!handle->HasPendingRead()) { |
| 706 handle->IssueRead(); |
| 707 } |
| 708 } |
| 709 |
| 710 // If out events (can write events) have been requested, and there |
| 711 // are no pending writes, post an out event immediately. |
| 712 if ((msg->data & (1 << kOutEvent)) != 0) { |
| 713 if (!handle->HasPendingWrite()) { |
| 714 int event_mask = (1 << kOutEvent); |
| 715 handle->set_mask(handle->mask() & ~event_mask); |
| 716 DartUtils::PostInt32(handle->port(), event_mask); |
| 717 } |
| 672 } | 718 } |
| 673 } | 719 } |
| 674 | 720 |
| 675 // If out events (can write events) have been requested, and there | |
| 676 // are no pending writes, post an out event immediately. | |
| 677 if ((msg->data & (1 << kOutEvent)) != 0) { | |
| 678 if (!handle->HasPendingWrite()) { | |
| 679 int event_mask = (1 << kOutEvent); | |
| 680 handle->set_mask(handle->mask() & ~event_mask); | |
| 681 DartUtils::PostInt32(handle->port(), event_mask); | |
| 682 } | |
| 683 } | |
| 684 | |
| 685 if (handle->is_client_socket()) { | 721 if (handle->is_client_socket()) { |
| 686 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(handle); | 722 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(handle); |
| 687 if ((msg->data & (1 << kShutdownReadCommand)) != 0) { | 723 if ((msg->data & (1 << kShutdownReadCommand)) != 0) { |
| 688 client_socket->Shutdown(SD_RECEIVE); | 724 client_socket->Shutdown(SD_RECEIVE); |
| 689 } | 725 } |
| 690 | 726 |
| 691 if ((msg->data & (1 << kShutdownWriteCommand)) != 0) { | 727 if ((msg->data & (1 << kShutdownWriteCommand)) != 0) { |
| 692 client_socket->Shutdown(SD_SEND); | 728 client_socket->Shutdown(SD_SEND); |
| 693 } | 729 } |
| 694 } | 730 } |
| 695 } | 731 } |
| 696 | 732 |
| 697 if ((msg->data & (1 << kCloseCommand)) != 0) { | 733 if ((msg->data & (1 << kCloseCommand)) != 0) { |
| 698 handle->close(); | 734 handle->Close(); |
| 699 if (handle->IsClosed()) { | 735 if (handle->IsClosed()) { |
| 700 delete_handle = true; | 736 delete_handle = true; |
| 701 } | 737 } |
| 702 } | 738 } |
| 703 } | 739 } |
| 704 if (delete_handle) { | 740 if (delete_handle) { |
| 705 delete handle; | 741 delete handle; |
| 706 } | 742 } |
| 707 } | 743 } |
| 708 } | 744 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 } else { | 823 } else { |
| 788 HandleError(handle); | 824 HandleError(handle); |
| 789 } | 825 } |
| 790 | 826 |
| 791 if (handle->IsClosed()) { | 827 if (handle->IsClosed()) { |
| 792 delete handle; | 828 delete handle; |
| 793 } | 829 } |
| 794 } | 830 } |
| 795 | 831 |
| 796 | 832 |
| 833 void EventHandlerImplementation::HandleDisconnect( |
| 834 ClientSocket* client_socket, |
| 835 int bytes, |
| 836 IOBuffer* buffer) { |
| 837 client_socket->DisconnectComplete(buffer); |
| 838 } |
| 839 |
| 797 void EventHandlerImplementation::HandleTimeout() { | 840 void EventHandlerImplementation::HandleTimeout() { |
| 798 // TODO(sgjesse) check if there actually is a timeout. | 841 // TODO(sgjesse) check if there actually is a timeout. |
| 799 DartUtils::PostNull(timeout_port_); | 842 DartUtils::PostNull(timeout_port_); |
| 800 timeout_ = kInfinityTimeout; | 843 timeout_ = kInfinityTimeout; |
| 801 timeout_port_ = 0; | 844 timeout_port_ = 0; |
| 802 } | 845 } |
| 803 | 846 |
| 804 | 847 |
| 805 void EventHandlerImplementation::HandleIOCompletion(DWORD bytes, | 848 void EventHandlerImplementation::HandleIOCompletion(DWORD bytes, |
| 806 ULONG_PTR key, | 849 ULONG_PTR key, |
| 807 OVERLAPPED* overlapped) { | 850 OVERLAPPED* overlapped) { |
| 808 IOBuffer* buffer = IOBuffer::GetFromOverlapped(overlapped); | 851 IOBuffer* buffer = IOBuffer::GetFromOverlapped(overlapped); |
| 809 switch (buffer->operation()) { | 852 switch (buffer->operation()) { |
| 810 case IOBuffer::kAccept: { | 853 case IOBuffer::kAccept: { |
| 811 ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(key); | 854 ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(key); |
| 812 HandleAccept(listen_socket, buffer); | 855 HandleAccept(listen_socket, buffer); |
| 813 break; | 856 break; |
| 814 } | 857 } |
| 815 case IOBuffer::kRead: { | 858 case IOBuffer::kRead: { |
| 816 Handle* handle = reinterpret_cast<Handle*>(key); | 859 Handle* handle = reinterpret_cast<Handle*>(key); |
| 817 HandleRead(handle, bytes, buffer); | 860 HandleRead(handle, bytes, buffer); |
| 818 break; | 861 break; |
| 819 } | 862 } |
| 820 case IOBuffer::kWrite: { | 863 case IOBuffer::kWrite: { |
| 821 Handle* handle = reinterpret_cast<Handle*>(key); | 864 Handle* handle = reinterpret_cast<Handle*>(key); |
| 822 HandleWrite(handle, bytes, buffer); | 865 HandleWrite(handle, bytes, buffer); |
| 823 break; | 866 break; |
| 824 } | 867 } |
| 868 case IOBuffer::kDisconnect: { |
| 869 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(key); |
| 870 HandleDisconnect(client_socket, bytes, buffer); |
| 871 break; |
| 872 } |
| 825 default: | 873 default: |
| 826 UNREACHABLE(); | 874 UNREACHABLE(); |
| 827 } | 875 } |
| 828 } | 876 } |
| 829 | 877 |
| 830 | 878 |
| 831 EventHandlerImplementation::EventHandlerImplementation() { | 879 EventHandlerImplementation::EventHandlerImplementation() { |
| 832 intptr_t result; | 880 intptr_t result; |
| 833 completion_port_ = | 881 completion_port_ = |
| 834 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); | 882 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 FATAL("Failed to initialized Windows sockets"); | 977 FATAL("Failed to initialized Windows sockets"); |
| 930 } | 978 } |
| 931 } | 979 } |
| 932 | 980 |
| 933 | 981 |
| 934 void EventHandlerImplementation::Shutdown() { | 982 void EventHandlerImplementation::Shutdown() { |
| 935 SendData(kShutdownId, 0, 0); | 983 SendData(kShutdownId, 0, 0); |
| 936 } | 984 } |
| 937 | 985 |
| 938 #endif // defined(TARGET_OS_WINDOWS) | 986 #endif // defined(TARGET_OS_WINDOWS) |
| OLD | NEW |