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

Side by Side 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, 7 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "nacl_io/devfs/jspipe_node.h" 5 #include "nacl_io/devfs/jspipe_node.h"
6 6
7 //#include <cstdio>
8 #include <cstring> 7 #include <cstring>
9 8
10 #include "nacl_io/devfs/dev_fs.h" 9 #include "nacl_io/devfs/dev_fs.h"
11 #include "nacl_io/error.h" 10 #include "nacl_io/error.h"
12 #include "nacl_io/ioctl.h" 11 #include "nacl_io/ioctl.h"
13 #include "nacl_io/kernel_handle.h" 12 #include "nacl_io/kernel_handle.h"
13 #include "nacl_io/log.h"
14 #include "nacl_io/pepper_interface.h" 14 #include "nacl_io/pepper_interface.h"
15 15
16 #define TRACE(format, ...) LOG_TRACE("jspipe: " format, ##__VA_ARGS__)
17 #define ERROR(format, ...) LOG_TRACE("jspipe: " format, ##__VA_ARGS__)
18
19 namespace {
20 const size_t kPostMessageBufferSize = 512*1024;
21 }
22
16 namespace nacl_io { 23 namespace nacl_io {
17 24
18 #define MAX_MESSAGE_SIZE (64*1024) 25 JSPipeNode::JSPipeNode(Filesystem* filesystem)
26 : Node(filesystem),
27 pipe_(new JSPipeEventEmitter(filesystem_->ppapi(), kPostMessageBufferSize)),
28 messaging_iface_(NULL),
29 var_iface_(NULL),
30 array_iface_(NULL),
31 buffer_iface_(NULL),
32 dict_iface_(NULL) {
33 PepperInterface* ppapi = filesystem_->ppapi();
34 if (ppapi) {
35 messaging_iface_ = ppapi->GetMessagingInterface();
36 var_iface_ = ppapi->GetVarInterface();
37 array_iface_ = ppapi->GetVarArrayInterface();
38 buffer_iface_ = ppapi->GetVarArrayBufferInterface();
39 dict_iface_ = ppapi->GetVarDictionaryInterface();
40 } else {
41 TRACE("missing PPAPI provider");
42 }
43 }
44
45 JSPipeEventEmitter* JSPipeNode::GetEventEmitter() {
46 return pipe_.get();
47 }
48
49 Error JSPipeNode::HandleJSWrite(struct PP_Var message) {
50 TRACE("HandleJSWrite");
51 if (message.type != PP_VARTYPE_ARRAY_BUFFER) {
52 TRACE("HandleJSWrite expected ArrayBuffer but got %d.", message.type);
53 return EINVAL;
54 }
55 uint32_t length;
56 if (buffer_iface_->ByteLength(message, &length) != PP_TRUE)
57 return EINVAL;
58
59 char* buffer = (char*)buffer_iface_->Map(message);
60
61 // Write data to the input fifo
62 int wrote = GetEventEmitter()->HandleJSWrite(buffer, length);
binji 2014/05/01 20:22:31 returns size_t
63 buffer_iface_->Unmap(message);
64 if (wrote != (int) length) {
65 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
66 return EIO;
67 }
68 TRACE("done HandleWrite: %d", length);
69 return 0;
70 }
71
72 Error JSPipeNode::HandleJSAck(PP_Var message) {
73 if (message.type != PP_VARTYPE_INT32) {
74 TRACE("HandleAck integer object expected but got %d.", message.type);
75 return EINVAL;
76 }
77 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
78 return 0;
79 }
80
81 Error JSPipeNode::HandleJSMessage(struct PP_Var message) {
82 Error err = 0;
83 if (!messaging_iface_ || !var_iface_ || !array_iface_ || !buffer_iface_) {
84 TRACE("HandleJSMessage: missing PPAPI interfaces");
85 return ENOSYS;
86 }
87
88 // Verify that we have an array with size two.
89 if (message.type != PP_VARTYPE_ARRAY) {
90 TRACE("HandleJSMessage passed non-array var");
91 return EINVAL;
92 }
93
94 if (array_iface_->GetLength(message) != 2) {
95 TRACE("HandleJSMessage passed array of size %d",
96 array_iface_->GetLength(message));
97 return EINVAL;
98 }
99
100 PP_Var message_type_var = array_iface_->Get(message, 0);
101 PP_Var payload = array_iface_->Get(message, 1);
102 if (message_type_var.type != PP_VARTYPE_STRING) {
103 err = EINVAL;
104 } else {
105 uint32_t length;
106 const char* message_type_string;
107 message_type_string = var_iface_->VarToUtf8(message_type_var, &length);
108 std::string message_type(message_type_string, length);
109
110 TRACE("HandleJSMessage %s", message_type.c_str());
111 if (message_type == "write") {
112 err = HandleJSWrite(payload);
113 } else if (message_type == "ack") {
114 err = HandleJSAck(payload);
115 } else {
116 TRACE("Unknown message type: %s", message_type.c_str());
117 err = EINVAL;
118 }
119 }
120
121 var_iface_->Release(message_type_var);
122 var_iface_->Release(payload);
123 return err;
124 }
125
126 Error JSPipeNode::Read(const HandleAttr& attr,
127 void* buf,
128 size_t count,
129 int* out_bytes) {
130 int ms = attr.IsBlocking() ? -1 : 0;
131
132 EventListenerLock wait(GetEventEmitter());
133 Error err = wait.WaitOnEvent(POLLIN, ms);
134 if (err == ETIMEDOUT)
135 err = EWOULDBLOCK;
136 if (err)
137 return err;
138
139 *out_bytes = GetEventEmitter()->Read_Locked(static_cast<char*>(buf), count);
140 return 0;
141 }
142
19 Error JSPipeNode::Write(const HandleAttr& attr, 143 Error JSPipeNode::Write(const HandleAttr& attr,
20 const void* buf, 144 const void* buf,
21 size_t count, 145 size_t count,
22 int* out_bytes) { 146 int* out_bytes) {
23 PepperInterface* ppapi = filesystem_->ppapi(); 147 int ms = attr.IsBlocking() ? -1 : 0;
24 MessagingInterface* iface = ppapi->GetMessagingInterface(); 148 TRACE("write %d", ms);
25 VarInterface* var_iface = ppapi->GetVarInterface();
26 VarArrayInterface* array_iface = ppapi->GetVarArrayInterface();
27 VarArrayBufferInterface* buffer_iface = ppapi->GetVarArrayBufferInterface();
28 if (!iface || !var_iface || !array_iface || !buffer_iface)
29 return ENOSYS;
30 149
31 if (name_.empty()) 150 EventListenerLock wait(GetEventEmitter());
32 return EIO; 151 Error err = wait.WaitOnEvent(POLLOUT, ms);
152 if (err == ETIMEDOUT)
153 err = EWOULDBLOCK;
154 if (err)
155 return err;
33 156
34 // Limit the size of the data we send with PostMessage to MAX_MESSAGE_SIZE 157 *out_bytes = GetEventEmitter()->Write_Locked(static_cast<const char*>(buf),
35 if (count > MAX_MESSAGE_SIZE) 158 count);
36 count = MAX_MESSAGE_SIZE;
37
38 // Copy data in a new ArrayBuffer
39 PP_Var buffer = buffer_iface->Create(count);
40 memcpy(buffer_iface->Map(buffer), buf, count);
41 buffer_iface->Unmap(buffer);
42
43 // Construct string var containing the name of the pipe
44 PP_Var string = var_iface->VarFromUtf8(name_.c_str(), name_.size());
45
46 // Construct two element array containing string and array buffer
47 PP_Var array = array_iface->Create();
48 array_iface->Set(array, 0, string);
49 array_iface->Set(array, 1, buffer);
50
51 // Release our handles to the items that are now in the array
52 var_iface->Release(string);
53 var_iface->Release(buffer);
54
55 // Send array via PostMessage
56 iface->PostMessage(ppapi->GetInstance(), array);
57
58 // Release the array
59 var_iface->Release(array);
60
61 *out_bytes = count;
62 return 0; 159 return 0;
63 } 160 }
64 161
65 Error JSPipeNode::VIoctl(int request, va_list args) { 162 Error JSPipeNode::VIoctl(int request, va_list args) {
163 AUTO_LOCK(node_lock_);
164
66 switch (request) { 165 switch (request) {
67 case TIOCNACLPIPENAME: { 166 case NACL_IOC_PIPE_SETNAME: {
68 // name can only be set once
69 if (!name_.empty())
70 return EIO;
71
72 const char* new_name = va_arg(args, char*); 167 const char* new_name = va_arg(args, char*);
73 // new name must not be empty 168 return GetEventEmitter()->SetName(new_name);
74 if (!new_name || strlen(new_name) == 0) 169 }
75 return EIO; 170 case NACL_IOC_PIPE_GETISPACE: {
76 171 int* space = va_arg(args, int*);
77 name_ = new_name; 172 *space = GetEventEmitter()->GetISpace();
78 return 0; 173 return 0;
79 } 174 }
80 case TIOCNACLINPUT: { 175 case NACL_IOC_PIPE_GETOSPACE: {
81 // This ioctl is used to deliver data from javascipt into the pipe. 176 int* space = va_arg(args, int*);
82 struct tioc_nacl_input_string* message = 177 *space = GetEventEmitter()->GetOSpace();
83 va_arg(args, struct tioc_nacl_input_string*);
84 const char* buffer = message->buffer;
85 int num_bytes = message->length;
86 int wrote = 0;
87 HandleAttr data;
88 // Write to the underlying pipe. Calling JSPipeNode::Write
89 // would write using PostMessage.
90 int error = PipeNode::Write(data, buffer, num_bytes, &wrote);
91 if (error || wrote != num_bytes)
92 return EIO;
93 return 0; 178 return 0;
94 } 179 }
180 case NACL_IOC_HANDLEMESSAGE: {
181 struct PP_Var* message = va_arg(args, struct PP_Var*);
182 return HandleJSMessage(*message);
183 }
184 default:
185 TRACE("unknown ioctl: %#x", request);
186 break;
95 } 187 }
96 188
97 return EINVAL; 189 return EINVAL;
98 } 190 }
99 191
100 } // namespace nacl_io 192 } // namespace nacl_io
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698