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

Unified Diff: native_client_sdk/src/libraries/nacl_io/devfs/jspipe_node.cc

Issue 242533005: [NaCl SDK] nacl_io: Add flow control the JavaScript pipes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/libraries/nacl_io/devfs/jspipe_node.cc
diff --git a/native_client_sdk/src/libraries/nacl_io/devfs/jspipe_node.cc b/native_client_sdk/src/libraries/nacl_io/devfs/jspipe_node.cc
index 7979e33a29d8cc09a19b3e459e3664ba84c35386..8b670d74f36aae6c0e5ad2cb5d89c7432ba5a8c8 100644
--- a/native_client_sdk/src/libraries/nacl_io/devfs/jspipe_node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/devfs/jspipe_node.cc
@@ -4,94 +4,186 @@
#include "nacl_io/devfs/jspipe_node.h"
-//#include <cstdio>
#include <cstring>
#include "nacl_io/devfs/dev_fs.h"
#include "nacl_io/error.h"
#include "nacl_io/ioctl.h"
#include "nacl_io/kernel_handle.h"
+#include "nacl_io/log.h"
#include "nacl_io/pepper_interface.h"
+#define TRACE(format, ...) LOG_TRACE("jspipe: " format, ##__VA_ARGS__)
+#define ERROR(format, ...) LOG_TRACE("jspipe: " format, ##__VA_ARGS__)
+
+namespace {
+const size_t kPostMessageBufferSize = 512*1024;
+}
+
namespace nacl_io {
-#define MAX_MESSAGE_SIZE (64*1024)
-Error JSPipeNode::Write(const HandleAttr& attr,
- const void* buf,
- size_t count,
- int* out_bytes) {
+JSPipeNode::JSPipeNode(Filesystem* filesystem)
+ : Node(filesystem),
+ pipe_(new JSPipeEventEmitter(filesystem_->ppapi(), kPostMessageBufferSize)),
+ messaging_iface_(NULL),
+ var_iface_(NULL),
+ array_iface_(NULL),
+ buffer_iface_(NULL),
+ dict_iface_(NULL) {
PepperInterface* ppapi = filesystem_->ppapi();
- MessagingInterface* iface = ppapi->GetMessagingInterface();
- VarInterface* var_iface = ppapi->GetVarInterface();
- VarArrayInterface* array_iface = ppapi->GetVarArrayInterface();
- VarArrayBufferInterface* buffer_iface = ppapi->GetVarArrayBufferInterface();
- if (!iface || !var_iface || !array_iface || !buffer_iface)
- return ENOSYS;
+ if (ppapi) {
+ messaging_iface_ = ppapi->GetMessagingInterface();
+ var_iface_ = ppapi->GetVarInterface();
+ array_iface_ = ppapi->GetVarArrayInterface();
+ buffer_iface_ = ppapi->GetVarArrayBufferInterface();
+ dict_iface_ = ppapi->GetVarDictionaryInterface();
+ } else {
+ TRACE("missing PPAPI provider");
+ }
+}
- if (name_.empty())
+JSPipeEventEmitter* JSPipeNode::GetEventEmitter() {
+ return pipe_.get();
+}
+
+Error JSPipeNode::HandleJSWrite(struct PP_Var message) {
+ TRACE("HandleJSWrite");
+ if (message.type != PP_VARTYPE_ARRAY_BUFFER) {
+ TRACE("HandleJSWrite expected ArrayBuffer but got %d.", message.type);
+ return EINVAL;
+ }
+ uint32_t length;
+ if (buffer_iface_->ByteLength(message, &length) != PP_TRUE)
+ return EINVAL;
+
+ char* buffer = (char*)buffer_iface_->Map(message);
+
+ // Write data to the input fifo
+ int wrote = GetEventEmitter()->HandleJSWrite(buffer, length);
binji 2014/05/01 20:22:31 returns size_t
+ buffer_iface_->Unmap(message);
+ if (wrote != (int) length) {
+ LOG_ERROR("Only wrote %d of %d bytes to pipe", wrote, length);
binji 2014/05/01 20:22:31 ERROR instead of LOG_ERROR?
Sam Clegg 2014/05/01 22:16:55 File local macro that also print the name of the p
return EIO;
+ }
+ TRACE("done HandleWrite: %d", length);
+ return 0;
+}
- // Limit the size of the data we send with PostMessage to MAX_MESSAGE_SIZE
- if (count > MAX_MESSAGE_SIZE)
- count = MAX_MESSAGE_SIZE;
+Error JSPipeNode::HandleJSAck(PP_Var message) {
+ if (message.type != PP_VARTYPE_INT32) {
+ TRACE("HandleAck integer object expected but got %d.", message.type);
+ return EINVAL;
+ }
+ GetEventEmitter()->HandleJSAck(message.value.as_int);
binji 2014/05/01 20:22:31 This will never be able to ack above 2**31
Sam Clegg 2014/05/01 22:16:55 True, this is a current know issue that also effec
+ return 0;
+}
- // Copy data in a new ArrayBuffer
- PP_Var buffer = buffer_iface->Create(count);
- memcpy(buffer_iface->Map(buffer), buf, count);
- buffer_iface->Unmap(buffer);
+Error JSPipeNode::HandleJSMessage(struct PP_Var message) {
+ Error err = 0;
+ if (!messaging_iface_ || !var_iface_ || !array_iface_ || !buffer_iface_) {
+ TRACE("HandleJSMessage: missing PPAPI interfaces");
+ return ENOSYS;
+ }
+
+ // Verify that we have an array with size two.
+ if (message.type != PP_VARTYPE_ARRAY) {
+ TRACE("HandleJSMessage passed non-array var");
+ return EINVAL;
+ }
+
+ if (array_iface_->GetLength(message) != 2) {
+ TRACE("HandleJSMessage passed array of size %d",
+ array_iface_->GetLength(message));
+ return EINVAL;
+ }
- // Construct string var containing the name of the pipe
- PP_Var string = var_iface->VarFromUtf8(name_.c_str(), name_.size());
+ PP_Var message_type_var = array_iface_->Get(message, 0);
+ PP_Var payload = array_iface_->Get(message, 1);
+ if (message_type_var.type != PP_VARTYPE_STRING) {
+ err = EINVAL;
+ } else {
+ uint32_t length;
+ const char* message_type_string;
+ message_type_string = var_iface_->VarToUtf8(message_type_var, &length);
+ std::string message_type(message_type_string, length);
+
+ TRACE("HandleJSMessage %s", message_type.c_str());
+ if (message_type == "write") {
+ err = HandleJSWrite(payload);
+ } else if (message_type == "ack") {
+ err = HandleJSAck(payload);
+ } else {
+ TRACE("Unknown message type: %s", message_type.c_str());
+ err = EINVAL;
+ }
+ }
- // Construct two element array containing string and array buffer
- PP_Var array = array_iface->Create();
- array_iface->Set(array, 0, string);
- array_iface->Set(array, 1, buffer);
+ var_iface_->Release(message_type_var);
+ var_iface_->Release(payload);
+ return err;
+}
- // Release our handles to the items that are now in the array
- var_iface->Release(string);
- var_iface->Release(buffer);
+Error JSPipeNode::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
+ int ms = attr.IsBlocking() ? -1 : 0;
- // Send array via PostMessage
- iface->PostMessage(ppapi->GetInstance(), array);
+ EventListenerLock wait(GetEventEmitter());
+ Error err = wait.WaitOnEvent(POLLIN, ms);
+ if (err == ETIMEDOUT)
+ err = EWOULDBLOCK;
+ if (err)
+ return err;
- // Release the array
- var_iface->Release(array);
+ *out_bytes = GetEventEmitter()->Read_Locked(static_cast<char*>(buf), count);
+ return 0;
+}
- *out_bytes = count;
+Error JSPipeNode::Write(const HandleAttr& attr,
+ const void* buf,
+ size_t count,
+ int* out_bytes) {
+ int ms = attr.IsBlocking() ? -1 : 0;
+ TRACE("write %d", ms);
+
+ EventListenerLock wait(GetEventEmitter());
+ Error err = wait.WaitOnEvent(POLLOUT, ms);
+ if (err == ETIMEDOUT)
+ err = EWOULDBLOCK;
+ if (err)
+ return err;
+
+ *out_bytes = GetEventEmitter()->Write_Locked(static_cast<const char*>(buf),
+ count);
return 0;
}
Error JSPipeNode::VIoctl(int request, va_list args) {
- switch (request) {
- case TIOCNACLPIPENAME: {
- // name can only be set once
- if (!name_.empty())
- return EIO;
+ AUTO_LOCK(node_lock_);
+ switch (request) {
+ case NACL_IOC_PIPE_SETNAME: {
const char* new_name = va_arg(args, char*);
- // new name must not be empty
- if (!new_name || strlen(new_name) == 0)
- return EIO;
-
- name_ = new_name;
+ return GetEventEmitter()->SetName(new_name);
+ }
+ case NACL_IOC_PIPE_GETISPACE: {
+ int* space = va_arg(args, int*);
+ *space = GetEventEmitter()->GetISpace();
return 0;
}
- case TIOCNACLINPUT: {
- // This ioctl is used to deliver data from javascipt into the pipe.
- struct tioc_nacl_input_string* message =
- va_arg(args, struct tioc_nacl_input_string*);
- const char* buffer = message->buffer;
- int num_bytes = message->length;
- int wrote = 0;
- HandleAttr data;
- // Write to the underlying pipe. Calling JSPipeNode::Write
- // would write using PostMessage.
- int error = PipeNode::Write(data, buffer, num_bytes, &wrote);
- if (error || wrote != num_bytes)
- return EIO;
+ case NACL_IOC_PIPE_GETOSPACE: {
+ int* space = va_arg(args, int*);
+ *space = GetEventEmitter()->GetOSpace();
return 0;
}
+ case NACL_IOC_HANDLEMESSAGE: {
+ struct PP_Var* message = va_arg(args, struct PP_Var*);
+ return HandleJSMessage(*message);
+ }
+ default:
+ TRACE("unknown ioctl: %#x", request);
+ break;
}
return EINVAL;

Powered by Google App Engine
This is Rietveld 408576698