blob: 8e3ecf0ba3c9503778becb7389e181738c5ebfdc [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.
#ifndef NINJA_SRC_IPC_UTILS_H_
#define NINJA_SRC_IPC_UTILS_H_
#include <string>
#include <vector>
#include "ipc_handle.h"
/// Convenience wrapper for an std::vector<std::string> that can save
/// the content of an (argc, argv) list of command-line arguments.
struct RemoteArguments {
RemoteArguments() = default;
RemoteArguments(int argc, char** argv);
void Reset(const std::vector<std::string>& args);
const std::vector<std::string>& args() const { return args_; }
/// Export instance as (argc, argv) pair.
int argc() const { return static_cast<int>(args_.size()); }
char** argv() const;
void InsertAt(size_t pos, std::string arg);
protected:
std::vector<std::string> args_;
mutable std::vector<char*> argv_;
};
/// Helper template to write values through an IpcHandle.
template <typename T>
bool RemoteWrite(const T& obj, IpcHandle& con, std::string* error) {
return con.WriteFull(&obj, sizeof(obj), error);
}
template <>
bool RemoteWrite<std::string>(const std::string& str, IpcHandle& con,
std::string* error);
template <>
bool RemoteWrite<RemoteArguments>(const RemoteArguments& args, IpcHandle& con,
std::string* error);
/// Helper template to read values through an IpcHandle
template <typename T>
bool RemoteRead(T& obj, IpcHandle& con, std::string* error) {
return con.ReadFull(&obj, sizeof(obj), error);
}
template <>
bool RemoteRead<std::string>(std::string& str, IpcHandle& con,
std::string* error);
template <>
bool RemoteRead<RemoteArguments>(RemoteArguments& args, IpcHandle& con,
std::string* error);
/// Simple class to encode values into a byte stream that
/// can be sent through IPC to another process. Usage is:
///
/// 1) Create instance.
/// 2) Call one of the Write() methods any number of times.
/// 3) Call GetResult() to retrieve the result as an std::string.
///
struct WireEncoder {
void Write(const void* buffer, size_t size);
void Write(const std::string& str);
template <typename T>
void Write(const T& v) {
Write(&v, sizeof(v));
}
std::string TakeResult() { return std::move(result_); }
std::string result_;
};
/// Decode a string of bytes received through IPC into values.
/// Usage is:
/// 1) Create instance passing the input stream as an std::string
/// 2) Call Read() methods as many times as necessary.
/// 3) Check has_error() after each Read(), or after a series of
/// Read() calls to see if there was any error (i.e. read overflow).
///
struct WireDecoder {
WireDecoder(const void* buffer, size_t size);
explicit WireDecoder(const std::string& str);
void Read(void* buffer, size_t size);
void Read(std::string& str);
template <typename T>
void Read(T& v) {
Read(&v, sizeof(T));
}
bool has_error() const { return has_error_; }
const char* p_ = nullptr;
const char* end_ = nullptr;
bool has_error_ = false;
};
#ifndef _WIN32
/// Convenience class to ignore SIGPIPE signals when
/// doing inter-process writes through a pipe.
class SigPipeBlocker {
public:
SigPipeBlocker();
~SigPipeBlocker();
private:
struct sigaction prev_action_;
};
#endif // !_WIN32
#endif // NINJA_SRC_IPC_UTILS_H_