<commit_before>/*
 *  Copyright 2017 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.
 */

#include "pc/rtp_transceiver.h"

#include <string>

#include "absl/algorithm/container.h"
#include "pc/channel_manager.h"
#include "pc/rtp_media_utils.h"
#include "pc/rtp_parameters_conversion.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {

RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
    : unified_plan_(false), media_type_(media_type) {
  RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
             media_type == cricket::MEDIA_TYPE_VIDEO);
}

RtpTransceiver::RtpTransceiver(
    rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
    rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
        receiver,
    cricket::ChannelManager* channel_manager)
    : unified_plan_(true),
      media_type_(sender->media_type()),
      channel_manager_(channel_manager) {
  RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
             media_type_ == cricket::MEDIA_TYPE_VIDEO);
  RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
  senders_.push_back(sender);
  receivers_.push_back(receiver);
}

RtpTransceiver::~RtpTransceiver() {
  Stop();
}

void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
  // Cannot set a non-null channel on a stopped transceiver.
  if (stopped_ && channel) {
    return;
  }

  if (channel) {
    RTC_DCHECK_EQ(media_type(), channel->media_type());
  }

  if (channel_) {
    channel_->SignalFirstPacketReceived().disconnect(this);
  }

  channel_ = channel;

  if (channel_) {
    channel_->SignalFirstPacketReceived().connect(
        this, &RtpTransceiver::OnFirstPacketReceived);
  }

  for (const auto& sender : senders_) {
    sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
                                                 : nullptr);
  }

  for (const auto& receiver : receivers_) {
    if (!channel_) {
      receiver->internal()->Stop();
    }

    receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
                                                   : nullptr);
  }
}

void RtpTransceiver::AddSender(
    rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
  RTC_DCHECK(!stopped_);
  RTC_DCHECK(!unified_plan_);
  RTC_DCHECK(sender);
  RTC_DCHECK_EQ(media_type(), sender->media_type());
  RTC_DCHECK(!absl::c_linear_search(senders_, sender));
  senders_.push_back(sender);
}

bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
  RTC_DCHECK(!unified_plan_);
  if (sender) {
    RTC_DCHECK_EQ(media_type(), sender->media_type());
  }
  auto it = absl::c_find(senders_, sender);
  if (it == senders_.end()) {
    return false;
  }
  (*it)->internal()->Stop();
  senders_.erase(it);
  return true;
}

void RtpTransceiver::AddReceiver(
    rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
        receiver) {
  RTC_DCHECK(!stopped_);
  RTC_DCHECK(!unified_plan_);
  RTC_DCHECK(receiver);
  RTC_DCHECK_EQ(media_type(), receiver->media_type());
  RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
  receivers_.push_back(receiver);
}

bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
  RTC_DCHECK(!unified_plan_);
  if (receiver) {
    RTC_DCHECK_EQ(media_type(), receiver->media_type());
  }
  auto it = absl::c_find(receivers_, receiver);
  if (it == receivers_.end()) {
    return false;
  }
  (*it)->internal()->Stop();
  receivers_.erase(it);
  return true;
}

rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
  RTC_DCHECK(unified_plan_);
  RTC_CHECK_EQ(1u, senders_.size());
  return senders_[0]->internal();
}

rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
    const {
  RTC_DCHECK(unified_plan_);
  RTC_CHECK_EQ(1u, receivers_.size());
  return receivers_[0]->internal();
}

cricket::MediaType RtpTransceiver::media_type() const {
  return media_type_;
}

absl::optional<std::string> RtpTransceiver::mid() const {
  return mid_;
}

void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
  for (const auto& receiver : receivers_) {
    receiver->internal()->NotifyFirstPacketReceived();
  }
}

rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
  RTC_DCHECK(unified_plan_);
  RTC_CHECK_EQ(1u, senders_.size());
  return senders_[0];
}

rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
  RTC_DCHECK(unified_plan_);
  RTC_CHECK_EQ(1u, receivers_.size());
  return receivers_[0];
}

void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
  RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
                   << ") current direction from "
                   << (current_direction_ ? RtpTransceiverDirectionToString(
                                                *current_direction_)
                                          : "<not set>")
                   << " to " << RtpTransceiverDirectionToString(direction)
                   << ".";
  current_direction_ = direction;
  if (RtpTransceiverDirectionHasSend(*current_direction_)) {
    has_ever_been_used_to_send_ = true;
  }
}

void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
  fired_direction_ = direction;
}

bool RtpTransceiver::stopped() const {
  return stopped_;
}

RtpTransceiverDirection RtpTransceiver::direction() const {
  return direction_;
}

void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) {
  if (stopped()) {
    return;
  }
  if (new_direction == direction_) {
    return;
  }
  direction_ = new_direction;
  SignalNegotiationNeeded();
}

absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
    const {
  return current_direction_;
}

absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
    const {
  return fired_direction_;
}

void RtpTransceiver::Stop() {
  for (const auto& sender : senders_) {
    sender->internal()->Stop();
  }
  for (const auto& receiver : receivers_) {
    receiver->internal()->Stop();
  }
  stopped_ = true;
  current_direction_ = absl::nullopt;
}

RTCError RtpTransceiver::SetCodecPreferences(
    rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
  RTC_DCHECK(unified_plan_);

  // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
  // to codecs and abort these steps.
  if (codec_capabilities.empty()) {
    codec_preferences_.clear();
    return RTCError::OK();
  }

  // 4. Remove any duplicate values in codecs.
  std::vector<RtpCodecCapability> codecs;
  absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
                         [&codecs](const RtpCodecCapability& codec) {
                           return absl::c_linear_search(codecs, codec);
                         });

  if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
    std::vector<cricket::AudioCodec> audio_codecs;

    std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
    channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
    channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);

    // 6. If the intersection between codecs and
    // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
    // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
    // RED or FEC codecs or is an empty set, throw InvalidModificationError.
    // This ensures that we always have something to offer, regardless of
    // transceiver.direction.

    if (!absl::c_any_of(
            codecs, [&recv_codecs](const RtpCodecCapability& codec) {
              return codec.name != cricket::kRtxCodecName &&
                     codec.name != cricket::kRedCodecName &&
                     codec.name != cricket::kFlexfecCodecName &&
                     absl::c_any_of(
                         recv_codecs,
                         [&codec](const cricket::AudioCodec& recv_codec) {
                           return recv_codec.MatchesCapability(codec);
                         });
            })) {
      return RTCError(RTCErrorType::INVALID_MODIFICATION,
                      "Invalid codec preferences: Missing codec from recv "
                      "codec capabilities.");
    }

    if (!absl::c_any_of(
            codecs, [&send_codecs](const RtpCodecCapability& codec) {
              return codec.name != cricket::kRtxCodecName &&
                     codec.name != cricket::kRedCodecName &&
                     codec.name != cricket::kFlexfecCodecName &&
                     absl::c_any_of(
                         send_codecs,
                         [&codec](const cricket::AudioCodec& send_codec) {
                           return send_codec.MatchesCapability(codec);
                         });
            })) {
      return RTCError(RTCErrorType::INVALID_MODIFICATION,
                      "Invalid codec preferences: Missing codec from send "
                      "codec capabilities.");
    }

    // 7. Let codecCapabilities be the union of
    // RTCRtpSender.getCapabilities(kind).codecs and
    // RTCRtpReceiver.getCapabilities(kind).codecs. 8.1 For each codec in
    // codecs, If codec is not in codecCapabilities, throw
    // InvalidModificationError.
    for (const auto& codec_preference : codecs) {
      bool is_recv_codec = absl::c_any_of(
          recv_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
            return codec.MatchesCapability(codec_preference);
          });

      bool is_send_codec = absl::c_any_of(
          send_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
            return codec.MatchesCapability(codec_preference);
          });

      if (!is_recv_codec && !is_send_codec) {
        return RTCError(
            RTCErrorType::INVALID_MODIFICATION,
            std::string(
                "Invalid codec preferences: invalid codec with name \"") +
                codec_preference.name + "\".");
      }
    }
  } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
    std::vector<cricket::VideoCodec> video_codecs;
    // Video codecs are both for the receive and send side, so the checks are
    // simpler than the audio ones.
    channel_manager_->GetSupportedVideoCodecs(&video_codecs);

    // Validate codecs
    for (const auto& codec_preference : codecs) {
      if (!absl::c_any_of(video_codecs, [&codec_preference](
                                            const cricket::VideoCodec& codec) {
            return codec.MatchesCapability(codec_preference);
          })) {
        return RTCError(
            RTCErrorType::INVALID_MODIFICATION,
            std::string(
                "Invalid codec preferences: invalid codec with name \"") +
                codec_preference.name + "\".");
      }
    }
  }

  // Check we have a real codec (not just rtx, red or fec)
  if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
        return codec.name == cricket::kRtxCodecName ||
               codec.name == cricket::kRedCodecName ||
               codec.name == cricket::kUlpfecCodecName;
      })) {
    return RTCError(RTCErrorType::INVALID_MODIFICATION,
                    "Invalid codec preferences: codec list must have a non "
                    "RTX, RED or FEC entry.");
  }

  codec_preferences_ = codecs;

  return RTCError::OK();
}

}  // namespace webrtc
<commit_msg>Fix Heap-use-after-free.<commit_after>/*
 *  Copyright 2017 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.
 */

