1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "nacl_io/devfs/jspipe_event_emitter.h" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <assert.h> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <errno.h> 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string.h> 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <algorithm> 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define TRACE(format, ...) \ 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG_TRACE("jspipe[%s]: " format, name_.c_str(), ##__VA_ARGS__) 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define ERROR(format, ...) \ 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG_ERROR("jspipe[%s]: " format, name_.c_str(), ##__VA_ARGS__) 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "nacl_io/log.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "nacl_io/osinttypes.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "nacl_io/pepper_interface.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const size_t kMaxPostMessageSize = 64 * 1024; 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char* kDictKeyPipe = "pipe"; 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char* kDictKeyOperation = "operation"; 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char* kDictKeyPayload = "payload"; 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char* kOperationNameAck = "ack"; 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char* kOperationNameWrite = "write"; 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace nacl_io { 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)JSPipeEventEmitter::JSPipeEventEmitter(PepperInterface* ppapi, size_t size) 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : input_fifo_(size), 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) post_message_buffer_size_(size), 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bytes_sent_(0), 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bytes_acked_(0), 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bytes_read_(0), 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ppapi_(ppapi), 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) messaging_iface_(NULL), 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) var_iface_(NULL), 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) array_iface_(NULL), 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) buffer_iface_(NULL), 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) dict_iface_(NULL), 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pipe_name_var_(PP_MakeUndefined()), 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pipe_key_(PP_MakeUndefined()), 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) operation_key_(PP_MakeUndefined()), 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) payload_key_(PP_MakeUndefined()), 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) write_var_(PP_MakeUndefined()), 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ack_var_(PP_MakeUndefined()) { 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UpdateStatus_Locked(); 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ppapi == NULL) { 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TRACE("missing PPAPI provider"); 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) messaging_iface_ = ppapi->GetMessagingInterface(); 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_ = ppapi->GetVarInterface(); 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) array_iface_ = ppapi->GetVarArrayInterface(); 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_iface_ = ppapi->GetVarArrayBufferInterface(); 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dict_iface_ = ppapi->GetVarDictionaryInterface(); 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (var_iface_ == NULL) 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pipe_key_ = VarFromCStr(kDictKeyPipe); 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) operation_key_ = VarFromCStr(kDictKeyOperation); 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) payload_key_ = VarFromCStr(kDictKeyPayload); 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) write_var_ = VarFromCStr(kOperationNameWrite); 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ack_var_ = VarFromCStr(kOperationNameAck); 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void JSPipeEventEmitter::Destroy() { 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (var_iface_ == NULL) 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(pipe_name_var_); 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(pipe_key_); 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(operation_key_); 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(payload_key_); 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(write_var_); 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(ack_var_); 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PP_Var JSPipeEventEmitter::VarFromCStr(const char* string) { 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) assert(var_iface_); 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return var_iface_->VarFromUtf8(string, strlen(string)); 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void JSPipeEventEmitter::UpdateStatus_Locked() { 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t status = 0; 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!input_fifo_.IsEmpty()) 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) status |= POLLIN; 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetOSpace() > 0) 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) status |= POLLOUT; 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ClearEvents_Locked(~status); 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RaiseEvents_Locked(status); 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error JSPipeEventEmitter::Read_Locked(char* data, size_t len, int* out_bytes) { 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *out_bytes = input_fifo_.Read(data, len); 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (*out_bytes > 0) { 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_read_ += *out_bytes; 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Error err = SendAckMessage(bytes_read_); 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (err != 0) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ERROR("Sending ACK failed: %d\n", err.error); 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UpdateStatus_Locked(); 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error JSPipeEventEmitter::SendWriteMessage(const void* buf, size_t count) { 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) TRACE("SendWriteMessage [%" PRIuS "] total=%" PRIuS, count, bytes_sent_); 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!var_iface_ || !buffer_iface_) { 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Got NULL interface(s): %s%s", 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var_iface_ ? "" : "Var ", 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch buffer_iface_ ? "" : "ArrayBuffer"); 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EIO; 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Copy payload data in a new ArrayBuffer 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PP_Var buffer = buffer_iface_->Create(count); 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memcpy(buffer_iface_->Map(buffer), buf, count); 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_iface_->Unmap(buffer); 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Error rtn = SendMessageToJS(write_var_, buffer); 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(buffer); 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return rtn; 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error JSPipeEventEmitter::SetName(const char* name) { 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (var_iface_ == NULL) { 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // No error here: many of the tests trigger this message. 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_TRACE("Got NULL interface: Var"); 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EIO; 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // name can only be set once 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!name_.empty()) { 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Attempting to set name more than once."); 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EIO; 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // new name must not be empty 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!name || strlen(name) == 0) { 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Empty name is invalid."); 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EIO; 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TRACE("set name: %s", name); 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) name_ = name; 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pipe_name_var_ = VarFromCStr(name); 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Error JSPipeEventEmitter::SendMessageToJS(PP_Var operation, PP_Var payload) { 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ppapi_) { 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("ppapi_ is NULL."); 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EIO; 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!messaging_iface_ || !var_iface_ || !dict_iface_) { 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Got NULL interface(s): %s%s%s", 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch messaging_iface_ ? "" : "Messaging ", 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch dict_iface_ ? "" : "Dictionary ", 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var_iface_ ? "" : "Var"); 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return EIO; 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Create dict object which will be sent to JavaScript. 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PP_Var dict = dict_iface_->Create(); 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Set three keys in the dictionary: 'pipe', 'operation', and 'payload' 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dict_iface_->Set(dict, pipe_key_, pipe_name_var_); 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dict_iface_->Set(dict, operation_key_, operation); 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dict_iface_->Set(dict, payload_key_, payload); 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Send the dict via PostMessage 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) messaging_iface_->PostMessage(ppapi_->GetInstance(), dict); 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Release the dict 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(dict); 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error JSPipeEventEmitter::SendAckMessage(size_t byte_count) { 18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) TRACE("SendAckMessage %" PRIuS, byte_count); 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PP_Var payload; 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) payload.type = PP_VARTYPE_INT32; 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) payload.value.as_int = (int32_t)byte_count; 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return SendMessageToJS(ack_var_, payload); 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t JSPipeEventEmitter::HandleJSWrite(const char* data, size_t len) { 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t out_len = input_fifo_.Write(data, len); 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UpdateStatus_Locked(); 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return out_len; 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void JSPipeEventEmitter::HandleJSAck(size_t byte_count) { 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (byte_count > bytes_sent_) { 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Unexpected byte count: %" PRIuS, byte_count); 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_acked_ = byte_count; 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TRACE("HandleAck: %" SCNuS "/%" PRIuS, bytes_acked_, bytes_sent_); 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UpdateStatus_Locked(); 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error JSPipeEventEmitter::HandleJSWrite(struct PP_Var message) { 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TRACE("HandleJSWrite"); 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (message.type != PP_VARTYPE_ARRAY_BUFFER) { 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Expected ArrayBuffer but got %d.", message.type); 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EINVAL; 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t length; 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (buffer_iface_->ByteLength(message, &length) != PP_TRUE) { 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("ArrayBuffer.ByteLength returned PP_FALSE"); 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EINVAL; 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) char* buffer = (char*)buffer_iface_->Map(message); 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Write data to the input fifo 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t wrote = HandleJSWrite(buffer, length); 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_iface_->Unmap(message); 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (wrote != length) { 231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Only wrote %d of %d bytes to pipe", (int)wrote, (int)length); 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EIO; 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TRACE("done HandleWrite: %d", length); 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error JSPipeEventEmitter::HandleJSAck(PP_Var message) { 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (message.type != PP_VARTYPE_INT32) { 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Integer object expected but got %d.", message.type); 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EINVAL; 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) HandleJSAck(message.value.as_int); 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int JSPipeEventEmitter::VarStrcmp(PP_Var a, PP_Var b) { 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t length_a = 0; 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t length_b = 0; 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const char* cstring_a = var_iface_->VarToUtf8(a, &length_a); 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const char* cstring_b = var_iface_->VarToUtf8(a, &length_b); 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string string_a(cstring_a, length_a); 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string string_b(cstring_b, length_a); 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return strcmp(string_a.c_str(), string_b.c_str()); 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error JSPipeEventEmitter::HandleJSMessage(struct PP_Var message) { 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Error err = 0; 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!messaging_iface_ || !var_iface_ || !dict_iface_ || !buffer_iface_) { 260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Got NULL interface(s): %s%s%s%s", 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch messaging_iface_ ? "" : "Messaging ", 262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var_iface_ ? "" : "Var ", 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch dict_iface_ ? "" : "Dictionary ", 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch buffer_iface_ ? "" : "ArrayBuffer"); 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return ENOSYS; 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Verify that we have an array with size two. 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (message.type != PP_VARTYPE_DICTIONARY) { 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Expected Dictionary but got %d.", message.type); 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EINVAL; 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#ifndef NDEBUG 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PP_Var pipe_name_var = dict_iface_->Get(message, pipe_key_); 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (VarStrcmp(pipe_name_var, pipe_name_var_)) { 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Wrong pipe name."); 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return EINVAL; 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(pipe_name_var); 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PP_Var operation_var = dict_iface_->Get(message, operation_key_); 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (operation_var.type != PP_VARTYPE_STRING) { 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Expected String but got %d.", operation_var.type); 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) err = EINVAL; 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t length; 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const char* operation_string; 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) operation_string = var_iface_->VarToUtf8(operation_var, &length); 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string message_type(operation_string, length); 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TRACE("HandleJSMessage %s", message_type.c_str()); 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PP_Var payload = dict_iface_->Get(message, payload_key_); 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (message_type == kOperationNameWrite) { 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) err = HandleJSWrite(payload); 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (message_type == kOperationNameAck) { 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) err = HandleJSAck(payload); 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ERROR("Unknown message type: %s", message_type.c_str()); 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) err = EINVAL; 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(payload); 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var_iface_->Release(operation_var); 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return err; 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Error JSPipeEventEmitter::Write_Locked(const char* data, 31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t len, 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int* out_bytes) { 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetOSpace() == 0) { 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *out_bytes = 0; 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (len > GetOSpace()) 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) len = GetOSpace(); 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Limit the size of the data we send with PostMessage to kMaxPostMessageSize 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (len > kMaxPostMessageSize) 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) len = kMaxPostMessageSize; 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Error err = SendWriteMessage(data, len); 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (err != 0) 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return err; 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *out_bytes = len; 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_sent_ += len; 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UpdateStatus_Locked(); 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace nacl_io 336