Chromium Code Reviews| Index: native_client_sdk/src/libraries/nacl_io/devfs/jspipe_event_emitter.cc |
| diff --git a/native_client_sdk/src/libraries/nacl_io/devfs/jspipe_event_emitter.cc b/native_client_sdk/src/libraries/nacl_io/devfs/jspipe_event_emitter.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5dea91d1e277b406033be3e5006fce9d6e77cd28 |
| --- /dev/null |
| +++ b/native_client_sdk/src/libraries/nacl_io/devfs/jspipe_event_emitter.cc |
| @@ -0,0 +1,170 @@ |
| +// Copyright 2013 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 "nacl_io/devfs/jspipe_event_emitter.h" |
| + |
| +#define __STDC_FORMAT_MACROS |
| +#include <errno.h> |
| +#include <inttypes.h> |
| +#include <string.h> |
| + |
| +#include <algorithm> |
| + |
| +#define TRACE(format, ...) \ |
| + LOG_TRACE("jspipe[%s]: " format, name_.c_str(), ##__VA_ARGS__) |
| +#define ERROR(format, ...) \ |
| + LOG_ERROR("jspipe[%s]: " format, name_.c_str(), ##__VA_ARGS__) |
| + |
| +#include "nacl_io/log.h" |
| +#include "nacl_io/pepper_interface.h" |
| + |
| +namespace { |
| +const size_t kMaxPostMessageSize = 64*1024; |
| +} |
| + |
| +namespace nacl_io { |
| + |
| +JSPipeEventEmitter::JSPipeEventEmitter(PepperInterface* ppapi, size_t size) |
| + : input_fifo_(size), |
| + post_message_buffer_size_(size), |
| + bytes_sent_(0), |
| + bytes_acked_(0), |
| + bytes_read_(0), |
| + ppapi_(ppapi) { |
| + if (ppapi) { |
| + messaging_iface_ = ppapi->GetMessagingInterface(); |
|
binji
2014/05/01 20:22:31
initialize to NULL if ppapi is NULL
Sam Clegg
2014/05/01 22:16:55
Done, and added a test.
|
| + var_iface_ = ppapi->GetVarInterface(); |
| + array_iface_ = ppapi->GetVarArrayInterface(); |
| + buffer_iface_ = ppapi->GetVarArrayBufferInterface(); |
| + dict_iface_ = ppapi->GetVarDictionaryInterface(); |
| + } |
| + UpdateStatus_Locked(); |
| +} |
| + |
| +void JSPipeEventEmitter::UpdateStatus_Locked() { |
| + uint32_t status = 0; |
| + if (!input_fifo_.IsEmpty()) |
| + status |= POLLIN; |
| + |
| + if (GetOSpace() > 0) |
| + status |= POLLOUT; |
| + |
| + ClearEvents_Locked(~status); |
| + RaiseEvents_Locked(status); |
| +} |
| + |
| +size_t JSPipeEventEmitter::Read_Locked(char* data, size_t len) { |
| + size_t out_len = input_fifo_.Read(data, len); |
| + if (out_len > 0) { |
| + bytes_read_ += out_len; |
| + SendAckMessage(bytes_read_); |
|
binji
2014/05/01 20:22:31
Why ack total count instead of the amount read?
binji
2014/05/01 20:22:31
check error
Sam Clegg
2014/05/01 22:16:55
The ack messages always contain the running total.
Sam Clegg
2014/05/01 22:16:55
Done.
|
| + } |
| + |
| + UpdateStatus_Locked(); |
| + return out_len; |
| +} |
| + |
| +Error JSPipeEventEmitter::SendWriteMessage(const void* buf, size_t count) { |
| + TRACE("SendWriteMessage [%zd] total=%" PRIi64, count, bytes_sent_); |
| + if (!var_iface_ || !buffer_iface_) |
| + return EIO; |
| + |
| + // Copy payload data in a new ArrayBuffer |
| + PP_Var buffer = buffer_iface_->Create(count); |
| + memcpy(buffer_iface_->Map(buffer), buf, count); |
| + buffer_iface_->Unmap(buffer); |
| + |
| + SendMessageToJS("write", buffer); |
|
binji
2014/05/01 20:22:31
check error
Sam Clegg
2014/05/01 22:16:55
Done.
|
| + |
| + var_iface_->Release(buffer); |
| + return 0; |
| +} |
| + |
| +Error JSPipeEventEmitter::SetName(const char* name) { |
| + // name can only be set once |
| + if (!name_.empty()) |
| + return EIO; |
| + |
| + // new name must not be empty |
| + if (!name || strlen(name) == 0) |
| + return EIO; |
| + |
| + TRACE("set name: %s", name); |
| + name_ = name; |
| + return 0; |
| +} |
| + |
| +Error JSPipeEventEmitter::SendMessageToJS(const char* message_type, |
| + PP_Var payload) { |
| + if (!messaging_iface_ || !var_iface_ || !dict_iface_ || !array_iface_) |
| + return EIO; |
| + |
| + // Construct two element array containing message type and the payload |
| + PP_Var array = array_iface_->Create(); |
| + PP_Var message_type_var = var_iface_->VarFromUtf8(message_type, |
|
binji
2014/05/01 20:22:31
are you expecting arbitrary message types? If not,
|
| + strlen(message_type)); |
| + array_iface_->Set(array, 0, message_type_var); |
|
binji
2014/05/01 20:22:31
check errors on these pepper functions
|
| + array_iface_->Set(array, 1, payload); |
| + var_iface_->Release(message_type_var); |
| + |
| + // Create dict object with pipe name as key and array as value. |
| + PP_Var dict = dict_iface_->Create(); |
| + PP_Var pipe_name = var_iface_->VarFromUtf8(name_.c_str(), name_.size()); |
|
binji
2014/05/01 20:22:31
cache this in SetName because it never changes?
|
| + dict_iface_->Set(dict, pipe_name, array); |
| + var_iface_->Release(pipe_name); |
| + var_iface_->Release(array); |
| + |
| + // Send the dict via PostMessage |
| + messaging_iface_->PostMessage(ppapi_->GetInstance(), dict); |
| + |
| + // Release the dict |
| + var_iface_->Release(dict); |
| + return 0; |
| +} |
| + |
| +Error JSPipeEventEmitter::SendAckMessage(int64_t byte_count) { |
| + TRACE("SendAckMessage %"PRIi64, byte_count); |
| + PP_Var payload; |
| + payload.type = PP_VARTYPE_INT32; |
| + payload.value.as_int = (int32_t)byte_count; |
| + |
| + return SendMessageToJS("ack", payload); |
| +} |
| + |
| +size_t JSPipeEventEmitter::HandleJSWrite(const char* data, size_t len) { |
| + size_t out_len = input_fifo_.Write(data, len); |
| + UpdateStatus_Locked(); |
| + return out_len; |
| +} |
| + |
| +void JSPipeEventEmitter::HandleJSAck(int64_t byte_count) { |
| + if (byte_count > bytes_sent_ || byte_count < 0) { |
| + ERROR("HandleAck unexpected byte count: %"PRIi64, byte_count); |
| + return; |
| + } |
| + |
| + bytes_acked_ = byte_count; |
| + TRACE("HandleAck: %" PRIi64 "/%" PRIi64, bytes_acked_, bytes_sent_); |
| + UpdateStatus_Locked(); |
| +} |
| + |
| +size_t JSPipeEventEmitter::Write_Locked(const char* data, size_t len) { |
| + if (GetOSpace() == 0) |
| + return -1; |
|
binji
2014/05/01 20:22:31
should this return ssize_t then?
Sam Clegg
2014/05/01 22:16:55
Done.
|
| + |
| + if (len > GetOSpace()) |
| + len = GetOSpace(); |
| + |
| + // Limit the size of the data we send with PostMessage to kMaxPostMessageSize |
| + if (len > kMaxPostMessageSize) |
| + len = kMaxPostMessageSize; |
| + |
| + SendWriteMessage(data, len); |
|
binji
2014/05/01 20:22:31
check error
Sam Clegg
2014/05/01 22:16:55
Done.
|
| + bytes_sent_ += len; |
| + |
| + UpdateStatus_Locked(); |
| + return len; |
| +} |
| + |
| +} // namespace nacl_io |