#include "pc/rtp_transceiver.h"

#include <string>

#include "absl/algorithm/container.h"
#include "pc/channel_manager.h"
#include "pc/rtp_media_utils.h"
#include "pc/rtp_parameters_conversion.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {

RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
    : unified_plan_(false), media_type_(media_type) {
  RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
             media_type == cricket::MEDIA_TYPE_VIDEO);
}

RtpTransceiver::RtpTransceiver(
    rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
    rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
        receiver,
    cricket::ChannelManager* channel_manager)
    : unified_plan_(true),
      media_type_(sender->media_type()),
      channel_manager_(channel_manager) {
  RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
             media_type_ == cricket::MEDIA_TYPE_VIDEO);
  RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
  senders_.push_back(sender);
  receivers_.push_back(receiver);
}

RtpTransceiver::~RtpTransceiver() {
  Stop();
}

void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
  // Cannot set a non-null channel on a stopped transceiver.
  if (stopped_ && channel) {
    return;
  }

  if (channel) {
    RTC_DCHECK_EQ(media_type(), channel->media_type());
  }

  if (channel_) {
    channel_->SignalFirstPacketReceived().disconnect(this);
  }

  channel_ = channel;

  if (channel_) {
    channel_->SignalFirstPacketReceived().connect(
        this, &RtpTransceiver::OnFirstPacketReceived);
  }

  for (const auto& sender : senders_) {
    sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
                                                 : nullptr);
  }

  for (const auto& receiver : receivers_) {
    if (!channel_) {
      receiver->internal()->Stop();
    }

    receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
                                                   : nullptr);
  }
}

void RtpTransceiver::AddSender(
    rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
  RTC_DCHECK(!stopped_);
  RTC_DCHECK(!unified_plan_);
  RTC_DCHECK(sender);
  RTC_DCHECK_EQ(media_type(), sender->media_type());
  RTC_DCHECK(!absl::c_linear_search(senders_, sender));
  senders_.push_back(sender);
}

bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
  RTC_DCHECK(!unified_plan_);
  if (sender) {
    RTC_DCHECK_EQ(media_type(), sender->media_type());
  }
  auto it = absl::c_find(senders_, sender);
  if (it == senders_.end()) {
    return false;
  }
  (*it)->internal()->Stop();
  senders_.erase(it);
  return true;
}

void RtpTransceiver::AddReceiver(
    rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
        receiver) {
  RTC_DCHECK(!stopped_);
  RTC_DCHECK(!unified_plan_);
  RTC_DCHECK(receiver);
  RTC_DCHECK_EQ(media_type(), receiver->media_type());
  RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
  receivers_.push_back(receiver);
}

bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
  RTC_DCHECK(!unified_plan_);
  if (receiver) {
    RTC_DCHECK_EQ(media_type(), receiver->media_type());
  }
  auto it = absl::c_find(receivers_, receiver);
  if (it == receivers_.end()) {
    return false;
  }
  (*it)->internal()->Stop();
  // After the receiver has been removed, there's no guarantee that the
  // contained media channel isn't deleted shortly after this. To make sure that
  // the receiver doesn't spontaneously try to use it's (potentially stale)
  // media channel reference, we clear it out.
  (*it)->internal()->SetMediaChannel(nullptr);
  receivers_.erase(it);
  return true;
}

rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
  RTC_DCHECK(unified_plan_);
  RTC_CHECK_EQ(1u, senders_.size());
  return senders_[0]->internal();
}

rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
    const {
  RTC_DCHECK(unified_plan_);
  RTC_CHECK_EQ(1u, receivers_.size());
  return receivers_[0]->internal();
}

cricket::MediaType RtpTransceiver::media_type() const {
  return media_type_;
}

absl::optional<std::string> RtpTransceiver::mid() const {
  return mid_;
}

void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
  for (const auto& receiver : receivers_) {
    receiver->internal()->NotifyFirstPacketReceived();
  }
}

rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
  RTC_DCHECK(unified_plan_);
  RTC_CHECK_EQ(1u, senders_.size());
  return senders_[0];
}

rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
  RTC_DCHECK(unified_plan_);
  RTC_CHECK_EQ(1u, receivers_.size());
  return receivers_[0];
}

void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
  RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
                   << ") current direction from "
                   << (current_direction_ ? RtpTransceiverDirectionToString(
                                                *current_direction_)
                                          : "<not set>")
                   << " to " << RtpTransceiverDirectionToString(direction)
                   << ".";
  current_direction_ = direction;
  if (RtpTransceiverDirectionHasSend(*current_direction_)) {
    has_ever_been_used_to_send_ = true;
  }
}

void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
  fired_direction_ = direction;
}

bool RtpTransceiver::stopped() const {
  return stopped_;
}

RtpTransceiverDirection RtpTransceiver::direction() const {
  return direction_;
}

void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) {
  if (stopped()) {
    return;
  }
  if (new_direction == direction_) {
    return;
  }
  direction_ = new_direction;
  SignalNegotiationNeeded();
}

absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
    const {
  return current_direction_;
}

absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
    const {
  return fired_direction_;
}

void RtpTransceiver::Stop() {
  for (const auto& sender : senders_) {
    sender->internal()->Stop();
  }
  for (const auto& receiver : receivers_) {
    receiver->internal()->Stop();
  }
  stopped_ = true;
  current_direction_ = absl::nullopt;
}

