bool Channel::CreatePipe(const IPC::ChannelHandle &channel_handle) { assert(INVALID_HANDLE_VALUE == pipe_); std::wstring pipe_name; // If we already have a valid pipe for channel just copy it. if (channel_handle.pipe.handle) { assert(channel_handle.name.empty()); pipe_name = L"Not Available"; // Just used for LOG // Check that the given pipe confirms to the specified mode. We can // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0. DWORD flags = 0; GetNamedPipeInfo(channel_handle.pipe.handle, &flags, NULL, NULL, NULL); assert(!(flags & PIPE_TYPE_MESSAGE)); if (!DuplicateHandle(GetCurrentProcess(), channel_handle.pipe.handle, GetCurrentProcess(), &pipe_, 0, FALSE, DUPLICATE_SAME_ACCESS)) { //LOG(WARNING) << "DuplicateHandle failed. Error :" << GetLastError(); return false; } } else { assert(!channel_handle.pipe.handle); pipe_name = PipeName(channel_handle.name, &client_secret_); //Ïȳ¢ÊÔ´´½¨ const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE; validate_client_ = !!client_secret_; pipe_ = CreateNamedPipeW(pipe_name.c_str(), open_mode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, kReadBufferSize, kReadBufferSize, 5000, NULL); if (pipe_ == INVALID_HANDLE_VALUE) { pipe_ = CreateFileW(pipe_name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | FILE_FLAG_OVERLAPPED, NULL); waiting_connect_ = false; } } if (pipe_ == INVALID_HANDLE_VALUE) { // If this process is being closed, the pipe may be gone already. //LOG(WARNING) << "Unable to create pipe \"" << pipe_name << // "\" in " << (mode & MODE_SERVER_FLAG ? "server" : "client") // << " mode. Error :" << GetLastError(); return false; } // Create the Hello message to be sent when Connect is called Message* m = new Message(MSG_ROUTING_NONE, HELLO_MESSAGE_TYPE, IPC::Message::PRIORITY_NORMAL); m->AddRef(); // Don't send the secret to the untrusted process, and don't send a secret // if the value is zero (for IPC backwards compatability). int32 secret = validate_client_ ? 0 : client_secret_; if (!m->WriteInt(GetCurrentProcessId()) || (secret && !m->WriteUInt32(secret))) { CloseHandle(pipe_); pipe_ = INVALID_HANDLE_VALUE; m->Release(); return false; } output_queue_.push(m); return true; }
Message* LocalTransport::CreateMessage(uint32_t protocol, uint32_t code) { Message* message = 0; std::map<uint32_t, std::list<Message*> >::iterator it; it = mMessagePool.find(protocol); if (it != mMessagePool.end()) { if (it->second.size()) { // free message in pool, use that message = it->second.front(); it->second.pop_front(); } } else { // initialize a list mMessagePool[protocol].clear(); } if(message == 0) { // no more messages, create a new one message = mHandlers.Create(protocol, code); message->AddToPool(*this); } message->AddRef(); return message; }
bool ChannelReader::DispatchInputData(const char* input_data, int input_data_len) { const char* p; const char* end; // Possibly combine with the overflow buffer to make a larger buffer. if (input_overflow_buf_.empty()) { p = input_data; end = input_data + input_data_len; } else { if (input_overflow_buf_.size() + input_data_len > Channel::kMaximumMessageSize) { input_overflow_buf_.clear(); //assert(ERROR) << "IPC message is too big"; return false; } input_overflow_buf_.append(input_data, input_data_len); p = input_overflow_buf_.data(); end = p + input_overflow_buf_.size(); } // Dispatch all complete messages in the data buffer. while (p < end) { const char* message_tail = Message::FindNext(p, end); if (message_tail) { int len = static_cast<int>(message_tail - p); Message* m = new Message(p, len); m->AddRef(); if (!WillDispatchInputMessage(m)) return false; #ifdef IPC_MESSAGE_LOG_ENABLED Logging* logger = Logging::GetInstance(); std::string name; logger->GetMessageText(m.type(), &name, &m, NULL); TRACE_EVENT1("ipc", "ChannelReader::DispatchInputData", "name", name); #else //TRACE_EVENT2("ipc", "ChannelReader::DispatchInputData", // "class", IPC_MESSAGE_ID_CLASS(m.type()), // "line", IPC_MESSAGE_ID_LINE(m.type())); #endif //m.TraceMessageEnd(); if (IsHelloMessage(m)) HandleHelloMessage(m); else listener_->OnMessageReceived(m); p = message_tail; } else { // Last message is partial. break; } } // Save any partial data in the overflow buffer. input_overflow_buf_.assign(p, end - p); if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) return false; return true; }