OLD | NEW |
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 { |
| 29 } |
| 30 |
| 31 JSPipeEventEmitter* JSPipeNode::GetEventEmitter() { |
| 32 return pipe_.get(); |
| 33 } |
| 34 |
| 35 Error JSPipeNode::Read(const HandleAttr& attr, |
| 36 void* buf, |
| 37 size_t count, |
| 38 int* out_bytes) { |
| 39 int ms = attr.IsBlocking() ? -1 : 0; |
| 40 |
| 41 EventListenerLock wait(GetEventEmitter()); |
| 42 Error err = wait.WaitOnEvent(POLLIN, ms); |
| 43 if (err == ETIMEDOUT) |
| 44 err = EWOULDBLOCK; |
| 45 if (err) |
| 46 return err; |
| 47 |
| 48 return GetEventEmitter()->Read_Locked(static_cast<char*>(buf), count, |
| 49 out_bytes); |
| 50 } |
| 51 |
19 Error JSPipeNode::Write(const HandleAttr& attr, | 52 Error JSPipeNode::Write(const HandleAttr& attr, |
20 const void* buf, | 53 const void* buf, |
21 size_t count, | 54 size_t count, |
22 int* out_bytes) { | 55 int* out_bytes) { |
23 PepperInterface* ppapi = filesystem_->ppapi(); | 56 int ms = attr.IsBlocking() ? -1 : 0; |
24 MessagingInterface* iface = ppapi->GetMessagingInterface(); | 57 TRACE("write timeout=%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 | 58 |
31 if (name_.empty()) | 59 EventListenerLock wait(GetEventEmitter()); |
32 return EIO; | 60 Error err = wait.WaitOnEvent(POLLOUT, ms); |
| 61 if (err == ETIMEDOUT) |
| 62 err = EWOULDBLOCK; |
| 63 if (err) |
| 64 return err; |
33 | 65 |
34 // Limit the size of the data we send with PostMessage to MAX_MESSAGE_SIZE | 66 return GetEventEmitter()->Write_Locked(static_cast<const char*>(buf), |
35 if (count > MAX_MESSAGE_SIZE) | 67 count, out_bytes); |
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; | |
63 } | 68 } |
64 | 69 |
65 Error JSPipeNode::VIoctl(int request, va_list args) { | 70 Error JSPipeNode::VIoctl(int request, va_list args) { |
| 71 AUTO_LOCK(node_lock_); |
| 72 |
66 switch (request) { | 73 switch (request) { |
67 case TIOCNACLPIPENAME: { | 74 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*); | 75 const char* new_name = va_arg(args, char*); |
73 // new name must not be empty | 76 return GetEventEmitter()->SetName(new_name); |
74 if (!new_name || strlen(new_name) == 0) | 77 } |
75 return EIO; | 78 case NACL_IOC_PIPE_GETISPACE: { |
76 | 79 int* space = va_arg(args, int*); |
77 name_ = new_name; | 80 *space = GetEventEmitter()->GetISpace(); |
78 return 0; | 81 return 0; |
79 } | 82 } |
80 case TIOCNACLINPUT: { | 83 case NACL_IOC_PIPE_GETOSPACE: { |
81 // This ioctl is used to deliver data from javascipt into the pipe. | 84 int* space = va_arg(args, int*); |
82 struct tioc_nacl_input_string* message = | 85 *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; | 86 return 0; |
94 } | 87 } |
| 88 case NACL_IOC_HANDLEMESSAGE: { |
| 89 struct PP_Var* message = va_arg(args, struct PP_Var*); |
| 90 return GetEventEmitter()->HandleJSMessage(*message); |
| 91 } |
| 92 default: |
| 93 TRACE("unknown ioctl: %#x", request); |
| 94 break; |
95 } | 95 } |
96 | 96 |
97 return EINVAL; | 97 return EINVAL; |
98 } | 98 } |
99 | 99 |
100 } // namespace nacl_io | 100 } // namespace nacl_io |
OLD | NEW |