RTCError RtpTransceiver::SetCodecPreferences(
    rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
  RTC_DCHECK(unified_plan_);

  // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
  // to codecs and abort these steps.
  if (codec_capabilities.empty()) {
    codec_preferences_.clear();
    return RTCError::OK();
  }

  // 4. Remove any duplicate values in codecs.
  std::vector<RtpCodecCapability> codecs;
  absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
                         [&codecs](const RtpCodecCapability& codec) {
                           return absl::c_linear_search(codecs, codec);
                         });

  if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
    std::vector<cricket::AudioCodec> audio_codecs;

    std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
    channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
    channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);

    // 6. If the intersection between codecs and
    // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
    // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
    // RED or FEC codecs or is an empty set, throw InvalidModificationError.
    // This ensures that we always have something to offer, regardless of
    // transceiver.direction.

    if (!absl::c_any_of(
            codecs, [&recv_codecs](const RtpCodecCapability& codec) {
              return codec.name != cricket::kRtxCodecName &&
                     codec.name != cricket::kRedCodecName &&
                     codec.name != cricket::kFlexfecCodecName &&
                     absl::c_any_of(
                         recv_codecs,
                         [&codec](const cricket::AudioCodec& recv_codec) {
                           return recv_codec.MatchesCapability(codec);
                         });
            })) {
      return RTCError(RTCErrorType::INVALID_MODIFICATION,
                      "Invalid codec preferences: Missing codec from recv "
                      "codec capabilities.");
    }

    if (!absl::c_any_of(
            codecs, [&send_codecs](const RtpCodecCapability& codec) {
              return codec.name != cricket::kRtxCodecName &&
                     codec.name != cricket::kRedCodecName &&
                     codec.name != cricket::kFlexfecCodecName &&
                     absl::c_any_of(
                         send_codecs,
                         [&codec](const cricket::AudioCodec& send_codec) {
                           return send_codec.MatchesCapability(codec);
                         });
            })) {
      return RTCError(RTCErrorType::INVALID_MODIFICATION,
                      "Invalid codec preferences: Missing codec from send "
                      "codec capabilities.");
    }

    // 7. Let codecCapabilities be the union of
    // RTCRtpSender.getCapabilities(kind).codecs and
    // RTCRtpReceiver.getCapabilities(kind).codecs. 8.1 For each codec in
    // codecs, If codec is not in codecCapabilities, throw
    // InvalidModificationError.
    for (const auto& codec_preference : codecs) {
      bool is_recv_codec = absl::c_any_of(
          recv_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
            return codec.MatchesCapability(codec_preference);
          });

      bool is_send_codec = absl::c_any_of(
          send_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
            return codec.MatchesCapability(codec_preference);
          });

      if (!is_recv_codec && !is_send_codec) {
        return RTCError(
            RTCErrorType::INVALID_MODIFICATION,
            std::string(
                "Invalid codec preferences: invalid codec with name \"") +
                codec_preference.name + "\".");
      }
    }
  } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
    std::vector<cricket::VideoCodec> video_codecs;
    // Video codecs are both for the receive and send side, so the checks are
    // simpler than the audio ones.
    channel_manager_->GetSupportedVideoCodecs(&video_codecs);

    // Validate codecs
    for (const auto& codec_preference : codecs) {
      if (!absl::c_any_of(video_codecs, [&codec_preference](
                                            const cricket::VideoCodec& codec) {
            return codec.MatchesCapability(codec_preference);
          })) {
        return RTCError(
            RTCErrorType::INVALID_MODIFICATION,
            std::string(
                "Invalid codec preferences: invalid codec with name \"") +
                codec_preference.name + "\".");
      }
    }
  }

  // Check we have a real codec (not just rtx, red or fec)
  if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
        return codec.name == cricket::kRtxCodecName ||
               codec.name == cricket::kRedCodecName ||
               codec.name == cricket::kUlpfecCodecName;
      })) {
    return RTCError(RTCErrorType::INVALID_MODIFICATION,
                    "Invalid codec preferences: codec list must have a non "
                    "RTX, RED or FEC entry.");
  }

  codec_preferences_ = codecs;

  return RTCError::OK();
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkMorphologicalOperationsWidget.h"
#include <mitkSliceNavigationController.h>
#include <mitkMorphologicalOperations.h>
#include "mitkProgressBar.h"

static const char* const HelpText = "Select a segmentation above";

QmitkMorphologicalOperationsWidget::QmitkMorphologicalOperationsWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent)
: QmitkSegmentationUtilityWidget(timeNavigationController, parent)
{
   m_Controls.setupUi(this);

   m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::SegmentationPredicate);
   m_Controls.dataSelectionWidget->SetHelpText(HelpText);

   connect(m_Controls.btnClosing, SIGNAL(clicked()), this, SLOT(OnbtnClosingClicked()) );
   connect(m_Controls.btnOpening, SIGNAL(clicked()), this, SLOT(OnbtnOpeningClicked()) );
   connect(m_Controls.btnDilatation, SIGNAL(clicked()), this, SLOT(OnbtnDilatationClicked()) );
   connect(m_Controls.btnErosion, SIGNAL(clicked()), this, SLOT(OnbtnErosionClicked()) );
   connect(m_Controls.btnFillHoles, SIGNAL(clicked()), this, SLOT(OnbtnFillHolesClicked()) );

   connect(m_Controls.radioButtonMorphoCross, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked()) );
   connect(m_Controls.radioButtonMorphoBall, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked()) );

   connect(m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
}

QmitkMorphologicalOperationsWidget::~QmitkMorphologicalOperationsWidget()
{
}

void QmitkMorphologicalOperationsWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection)
{
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);

   if (node.IsNotNull())
   {
      m_Controls.dataSelectionWidget->SetHelpText("");
      this->EnableButtons(true);
   }
   else
   {
      m_Controls.dataSelectionWidget->SetHelpText(HelpText);
      this->EnableButtons(false);
   }
}

void QmitkMorphologicalOperationsWidget::EnableButtons(bool enable)
{
   m_Controls.btnClosing->setEnabled(enable);
   m_Controls.btnDilatation->setEnabled(enable);
   m_Controls.btnErosion->setEnabled(enable);
   m_Controls.btnFillHoles->setEnabled(enable);
   m_Controls.btnOpening->setEnabled(enable);
}

void QmitkMorphologicalOperationsWidget::OnRadioButtonsClicked()
{
   m_Controls.sliderMorphFactor->setEnabled(
      m_Controls.radioButtonMorphoBall->isChecked());

   m_Controls.spinBoxMorphFactor->setEnabled(
      m_Controls.radioButtonMorphoBall->isChecked());
}

void QmitkMorphologicalOperationsWidget::OnbtnClosingClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());
   mitk::MorphologicalOperations::StructuralElementType structuralElement;

   if (m_Controls.radioButtonMorphoBall->isChecked())
      structuralElement = mitk::MorphologicalOperations::BALL;
   else
      structuralElement = mitk::MorphologicalOperations::CUBE;

   try
   {
      mitk::MorphologicalOperations::Closing(image, m_Controls.spinBoxMorphFactor->value(), structuralElement);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}

void QmitkMorphologicalOperationsWidget::OnbtnOpeningClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());
   mitk::MorphologicalOperations::StructuralElementType structuralElement;

   if (m_Controls.radioButtonMorphoBall->isChecked())
      structuralElement = mitk::MorphologicalOperations::BALL;
   else
      structuralElement = mitk::MorphologicalOperations::CUBE;

   try
   {
      mitk::MorphologicalOperations::Opening(image, m_Controls.spinBoxMorphFactor->value(), structuralElement);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}

void QmitkMorphologicalOperationsWidget::OnbtnDilatationClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());
   mitk::MorphologicalOperations::StructuralElementType structuralElement;

   if (m_Controls.radioButtonMorphoBall->isChecked())
      structuralElement = mitk::MorphologicalOperations::BALL;
   else
      structuralElement = mitk::MorphologicalOperations::CUBE;

   try
   {
      mitk::MorphologicalOperations::Dilate(image, m_Controls.spinBoxMorphFactor->value(), structuralElement);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}

void QmitkMorphologicalOperationsWidget::OnbtnErosionClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());
   mitk::MorphologicalOperations::StructuralElementType structuralElement;

   if (m_Controls.radioButtonMorphoBall->isChecked())
      structuralElement = mitk::MorphologicalOperations::BALL;
   else
      structuralElement = mitk::MorphologicalOperations::CUBE;

   try
   {
      mitk::MorphologicalOperations::Erode(image, m_Controls.spinBoxMorphFactor->value(), structuralElement);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}

void QmitkMorphologicalOperationsWidget::OnbtnFillHolesClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());

   try
   {
      mitk::MorphologicalOperations::Fillhole(image);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}
<commit_msg>Fixed wrong initialization. Now buttons are enabled correctly<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkMorphologicalOperationsWidget.h"
#include <mitkSliceNavigationController.h>
#include <mitkMorphologicalOperations.h>
#include "mitkProgressBar.h"

static const char* const HelpText = "Select a segmentation above";

QmitkMorphologicalOperationsWidget::QmitkMorphologicalOperationsWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent)
: QmitkSegmentationUtilityWidget(timeNavigationController, parent)
{
   m_Controls.setupUi(this);

   m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::SegmentationPredicate);
   m_Controls.dataSelectionWidget->SetHelpText(HelpText);

   connect(m_Controls.btnClosing, SIGNAL(clicked()), this, SLOT(OnbtnClosingClicked()) );
   connect(m_Controls.btnOpening, SIGNAL(clicked()), this, SLOT(OnbtnOpeningClicked()) );
   connect(m_Controls.btnDilatation, SIGNAL(clicked()), this, SLOT(OnbtnDilatationClicked()) );
   connect(m_Controls.btnErosion, SIGNAL(clicked()), this, SLOT(OnbtnErosionClicked()) );
   connect(m_Controls.btnFillHoles, SIGNAL(clicked()), this, SLOT(OnbtnFillHolesClicked()) );

   connect(m_Controls.radioButtonMorphoCross, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked()) );
   connect(m_Controls.radioButtonMorphoBall, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked()) );

   connect(m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)),
           this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));

   if( m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull())
   {
     this->OnSelectionChanged( 0, m_Controls.dataSelectionWidget->GetSelection(0));
   }
}

