blob: 31f346b4fe8f652485651e6a355af8739f794945 [file] [log] [blame]
// Copyright 2023 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "ipc_utils.h"
#include "util.h"
#ifndef _WIN32
#include <sys/signal.h>
#include <unistd.h>
#endif
RemoteArguments::RemoteArguments(int argc, char** argv) {
if (argc > 0) {
args_.reserve(static_cast<size_t>(argc));
for (int n = 0; n < argc; ++n) {
args_.push_back(argv[n]);
}
}
}
void RemoteArguments::Reset(const std::vector<std::string>& args) {
args_ = args;
}
char** RemoteArguments::argv() const {
if (args_.empty())
return nullptr;
argv_.clear();
argv_.reserve(args_.size());
for (const auto& arg : args_)
argv_.push_back(const_cast<char*>(arg.data()));
return argv_.data();
}
void RemoteArguments::InsertAt(size_t pos, std::string arg) {
if (pos > args_.size())
pos = args_.size();
args_.insert(args_.begin() + pos, std::move(arg));
}
template <>
bool RemoteWrite<std::string>(const std::string& obj, IpcHandle& con,
std::string* error) {
size_t size = obj.size();
return RemoteWrite(size, con, error) &&
con.WriteFull(obj.data(), size, error);
}
template <>
bool RemoteWrite<RemoteArguments>(const RemoteArguments& obj, IpcHandle& con,
std::string* error) {
size_t size = obj.args().size();
if (!RemoteWrite(size, con, error))
return false;
for (const auto& arg : obj.args()) {
if (!RemoteWrite(arg, con, error))
return false;
}
return true;
}
template <>
bool RemoteRead<std::string>(std::string& obj, IpcHandle& con,
std::string* error) {
size_t size;
if (!RemoteRead(size, con, error))
return false;
obj.resize(size);
if (!size)
return true;
return con.ReadFull(const_cast<char*>(obj.data()), size, error);
}
template <>
bool RemoteRead<RemoteArguments>(RemoteArguments& obj, IpcHandle& con,
std::string* error) {
size_t size;
if (!RemoteRead(size, con, error))
return false;
std::vector<std::string> vec;
vec.resize(size);
for (auto& arg : vec) {
if (!RemoteRead(arg, con, error))
return false;
}
obj.Reset(std::move(vec));
return true;
}
void WireEncoder::Write(const void* buffer, size_t size) {
result_.append(static_cast<const char*>(buffer), size);
}
void WireEncoder::Write(const std::string& str) {
Write(static_cast<uint32_t>(str.size()));
Write(str.data(), str.size());
}
WireDecoder::WireDecoder(const void* buffer, size_t size)
: p_(static_cast<const char*>(buffer)), end_(p_ + size) {}
WireDecoder::WireDecoder(const std::string& str)
: WireDecoder(str.data(), str.size()) {}
void WireDecoder::Read(void* buffer, size_t size) {
if (p_ + size <= end_) {
::memcpy(buffer, p_, size);
p_ += size;
} else {
// To avoid relying on un-initialized memory at runtime
// if the client fails to check for errors.
::memset(buffer, '\0', size);
p_ = end_;
has_error_ = true;
}
}
void WireDecoder::Read(std::string& str) {
uint32_t size = 0;
Read(size);
std::string result;
if (size) {
result.resize(size);
Read(const_cast<char*>(result.data()), result.size());
}
str = std::move(result);
}
#ifndef _WIN32
SigPipeBlocker::SigPipeBlocker() {
struct sigaction action = {};
action.sa_handler = SIG_IGN;
if (sigaction(SIGPIPE, &action, &prev_action_) < 0)
ErrnoFatal("sigaction");
}
SigPipeBlocker::~SigPipeBlocker() {
if (sigaction(SIGPIPE, &prev_action_, nullptr) < 0)
ErrnoFatal("sigaction");
}
#endif // !_WIN32