diff --git a/base/BUILD.gn b/base/BUILD.gn index 7c6d297973..7c9180ba3f 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -1613,7 +1613,12 @@ jumbo_component("base") { "memory/shared_memory_helper.h", "strings/string16.cc", ] - + if (enable_castanets) { + sources += [ + "memory/shared_memory_helper.cc", + "memory/shared_memory_helper.h", + ] + } deps += [ "//base/trace_event/etw_manifest:chrome_events_win", "//base/win:base_win_buildflags", diff --git a/base/memory/castanets_memory_mapping.cc b/base/memory/castanets_memory_mapping.cc index b49341df03..567f865d27 100644 --- a/base/memory/castanets_memory_mapping.cc +++ b/base/memory/castanets_memory_mapping.cc @@ -2,7 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#if defined(_WINDOWS) +#include +#include +#include +#else #include +#endif #include "base/memory/castanets_memory_mapping.h" @@ -43,8 +49,14 @@ void* CastanetsMemoryMapping::GetMemory() { void* CastanetsMemoryMapping::MapForSync(int fd) { CHECK(fd != -1); +#if defined(OS_WIN) + void* memory = + MapViewOfFile(HANDLE(fd), FILE_MAP_READ | FILE_MAP_WRITE, + static_cast(0) >> 32, static_cast (0), mapped_size_); +#else void* memory = mmap(NULL, mapped_size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); +#endif CHECK(memory); AddMapping(memory); return memory; @@ -53,7 +65,11 @@ void* CastanetsMemoryMapping::MapForSync(int fd) { void CastanetsMemoryMapping::UnmapForSync(void* memory) { CHECK(memory); RemoveMapping(memory); +#if defined(OS_WIN) + UnmapViewOfFile(memory); +#else munmap(memory, mapped_size_); +#endif } } // namespace base diff --git a/base/memory/shared_memory_helper.cc b/base/memory/shared_memory_helper.cc old mode 100755 new mode 100644 index 610b5082c0..40ae4fe222 --- a/base/memory/shared_memory_helper.cc +++ b/base/memory/shared_memory_helper.cc @@ -19,10 +19,20 @@ #include #include "third_party/ashmem/ashmem.h" #endif -#endif // defined(CASTANETS) +#if defined(OS_WIN) +#include +#include +#include +#include "base/allocator/partition_allocator/page_allocator.h" +#include "base/rand_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/unguessable_token.h" +#endif +#endif // defined(CASTANETS) namespace base { - +#if !defined(OS_WIN) struct ScopedPathUnlinkerTraits { static const FilePath* InvalidValue() { return nullptr; } @@ -35,8 +45,97 @@ struct ScopedPathUnlinkerTraits { // Unlinks the FilePath when the object is destroyed. using ScopedPathUnlinker = ScopedGeneric; +#endif #if !defined(OS_ANDROID) +#if defined(OS_WIN) + +HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa, + size_t rounded_size, + LPCWSTR name) { + HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0, + static_cast(rounded_size), name); + if (!h) { + // LogError(CREATE_FILE_MAPPING_FAILURE, GetLastError()); + return nullptr; + } + + HANDLE dup_handle; + BOOL success = ::DuplicateHandle( + GetCurrentProcess(), h, GetCurrentProcess(), &dup_handle, + FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, FALSE, 0); + BOOL rv = ::CloseHandle(h); + DCHECK(rv); + + if (!success) { + LOG(ERROR)<<" Failure "; + return nullptr; + } + return dup_handle; +} + +bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, + win::ScopedHandle* handle) { + // TODO(crbug.com/210609): NaCl forces us to round up 64k here, wasting 32k + // per mapping on average. + static const size_t kSectionMask = 65536 - 1; + DCHECK(!options.executable); + if (options.size == 0) { + LOG(ERROR) << " Failure "; + return false; + } + + // Check maximum accounting for overflow. + if (options.size > + static_cast(std::numeric_limits::max()) - kSectionMask) { + LOG(ERROR) << " Failure "; + return false; + } + + size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; + string16 name_ = + options.name_deprecated ? ASCIIToUTF16(*options.name_deprecated) : L""; + SECURITY_ATTRIBUTES sa = {sizeof(sa), nullptr, FALSE}; + SECURITY_DESCRIPTOR sd; + ACL dacl; + + if (name_.empty()) { + // Add an empty DACL to enforce anonymous read-only sections. + sa.lpSecurityDescriptor = &sd; + if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) { + LOG(ERROR) << " Failure "; + return false; + } + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { + LOG(ERROR) << " Failure "; + return false; + } + if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) { + LOG(ERROR) << " Failure "; + return false; + } + + // Windows ignores DACLs on certain unnamed objects (like shared sections). + // So, we generate a random name when we need to enforce read-only. + uint64_t rand_values[4]; + RandBytes(&rand_values, sizeof(rand_values)); + name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", + rand_values[0], rand_values[1], rand_values[2], + rand_values[3]); + } + DCHECK(!name_.empty()); + HANDLE h = + CreateFileMappingWithReducedPermissions(&sa, rounded_size, name_.c_str()); + if (h == nullptr) { + // The error is logged within CreateFileMappingWithReducedPermissions(). + LOG(ERROR) << " Failure "; + return false; + } + handle->Set(h); + + return true; +} +#else bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, ScopedFD* fd, ScopedFD* readonly_fd, @@ -160,7 +259,7 @@ bool PrepareMapFile(ScopedFD fd, return true; } - +#endif #elif defined(OS_ANDROID) && defined(CASTANETS) bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, ScopedFD* fd, @@ -199,13 +298,30 @@ subtle::PlatformSharedMemoryRegion CreateAnonymousSharedMemoryIfNeeded( if (region.IsValid()) return region; +#if defined(OS_WIN) + win::ScopedHandle handle; + if (!CreateAnonymousSharedMemory(option, &handle)) + return subtle::PlatformSharedMemoryRegion(); + + subtle::PlatformSharedMemoryRegion::Mode mode = + subtle::PlatformSharedMemoryRegion::Mode::kUnsafe; + if (option.share_read_only) { + mode = subtle::PlatformSharedMemoryRegion::Mode::kReadOnly; + } + + region = subtle::PlatformSharedMemoryRegion::Take(std::move(handle), mode, + option.size, guid); + + SharedMemoryTracker::GetInstance()->AddHolder(region.Duplicate()); + return region; +#else + ScopedFD new_fd; ScopedFD readonly_fd; FilePath path; VLOG(1) << "Create anonymous shared memory for Castanets" << guid; if (!CreateAnonymousSharedMemory(option, &new_fd, &readonly_fd, &path)) return subtle::PlatformSharedMemoryRegion(); - #if !defined(OS_ANDROID) struct stat stat; CHECK(!fstat(new_fd.get(), &stat)); @@ -223,12 +339,13 @@ subtle::PlatformSharedMemoryRegion CreateAnonymousSharedMemoryIfNeeded( } region = subtle::PlatformSharedMemoryRegion::Take( - subtle::ScopedFDPair(std::move(new_fd), std::move(readonly_fd)), - mode, option.size, guid); + subtle::ScopedFDPair(std::move(new_fd), std::move(readonly_fd)), mode, + option.size, guid); SharedMemoryTracker::GetInstance()->AddHolder(region.Duplicate()); return region; +#endif } -#endif // defined(CASTANETS) +#endif // defined(CASTANETS) } // namespace base diff --git a/base/memory/shared_memory_helper.h b/base/memory/shared_memory_helper.h index 18429d6f4f..4adb801004 100644 --- a/base/memory/shared_memory_helper.h +++ b/base/memory/shared_memory_helper.h @@ -10,13 +10,17 @@ #if defined(CASTANETS) #include "base/memory/platform_shared_memory_region.h" -#endif // defined(CASTANETS) +#endif // defined(CASTANETS) #include namespace base { #if !defined(OS_ANDROID) +#if defined(OS_WIN) +bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, + win::ScopedHandle* handle); +#else // Makes a temporary file, fdopens it, and then unlinks it. |fd| is populated // with the opened fd. |readonly_fd| is populated with the opened fd if // options.share_read_only is true. |path| is populated with the location of @@ -33,6 +37,7 @@ bool PrepareMapFile(ScopedFD fd, ScopedFD readonly_fd, int* mapped_file, int* readonly_mapped_file); +#endif #elif defined(OS_ANDROID) && defined(CASTANETS) bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, ScopedFD* fd, @@ -45,7 +50,7 @@ bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, subtle::PlatformSharedMemoryRegion BASE_EXPORT CreateAnonymousSharedMemoryIfNeeded(const UnguessableToken& guid, const SharedMemoryCreateOptions& option); -#endif // defined(CASTANETS) +#endif // defined(CASTANETS) } // namespace base diff --git a/base/process/process_handle.h b/base/process/process_handle.h index 7d8cafd0af..08782b3ffb 100644 --- a/base/process/process_handle.h +++ b/base/process/process_handle.h @@ -31,6 +31,8 @@ typedef DWORD ProcessId; typedef HANDLE UserTokenHandle; const ProcessHandle kNullProcessHandle = NULL; const ProcessId kNullProcessId = 0; +const ProcessHandle kCastanetsProcessHandle = NULL; +const ProcessId kCastanetsProcessId = -1; #elif defined(OS_FUCHSIA) typedef zx_handle_t ProcessHandle; typedef zx_koid_t ProcessId; diff --git a/base/win/scoped_handle_verifier.cc b/base/win/scoped_handle_verifier.cc index 191a2401a2..433d9b2d74 100644 --- a/base/win/scoped_handle_verifier.cc +++ b/base/win/scoped_handle_verifier.cc @@ -70,7 +70,9 @@ ScopedHandleVerifier* ScopedHandleVerifier::Get() { bool CloseHandleWrapper(HANDLE handle) { if (!::CloseHandle(handle)) +#if !defined(CASTANETS) CHECK(false); // CloseHandle failed. +#endif return true; } diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 959a592317..c4a07ae6dd 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -41,7 +41,7 @@ declare_args() { # warnings with known toolchains. Allow overriding this e.g. for Chromium # builds on Linux that could use a different version of the compiler. # With GCC, warnings in no-Chromium code are always not treated as errors. - treat_warnings_as_errors = true + treat_warnings_as_errors = !is_win # Normally, Android builds are lightly optimized, even for debug builds, to # keep binary size down. Setting this flag to true disables such optimization diff --git a/cc/paint/paint_typeface.cc b/cc/paint/paint_typeface.cc index d6ee8c0bb0..03d25c52d2 100644 --- a/cc/paint/paint_typeface.cc +++ b/cc/paint/paint_typeface.cc @@ -6,6 +6,9 @@ #include "build/build_config.h" #include "third_party/skia/include/core/SkFontMgr.h" #include "third_party/skia/include/ports/SkFontConfigInterface.h" +#if defined(OS_WIN) && defined(CASTANETS) +#include "third_party/skia/include/ports/SkTypeface_win.h" +#endif namespace cc { @@ -141,7 +144,11 @@ void PaintTypeface::CreateSkTypeface() { // This is a fallthrough in all cases in FontCache::CreateTypeface, so // this is done unconditionally. Since we create the typeface upon // PaintTypeface creation, this should be safe in all cases. +#if defined(OS_WIN) && defined(CASTANETS) + auto fm(SkFontMgr_New_DirectWrite()); +#else auto fm(SkFontMgr::RefDefault()); +#endif sk_typeface_ = fm->legacyMakeTypeface(family_name_.c_str(), font_style_); break; } diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc index dca4d2af31..91aca49ae4 100644 --- a/chrome/renderer/chrome_render_frame_observer.cc +++ b/chrome/renderer/chrome_render_frame_observer.cc @@ -500,7 +500,7 @@ void ChromeRenderFrameObserver::UpdateBrowserControlsState( content::BrowserControlsState constraints, content::BrowserControlsState current, bool animate) { -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_WIN) return; #else render_frame()->GetRenderView()->UpdateBrowserControlsState(constraints, diff --git a/components/services/font/public/cpp/font_service_thread.cc b/components/services/font/public/cpp/font_service_thread.cc index 69070a0858..16c58928dc 100644 --- a/components/services/font/public/cpp/font_service_thread.cc +++ b/components/services/font/public/cpp/font_service_thread.cc @@ -11,8 +11,10 @@ #include #include #include +#if !defined(OS_WIN) #include #endif +#endif #include "base/bind.h" #include "base/files/file.h" @@ -45,15 +47,12 @@ bool FontServiceThread::MatchFamilyName( bool out_valid = false; // This proxies to the other thread, which proxies to mojo. Only on the reply // from mojo do we return from this. -#if defined(CASTANETS) +#if defined(CASTANETS) && !defined(OS_WIN) SkFontConfigInterface* fc = SkFontConfigInterface::GetSingletonDirectInterface(); out_valid = - fc->matchFamilyName(family_name, - requested_style, - out_font_identity, - out_family_name, - out_style); + fc->matchFamilyName(family_name, requested_style, out_font_identity, + out_family_name, out_style); #else base::WaitableEvent done_event; task_runner()->PostTask( @@ -127,7 +126,7 @@ scoped_refptr FontServiceThread::OpenStream( const SkFontConfigInterface::FontIdentity& identity) { DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId()); -#if defined(CASTANETS) +#if defined(CASTANETS) && !defined(OS_WIN) int result_fd = open(identity.fString.c_str(), O_RDONLY); base::File stream_file(result_fd); #else diff --git a/content/browser/child_process_launcher_helper_win.cc b/content/browser/child_process_launcher_helper_win.cc index 4deb9438f1..e962ee0929 100644 --- a/content/browser/child_process_launcher_helper_win.cc +++ b/content/browser/child_process_launcher_helper_win.cc @@ -20,6 +20,11 @@ #include "services/service_manager/embedder/result_codes.h" #include "services/service_manager/sandbox/win/sandbox_win.h" +#if defined(CASTANETS) +#include "base/base_switches.h" +#include "content/public/common/content_switches.h" +#endif + namespace content { namespace internal { @@ -29,8 +34,29 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() { base::Optional ChildProcessLauncherHelper::CreateNamedPlatformChannelOnClientThread() { +#if defined(CASTANETS) DCHECK_CURRENTLY_ON(client_thread_id_); + if (!remote_process_) + return base::nullopt; + + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kServerAddress) || + command_line->GetSwitchValueASCII(switches::kServerAddress).empty()) { + mojo::NamedPlatformChannel::Options options; + options.port = (GetProcessType() == switches::kRendererProcess) + ? mojo::kCastanetsRendererPort + : mojo::kCastanetsUtilityPort; + + // This socket pair is not used, however it is added + // to avoid failure of validation check of codes afterwards. + if (options.port == mojo::kCastanetsUtilityPort) + return base::nullopt; + mojo_channel_.emplace(); + return mojo::NamedPlatformChannel(options); + } + return base::nullopt; +#else if (!delegate_->ShouldLaunchElevated()) return base::nullopt; @@ -38,6 +64,7 @@ ChildProcessLauncherHelper::CreateNamedPlatformChannelOnClientThread() { mojo::NamedPlatformChannel named_channel(options); named_channel.PassServerNameOnCommandLine(command_line()); return named_channel; +#endif } std::unique_ptr @@ -60,6 +87,20 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread( int* launch_result) { DCHECK(CurrentlyOnProcessLauncherTaskRunner()); *is_synchronous_launch = true; + +#if defined(CASTANETS) + if (remote_process_) { + LOG(ERROR) << " enable forking not given"; + Process castanets_process; + // Positive: normal process + // 0: kNullProcessHandle + // Negative: Castanets Process + castanets_process.process = + base::Process((HANDLE)((int)base::kCastanetsProcessHandle - child_process_id_)); + *launch_result = LAUNCH_RESULT_SUCCESS; + return castanets_process; + } +#endif if (delegate_->ShouldLaunchElevated()) { // When establishing a Mojo connection, the pipe path has already been added // to the command line. diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index f083048216..c8db987f90 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -189,7 +189,7 @@ void RenderMessageFilter::SetThreadPriorityOnFileThread( #if defined(OS_LINUX) || defined(CASTANETS) void RenderMessageFilter::SetThreadPriority(int32_t ns_tid, base::ThreadPriority priority) { -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) return; #else constexpr base::TaskTraits kTraits = { diff --git a/content/renderer/media/audio/mojo_audio_output_ipc.cc b/content/renderer/media/audio/mojo_audio_output_ipc.cc index 0f53c0b36c..b6f02afd31 100644 --- a/content/renderer/media/audio/mojo_audio_output_ipc.cc +++ b/content/renderer/media/audio/mojo_audio_output_ipc.cc @@ -239,7 +239,7 @@ void MojoAudioOutputIPC::Created( #if defined(CASTANETS) // If socket_handle is invalid. - if (socket_handle < 0) { + if ((int)socket_handle < 0) { // Request to create TCP server on browser process and get the port number. stream_->RequestTCPConnect(base::BindOnce( &MojoAudioOutputIPC::RequestTCPConnectCallback, base::Unretained(this), @@ -267,8 +267,11 @@ void MojoAudioOutputIPC::RequestTCPConnectCallback( LOG(ERROR) << __func__ << " tcp_client_handle is not valid."; return; } - +#if defined(OS_WIN) + base::PlatformFile socket_handle(tcp_client_handle.GetHandle().Get()); +#else base::PlatformFile socket_handle = tcp_client_handle.ReleaseFD(); +#endif delegate_->OnStreamCreated(std::move(shared_memory_region), socket_handle, expected_state_ == kPlaying); diff --git a/media/audio/audio_sync_reader.h b/media/audio/audio_sync_reader.h index 718b11a6fb..461863e875 100644 --- a/media/audio/audio_sync_reader.h +++ b/media/audio/audio_sync_reader.h @@ -26,6 +26,9 @@ #if defined(OS_POSIX) #include "base/file_descriptor_posix.h" #endif +#if defined(OS_WIN) +#include "base/files/file.h" +#endif namespace media { diff --git a/media/mojo/services/mojo_audio_output_stream.cc b/media/mojo/services/mojo_audio_output_stream.cc index 0670f0534a..5d5116e0d6 100644 --- a/media/mojo/services/mojo_audio_output_stream.cc +++ b/media/mojo/services/mojo_audio_output_stream.cc @@ -74,9 +74,15 @@ void MojoAudioOutputStream::RequestTCPConnect( // Ack with the port number. std::move(callback).Run(port); +#if defined(OS_WIN) + base::win::ScopedHandle accept_handle; + mojo::TCPServerAcceptConnection(server_handle.GetHandle().Get(), &accept_handle); + delegate_->OnTCPConnected(accept_handle.Take()); +#else base::ScopedFD accept_handle; mojo::TCPServerAcceptConnection(server_handle.GetFD().get(), &accept_handle); delegate_->OnTCPConnected(accept_handle.release()); +#endif } #endif diff --git a/mojo/core/BUILD.gn b/mojo/core/BUILD.gn index bcc14fcec8..8053a25934 100644 --- a/mojo/core/BUILD.gn +++ b/mojo/core/BUILD.gn @@ -137,9 +137,13 @@ template("core_impl_source_set") { } if (enable_castanets) { + if (is_posix || is_win) { + sources += [ + "broker_castanets.cc", + "broker_castanets.h", + ] + } sources += [ - "broker_castanets.cc", - "broker_castanets.h", "castanets_fence.cc", "castanets_fence.h", ] diff --git a/mojo/core/broker_castanets.cc b/mojo/core/broker_castanets.cc index f4e95f03be..30d7516daa 100644 --- a/mojo/core/broker_castanets.cc +++ b/mojo/core/broker_castanets.cc @@ -5,7 +5,6 @@ #include "mojo/core/broker_castanets.h" #include -#include #include "base/lazy_instance.h" #include "base/memory/castanets_memory_mapping.h" @@ -18,9 +17,18 @@ #include "mojo/core/castanets_fence.h" #include "mojo/core/node_channel.h" #include "mojo/core/platform_handle_utils.h" -#include "mojo/public/cpp/platform/socket_utils_posix.h" #include "mojo/public/cpp/platform/tcp_platform_handle_utils.h" +#if defined(_WINDOWS) +#include +#include +#include "base/debug/alias.h" +#include "mojo/public/cpp/platform/named_platform_channel.h" +#else +#include +#include "mojo/public/cpp/platform/socket_utils_posix.h" +#endif + namespace mojo { namespace core { @@ -62,6 +70,64 @@ FenceId GenerateRandomFenceId() { return g_id_generator.Get().GenerateRandomId(); } +#if defined(OS_WIN) +// 256 bytes should be enough for anyone! +const size_t kMaxBrokerMessageSize = 256; + +bool TakeHandlesFromBrokerMessage(Channel::Message* message, + size_t num_handles, + PlatformHandle* out_handles) { + if (message->num_handles() != num_handles) { + for (size_t i = 0; i < num_handles; ++i) + out_handles[i] = PlatformHandle((base::win::ScopedHandle((HANDLE)-765))); + return true; + } + std::vector handles = message->TakeHandles(); + DCHECK_EQ(handles.size(), num_handles); + DCHECK(out_handles); + + for (size_t i = 0; i < num_handles; ++i) + out_handles[i] = handles[i].TakeHandle(); + return true; +} + +Channel::MessagePtr WaitForBrokerMessage(HANDLE pipe_handle, + BrokerMessageType expected_type) { + char buffer[kMaxBrokerMessageSize]; + DWORD bytes_read = 0; + bytes_read = recv((SOCKET)pipe_handle, buffer, kMaxBrokerMessageSize, 0); + // BOOL result = ::ReadFile(pipe_handle, buffer, kMaxBrokerMessageSize, + //&bytes_read, nullptr); + if (bytes_read <= 0) { + // The pipe may be broken if the browser side has been closed, e.g. during + // browser shutdown. In that case the ReadFile call will fail and we + // shouldn't continue waiting. + PLOG(ERROR) << "Error reading broker pipe"; + return nullptr; + } + + Channel::MessagePtr message = + Channel::Message::Deserialize(buffer, static_cast(bytes_read)); + if (!message || message->payload_size() < sizeof(BrokerMessageHeader)) { + LOG(ERROR) << "Invalid broker message"; + base::debug::Alias(&buffer[0]); + base::debug::Alias(&bytes_read); + CHECK(false); + return nullptr; + } + + const BrokerMessageHeader* header = + reinterpret_cast(message->payload()); + if (header->type != expected_type) { + LOG(ERROR) << "Unexpected broker message type"; + base::debug::Alias(&buffer[0]); + base::debug::Alias(&bytes_read); + CHECK(false); + return nullptr; + } + return message; +} +#else Channel::MessagePtr WaitForBrokerMessage( int socket_fd, BrokerMessageType expected_type, @@ -112,7 +178,7 @@ Channel::MessagePtr WaitForBrokerMessage( return message; } - +#endif } // namespace BrokerCastanets::BrokerCastanets(ConnectionParams connection_params, @@ -161,9 +227,16 @@ void BrokerCastanets::Initialize( scoped_refptr io_task_runner) { CHECK(connection_params.endpoint().is_valid() || connection_params.server_endpoint().is_valid()); +#if defined(OS_WIN) + if (IsNetworkSocket( + connection_params.server_endpoint().platform_handle().GetHandle()) || + IsNetworkSocket( + connection_params.endpoint().platform_handle().GetHandle())) { +#else if (IsNetworkSocket( connection_params.server_endpoint().platform_handle().GetFD()) || IsNetworkSocket(connection_params.endpoint().platform_handle().GetFD())) { +#endif tcp_connection_ = true; uint16_t port = 0; bool secure_connection = false; @@ -183,11 +256,27 @@ void BrokerCastanets::Initialize( LOG(INFO) << "Connecting broker channel to " << connection_params.tcp_address() << ":" << connection_params.tcp_port(); + +#if defined(OS_WIN) if (!mojo::TCPClientConnect( - connection_params.endpoint().platform_handle().GetFD(), + connection_params.endpoint().platform_handle().GetHandle(), connection_params.tcp_address(), connection_params.tcp_port())) return; + Channel::MessagePtr message = WaitForBrokerMessage( + connection_params.endpoint().platform_handle().GetHandle().Get(), BrokerMessageType::INIT); + + // If we fail to read a message (broken pipe), just return early. The + // inviter handle will be null and callers must handle this gracefully. + if (!message) + return; + PlatformHandle endpoint_handle; + TakeHandlesFromBrokerMessage(message.get(), 1, &endpoint_handle); +#else + if (!mojo::TCPClientConnect( + connection_params.endpoint().platform_handle().GetFD(), + connection_params.tcp_address(), connection_params.tcp_port())) + return; // Wait for the first message. int fd = connection_params.endpoint().platform_handle().GetFD().get(); // Mark the channel as blocking. @@ -195,11 +284,11 @@ void BrokerCastanets::Initialize( PCHECK(flags != -1); flags = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); PCHECK(flags != -1); - LOG(INFO) << "Wait for INIT message... from fd:" << fd; // Wait for the first message. Channel::MessagePtr message = WaitForBrokerMessage( fd, BrokerMessageType::INIT, 0, sizeof(InitData), nullptr); +#endif // Received the port number of tcp server socket for node channel. const BrokerMessageHeader* header = static_cast(message->payload()); @@ -229,6 +318,23 @@ void BrokerCastanets::Initialize( // Unix Domain Socket CHECK((connection_params.endpoint().is_valid())); if (io_task_runner.get()) { +#if defined(OS_WIN) + sync_channel_ = connection_params.TakeEndpoint().TakePlatformHandle(); + + Channel::MessagePtr message = WaitForBrokerMessage( + sync_channel_.GetHandle().Get(), BrokerMessageType::INIT); + + // If we fail to read a message (broken pipe), just return early. The + // inviter handle will be null and callers must handle this gracefully. + if (!message) + return; + + PlatformHandle endpoint_handle; + if (TakeHandlesFromBrokerMessage(message.get(), 1, &endpoint_handle)) { + inviter_connection_params_ = ConnectionParams( + mojo::PlatformChannelEndpoint(std::move(endpoint_handle))); + } +#else // Use |sync_channel_| only for IPC Broker without Channel. sync_channel_ = connection_params.TakeEndpoint().TakePlatformHandle(); @@ -248,6 +354,7 @@ void BrokerCastanets::Initialize( std::move(incoming_platform_handles[0]))); LOG(INFO) << "Connection Success: Unix Domain Socket"; } +#endif } else { StartChannelOnIOThread(std::move(connection_params), 0, false); } @@ -270,17 +377,16 @@ void BrokerCastanets::SendSyncEvent( sync_size, mapping_info->mapped_size(), write_lock); } -bool BrokerCastanets::SyncSharedBuffer( - const base::UnguessableToken& guid, - size_t offset, - size_t sync_size) { +bool BrokerCastanets::SyncSharedBuffer(const base::UnguessableToken& guid, + size_t offset, + size_t sync_size) { if (!tcp_connection_) return true; scoped_refptr mapping = base::SharedMemoryTracker::GetInstance()->FindMappedMemory(guid); if (!mapping) - return MOJO_RESULT_NOT_FOUND; + return MOJO_RESULT_NOT_FOUND; SyncSharedBufferImpl(guid, static_cast(mapping->GetMemory()), offset, sync_size, mapping->mapped_size()); @@ -327,9 +433,8 @@ void BrokerCastanets::SyncSharedBufferImpl(const base::UnguessableToken& guid, CHECK_GE(mapped_size, offset + sync_size); BufferSyncData* buffer_sync = nullptr; void* extra_data = nullptr; - Channel::MessagePtr out_message = - CreateBrokerMessage(BrokerMessageType::BUFFER_SYNC, 0, sync_size, - &buffer_sync, &extra_data); + Channel::MessagePtr out_message = CreateBrokerMessage( + BrokerMessageType::BUFFER_SYNC, 0, sync_size, &buffer_sync, &extra_data); FenceId fence_id = GenerateRandomFenceId(); buffer_sync->guid_high = guid.GetHighForSerialization(); @@ -392,8 +497,7 @@ void BrokerCastanets::SyncSharedBufferImpl2d(const base::UnguessableToken& guid, << ", sync_size: " << sync_size << ", buffer_size: " << buffer_sync->buffer_bytes << ", width: " << buffer_sync->width - << ", stride: " << buffer_sync->stride - << ", fence_id: " << fence_id; + << ", stride: " << buffer_sync->stride << ", fence_id: " << fence_id; channel_->Write(std::move(out_message)); node_channel_->AddSyncFence(guid, fence_id, write_lock); @@ -413,8 +517,7 @@ void BrokerCastanets::OnBufferSync(uint64_t guid_high, base::AutoGuidLock guid_lock(guid); VLOG(2) << "Recv sync" << guid << " offset: " << offset - << ", sync_size: " << sync_bytes - << ", buffer_size: " << buffer_bytes + << ", sync_size: " << sync_bytes << ", buffer_size: " << buffer_bytes << ", fence_id: " << fence_id; scoped_refptr mapping = @@ -434,11 +537,23 @@ void BrokerCastanets::OnBufferSync(uint64_t guid_high, base::CreateAnonymousSharedMemoryIfNeeded(guid, options); CHECK(handle.IsValid()); +#if defined(OS_WIN) + void* memory = + MapViewOfFile(handle.GetPlatformHandle(), FILE_MAP_READ | FILE_MAP_WRITE, + static_cast(0) >> 32, static_cast(0), + sync_bytes + offset); +#else void* memory = mmap(NULL, sync_bytes + offset, PROT_READ | PROT_WRITE, MAP_SHARED, handle.GetPlatformHandle().fd, 0); +#endif + uint8_t* ptr = static_cast(memory); memcpy(ptr + offset, data, sync_bytes); +#if defined(OS_WIN) + UnmapViewOfFile(ptr); +#else munmap(ptr, sync_bytes + offset); +#endif fence_queue_->RemoveFence(guid, fence_id); } @@ -520,6 +635,40 @@ base::WritableSharedMemoryRegion BrokerCastanets::GetWritableSharedMemoryRegion( return r; } +#if defined(OS_WIN) + BufferRequestData* buffer_request; + Channel::MessagePtr out_message = CreateBrokerMessage( + BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request); + buffer_request->size = base::checked_cast(num_bytes); + DWORD bytes_written = 0; + + BOOL result = + ::WriteFile(sync_channel_.GetHandle().Get(), out_message->data(), + static_cast(out_message->data_num_bytes()), + &bytes_written, nullptr); + if (!result || + static_cast(bytes_written) != out_message->data_num_bytes()) { + PLOG(ERROR) << "Error sending sync broker message"; + return base::WritableSharedMemoryRegion(); + } + + PlatformHandle handle; + Channel::MessagePtr response = WaitForBrokerMessage( + sync_channel_.GetHandle().Get(), BrokerMessageType::BUFFER_RESPONSE); + if (response && TakeHandlesFromBrokerMessage(response.get(), 1, &handle)) { + BufferResponseData* data; + if (!GetBrokerMessageData(response.get(), &data)) + return base::WritableSharedMemoryRegion(); + return base::WritableSharedMemoryRegion::Deserialize( + base::subtle::PlatformSharedMemoryRegion::Take( + CreateSharedMemoryRegionHandleFromPlatformHandles(std::move(handle), + PlatformHandle()), + base::subtle::PlatformSharedMemoryRegion::Mode::kWritable, + num_bytes, + base::UnguessableToken::Deserialize(data->guid_high, + data->guid_low))); + } +#else BufferRequestData* buffer_request; Channel::MessagePtr out_message = CreateBrokerMessage( BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request); @@ -566,6 +715,7 @@ base::WritableSharedMemoryRegion BrokerCastanets::GetWritableSharedMemoryRegion( base::UnguessableToken::Deserialize(data->guid_high, data->guid_low))); } +#endif return base::WritableSharedMemoryRegion(); } @@ -573,17 +723,14 @@ bool BrokerCastanets::SendChannel(PlatformHandle handle) { CHECK(handle.is_valid()); CHECK(channel_); -#if defined(OS_WIN) - InitData* data; - Channel::MessagePtr message = - CreateBrokerMessage(BrokerMessageType::INIT, 1, 0, &data); - data->pipe_name_length = 0; -#else InitData* data; Channel::MessagePtr message = CreateBrokerMessage(BrokerMessageType::INIT, 1, 0, &data); data->port = -1; data->secure_connection = 0; + +#if defined(OS_WIN) + data->pipe_name_length = 0; #endif std::vector handles(1); handles[0] = PlatformHandleInTransit(std::move(handle)); @@ -632,7 +779,7 @@ void BrokerCastanets::SendNamedChannel(const base::StringPiece16& pipe_name) { bool BrokerCastanets::PrepareHandlesForClient( std::vector* handles) { -#if defined(OS_WIN) +#if defined(OS_WIN) && !defined(CASTANETS) bool handles_ok = true; for (auto& handle : *handles) { if (!handle.TransferToProcess(client_process_.Clone())) @@ -698,12 +845,11 @@ void BrokerCastanets::OnChannelMessage(const void* payload, } break; - case BrokerMessageType::BUFFER_SYNC: - { + case BrokerMessageType::BUFFER_SYNC: { const BufferSyncData* sync = reinterpret_cast(header + 1); - if (payload_size == sizeof(BrokerMessageHeader) + - sizeof(BufferSyncData) + sync->sync_bytes) + if (payload_size == sizeof(BrokerMessageHeader) + sizeof(BufferSyncData) + + sync->sync_bytes) OnBufferSync(sync->guid_high, sync->guid_low, sync->fence_id, sync->offset, sync->sync_bytes, sync->buffer_bytes, sync + 1); @@ -728,11 +874,10 @@ void BrokerCastanets::OnChannelMessage(const void* payload, case BrokerMessageType::BUFFER_CREATED: { const BufferResponseData* buffer = reinterpret_cast(header + 1); - if (payload_size == sizeof(BrokerMessageHeader) + - sizeof(BufferResponseData)) { - base::UnguessableToken guid = - base::UnguessableToken::Deserialize(buffer->guid_high, - buffer->guid_low); + if (payload_size == + sizeof(BrokerMessageHeader) + sizeof(BufferResponseData)) { + base::UnguessableToken guid = base::UnguessableToken::Deserialize( + buffer->guid_high, buffer->guid_low); base::SharedMemoryTracker::GetInstance()->OnBufferCreated(guid, this); } else LOG(WARNING) << "Wrong size for sync data"; diff --git a/mojo/core/broker_host.cc b/mojo/core/broker_host.cc index 1327dacac6..9c0039aab6 100644 --- a/mojo/core/broker_host.cc +++ b/mojo/core/broker_host.cc @@ -65,12 +65,12 @@ bool BrokerHost::PrepareHandlesForClient( bool BrokerHost::SendChannel(PlatformHandle handle) { CHECK(handle.is_valid()); CHECK(channel_); - #if defined(OS_WIN) InitData* data; Channel::MessagePtr message = CreateBrokerMessage(BrokerMessageType::INIT, 1, 0, &data); data->pipe_name_length = 0; + data->port = -1; #else #if defined(CASTANETS) InitData* data; diff --git a/mojo/core/channel_win.cc b/mojo/core/channel_win.cc index 30a14867be..e5e445691b 100644 --- a/mojo/core/channel_win.cc +++ b/mojo/core/channel_win.cc @@ -24,6 +24,13 @@ #include "base/win/scoped_handle.h" #include "base/win/win_util.h" +#if defined(CASTANETS) +#include "base/memory/castanets_memory_syncer.h" +#include "base/memory/shared_memory_tracker.h" +#include "mojo/core/core.h" +#include "mojo/public/cpp/platform/tcp_platform_handle_utils.h" +#endif + namespace mojo { namespace core { @@ -50,6 +57,16 @@ class ChannelWin : public Channel, CHECK(handle_.IsValid()); } +#if defined(CASTANETS) + void SetSocket(ConnectionParams connection_params) override { + handle_ = connection_params.TakeEndpoint().TakePlatformHandle().TakeHandle(); + } + + void ClearOutgoingMessages() override { + outgoing_messages_.clear(); + } +#endif + void Start() override { io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ChannelWin::StartOnIOThread, this)); @@ -60,15 +77,51 @@ class ChannelWin : public Channel, io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ChannelWin::ShutDownOnIOThread, this)); } +#if defined(CASTANETS) + void WriteNoLockImmediately(MessagePtr message) override { + bool write_error = false; + if (reject_writes_) + return; + if (outgoing_messages_.empty()) { + if (!WriteNoLock(std::move(message))) + reject_writes_ = write_error = true; + } + else { + outgoing_messages_.emplace_back(std::move(message)); + } + if (write_error) { + // Invoke OnWriteError() asynchronously on the IO thread, in case Write() + // was called by the delegate, in which case we should not re-enter it. + io_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&ChannelWin::OnWriteError, this, + Error::kDisconnected)); + } + } +#endif void Write(MessagePtr message) override { if (remote_process().is_valid()) { + // If we know the remote process handle, we transfer all outgoing handles // to the process now rewriting them in the message. std::vector handles = message->TakeHandles(); for (auto& handle : handles) { - if (handle.handle().is_valid()) + if (handle.handle().is_valid()) { +#if defined(CASTANETS) + scoped_refptr delegate = + Core::Get()->GetNodeController()->GetSyncDelegate( + remote_process().get()); + if (delegate) { + base::SharedMemoryTracker::GetInstance()->MapExternalMemory( + (int)handle.handle().GetHandle().Get(), delegate); + } + else { + base::SharedMemoryTracker::GetInstance()->MapInternalMemory( + (int)handle.handle().GetHandle().Get()); + } +#endif handle.TransferToProcess(remote_process().Clone()); + } } message->SetHandles(std::move(handles)); } @@ -108,10 +161,20 @@ class ChannelWin : public Channel, DCHECK(extra_header); if (num_handles > std::numeric_limits::max()) return false; + using HandleEntry = Channel::Message::HandleEntry; size_t handles_size = sizeof(HandleEntry) * num_handles; - if (handles_size > extra_header_size) + if (num_handles) { +#if defined(CASTANETS) + handles->clear(); + handles->resize(num_handles); + for (size_t i = 0; i < num_handles; ++i) + handles->at(i) = PlatformHandle((base::win::ScopedHandle((HANDLE)-765/*kCastanetsHandle*/))); + return true; +#else return false; +#endif + } handles->reserve(num_handles); const HandleEntry* extra_header_handles = reinterpret_cast(extra_header); @@ -136,17 +199,29 @@ class ChannelWin : public Channel, ~ChannelWin() override {} void StartOnIOThread() { - base::MessageLoopCurrent::Get()->AddDestructionObserver(this); - base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(handle_.Get(), - this); + if (!needs_connection_) { + base::MessageLoopCurrent::Get()->AddDestructionObserver(this); + base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(handle_.Get(), + this); + } if (needs_connection_) { +#if defined(CASTANETS) + base::win::ScopedHandle accept_socket; + TCPServerAcceptConnection(handle_.Get(), &accept_socket); + handle_.Close(); + handle_ = std::move(accept_socket); + needs_connection_ = false; + StartOnIOThread(); + return; +#else BOOL ok = ::ConnectNamedPipe(handle_.Get(), &connect_context_.overlapped); if (ok) { PLOG(ERROR) << "Unexpected success while waiting for pipe connection"; OnError(Error::kConnectionFailed); return; } +#endif const DWORD err = GetLastError(); switch (err) { @@ -305,6 +380,8 @@ class ChannelWin : public Channel, BOOL ok = WriteFile(handle_.Get(), message->data(), static_cast(message->data_num_bytes()), NULL, &write_context_.overlapped); + // TODO (suyambu.rm) find a way to remove this 10ms sleep. + _sleep(10); if (ok || GetLastError() == ERROR_IO_PENDING) { is_write_pending_ = true; AddRef(); diff --git a/mojo/core/data_pipe_consumer_dispatcher.cc b/mojo/core/data_pipe_consumer_dispatcher.cc index f1eb6d935d..8798fb308d 100644 --- a/mojo/core/data_pipe_consumer_dispatcher.cc +++ b/mojo/core/data_pipe_consumer_dispatcher.cc @@ -204,6 +204,7 @@ MojoResult DataPipeConsumerDispatcher::BeginReadData( #if defined(CASTANETS) node_controller_->WaitSyncSharedBuffer(ring_buffer_mapping_.guid()); #endif + base::AutoLock lock(lock_); if (!shared_ring_buffer_.IsValid() || in_transit_) return MOJO_RESULT_INVALID_ARGUMENT; @@ -341,7 +342,11 @@ bool DataPipeConsumerDispatcher::EndSerialize( platform_handles[0] = std::move(handle); #if defined(CASTANETS) base::SharedMemoryTracker::GetInstance()->AddFDInTransit( +#if defined(OS_WIN) + guid, (int)platform_handles[0].GetHandle().Get()); +#else guid, platform_handles[0].GetFD().get()); +#endif #endif return true; } @@ -399,7 +404,11 @@ DataPipeConsumerDispatcher::Deserialize(const void* data, #if defined(CASTANETS) base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle region_handle; +#if defined(OS_WIN) + if ((int)handles[0].GetHandle().Get() < 0) { +#else if (handles[0].GetFD().get() < 0) { +#endif base::SharedMemoryCreateOptions options; options.size = static_cast(state->options.capacity_num_bytes); auto new_region = base::CreateAnonymousSharedMemoryIfNeeded( @@ -409,7 +418,11 @@ DataPipeConsumerDispatcher::Deserialize(const void* data, region_handle = new_region.PassPlatformHandle(); } else { base::SharedMemoryTracker::GetInstance()->MapInternalMemory( +#if defined(OS_WIN) + (int)handles[0].GetHandle().Get()); +#else handles[0].GetFD().get()); +#endif region_handle = CreateSharedMemoryRegionHandleFromPlatformHandles( std::move(handles[0]), PlatformHandle()); } @@ -449,7 +462,6 @@ DataPipeConsumerDispatcher::Deserialize(const void* data, } dispatcher->UpdateSignalsStateNoLock(); } - return dispatcher; } @@ -555,9 +567,9 @@ void DataPipeConsumerDispatcher::OnPortStatusChanged() { base::AutoLock lock(lock_); - // We stop observing the control port as soon it's transferred, but this can - // race with events which are raised right before that happens. This is fine - // to ignore. + // We stop observing the control port as soon it's transferred, but this + // can race with events which are raised right before that happens. This + // is fine to ignore. if (transferred_) return; diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc index fad97bbd1d..e60f3b623f 100644 --- a/mojo/core/node_controller.cc +++ b/mojo/core/node_controller.cc @@ -37,6 +37,9 @@ #include "mojo/core/broker_castanets.h" #include "mojo/core/castanets_fence.h" #include "mojo/public/cpp/platform/tcp_platform_handle_utils.h" +#if defined(OS_WIN) +#include +#endif #endif #if defined(OS_WIN) @@ -402,8 +405,11 @@ scoped_refptr NodeController::GetSyncDelegate( auto it = broker_hosts_.find(process); if (it != broker_hosts_.end() && it->second->is_tcp_connection()) return it->second; - +#if defined(OS_WIN) + CHECK_GE((int)process, 0); +#else CHECK_GE(process, 0); +#endif return nullptr; } @@ -485,7 +491,7 @@ void NodeController::SendBrokerClientInvitationOnIOThread( bool channel_ok = broker_host->SendChannel( node_channel.TakeRemoteEndpoint().TakePlatformHandle()); #endif -#if defined(OS_WIN) +#if defined(OS_WIN) && !defined(CASTANETS) if (!channel_ok) { // On Windows the above operation may fail if the channel is crossing a // session boundary. In that case we fall back to a named pipe. @@ -543,7 +549,7 @@ void NodeController::RetryInvitationOnIOThread( bool channel_ok = broker_it->second->SendChannel( node_channel.TakeRemoteEndpoint().TakePlatformHandle()); -#if defined(OS_WIN) +#if defined(OS_WIN) && !defined(CASTANETS) if (!channel_ok) { // On Windows the above operation may fail if the channel is crossing a // session boundary. In that case we fall back to a named pipe. @@ -1262,7 +1268,14 @@ void NodeController::OnIntroduce(const ports::NodeName& from_node, if (!channel_handle.is_valid()) { #if defined(CASTANETS) - NamedPlatformChannel::ServerName shmem_name = ".org.castanets.Castanets.shmem.network"; +#if defined(OS_WIN) + NamedPlatformChannel::ServerName shmem_name = + L".org.castanets.Castanets.shmem.network"; +#else + NamedPlatformChannel::ServerName shmem_name = + ".org.castanets.Castanets.shmem.network"; +#endif + std::string process_type_str = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII("type"); if (process_type_str == "utility") { @@ -1283,7 +1296,11 @@ void NodeController::OnIntroduce(const ports::NodeName& from_node, if (channel_endpoint.is_valid()) break; if (nsec <= 128 / 2) +#if defined(OS_WIN) + Sleep(nsec * 1000); +#else sleep(nsec); +#endif } scoped_refptr channel = NodeChannel::Create(this, ConnectionParams(std::move(channel_endpoint)), diff --git a/mojo/core/scoped_process_handle.cc b/mojo/core/scoped_process_handle.cc index 65dfcf78aa..895f173058 100644 --- a/mojo/core/scoped_process_handle.cc +++ b/mojo/core/scoped_process_handle.cc @@ -44,7 +44,7 @@ ScopedProcessHandle ScopedProcessHandle::CloneFrom(base::ProcessHandle handle) { if (handle == base::kNullProcessHandle) return ScopedProcessHandle(); -#if defined(OS_WIN) +#if defined(OS_WIN) && !defined(CASTANETS) BOOL ok = ::DuplicateHandle(GetCurrentProcessHandle(), handle, GetCurrentProcessHandle(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); @@ -58,6 +58,9 @@ ScopedProcessHandle& ScopedProcessHandle::operator=(ScopedProcessHandle&&) = bool ScopedProcessHandle::is_valid() const { #if defined(OS_WIN) +# if defined(CASTANETS) + return true; +#endif return handle_.IsValid(); #else return handle_ != base::kNullProcessHandle; @@ -81,6 +84,9 @@ base::ProcessHandle ScopedProcessHandle::release() { } ScopedProcessHandle ScopedProcessHandle::Clone() const { +#if defined(OS_WIN) && defined(CASTANETS) + return ScopedProcessHandle(get()); +#endif if (is_valid()) return CloneFrom(get()); return ScopedProcessHandle(); diff --git a/mojo/core/shared_buffer_dispatcher.cc b/mojo/core/shared_buffer_dispatcher.cc index 7549ee6b8a..47de671650 100644 --- a/mojo/core/shared_buffer_dispatcher.cc +++ b/mojo/core/shared_buffer_dispatcher.cc @@ -24,7 +24,7 @@ #if defined(CASTANETS) #include "base/memory/shared_memory_helper.h" #include "base/memory/shared_memory_tracker.h" -#endif // defined(CASTANETS) +#endif // defined(CASTANETS) namespace mojo { namespace core { @@ -196,7 +196,11 @@ scoped_refptr SharedBufferDispatcher::Deserialize( region = base::CreateAnonymousSharedMemoryIfNeeded(guid, options); } else { base::SharedMemoryTracker::GetInstance()->MapInternalMemory( +#if defined(OS_WIN) + (int)region.GetPlatformHandle()); +#else region.GetPlatformHandle().fd); +#endif } #endif @@ -261,9 +265,9 @@ MojoResult SharedBufferDispatcher::DuplicateBufferHandle( DCHECK_EQ(region_.GetMode(), base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly); } else { - // A writable duplicate was requested. If this is already a read-only handle - // we have to reject. Otherwise we have to convert to unsafe to ensure that - // no future read-only duplication requests can succeed. + // A writable duplicate was requested. If this is already a read-only + // handle we have to reject. Otherwise we have to convert to unsafe to + // ensure that no future read-only duplication requests can succeed. if (region_.GetMode() == base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly) { return MOJO_RESULT_FAILED_PRECONDITION; @@ -396,7 +400,11 @@ bool SharedBufferDispatcher::EndSerialize(void* destination, handles[0] = std::move(platform_handle); #if defined(CASTANETS) base::SharedMemoryTracker::GetInstance()->AddFDInTransit( +#if defined(OS_WIN) + guid, (int)handles[0].GetHandle().Get()); +#else guid, handles[0].GetFD().get()); +#endif #endif return true; } diff --git a/mojo/public/cpp/platform/BUILD.gn b/mojo/public/cpp/platform/BUILD.gn index 041b88a15c..29c2649d90 100644 --- a/mojo/public/cpp/platform/BUILD.gn +++ b/mojo/public/cpp/platform/BUILD.gn @@ -40,10 +40,15 @@ component("platform") { "tcp_platform_handle_utils.h", "secure_socket_utils_posix.h", ] - sources += [ - "tcp_platform_handle_utils_posix.cc", - "secure_socket_utils_posix.cc", - ] + if (is_posix) { + sources += [ + "tcp_platform_handle_utils_posix.cc", + "secure_socket_utils_posix.cc", + ] + } + if (is_win) { + sources += [ "tcp_platform_handle_utils_win.cc" ] + } public_deps += [ "//base:base_static", "//crypto", diff --git a/mojo/public/cpp/platform/named_platform_channel_win.cc b/mojo/public/cpp/platform/named_platform_channel_win.cc index 9c329bd6d8..eb049f9330 100644 --- a/mojo/public/cpp/platform/named_platform_channel_win.cc +++ b/mojo/public/cpp/platform/named_platform_channel_win.cc @@ -46,6 +46,12 @@ base::string16 GetPipeNameFromServerName( PlatformChannelServerEndpoint NamedPlatformChannel::CreateServerEndpoint( const Options& options, ServerName* server_name) { +#if defined(CASTANETS) + if (options.port > -1) { + uint16_t port = options.port; + return PlatformChannelServerEndpoint((CreateTCPServerHandle(port, &port))); + } +#endif ServerName name = options.server_name; if (name.empty()) name = GenerateRandomServerName(); diff --git a/mojo/public/cpp/platform/tcp_platform_handle_utils.h b/mojo/public/cpp/platform/tcp_platform_handle_utils.h index 0a23bf9ce3..dcd99256c0 100644 --- a/mojo/public/cpp/platform/tcp_platform_handle_utils.h +++ b/mojo/public/cpp/platform/tcp_platform_handle_utils.h @@ -26,25 +26,40 @@ COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformHandle CreateTCPClientHandle(const uint16_t port, std::string server_address = ""); -COMPONENT_EXPORT(MOJO_CPP_PLATFORM) -bool TCPClientConnect(const base::ScopedFD& fd, - std::string server_address, - const uint16_t port); - COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformHandle CreateTCPServerHandle(uint16_t port, uint16_t* out_port = nullptr); COMPONENT_EXPORT(MOJO_CPP_PLATFORM) bool TCPServerAcceptConnection(const base::PlatformFile server_socket, +#if defined(OS_WIN) + base::win::ScopedHandle* handle); +#else base::ScopedFD* accept_socket); +#endif +#if defined(OS_WIN) +COMPONENT_EXPORT(MOJO_CPP_PLATFORM) +bool TCPClientConnect(const base::win::ScopedHandle& fd, + std::string server_address, + const uint16_t port); + +COMPONENT_EXPORT(MOJO_CPP_PLATFORM) +bool IsNetworkSocket(const base::win::ScopedHandle& fd); + +COMPONENT_EXPORT(MOJO_CPP_PLATFORM) +std::string GetPeerAddress(const base::win::ScopedHandle& fd); +#else +COMPONENT_EXPORT(MOJO_CPP_PLATFORM) +bool TCPClientConnect(const base::ScopedFD& fd, + std::string server_address, + const uint16_t port); COMPONENT_EXPORT(MOJO_CPP_PLATFORM) bool IsNetworkSocket(const base::ScopedFD& fd); COMPONENT_EXPORT(MOJO_CPP_PLATFORM) std::string GetPeerAddress(const base::ScopedFD& fd); - +#endif } // namespace mojo #endif // MOJO_EDK_EMBEDDER_TCP_PLATFORM_HANDLE_UTILS_H_ diff --git a/mojo/public/cpp/platform/tcp_platform_handle_utils_win.cc b/mojo/public/cpp/platform/tcp_platform_handle_utils_win.cc new file mode 100644 index 0000000000..3de08a47bd --- /dev/null +++ b/mojo/public/cpp/platform/tcp_platform_handle_utils_win.cc @@ -0,0 +1,209 @@ +// Copyright 2019 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "tcp_platform_handle_utils.h" + +#ifndef UNICODE +#define UNICODE +#endif + +#define WIN32_LEAN_AND_MEAN + +// Need to link with Ws2_32.lib +#pragma comment(lib, "Ws2_32.lib") + +#include +#include +#include +#include + +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/posix/eintr_wrapper.h" + +static int init = 0; +namespace mojo { + +PlatformHandle CreateTCPSocketHandle() { + // Create the inet socket. + if (init == 0) { + WSADATA wsaData; + int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != 0) { + LOG(ERROR) << "WSAStartup failed with error: "<< iResult; + return PlatformHandle(); + } + init = 1; + } + PlatformHandle handle(base::win::ScopedHandle((HANDLE)socket(AF_INET, SOCK_STREAM, 0))); + //socket_handle.needs_connection = needs_connection; + if (!handle.is_valid()) { + PLOG(ERROR) << "Failed to create AF_INET socket."; + return PlatformHandle(); + } + + // Now set it as non-blocking. + if (0 && !base::SetNonBlocking((int)handle.GetHandle().Get())) { + PLOG(ERROR) << "base::SetNonBlocking() failed " << handle.GetHandle().Get(); + return PlatformHandle(); + } + return handle; +} + +PlatformHandle CreateTCPClientHandle(const uint16_t port, + std::string server_address) { + char temp_string[20]; + sprintf(temp_string, "%zu", port); + if (server_address.empty()) { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kServerAddress)) + server_address = + command_line->GetSwitchValueASCII(switches::kServerAddress); + else + server_address = "127.0.0.1"; + } + PlatformHandle handle = CreateTCPSocketHandle(); + if (!handle.is_valid()) + return PlatformHandle(); + + LOG(INFO) << "Connecting TCP Socket to " << server_address << ":" << port; + if (!TCPClientConnect(handle.GetHandle(), server_address, port)) + return PlatformHandle(); + return handle; +} +bool TCPClientConnect(const base::win::ScopedHandle& fd, + std::string server_address, + const uint16_t port) { + struct addrinfo *result = NULL, hints; + int iResult; + // IPv4 + SOCKADDR_IN ServerAddr; + ServerAddr.sin_family = AF_INET; + // Port no. + ServerAddr.sin_port = htons(port); + // The IP address + ServerAddr.sin_addr.s_addr = inet_addr(server_address.c_str()); + + if (HANDLE_EINTR(connect((SOCKET)fd.Get(), (SOCKADDR*)&ServerAddr, + sizeof(ServerAddr))) < 0) { + PLOG(ERROR) << "connect " << fd.Get(); + return false; + } + + //static const int kOn = 1; + //setsockopt(fd.Get(), IPPROTO_TCP, TCP_NODELAY, &kOn, sizeof(kOn)); + + LOG(INFO) << "TCP Client connected to " << server_address << ":" << port + << ", fd:" << fd.Get(); + return true; +} + +PlatformHandle CreateTCPServerHandle(uint16_t port, uint16_t* out_port) { + char temp_string[20]; + sprintf(temp_string, "%zu", port); + struct addrinfo* result = NULL; + struct addrinfo hints; + int iResult; + SOCKADDR_IN local; + local.sin_family = AF_INET; + local.sin_addr.s_addr = INADDR_ANY; + /* Port MUST be in Network Byte Order */ + local.sin_port = htons(port); + + // TCP socket + PlatformHandle handle = CreateTCPSocketHandle(); + if (!handle.is_valid()) + return PlatformHandle(); + + static const int kOn = 1; +#ifdef OS_ANDROID + setsockopt(handle.get().handle, SOL_SOCKET, 15, &kOn, sizeof(kOn)); +#else + setsockopt((SOCKET)handle.GetHandle().Get(), SOL_SOCKET, SO_REUSEADDR, (char*)&kOn, + sizeof(kOn)); +#endif + // Bind the socket. + if (bind((SOCKET)handle.GetHandle().Get(), (SOCKADDR*)&local, sizeof(local)) < 0) { + PLOG(ERROR) << "bind " << handle.GetHandle().Get(); + return PlatformHandle(); + } + + // Start listening on the socket. + if (listen((SOCKET)handle.GetHandle().Get(), SOMAXCONN) < 0) { + PLOG(ERROR) << "listen" << handle.GetHandle().Get(); + return PlatformHandle(); + } + + // Get port number + if (port == 0) { + CHECK(out_port); + SOCKADDR_IN sin; + socklen_t len = sizeof(sin); + if (getsockname((SOCKET)handle.GetHandle().Get(), (struct sockaddr*)&sin, &len) < 0) { + PLOG(ERROR) << "getsockname() " << handle.GetHandle().Get(); + return PlatformHandle(); + } + port = *out_port = ntohs(sin.sin_port); + } + return handle; +} + +bool TCPServerAcceptConnection(const base::PlatformFile server_socket, +#if defined(OS_WIN) + base::win::ScopedHandle* accept_socket) { +#else + base::ScopedFD* accept_socket) { +#endif + DCHECK(server_socket); + accept_socket->Close(); + +#if defined(OS_NACL) + NOTREACHED(); + return false; +#else + HANDLE handle = (HANDLE)accept((SOCKET)server_socket, NULL, 0); + base::win::ScopedHandle accept_handle(handle); + if (!accept_handle.IsValid()) { + PLOG(ERROR) << "accept " << server_socket; + return false; + } + + if (0 && !base::SetNonBlocking((int)accept_handle.Get())) { + PLOG(ERROR) << "base::SetNonBlocking() failed " + << accept_handle.Get(); + // It's safe to keep listening on |server_handle| even if the attempt to set + // O_NONBLOCK failed on the client fd. + return true; + } + + *accept_socket = std::move(accept_handle); + + return true; +#endif // defined(OS_NACL) +} + +COMPONENT_EXPORT(MOJO_CPP_PLATFORM) +bool IsNetworkSocket(const base::win::ScopedHandle& fd) { + // TODO (suyambu.rm) check why this method returns false + return true; + struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + if (!getsockname((int)fd.Get(), (struct sockaddr*)&addr, &len)) { + return (addr.ss_family == AF_INET); + } + return false; +} + +COMPONENT_EXPORT(MOJO_CPP_PLATFORM) +std::string GetPeerAddress(const base::win::ScopedHandle& fd) { + SOCKADDR_IN addr; + socklen_t addr_size = sizeof(addr); + if (!getpeername((int)fd.Get(), (struct sockaddr*)&addr, &addr_size)) + return inet_ntoa(addr.sin_addr); + return std::string(); +} + +} // namespace mojo + diff --git a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc index 0b98f2ba35..74f0b45089 100644 --- a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc +++ b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc @@ -252,7 +252,7 @@ PaintTypeface FontCache::CreateTypeface( } #endif -#if defined(OS_LINUX) || defined(OS_WIN) +#if defined(OS_LINUX) || (defined(OS_WIN) && !defined(CASTANETS)) // On linux if the fontManager has been overridden then we should be calling // the embedder provided font Manager rather than calling // SkTypeface::CreateFromName which may redirect the call to the default font @@ -266,7 +266,6 @@ PaintTypeface FontCache::CreateTypeface( return PaintTypeface::FromSkTypeface(std::move(tf)); } #endif - // FIXME: Use m_fontManager, matchFamilyStyle instead of // legacyCreateTypeface on all platforms. return PaintTypeface::FromFamilyNameAndFontStyle( diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h index 73cf7530c3..5354376d90 100644 --- a/ui/gfx/gpu_memory_buffer.h +++ b/ui/gfx/gpu_memory_buffer.h @@ -16,7 +16,7 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/gfx_export.h" -#if defined(OS_LINUX) || defined(CASTANETS) +#if defined(OS_LINUX) || (defined(CASTANETS) && !defined(OS_WIN)) #include "ui/gfx/native_pixmap_handle.h" #elif defined(OS_MACOSX) && !defined(OS_IOS) #include "ui/gfx/mac/io_surface.h" @@ -57,7 +57,7 @@ struct GFX_EXPORT GpuMemoryBufferHandle { base::SharedMemoryHandle handle; uint32_t offset; int32_t stride; -#if defined(OS_LINUX) || defined(CASTANETS) +#if defined(OS_LINUX) || (defined(CASTANETS) && !defined(OS_WIN)) NativePixmapHandle native_pixmap_handle; uint32_t tbm_surface; uint32_t media_packet; diff --git a/ui/gfx/ipc/gfx_param_traits_macros.h b/ui/gfx/ipc/gfx_param_traits_macros.h index f6f9e25621..13df00b403 100644 --- a/ui/gfx/ipc/gfx_param_traits_macros.h +++ b/ui/gfx/ipc/gfx_param_traits_macros.h @@ -18,7 +18,7 @@ #include "ui/gfx/selection_bound.h" #include "ui/gfx/swap_result.h" -#if defined(OS_LINUX) || defined(CASTANETS) +#if defined(OS_LINUX) || (defined(CASTANETS) && !defined(OS_WIN)) #include "ui/gfx/native_pixmap_handle.h" #endif @@ -51,7 +51,7 @@ IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle) IPC_STRUCT_TRAITS_MEMBER(handle) IPC_STRUCT_TRAITS_MEMBER(offset) IPC_STRUCT_TRAITS_MEMBER(stride) -#if defined(OS_LINUX) || defined (CASTANETS) +#if defined(OS_LINUX) || (defined(CASTANETS) && !defined(OS_WIN)) IPC_STRUCT_TRAITS_MEMBER(native_pixmap_handle) IPC_STRUCT_TRAITS_MEMBER(tbm_surface) IPC_STRUCT_TRAITS_MEMBER(media_packet) @@ -68,7 +68,7 @@ IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferId) IPC_STRUCT_TRAITS_MEMBER(id) IPC_STRUCT_TRAITS_END() -#if defined(OS_LINUX) || defined(CASTANETS) +#if defined(OS_LINUX) || (defined(CASTANETS) && !defined(OS_WIN)) IPC_STRUCT_TRAITS_BEGIN(gfx::NativePixmapPlane) IPC_STRUCT_TRAITS_MEMBER(stride) IPC_STRUCT_TRAITS_MEMBER(offset) diff --git a/ui/gfx/native_pixmap_handle.h b/ui/gfx/native_pixmap_handle.h index 50a0b814f5..b3c500ba2b 100644 --- a/ui/gfx/native_pixmap_handle.h +++ b/ui/gfx/native_pixmap_handle.h @@ -13,7 +13,7 @@ #include "build/build_config.h" #include "ui/gfx/gfx_export.h" -#if defined(OS_LINUX) || defined(CASTANETS) +#if defined(OS_LINUX) || (defined(CASTANETS) && !defined(OS_WIN)) #include "base/file_descriptor_posix.h" #endif @@ -54,7 +54,7 @@ struct GFX_EXPORT NativePixmapHandle { ~NativePixmapHandle(); -#if defined(OS_LINUX) || defined(CASTANETS) +#if defined(OS_LINUX) || (defined(CASTANETS) && !defined(OS_WIN)) // File descriptors for the underlying memory objects (usually dmabufs). std::vector fds; #endif