<commit_before>/* Copyright 2021, The TensorFlow Federated Authors.

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 "tensorflow_federated/cc/core/impl/executor_stacks/remote_stacks.h"

#include <chrono>  // NOLINT
#include <limits>
#include <memory>

#include "net/grpc/public/include/grpcpp/grpcpp.h"
#include "net/grpc/public/include/grpcpp/support/time.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/time/time.h"
#include "tensorflow_federated/cc/core/impl/executors/cardinalities.h"
#include "tensorflow_federated/cc/core/impl/executors/composing_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/federating_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/reference_resolving_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/remote_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/tensorflow_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/threading.h"

namespace tensorflow_federated {

// This function queries the state of the incoming channels, filtering to those
// which are ready or idle. This function blocks up to
// `wait_connected_duration_millis` milliseconds, awaiting all channels in
// `channels` to be ready.
std::vector<const std::shared_ptr<grpc::ChannelInterface>>
FilterToLiveChannels_(
    absl::Span<const std::shared_ptr<grpc::ChannelInterface>> channels,
    int wait_connected_duration_millis = 100) {
  std::vector<const std::shared_ptr<grpc::ChannelInterface>> live_channels;
  auto wait_connected =
      [&wait_connected_duration_millis](
          std::shared_ptr<grpc::ChannelInterface> channel) -> absl::Status {
    bool connected = channel->WaitForConnected(
        std::chrono::system_clock::now() +
        std::chrono::milliseconds(wait_connected_duration_millis));
    if (connected) {
      return absl::OkStatus();
    } else {
      return absl::UnavailableError("Channel not ready.");
    }
  };

  ParallelTasks wait_connected_tasks;
  for (const std::shared_ptr<grpc::ChannelInterface>& channel : channels) {
    wait_connected_tasks.add_task(std::bind(wait_connected, channel));
  }
  // Block up to WaitConnectedDuration for all tasks to complete.
  absl::Status all_channels_ready = wait_connected_tasks.WaitAll();

  for (const std::shared_ptr<grpc::ChannelInterface>& channel : channels) {
    // We can wait 0 duration here since we have already blocked for all
    // channels to attempt connection.
    bool connected =
        channel->WaitForConnected(std::chrono::system_clock::now());
    if (!connected) {
      // This channel is not yet ready to serve requests.
      continue;
    } else {
      live_channels.emplace_back(channel);
    }
  }
  return live_channels;
}

absl::StatusOr<std::shared_ptr<Executor>> CreateRemoteExecutorStack(
    absl::Span<const std::shared_ptr<grpc::ChannelInterface>> channels,
    const CardinalityMap& cardinalities) {
  auto rre_tf_leaf_executor = []() {
    return CreateReferenceResolvingExecutor(CreateTensorFlowExecutor());
  };
  ComposingChildFn composing_child_factory =
      [](std::shared_ptr<grpc::ChannelInterface> channel,
         const CardinalityMap& cardinalities)
      -> absl::StatusOr<ComposingChild> {
    return TFF_TRY(ComposingChild::Make(
        CreateRemoteExecutor(channel, cardinalities), cardinalities));
  };

  return CreateRemoteExecutorStack(
      channels, cardinalities, rre_tf_leaf_executor, composing_child_factory);
}

absl::StatusOr<std::shared_ptr<Executor>> CreateRemoteExecutorStack(
    absl::Span<const std::shared_ptr<grpc::ChannelInterface>> channels,
    const CardinalityMap& cardinalities, ExecutorFn leaf_executor_fn,
    ComposingChildFn composing_child_fn) {
  int num_clients = 0;
  auto cards_iterator = cardinalities.find(kClientsUri);
  if (cards_iterator != cardinalities.end()) {
    num_clients = cards_iterator->second;
  } else {
    return absl::InvalidArgumentError(
        "Num clients not specified in cardinalities.");
  }
  std::shared_ptr<Executor> server = TFF_TRY(leaf_executor_fn());
  int remaining_clients = num_clients;
  if (remaining_clients == 0) {
    auto federated_cardinalities = cardinalities;
    federated_cardinalities.insert_or_assign(kClientsUri, 0);
    return CreateReferenceResolvingExecutor(
        TFF_TRY(CreateFederatingExecutor(server, federated_cardinalities)));
  } else if (channels.empty()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "A remote executor stack with nonzero number of clients must be "
        "configured with some remote worker. Found 0 remote channels but ",
        remaining_clients, " num_clients."));
  }

  auto live_channels = FilterToLiveChannels_(channels);
  int remaining_num_executors = live_channels.size();
  if (live_channels.empty()) {
    return absl::UnavailableError(
        "No TFF workers are ready; try again to reconnect");
  }
  std::vector<ComposingChild> remote_executors;
  for (const std::shared_ptr<grpc::ChannelInterface>& channel : live_channels) {
    int clients_for_executor = remaining_clients / remaining_num_executors;
    CardinalityMap cardinalities_for_executor = cardinalities;
    cardinalities_for_executor.insert_or_assign(kClientsUri,
                                                clients_for_executor);
    remote_executors.emplace_back(
        TFF_TRY(composing_child_fn(channel, cardinalities_for_executor)));
    remaining_clients -= clients_for_executor;
    remaining_num_executors -= 1;
  }
  VLOG(2) << "Addressing: " << remote_executors.size() << " Live TFF workers.";
  return CreateReferenceResolvingExecutor(
      CreateComposingExecutor(server, remote_executors));
}

}  // namespace tensorflow_federated
<commit_msg>Swaps LOG(INFO) for VLOG(1) in querying for borg tasks.<commit_after>/* Copyright 2021, The TensorFlow Federated Authors.

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 "tensorflow_federated/cc/core/impl/executor_stacks/remote_stacks.h"

#include <chrono>  // NOLINT
#include <limits>
#include <memory>

#include "net/grpc/public/include/grpcpp/grpcpp.h"
#include "net/grpc/public/include/grpcpp/support/time.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/time/time.h"
#include "tensorflow_federated/cc/core/impl/executors/cardinalities.h"
#include "tensorflow_federated/cc/core/impl/executors/composing_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/federating_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/reference_resolving_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/remote_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/tensorflow_executor.h"
#include "tensorflow_federated/cc/core/impl/executors/threading.h"

namespace tensorflow_federated {

// This function queries the state of the incoming channels, filtering to those
// which are ready or idle. This function blocks up to
// `wait_connected_duration_millis` milliseconds, awaiting all channels in
// `channels` to be ready.
std::vector<const std::shared_ptr<grpc::ChannelInterface>>
FilterToLiveChannels_(
    absl::Span<const std::shared_ptr<grpc::ChannelInterface>> channels,
    int wait_connected_duration_millis = 1000) {
  std::vector<const std::shared_ptr<grpc::ChannelInterface>> live_channels;
  auto wait_connected =
      [&wait_connected_duration_millis](
          std::shared_ptr<grpc::ChannelInterface> channel) -> absl::Status {
    bool connected = channel->WaitForConnected(
        std::chrono::system_clock::now() +
        std::chrono::milliseconds(wait_connected_duration_millis));
    if (connected) {
      return absl::OkStatus();
    } else {
      return absl::UnavailableError("Channel not ready.");
    }
  };

  ParallelTasks wait_connected_tasks;
  for (const std::shared_ptr<grpc::ChannelInterface>& channel : channels) {
    wait_connected_tasks.add_task(std::bind(wait_connected, channel));
  }
  // Block up to WaitConnectedDuration for all tasks to complete.
  absl::Status all_channels_ready = wait_connected_tasks.WaitAll();

  for (const std::shared_ptr<grpc::ChannelInterface>& channel : channels) {
    // We can wait 0 duration here since we have already blocked for all
    // channels to attempt connection.
    bool connected =
        channel->WaitForConnected(std::chrono::system_clock::now());
    if (!connected) {
      // This channel is not yet ready to serve requests.
      continue;
    } else {
      live_channels.emplace_back(channel);
    }
  }
  return live_channels;
}

absl::StatusOr<std::shared_ptr<Executor>> CreateRemoteExecutorStack(
    absl::Span<const std::shared_ptr<grpc::ChannelInterface>> channels,
    const CardinalityMap& cardinalities) {
  auto rre_tf_leaf_executor = []() {
    return CreateReferenceResolvingExecutor(CreateTensorFlowExecutor());
  };
  ComposingChildFn composing_child_factory =
      [](std::shared_ptr<grpc::ChannelInterface> channel,
         const CardinalityMap& cardinalities)
      -> absl::StatusOr<ComposingChild> {
    return TFF_TRY(ComposingChild::Make(
        CreateRemoteExecutor(channel, cardinalities), cardinalities));
  };

  return CreateRemoteExecutorStack(
      channels, cardinalities, rre_tf_leaf_executor, composing_child_factory);
}

absl::StatusOr<std::shared_ptr<Executor>> CreateRemoteExecutorStack(
    absl::Span<const std::shared_ptr<grpc::ChannelInterface>> channels,
    const CardinalityMap& cardinalities, ExecutorFn leaf_executor_fn,
    ComposingChildFn composing_child_fn) {
  int num_clients = 0;
  auto cards_iterator = cardinalities.find(kClientsUri);
  if (cards_iterator != cardinalities.end()) {
    num_clients = cards_iterator->second;
  } else {
    return absl::InvalidArgumentError(
        "Num clients not specified in cardinalities.");
  }
  std::shared_ptr<Executor> server = TFF_TRY(leaf_executor_fn());
  int remaining_clients = num_clients;
  if (remaining_clients == 0) {
    auto federated_cardinalities = cardinalities;
    federated_cardinalities.insert_or_assign(kClientsUri, 0);
    return CreateReferenceResolvingExecutor(
        TFF_TRY(CreateFederatingExecutor(server, federated_cardinalities)));
  } else if (channels.empty()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "A remote executor stack with nonzero number of clients must be "
        "configured with some remote worker. Found 0 remote channels but ",
        remaining_clients, " num_clients."));
  }

  auto live_channels = FilterToLiveChannels_(channels);
  int remaining_num_executors = live_channels.size();
  if (live_channels.empty()) {
    return absl::UnavailableError(
        "No TFF workers are ready; try again to reconnect");
  }
  std::vector<ComposingChild> remote_executors;
  for (const std::shared_ptr<grpc::ChannelInterface>& channel : live_channels) {
    int clients_for_executor = remaining_clients / remaining_num_executors;
    CardinalityMap cardinalities_for_executor = cardinalities;
    cardinalities_for_executor.insert_or_assign(kClientsUri,
                                                clients_for_executor);
    remote_executors.emplace_back(
        TFF_TRY(composing_child_fn(channel, cardinalities_for_executor)));
    remaining_clients -= clients_for_executor;
    remaining_num_executors -= 1;
  }
  VLOG(2) << "Addressing: " << remote_executors.size() << " Live TFF workers.";
  return CreateReferenceResolvingExecutor(
      CreateComposingExecutor(server, remote_executors));
}

}  // namespace tensorflow_federated
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// This is the implementation of the PacketBuffer class. It is mostly based on
// an STL list. The list is kept sorted at all times so that the next packet to
// decode is at the beginning of the list.

#include "webrtc/modules/audio_coding/neteq4/packet_buffer.h"

#include <algorithm>  // find_if()

#include "webrtc/modules/audio_coding/neteq4/decoder_database.h"
#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"

namespace webrtc {

// Predicate used when inserting packets in the buffer list.
// Operator() returns true when |packet| goes before |new_packet|.
class NewTimestampIsLarger {
 public:
  explicit NewTimestampIsLarger(const Packet* new_packet)
      : new_packet_(new_packet) {
  }
  bool operator()(Packet* packet) {
    return (*new_packet_ >= *packet);
  }

 private:
  const Packet* new_packet_;
};

PacketBuffer::PacketBuffer(size_t max_number_of_packets)
    : max_number_of_packets_(max_number_of_packets) {}

// Destructor. All packets in the buffer will be destroyed.
PacketBuffer::~PacketBuffer() {
  Flush();
}

// Flush the buffer. All packets in the buffer will be destroyed.
void PacketBuffer::Flush() {
  DeleteAllPackets(&buffer_);
}

int PacketBuffer::InsertPacket(Packet* packet) {
  if (!packet || !packet->payload) {
    if (packet) {
      delete packet;
    }
    return kInvalidPacket;
  }

  int return_val = kOK;

  if (buffer_.size() >= max_number_of_packets_) {
    // Buffer is full. Flush it.
    Flush();
    return_val = kFlushed;
  }

  // Get an iterator pointing to the place in the buffer where the new packet
  // should be inserted. The list is searched from the back, since the most
  // likely case is that the new packet should be near the end of the list.
  PacketList::reverse_iterator rit = std::find_if(
      buffer_.rbegin(), buffer_.rend(),
      NewTimestampIsLarger(packet));
  buffer_.insert(rit.base(), packet);  // Insert the packet at that position.

  return return_val;
}

int PacketBuffer::InsertPacketList(PacketList* packet_list,
                                   const DecoderDatabase& decoder_database,
                                   uint8_t* current_rtp_payload_type,
                                   uint8_t* current_cng_rtp_payload_type) {
  bool flushed = false;
  while (!packet_list->empty()) {
    Packet* packet = packet_list->front();
    if (decoder_database.IsComfortNoise(packet->header.payloadType)) {
      if (*current_cng_rtp_payload_type != 0xFF &&
          *current_cng_rtp_payload_type != packet->header.payloadType) {
        // New CNG payload type implies new codec type.
        *current_rtp_payload_type = 0xFF;
        Flush();
        flushed = true;
      }
      *current_cng_rtp_payload_type = packet->header.payloadType;
    } else if (!decoder_database.IsDtmf(packet->header.payloadType)) {
      // This must be speech.
      if (*current_rtp_payload_type != 0xFF &&
          *current_rtp_payload_type != packet->header.payloadType) {
        *current_cng_rtp_payload_type = 0xFF;
        Flush();
        flushed = true;
      }
      *current_rtp_payload_type = packet->header.payloadType;
    }
    int return_val = InsertPacket(packet);
    packet_list->pop_front();
    if (return_val == kFlushed) {
      // The buffer flushed, but this is not an error. We can still continue.
      flushed = true;
    } else if (return_val != kOK) {
      // An error occurred. Delete remaining packets in list and return.
      DeleteAllPackets(packet_list);
      return return_val;
    }
  }
  return flushed ? kFlushed : kOK;
}

int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
  if (Empty()) {
    return kBufferEmpty;
  }
  if (!next_timestamp) {
    return kInvalidPointer;
  }
  *next_timestamp = buffer_.front()->header.timestamp;
  return kOK;
}

int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
                                      uint32_t* next_timestamp) const {
  if (Empty()) {
    return kBufferEmpty;
  }
  if (!next_timestamp) {
    return kInvalidPointer;
  }
  PacketList::const_iterator it;
  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
    if ((*it)->header.timestamp >= timestamp) {
      // Found a packet matching the search.
      *next_timestamp = (*it)->header.timestamp;
      return kOK;
    }
  }
  return kNotFound;
}

const RTPHeader* PacketBuffer::NextRtpHeader() const {
  if (Empty()) {
    return NULL;
  }
  return const_cast<const RTPHeader*>(&(buffer_.front()->header));
}

Packet* PacketBuffer::GetNextPacket(int* discard_count) {
  if (Empty()) {
    // Buffer is empty.
    return NULL;
  }

  Packet* packet = buffer_.front();
  // Assert that the packet sanity checks in InsertPacket method works.
  assert(packet && packet->payload);
  buffer_.pop_front();
  // Discard other packets with the same timestamp. These are duplicates or
  // redundant payloads that should not be used.
  if (discard_count) {
    *discard_count = 0;
  }
  while (!Empty() &&
      buffer_.front()->header.timestamp == packet->header.timestamp) {
    if (DiscardNextPacket() != kOK) {
      assert(false);  // Must be ok by design.
    }
    if (discard_count) {
      ++(*discard_count);
    }
  }
  return packet;
}

int PacketBuffer::DiscardNextPacket() {
  if (Empty()) {
    return kBufferEmpty;
  }
  Packet* temp_packet = buffer_.front();
  // Assert that the packet sanity checks in InsertPacket method works.
  assert(temp_packet && temp_packet->payload);
  DeleteFirstPacket(&buffer_);
  return kOK;
}

int PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit) {
  while (!Empty() &&
      timestamp_limit != buffer_.front()->header.timestamp &&
      static_cast<uint32_t>(timestamp_limit
                            - buffer_.front()->header.timestamp) <
                            0xFFFFFFFF / 2) {
    if (DiscardNextPacket() != kOK) {
      assert(false);  // Must be ok by design.
    }
  }
  return 0;
}

int PacketBuffer::NumSamplesInBuffer(DecoderDatabase* decoder_database,
                                     int last_decoded_length) const {
  PacketList::const_iterator it;
  int num_samples = 0;
  int last_duration = last_decoded_length;
  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
    Packet* packet = (*it);
    AudioDecoder* decoder =
        decoder_database->GetDecoder(packet->header.payloadType);
    if (decoder) {
      int duration;
      if (packet->sync_packet) {
        duration = last_duration;
      } else {
        duration = packet->primary ?
            decoder->PacketDuration(packet->payload, packet->payload_length) :
            decoder->PacketDurationRedundant(packet->payload,
                                             packet->payload_length);
      }
      if (duration >= 0) {
        last_duration = duration;  // Save the most up-to-date (valid) duration.
      }
    }
    num_samples += last_duration;
  }
  return num_samples;
}

void PacketBuffer::IncrementWaitingTimes(int inc) {
  PacketList::iterator it;
  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
    (*it)->waiting_time += inc;
  }
}

bool PacketBuffer::DeleteFirstPacket(PacketList* packet_list) {
  if (packet_list->empty()) {
    return false;
  }
  Packet* first_packet = packet_list->front();
  delete [] first_packet->payload;
  delete first_packet;
  packet_list->pop_front();
  return true;
}

void PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
  while (DeleteFirstPacket(packet_list)) {
    // Continue while the list is not empty.
  }
}

void PacketBuffer::BufferStat(int* num_packets, int* max_num_packets) const {
  *num_packets = static_cast<int>(buffer_.size());
  *max_num_packets = static_cast<int>(max_number_of_packets_);
}

}  // namespace webrtc
<commit_msg>Fix the NetEq build<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// This is the implementation of the PacketBuffer class. It is mostly based on
// an STL list. The list is kept sorted at all times so that the next packet to
// decode is at the beginning of the list.

#include "webrtc/modules/audio_coding/neteq4/packet_buffer.h"

#include <algorithm>  // find_if()

#include "webrtc/modules/audio_coding/neteq4/decoder_database.h"
#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"

namespace webrtc {

// Predicate used when inserting packets in the buffer list.
// Operator() returns true when |packet| goes before |new_packet|.
class NewTimestampIsLarger {
 public:
  explicit NewTimestampIsLarger(const Packet* new_packet)
      : new_packet_(new_packet) {
  }
  bool operator()(Packet* packet) {
    return (*new_packet_ >= *packet);
  }

 private:
  const Packet* new_packet_;
};

PacketBuffer::PacketBuffer(size_t max_number_of_packets)
    : max_number_of_packets_(max_number_of_packets) {}

// Destructor. All packets in the buffer will be destroyed.
PacketBuffer::~PacketBuffer() {
  Flush();
}

// Flush the buffer. All packets in the buffer will be destroyed.
void PacketBuffer::Flush() {
  DeleteAllPackets(&buffer_);
}

int PacketBuffer::InsertPacket(Packet* packet) {
  if (!packet || !packet->payload) {
    if (packet) {
      delete packet;
    }
    return kInvalidPacket;
  }

  int return_val = kOK;

  if (buffer_.size() >= max_number_of_packets_) {
    // Buffer is full. Flush it.
    Flush();
    return_val = kFlushed;
  }

  // Get an iterator pointing to the place in the buffer where the new packet
  // should be inserted. The list is searched from the back, since the most
  // likely case is that the new packet should be near the end of the list.
  PacketList::reverse_iterator rit = std::find_if(
      buffer_.rbegin(), buffer_.rend(),
      NewTimestampIsLarger(packet));
  buffer_.insert(rit.base(), packet);  // Insert the packet at that position.

  return return_val;
}

int PacketBuffer::InsertPacketList(PacketList* packet_list,
                                   const DecoderDatabase& decoder_database,
                                   uint8_t* current_rtp_payload_type,
                                   uint8_t* current_cng_rtp_payload_type) {
  bool flushed = false;
  while (!packet_list->empty()) {
    Packet* packet = packet_list->front();
    if (decoder_database.IsComfortNoise(packet->header.payloadType)) {
      if (*current_cng_rtp_payload_type != 0xFF &&
          *current_cng_rtp_payload_type != packet->header.payloadType) {
        // New CNG payload type implies new codec type.
        *current_rtp_payload_type = 0xFF;
        Flush();
        flushed = true;
      }
      *current_cng_rtp_payload_type = packet->header.payloadType;
    } else if (!decoder_database.IsDtmf(packet->header.payloadType)) {
      // This must be speech.
      if (*current_rtp_payload_type != 0xFF &&
          *current_rtp_payload_type != packet->header.payloadType) {
        *current_cng_rtp_payload_type = 0xFF;
        Flush();
        flushed = true;
      }
      *current_rtp_payload_type = packet->header.payloadType;
    }
    int return_val = InsertPacket(packet);
    packet_list->pop_front();
    if (return_val == kFlushed) {
      // The buffer flushed, but this is not an error. We can still continue.
      flushed = true;
    } else if (return_val != kOK) {
      // An error occurred. Delete remaining packets in list and return.
      DeleteAllPackets(packet_list);
      return return_val;
    }
  }
  return flushed ? kFlushed : kOK;
}

int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
  if (Empty()) {
    return kBufferEmpty;
  }
  if (!next_timestamp) {
    return kInvalidPointer;
  }
  *next_timestamp = buffer_.front()->header.timestamp;
  return kOK;
}

int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
                                      uint32_t* next_timestamp) const {
  if (Empty()) {
    return kBufferEmpty;
  }
  if (!next_timestamp) {
    return kInvalidPointer;
  }
  PacketList::const_iterator it;
  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
    if ((*it)->header.timestamp >= timestamp) {
      // Found a packet matching the search.
      *next_timestamp = (*it)->header.timestamp;
      return kOK;
    }
  }
  return kNotFound;
}

const RTPHeader* PacketBuffer::NextRtpHeader() const {
  if (Empty()) {
    return NULL;
  }
  return const_cast<const RTPHeader*>(&(buffer_.front()->header));
}

Packet* PacketBuffer::GetNextPacket(int* discard_count) {
  if (Empty()) {
    // Buffer is empty.
    return NULL;
  }

  Packet* packet = buffer_.front();
  // Assert that the packet sanity checks in InsertPacket method works.
  assert(packet && packet->payload);
  buffer_.pop_front();
  // Discard other packets with the same timestamp. These are duplicates or
  // redundant payloads that should not be used.
  if (discard_count) {
    *discard_count = 0;
  }
  while (!Empty() &&
      buffer_.front()->header.timestamp == packet->header.timestamp) {
    if (DiscardNextPacket() != kOK) {
      assert(false);  // Must be ok by design.
    }
    if (discard_count) {
      ++(*discard_count);
    }
  }
  return packet;
}

int PacketBuffer::DiscardNextPacket() {
  if (Empty()) {
    return kBufferEmpty;
  }
  // Assert that the packet sanity checks in InsertPacket method works.
  assert(buffer_.front());
  assert(buffer_.front()->payload);
  DeleteFirstPacket(&buffer_);
  return kOK;
}

int PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit) {
  while (!Empty() &&
      timestamp_limit != buffer_.front()->header.timestamp &&
      static_cast<uint32_t>(timestamp_limit
                            - buffer_.front()->header.timestamp) <
                            0xFFFFFFFF / 2) {
    if (DiscardNextPacket() != kOK) {
      assert(false);  // Must be ok by design.
    }
  }
  return 0;
}

int PacketBuffer::NumSamplesInBuffer(DecoderDatabase* decoder_database,
                                     int last_decoded_length) const {
  PacketList::const_iterator it;
  int num_samples = 0;
  int last_duration = last_decoded_length;
  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
    Packet* packet = (*it);
    AudioDecoder* decoder =
        decoder_database->GetDecoder(packet->header.payloadType);
    if (decoder) {
      int duration;
      if (packet->sync_packet) {
        duration = last_duration;
      } else {
        duration = packet->primary ?
            decoder->PacketDuration(packet->payload, packet->payload_length) :
            decoder->PacketDurationRedundant(packet->payload,
                                             packet->payload_length);
      }
      if (duration >= 0) {
        last_duration = duration;  // Save the most up-to-date (valid) duration.
      }
    }
    num_samples += last_duration;
  }
  return num_samples;
}

void PacketBuffer::IncrementWaitingTimes(int inc) {
  PacketList::iterator it;
  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
    (*it)->waiting_time += inc;
  }
}

bool PacketBuffer::DeleteFirstPacket(PacketList* packet_list) {
  if (packet_list->empty()) {
    return false;
  }
  Packet* first_packet = packet_list->front();
  delete [] first_packet->payload;
  delete first_packet;
  packet_list->pop_front();
  return true;
}

void PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
  while (DeleteFirstPacket(packet_list)) {
    // Continue while the list is not empty.
  }
}

void PacketBuffer::BufferStat(int* num_packets, int* max_num_packets) const {
  *num_packets = static_cast<int>(buffer_.size());
  *max_num_packets = static_cast<int>(max_number_of_packets_);
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Fangfang Bai, fangfang@multicorewareinc.com
//    Jin Ma,       jin@multicorewareinc.com
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors as is and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "perf_precomp.hpp"
#include "opencv2/ts/ocl_perf.hpp"

#ifdef HAVE_OPENCL

namespace cvtest {
namespace ocl {

///////////// WarpAffine ////////////////////////

CV_ENUM(InterType, INTER_NEAREST, INTER_LINEAR)

typedef tuple<Size, MatType, InterType> WarpAffineParams;
typedef TestBaseWithParam<WarpAffineParams> WarpAffineFixture;

OCL_PERF_TEST_P(WarpAffineFixture, WarpAffine,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134, InterType::all()))
{
    static const double coeffs[2][3] =
    {
        { cos(CV_PI / 6), -sin(CV_PI / 6), 100.0  },
        { sin(CV_PI / 6), cos(CV_PI / 6) , -100.0 }
    };
    Mat M(2, 3, CV_64F, (void *)coeffs);

    const WarpAffineParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params), interpolation = get<2>(params);
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);

    UMat src(srcSize, type), dst(srcSize, type);
    declare.in(src, WARMUP_RNG).out(dst);

    OCL_TEST_CYCLE() cv::warpAffine(src, dst, M, srcSize, interpolation);

    SANITY_CHECK(dst, eps);
}

///////////// WarpPerspective ////////////////////////

typedef WarpAffineParams WarpPerspectiveParams;
typedef TestBaseWithParam<WarpPerspectiveParams> WarpPerspectiveFixture;

OCL_PERF_TEST_P(WarpPerspectiveFixture, WarpPerspective,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134, InterType::all()))
{
    static const double coeffs[3][3] =
    {
        {cos(CV_PI / 6), -sin(CV_PI / 6), 100.0},
        {sin(CV_PI / 6), cos(CV_PI / 6), -100.0},
        {0.0, 0.0, 1.0}
    };
    Mat M(3, 3, CV_64F, (void *)coeffs);

    const WarpPerspectiveParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params), interpolation = get<2>(params);
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);

    UMat src(srcSize, type), dst(srcSize, type);
    declare.in(src, WARMUP_RNG).out(dst);

    OCL_TEST_CYCLE() cv::warpPerspective(src, dst, M, srcSize, interpolation);

    SANITY_CHECK(dst, eps);
}

///////////// Resize ////////////////////////

typedef tuple<Size, MatType, InterType, double> ResizeParams;
typedef TestBaseWithParam<ResizeParams> ResizeFixture;

OCL_PERF_TEST_P(ResizeFixture, Resize,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134,
                               InterType::all(), ::testing::Values(0.5, 2.0)))
{
    const ResizeParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params), interType = get<2>(params);
    double scale = get<3>(params);
    const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale));
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);
    checkDeviceMaxMemoryAllocSize(dstSize, type);

    UMat src(srcSize, type), dst(dstSize, type);
    declare.in(src, WARMUP_RNG).out(dst);

    OCL_TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, interType);

    SANITY_CHECK(dst, eps);
}

typedef tuple<Size, MatType, double> ResizeAreaParams;
typedef TestBaseWithParam<ResizeAreaParams> ResizeAreaFixture;

OCL_PERF_TEST_P(ResizeAreaFixture, Resize,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134, ::testing::Values(0.3, 0.5, 0.6)))
{
    const ResizeAreaParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params);
    double scale = get<2>(params);
    const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale));
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);
    checkDeviceMaxMemoryAllocSize(dstSize, type);

    UMat src(srcSize, type), dst(dstSize, type);
    declare.in(src, WARMUP_RNG).out(dst);

    OCL_TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, cv::INTER_AREA);

    SANITY_CHECK(dst, eps);
}

///////////// Remap ////////////////////////

typedef tuple<Size, MatType, InterType> RemapParams;
typedef TestBaseWithParam<RemapParams> RemapFixture;

OCL_PERF_TEST_P(RemapFixture, Remap,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134, InterType::all()))
{
    const RemapParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params), interpolation = get<2>(params), borderMode = BORDER_CONSTANT;
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);

    UMat src(srcSize, type), dst(srcSize, type);
    UMat xmap(srcSize, CV_32FC1), ymap(srcSize, CV_32FC1);

    {
        Mat _xmap = xmap.getMat(ACCESS_WRITE), _ymap = ymap.getMat(ACCESS_WRITE);
        for (int i = 0; i < srcSize.height; ++i)
        {
            float * const xmap_row = _xmap.ptr<float>(i);
            float * const ymap_row = _ymap.ptr<float>(i);

            for (int j = 0; j < srcSize.width; ++j)
            {
                xmap_row[j] = (j - srcSize.width * 0.5f) * 0.75f + srcSize.width * 0.5f;
                ymap_row[j] = (i - srcSize.height * 0.5f) * 0.75f + srcSize.height * 0.5f;
            }
        }
    }
    declare.in(src, WARMUP_RNG).in(xmap, ymap, WARMUP_READ).out(dst);

    OCL_TEST_CYCLE() cv::remap(src, dst, xmap, ymap, interpolation, borderMode);

    SANITY_CHECK(dst, eps);
}

} } // namespace cvtest::ocl

#endif // HAVE_OPENCL
<commit_msg>added missed INTER_CUBIC<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Fangfang Bai, fangfang@multicorewareinc.com
//    Jin Ma,       jin@multicorewareinc.com
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors as is and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "perf_precomp.hpp"
#include "opencv2/ts/ocl_perf.hpp"

#ifdef HAVE_OPENCL

namespace cvtest {
namespace ocl {

///////////// WarpAffine ////////////////////////

CV_ENUM(InterType, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC)

typedef tuple<Size, MatType, InterType> WarpAffineParams;
typedef TestBaseWithParam<WarpAffineParams> WarpAffineFixture;

OCL_PERF_TEST_P(WarpAffineFixture, WarpAffine,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134, InterType::all()))
{
    static const double coeffs[2][3] =
    {
        { cos(CV_PI / 6), -sin(CV_PI / 6), 100.0  },
        { sin(CV_PI / 6), cos(CV_PI / 6) , -100.0 }
    };
    Mat M(2, 3, CV_64F, (void *)coeffs);

    const WarpAffineParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params), interpolation = get<2>(params);
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : interpolation == INTER_CUBIC ? 2e-3 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);

    UMat src(srcSize, type), dst(srcSize, type);
    declare.in(src, WARMUP_RNG).out(dst);

    OCL_TEST_CYCLE() cv::warpAffine(src, dst, M, srcSize, interpolation);

    SANITY_CHECK(dst, eps);
}

///////////// WarpPerspective ////////////////////////

typedef WarpAffineParams WarpPerspectiveParams;
typedef TestBaseWithParam<WarpPerspectiveParams> WarpPerspectiveFixture;

OCL_PERF_TEST_P(WarpPerspectiveFixture, WarpPerspective,
                ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134,
                                   OCL_PERF_ENUM(InterType(INTER_NEAREST), InterType(INTER_LINEAR))))
{
    static const double coeffs[3][3] =
    {
        {cos(CV_PI / 6), -sin(CV_PI / 6), 100.0},
        {sin(CV_PI / 6), cos(CV_PI / 6), -100.0},
        {0.0, 0.0, 1.0}
    };
    Mat M(3, 3, CV_64F, (void *)coeffs);

    const WarpPerspectiveParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params), interpolation = get<2>(params);
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);

    UMat src(srcSize, type), dst(srcSize, type);
    declare.in(src, WARMUP_RNG).out(dst);

    OCL_TEST_CYCLE() cv::warpPerspective(src, dst, M, srcSize, interpolation);

    SANITY_CHECK(dst, eps);
}

///////////// Resize ////////////////////////

typedef tuple<Size, MatType, InterType, double> ResizeParams;
typedef TestBaseWithParam<ResizeParams> ResizeFixture;

OCL_PERF_TEST_P(ResizeFixture, Resize,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134,
                               OCL_PERF_ENUM(InterType(INTER_NEAREST), InterType(INTER_LINEAR)),
                               ::testing::Values(0.5, 2.0)))
{
    const ResizeParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params), interType = get<2>(params);
    double scale = get<3>(params);
    const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale));
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);
    checkDeviceMaxMemoryAllocSize(dstSize, type);

    UMat src(srcSize, type), dst(dstSize, type);
    declare.in(src, WARMUP_RNG).out(dst);

    OCL_TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, interType);

    SANITY_CHECK(dst, eps);
}

typedef tuple<Size, MatType, double> ResizeAreaParams;
typedef TestBaseWithParam<ResizeAreaParams> ResizeAreaFixture;

OCL_PERF_TEST_P(ResizeAreaFixture, Resize,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134, ::testing::Values(0.3, 0.5, 0.6)))
{
    const ResizeAreaParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params);
    double scale = get<2>(params);
    const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale));
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);
    checkDeviceMaxMemoryAllocSize(dstSize, type);

    UMat src(srcSize, type), dst(dstSize, type);
    declare.in(src, WARMUP_RNG).out(dst);

    OCL_TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, cv::INTER_AREA);

    SANITY_CHECK(dst, eps);
}

///////////// Remap ////////////////////////

typedef tuple<Size, MatType, InterType> RemapParams;
typedef TestBaseWithParam<RemapParams> RemapFixture;

OCL_PERF_TEST_P(RemapFixture, Remap,
            ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES_134,
                               OCL_PERF_ENUM(InterType(INTER_NEAREST), InterType(INTER_LINEAR))))
{
    const RemapParams params = GetParam();
    const Size srcSize = get<0>(params);
    const int type = get<1>(params), interpolation = get<2>(params), borderMode = BORDER_CONSTANT;
    const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4;

    checkDeviceMaxMemoryAllocSize(srcSize, type);

    UMat src(srcSize, type), dst(srcSize, type);
    UMat xmap(srcSize, CV_32FC1), ymap(srcSize, CV_32FC1);

    {
        Mat _xmap = xmap.getMat(ACCESS_WRITE), _ymap = ymap.getMat(ACCESS_WRITE);
        for (int i = 0; i < srcSize.height; ++i)
        {
            float * const xmap_row = _xmap.ptr<float>(i);
            float * const ymap_row = _ymap.ptr<float>(i);

            for (int j = 0; j < srcSize.width; ++j)
            {
                xmap_row[j] = (j - srcSize.width * 0.5f) * 0.75f + srcSize.width * 0.5f;
                ymap_row[j] = (i - srcSize.height * 0.5f) * 0.75f + srcSize.height * 0.5f;
            }
        }
    }
    declare.in(src, WARMUP_RNG).in(xmap, ymap, WARMUP_READ).out(dst);

    OCL_TEST_CYCLE() cv::remap(src, dst, xmap, ymap, interpolation, borderMode);

    SANITY_CHECK(dst, eps);
}

} } // namespace cvtest::ocl

#endif // HAVE_OPENCL
<|endoftext|>


<commit_before>#include <pthread.h>
#include <sys/time.h>

#include "stinger_core/xmalloc.h"
#include "stinger_core/x86_full_empty.h"
#include "stinger_core/stinger_shared.h"
#include "rpc_state.h"
#include "stinger_core/stinger.h"

using namespace gt::stinger;

JSON_RPCServerState &
JSON_RPCServerState::get_server_state()
{
  static JSON_RPCServerState state;
  return state;
}

JSON_RPCServerState::JSON_RPCServerState() :
  next_session_id(1), session_lock(0),
  max_sessions(20), StingerMon()
{
}

JSON_RPCServerState::~JSON_RPCServerState()
{
}

void
JSON_RPCServerState::add_rpc_function(std::string name, JSON_RPCFunction * func)
{
  LOG_D_A("Adding RPC function %s", name.c_str());
  if(func)
    function_map[name] = func;
}

JSON_RPCFunction *
JSON_RPCServerState::get_rpc_function(std::string name)
{
  return function_map[name];
}

bool
JSON_RPCServerState::has_rpc_function(std::string name)
{
  return function_map.count(name) > 0;
}

void
JSON_RPCServerState::add_rpc_session(std::string name, JSON_RPCSession * func)
{
  LOG_D_A("Adding RPC session type %s", name.c_str());
  if(func)
    session_map[name] = func;
}

JSON_RPCSession *
JSON_RPCServerState::get_rpc_session(std::string name)
{
  return session_map[name];
}

bool
JSON_RPCServerState::has_rpc_session(std::string name)
{
  return session_map.count(name) > 0;
}

void
JSON_RPCServerState::update_algs(stinger_t * stinger_copy, std::string new_loc, int64_t new_sz,
                                 std::vector<StingerAlgState *> * new_algs, std::map<std::string, StingerAlgState *> * new_alg_map,
                                 const StingerBatch & batch)
{
  StingerMon::update_algs(stinger_copy, new_loc, new_sz, new_algs, new_alg_map, batch);

  readfe((uint64_t *)&session_lock);
  for(std::map<int64_t, JSON_RPCSession *>::iterator tmp = active_session_map.begin(); tmp != active_session_map.end(); tmp++)
  {
    JSON_RPCSession * session = tmp->second;
    session->lock();
    if (session->is_timed_out())
    {
      int64_t session_id = session->get_session_id();
      LOG_D_A ("Session %ld timed out. Destroying...", (long) session_id);
      delete active_session_map[session_id];
      active_session_map.erase (session_id);
    }
    else
    {
      session->update(batch);
      session->unlock();
    }
  }
  writeef((uint64_t *)&session_lock, 0);
}

bool
JSON_RPCFunction::contains_params(rpc_params_t * p, rapidjson::Value * params)
{
  if (!params)
    return true; //shouldn't this be return false?

  if (params->IsArray())
    return false;

  while(p->name)
  {
    if(!params->HasMember(p->name))
    {
      if(p->optional)
      {
        switch(p->type)
        {
        case TYPE_INT64:
        {
          *((int64_t *)p->output) = p->def;
        }
        break;
        case TYPE_STRING:
        {
          *((char **)p->output) = (char *) p->def;
        }
        break;
        case TYPE_DOUBLE:
        {
          *((double *)p->output) = (double) p->def;
        }
        break;
        case TYPE_BOOL:
        {
          *((bool *)p->output) = (bool) p->def;
        }
        break;
        case TYPE_ARRAY:
        {
          params_array_t * ptr = (params_array_t *) p->output;
          ptr->len = 0;
          ptr->arr = NULL;
        }
        break;
        }
      }
      else
      {
        return false;
      }
    }
    else
    {

      stinger_t * S = server_state->get_stinger();
      switch(p->type)
      {
      case TYPE_VERTEX:
      {
        if((*params)[p->name].IsInt64())
        {
          int64_t tmp = (*params)[p->name].GetInt64();
          if (tmp < 0 || tmp >= STINGER_MAX_LVERTICES)
            return false;
          *((int64_t *)p->output) = tmp;
        }
        else if((*params)[p->name].IsString())
        {
          int64_t tmp = stinger_mapping_lookup(S, (*params)[p->name].GetString(), (*params)[p->name].GetStringLength());
          if (tmp == -1)
            return false;
          *((int64_t *)p->output) = tmp;
        }
        else
        {
          return false;
        }
      }
      break;
      case TYPE_INT64:
      {
        if(!(*params)[p->name].IsInt64())
        {
          return false;
        }
        *((int64_t *)p->output) = (*params)[p->name].GetInt64();
      }
      break;
      case TYPE_STRING:
      {
        if(!(*params)[p->name].IsString())
        {
          return false;
        }
        *((char **)p->output) = (char *) (*params)[p->name].GetString();
      }
      break;
      case TYPE_DOUBLE:
      {
        if(!(*params)[p->name].IsDouble())
        {
          return false;
        }
        *((double *)p->output) = (*params)[p->name].GetDouble();
      }
      break;
      case TYPE_BOOL:
      {
        if(!(*params)[p->name].IsBool())
        {
          return false;
        }
        *((bool *)p->output) = (*params)[p->name].GetBool();
      }
      break;
      case TYPE_ARRAY:
      {
        if(!(*params)[p->name].IsArray())
        {
          return false;
        }
        params_array_t * ptr = (params_array_t *) p->output;
        ptr->len = (*params)[p->name].Size();
        ptr->arr = (int64_t *) xmalloc(sizeof(int64_t) * ptr->len);
        for (int64_t i = 0; i < ptr->len; i++)
        {
          if ((*params)[p->name][i].IsInt64())
          {
            int64_t tmp = (*params)[p->name][i].GetInt64();
            if (tmp < 0 || tmp >= STINGER_MAX_LVERTICES)
            {
              return false;
            }
            ptr->arr[i] = tmp;
          }
          else if ((*params)[p->name][i].IsString())
          {
            int64_t tmp = stinger_mapping_lookup(S, (*params)[p->name][i].GetString(), (*params)[p->name][i].GetStringLength());
            if (tmp == -1)
            {
              return false;
            }
            ptr->arr[i] = tmp;
          }
        }
      }
      break;
      }
    }
    p++;
  }
  return true;
}

void
JSON_RPCSession::lock()
{
  readfe((uint64_t *)&the_lock);
}

void
JSON_RPCSession::unlock()
{
  writeef((uint64_t *)&the_lock, 0);
}

bool
JSON_RPCSession::is_timed_out()
{
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return tv.tv_sec > last_touched + 30;
}

int64_t
JSON_RPCSession::reset_timeout()
{
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return last_touched = tv.tv_sec;
}

int64_t
JSON_RPCSession::get_session_id()
{
  return session_id;
}

int64_t
JSON_RPCSession::get_time_since()
{
  return last_touched;
}

params_array_t::params_array_t():arr(NULL) {}

params_array_t::~params_array_t()
{
  if (arr)
    free (arr);
}

int64_t
JSON_RPCServerState::get_next_session()
{
  readfe((uint64_t *)&session_lock);
  int64_t rtn = next_session_id++;
  writeef((uint64_t *)&session_lock, 0);
  return rtn;
}

int64_t
JSON_RPCServerState::add_session(int64_t session_id, JSON_RPCSession * session)
{
  readfe((uint64_t *)&session_lock);
  if (active_session_map.size() < max_sessions)
  {
    active_session_map.insert( std::pair<int64_t, JSON_RPCSession *>(session_id, session) );
  }
  else
  {
    session_id = -1;
  }
  writeef((uint64_t *)&session_lock, 0);
  return session_id;
}

int64_t
JSON_RPCServerState::destroy_session(int64_t session_id)
{
  readfe((uint64_t *)&session_lock);
  delete active_session_map[session_id];
  int64_t rtn = active_session_map.erase (session_id);
  writeef((uint64_t *)&session_lock, 0);
  return rtn;
}

int64_t
JSON_RPCServerState::get_num_sessions()
{
  readfe((uint64_t *)&session_lock);
  int64_t rtn = active_session_map.size();
  writeef((uint64_t *)&session_lock, 0);
  return rtn;
}

JSON_RPCSession *
JSON_RPCServerState::get_session(int64_t session_id)
{
  readfe((uint64_t *)&session_lock);
  std::map<int64_t, JSON_RPCSession *>::iterator tmp = active_session_map.find(session_id);
  writeef((uint64_t *)&session_lock, 0);

  if (tmp == active_session_map.end())
    return NULL;
  else
    return tmp->second;
}
<commit_msg>ran astyle -s2 --style=java on rpc_state.cpp<commit_after>#include <pthread.h>
#include <sys/time.h>

#include "stinger_core/xmalloc.h"
#include "stinger_core/x86_full_empty.h"
#include "stinger_core/stinger_shared.h"
#include "rpc_state.h"
#include "stinger_core/stinger.h"

using namespace gt::stinger;

JSON_RPCServerState &
JSON_RPCServerState::get_server_state() {
  static JSON_RPCServerState state;
  return state;
}

JSON_RPCServerState::JSON_RPCServerState() :
  next_session_id(1), session_lock(0),
  max_sessions(20), StingerMon() {
}

JSON_RPCServerState::~JSON_RPCServerState() {
}

void
JSON_RPCServerState::add_rpc_function(std::string name, JSON_RPCFunction * func) {
  LOG_D_A("Adding RPC function %s", name.c_str());
  if(func)
    function_map[name] = func;
}

JSON_RPCFunction *
JSON_RPCServerState::get_rpc_function(std::string name) {
  return function_map[name];
}

bool
JSON_RPCServerState::has_rpc_function(std::string name) {
  return function_map.count(name) > 0;
}

void
JSON_RPCServerState::add_rpc_session(std::string name, JSON_RPCSession * func) {
  LOG_D_A("Adding RPC session type %s", name.c_str());
  if(func)
    session_map[name] = func;
}

JSON_RPCSession *
JSON_RPCServerState::get_rpc_session(std::string name) {
  return session_map[name];
}

bool
JSON_RPCServerState::has_rpc_session(std::string name) {
  return session_map.count(name) > 0;
}

void
JSON_RPCServerState::update_algs(stinger_t * stinger_copy, std::string new_loc, int64_t new_sz,
                                 std::vector<StingerAlgState *> * new_algs, std::map<std::string, StingerAlgState *> * new_alg_map,
                                 const StingerBatch & batch) {
  StingerMon::update_algs(stinger_copy, new_loc, new_sz, new_algs, new_alg_map, batch);

  readfe((uint64_t *)&session_lock);
  for(std::map<int64_t, JSON_RPCSession *>::iterator tmp = active_session_map.begin(); tmp != active_session_map.end(); tmp++) {
    JSON_RPCSession * session = tmp->second;
    session->lock();
    if (session->is_timed_out()) {
      int64_t session_id = session->get_session_id();
      LOG_D_A ("Session %ld timed out. Destroying...", (long) session_id);
      delete active_session_map[session_id];
      active_session_map.erase (session_id);
    } else {
      session->update(batch);
      session->unlock();
    }
  }
  writeef((uint64_t *)&session_lock, 0);
}

bool
JSON_RPCFunction::contains_params(rpc_params_t * p, rapidjson::Value * params) {
  if (!params)
    return true; //shouldn't this be return false?

  if (params->IsArray())
    return false;

  while(p->name) {
    if(!params->HasMember(p->name)) {
      if(p->optional) {
        switch(p->type) {
        case TYPE_INT64: {
          *((int64_t *)p->output) = p->def;
        }
        break;
        case TYPE_STRING: {
          *((char **)p->output) = (char *) p->def;
        }
        break;
        case TYPE_DOUBLE: {
          *((double *)p->output) = (double) p->def;
        }
        break;
        case TYPE_BOOL: {
          *((bool *)p->output) = (bool) p->def;
        }
        break;
        case TYPE_ARRAY: {
          params_array_t * ptr = (params_array_t *) p->output;
          ptr->len = 0;
          ptr->arr = NULL;
        }
        break;
        }
      } else {
        return false;
      }
    } else {

      stinger_t * S = server_state->get_stinger();
      switch(p->type) {
      case TYPE_VERTEX: {
        if((*params)[p->name].IsInt64()) {
          int64_t tmp = (*params)[p->name].GetInt64();
          if (tmp < 0 || tmp >= STINGER_MAX_LVERTICES)
            return false;
          *((int64_t *)p->output) = tmp;
        } else if((*params)[p->name].IsString()) {
          int64_t tmp = stinger_mapping_lookup(S, (*params)[p->name].GetString(), (*params)[p->name].GetStringLength());
          if (tmp == -1)
            return false;
          *((int64_t *)p->output) = tmp;
        } else {
          return false;
        }
      }
      break;
      case TYPE_INT64: {
        if(!(*params)[p->name].IsInt64()) {
          return false;
        }
        *((int64_t *)p->output) = (*params)[p->name].GetInt64();
      }
      break;
      case TYPE_STRING: {
        if(!(*params)[p->name].IsString()) {
          return false;
        }
        *((char **)p->output) = (char *) (*params)[p->name].GetString();
      }
      break;
      case TYPE_DOUBLE: {
        if(!(*params)[p->name].IsDouble()) {
          return false;
        }
        *((double *)p->output) = (*params)[p->name].GetDouble();
      }
      break;
      case TYPE_BOOL: {
        if(!(*params)[p->name].IsBool()) {
          return false;
        }
        *((bool *)p->output) = (*params)[p->name].GetBool();
      }
      break;
      case TYPE_ARRAY: {
        if(!(*params)[p->name].IsArray()) {
          return false;
        }
        params_array_t * ptr = (params_array_t *) p->output;
        ptr->len = (*params)[p->name].Size();
        ptr->arr = (int64_t *) xmalloc(sizeof(int64_t) * ptr->len);
        for (int64_t i = 0; i < ptr->len; i++) {
          if ((*params)[p->name][i].IsInt64()) {
            int64_t tmp = (*params)[p->name][i].GetInt64();
            if (tmp < 0 || tmp >= STINGER_MAX_LVERTICES) {
              return false;
            }
            ptr->arr[i] = tmp;
          } else if ((*params)[p->name][i].IsString()) {
            int64_t tmp = stinger_mapping_lookup(S, (*params)[p->name][i].GetString(), (*params)[p->name][i].GetStringLength());
            if (tmp == -1) {
              return false;
            }
            ptr->arr[i] = tmp;
          }
        }
      }
      break;
      }
    }
    p++;
  }
  return true;
}

void
JSON_RPCSession::lock() {
  readfe((uint64_t *)&the_lock);
}

void
JSON_RPCSession::unlock() {
  writeef((uint64_t *)&the_lock, 0);
}

bool
JSON_RPCSession::is_timed_out() {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return tv.tv_sec > last_touched + 30;
}

int64_t
JSON_RPCSession::reset_timeout() {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return last_touched = tv.tv_sec;
}

int64_t
JSON_RPCSession::get_session_id() {
  return session_id;
}

int64_t
JSON_RPCSession::get_time_since() {
  return last_touched;
}

params_array_t::params_array_t():arr(NULL) {}

params_array_t::~params_array_t() {
  if (arr)
    free (arr);
}

int64_t
JSON_RPCServerState::get_next_session() {
  readfe((uint64_t *)&session_lock);
  int64_t rtn = next_session_id++;
  writeef((uint64_t *)&session_lock, 0);
  return rtn;
}

int64_t
JSON_RPCServerState::add_session(int64_t session_id, JSON_RPCSession * session) {
  readfe((uint64_t *)&session_lock);
  if (active_session_map.size() < max_sessions) {
    active_session_map.insert( std::pair<int64_t, JSON_RPCSession *>(session_id, session) );
  } else {
    session_id = -1;
  }
  writeef((uint64_t *)&session_lock, 0);
  return session_id;
}

int64_t
JSON_RPCServerState::destroy_session(int64_t session_id) {
  readfe((uint64_t *)&session_lock);
  delete active_session_map[session_id];
  int64_t rtn = active_session_map.erase (session_id);
  writeef((uint64_t *)&session_lock, 0);
  return rtn;
}

int64_t
JSON_RPCServerState::get_num_sessions() {
  readfe((uint64_t *)&session_lock);
  int64_t rtn = active_session_map.size();
  writeef((uint64_t *)&session_lock, 0);
  return rtn;
}

JSON_RPCSession *
JSON_RPCServerState::get_session(int64_t session_id) {
  readfe((uint64_t *)&session_lock);
  std::map<int64_t, JSON_RPCSession *>::iterator tmp = active_session_map.find(session_id);
  writeef((uint64_t *)&session_lock, 0);

  if (tmp == active_session_map.end())
    return NULL;
  else
    return tmp->second;
}
<|endoftext|>


<commit_before>// Copyright (c) 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.

#include <algorithm>

#include "net/proxy/proxy_server.h"

#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "net/base/net_util.h"
#include "net/http/http_util.h"

namespace net {

namespace {

// Returns the default port number for proxy server with the
// specified scheme. Returns -1 if unknown.
int GetDefaultPortForScheme(ProxyServer::Scheme scheme) {
  switch (scheme) {
    case ProxyServer::SCHEME_HTTP:
      return 80;
    case ProxyServer::SCHEME_SOCKS4:
    case ProxyServer::SCHEME_SOCKS5:
      return 1080;
    default:
      return -1;
  }
}

// Parse the proxy type from a PAC string, to a ProxyServer::Scheme.
// This mapping is case-insensitive. If no type could be matched
// returns SCHEME_INVALID.
ProxyServer::Scheme GetSchemeFromPacType(std::string::const_iterator begin,
                                         std::string::const_iterator end) {
  if (LowerCaseEqualsASCII(begin, end, "proxy"))
    return ProxyServer::SCHEME_HTTP;
  if (LowerCaseEqualsASCII(begin, end, "socks")) {
    // Default to v4 for compatibility. This is because the SOCKS4 vs SOCKS5
    // notation didn't originally exist, so if a client returns SOCKS they
    // really meant SOCKS4.
    return ProxyServer::SCHEME_SOCKS4;
  }
  if (LowerCaseEqualsASCII(begin, end, "socks4"))
    return ProxyServer::SCHEME_SOCKS4;
  if (LowerCaseEqualsASCII(begin, end, "socks5"))
    return ProxyServer::SCHEME_SOCKS5;
  if (LowerCaseEqualsASCII(begin, end, "direct"))
    return ProxyServer::SCHEME_DIRECT;

  return ProxyServer::SCHEME_INVALID;
}

// Parse the proxy scheme from a URL-like representation, to a
// ProxyServer::Scheme.  This corresponds with the values used in
// ProxyServer::ToURI(). If no type could be matched, returns SCHEME_INVALID.
ProxyServer::Scheme GetSchemeFromURI(std::string::const_iterator begin,
                                     std::string::const_iterator end) {
  if (LowerCaseEqualsASCII(begin, end, "http"))
    return ProxyServer::SCHEME_HTTP;
  if (LowerCaseEqualsASCII(begin, end, "socks4"))
    return ProxyServer::SCHEME_SOCKS4;
  if (LowerCaseEqualsASCII(begin, end, "socks5"))
    return ProxyServer::SCHEME_SOCKS5;
  if (LowerCaseEqualsASCII(begin, end, "direct"))
    return ProxyServer::SCHEME_DIRECT;
  return ProxyServer::SCHEME_INVALID;
}

}  // namespace

const std::string& ProxyServer::host() const {
  // Doesn't make sense to call this if the URI scheme doesn't
  // have concept of a host.
  DCHECK(is_valid() && !is_direct());
  return host_;
}

int ProxyServer::port() const {
  // Doesn't make sense to call this if the URI scheme doesn't
  // have concept of a port.
  DCHECK(is_valid() && !is_direct());
  return port_;
}

std::string ProxyServer::host_and_port() const {
  // Doesn't make sense to call this if the URI scheme doesn't
  // have concept of a host.
  DCHECK(is_valid() && !is_direct());
  return host_ + ":" + IntToString(port_);
}

// static
ProxyServer ProxyServer::FromURI(const std::string& uri) {
  return FromURI(uri.begin(), uri.end());
}

// static
ProxyServer ProxyServer::FromURI(std::string::const_iterator begin,
                                 std::string::const_iterator end) {
  // We will default to HTTP if no scheme specifier was given.
  Scheme scheme = SCHEME_HTTP;

  // Trim the leading/trailing whitespace.
  HttpUtil::TrimLWS(&begin, &end);

  // Check for [<scheme> "://"]
  std::string::const_iterator colon = std::find(begin, end, ':');
  if (colon != end &&
      (end - colon) >= 3 &&
      *(colon + 1) == '/' &&
      *(colon + 2) == '/') {
    scheme = GetSchemeFromURI(begin, colon);
    begin = colon + 3;  // Skip past the "://"
  }

  // Now parse the <host>[":"<port>].
  return FromSchemeHostAndPort(scheme, begin, end);
}

std::string ProxyServer::ToURI() const {
  switch (scheme_) {
    case SCHEME_DIRECT:
      return "direct://";
    case SCHEME_HTTP:
      // Leave off "http://" since it is our default scheme.
      return host_and_port();
    case SCHEME_SOCKS4:
      return std::string("socks4://") + host_and_port();
    case SCHEME_SOCKS5:
      return std::string("socks5://") + host_and_port();
    default:
      // Got called with an invalid scheme.
      NOTREACHED();
      return std::string();
  }
}

// static
ProxyServer ProxyServer::FromPacString(const std::string& pac_string) {
  return FromPacString(pac_string.begin(), pac_string.end());
}

ProxyServer ProxyServer::FromPacString(std::string::const_iterator begin,
                                       std::string::const_iterator end) {
  // Trim the leading/trailing whitespace.
  HttpUtil::TrimLWS(&begin, &end);

  // Input should match:
  // "DIRECT" | ( <type> 1*(LWS) <host-and-port> )

  // Start by finding the first space (if any).
  std::string::const_iterator space;
  for (space = begin; space != end; ++space) {
    if (HttpUtil::IsLWS(*space)) {
      break;
    }
  }

  // Everything to the left of the space is the scheme.
  Scheme scheme = GetSchemeFromPacType(begin, space);

  // And everything to the right of the space is the
  // <host>[":" <port>].
  return FromSchemeHostAndPort(scheme, space, end);
}

std::string ProxyServer::ToPacString() const {
    switch (scheme_) {
    case SCHEME_DIRECT:
      return "DIRECT";
    case SCHEME_HTTP:
      return std::string("PROXY ") + host_and_port();
    case SCHEME_SOCKS4:
      // For compatibility send SOCKS instead of SOCKS4.
      return std::string("SOCKS ") + host_and_port();
    case SCHEME_SOCKS5:
      return std::string("SOCKS5 ") + host_and_port();
    default:
      // Got called with an invalid scheme.
      NOTREACHED();
      return std::string();
  }
}

// static
ProxyServer ProxyServer::FromSchemeHostAndPort(
    Scheme scheme,
    std::string::const_iterator begin,
    std::string::const_iterator end) {

  // Trim leading/trailing space.
  HttpUtil::TrimLWS(&begin, &end);

  if (scheme == SCHEME_DIRECT && begin != end)
    return ProxyServer();  // Invalid -- DIRECT cannot have a host/port.

  std::string host;
  int port = -1;

  if (scheme != SCHEME_INVALID && scheme != SCHEME_DIRECT) {
    // If the scheme has a host/port, parse it.
    bool ok = net::GetHostAndPort(begin, end, &host, &port);
    if (!ok)
      return ProxyServer();  // Invalid -- failed parsing <host>[":"<port>]
  }

  // Choose a default port number if none was given.
  if (port == -1)
    port = GetDefaultPortForScheme(scheme);

  return ProxyServer(scheme, host, port);
}

}  // namespace net

<commit_msg>Fix header order.<commit_after>// Copyright (c) 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.

#include "net/proxy/proxy_server.h"

#include <algorithm>

#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "net/base/net_util.h"
#include "net/http/http_util.h"

namespace net {

namespace {

// Returns the default port number for proxy server with the
// specified scheme. Returns -1 if unknown.
int GetDefaultPortForScheme(ProxyServer::Scheme scheme) {
  switch (scheme) {
    case ProxyServer::SCHEME_HTTP:
      return 80;
    case ProxyServer::SCHEME_SOCKS4:
    case ProxyServer::SCHEME_SOCKS5:
      return 1080;
    default:
      return -1;
  }
}

// Parse the proxy type from a PAC string, to a ProxyServer::Scheme.
// This mapping is case-insensitive. If no type could be matched
// returns SCHEME_INVALID.
ProxyServer::Scheme GetSchemeFromPacType(std::string::const_iterator begin,
                                         std::string::const_iterator end) {
  if (LowerCaseEqualsASCII(begin, end, "proxy"))
    return ProxyServer::SCHEME_HTTP;
  if (LowerCaseEqualsASCII(begin, end, "socks")) {
    // Default to v4 for compatibility. This is because the SOCKS4 vs SOCKS5
    // notation didn't originally exist, so if a client returns SOCKS they
    // really meant SOCKS4.
    return ProxyServer::SCHEME_SOCKS4;
  }
  if (LowerCaseEqualsASCII(begin, end, "socks4"))
    return ProxyServer::SCHEME_SOCKS4;
  if (LowerCaseEqualsASCII(begin, end, "socks5"))
    return ProxyServer::SCHEME_SOCKS5;
  if (LowerCaseEqualsASCII(begin, end, "direct"))
    return ProxyServer::SCHEME_DIRECT;

  return ProxyServer::SCHEME_INVALID;
}

// Parse the proxy scheme from a URL-like representation, to a
// ProxyServer::Scheme.  This corresponds with the values used in
// ProxyServer::ToURI(). If no type could be matched, returns SCHEME_INVALID.
ProxyServer::Scheme GetSchemeFromURI(std::string::const_iterator begin,
                                     std::string::const_iterator end) {
  if (LowerCaseEqualsASCII(begin, end, "http"))
    return ProxyServer::SCHEME_HTTP;
  if (LowerCaseEqualsASCII(begin, end, "socks4"))
    return ProxyServer::SCHEME_SOCKS4;
  if (LowerCaseEqualsASCII(begin, end, "socks5"))
    return ProxyServer::SCHEME_SOCKS5;
  if (LowerCaseEqualsASCII(begin, end, "direct"))
    return ProxyServer::SCHEME_DIRECT;
  return ProxyServer::SCHEME_INVALID;
}

}  // namespace

const std::string& ProxyServer::host() const {
  // Doesn't make sense to call this if the URI scheme doesn't
  // have concept of a host.
  DCHECK(is_valid() && !is_direct());
  return host_;
}

int ProxyServer::port() const {
  // Doesn't make sense to call this if the URI scheme doesn't
  // have concept of a port.
  DCHECK(is_valid() && !is_direct());
  return port_;
}

std::string ProxyServer::host_and_port() const {
  // Doesn't make sense to call this if the URI scheme doesn't
  // have concept of a host.
  DCHECK(is_valid() && !is_direct());
  return host_ + ":" + IntToString(port_);
}

// static
ProxyServer ProxyServer::FromURI(const std::string& uri) {
  return FromURI(uri.begin(), uri.end());
}

// static
ProxyServer ProxyServer::FromURI(std::string::const_iterator begin,
                                 std::string::const_iterator end) {
  // We will default to HTTP if no scheme specifier was given.
  Scheme scheme = SCHEME_HTTP;

  // Trim the leading/trailing whitespace.
  HttpUtil::TrimLWS(&begin, &end);

  // Check for [<scheme> "://"]
  std::string::const_iterator colon = std::find(begin, end, ':');
  if (colon != end &&
      (end - colon) >= 3 &&
      *(colon + 1) == '/' &&
      *(colon + 2) == '/') {
    scheme = GetSchemeFromURI(begin, colon);
    begin = colon + 3;  // Skip past the "://"
  }

  // Now parse the <host>[":"<port>].
  return FromSchemeHostAndPort(scheme, begin, end);
}

std::string ProxyServer::ToURI() const {
  switch (scheme_) {
    case SCHEME_DIRECT:
      return "direct://";
    case SCHEME_HTTP:
      // Leave off "http://" since it is our default scheme.
      return host_and_port();
    case SCHEME_SOCKS4:
      return std::string("socks4://") + host_and_port();
    case SCHEME_SOCKS5:
      return std::string("socks5://") + host_and_port();
    default:
      // Got called with an invalid scheme.
      NOTREACHED();
      return std::string();
  }
}

// static
ProxyServer ProxyServer::FromPacString(const std::string& pac_string) {
  return FromPacString(pac_string.begin(), pac_string.end());
}

ProxyServer ProxyServer::FromPacString(std::string::const_iterator begin,
                                       std::string::const_iterator end) {
  // Trim the leading/trailing whitespace.
  HttpUtil::TrimLWS(&begin, &end);

  // Input should match:
  // "DIRECT" | ( <type> 1*(LWS) <host-and-port> )

  // Start by finding the first space (if any).
  std::string::const_iterator space;
  for (space = begin; space != end; ++space) {
    if (HttpUtil::IsLWS(*space)) {
      break;
    }
  }

  // Everything to the left of the space is the scheme.
  Scheme scheme = GetSchemeFromPacType(begin, space);

  // And everything to the right of the space is the
  // <host>[":" <port>].
  return FromSchemeHostAndPort(scheme, space, end);
}

std::string ProxyServer::ToPacString() const {
    switch (scheme_) {
    case SCHEME_DIRECT:
      return "DIRECT";
    case SCHEME_HTTP:
      return std::string("PROXY ") + host_and_port();
    case SCHEME_SOCKS4:
      // For compatibility send SOCKS instead of SOCKS4.
      return std::string("SOCKS ") + host_and_port();
    case SCHEME_SOCKS5:
      return std::string("SOCKS5 ") + host_and_port();
    default:
      // Got called with an invalid scheme.
      NOTREACHED();
      return std::string();
  }
}

// static
ProxyServer ProxyServer::FromSchemeHostAndPort(
    Scheme scheme,
    std::string::const_iterator begin,
    std::string::const_iterator end) {

  // Trim leading/trailing space.
  HttpUtil::TrimLWS(&begin, &end);

  if (scheme == SCHEME_DIRECT && begin != end)
    return ProxyServer();  // Invalid -- DIRECT cannot have a host/port.

  std::string host;
  int port = -1;

  if (scheme != SCHEME_INVALID && scheme != SCHEME_DIRECT) {
    // If the scheme has a host/port, parse it.
    bool ok = net::GetHostAndPort(begin, end, &host, &port);
    if (!ok)
      return ProxyServer();  // Invalid -- failed parsing <host>[":"<port>]
  }

  // Choose a default port number if none was given.
  if (port == -1)
    port = GetDefaultPortForScheme(scheme);

  return ProxyServer(scheme, host, port);
}

}  // namespace net

<|endoftext|>


<commit_before>// Copyright (c) 2012, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// linux_ptrace_dumper.cc: Implement google_breakpad::LinuxPtraceDumper.
// See linux_ptrace_dumper.h for detals.
// This class was originally splitted from google_breakpad::LinuxDumper.

// This code deals with the mechanics of getting information about a crashed
// process. Since this code may run in a compromised address space, the same
// rules apply as detailed at the top of minidump_writer.h: no libc calls and
// use the alternative allocator.

#include "client/linux/minidump_writer/linux_ptrace_dumper.h"

#include <asm/ptrace.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/wait.h>

#include "client/linux/minidump_writer/directory_reader.h"
#include "client/linux/minidump_writer/line_reader.h"
#include "common/linux/linux_libc_support.h"
#include "third_party/lss/linux_syscall_support.h"

// Suspends a thread by attaching to it.
static bool SuspendThread(pid_t pid) {
  // This may fail if the thread has just died or debugged.
  errno = 0;
  if (sys_ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 &&
      errno != 0) {
    return false;
  }
  while (sys_waitpid(pid, NULL, __WALL) < 0) {
    if (errno != EINTR) {
      sys_ptrace(PTRACE_DETACH, pid, NULL, NULL);
      return false;
    }
  }
#if defined(__i386) || defined(__x86_64)
  // On x86, the stack pointer is NULL or -1, when executing trusted code in
  // the seccomp sandbox. Not only does this cause difficulties down the line
  // when trying to dump the thread's stack, it also results in the minidumps
  // containing information about the trusted threads. This information is
  // generally completely meaningless and just pollutes the minidumps.
  // We thus test the stack pointer and exclude any threads that are part of
  // the seccomp sandbox's trusted code.
  user_regs_struct regs;
  if (sys_ptrace(PTRACE_GETREGS, pid, NULL, &regs) == -1 ||
#if defined(__i386)
      !regs.esp
#elif defined(__x86_64)
      !regs.rsp
#endif
      ) {
    sys_ptrace(PTRACE_DETACH, pid, NULL, NULL);
    return false;
  }
#endif
  return true;
}

// Resumes a thread by detaching from it.
static bool ResumeThread(pid_t pid) {
  return sys_ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0;
}

namespace google_breakpad {

LinuxPtraceDumper::LinuxPtraceDumper(pid_t pid)
    : LinuxDumper(pid),
      threads_suspended_(false) {
}

bool LinuxPtraceDumper::BuildProcPath(char* path, pid_t pid,
                                      const char* node) const {
  if (!path || !node || pid <= 0)
    return false;

  size_t node_len = my_strlen(node);
  if (node_len == 0)
    return false;

  const unsigned pid_len = my_int_len(pid);
  const size_t total_length = 6 + pid_len + 1 + node_len;
  if (total_length >= NAME_MAX)
    return false;

  memcpy(path, "/proc/", 6);
  my_itos(path + 6, pid, pid_len);
  path[6 + pid_len] = '/';
  memcpy(path + 6 + pid_len + 1, node, node_len);
  path[total_length] = '\0';
  return true;
}

void LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
                                        const void* src, size_t length) {
  unsigned long tmp = 55;
  size_t done = 0;
  static const size_t word_size = sizeof(tmp);
  uint8_t* const local = (uint8_t*) dest;
  uint8_t* const remote = (uint8_t*) src;

  while (done < length) {
    const size_t l = (length - done > word_size) ? word_size : (length - done);
    if (sys_ptrace(PTRACE_PEEKDATA, child, remote + done, &tmp) == -1) {
      tmp = 0;
    }
    memcpy(local + done, &tmp, l);
    done += l;
  }
}

// Read thread info from /proc/$pid/status.
// Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailable,
// these members are set to -1. Returns true iff all three members are
// available.
bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
  if (index >= threads_.size())
    return false;

  pid_t tid = threads_[index];

  assert(info != NULL);
  char status_path[NAME_MAX];
  if (!BuildProcPath(status_path, tid, "status"))
    return false;

  const int fd = sys_open(status_path, O_RDONLY, 0);
  if (fd < 0)
    return false;

  LineReader* const line_reader = new(allocator_) LineReader(fd);
  const char* line;
  unsigned line_len;

  info->ppid = info->tgid = -1;

  while (line_reader->GetNextLine(&line, &line_len)) {
    if (my_strncmp("Tgid:\t", line, 6) == 0) {
      my_strtoui(&info->tgid, line + 6);
    } else if (my_strncmp("PPid:\t", line, 6) == 0) {
      my_strtoui(&info->ppid, line + 6);
    }

    line_reader->PopLine(line_len);
  }

  if (info->ppid == -1 || info->tgid == -1)
    return false;

  if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1) {
    return false;
  }

#if !defined(__ANDROID__)
  if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) {
    return false;
  }
#endif

#if defined(__i386)
  if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1)
    return false;
#endif

#if defined(__i386) || defined(__x86_64)
  for (unsigned i = 0; i < ThreadInfo::kNumDebugRegisters; ++i) {
    if (sys_ptrace(
        PTRACE_PEEKUSER, tid,
        reinterpret_cast<void*> (offsetof(struct user,
                                          u_debugreg[0]) + i *
                                 sizeof(debugreg_t)),
        &info->dregs[i]) == -1) {
      return false;
    }
  }
#endif

  const uint8_t* stack_pointer;
#if defined(__i386)
  memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
#elif defined(__x86_64)
  memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
#elif defined(__ARM_EABI__)
  memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
#else
#error "This code hasn't been ported to your platform yet."
#endif

  return GetStackInfo(&info->stack, &info->stack_len,
                      (uintptr_t) stack_pointer);
}

bool LinuxPtraceDumper::IsPostMortem() const {
  return false;
}

bool LinuxPtraceDumper::ThreadsSuspend() {
  if (threads_suspended_)
    return true;
  for (size_t i = 0; i < threads_.size(); ++i) {
    if (!SuspendThread(threads_[i])) {
      // If the thread either disappeared before we could attach to it, or if
      // it was part of the seccomp sandbox's trusted code, it is OK to
      // silently drop it from the minidump.
      memmove(&threads_[i], &threads_[i+1],
              (threads_.size() - i - 1) * sizeof(threads_[i]));
      threads_.resize(threads_.size() - 1);
      --i;
    }
  }
  threads_suspended_ = true;
  return threads_.size() > 0;
}

bool LinuxPtraceDumper::ThreadsResume() {
  if (!threads_suspended_)
    return false;
  bool good = true;
  for (size_t i = 0; i < threads_.size(); ++i)
    good &= ResumeThread(threads_[i]);
  threads_suspended_ = false;
  return good;
}

// Parse /proc/$pid/task to list all the threads of the process identified by
// pid.
bool LinuxPtraceDumper::EnumerateThreads() {
  char task_path[NAME_MAX];
  if (!BuildProcPath(task_path, pid_, "task"))
    return false;

  const int fd = sys_open(task_path, O_RDONLY | O_DIRECTORY, 0);
  if (fd < 0)
    return false;
  DirectoryReader* dir_reader = new(allocator_) DirectoryReader(fd);

  // The directory may contain duplicate entries which we filter by assuming
  // that they are consecutive.
  int last_tid = -1;
  const char* dent_name;
  while (dir_reader->GetNextEntry(&dent_name)) {
    if (my_strcmp(dent_name, ".") &&
        my_strcmp(dent_name, "..")) {
      int tid = 0;
      if (my_strtoui(&tid, dent_name) &&
          last_tid != tid) {
        last_tid = tid;
        threads_.push_back(tid);
      }
    }
    dir_reader->PopEntry();
  }

  sys_close(fd);
  return true;
}

}  // namespace google_breakpad
<commit_msg>Fix file descriptor leak in GetThreadInfoByIndex<commit_after>// Copyright (c) 2012, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// linux_ptrace_dumper.cc: Implement google_breakpad::LinuxPtraceDumper.
// See linux_ptrace_dumper.h for detals.
// This class was originally splitted from google_breakpad::LinuxDumper.

// This code deals with the mechanics of getting information about a crashed
// process. Since this code may run in a compromised address space, the same
// rules apply as detailed at the top of minidump_writer.h: no libc calls and
// use the alternative allocator.

#include "client/linux/minidump_writer/linux_ptrace_dumper.h"

#include <asm/ptrace.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/wait.h>

#include "client/linux/minidump_writer/directory_reader.h"
#include "client/linux/minidump_writer/line_reader.h"
#include "common/linux/linux_libc_support.h"
#include "third_party/lss/linux_syscall_support.h"

// Suspends a thread by attaching to it.
static bool SuspendThread(pid_t pid) {
  // This may fail if the thread has just died or debugged.
  errno = 0;
  if (sys_ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 &&
      errno != 0) {
    return false;
  }
  while (sys_waitpid(pid, NULL, __WALL) < 0) {
    if (errno != EINTR) {
      sys_ptrace(PTRACE_DETACH, pid, NULL, NULL);
      return false;
    }
  }
#if defined(__i386) || defined(__x86_64)
  // On x86, the stack pointer is NULL or -1, when executing trusted code in
  // the seccomp sandbox. Not only does this cause difficulties down the line
  // when trying to dump the thread's stack, it also results in the minidumps
  // containing information about the trusted threads. This information is
  // generally completely meaningless and just pollutes the minidumps.
  // We thus test the stack pointer and exclude any threads that are part of
  // the seccomp sandbox's trusted code.
  user_regs_struct regs;
  if (sys_ptrace(PTRACE_GETREGS, pid, NULL, &regs) == -1 ||
#if defined(__i386)
      !regs.esp
#elif defined(__x86_64)
      !regs.rsp
#endif
      ) {
    sys_ptrace(PTRACE_DETACH, pid, NULL, NULL);
    return false;
  }
#endif
  return true;
}

// Resumes a thread by detaching from it.
static bool ResumeThread(pid_t pid) {
  return sys_ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0;
}

namespace google_breakpad {

LinuxPtraceDumper::LinuxPtraceDumper(pid_t pid)
    : LinuxDumper(pid),
      threads_suspended_(false) {
}

bool LinuxPtraceDumper::BuildProcPath(char* path, pid_t pid,
                                      const char* node) const {
  if (!path || !node || pid <= 0)
    return false;

  size_t node_len = my_strlen(node);
  if (node_len == 0)
    return false;

  const unsigned pid_len = my_int_len(pid);
  const size_t total_length = 6 + pid_len + 1 + node_len;
  if (total_length >= NAME_MAX)
    return false;

  memcpy(path, "/proc/", 6);
  my_itos(path + 6, pid, pid_len);
  path[6 + pid_len] = '/';
  memcpy(path + 6 + pid_len + 1, node, node_len);
  path[total_length] = '\0';
  return true;
}

void LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
                                        const void* src, size_t length) {
  unsigned long tmp = 55;
  size_t done = 0;
  static const size_t word_size = sizeof(tmp);
  uint8_t* const local = (uint8_t*) dest;
  uint8_t* const remote = (uint8_t*) src;

  while (done < length) {
    const size_t l = (length - done > word_size) ? word_size : (length - done);
    if (sys_ptrace(PTRACE_PEEKDATA, child, remote + done, &tmp) == -1) {
      tmp = 0;
    }
    memcpy(local + done, &tmp, l);
    done += l;
  }
}

// Read thread info from /proc/$pid/status.
// Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailable,
// these members are set to -1. Returns true iff all three members are
// available.
bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
  if (index >= threads_.size())
    return false;

  pid_t tid = threads_[index];

  assert(info != NULL);
  char status_path[NAME_MAX];
  if (!BuildProcPath(status_path, tid, "status"))
    return false;

  const int fd = sys_open(status_path, O_RDONLY, 0);
  if (fd < 0)
    return false;

  LineReader* const line_reader = new(allocator_) LineReader(fd);
  const char* line;
  unsigned line_len;

  info->ppid = info->tgid = -1;

  while (line_reader->GetNextLine(&line, &line_len)) {
    if (my_strncmp("Tgid:\t", line, 6) == 0) {
      my_strtoui(&info->tgid, line + 6);
    } else if (my_strncmp("PPid:\t", line, 6) == 0) {
      my_strtoui(&info->ppid, line + 6);
    }

    line_reader->PopLine(line_len);
  }
  sys_close(fd);

  if (info->ppid == -1 || info->tgid == -1)
    return false;

  if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1) {
    return false;
  }

#if !defined(__ANDROID__)
  if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) {
    return false;
  }
#endif

#if defined(__i386)
  if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1)
    return false;
#endif

#if defined(__i386) || defined(__x86_64)
  for (unsigned i = 0; i < ThreadInfo::kNumDebugRegisters; ++i) {
    if (sys_ptrace(
        PTRACE_PEEKUSER, tid,
        reinterpret_cast<void*> (offsetof(struct user,
                                          u_debugreg[0]) + i *
                                 sizeof(debugreg_t)),
        &info->dregs[i]) == -1) {
      return false;
    }
  }
#endif

  const uint8_t* stack_pointer;
#if defined(__i386)
  memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
#elif defined(__x86_64)
  memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
#elif defined(__ARM_EABI__)
  memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
#else
#error "This code hasn't been ported to your platform yet."
#endif

  return GetStackInfo(&info->stack, &info->stack_len,
                      (uintptr_t) stack_pointer);
}

bool LinuxPtraceDumper::IsPostMortem() const {
  return false;
}

bool LinuxPtraceDumper::ThreadsSuspend() {
  if (threads_suspended_)
    return true;
  for (size_t i = 0; i < threads_.size(); ++i) {
    if (!SuspendThread(threads_[i])) {
      // If the thread either disappeared before we could attach to it, or if
      // it was part of the seccomp sandbox's trusted code, it is OK to
      // silently drop it from the minidump.
      memmove(&threads_[i], &threads_[i+1],
              (threads_.size() - i - 1) * sizeof(threads_[i]));
      threads_.resize(threads_.size() - 1);
      --i;
    }
  }
  threads_suspended_ = true;
  return threads_.size() > 0;
}

bool LinuxPtraceDumper::ThreadsResume() {
  if (!threads_suspended_)
    return false;
  bool good = true;
  for (size_t i = 0; i < threads_.size(); ++i)
    good &= ResumeThread(threads_[i]);
  threads_suspended_ = false;
  return good;
}

// Parse /proc/$pid/task to list all the threads of the process identified by
// pid.
bool LinuxPtraceDumper::EnumerateThreads() {
  char task_path[NAME_MAX];
  if (!BuildProcPath(task_path, pid_, "task"))
    return false;

  const int fd = sys_open(task_path, O_RDONLY | O_DIRECTORY, 0);
  if (fd < 0)
    return false;
  DirectoryReader* dir_reader = new(allocator_) DirectoryReader(fd);

  // The directory may contain duplicate entries which we filter by assuming
  // that they are consecutive.
  int last_tid = -1;
  const char* dent_name;
  while (dir_reader->GetNextEntry(&dent_name)) {
    if (my_strcmp(dent_name, ".") &&
        my_strcmp(dent_name, "..")) {
      int tid = 0;
      if (my_strtoui(&tid, dent_name) &&
          last_tid != tid) {
        last_tid = tid;
        threads_.push_back(tid);
      }
    }
    dir_reader->PopEntry();
  }

  sys_close(fd);
  return true;
}

}  // namespace google_breakpad
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: res_services.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2006-03-29 12:42:32 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef EXTENSIONS_RESOURCE_SERVICES_HXX
#define EXTENSIONS_RESOURCE_SERVICES_HXX

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif
/** === end UNO includes === **/