QmitkMorphologicalOperationsWidget::~QmitkMorphologicalOperationsWidget()
{
}

void QmitkMorphologicalOperationsWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection)
{
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);

   if (node.IsNotNull())
   {
      m_Controls.dataSelectionWidget->SetHelpText("");
      this->EnableButtons(true);
   }
   else
   {
      m_Controls.dataSelectionWidget->SetHelpText(HelpText);
      this->EnableButtons(false);
   }
}

void QmitkMorphologicalOperationsWidget::EnableButtons(bool enable)
{
   m_Controls.btnClosing->setEnabled(enable);
   m_Controls.btnDilatation->setEnabled(enable);
   m_Controls.btnErosion->setEnabled(enable);
   m_Controls.btnFillHoles->setEnabled(enable);
   m_Controls.btnOpening->setEnabled(enable);
}

void QmitkMorphologicalOperationsWidget::OnRadioButtonsClicked()
{
   m_Controls.sliderMorphFactor->setEnabled(
      m_Controls.radioButtonMorphoBall->isChecked());

   m_Controls.spinBoxMorphFactor->setEnabled(
      m_Controls.radioButtonMorphoBall->isChecked());
}

void QmitkMorphologicalOperationsWidget::OnbtnClosingClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());
   mitk::MorphologicalOperations::StructuralElementType structuralElement;

   if (m_Controls.radioButtonMorphoBall->isChecked())
      structuralElement = mitk::MorphologicalOperations::BALL;
   else
      structuralElement = mitk::MorphologicalOperations::CUBE;

   try
   {
      mitk::MorphologicalOperations::Closing(image, m_Controls.spinBoxMorphFactor->value(), structuralElement);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}

void QmitkMorphologicalOperationsWidget::OnbtnOpeningClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());
   mitk::MorphologicalOperations::StructuralElementType structuralElement;

   if (m_Controls.radioButtonMorphoBall->isChecked())
      structuralElement = mitk::MorphologicalOperations::BALL;
   else
      structuralElement = mitk::MorphologicalOperations::CUBE;

   try
   {
      mitk::MorphologicalOperations::Opening(image, m_Controls.spinBoxMorphFactor->value(), structuralElement);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}

void QmitkMorphologicalOperationsWidget::OnbtnDilatationClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());
   mitk::MorphologicalOperations::StructuralElementType structuralElement;

   if (m_Controls.radioButtonMorphoBall->isChecked())
      structuralElement = mitk::MorphologicalOperations::BALL;
   else
      structuralElement = mitk::MorphologicalOperations::CUBE;

   try
   {
      mitk::MorphologicalOperations::Dilate(image, m_Controls.spinBoxMorphFactor->value(), structuralElement);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}

void QmitkMorphologicalOperationsWidget::OnbtnErosionClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());
   mitk::MorphologicalOperations::StructuralElementType structuralElement;

   if (m_Controls.radioButtonMorphoBall->isChecked())
      structuralElement = mitk::MorphologicalOperations::BALL;
   else
      structuralElement = mitk::MorphologicalOperations::CUBE;

   try
   {
      mitk::MorphologicalOperations::Erode(image, m_Controls.spinBoxMorphFactor->value(), structuralElement);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}

void QmitkMorphologicalOperationsWidget::OnbtnFillHolesClicked()
{
   QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); //Enable Busy Cursor

   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
   mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
   mitk::Image::Pointer image = dynamic_cast< mitk::Image* >(node->GetData());

   try
   {
      mitk::MorphologicalOperations::Fillhole(image);
   }
   catch ( itk::ExceptionObject* itkObj)
   {
      MITK_WARN << "Exception caught: " << itkObj->GetDescription();
      QApplication::restoreOverrideCursor(); //Disable Busy Cursor
   }

   node->SetData(image);
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();

   QApplication::restoreOverrideCursor(); //Disable Busy Cursor
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2013-2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/
/**
 * @file navigator_rtl.cpp
 * Helper class to access RTL
 * @author Julian Oes <julian@oes.ch>
 * @author Anton Babushkin <anton.babushkin@me.com>
 */

#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <fcntl.h>

#include <mavlink/mavlink_log.h>
#include <systemlib/err.h>
#include <geo/geo.h>

#include <uORB/uORB.h>
#include <navigator/navigation.h>
#include <uORB/topics/home_position.h>

#include "navigator.h"
#include "rtl.h"

#define DELAY_SIGMA	0.01f

RTL::RTL(Navigator *navigator, const char *name) :
	MissionBlock(navigator, name),
	_rtl_state(RTL_STATE_NONE),
	_param_return_alt(this, "RTL_RETURN_ALT", false),
	_param_descend_alt(this, "RTL_DESCEND_ALT", false),
	_param_land_delay(this, "RTL_LAND_DELAY", false)
{
	/* load initial params */
	updateParams();
	/* initial reset */
	on_inactive();
}

RTL::~RTL()
{
}

void
RTL::on_inactive()
{
	/* reset RTL state only if setpoint moved */
	if (!_navigator->get_can_loiter_at_sp()) {
		_rtl_state = RTL_STATE_NONE;
	}
}

void
RTL::on_activation()
{
	/* decide where to enter the RTL procedure when we switch into it */
	if (_rtl_state == RTL_STATE_NONE) {
		/* for safety reasons don't go into RTL if landed */
		if (_navigator->get_vstatus()->condition_landed) {
			_rtl_state = RTL_STATE_LANDED;
			mavlink_log_critical(_navigator->get_mavlink_fd(), "no RTL when landed");

		/* if lower than return altitude, climb up first */
		} else if (_navigator->get_global_position()->alt < _navigator->get_home_position()->alt
			   + _param_return_alt.get()) {
			_rtl_state = RTL_STATE_CLIMB;

		/* otherwise go straight to return */
		} else {
			/* set altitude setpoint to current altitude */
			_rtl_state = RTL_STATE_RETURN;
			_mission_item.altitude_is_relative = false;
			_mission_item.altitude = _navigator->get_global_position()->alt;
		}

	}

	set_rtl_item();
}

void
RTL::on_active()
{
	if (_rtl_state != RTL_STATE_LANDED && is_mission_item_reached()) {
		advance_rtl();
		set_rtl_item();
	}
}

