Source code

Revision control

Copy as Markdown

Other Tools

/*
* Copyright 2024 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.
*/
#ifndef P2P_DTLS_DTLS_STUN_PIGGYBACK_CONTROLLER_H_
#define P2P_DTLS_DTLS_STUN_PIGGYBACK_CONTROLLER_H_
#include <cstdint>
#include <optional>
#include <set>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/sequence_checker.h"
#include "api/transport/stun.h"
#include "rtc_base/buffer.h"
#include "rtc_base/byte_buffer.h"
#include "rtc_base/system/no_unique_address.h"
#include "rtc_base/thread_annotations.h"
namespace cricket {
// This class is not thread safe; all methods must be called on the same thread
// as the constructor.
class DtlsStunPiggybackController {
public:
// dtls_data_callback will be called with any DTLS packets received
// piggybacked.
DtlsStunPiggybackController(
absl::AnyInvocable<void(rtc::ArrayView<const uint8_t>)>
dtls_data_callback);
~DtlsStunPiggybackController();
enum class State {
// We don't know if peer support DTLS piggybacked in STUN.
// We will piggyback DTLS until we get a piggybacked response
// or a STUN response with piggyback support.
TENTATIVE = 0,
// The peer supports DTLS in STUN and we continue the handshake.
CONFIRMED = 1,
// We are waiting for the final ack. Semantic differs depending
// on DTLS role.
PENDING = 2,
// We successfully completed the DTLS handshake in STUN.
COMPLETE = 3,
// The peer does not support piggybacking DTLS in STUN.
OFF = 4,
};
State state() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
return state_;
}
// Called by DtlsTransport when handshake is complete.
void SetDtlsHandshakeComplete(bool is_dtls_client, bool is_dtls13);
// Intercepts DTLS packets which should go into the STUN packets during the
// handshake.
bool MaybeConsumePacket(rtc::ArrayView<const uint8_t> data);
void ClearCachedPacketForTesting();
// Called by Connection, when sending a STUN BINDING { REQUEST / RESPONSE }
// to obtain optional DTLS data or ACKs.
std::optional<absl::string_view> GetDataToPiggyback(
StunMessageType stun_message_type);
std::optional<absl::string_view> GetAckToPiggyback(
StunMessageType stun_message_type);
// Called by Connection when receiving a STUN BINDING { REQUEST / RESPONSE }.
void ReportDataPiggybacked(const StunByteStringAttribute* data,
const StunByteStringAttribute* ack);
private:
State state_ RTC_GUARDED_BY(sequence_checker_) = State::TENTATIVE;
rtc::Buffer pending_packet_ RTC_GUARDED_BY(sequence_checker_);
absl::AnyInvocable<void(rtc::ArrayView<const uint8_t>)> dtls_data_callback_;
std::set<uint16_t> handshake_messages_received_
RTC_GUARDED_BY(sequence_checker_);
rtc::ByteBufferWriter handshake_ack_writer_ RTC_GUARDED_BY(sequence_checker_);
// In practice this will be the network thread.
RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker sequence_checker_;
};
} // namespace cricket
#endif // P2P_DTLS_DTLS_STUN_PIGGYBACK_CONTROLLER_H_