#ifndef _CPPUHELPER_FACTORY_HXX_
#include <cppuhelper/factory.hxx>
#endif

//........................................................................
namespace res
{
//........................................................................

    struct ComponentInfo
    {
        /// services supported by the component
        ::com::sun::star::uno::Sequence< ::rtl::OUString >  aSupportedServices;
        /// implementation name of the component
        ::rtl::OUString                                     sImplementationName;
        /** name of the singleton instance of the component, if it is a singleton, empty otherwise
            If the component is a singleton, aSupportedServices must contain exactly one element.
        */
        ::rtl::OUString                                     sSingletonName;
        /// factory for creating the component
        ::cppu::ComponentFactoryFunc                        pFactory;
    };

    ComponentInfo   getComponentInfo_VclStringResourceLoader();
    ComponentInfo   getComponentInfo_OpenOfficeResourceLoader();

//........................................................................
}   // namespace res
//........................................................................

#endif // EXTENSIONS_RESOURCE_SERVICES_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.2.372); FILE MERGED 2008/04/01 15:15:23 thb 1.2.372.3: #i85898# Stripping all external header guards 2008/04/01 12:29:56 thb 1.2.372.2: #i85898# Stripping all external header guards 2008/03/31 12:32:04 rt 1.2.372.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: res_services.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef EXTENSIONS_RESOURCE_SERVICES_HXX
#define EXTENSIONS_RESOURCE_SERVICES_HXX

/** === begin UNO includes === **/
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/XInterface.hpp>
/** === end UNO includes === **/
#include <cppuhelper/factory.hxx>

//........................................................................
namespace res
{
//........................................................................

    struct ComponentInfo
    {
        /// services supported by the component
        ::com::sun::star::uno::Sequence< ::rtl::OUString >  aSupportedServices;
        /// implementation name of the component
        ::rtl::OUString                                     sImplementationName;
        /** name of the singleton instance of the component, if it is a singleton, empty otherwise
            If the component is a singleton, aSupportedServices must contain exactly one element.
        */
        ::rtl::OUString                                     sSingletonName;
        /// factory for creating the component
        ::cppu::ComponentFactoryFunc                        pFactory;
    };

    ComponentInfo   getComponentInfo_VclStringResourceLoader();
    ComponentInfo   getComponentInfo_OpenOfficeResourceLoader();

//........................................................................
}   // namespace res
//........................................................................

#endif // EXTENSIONS_RESOURCE_SERVICES_HXX
<|endoftext|>