| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <set> |
| #include <vector> |
| |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "dart/runtime/include/dart_api.h" |
| #include "mojo/dart/embedder/builtin.h" |
| #include "mojo/dart/embedder/mojo_dart_state.h" |
| #include "mojo/public/c/system/core.h" |
| #include "mojo/public/cpp/system/core.h" |
| |
| namespace mojo { |
| namespace dart { |
| |
| #define MOJO_NATIVE_LIST(V) \ |
| V(MojoSharedBuffer_Create, 2) \ |
| V(MojoSharedBuffer_Duplicate, 2) \ |
| V(MojoSharedBuffer_Map, 5) \ |
| V(MojoSharedBuffer_Unmap, 1) \ |
| V(MojoDataPipe_Create, 3) \ |
| V(MojoDataPipe_WriteData, 4) \ |
| V(MojoDataPipe_BeginWriteData, 3) \ |
| V(MojoDataPipe_EndWriteData, 2) \ |
| V(MojoDataPipe_ReadData, 4) \ |
| V(MojoDataPipe_BeginReadData, 3) \ |
| V(MojoDataPipe_EndReadData, 2) \ |
| V(MojoMessagePipe_Create, 1) \ |
| V(MojoMessagePipe_Write, 5) \ |
| V(MojoMessagePipe_Read, 5) \ |
| V(Mojo_GetTimeTicksNow, 0) \ |
| V(MojoHandle_Close, 1) \ |
| V(MojoHandle_Wait, 3) \ |
| V(MojoHandle_Register, 2) \ |
| V(MojoHandle_WaitMany, 3) \ |
| V(MojoHandleWatcher_SendControlData, 4) \ |
| V(MojoHandleWatcher_RecvControlData, 1) \ |
| V(MojoHandleWatcher_SetControlHandle, 1) \ |
| V(MojoHandleWatcher_GetControlHandle, 0) |
| |
| MOJO_NATIVE_LIST(DECLARE_FUNCTION); |
| |
| static struct NativeEntries { |
| const char* name; |
| Dart_NativeFunction function; |
| int argument_count; |
| } MojoEntries[] = {MOJO_NATIVE_LIST(REGISTER_FUNCTION)}; |
| |
| Dart_NativeFunction MojoNativeLookup(Dart_Handle name, |
| int argument_count, |
| bool* auto_setup_scope) { |
| const char* function_name = nullptr; |
| Dart_Handle result = Dart_StringToCString(name, &function_name); |
| DART_CHECK_VALID(result); |
| DCHECK(function_name != nullptr); |
| DCHECK(auto_setup_scope != nullptr); |
| *auto_setup_scope = true; |
| size_t num_entries = arraysize(MojoEntries); |
| for (size_t i = 0; i < num_entries; ++i) { |
| const struct NativeEntries& entry = MojoEntries[i]; |
| if (!strcmp(function_name, entry.name) && |
| (entry.argument_count == argument_count)) { |
| return entry.function; |
| } |
| } |
| return nullptr; |
| } |
| |
| const uint8_t* MojoNativeSymbol(Dart_NativeFunction nf) { |
| size_t num_entries = arraysize(MojoEntries); |
| for (size_t i = 0; i < num_entries; ++i) { |
| const struct NativeEntries& entry = MojoEntries[i]; |
| if (entry.function == nf) { |
| return reinterpret_cast<const uint8_t*>(entry.name); |
| } |
| } |
| return nullptr; |
| } |
| |
| static void SetNullReturn(Dart_NativeArguments arguments) { |
| Dart_SetReturnValue(arguments, Dart_Null()); |
| } |
| |
| static void SetInvalidArgumentReturn(Dart_NativeArguments arguments) { |
| Dart_SetIntegerReturnValue( |
| arguments, static_cast<int64_t>(MOJO_RESULT_INVALID_ARGUMENT)); |
| } |
| |
| static Dart_Handle SignalsStateToDart(const MojoHandleSignalsState& state) { |
| Dart_Handle list = Dart_NewList(2); |
| Dart_Handle arg0 = Dart_NewInteger(state.satisfied_signals); |
| Dart_Handle arg1 = Dart_NewInteger(state.satisfiable_signals); |
| Dart_ListSetAt(list, 0, arg0); |
| Dart_ListSetAt(list, 1, arg1); |
| return list; |
| } |
| |
| #define CHECK_INTEGER_ARGUMENT(args, num, result, failure) \ |
| { \ |
| Dart_Handle __status; \ |
| __status = Dart_GetNativeIntegerArgument(args, num, result); \ |
| if (Dart_IsError(__status)) { \ |
| Set##failure##Return(arguments); \ |
| return; \ |
| } \ |
| } \ |
| |
| struct CloserCallbackPeer { |
| MojoHandle handle; |
| }; |
| |
| static void MojoHandleCloserCallback(void* isolate_data, |
| Dart_WeakPersistentHandle handle, |
| void* peer) { |
| CloserCallbackPeer* callback_peer = |
| reinterpret_cast<CloserCallbackPeer*>(peer); |
| if (callback_peer->handle != MOJO_HANDLE_INVALID) { |
| MojoResult res = MojoClose(callback_peer->handle); |
| if (res == MOJO_RESULT_OK) { |
| // If this finalizer callback successfully closes a handle, it means that |
| // the handle has leaked from the Dart code, which is an error. |
| LOG(ERROR) << "Handle Finalizer closing handle:\n\tisolate: " |
| << "\n\thandle: " << callback_peer->handle; |
| } |
| } |
| delete callback_peer; |
| } |
| |
| // Setup a weak persistent handle for a MojoHandle that calls MojoClose on the |
| // handle when the MojoHandle is GC'd or the VM is going down. |
| void MojoHandle_Register(Dart_NativeArguments arguments) { |
| Dart_Handle mojo_handle_instance = Dart_GetNativeArgument(arguments, 0); |
| if (!Dart_IsInstance(mojo_handle_instance)) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| |
| int64_t raw_handle = static_cast<int64_t>(MOJO_HANDLE_INVALID); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &raw_handle, InvalidArgument); |
| if (raw_handle == static_cast<int64_t>(MOJO_HANDLE_INVALID)) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| |
| // Add the handle to this isolate's set. |
| MojoHandle handle = static_cast<MojoHandle>(raw_handle); |
| auto isolate_data = MojoDartState::Current(); |
| DCHECK(isolate_data != nullptr); |
| isolate_data->unclosed_handles().insert(handle); |
| |
| // Set up a finalizer. |
| CloserCallbackPeer* callback_peer = new CloserCallbackPeer(); |
| callback_peer->handle = handle; |
| Dart_NewWeakPersistentHandle(mojo_handle_instance, |
| reinterpret_cast<void*>(callback_peer), |
| sizeof(CloserCallbackPeer), |
| MojoHandleCloserCallback); |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(MOJO_RESULT_OK)); |
| } |
| |
| void Mojo_GetTimeTicksNow(Dart_NativeArguments arguments) { |
| MojoTimeTicks ticks = MojoGetTimeTicksNow(); |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(ticks)); |
| } |
| |
| void MojoHandle_Close(Dart_NativeArguments arguments) { |
| int64_t raw_handle; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &raw_handle, InvalidArgument); |
| |
| // Remove the handle from this isolate's set. |
| MojoHandle handle = static_cast<MojoHandle>(raw_handle); |
| auto isolate_data = MojoDartState::Current(); |
| DCHECK(isolate_data != nullptr); |
| isolate_data->unclosed_handles().erase(handle); |
| |
| MojoResult res = MojoClose(handle); |
| |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); |
| } |
| |
| void MojoHandle_Wait(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| int64_t signals = 0; |
| int64_t deadline = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &signals, InvalidArgument); |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &deadline, InvalidArgument); |
| |
| MojoHandleSignalsState state; |
| MojoResult r = mojo::Wait(mojo::Handle(static_cast<MojoHandle>(handle)), |
| static_cast<MojoHandleSignals>(signals), |
| static_cast<MojoDeadline>(deadline), &state); |
| |
| // The return value is structured as a list of length 2: |
| // [0] MojoResult |
| // [1] MojoHandleSignalsState. (may be null) |
| Dart_Handle list = Dart_NewList(2); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(r)); |
| if (mojo::WaitManyResult(r).AreSignalsStatesValid()) { |
| Dart_ListSetAt(list, 1, SignalsStateToDart(state)); |
| } else { |
| Dart_ListSetAt(list, 1, Dart_Null()); |
| } |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoHandle_WaitMany(Dart_NativeArguments arguments) { |
| int64_t deadline = 0; |
| Dart_Handle handles = Dart_GetNativeArgument(arguments, 0); |
| Dart_Handle signals = Dart_GetNativeArgument(arguments, 1); |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &deadline, InvalidArgument); |
| |
| if (!Dart_IsList(handles) || !Dart_IsList(signals)) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| |
| intptr_t handles_len = 0; |
| intptr_t signals_len = 0; |
| Dart_ListLength(handles, &handles_len); |
| Dart_ListLength(signals, &signals_len); |
| if (handles_len != signals_len) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| |
| std::vector<mojo::Handle> mojo_handles(handles_len); |
| std::vector<MojoHandleSignals> mojo_signals(handles_len); |
| |
| for (int i = 0; i < handles_len; i++) { |
| Dart_Handle dart_handle = Dart_ListGetAt(handles, i); |
| Dart_Handle dart_signal = Dart_ListGetAt(signals, i); |
| if (!Dart_IsInteger(dart_handle) || !Dart_IsInteger(dart_signal)) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| int64_t mojo_handle = 0; |
| int64_t mojo_signal = 0; |
| Dart_IntegerToInt64(dart_handle, &mojo_handle); |
| Dart_IntegerToInt64(dart_signal, &mojo_signal); |
| mojo_handles[i] = mojo::Handle(mojo_handle); |
| mojo_signals[i] = static_cast<MojoHandleSignals>(mojo_signal); |
| } |
| |
| std::vector<MojoHandleSignalsState> states(handles_len); |
| mojo::WaitManyResult wmr = mojo::WaitMany( |
| mojo_handles, mojo_signals, static_cast<MojoDeadline>(deadline), &states); |
| |
| // The return value is structured as a list of length 3: |
| // [0] MojoResult |
| // [1] index of handle that caused a return (may be null) |
| // [2] list of MojoHandleSignalsState. (may be null) |
| Dart_Handle list = Dart_NewList(3); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(wmr.result)); |
| if (wmr.IsIndexValid()) |
| Dart_ListSetAt(list, 1, Dart_NewInteger(wmr.index)); |
| else |
| Dart_ListSetAt(list, 1, Dart_Null()); |
| if (wmr.AreSignalsStatesValid()) { |
| Dart_Handle stateList = Dart_NewList(handles_len); |
| for (int i = 0; i < handles_len; i++) { |
| Dart_ListSetAt(stateList, i, SignalsStateToDart(states[i])); |
| } |
| Dart_ListSetAt(list, 2, stateList); |
| } else { |
| Dart_ListSetAt(list, 2, Dart_Null()); |
| } |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoSharedBuffer_Create(Dart_NativeArguments arguments) { |
| int64_t num_bytes = 0; |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &num_bytes, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &flags, Null); |
| |
| MojoCreateSharedBufferOptions options; |
| options.struct_size = sizeof(MojoCreateSharedBufferOptions); |
| options.flags = static_cast<MojoCreateSharedBufferOptionsFlags>(flags); |
| |
| MojoHandle out = MOJO_HANDLE_INVALID;; |
| MojoResult res = MojoCreateSharedBuffer( |
| &options, static_cast<int32_t>(num_bytes), &out); |
| |
| Dart_Handle list = Dart_NewList(2); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, Dart_NewInteger(out)); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoSharedBuffer_Duplicate(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &flags, Null); |
| |
| MojoDuplicateBufferHandleOptions options; |
| options.struct_size = sizeof(MojoDuplicateBufferHandleOptions); |
| options.flags = static_cast<MojoDuplicateBufferHandleOptionsFlags>(flags); |
| |
| MojoHandle out = MOJO_HANDLE_INVALID;; |
| MojoResult res = MojoDuplicateBufferHandle( |
| static_cast<MojoHandle>(handle), &options, &out); |
| |
| Dart_Handle list = Dart_NewList(2); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, Dart_NewInteger(out)); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| static void MojoBufferUnmapCallback(void* isolate_data, |
| Dart_WeakPersistentHandle handle, |
| void* peer) { |
| MojoUnmapBuffer(peer); |
| } |
| |
| void MojoSharedBuffer_Map(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| int64_t offset = 0; |
| int64_t num_bytes = 0; |
| int64_t flags = 0; |
| Dart_Handle mojo_buffer = Dart_GetNativeArgument(arguments, 0); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &handle, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &offset, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 3, &num_bytes, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 4, &flags, Null); |
| |
| void* out; |
| MojoResult res = MojoMapBuffer(static_cast<MojoHandle>(handle), |
| offset, |
| num_bytes, |
| &out, |
| static_cast<MojoMapBufferFlags>(flags)); |
| |
| Dart_Handle list = Dart_NewList(2); |
| Dart_Handle typed_data; |
| if (res == MOJO_RESULT_OK) { |
| typed_data = Dart_NewExternalTypedData( |
| Dart_TypedData_kByteData, out, num_bytes); |
| Dart_NewWeakPersistentHandle( |
| mojo_buffer, out, num_bytes, MojoBufferUnmapCallback); |
| } else { |
| typed_data = Dart_Null(); |
| } |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, typed_data); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoSharedBuffer_Unmap(Dart_NativeArguments arguments) { |
| Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 0); |
| if (Dart_GetTypeOfExternalTypedData(typed_data) == Dart_TypedData_kInvalid) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| |
| Dart_TypedData_Type typ; |
| void *data; |
| intptr_t len; |
| Dart_TypedDataAcquireData(typed_data, &typ, &data, &len); |
| MojoResult res = MojoUnmapBuffer(data); |
| Dart_TypedDataReleaseData(typed_data); |
| |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); |
| } |
| |
| void MojoDataPipe_Create(Dart_NativeArguments arguments) { |
| int64_t element_bytes = 0; |
| int64_t capacity_bytes = 0; |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &element_bytes, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &capacity_bytes, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); |
| |
| MojoCreateDataPipeOptions options; |
| options.struct_size = sizeof(MojoCreateDataPipeOptions); |
| options.flags = static_cast<MojoCreateDataPipeOptionsFlags>(flags); |
| options.element_num_bytes = static_cast<uint32_t>(element_bytes); |
| options.capacity_num_bytes = static_cast<uint32_t>(capacity_bytes); |
| |
| MojoHandle producer = MOJO_HANDLE_INVALID; |
| MojoHandle consumer = MOJO_HANDLE_INVALID; |
| MojoResult res = MojoCreateDataPipe(&options, &producer, &consumer); |
| |
| Dart_Handle list = Dart_NewList(3); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, Dart_NewInteger(producer)); |
| Dart_ListSetAt(list, 2, Dart_NewInteger(consumer)); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoDataPipe_WriteData(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); |
| |
| Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); |
| if (!Dart_IsTypedData(typed_data)) { |
| SetNullReturn(arguments); |
| return; |
| } |
| |
| int64_t num_bytes = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); |
| if (num_bytes <= 0) { |
| SetNullReturn(arguments); |
| return; |
| } |
| |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 3, &flags, Null); |
| |
| Dart_TypedData_Type type; |
| void* data; |
| intptr_t data_length; |
| Dart_TypedDataAcquireData(typed_data, &type, &data, &data_length); |
| uint32_t length = static_cast<uint32_t>(num_bytes); |
| MojoResult res = MojoWriteData( |
| static_cast<MojoHandle>(handle), |
| data, |
| &length, |
| static_cast<MojoWriteDataFlags>(flags)); |
| Dart_TypedDataReleaseData(typed_data); |
| |
| Dart_Handle list = Dart_NewList(2); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, Dart_NewInteger(length)); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoDataPipe_BeginWriteData(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| int64_t buffer_bytes = 0; |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &buffer_bytes, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); |
| |
| void* buffer; |
| uint32_t size = static_cast<uint32_t>(buffer_bytes); |
| MojoResult res = MojoBeginWriteData( |
| static_cast<MojoHandle>(handle), |
| &buffer, |
| &size, |
| static_cast<MojoWriteDataFlags>(flags)); |
| |
| Dart_Handle list = Dart_NewList(2); |
| Dart_Handle typed_data; |
| if (res == MOJO_RESULT_OK) { |
| typed_data = Dart_NewExternalTypedData( |
| Dart_TypedData_kByteData, buffer, size); |
| } else { |
| typed_data = Dart_Null(); |
| } |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, typed_data); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoDataPipe_EndWriteData(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| int64_t num_bytes_written = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &num_bytes_written, InvalidArgument); |
| |
| MojoResult res = MojoEndWriteData( |
| static_cast<MojoHandle>(handle), |
| static_cast<uint32_t>(num_bytes_written)); |
| |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); |
| } |
| |
| void MojoDataPipe_ReadData(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); |
| |
| Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); |
| if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { |
| SetNullReturn(arguments); |
| return; |
| } |
| // When querying the amount of data available to read from the pipe, |
| // null is passed in for typed_data. |
| |
| int64_t num_bytes = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); |
| |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 3, &flags, Null); |
| |
| Dart_TypedData_Type typ; |
| void* data = nullptr; |
| intptr_t bdlen = 0; |
| if (!Dart_IsNull(typed_data)) { |
| Dart_TypedDataAcquireData(typed_data, &typ, &data, &bdlen); |
| } |
| uint32_t len = static_cast<uint32_t>(num_bytes); |
| MojoResult res = MojoReadData( |
| static_cast<MojoHandle>(handle), |
| data, |
| &len, |
| static_cast<MojoReadDataFlags>(flags)); |
| if (!Dart_IsNull(typed_data)) { |
| Dart_TypedDataReleaseData(typed_data); |
| } |
| |
| Dart_Handle list = Dart_NewList(2); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, Dart_NewInteger(len)); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoDataPipe_BeginReadData(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| int64_t buffer_bytes = 0; |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &buffer_bytes, Null); |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); |
| |
| void* buffer; |
| uint32_t size = static_cast<uint32_t>(buffer_bytes); |
| MojoResult res = MojoBeginReadData( |
| static_cast<MojoHandle>(handle), |
| const_cast<const void**>(&buffer), |
| &size, |
| static_cast<MojoWriteDataFlags>(flags)); |
| |
| Dart_Handle list = Dart_NewList(2); |
| Dart_Handle typed_data; |
| if (res == MOJO_RESULT_OK) { |
| typed_data = Dart_NewExternalTypedData( |
| Dart_TypedData_kByteData, buffer, size); |
| } else { |
| typed_data = Dart_Null(); |
| } |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, typed_data); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoDataPipe_EndReadData(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| int64_t num_bytes_read = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &num_bytes_read, InvalidArgument); |
| |
| MojoResult res = MojoEndReadData( |
| static_cast<MojoHandle>(handle), |
| static_cast<uint32_t>(num_bytes_read)); |
| |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); |
| } |
| |
| void MojoMessagePipe_Create(Dart_NativeArguments arguments) { |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &flags, Null); |
| |
| MojoCreateMessagePipeOptions options; |
| options.struct_size = sizeof(MojoCreateMessagePipeOptions); |
| options.flags = static_cast<MojoCreateMessagePipeOptionsFlags>(flags); |
| |
| MojoHandle end1 = MOJO_HANDLE_INVALID; |
| MojoHandle end2 = MOJO_HANDLE_INVALID; |
| MojoResult res = MojoCreateMessagePipe(&options, &end1, &end2); |
| |
| Dart_Handle list = Dart_NewList(3); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, Dart_NewInteger(end1)); |
| Dart_ListSetAt(list, 2, Dart_NewInteger(end2)); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| void MojoMessagePipe_Write(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); |
| |
| Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); |
| if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| |
| int64_t num_bytes = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, InvalidArgument); |
| if ((Dart_IsNull(typed_data) && (num_bytes != 0)) || |
| (!Dart_IsNull(typed_data) && (num_bytes <= 0))) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| |
| Dart_Handle handles = Dart_GetNativeArgument(arguments, 3); |
| if (!Dart_IsList(handles) && !Dart_IsNull(handles)) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 4, &flags, InvalidArgument); |
| |
| // Grab the data if there is any. |
| Dart_TypedData_Type typ; |
| void* bytes = nullptr; |
| intptr_t bdlen = 0; |
| if (!Dart_IsNull(typed_data)) { |
| Dart_TypedDataAcquireData(typed_data, &typ, &bytes, &bdlen); |
| } |
| |
| // Grab the handles if there are any. |
| scoped_ptr<MojoHandle[]> mojo_handles; |
| intptr_t handles_len = 0; |
| if (!Dart_IsNull(handles)) { |
| Dart_ListLength(handles, &handles_len); |
| if (handles_len > 0) { |
| mojo_handles.reset(new MojoHandle[handles_len]); |
| } |
| for (int i = 0; i < handles_len; i++) { |
| Dart_Handle dart_handle = Dart_ListGetAt(handles, i); |
| if (!Dart_IsInteger(dart_handle)) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| int64_t mojo_handle = 0; |
| Dart_IntegerToInt64(dart_handle, &mojo_handle); |
| mojo_handles[i] = static_cast<MojoHandle>(mojo_handle); |
| } |
| } |
| |
| MojoResult res = MojoWriteMessage( |
| static_cast<MojoHandle>(handle), |
| const_cast<const void*>(bytes), |
| static_cast<uint32_t>(num_bytes), |
| mojo_handles.get(), |
| static_cast<uint32_t>(handles_len), |
| static_cast<MojoWriteMessageFlags>(flags)); |
| |
| // Release the data. |
| if (!Dart_IsNull(typed_data)) { |
| Dart_TypedDataReleaseData(typed_data); |
| } |
| |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); |
| } |
| |
| void MojoMessagePipe_Read(Dart_NativeArguments arguments) { |
| int64_t handle = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); |
| |
| Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); |
| if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { |
| SetNullReturn(arguments); |
| return; |
| } |
| // When querying the amount of data available to read from the pipe, |
| // null is passed in for typed_data. |
| |
| int64_t num_bytes = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); |
| if ((Dart_IsNull(typed_data) && (num_bytes != 0)) || |
| (!Dart_IsNull(typed_data) && (num_bytes <= 0))) { |
| SetNullReturn(arguments); |
| return; |
| } |
| |
| Dart_Handle handles = Dart_GetNativeArgument(arguments, 3); |
| if (!Dart_IsList(handles) && !Dart_IsNull(handles)) { |
| SetNullReturn(arguments); |
| return; |
| } |
| |
| int64_t flags = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 4, &flags, Null); |
| |
| // Grab the data if there is any. |
| Dart_TypedData_Type typ; |
| void* bytes = nullptr; |
| intptr_t byte_data_len = 0; |
| if (!Dart_IsNull(typed_data)) { |
| Dart_TypedDataAcquireData(typed_data, &typ, &bytes, &byte_data_len); |
| } |
| uint32_t blen = static_cast<uint32_t>(num_bytes); |
| |
| // Grab the handles if there are any. |
| scoped_ptr<MojoHandle[]> mojo_handles; |
| intptr_t handles_len = 0; |
| if (!Dart_IsNull(handles)) { |
| Dart_ListLength(handles, &handles_len); |
| mojo_handles.reset(new MojoHandle[handles_len]); |
| } |
| uint32_t hlen = static_cast<uint32_t>(handles_len); |
| |
| MojoResult res = MojoReadMessage( |
| static_cast<MojoHandle>(handle), |
| bytes, |
| &blen, |
| mojo_handles.get(), |
| &hlen, |
| static_cast<MojoReadMessageFlags>(flags)); |
| |
| // Release the data. |
| if (!Dart_IsNull(typed_data)) { |
| Dart_TypedDataReleaseData(typed_data); |
| } |
| |
| if (!Dart_IsNull(handles)) { |
| for (int i = 0; i < handles_len; i++) { |
| Dart_ListSetAt(handles, i, Dart_NewInteger(mojo_handles[i])); |
| } |
| } |
| |
| Dart_Handle list = Dart_NewList(3); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(res)); |
| Dart_ListSetAt(list, 1, Dart_NewInteger(blen)); |
| Dart_ListSetAt(list, 2, Dart_NewInteger(hlen)); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| struct ControlData { |
| int64_t handle; |
| Dart_Port port; |
| int64_t data; |
| }; |
| |
| void MojoHandleWatcher_SendControlData(Dart_NativeArguments arguments) { |
| int64_t control_handle = 0; |
| int64_t client_handle = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, InvalidArgument); |
| CHECK_INTEGER_ARGUMENT(arguments, 1, &client_handle, InvalidArgument); |
| |
| Dart_Handle send_port_handle = Dart_GetNativeArgument(arguments, 2); |
| Dart_Port send_port_id = ILLEGAL_PORT; |
| if (!Dart_IsNull(send_port_handle)) { |
| Dart_Handle result = Dart_SendPortGetId(send_port_handle, &send_port_id); |
| if (Dart_IsError(result)) { |
| SetInvalidArgumentReturn(arguments); |
| return; |
| } |
| } |
| |
| int64_t data = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 3, &data, InvalidArgument); |
| |
| ControlData cd; |
| cd.handle = client_handle; |
| cd.port = send_port_id; |
| cd.data = data; |
| const void* bytes = reinterpret_cast<const void*>(&cd); |
| MojoResult res = MojoWriteMessage( |
| control_handle, bytes, sizeof(cd), nullptr, 0, 0); |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); |
| } |
| |
| void MojoHandleWatcher_RecvControlData(Dart_NativeArguments arguments) { |
| int64_t control_handle = 0; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, Null); |
| |
| ControlData cd; |
| void* bytes = reinterpret_cast<void*>(&cd); |
| uint32_t num_bytes = sizeof(cd); |
| uint32_t num_handles = 0; |
| MojoResult res = MojoReadMessage( |
| control_handle, bytes, &num_bytes, nullptr, &num_handles, 0); |
| if (res != MOJO_RESULT_OK) { |
| SetNullReturn(arguments); |
| return; |
| } |
| |
| Dart_Handle list = Dart_NewList(3); |
| Dart_ListSetAt(list, 0, Dart_NewInteger(cd.handle)); |
| if (cd.port != ILLEGAL_PORT) { |
| Dart_ListSetAt(list, 1, Dart_NewSendPort(cd.port)); |
| } |
| Dart_ListSetAt(list, 2, Dart_NewInteger(cd.data)); |
| Dart_SetReturnValue(arguments, list); |
| } |
| |
| static int64_t mojo_control_handle = MOJO_HANDLE_INVALID; |
| void MojoHandleWatcher_SetControlHandle(Dart_NativeArguments arguments) { |
| int64_t control_handle; |
| CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, InvalidArgument); |
| mojo_control_handle = control_handle; |
| Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(MOJO_RESULT_OK)); |
| } |
| |
| void MojoHandleWatcher_GetControlHandle(Dart_NativeArguments arguments) { |
| Dart_SetIntegerReturnValue(arguments, mojo_control_handle); |
| } |
| |
| } // namespace dart |
| } // namespace mojo |