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 |