Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/posix/can_lower_nice_to.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
// Not defined on AIX by default.
|
||||
#if defined(OS_AIX)
|
||||
#if defined(RLIMIT_NICE)
|
||||
#error Assumption about OS_AIX is incorrect
|
||||
#endif
|
||||
#define RLIMIT_NICE 20
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
||||
bool CanLowerNiceTo(int nice_value) {
|
||||
// On a POSIX system, the nice value of a thread can be lowered 1. by the root
|
||||
// user, 2. by a user with the CAP_SYS_NICE permission or 3. by any user if
|
||||
// the target value is within the range allowed by RLIMIT_NICE.
|
||||
|
||||
// 1. Check for root user.
|
||||
if (geteuid() == 0)
|
||||
return true;
|
||||
|
||||
// 2. Skip checking the CAP_SYS_NICE permission because it would require
|
||||
// libcap.so.
|
||||
|
||||
// 3. Check whether the target value is within the range allowed by
|
||||
// RLIMIT_NICE.
|
||||
//
|
||||
// NZERO should be defined in <limits.h> per POSIX, and should be at least 20.
|
||||
// (NZERO-1) is the highest possible niceness value (i.e. lowest priority).
|
||||
// Most platforms use NZERO=20.
|
||||
//
|
||||
// RLIMIT_NICE tells us how much we can reduce niceness (increase priority) if
|
||||
// we start at NZERO. For example, if NZERO is 20 and the rlimit is 30, we can
|
||||
// lower niceness anywhere within the [-10, 19] range (20 - 30 = -10).
|
||||
//
|
||||
// So, we are allowed to reduce niceness to a minimum of NZERO - rlimit:
|
||||
struct rlimit rlim;
|
||||
if (getrlimit(RLIMIT_NICE, &rlim) != 0)
|
||||
return false;
|
||||
const int lowest_nice_allowed = NZERO - static_cast<int>(rlim.rlim_cur);
|
||||
|
||||
// And lowering niceness to |nice_value| is allowed if it is greater than or
|
||||
// equal to the limit:
|
||||
return nice_value >= lowest_nice_allowed;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
19
TMessagesProj/jni/voip/webrtc/base/posix/can_lower_nice_to.h
Normal file
19
TMessagesProj/jni/voip/webrtc/base/posix/can_lower_nice_to.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_POSIX_CAN_LOWER_NICE_TO_H_
|
||||
#define BASE_POSIX_CAN_LOWER_NICE_TO_H_
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
||||
// Returns true if lowering the nice value of a process or thread to
|
||||
// |nice_value| using setpriority() or nice() should succeed. Note: A lower nice
|
||||
// value means a higher priority.
|
||||
bool CanLowerNiceTo(int nice_value);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_POSIX_CAN_LOWER_NICE_TO_H_
|
||||
68
TMessagesProj/jni/voip/webrtc/base/posix/eintr_wrapper.h
Normal file
68
TMessagesProj/jni/voip/webrtc/base/posix/eintr_wrapper.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This provides a wrapper around system calls which may be interrupted by a
|
||||
// signal and return EINTR. See man 7 signal.
|
||||
// To prevent long-lasting loops (which would likely be a bug, such as a signal
|
||||
// that should be masked) to go unnoticed, there is a limit after which the
|
||||
// caller will nonetheless see an EINTR in Debug builds.
|
||||
//
|
||||
// On Windows and Fuchsia, this wrapper macro does nothing because there are no
|
||||
// signals.
|
||||
//
|
||||
// Don't wrap close calls in HANDLE_EINTR. Use IGNORE_EINTR if the return
|
||||
// value of close is significant. See http://crbug.com/269623.
|
||||
|
||||
#ifndef BASE_POSIX_EINTR_WRAPPER_H_
|
||||
#define BASE_POSIX_EINTR_WRAPPER_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(NDEBUG)
|
||||
|
||||
#define HANDLE_EINTR(x) ({ \
|
||||
decltype(x) eintr_wrapper_result; \
|
||||
do { \
|
||||
eintr_wrapper_result = (x); \
|
||||
} while (eintr_wrapper_result == -1 && errno == EINTR); \
|
||||
eintr_wrapper_result; \
|
||||
})
|
||||
|
||||
#else
|
||||
|
||||
#define HANDLE_EINTR(x) ({ \
|
||||
int eintr_wrapper_counter = 0; \
|
||||
decltype(x) eintr_wrapper_result; \
|
||||
do { \
|
||||
eintr_wrapper_result = (x); \
|
||||
} while (eintr_wrapper_result == -1 && errno == EINTR && \
|
||||
eintr_wrapper_counter++ < 100); \
|
||||
eintr_wrapper_result; \
|
||||
})
|
||||
|
||||
#endif // NDEBUG
|
||||
|
||||
#define IGNORE_EINTR(x) ({ \
|
||||
decltype(x) eintr_wrapper_result; \
|
||||
do { \
|
||||
eintr_wrapper_result = (x); \
|
||||
if (eintr_wrapper_result == -1 && errno == EINTR) { \
|
||||
eintr_wrapper_result = 0; \
|
||||
} \
|
||||
} while (0); \
|
||||
eintr_wrapper_result; \
|
||||
})
|
||||
|
||||
#else // !OS_POSIX
|
||||
|
||||
#define HANDLE_EINTR(x) (x)
|
||||
#define IGNORE_EINTR(x) (x)
|
||||
|
||||
#endif // !OS_POSIX
|
||||
|
||||
#endif // BASE_POSIX_EINTR_WRAPPER_H_
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/posix/file_descriptor_shuffle.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <ostream>
|
||||
|
||||
#include "base/posix/eintr_wrapper.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
bool PerformInjectiveMultimapDestructive(
|
||||
InjectiveMultimap* m, InjectionDelegate* delegate) {
|
||||
static const size_t kMaxExtraFDs = 16;
|
||||
int extra_fds[kMaxExtraFDs];
|
||||
unsigned next_extra_fd = 0;
|
||||
|
||||
// DANGER: this function must not allocate or lock.
|
||||
// Cannot use STL iterators here, since debug iterators use locks.
|
||||
|
||||
for (size_t i_index = 0; i_index < m->size(); ++i_index) {
|
||||
InjectiveMultimap::value_type* i = &(*m)[i_index];
|
||||
int temp_fd = -1;
|
||||
|
||||
// We DCHECK the injectiveness of the mapping.
|
||||
for (size_t j_index = i_index + 1; j_index < m->size(); ++j_index) {
|
||||
InjectiveMultimap::value_type* j = &(*m)[j_index];
|
||||
DCHECK(i->dest != j->dest) << "Both fd " << i->source
|
||||
<< " and " << j->source << " map to " << i->dest;
|
||||
}
|
||||
|
||||
const bool is_identity = i->source == i->dest;
|
||||
|
||||
for (size_t j_index = i_index + 1; j_index < m->size(); ++j_index) {
|
||||
InjectiveMultimap::value_type* j = &(*m)[j_index];
|
||||
if (!is_identity && i->dest == j->source) {
|
||||
if (temp_fd == -1) {
|
||||
if (!delegate->Duplicate(&temp_fd, i->dest))
|
||||
return false;
|
||||
if (next_extra_fd < kMaxExtraFDs) {
|
||||
extra_fds[next_extra_fd++] = temp_fd;
|
||||
} else {
|
||||
RAW_LOG(ERROR, "PerformInjectiveMultimapDestructive overflowed "
|
||||
"extra_fds. Leaking file descriptors!");
|
||||
}
|
||||
}
|
||||
|
||||
j->source = temp_fd;
|
||||
j->close = false;
|
||||
}
|
||||
|
||||
if (i->close && i->source == j->dest)
|
||||
i->close = false;
|
||||
|
||||
if (i->close && i->source == j->source) {
|
||||
i->close = false;
|
||||
j->close = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_identity) {
|
||||
if (!delegate->Move(i->source, i->dest))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_identity && i->close)
|
||||
delegate->Close(i->source);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < next_extra_fd; i++)
|
||||
delegate->Close(extra_fds[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PerformInjectiveMultimap(const InjectiveMultimap& m_in,
|
||||
InjectionDelegate* delegate) {
|
||||
InjectiveMultimap m(m_in);
|
||||
return PerformInjectiveMultimapDestructive(&m, delegate);
|
||||
}
|
||||
|
||||
bool FileDescriptorTableInjection::Duplicate(int* result, int fd) {
|
||||
*result = HANDLE_EINTR(dup(fd));
|
||||
return *result >= 0;
|
||||
}
|
||||
|
||||
bool FileDescriptorTableInjection::Move(int src, int dest) {
|
||||
return HANDLE_EINTR(dup2(src, dest)) != -1;
|
||||
}
|
||||
|
||||
void FileDescriptorTableInjection::Close(int fd) {
|
||||
int ret = IGNORE_EINTR(close(fd));
|
||||
DPCHECK(ret == 0);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_POSIX_FILE_DESCRIPTOR_SHUFFLE_H_
|
||||
#define BASE_POSIX_FILE_DESCRIPTOR_SHUFFLE_H_
|
||||
|
||||
// This code exists to shuffle file descriptors, which is commonly needed when
|
||||
// forking subprocesses. The naive approach (just call dup2 to set up the
|
||||
// desired descriptors) is very simple, but wrong: it won't handle edge cases
|
||||
// (like mapping 0 -> 1, 1 -> 0) correctly.
|
||||
//
|
||||
// In order to unittest this code, it's broken into the abstract action (an
|
||||
// injective multimap) and the concrete code for dealing with file descriptors.
|
||||
// Users should use the code like this:
|
||||
// base::InjectiveMultimap file_descriptor_map;
|
||||
// file_descriptor_map.push_back(base::InjectionArc(devnull, 0, true));
|
||||
// file_descriptor_map.push_back(base::InjectionArc(devnull, 2, true));
|
||||
// file_descriptor_map.push_back(base::InjectionArc(pipe[1], 1, true));
|
||||
// base::ShuffleFileDescriptors(file_descriptor_map);
|
||||
//
|
||||
// and trust the the Right Thing will get done.
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/compiler_specific.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// A Delegate which performs the actions required to perform an injective
|
||||
// multimapping in place.
|
||||
class InjectionDelegate {
|
||||
public:
|
||||
// Duplicate |fd|, an element of the domain, and write a fresh element of the
|
||||
// domain into |result|. Returns true iff successful.
|
||||
virtual bool Duplicate(int* result, int fd) = 0;
|
||||
// Destructively move |src| to |dest|, overwriting |dest|. Returns true iff
|
||||
// successful.
|
||||
virtual bool Move(int src, int dest) = 0;
|
||||
// Delete an element of the domain.
|
||||
virtual void Close(int fd) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~InjectionDelegate() = default;
|
||||
};
|
||||
|
||||
// An implementation of the InjectionDelegate interface using the file
|
||||
// descriptor table of the current process as the domain.
|
||||
class BASE_EXPORT FileDescriptorTableInjection : public InjectionDelegate {
|
||||
bool Duplicate(int* result, int fd) override;
|
||||
bool Move(int src, int dest) override;
|
||||
void Close(int fd) override;
|
||||
};
|
||||
|
||||
// A single arc of the directed graph which describes an injective multimapping.
|
||||
struct InjectionArc {
|
||||
InjectionArc(int in_source, int in_dest, bool in_close)
|
||||
: source(in_source),
|
||||
dest(in_dest),
|
||||
close(in_close) {
|
||||
}
|
||||
|
||||
int source;
|
||||
int dest;
|
||||
bool close; // if true, delete the source element after performing the
|
||||
// mapping.
|
||||
};
|
||||
|
||||
typedef std::vector<InjectionArc> InjectiveMultimap;
|
||||
|
||||
BASE_EXPORT bool PerformInjectiveMultimap(const InjectiveMultimap& map,
|
||||
InjectionDelegate* delegate);
|
||||
|
||||
BASE_EXPORT bool PerformInjectiveMultimapDestructive(
|
||||
InjectiveMultimap* map,
|
||||
InjectionDelegate* delegate);
|
||||
|
||||
// This function will not call malloc but will mutate |map|
|
||||
static inline bool ShuffleFileDescriptors(InjectiveMultimap* map) {
|
||||
FileDescriptorTableInjection delegate;
|
||||
return PerformInjectiveMultimapDestructive(map, &delegate);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_POSIX_FILE_DESCRIPTOR_SHUFFLE_H_
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/posix/global_descriptors.h"
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
GlobalDescriptors::Descriptor::Descriptor(Key key, int fd)
|
||||
: key(key), fd(fd), region(base::MemoryMappedFile::Region::kWholeFile) {
|
||||
}
|
||||
|
||||
GlobalDescriptors::Descriptor::Descriptor(Key key,
|
||||
int fd,
|
||||
base::MemoryMappedFile::Region region)
|
||||
: key(key), fd(fd), region(region) {
|
||||
}
|
||||
|
||||
// static
|
||||
GlobalDescriptors* GlobalDescriptors::GetInstance() {
|
||||
typedef Singleton<base::GlobalDescriptors,
|
||||
LeakySingletonTraits<base::GlobalDescriptors> >
|
||||
GlobalDescriptorsSingleton;
|
||||
return GlobalDescriptorsSingleton::get();
|
||||
}
|
||||
|
||||
int GlobalDescriptors::Get(Key key) const {
|
||||
const int ret = MaybeGet(key);
|
||||
|
||||
if (ret == -1)
|
||||
DLOG(DCHECK) << "Unknown global descriptor: " << key;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GlobalDescriptors::MaybeGet(Key key) const {
|
||||
for (const auto& i : descriptors_) {
|
||||
if (i.key == key)
|
||||
return i.fd;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
base::ScopedFD GlobalDescriptors::TakeFD(
|
||||
Key key,
|
||||
base::MemoryMappedFile::Region* region) {
|
||||
base::ScopedFD fd;
|
||||
for (auto i = descriptors_.begin(); i != descriptors_.end(); ++i) {
|
||||
if (i->key == key) {
|
||||
*region = i->region;
|
||||
fd.reset(i->fd);
|
||||
descriptors_.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void GlobalDescriptors::Set(Key key, int fd) {
|
||||
Set(key, fd, base::MemoryMappedFile::Region::kWholeFile);
|
||||
}
|
||||
|
||||
void GlobalDescriptors::Set(Key key,
|
||||
int fd,
|
||||
base::MemoryMappedFile::Region region) {
|
||||
for (auto& i : descriptors_) {
|
||||
if (i.key == key) {
|
||||
i.fd = fd;
|
||||
i.region = region;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
descriptors_.push_back(Descriptor(key, fd, region));
|
||||
}
|
||||
|
||||
base::MemoryMappedFile::Region GlobalDescriptors::GetRegion(Key key) const {
|
||||
for (const auto& i : descriptors_) {
|
||||
if (i.key == key)
|
||||
return i.region;
|
||||
}
|
||||
DLOG(DCHECK) << "Unknown global descriptor: " << key;
|
||||
return base::MemoryMappedFile::Region::kWholeFile;
|
||||
}
|
||||
|
||||
void GlobalDescriptors::Reset(const Mapping& mapping) {
|
||||
descriptors_ = mapping;
|
||||
}
|
||||
|
||||
GlobalDescriptors::GlobalDescriptors() = default;
|
||||
|
||||
GlobalDescriptors::~GlobalDescriptors() = default;
|
||||
|
||||
} // namespace base
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_POSIX_GLOBAL_DESCRIPTORS_H_
|
||||
#define BASE_POSIX_GLOBAL_DESCRIPTORS_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base/files/memory_mapped_file.h"
|
||||
#include "base/files/scoped_file.h"
|
||||
#include "base/memory/singleton.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// It's common practice to install file descriptors into well known slot
|
||||
// numbers before execing a child; stdin, stdout and stderr are ubiqutous
|
||||
// examples.
|
||||
//
|
||||
// However, when using a zygote model, this becomes troublesome. Since the
|
||||
// descriptors which need to be in these slots generally aren't known, any code
|
||||
// could open a resource and take one of the reserved descriptors. Simply
|
||||
// overwriting the slot isn't a viable solution.
|
||||
//
|
||||
// We could try to fill the reserved slots as soon as possible, but this is a
|
||||
// fragile solution since global constructors etc are able to open files.
|
||||
//
|
||||
// Instead, we retreat from the idea of installing descriptors in specific
|
||||
// slots and add a layer of indirection in the form of this singleton object.
|
||||
// It maps from an abstract key to a descriptor. If independent modules each
|
||||
// need to define keys, then values should be chosen randomly so as not to
|
||||
// collide.
|
||||
//
|
||||
// Note that this class is deprecated and passing file descriptor should ideally
|
||||
// be done through the command line and using FileDescriptorStore.
|
||||
// See https://crbugs.com/detail?id=692619
|
||||
class BASE_EXPORT GlobalDescriptors {
|
||||
public:
|
||||
typedef uint32_t Key;
|
||||
struct Descriptor {
|
||||
Descriptor(Key key, int fd);
|
||||
Descriptor(Key key, int fd, base::MemoryMappedFile::Region region);
|
||||
|
||||
// Globally unique key.
|
||||
Key key;
|
||||
// Actual FD.
|
||||
int fd;
|
||||
// Optional region, defaults to kWholeFile.
|
||||
base::MemoryMappedFile::Region region;
|
||||
};
|
||||
typedef std::vector<Descriptor> Mapping;
|
||||
|
||||
// Often we want a canonical descriptor for a given Key. In this case, we add
|
||||
// the following constant to the key value:
|
||||
static const int kBaseDescriptor = 3; // 0, 1, 2 are already taken.
|
||||
|
||||
// Return the singleton instance of GlobalDescriptors.
|
||||
static GlobalDescriptors* GetInstance();
|
||||
|
||||
// Get a descriptor given a key. It is a fatal error if the key is not known.
|
||||
int Get(Key key) const;
|
||||
|
||||
// Get a descriptor given a key. Returns -1 on error.
|
||||
int MaybeGet(Key key) const;
|
||||
|
||||
// Returns a descriptor given a key and removes it from this class mappings.
|
||||
// Also populates |region|.
|
||||
// It is a fatal error if the key is not known.
|
||||
base::ScopedFD TakeFD(Key key, base::MemoryMappedFile::Region* region);
|
||||
|
||||
// Get a region given a key. It is a fatal error if the key is not known.
|
||||
base::MemoryMappedFile::Region GetRegion(Key key) const;
|
||||
|
||||
// Set the descriptor for the given |key|. This sets the region associated
|
||||
// with |key| to kWholeFile.
|
||||
void Set(Key key, int fd);
|
||||
|
||||
// Set the descriptor and |region| for the given |key|.
|
||||
void Set(Key key, int fd, base::MemoryMappedFile::Region region);
|
||||
|
||||
void Reset(const Mapping& mapping);
|
||||
|
||||
private:
|
||||
friend struct DefaultSingletonTraits<GlobalDescriptors>;
|
||||
GlobalDescriptors();
|
||||
~GlobalDescriptors();
|
||||
|
||||
Mapping descriptors_;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_POSIX_GLOBAL_DESCRIPTORS_H_
|
||||
128
TMessagesProj/jni/voip/webrtc/base/posix/safe_strerror.cc
Normal file
128
TMessagesProj/jni/voip/webrtc/base/posix/safe_strerror.cc
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// Post-L versions of bionic define the GNU-specific strerror_r if _GNU_SOURCE
|
||||
// is defined, but the symbol is renamed to __gnu_strerror_r which only exists
|
||||
// on those later versions. To preserve ABI compatibility with older versions,
|
||||
// undefine _GNU_SOURCE and use the POSIX version.
|
||||
#undef _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include "base/posix/safe_strerror.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
#if defined(__GLIBC__) || defined(OS_NACL)
|
||||
#define USE_HISTORICAL_STRERRO_R 1
|
||||
#else
|
||||
#define USE_HISTORICAL_STRERRO_R 0
|
||||
#endif
|
||||
|
||||
#if USE_HISTORICAL_STRERRO_R && defined(__GNUC__)
|
||||
// GCC will complain about the unused second wrap function unless we tell it
|
||||
// that we meant for them to be potentially unused, which is exactly what this
|
||||
// attribute is for.
|
||||
#define POSSIBLY_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define POSSIBLY_UNUSED
|
||||
#endif
|
||||
|
||||
#if USE_HISTORICAL_STRERRO_R
|
||||
// glibc has two strerror_r functions: a historical GNU-specific one that
|
||||
// returns type char *, and a POSIX.1-2001 compliant one available since 2.3.4
|
||||
// that returns int. This wraps the GNU-specific one.
|
||||
static void POSSIBLY_UNUSED wrap_posix_strerror_r(
|
||||
char *(*strerror_r_ptr)(int, char *, size_t),
|
||||
int err,
|
||||
char *buf,
|
||||
size_t len) {
|
||||
// GNU version.
|
||||
char *rc = (*strerror_r_ptr)(err, buf, len);
|
||||
if (rc != buf) {
|
||||
// glibc did not use buf and returned a static string instead. Copy it
|
||||
// into buf.
|
||||
buf[0] = '\0';
|
||||
strncat(buf, rc, len - 1);
|
||||
}
|
||||
// The GNU version never fails. Unknown errors get an "unknown error" message.
|
||||
// The result is always null terminated.
|
||||
}
|
||||
#endif // USE_HISTORICAL_STRERRO_R
|
||||
|
||||
// Wrapper for strerror_r functions that implement the POSIX interface. POSIX
|
||||
// does not define the behaviour for some of the edge cases, so we wrap it to
|
||||
// guarantee that they are handled. This is compiled on all POSIX platforms, but
|
||||
// it will only be used on Linux if the POSIX strerror_r implementation is
|
||||
// being used (see below).
|
||||
static void POSSIBLY_UNUSED wrap_posix_strerror_r(
|
||||
int (*strerror_r_ptr)(int, char *, size_t),
|
||||
int err,
|
||||
char *buf,
|
||||
size_t len) {
|
||||
int old_errno = errno;
|
||||
// Have to cast since otherwise we get an error if this is the GNU version
|
||||
// (but in such a scenario this function is never called). Sadly we can't use
|
||||
// C++-style casts because the appropriate one is reinterpret_cast but it's
|
||||
// considered illegal to reinterpret_cast a type to itself, so we get an
|
||||
// error in the opposite case.
|
||||
int result = (*strerror_r_ptr)(err, buf, len);
|
||||
if (result == 0) {
|
||||
// POSIX is vague about whether the string will be terminated, although
|
||||
// it indirectly implies that typically ERANGE will be returned, instead
|
||||
// of truncating the string. We play it safe by always terminating the
|
||||
// string explicitly.
|
||||
buf[len - 1] = '\0';
|
||||
} else {
|
||||
// Error. POSIX is vague about whether the return value is itself a system
|
||||
// error code or something else. On Linux currently it is -1 and errno is
|
||||
// set. On BSD-derived systems it is a system error and errno is unchanged.
|
||||
// We try and detect which case it is so as to put as much useful info as
|
||||
// we can into our message.
|
||||
int strerror_error; // The error encountered in strerror
|
||||
int new_errno = errno;
|
||||
if (new_errno != old_errno) {
|
||||
// errno was changed, so probably the return value is just -1 or something
|
||||
// else that doesn't provide any info, and errno is the error.
|
||||
strerror_error = new_errno;
|
||||
} else {
|
||||
// Either the error from strerror_r was the same as the previous value, or
|
||||
// errno wasn't used. Assume the latter.
|
||||
strerror_error = result;
|
||||
}
|
||||
// snprintf truncates and always null-terminates.
|
||||
snprintf(buf,
|
||||
len,
|
||||
"Error %d while retrieving error %d",
|
||||
strerror_error,
|
||||
err);
|
||||
}
|
||||
errno = old_errno;
|
||||
}
|
||||
|
||||
void safe_strerror_r(int err, char *buf, size_t len) {
|
||||
if (buf == nullptr || len <= 0) {
|
||||
return;
|
||||
}
|
||||
// If using glibc (i.e., Linux), the compiler will automatically select the
|
||||
// appropriate overloaded function based on the function type of strerror_r.
|
||||
// The other one will be elided from the translation unit since both are
|
||||
// static.
|
||||
wrap_posix_strerror_r(&strerror_r, err, buf, len);
|
||||
}
|
||||
|
||||
std::string safe_strerror(int err) {
|
||||
const int buffer_size = 256;
|
||||
char buf[buffer_size];
|
||||
safe_strerror_r(err, buf, sizeof(buf));
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
44
TMessagesProj/jni/voip/webrtc/base/posix/safe_strerror.h
Normal file
44
TMessagesProj/jni/voip/webrtc/base/posix/safe_strerror.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_POSIX_SAFE_STRERROR_H_
|
||||
#define BASE_POSIX_SAFE_STRERROR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// BEFORE using anything from this file, first look at PLOG and friends in
|
||||
// logging.h and use them instead if applicable.
|
||||
//
|
||||
// This file declares safe, portable alternatives to the POSIX strerror()
|
||||
// function. strerror() is inherently unsafe in multi-threaded apps and should
|
||||
// never be used. Doing so can cause crashes. Additionally, the thread-safe
|
||||
// alternative strerror_r varies in semantics across platforms. Use these
|
||||
// functions instead.
|
||||
|
||||
// Thread-safe strerror function with dependable semantics that never fails.
|
||||
// It will write the string form of error "err" to buffer buf of length len.
|
||||
// If there is an error calling the OS's strerror_r() function then a message to
|
||||
// that effect will be printed into buf, truncating if necessary. The final
|
||||
// result is always null-terminated. The value of errno is never changed.
|
||||
//
|
||||
// Use this instead of strerror_r().
|
||||
BASE_EXPORT void safe_strerror_r(int err, char *buf, size_t len);
|
||||
|
||||
// Calls safe_strerror_r with a buffer of suitable size and returns the result
|
||||
// in a C++ string.
|
||||
//
|
||||
// Use this instead of strerror(). Note though that safe_strerror_r will be
|
||||
// more robust in the case of heap corruption errors, since it doesn't need to
|
||||
// allocate a string.
|
||||
BASE_EXPORT std::string safe_strerror(int err);
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_POSIX_SAFE_STRERROR_H_
|
||||
288
TMessagesProj/jni/voip/webrtc/base/posix/unix_domain_socket.cc
Normal file
288
TMessagesProj/jni/voip/webrtc/base/posix/unix_domain_socket.cc
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/posix/unix_domain_socket.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#if !defined(OS_NACL_NONSFI)
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/files/scoped_file.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/pickle.h"
|
||||
#include "base/posix/eintr_wrapper.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if !defined(OS_NACL_NONSFI)
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
|
||||
const size_t UnixDomainSocket::kMaxFileDescriptors = 16;
|
||||
|
||||
#if !defined(OS_NACL_NONSFI)
|
||||
bool CreateSocketPair(ScopedFD* one, ScopedFD* two) {
|
||||
int raw_socks[2];
|
||||
#if defined(OS_MACOSX)
|
||||
// macOS does not support SEQPACKET.
|
||||
const int flags = SOCK_STREAM;
|
||||
#else
|
||||
const int flags = SOCK_SEQPACKET;
|
||||
#endif
|
||||
if (socketpair(AF_UNIX, flags, 0, raw_socks) == -1)
|
||||
return false;
|
||||
#if defined(OS_MACOSX)
|
||||
// On macOS, preventing SIGPIPE is done with socket option.
|
||||
const int no_sigpipe = 1;
|
||||
if (setsockopt(raw_socks[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
|
||||
sizeof(no_sigpipe)) != 0)
|
||||
return false;
|
||||
if (setsockopt(raw_socks[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
|
||||
sizeof(no_sigpipe)) != 0)
|
||||
return false;
|
||||
#endif
|
||||
one->reset(raw_socks[0]);
|
||||
two->reset(raw_socks[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool UnixDomainSocket::EnableReceiveProcessId(int fd) {
|
||||
#if !defined(OS_MACOSX)
|
||||
const int enable = 1;
|
||||
return setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)) == 0;
|
||||
#else
|
||||
// SO_PASSCRED is not supported on macOS.
|
||||
return true;
|
||||
#endif // OS_MACOSX
|
||||
}
|
||||
#endif // !defined(OS_NACL_NONSFI)
|
||||
|
||||
// static
|
||||
bool UnixDomainSocket::SendMsg(int fd,
|
||||
const void* buf,
|
||||
size_t length,
|
||||
const std::vector<int>& fds) {
|
||||
struct msghdr msg = {};
|
||||
struct iovec iov = {const_cast<void*>(buf), length};
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
char* control_buffer = nullptr;
|
||||
if (fds.size()) {
|
||||
const unsigned control_len = CMSG_SPACE(sizeof(int) * fds.size());
|
||||
control_buffer = new char[control_len];
|
||||
|
||||
struct cmsghdr* cmsg;
|
||||
msg.msg_control = control_buffer;
|
||||
msg.msg_controllen = control_len;
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds.size());
|
||||
memcpy(CMSG_DATA(cmsg), &fds[0], sizeof(int) * fds.size());
|
||||
msg.msg_controllen = cmsg->cmsg_len;
|
||||
}
|
||||
|
||||
// Avoid a SIGPIPE if the other end breaks the connection.
|
||||
// Due to a bug in the Linux kernel (net/unix/af_unix.c) MSG_NOSIGNAL isn't
|
||||
// regarded for SOCK_SEQPACKET in the AF_UNIX domain, but it is mandated by
|
||||
// POSIX. On Mac MSG_NOSIGNAL is not supported, so we need to ensure that
|
||||
// SO_NOSIGPIPE is set during socket creation.
|
||||
#if defined(OS_MACOSX)
|
||||
const int flags = 0;
|
||||
int no_sigpipe = 0;
|
||||
socklen_t no_sigpipe_len = sizeof(no_sigpipe);
|
||||
DPCHECK(getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
|
||||
&no_sigpipe_len) == 0)
|
||||
<< "Failed ot get socket option.";
|
||||
DCHECK(no_sigpipe) << "SO_NOSIGPIPE not set on the socket.";
|
||||
#else
|
||||
const int flags = MSG_NOSIGNAL;
|
||||
#endif // OS_MACOSX
|
||||
const ssize_t r = HANDLE_EINTR(sendmsg(fd, &msg, flags));
|
||||
const bool ret = static_cast<ssize_t>(length) == r;
|
||||
delete[] control_buffer;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// static
|
||||
ssize_t UnixDomainSocket::RecvMsg(int fd,
|
||||
void* buf,
|
||||
size_t length,
|
||||
std::vector<ScopedFD>* fds) {
|
||||
return UnixDomainSocket::RecvMsgWithPid(fd, buf, length, fds, nullptr);
|
||||
}
|
||||
|
||||
// static
|
||||
ssize_t UnixDomainSocket::RecvMsgWithPid(int fd,
|
||||
void* buf,
|
||||
size_t length,
|
||||
std::vector<ScopedFD>* fds,
|
||||
ProcessId* pid) {
|
||||
return UnixDomainSocket::RecvMsgWithFlags(fd, buf, length, 0, fds, pid);
|
||||
}
|
||||
|
||||
// static
|
||||
ssize_t UnixDomainSocket::RecvMsgWithFlags(int fd,
|
||||
void* buf,
|
||||
size_t length,
|
||||
int flags,
|
||||
std::vector<ScopedFD>* fds,
|
||||
ProcessId* out_pid) {
|
||||
fds->clear();
|
||||
|
||||
struct msghdr msg = {};
|
||||
struct iovec iov = {buf, length};
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
const size_t kControlBufferSize =
|
||||
CMSG_SPACE(sizeof(int) * kMaxFileDescriptors)
|
||||
#if !defined(OS_NACL_NONSFI) && !defined(OS_MACOSX)
|
||||
// The PNaCl toolchain for Non-SFI binary build and macOS do not support
|
||||
// ucred. macOS supports xucred, but this structure is insufficient.
|
||||
+ CMSG_SPACE(sizeof(struct ucred))
|
||||
#endif // OS_NACL_NONSFI or OS_MACOSX
|
||||
;
|
||||
char control_buffer[kControlBufferSize];
|
||||
msg.msg_control = control_buffer;
|
||||
msg.msg_controllen = sizeof(control_buffer);
|
||||
|
||||
const ssize_t r = HANDLE_EINTR(recvmsg(fd, &msg, flags));
|
||||
if (r == -1)
|
||||
return -1;
|
||||
|
||||
int* wire_fds = nullptr;
|
||||
unsigned wire_fds_len = 0;
|
||||
ProcessId pid = -1;
|
||||
|
||||
if (msg.msg_controllen > 0) {
|
||||
struct cmsghdr* cmsg;
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
|
||||
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
DCHECK_EQ(payload_len % sizeof(int), 0u);
|
||||
DCHECK_EQ(wire_fds, static_cast<void*>(nullptr));
|
||||
wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
|
||||
wire_fds_len = payload_len / sizeof(int);
|
||||
}
|
||||
#if !defined(OS_NACL_NONSFI) && !defined(OS_MACOSX)
|
||||
// The PNaCl toolchain for Non-SFI binary build and macOS do not support
|
||||
// SCM_CREDENTIALS.
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_CREDENTIALS) {
|
||||
DCHECK_EQ(payload_len, sizeof(struct ucred));
|
||||
DCHECK_EQ(pid, -1);
|
||||
pid = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg))->pid;
|
||||
}
|
||||
#endif // !defined(OS_NACL_NONSFI) && !defined(OS_MACOSX)
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.msg_flags & MSG_TRUNC || msg.msg_flags & MSG_CTRUNC) {
|
||||
if (msg.msg_flags & MSG_CTRUNC) {
|
||||
// Extraordinary case, not caller fixable. Log something.
|
||||
LOG(ERROR) << "recvmsg returned MSG_CTRUNC flag, buffer len is "
|
||||
<< msg.msg_controllen;
|
||||
}
|
||||
for (unsigned i = 0; i < wire_fds_len; ++i)
|
||||
close(wire_fds[i]);
|
||||
errno = EMSGSIZE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wire_fds) {
|
||||
for (unsigned i = 0; i < wire_fds_len; ++i)
|
||||
fds->push_back(ScopedFD(wire_fds[i])); // TODO(mdempsky): emplace_back
|
||||
}
|
||||
|
||||
if (out_pid) {
|
||||
#if defined(OS_MACOSX)
|
||||
socklen_t pid_size = sizeof(pid);
|
||||
if (getsockopt(fd, SOL_LOCAL, LOCAL_PEERPID, &pid, &pid_size) != 0)
|
||||
pid = -1;
|
||||
#else
|
||||
// |pid| will legitimately be -1 if we read EOF, so only DCHECK if we
|
||||
// actually received a message. Unfortunately, Linux allows sending zero
|
||||
// length messages, which are indistinguishable from EOF, so this check
|
||||
// has false negatives.
|
||||
if (r > 0 || msg.msg_controllen > 0)
|
||||
DCHECK_GE(pid, 0);
|
||||
#endif
|
||||
|
||||
*out_pid = pid;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#if !defined(OS_NACL_NONSFI)
|
||||
// static
|
||||
ssize_t UnixDomainSocket::SendRecvMsg(int fd,
|
||||
uint8_t* reply,
|
||||
unsigned max_reply_len,
|
||||
int* result_fd,
|
||||
const Pickle& request) {
|
||||
return UnixDomainSocket::SendRecvMsgWithFlags(fd, reply, max_reply_len,
|
||||
0, /* recvmsg_flags */
|
||||
result_fd, request);
|
||||
}
|
||||
|
||||
// static
|
||||
ssize_t UnixDomainSocket::SendRecvMsgWithFlags(int fd,
|
||||
uint8_t* reply,
|
||||
unsigned max_reply_len,
|
||||
int recvmsg_flags,
|
||||
int* result_fd,
|
||||
const Pickle& request) {
|
||||
// This socketpair is only used for the IPC and is cleaned up before
|
||||
// returning.
|
||||
ScopedFD recv_sock, send_sock;
|
||||
if (!CreateSocketPair(&recv_sock, &send_sock))
|
||||
return -1;
|
||||
|
||||
{
|
||||
std::vector<int> send_fds;
|
||||
send_fds.push_back(send_sock.get());
|
||||
if (!SendMsg(fd, request.data(), request.size(), send_fds))
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Close the sending end of the socket right away so that if our peer closes
|
||||
// it before sending a response (e.g., from exiting), RecvMsgWithFlags() will
|
||||
// return EOF instead of hanging.
|
||||
send_sock.reset();
|
||||
|
||||
std::vector<ScopedFD> recv_fds;
|
||||
// When porting to OSX keep in mind it doesn't support MSG_NOSIGNAL, so the
|
||||
// sender might get a SIGPIPE.
|
||||
const ssize_t reply_len = RecvMsgWithFlags(
|
||||
recv_sock.get(), reply, max_reply_len, recvmsg_flags, &recv_fds, nullptr);
|
||||
recv_sock.reset();
|
||||
if (reply_len == -1)
|
||||
return -1;
|
||||
|
||||
// If we received more file descriptors than caller expected, then we treat
|
||||
// that as an error.
|
||||
if (recv_fds.size() > (result_fd != nullptr ? 1 : 0)) {
|
||||
NOTREACHED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (result_fd)
|
||||
*result_fd = recv_fds.empty() ? -1 : recv_fds[0].release();
|
||||
|
||||
return reply_len;
|
||||
}
|
||||
#endif // !defined(OS_NACL_NONSFI)
|
||||
|
||||
} // namespace base
|
||||
111
TMessagesProj/jni/voip/webrtc/base/posix/unix_domain_socket.h
Normal file
111
TMessagesProj/jni/voip/webrtc/base/posix/unix_domain_socket.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_POSIX_UNIX_DOMAIN_SOCKET_H_
|
||||
#define BASE_POSIX_UNIX_DOMAIN_SOCKET_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/files/scoped_file.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
class Pickle;
|
||||
|
||||
#if !defined(OS_NACL_NONSFI)
|
||||
// Creates a connected pair of UNIX-domain SOCK_SEQPACKET sockets, and passes
|
||||
// ownership of the newly allocated file descriptors to |one| and |two|.
|
||||
// Returns true on success.
|
||||
bool BASE_EXPORT CreateSocketPair(ScopedFD* one, ScopedFD* two);
|
||||
#endif
|
||||
|
||||
class BASE_EXPORT UnixDomainSocket {
|
||||
public:
|
||||
// Maximum number of file descriptors that can be read by RecvMsg().
|
||||
static const size_t kMaxFileDescriptors;
|
||||
|
||||
#if !defined(OS_NACL_NONSFI)
|
||||
// Use to enable receiving process IDs in RecvMsgWithPid. Should be called on
|
||||
// the receiving socket (i.e., the socket passed to RecvMsgWithPid). Returns
|
||||
// true if successful.
|
||||
static bool EnableReceiveProcessId(int fd);
|
||||
#endif // !defined(OS_NACL_NONSFI)
|
||||
|
||||
// Use sendmsg to write the given msg and include a vector of file
|
||||
// descriptors. Returns true if successful.
|
||||
static bool SendMsg(int fd,
|
||||
const void* msg,
|
||||
size_t length,
|
||||
const std::vector<int>& fds);
|
||||
|
||||
// Use recvmsg to read a message and an array of file descriptors. Returns
|
||||
// -1 on failure. Note: will read, at most, |kMaxFileDescriptors| descriptors.
|
||||
static ssize_t RecvMsg(int fd,
|
||||
void* msg,
|
||||
size_t length,
|
||||
std::vector<ScopedFD>* fds);
|
||||
|
||||
// Same as RecvMsg above, but also returns the sender's process ID (as seen
|
||||
// from the caller's namespace). However, before using this function to
|
||||
// receive process IDs, EnableReceiveProcessId() should be called on the
|
||||
// receiving socket.
|
||||
static ssize_t RecvMsgWithPid(int fd,
|
||||
void* msg,
|
||||
size_t length,
|
||||
std::vector<ScopedFD>* fds,
|
||||
ProcessId* pid);
|
||||
|
||||
#if !defined(OS_NACL_NONSFI)
|
||||
// Perform a sendmsg/recvmsg pair.
|
||||
// 1. This process creates a UNIX SEQPACKET socketpair. Using
|
||||
// connection-oriented sockets (SEQPACKET or STREAM) is critical here,
|
||||
// because if one of the ends closes the other one must be notified.
|
||||
// 2. This process writes a request to |fd| with an SCM_RIGHTS control
|
||||
// message containing on end of the fresh socket pair.
|
||||
// 3. This process blocks reading from the other end of the fresh
|
||||
// socketpair.
|
||||
// 4. The target process receives the request, processes it and writes the
|
||||
// reply to the end of the socketpair contained in the request.
|
||||
// 5. This process wakes up and continues.
|
||||
//
|
||||
// fd: descriptor to send the request on
|
||||
// reply: buffer for the reply
|
||||
// reply_len: size of |reply|
|
||||
// result_fd: (may be NULL) the file descriptor returned in the reply
|
||||
// (if any)
|
||||
// request: the bytes to send in the request
|
||||
static ssize_t SendRecvMsg(int fd,
|
||||
uint8_t* reply,
|
||||
unsigned reply_len,
|
||||
int* result_fd,
|
||||
const Pickle& request);
|
||||
|
||||
// Similar to SendRecvMsg(), but |recvmsg_flags| allows to control the flags
|
||||
// of the recvmsg(2) call.
|
||||
static ssize_t SendRecvMsgWithFlags(int fd,
|
||||
uint8_t* reply,
|
||||
unsigned reply_len,
|
||||
int recvmsg_flags,
|
||||
int* result_fd,
|
||||
const Pickle& request);
|
||||
#endif // !defined(OS_NACL_NONSFI)
|
||||
private:
|
||||
// Similar to RecvMsg, but allows to specify |flags| for recvmsg(2).
|
||||
static ssize_t RecvMsgWithFlags(int fd,
|
||||
void* msg,
|
||||
size_t length,
|
||||
int flags,
|
||||
std::vector<ScopedFD>* fds,
|
||||
ProcessId* pid);
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_POSIX_UNIX_DOMAIN_SOCKET_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue