Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: runtime/bin/eventhandler_win.cc

Issue 264613002: Use ConnectEx on Windows, to do async connect of sockets. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/eventhandler_win.h ('k') | runtime/bin/socket_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 <winsock2.h> // NOLINT 10 #include <winsock2.h> // NOLINT
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 OverlappedBuffer* OverlappedBuffer::AllocateSendToBuffer(int buffer_size) { 66 OverlappedBuffer* OverlappedBuffer::AllocateSendToBuffer(int buffer_size) {
67 return AllocateBuffer(buffer_size, kSendTo); 67 return AllocateBuffer(buffer_size, kSendTo);
68 } 68 }
69 69
70 70
71 OverlappedBuffer* OverlappedBuffer::AllocateDisconnectBuffer() { 71 OverlappedBuffer* OverlappedBuffer::AllocateDisconnectBuffer() {
72 return AllocateBuffer(0, kDisconnect); 72 return AllocateBuffer(0, kDisconnect);
73 } 73 }
74 74
75 75
76 OverlappedBuffer* OverlappedBuffer::AllocateConnectBuffer() {
77 return AllocateBuffer(0, kConnect);
78 }
79
80
76 void OverlappedBuffer::DisposeBuffer(OverlappedBuffer* buffer) { 81 void OverlappedBuffer::DisposeBuffer(OverlappedBuffer* buffer) {
77 delete buffer; 82 delete buffer;
78 } 83 }
79 84
80 85
81 OverlappedBuffer* OverlappedBuffer::GetFromOverlapped(OVERLAPPED* overlapped) { 86 OverlappedBuffer* OverlappedBuffer::GetFromOverlapped(OVERLAPPED* overlapped) {
82 OverlappedBuffer* buffer = 87 OverlappedBuffer* buffer =
83 CONTAINING_RECORD(overlapped, OverlappedBuffer, overlapped_); 88 CONTAINING_RECORD(overlapped, OverlappedBuffer, overlapped_);
84 return buffer; 89 return buffer;
85 } 90 }
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 if (!IsClosing()) { 472 if (!IsClosing()) {
468 // Update the accepted socket to support the full range of API calls. 473 // Update the accepted socket to support the full range of API calls.
469 SOCKET s = socket(); 474 SOCKET s = socket();
470 int rc = setsockopt(buffer->client(), 475 int rc = setsockopt(buffer->client(),
471 SOL_SOCKET, 476 SOL_SOCKET,
472 SO_UPDATE_ACCEPT_CONTEXT, 477 SO_UPDATE_ACCEPT_CONTEXT,
473 reinterpret_cast<char*>(&s), sizeof(s)); 478 reinterpret_cast<char*>(&s), sizeof(s));
474 if (rc == NO_ERROR) { 479 if (rc == NO_ERROR) {
475 // Insert the accepted socket into the list. 480 // Insert the accepted socket into the list.
476 ClientSocket* client_socket = new ClientSocket(buffer->client(), 0); 481 ClientSocket* client_socket = new ClientSocket(buffer->client(), 0);
482 client_socket->mark_connected();
477 client_socket->CreateCompletionPort(completion_port); 483 client_socket->CreateCompletionPort(completion_port);
478 if (accepted_head_ == NULL) { 484 if (accepted_head_ == NULL) {
479 accepted_head_ = client_socket; 485 accepted_head_ = client_socket;
480 accepted_tail_ = client_socket; 486 accepted_tail_ = client_socket;
481 } else { 487 } else {
482 ASSERT(accepted_tail_ != NULL); 488 ASSERT(accepted_tail_ != NULL);
483 accepted_tail_->set_next(client_socket); 489 accepted_tail_->set_next(client_socket);
484 accepted_tail_ = client_socket; 490 accepted_tail_ = client_socket;
485 } 491 }
486 } else { 492 } else {
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 return true; 810 return true;
805 } 811 }
806 OverlappedBuffer::DisposeBuffer(pending_write_); 812 OverlappedBuffer::DisposeBuffer(pending_write_);
807 pending_write_ = NULL; 813 pending_write_ = NULL;
808 HandleIssueError(); 814 HandleIssueError();
809 return false; 815 return false;
810 } 816 }
811 817
812 818
813 void ClientSocket::IssueDisconnect() { 819 void ClientSocket::IssueDisconnect() {
814 Dart_Port p = port();
815 OverlappedBuffer* buffer = OverlappedBuffer::AllocateDisconnectBuffer(); 820 OverlappedBuffer* buffer = OverlappedBuffer::AllocateDisconnectBuffer();
816 BOOL ok = DisconnectEx_( 821 BOOL ok = DisconnectEx_(
817 socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0); 822 socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0);
818 if (!ok && WSAGetLastError() != WSA_IO_PENDING) { 823 // DisconnectEx works like other OverlappedIO APIs, where we can get either an
824 // immediate success or delayed operation by WSA_IO_PENDING being set.
825 if (ok || WSAGetLastError() != WSA_IO_PENDING) {
819 DisconnectComplete(buffer); 826 DisconnectComplete(buffer);
820 } 827 }
828 Dart_Port p = port();
821 if (p != ILLEGAL_PORT) DartUtils::PostInt32(p, 1 << kDestroyedEvent); 829 if (p != ILLEGAL_PORT) DartUtils::PostInt32(p, 1 << kDestroyedEvent);
830 port_ = ILLEGAL_PORT;
822 } 831 }
823 832
824 833
825 void ClientSocket::DisconnectComplete(OverlappedBuffer* buffer) { 834 void ClientSocket::DisconnectComplete(OverlappedBuffer* buffer) {
826 OverlappedBuffer::DisposeBuffer(buffer); 835 OverlappedBuffer::DisposeBuffer(buffer);
827 closesocket(socket()); 836 closesocket(socket());
828 if (data_ready_ != NULL) { 837 if (data_ready_ != NULL) {
829 OverlappedBuffer::DisposeBuffer(data_ready_); 838 OverlappedBuffer::DisposeBuffer(data_ready_);
830 } 839 }
831 // When disconnect is complete get rid of the object. 840 closed_ = true;
832 delete this;
833 } 841 }
834 842
835 843
844 void ClientSocket::ConnectComplete(OverlappedBuffer* buffer) {
845 OverlappedBuffer::DisposeBuffer(buffer);
846 // Update socket to support full socket API, after ConnectEx completed.
847 setsockopt(socket(), SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
848 connected_ = true;
849 Dart_Port p = port();
850 if (p != ILLEGAL_PORT) {
851 // If the port is set, we already listen for this socket in Dart.
852 // Handle the cases here.
853 if (!IsClosedRead()) {
854 IssueRead();
855 }
856 if (!IsClosedWrite()) {
857 DartUtils::PostInt32(p, 1 << kOutEvent);
858 }
859 }
860 }
861
862
836 void ClientSocket::EnsureInitialized( 863 void ClientSocket::EnsureInitialized(
837 EventHandlerImplementation* event_handler) { 864 EventHandlerImplementation* event_handler) {
838 ScopedLock lock(this); 865 ScopedLock lock(this);
839 if (completion_port_ == INVALID_HANDLE_VALUE) { 866 if (completion_port_ == INVALID_HANDLE_VALUE) {
840 ASSERT(event_handler_ == NULL); 867 ASSERT(event_handler_ == NULL);
841 event_handler_ = event_handler; 868 event_handler_ = event_handler;
842 CreateCompletionPort(event_handler_->completion_port()); 869 CreateCompletionPort(event_handler_->completion_port());
843 } 870 }
844 } 871 }
845 872
846 873
847 bool ClientSocket::IsClosed() { 874 bool ClientSocket::IsClosed() {
848 return false; 875 return closed_;
849 } 876 }
850 877
851 878
852 bool DatagramSocket::IssueSendTo(struct sockaddr* sa, socklen_t sa_len) { 879 bool DatagramSocket::IssueSendTo(struct sockaddr* sa, socklen_t sa_len) {
853 ScopedLock lock(this); 880 ScopedLock lock(this);
854 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); 881 ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
855 ASSERT(pending_write_ != NULL); 882 ASSERT(pending_write_ != NULL);
856 ASSERT(pending_write_->operation() == OverlappedBuffer::kSendTo); 883 ASSERT(pending_write_->operation() == OverlappedBuffer::kSendTo);
857 884
858 int rc = WSASendTo(socket(), 885 int rc = WSASendTo(socket(),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 closesocket(socket()); 952 closesocket(socket());
926 MarkClosedRead(); 953 MarkClosedRead();
927 MarkClosedWrite(); 954 MarkClosedWrite();
928 } 955 }
929 956
930 957
931 static void DeleteIfClosed(Handle* handle) { 958 static void DeleteIfClosed(Handle* handle) {
932 if (handle->IsClosed()) { 959 if (handle->IsClosed()) {
933 Dart_Port port = handle->port(); 960 Dart_Port port = handle->port();
934 delete handle; 961 delete handle;
935 DartUtils::PostInt32(port, 1 << kDestroyedEvent); 962 if (port != ILLEGAL_PORT) {
963 DartUtils::PostInt32(port, 1 << kDestroyedEvent);
964 }
936 } 965 }
937 } 966 }
938 967
939 968
940 void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) { 969 void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) {
941 if (msg->id == kTimeoutId) { 970 if (msg->id == kTimeoutId) {
942 // Change of timeout request. Just set the new timeout and port as the 971 // Change of timeout request. Just set the new timeout and port as the
943 // completion thread will use the new timeout value for its next wait. 972 // completion thread will use the new timeout value for its next wait.
944 timeout_queue_.UpdateTimeout(msg->dart_port, msg->data); 973 timeout_queue_.UpdateTimeout(msg->dart_port, msg->data);
945 } else if (msg->id == kShutdownId) { 974 } else if (msg->id == kShutdownId) {
(...skipping 21 matching lines...) Expand all
967 } 996 }
968 // Always keep 5 outstanding accepts going, to enhance performance. 997 // Always keep 5 outstanding accepts going, to enhance performance.
969 while (listen_socket->pending_accept_count() < 5) { 998 while (listen_socket->pending_accept_count() < 5) {
970 bool accept_success = listen_socket->IssueAccept(); 999 bool accept_success = listen_socket->IssueAccept();
971 if (!accept_success) { 1000 if (!accept_success) {
972 HandleError(listen_socket); 1001 HandleError(listen_socket);
973 break; 1002 break;
974 } 1003 }
975 } 1004 }
976 } 1005 }
977
978 if ((msg->data & (1 << kCloseCommand)) != 0) {
979 listen_socket->Close();
980 }
981 } else { 1006 } else {
982 handle->EnsureInitialized(this); 1007 handle->EnsureInitialized(this);
983 1008
984 Handle::ScopedLock lock(handle); 1009 Handle::ScopedLock lock(handle);
985 1010
986 // Only set mask if we turned on kInEvent or kOutEvent. 1011 // Only set mask if we turned on kInEvent or kOutEvent.
987 if ((msg->data & ((1 << kInEvent) | (1 << kOutEvent))) != 0) { 1012 if ((msg->data & ((1 << kInEvent) | (1 << kOutEvent))) != 0) {
988 handle->SetPortAndMask(msg->dart_port, msg->data); 1013 handle->SetPortAndMask(msg->dart_port, msg->data);
989 } 1014 }
990 1015
991 // Issue a read. 1016 // Issue a read.
992 if ((msg->data & (1 << kInEvent)) != 0) { 1017 if ((msg->data & (1 << kInEvent)) != 0) {
993 handle->SetPortAndMask(msg->dart_port, msg->data);
994 if (handle->is_datagram_socket()) { 1018 if (handle->is_datagram_socket()) {
995 handle->IssueRecvFrom(); 1019 handle->IssueRecvFrom();
1020 } else if (handle->is_client_socket()) {
1021 if (reinterpret_cast<ClientSocket*>(handle)->is_connected()) {
1022 handle->IssueRead();
1023 }
996 } else { 1024 } else {
997 handle->IssueRead(); 1025 handle->IssueRead();
998 } 1026 }
999 } 1027 }
1000 1028
1001 // If out events (can write events) have been requested, and there 1029 // If out events (can write events) have been requested, and there
1002 // are no pending writes, meaning any writes are already complete, 1030 // are no pending writes, meaning any writes are already complete,
1003 // post an out event immediately. 1031 // post an out event immediately.
1004 if ((msg->data & (1 << kOutEvent)) != 0) { 1032 if ((msg->data & (1 << kOutEvent)) != 0) {
1005 handle->SetPortAndMask(msg->dart_port, msg->data);
1006 if (!handle->HasPendingWrite()) { 1033 if (!handle->HasPendingWrite()) {
1007 int event_mask = (1 << kOutEvent); 1034 if (handle->is_client_socket()) {
1008 DartUtils::PostInt32(handle->port(), event_mask); 1035 if (reinterpret_cast<ClientSocket*>(handle)->is_connected()) {
1036 DartUtils::PostInt32(handle->port(), 1 << kOutEvent);
1037 }
1038 } else {
1039 DartUtils::PostInt32(handle->port(), 1 << kOutEvent);
1040 }
1009 } 1041 }
1010 } 1042 }
1011 1043
1012 if (handle->is_client_socket()) { 1044 if (handle->is_client_socket()) {
1013 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(handle); 1045 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(handle);
1014 if ((msg->data & (1 << kShutdownReadCommand)) != 0) { 1046 if ((msg->data & (1 << kShutdownReadCommand)) != 0) {
1015 client_socket->Shutdown(SD_RECEIVE); 1047 client_socket->Shutdown(SD_RECEIVE);
1016 } 1048 }
1017 1049
1018 if ((msg->data & (1 << kShutdownWriteCommand)) != 0) { 1050 if ((msg->data & (1 << kShutdownWriteCommand)) != 0) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 1139
1108 1140
1109 void EventHandlerImplementation::HandleWrite(Handle* handle, 1141 void EventHandlerImplementation::HandleWrite(Handle* handle,
1110 int bytes, 1142 int bytes,
1111 OverlappedBuffer* buffer) { 1143 OverlappedBuffer* buffer) {
1112 handle->WriteComplete(buffer); 1144 handle->WriteComplete(buffer);
1113 1145
1114 if (bytes >= 0) { 1146 if (bytes >= 0) {
1115 if (!handle->IsError() && !handle->IsClosing()) { 1147 if (!handle->IsError() && !handle->IsClosing()) {
1116 int event_mask = 1 << kOutEvent; 1148 int event_mask = 1 << kOutEvent;
1149 ASSERT(!handle->is_client_socket() ||
1150 reinterpret_cast<ClientSocket*>(handle)->is_connected());
1117 if ((handle->mask() & event_mask) != 0) { 1151 if ((handle->mask() & event_mask) != 0) {
1118 DartUtils::PostInt32(handle->port(), event_mask); 1152 DartUtils::PostInt32(handle->port(), event_mask);
1119 } 1153 }
1120 } 1154 }
1121 } else { 1155 } else {
1122 HandleError(handle); 1156 HandleError(handle);
1123 } 1157 }
1124 1158
1125 DeleteIfClosed(handle); 1159 DeleteIfClosed(handle);
1126 } 1160 }
1127 1161
1128 1162
1129 void EventHandlerImplementation::HandleDisconnect( 1163 void EventHandlerImplementation::HandleDisconnect(
1130 ClientSocket* client_socket, 1164 ClientSocket* client_socket,
1131 int bytes, 1165 int bytes,
1132 OverlappedBuffer* buffer) { 1166 OverlappedBuffer* buffer) {
1133 client_socket->DisconnectComplete(buffer); 1167 client_socket->DisconnectComplete(buffer);
1168 DeleteIfClosed(client_socket);
1134 } 1169 }
1135 1170
1171
1172 void EventHandlerImplementation::HandleConnect(
1173 ClientSocket* client_socket,
1174 int bytes,
1175 OverlappedBuffer* buffer) {
1176 if (bytes < 0) {
1177 HandleError(client_socket);
1178 OverlappedBuffer::DisposeBuffer(buffer);
1179 } else {
1180 client_socket->ConnectComplete(buffer);
1181 }
1182 }
1183
1184
1136 void EventHandlerImplementation::HandleTimeout() { 1185 void EventHandlerImplementation::HandleTimeout() {
1137 if (!timeout_queue_.HasTimeout()) return; 1186 if (!timeout_queue_.HasTimeout()) return;
1138 DartUtils::PostNull(timeout_queue_.CurrentPort()); 1187 DartUtils::PostNull(timeout_queue_.CurrentPort());
1139 timeout_queue_.RemoveCurrent(); 1188 timeout_queue_.RemoveCurrent();
1140 } 1189 }
1141 1190
1142 1191
1143 void EventHandlerImplementation::HandleIOCompletion(DWORD bytes, 1192 void EventHandlerImplementation::HandleIOCompletion(DWORD bytes,
1144 ULONG_PTR key, 1193 ULONG_PTR key,
1145 OVERLAPPED* overlapped) { 1194 OVERLAPPED* overlapped) {
(...skipping 18 matching lines...) Expand all
1164 case OverlappedBuffer::kSendTo: { 1213 case OverlappedBuffer::kSendTo: {
1165 Handle* handle = reinterpret_cast<Handle*>(key); 1214 Handle* handle = reinterpret_cast<Handle*>(key);
1166 HandleWrite(handle, bytes, buffer); 1215 HandleWrite(handle, bytes, buffer);
1167 break; 1216 break;
1168 } 1217 }
1169 case OverlappedBuffer::kDisconnect: { 1218 case OverlappedBuffer::kDisconnect: {
1170 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(key); 1219 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(key);
1171 HandleDisconnect(client_socket, bytes, buffer); 1220 HandleDisconnect(client_socket, bytes, buffer);
1172 break; 1221 break;
1173 } 1222 }
1223 case OverlappedBuffer::kConnect: {
1224 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(key);
1225 HandleConnect(client_socket, bytes, buffer);
1226 break;
1227 }
1174 default: 1228 default:
1175 UNREACHABLE(); 1229 UNREACHABLE();
1176 } 1230 }
1177 } 1231 }
1178 1232
1179 1233
1180 EventHandlerImplementation::EventHandlerImplementation() { 1234 EventHandlerImplementation::EventHandlerImplementation() {
1181 intptr_t result; 1235 intptr_t result;
1182 completion_port_ = 1236 completion_port_ =
1183 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); 1237 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 1343
1290 1344
1291 void EventHandlerImplementation::Shutdown() { 1345 void EventHandlerImplementation::Shutdown() {
1292 SendData(kShutdownId, 0, 0); 1346 SendData(kShutdownId, 0, 0);
1293 } 1347 }
1294 1348
1295 } // namespace bin 1349 } // namespace bin
1296 } // namespace dart 1350 } // namespace dart
1297 1351
1298 #endif // defined(TARGET_OS_WINDOWS) 1352 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW
« no previous file with comments | « runtime/bin/eventhandler_win.h ('k') | runtime/bin/socket_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698