void
RTL::set_rtl_item()
{
	struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();

	/* make sure we have the latest params */
	updateParams();

	set_previous_pos_setpoint();
	_navigator->set_can_loiter_at_sp(false);

	switch (_rtl_state) {
	case RTL_STATE_CLIMB: {
		float climb_alt = _navigator->get_home_position()->alt + _param_return_alt.get();

		_mission_item.lat = _navigator->get_global_position()->lat;
		_mission_item.lon = _navigator->get_global_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = climb_alt;
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_WAYPOINT;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: climb to %d m (%d m above home)",
			(int)(climb_alt),
			(int)(climb_alt - _navigator->get_home_position()->alt));
		break;
	}

	case RTL_STATE_RETURN: {
		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		 // don't change altitude

		 if (pos_sp_triplet->previous.valid) {
		 	/* if previous setpoint is valid then use it to calculate heading to home */
		 	_mission_item.yaw = get_bearing_to_next_waypoint(
		 	        pos_sp_triplet->previous.lat, pos_sp_triplet->previous.lon,
		 	        _mission_item.lat, _mission_item.lon);

		 } else {
		 	/* else use current position */
		 	_mission_item.yaw = get_bearing_to_next_waypoint(
		 	        _navigator->get_global_position()->lat, _navigator->get_global_position()->lon,
		 	        _mission_item.lat, _mission_item.lon);
		 }
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_WAYPOINT;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: return at %d m (%d m above home)",
			(int)(_mission_item.altitude),
			(int)(_mission_item.altitude - _navigator->get_home_position()->alt));
		break;
	}

	case RTL_STATE_DESCEND: {
		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = _navigator->get_home_position()->alt + _param_descend_alt.get();
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_LOITER_TIME_LIMIT;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = false;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: descend to %d m (%d m above home)",
			(int)(_mission_item.altitude),
			(int)(_mission_item.altitude - _navigator->get_home_position()->alt));
		break;
	}

	case RTL_STATE_LOITER: {
		bool autoland = _param_land_delay.get() > -DELAY_SIGMA;

		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = _navigator->get_home_position()->alt + _param_descend_alt.get();
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = autoland ? NAV_CMD_LOITER_TIME_LIMIT : NAV_CMD_LOITER_UNLIMITED;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = _param_land_delay.get() < 0.0f ? 0.0f : _param_land_delay.get();
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = autoland;
		_mission_item.origin = ORIGIN_ONBOARD;

		_navigator->set_can_loiter_at_sp(true);

		if (autoland) {
			mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: loiter %.1fs", (double)_mission_item.time_inside);

		} else {
			mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: completed, loiter");
		}
		break;
	}

	case RTL_STATE_LAND: {
		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = _navigator->get_home_position()->alt;
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_LAND;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: land at home");
		break;
	}

	case RTL_STATE_LANDED: {
		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = _navigator->get_home_position()->alt;
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_IDLE;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: completed, landed");
		break;
	}

	default:
		break;
	}

	reset_mission_item_reached();

	/* convert mission item to current position setpoint and make it valid */
	mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
	pos_sp_triplet->next.valid = false;

	_navigator->set_position_setpoint_triplet_updated();
}

void
RTL::advance_rtl()
{
	switch (_rtl_state) {
	case RTL_STATE_CLIMB:
		_rtl_state = RTL_STATE_RETURN;
		break;

	case RTL_STATE_RETURN:
		_rtl_state = RTL_STATE_DESCEND;
		break;

	case RTL_STATE_DESCEND:
		/* only go to land if autoland is enabled */
		if (_param_land_delay.get() < -DELAY_SIGMA || _param_land_delay.get() > DELAY_SIGMA) {
			_rtl_state = RTL_STATE_LOITER;

		} else {
			_rtl_state = RTL_STATE_LAND;
		}
		break;

	case RTL_STATE_LOITER:
		_rtl_state = RTL_STATE_LAND;
		break;

	case RTL_STATE_LAND:
		_rtl_state = RTL_STATE_LANDED;
		break;

	default:
		break;
	}
}
<commit_msg>Navigator: Use yaw of home position<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2013-2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/
/**
 * @file navigator_rtl.cpp
 * Helper class to access RTL
 * @author Julian Oes <julian@oes.ch>
 * @author Anton Babushkin <anton.babushkin@me.com>
 */

#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <fcntl.h>

#include <mavlink/mavlink_log.h>
#include <systemlib/err.h>
#include <geo/geo.h>

#include <uORB/uORB.h>
#include <navigator/navigation.h>
#include <uORB/topics/home_position.h>

#include "navigator.h"
#include "rtl.h"

#define DELAY_SIGMA	0.01f

RTL::RTL(Navigator *navigator, const char *name) :
	MissionBlock(navigator, name),
	_rtl_state(RTL_STATE_NONE),
	_param_return_alt(this, "RTL_RETURN_ALT", false),
	_param_descend_alt(this, "RTL_DESCEND_ALT", false),
	_param_land_delay(this, "RTL_LAND_DELAY", false)
{
	/* load initial params */
	updateParams();
	/* initial reset */
	on_inactive();
}

RTL::~RTL()
{
}

void
RTL::on_inactive()
{
	/* reset RTL state only if setpoint moved */
	if (!_navigator->get_can_loiter_at_sp()) {
		_rtl_state = RTL_STATE_NONE;
	}
}

void
RTL::on_activation()
{
	/* decide where to enter the RTL procedure when we switch into it */
	if (_rtl_state == RTL_STATE_NONE) {
		/* for safety reasons don't go into RTL if landed */
		if (_navigator->get_vstatus()->condition_landed) {
			_rtl_state = RTL_STATE_LANDED;
			mavlink_log_critical(_navigator->get_mavlink_fd(), "no RTL when landed");

		/* if lower than return altitude, climb up first */
		} else if (_navigator->get_global_position()->alt < _navigator->get_home_position()->alt
			   + _param_return_alt.get()) {
			_rtl_state = RTL_STATE_CLIMB;

		/* otherwise go straight to return */
		} else {
			/* set altitude setpoint to current altitude */
			_rtl_state = RTL_STATE_RETURN;
			_mission_item.altitude_is_relative = false;
			_mission_item.altitude = _navigator->get_global_position()->alt;
		}

	}

	set_rtl_item();
}

void
RTL::on_active()
{
	if (_rtl_state != RTL_STATE_LANDED && is_mission_item_reached()) {
		advance_rtl();
		set_rtl_item();
	}
}

void
RTL::set_rtl_item()
{
	struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();

	/* make sure we have the latest params */
	updateParams();

	set_previous_pos_setpoint();
	_navigator->set_can_loiter_at_sp(false);

	switch (_rtl_state) {
	case RTL_STATE_CLIMB: {
		float climb_alt = _navigator->get_home_position()->alt + _param_return_alt.get();

		_mission_item.lat = _navigator->get_global_position()->lat;
		_mission_item.lon = _navigator->get_global_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = climb_alt;
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_WAYPOINT;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: climb to %d m (%d m above home)",
			(int)(climb_alt),
			(int)(climb_alt - _navigator->get_home_position()->alt));
		break;
	}

	case RTL_STATE_RETURN: {
		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		 // don't change altitude

		 if (pos_sp_triplet->previous.valid) {
		 	/* if previous setpoint is valid then use it to calculate heading to home */
		 	_mission_item.yaw = get_bearing_to_next_waypoint(
		 	        pos_sp_triplet->previous.lat, pos_sp_triplet->previous.lon,
		 	        _mission_item.lat, _mission_item.lon);

		 } else {
		 	/* else use current position */
		 	_mission_item.yaw = get_bearing_to_next_waypoint(
		 	        _navigator->get_global_position()->lat, _navigator->get_global_position()->lon,
		 	        _mission_item.lat, _mission_item.lon);
		 }
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_WAYPOINT;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: return at %d m (%d m above home)",
			(int)(_mission_item.altitude),
			(int)(_mission_item.altitude - _navigator->get_home_position()->alt));
		break;
	}

	case RTL_STATE_DESCEND: {
		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = _navigator->get_home_position()->alt + _param_descend_alt.get();
		_mission_item.yaw = _navigator->get_home_position()->yaw;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_LOITER_TIME_LIMIT;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = false;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: descend to %d m (%d m above home)",
			(int)(_mission_item.altitude),
			(int)(_mission_item.altitude - _navigator->get_home_position()->alt));
		break;
	}

	case RTL_STATE_LOITER: {
		bool autoland = _param_land_delay.get() > -DELAY_SIGMA;

		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = _navigator->get_home_position()->alt + _param_descend_alt.get();
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = autoland ? NAV_CMD_LOITER_TIME_LIMIT : NAV_CMD_LOITER_UNLIMITED;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = _param_land_delay.get() < 0.0f ? 0.0f : _param_land_delay.get();
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = autoland;
		_mission_item.origin = ORIGIN_ONBOARD;

		_navigator->set_can_loiter_at_sp(true);

		if (autoland) {
			mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: loiter %.1fs", (double)_mission_item.time_inside);

		} else {
			mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: completed, loiter");
		}
		break;
	}

	case RTL_STATE_LAND: {
		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = _navigator->get_home_position()->alt;
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_LAND;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: land at home");
		break;
	}

	case RTL_STATE_LANDED: {
		_mission_item.lat = _navigator->get_home_position()->lat;
		_mission_item.lon = _navigator->get_home_position()->lon;
		_mission_item.altitude_is_relative = false;
		_mission_item.altitude = _navigator->get_home_position()->alt;
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_IDLE;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.time_inside = 0.0f;
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		mavlink_log_critical(_navigator->get_mavlink_fd(), "RTL: completed, landed");
		break;
	}

	default:
		break;
	}

	reset_mission_item_reached();

	/* convert mission item to current position setpoint and make it valid */
	mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
	pos_sp_triplet->next.valid = false;

	_navigator->set_position_setpoint_triplet_updated();
}

