Chromium Code Reviews| Index: runtime/bin/sync_socket_win.cc |
| diff --git a/runtime/bin/sync_socket_win.cc b/runtime/bin/sync_socket_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..20a992165235976837451e593259e45e5b88b29b |
| --- /dev/null |
| +++ b/runtime/bin/sync_socket_win.cc |
| @@ -0,0 +1,149 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
|
zra
2017/04/07 16:29:41
2017
bkonyi
2017/04/10 19:20:06
Done.
|
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +#if !defined(DART_IO_DISABLED) |
| + |
| +#include "platform/globals.h" |
| +#if defined(HOST_OS_WINDOWS) |
| + |
| +#include "bin/builtin.h" |
| +#include "bin/eventhandler.h" |
| +#include "bin/file.h" |
| +#include "bin/lockers.h" |
| +#include "bin/log.h" |
| +#include "bin/socket.h" |
| +#include "bin/socket_base_win.h" |
| +#include "bin/thread.h" |
| +#include "bin/utils.h" |
| +#include "bin/utils_win.h" |
| + |
| +namespace dart { |
| +namespace bin { |
| + |
| +SynchronousSocket::SynchronousSocket(intptr_t fd) |
| + : ReferenceCounted(), fd_(fd), port_(ILLEGAL_PORT) { |
| + ASSERT(fd_ != kClosedFd); |
| + Handle* handle = reinterpret_cast<Handle*>(fd_); |
| + ASSERT(handle != NULL); |
| +} |
| + |
| + |
| +void SynchronousSocket::SetClosedFd() { |
| + ASSERT(fd_ != kClosedFd); |
| + Handle* handle = reinterpret_cast<Handle*>(fd_); |
| + ASSERT(handle != NULL); |
| + handle->Release(); |
| + fd_ = kClosedFd; |
| +} |
| + |
| + |
| +static intptr_t Create(const RawAddr& addr) { |
| + SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, 0); |
| + if (s == INVALID_SOCKET) { |
| + return -1; |
| + } |
| + |
| + linger l; |
| + l.l_onoff = 1; |
| + l.l_linger = 10; |
| + int status = setsockopt(s, SOL_SOCKET, SO_LINGER, reinterpret_cast<char*>(&l), |
| + sizeof(l)); |
| + if (status != NO_ERROR) { |
| + FATAL("Failed setting SO_LINGER on socket"); |
| + } |
| + |
| + ClientSocket* client_socket = new ClientSocket(s, true); |
| + return reinterpret_cast<intptr_t>(client_socket); |
| +} |
| + |
| + |
| +static intptr_t Connect(intptr_t fd, |
| + const RawAddr& addr, |
| + const RawAddr& bind_addr) { |
| + ASSERT(reinterpret_cast<Handle*>(fd)->is_client_socket()); |
| + ClientSocket* handle = reinterpret_cast<ClientSocket*>(fd); |
| + SOCKET s = handle->socket(); |
| + |
| + int status = |
| + bind(s, &bind_addr.addr, SocketAddress::GetAddrLength(bind_addr)); |
| + if (status != NO_ERROR) { |
| + int rc = WSAGetLastError(); |
| + handle->mark_closed(); // Destructor asserts that socket is marked closed. |
| + handle->Release(); |
| + closesocket(s); |
| + SetLastError(rc); |
| + return -1; |
| + } |
| + |
| + LPFN_CONNECTEX connectEx = NULL; |
| + GUID guid_connect_ex = WSAID_CONNECTEX; |
| + DWORD bytes; |
| + status = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid_connect_ex, |
| + sizeof(guid_connect_ex), &connectEx, sizeof(connectEx), |
| + &bytes, NULL, NULL); |
| + DWORD rc; |
| + if (status != SOCKET_ERROR) { |
| + handle->EnsureInitialized(EventHandler::delegate()); |
| + |
| + OverlappedBuffer* overlapped = OverlappedBuffer::AllocateConnectBuffer(); |
| + |
| + status = connectEx(s, &addr.addr, SocketAddress::GetAddrLength(addr), NULL, |
| + 0, NULL, overlapped->GetCleanOverlapped()); |
| + |
| + |
| + if (status == TRUE) { |
| + handle->ConnectComplete(overlapped); |
| + return fd; |
| + } else if (WSAGetLastError() == ERROR_IO_PENDING) { |
| + return fd; |
| + } |
| + rc = WSAGetLastError(); |
| + // Cleanup in case of error. |
| + OverlappedBuffer::DisposeBuffer(overlapped); |
| + handle->Release(); |
| + } else { |
| + rc = WSAGetLastError(); |
| + } |
| + handle->Close(); |
| + handle->Release(); |
| + SetLastError(rc); |
| + return -1; |
| +} |
| + |
| + |
| +intptr_t SynchronousSocket::CreateConnect(const RawAddr& addr) { |
| + intptr_t fd = Create(addr); |
| + if (fd < 0) { |
| + return fd; |
| + } |
| + |
| + RawAddr bind_addr; |
| + memset(&bind_addr, 0, sizeof(bind_addr)); |
| + bind_addr.ss.ss_family = addr.ss.ss_family; |
| + if (addr.ss.ss_family == AF_INET) { |
| + bind_addr.in.sin_addr.s_addr = INADDR_ANY; |
| + } else { |
| + bind_addr.in6.sin6_addr = in6addr_any; |
| + } |
| + |
| + return Connect(fd, addr, bind_addr); |
| +} |
| + |
| + |
| +intptr_t SynchronousSocket::CreateBindConnect(const RawAddr& addr, |
| + const RawAddr& source_addr) { |
| + intptr_t fd = Create(addr); |
| + if (fd < 0) { |
| + return fd; |
| + } |
| + |
| + return Connect(fd, addr, source_addr); |
| +} |
| + |
| +} // namespace bin |
| +} // namespace dart |
| + |
| +#endif // defined(HOST_OS_WINDOWS) |
| + |
| +#endif // !defined(DART_IO_DISABLED) |