// 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 "ipc/file_descriptor_set_posix.h"

#include <sys/types.h>
#include <sys/stat.h>

#include "base/eintr_wrapper.h"
#include "base/logging.h"

FileDescriptorSet::FileDescriptorSet()
    : consumed_descriptor_highwater_(0) {
}

FileDescriptorSet::~FileDescriptorSet() {
  if (consumed_descriptor_highwater_ == descriptors_.size())
    return;

  LOG(WARNING) << "FileDescriptorSet destroyed with unconsumed descriptors";
  // We close all the descriptors where the close flag is set. If this
  // message should have been transmitted, then closing those with close
  // flags set mirrors the expected behaviour.
  //
  // If this message was received with more descriptors than expected
  // (which could a DOS against the browser by a rogue renderer) then all
  // the descriptors have their close flag set and we free all the extra
  // kernel resources.
  for (unsigned i = consumed_descriptor_highwater_;
       i < descriptors_.size(); ++i) {
    if (descriptors_[i].auto_close)
      if (HANDLE_EINTR(close(descriptors_[i].fd)) < 0)
        PLOG(ERROR) << "close";
  }
}

bool FileDescriptorSet::Add(int fd) {
  if (descriptors_.size() == kMaxDescriptorsPerMessage)
    return false;

  struct base::FileDescriptor sd;
  sd.fd = fd;
  sd.auto_close = false;
  descriptors_.push_back(sd);
  return true;
}

bool FileDescriptorSet::AddAndAutoClose(int fd) {
  if (descriptors_.size() == kMaxDescriptorsPerMessage)
    return false;

  struct base::FileDescriptor sd;
  sd.fd = fd;
  sd.auto_close = true;
  descriptors_.push_back(sd);
  DCHECK(descriptors_.size() <= kMaxDescriptorsPerMessage);
  return true;
}

int FileDescriptorSet::GetDescriptorAt(unsigned index) const {
  if (index >= descriptors_.size())
    return -1;

  // We should always walk the descriptors in order, so it's reasonable to
  // enforce this. Consider the case where a compromised renderer sends us
  // the following message:
  //
  //   ExampleMsg:
  //     num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m}
  //
  // Here the renderer sent us a message which should have a descriptor, but
  // actually sent two in an attempt to fill our fd table and kill us. By
  // setting the index of the descriptor in the message to 1 (it should be
  // 0), we would record a highwater of 1 and then consider all the
  // descriptors to have been used.
  //
  // So we can either track of the use of each descriptor in a bitset, or we
  // can enforce that we walk the indexes strictly in order.
  //
  // There's one more wrinkle: When logging messages, we may reparse them. So
  // we have an exception: When the consumed_descriptor_highwater_ is at the
  // end of the array and index 0 is requested, we reset the highwater value.
  if (index == 0 && consumed_descriptor_highwater_ == descriptors_.size())
    consumed_descriptor_highwater_ = 0;

  if (index != consumed_descriptor_highwater_)
    return -1;

  consumed_descriptor_highwater_ = index + 1;
  return descriptors_[index].fd;
}

void FileDescriptorSet::GetDescriptors(int* buffer) const {
  for (std::vector<base::FileDescriptor>::const_iterator
       i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    *(buffer++) = i->fd;
  }
}

bool FileDescriptorSet::ContainsDirectoryDescriptor() const {
  struct stat st;

  for (std::vector<base::FileDescriptor>::const_iterator
       i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    if (fstat(i->fd, &st) == 0 && S_ISDIR(st.st_mode))
      return true;
  }

  return false;
}

void FileDescriptorSet::CommitAll() {
  for (std::vector<base::FileDescriptor>::iterator
       i = descriptors_.begin(); i != descriptors_.end(); ++i) {
    if (i->auto_close)
      if (HANDLE_EINTR(close(i->fd)) < 0)
        PLOG(ERROR) << "close";
  }
  descriptors_.clear();
  consumed_descriptor_highwater_ = 0;
}

void FileDescriptorSet::SetDescriptors(const int* buffer, unsigned count) {
  DCHECK(count <= kMaxDescriptorsPerMessage);
  DCHECK_EQ(descriptors_.size(), 0u);
  DCHECK_EQ(consumed_descriptor_highwater_, 0u);

  descriptors_.reserve(count);
  for (unsigned i = 0; i < count; ++i) {
    struct base::FileDescriptor sd;
    sd.fd = buffer[i];
    sd.auto_close = true;
    descriptors_.push_back(sd);
  }
}