void
RTL::advance_rtl()
{
	switch (_rtl_state) {
	case RTL_STATE_CLIMB:
		_rtl_state = RTL_STATE_RETURN;
		break;

	case RTL_STATE_RETURN:
		_rtl_state = RTL_STATE_DESCEND;
		break;

	case RTL_STATE_DESCEND:
		/* only go to land if autoland is enabled */
		if (_param_land_delay.get() < -DELAY_SIGMA || _param_land_delay.get() > DELAY_SIGMA) {
			_rtl_state = RTL_STATE_LOITER;

		} else {
			_rtl_state = RTL_STATE_LAND;
		}
		break;

	case RTL_STATE_LOITER:
		_rtl_state = RTL_STATE_LAND;
		break;

	case RTL_STATE_LAND:
		_rtl_state = RTL_STATE_LANDED;
		break;

	default:
		break;
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: layerupdatemerger.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 03:32:30 $
 *
 *  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 CONFIGMGR_BACKEND_LAYERUPDATEMERGER_HXX
#define CONFIGMGR_BACKEND_LAYERUPDATEMERGER_HXX

#ifndef CONFIGMGR_BACKEND_BASICUPDATEMERGER_HXX
#include "basicupdatemerger.hxx"
#endif

#ifndef CONFIGMGR_BACKEND_LAYERUPDATE_HXX
#include "layerupdate.hxx"
#endif

#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif
// -----------------------------------------------------------------------------

namespace configmgr
{
// -----------------------------------------------------------------------------
    namespace backend
    {
// -----------------------------------------------------------------------------
        using rtl::OUString;
// -----------------------------------------------------------------------------
        class NodeUpdate;
        class PropertyUpdate;
        typedef rtl::Reference<NodeUpdate>      NodeUpdateRef;
        typedef rtl::Reference<PropertyUpdate>  PropertyUpdateRef;

        class LayerUpdateMerger : protected BasicUpdateMerger
        {
        public:
            static LayerSource getMergedLayer(LayerSource const & _xSourceLayer, LayerUpdate const & _aLayerUpdate)
            { return new LayerUpdateMerger(_xSourceLayer, _aLayerUpdate); }

        public:
            explicit
            LayerUpdateMerger( LayerSource const & _xSourceLayer, LayerUpdate const & _aLayerUpdate);

            ~LayerUpdateMerger();

        // XLayerHandler overrides
        protected:
            virtual void SAL_CALL
                startLayer(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endLayer(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                overrideNode( const OUString& aName, sal_Int16 aAttributes, sal_Bool bClear )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addOrReplaceNode( const OUString& aName, sal_Int16 aAttributes )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addOrReplaceNodeFromTemplate( const OUString& aName, const TemplateIdentifier& aTemplate, sal_Int16 aAttributes )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endNode(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                dropNode( const OUString& aName )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                overrideProperty( const OUString& aName, sal_Int16 aAttributes, const uno::Type& aType, sal_Bool bClear )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endProperty(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                setPropertyValue( const uno::Any& aValue )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                setPropertyValueForLocale( const uno::Any& aValue, const OUString & aLocale )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addProperty( const OUString& aName, sal_Int16 aAttributes, const uno::Type& aType )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addPropertyWithValue( const OUString& aName, sal_Int16 aAttributes, const uno::Any& aValue )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

        // BasicUpdateMerger
            virtual void flushUpdate();
        private:
            void malformedUpdate(sal_Char const * pMsg);
            void illegalUpdate(sal_Char const * pMsg);
        private:
            LayerUpdate                 m_aLayerUpdate;
            NodeUpdateRef               m_xCurrentNode;
            PropertyUpdateRef           m_xCurrentProp;
        };
// -----------------------------------------------------------------------------
    } // namespace xml
// -----------------------------------------------------------------------------

} // namespace configmgr
#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.6.130); FILE MERGED 2008/04/01 15:06:38 thb 1.6.130.3: #i85898# Stripping all external header guards 2008/04/01 12:27:18 thb 1.6.130.2: #i85898# Stripping all external header guards 2008/03/31 12:22:40 rt 1.6.130.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: layerupdatemerger.hxx,v $
 * $Revision: 1.7 $
 *
 * 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 CONFIGMGR_BACKEND_LAYERUPDATEMERGER_HXX
#define CONFIGMGR_BACKEND_LAYERUPDATEMERGER_HXX

#include "basicupdatemerger.hxx"
#include "layerupdate.hxx"
#include <rtl/ref.hxx>
// -----------------------------------------------------------------------------

namespace configmgr
{
// -----------------------------------------------------------------------------
    namespace backend
    {
// -----------------------------------------------------------------------------
        using rtl::OUString;
// -----------------------------------------------------------------------------
        class NodeUpdate;
        class PropertyUpdate;
        typedef rtl::Reference<NodeUpdate>      NodeUpdateRef;
        typedef rtl::Reference<PropertyUpdate>  PropertyUpdateRef;

        class LayerUpdateMerger : protected BasicUpdateMerger
        {
        public:
            static LayerSource getMergedLayer(LayerSource const & _xSourceLayer, LayerUpdate const & _aLayerUpdate)
            { return new LayerUpdateMerger(_xSourceLayer, _aLayerUpdate); }

        public:
            explicit
            LayerUpdateMerger( LayerSource const & _xSourceLayer, LayerUpdate const & _aLayerUpdate);

            ~LayerUpdateMerger();

        // XLayerHandler overrides
        protected:
            virtual void SAL_CALL
                startLayer(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endLayer(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                overrideNode( const OUString& aName, sal_Int16 aAttributes, sal_Bool bClear )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addOrReplaceNode( const OUString& aName, sal_Int16 aAttributes )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addOrReplaceNodeFromTemplate( const OUString& aName, const TemplateIdentifier& aTemplate, sal_Int16 aAttributes )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endNode(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                dropNode( const OUString& aName )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                overrideProperty( const OUString& aName, sal_Int16 aAttributes, const uno::Type& aType, sal_Bool bClear )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endProperty(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                setPropertyValue( const uno::Any& aValue )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                setPropertyValueForLocale( const uno::Any& aValue, const OUString & aLocale )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addProperty( const OUString& aName, sal_Int16 aAttributes, const uno::Type& aType )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addPropertyWithValue( const OUString& aName, sal_Int16 aAttributes, const uno::Any& aValue )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

        // BasicUpdateMerger
            virtual void flushUpdate();
        private:
            void malformedUpdate(sal_Char const * pMsg);
            void illegalUpdate(sal_Char const * pMsg);
        private:
            LayerUpdate                 m_aLayerUpdate;
            NodeUpdateRef               m_xCurrentNode;
            PropertyUpdateRef           m_xCurrentProp;
        };
// -----------------------------------------------------------------------------
    } // namespace xml
// -----------------------------------------------------------------------------

} // namespace configmgr
#endif

<|endoftext|>


<commit_before><commit_msg>pr change<commit_after><|endoftext|>


<commit_before>/*
 * Licensed under the MIT License (MIT)
 *
 * Copyright (c) 2013 AudioScience Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * net_interface_imp.cpp
 *
 * Network interface implementation class
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/filter.h>
#include <linux/if.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ifaddrs.h>

#include "util_imp.h"
#include "enumeration.h"
#include "log.h"
#include "jdksavdecc_util.h"
#include "net_interface_imp.h"

#include "bpf.h"

namespace avdecc_lib
{

    struct etherII
    {
        uint8_t destmac[6];
        uint8_t srcmac[6];
        uint8_t type[2];
    };
    struct ipheader
    {
        uint8_t ver_len;
        uint8_t service;
        uint8_t len[2];
        uint8_t ident[2];
        uint8_t flags;
        uint8_t frag_offset[2];
        uint8_t ttl;
        uint8_t protocol;
        uint8_t chksum[2];
        uint8_t sourceip[4];
        uint8_t destip[4];
    };
    struct udpheader
    {
        uint8_t srcport[2];
        uint8_t destport[2];
        uint8_t len[2];
        uint8_t chksum[2];
    };

    net_interface_imp::net_interface_imp()
    {
        struct ifaddrs *ifaddr, *ifa;
        int family, s;
        char host[NI_MAXHOST];
        char ifname[256];

        interface_num = 0;
        total_devs = 0;

        ip_hdr_store = new ipheader;
        udp_hdr_store = new udpheader;

        if (getifaddrs(&ifaddr) == -1)
        {
            perror("getifaddrs");
            exit(EXIT_FAILURE);
        }

        /* Walk through linked list, maintaining head pointer so we
        can free list later */

        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
        {
            if (ifa->ifa_addr == NULL)
                continue;

            family = ifa->ifa_addr->sa_family;

            /* Display interface name and family (including symbolic
            form of the latter for the common families) */
            if (family == AF_INET)
            {
                s = getnameinfo(ifa->ifa_addr,
                                (family == AF_INET) ? sizeof(struct sockaddr_in) :
                                sizeof(struct sockaddr_in6),
                                host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);

                snprintf(ifname, sizeof(ifname), "%s, address: <%s>",ifa->ifa_name, host);
                if (s != 0)
                {
                    printf("getnameinfo() failed: %s\n", gai_strerror(s));
                    exit(EXIT_FAILURE);
                }
                ifnames.push_back(ifname);
                total_devs++;
            }
        }

        freeifaddrs(ifaddr);
    }

    net_interface_imp::~net_interface_imp()
    {
        close(rawsock);
    }

    void STDCALL net_interface_imp::destroy()
    {
        delete this;
    }

    uint32_t STDCALL net_interface_imp::devs_count()
    {
        return total_devs;
    }

    uint64_t net_interface_imp::mac_addr()
    {
        return mac;
    }

    char * STDCALL net_interface_imp::get_dev_desc_by_index(uint32_t dev_index)
    {
        return (char *)ifnames[dev_index].c_str();
    }

    int net_interface_imp::get_fd()
    {
        return rawsock;
    }

    int STDCALL net_interface_imp::select_interface_by_num(uint32_t interface_num)
    {
        struct sockaddr_ll sll;
        struct ifreq if_mac;
        const char *ifname;
        char *s;

        ifname = ifnames[interface_num].c_str();
        s = (char *)ifname;
        while(*s != ',')
        {
            s++;
        }
        *s = 0;
        rawsock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        if (rawsock == -1)
        {
            fprintf(stderr, "Socket open failed! %s\nuse sudo?\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        ifindex = getifindex(rawsock, ifname);

        // get the mac address of the eth0 interface
        memset(&if_mac, 0, sizeof(struct ifreq));
        strncpy(if_mac.ifr_name, ifname, IFNAMSIZ-1);
        if (ioctl(rawsock, SIOCGIFHWADDR, &if_mac) < 0)
        {
            perror("SIOCGIFHWADDR");
            exit(EXIT_FAILURE);
        }

        setpromiscuous(rawsock, ifindex);

        memset(&sll,0, sizeof(sll));
        sll.sll_family = AF_PACKET;
        sll.sll_ifindex = ifindex;
        sll.sll_protocol = htons(ETH_P_ALL);
        bind(rawsock, (struct sockaddr *)&sll, sizeof(sll));

        utility->convert_eui48_to_uint64((uint8_t *)if_mac.ifr_hwaddr.sa_data, mac);

        uint16_t etypes[1] = {0x22f0};
        set_capture_ether_type(etypes, 1);

        return 0;
    }

    int net_interface_imp::set_capture_ether_type(uint16_t *ether_type, uint32_t count)
    {
        struct sock_fprog Filter;

        Filter.len = sizeof(BPF_code) / 8;
        Filter.filter = BPF_code;

        for (unsigned int i = 0; i < count; i++)
        {
            if (ether_type[i] != (uint16_t)ethernet_proto_bpf[i])
                fprintf(stderr, "NETIF - packet filter mismatch\n");
        }

        // attach filter to socket
        if(setsockopt(rawsock, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter)) == -1)
        {
            fprintf(stderr, "socket attach filter failed! %s\n", strerror(errno));
            close(rawsock);
            exit(EXIT_FAILURE);
        }

        return 0;
    }

    int STDCALL net_interface_imp::capture_frame(const uint8_t **frame, uint16_t *mem_buf_len)
    {
        int len;

        *frame = &rx_buf[0];
        len = read(rawsock, &rx_buf[0], sizeof(rx_buf));
        if (len < 0)
        {
            *mem_buf_len = 0;
        }
        else
        {
            *mem_buf_len = len;
        }
        return len;
    }

    int net_interface_imp::send_frame(uint8_t *frame, uint16_t mem_buf_len)
    {
        int send_result;

        /*target address*/
        struct sockaddr_ll socket_address;

        /*prepare sockaddr_ll*/

        /*RAW communication*/
        socket_address.sll_family   = PF_PACKET;
        socket_address.sll_protocol = htons(ethertype);

        /*index of the network device
        see full code later how to retrieve it*/
        socket_address.sll_ifindex  = ifindex;

        /*ARP hardware identifier is ethernet*/
        socket_address.sll_hatype   = ARPHRD_ETHER;

        /*target is another host*/
        socket_address.sll_pkttype  = PACKET_OTHERHOST;

        /*address length*/
        socket_address.sll_halen    = ETH_ALEN;
        /*MAC - begin*/
        memcpy(&socket_address.sll_addr[0], &frame[0], 6);
        /*MAC - end*/
        socket_address.sll_addr[6]  = 0x00;/*not used*/
        socket_address.sll_addr[7]  = 0x00;/*not used*/

        /*send the packet*/
        send_result = sendto(rawsock, frame, mem_buf_len, 0,
                             (struct sockaddr*)&socket_address, sizeof(socket_address));

        return send_result;
    }

    int net_interface_imp::getifindex(int rawsock, const char *iface)
    {
        struct ifreq ifr;
        int ret;

        memset(&ifr,0,sizeof(ifr));
        strncpy(ifr.ifr_name,iface,sizeof(ifr.ifr_name));

        ret=ioctl(rawsock,SIOCGIFINDEX,&ifr);

        if(ret<0)
        {
            return ret;
        }

        return ifr.ifr_ifindex;
    }

    int net_interface_imp::setpromiscuous(int rawsock, int ifindex)
    {
        struct packet_mreq mr;

        memset(&mr,0,sizeof(mr));
        mr.mr_ifindex=ifindex;
        mr.mr_type=PACKET_MR_ALLMULTI;

        return setsockopt(rawsock, SOL_PACKET,
                          PACKET_ADD_MEMBERSHIP,&mr,sizeof(mr));
    }

    net_interface * create_net_interface()
    {
        return (new net_interface_imp());
    }

}
<commit_msg>linux: netif module, correct selected interface index<commit_after>/*
 * Licensed under the MIT License (MIT)
 *
 * Copyright (c) 2013 AudioScience Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * net_interface_imp.cpp
 *
 * Network interface implementation class
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/filter.h>
#include <linux/if.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ifaddrs.h>

#include "util_imp.h"
#include "enumeration.h"
#include "log.h"
#include "jdksavdecc_util.h"
#include "net_interface_imp.h"

#include "bpf.h"

namespace avdecc_lib
{

    struct etherII
    {
        uint8_t destmac[6];
        uint8_t srcmac[6];
        uint8_t type[2];
    };
    struct ipheader
    {
        uint8_t ver_len;
        uint8_t service;
        uint8_t len[2];
        uint8_t ident[2];
        uint8_t flags;
        uint8_t frag_offset[2];
        uint8_t ttl;
        uint8_t protocol;
        uint8_t chksum[2];
        uint8_t sourceip[4];
        uint8_t destip[4];
    };
    struct udpheader
    {
        uint8_t srcport[2];
        uint8_t destport[2];
        uint8_t len[2];
        uint8_t chksum[2];
    };

    net_interface_imp::net_interface_imp()
    {
        struct ifaddrs *ifaddr, *ifa;
        int family, s;
        char host[NI_MAXHOST];
        char ifname[256];

        interface_num = 0;
        total_devs = 0;

        ip_hdr_store = new ipheader;
        udp_hdr_store = new udpheader;

        if (getifaddrs(&ifaddr) == -1)
        {
            perror("getifaddrs");
            exit(EXIT_FAILURE);
        }

        /* Walk through linked list, maintaining head pointer so we
        can free list later */

        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
        {
            if (ifa->ifa_addr == NULL)
                continue;

            family = ifa->ifa_addr->sa_family;

            /* Display interface name and family (including symbolic
            form of the latter for the common families) */
            if (family == AF_INET)
            {
                s = getnameinfo(ifa->ifa_addr,
                                (family == AF_INET) ? sizeof(struct sockaddr_in) :
                                sizeof(struct sockaddr_in6),
                                host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);

                snprintf(ifname, sizeof(ifname), "%s, address: <%s>",ifa->ifa_name, host);
                if (s != 0)
                {
                    printf("getnameinfo() failed: %s\n", gai_strerror(s));
                    exit(EXIT_FAILURE);
                }
                ifnames.push_back(ifname);
                total_devs++;
            }
        }

        freeifaddrs(ifaddr);
    }

    net_interface_imp::~net_interface_imp()
    {
        close(rawsock);
    }

    void STDCALL net_interface_imp::destroy()
    {
        delete this;
    }

    uint32_t STDCALL net_interface_imp::devs_count()
    {
        return total_devs;
    }

    uint64_t net_interface_imp::mac_addr()
    {
        return mac;
    }

    char * STDCALL net_interface_imp::get_dev_desc_by_index(uint32_t dev_index)
    {
        return (char *)ifnames[dev_index].c_str();
    }

    int net_interface_imp::get_fd()
    {
        return rawsock;
    }

    int STDCALL net_interface_imp::select_interface_by_num(uint32_t interface_num)
    {
        struct sockaddr_ll sll;
        struct ifreq if_mac;
        const char *ifname;
        char *s;

        /* adjust interface numnber since count starts at 1 */
        interface_num--;

        ifname = ifnames[interface_num].c_str();
        s = (char *)ifname;
        while(*s != ',')
        {
            s++;
        }
        *s = 0;
        rawsock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        if (rawsock == -1)
        {
            fprintf(stderr, "Socket open failed! %s\nuse sudo?\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        ifindex = getifindex(rawsock, ifname);

        // get the mac address of the eth0 interface
        memset(&if_mac, 0, sizeof(struct ifreq));
        strncpy(if_mac.ifr_name, ifname, IFNAMSIZ-1);
        if (ioctl(rawsock, SIOCGIFHWADDR, &if_mac) < 0)
        {
            perror("SIOCGIFHWADDR");
            exit(EXIT_FAILURE);
        }

        setpromiscuous(rawsock, ifindex);

        memset(&sll,0, sizeof(sll));
        sll.sll_family = AF_PACKET;
        sll.sll_ifindex = ifindex;
        sll.sll_protocol = htons(ETH_P_ALL);
        bind(rawsock, (struct sockaddr *)&sll, sizeof(sll));

        utility->convert_eui48_to_uint64((uint8_t *)if_mac.ifr_hwaddr.sa_data, mac);

        uint16_t etypes[1] = {0x22f0};
        set_capture_ether_type(etypes, 1);

        return 0;
    }

    int net_interface_imp::set_capture_ether_type(uint16_t *ether_type, uint32_t count)
    {
        struct sock_fprog Filter;

        Filter.len = sizeof(BPF_code) / 8;
        Filter.filter = BPF_code;

        for (unsigned int i = 0; i < count; i++)
        {
            if (ether_type[i] != (uint16_t)ethernet_proto_bpf[i])
                fprintf(stderr, "NETIF - packet filter mismatch\n");
        }

        // attach filter to socket
        if(setsockopt(rawsock, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter)) == -1)
        {
            fprintf(stderr, "socket attach filter failed! %s\n", strerror(errno));
            close(rawsock);
            exit(EXIT_FAILURE);
        }

        return 0;
    }

    int STDCALL net_interface_imp::capture_frame(const uint8_t **frame, uint16_t *mem_buf_len)
    {
        int len;

        *frame = &rx_buf[0];
        len = read(rawsock, &rx_buf[0], sizeof(rx_buf));
        if (len < 0)
        {
            *mem_buf_len = 0;
        }
        else
        {
            *mem_buf_len = len;
        }
        return len;
    }

    int net_interface_imp::send_frame(uint8_t *frame, uint16_t mem_buf_len)
    {
        int send_result;

        /*target address*/
        struct sockaddr_ll socket_address;

        /*prepare sockaddr_ll*/

        /*RAW communication*/
        socket_address.sll_family   = PF_PACKET;
        socket_address.sll_protocol = htons(ethertype);

        /*index of the network device
        see full code later how to retrieve it*/
        socket_address.sll_ifindex  = ifindex;

        /*ARP hardware identifier is ethernet*/
        socket_address.sll_hatype   = ARPHRD_ETHER;

        /*target is another host*/
        socket_address.sll_pkttype  = PACKET_OTHERHOST;

        /*address length*/
        socket_address.sll_halen    = ETH_ALEN;
        /*MAC - begin*/
        memcpy(&socket_address.sll_addr[0], &frame[0], 6);
        /*MAC - end*/
        socket_address.sll_addr[6]  = 0x00;/*not used*/
        socket_address.sll_addr[7]  = 0x00;/*not used*/

        /*send the packet*/
        send_result = sendto(rawsock, frame, mem_buf_len, 0,
                             (struct sockaddr*)&socket_address, sizeof(socket_address));

        return send_result;
    }

    int net_interface_imp::getifindex(int rawsock, const char *iface)
    {
        struct ifreq ifr;
        int ret;

        memset(&ifr,0,sizeof(ifr));
        strncpy(ifr.ifr_name,iface,sizeof(ifr.ifr_name));

        ret=ioctl(rawsock,SIOCGIFINDEX,&ifr);

        if(ret<0)
        {
            return ret;
        }

        return ifr.ifr_ifindex;
    }

    int net_interface_imp::setpromiscuous(int rawsock, int ifindex)
    {
        struct packet_mreq mr;

        memset(&mr,0,sizeof(mr));
        mr.mr_ifindex=ifindex;
        mr.mr_type=PACKET_MR_ALLMULTI;

        return setsockopt(rawsock, SOL_PACKET,
                          PACKET_ADD_MEMBERSHIP,&mr,sizeof(mr));
    }

    net_interface * create_net_interface()
    {
        return (new net_interface_imp());
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2016 ASMlover. 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 ofconditions 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 materialsprovided with the
//    distribution.
//
// 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 HOLDER 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.
#include <sys/syscall.h>
#include <unistd.h>
#include <mach/mach_time.h>
#include "../TPlatform.h"

namespace tyr { namespace basic {

pid_t kern_gettid(void) {
  return static_cast<pid_t>(syscall(SYS_thread_selfid));
}

int kern_this_thread_setname(const char* name) {
  return pthread_setname_np(name);
}

int kern_gettime(struct timespec* timep) {
  mach_timebase_info_data_t info;
  if (KERN_SUCCESS != mach_timebase_info(&info))
    abort();
  uint64_t realtime = mach_absolute_time() * info.numer / info.denom;
  timep->tv_sec = realtime / NANOSEC;
  timep->tv_nsec = realtime % NANOSEC;
  return 0;
}

}}
<commit_msg>fix(cond): fixed bug of kernel syscall of condition variable for darwin platform<commit_after>// Copyright (c) 2016 ASMlover. 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 ofconditions 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 materialsprovided with the
//    distribution.
//
// 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 HOLDER 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.
#include <mach/mach_time.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdlib.h>
#include "../TPlatform.h"

namespace tyr { namespace basic {

pid_t kern_gettid(void) {
  return static_cast<pid_t>(syscall(SYS_thread_selfid));
}

int kern_this_thread_setname(const char* name) {
  return pthread_setname_np(name);
}

int kern_gettime(struct timespec* timep) {
  mach_timebase_info_data_t info;
  if (KERN_SUCCESS != mach_timebase_info(&info))
    abort();
  uint64_t realtime = mach_absolute_time() * info.numer / info.denom;
  timep->tv_sec = realtime / NANOSEC;
  timep->tv_nsec = realtime % NANOSEC;
  return 0;
}

}}
<|endoftext|>