From 56d945233d17a22d8dcc5c029a72198f845a04a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20H=C3=B6glund?= Date: Mon, 18 Nov 2019 15:53:32 +0100 Subject: [PATCH] Move stun.h to api/. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now have two downstream users of stun.h, so it appears to be generally usable. I put this in a new dir networking/, but I'm open to suggestions here (maybe some things in api/ should move in there). I checked what our downstream users are actually using, and it's cricket::ComputeStunCredentialHash cricket:: cricket::TurnMessage cricket::GetStunErrorResponseType cricket::StunAttribute::CreateAddress cricket::StunErrorCodeAttribute cricket::StunByteStringAttribute StunAttribute::CreateUnknownAttributes cricket::TurnErrorType cricket::StunMessage I reckoned that was pretty much everything in stun.h, so I didn't bother splitting it up. They don't use every function and constant in there, but all _types_ of functions and constants, so for the sake of coherence I don't think it makes sense to split it. There's some old stuff in there like GTURN which could arguably be split out, but it should likely go away soon anyway, so I don't think it's worth the effort. Steps: 1) land this 2) update downstream to point to the new header and target 3) remove p2p/base:stun_types. Bug: webrtc:11091 Change-Id: I1f05bf06055475d25601197ec6fefb8d3b55e8e3 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/159923 Commit-Queue: Patrik Höglund Reviewed-by: Niels Moller Cr-Commit-Position: refs/heads/master@{#29822} --- BUILD.gn | 1 + api/transport/BUILD.gn | 33 + api/transport/DEPS | 7 + {p2p/base => api/transport}/stun.cc | 2 +- api/transport/stun.h | 635 +++++++++++++++++++ {p2p/base => api/transport}/stun_unittest.cc | 2 +- media/BUILD.gn | 1 + media/base/turn_utils.cc | 2 +- p2p/BUILD.gn | 10 +- p2p/base/async_stun_tcp_socket.cc | 2 +- p2p/base/connection.h | 2 +- p2p/base/empty.cc | 11 + p2p/base/port.h | 2 +- p2p/base/port_unittest.cc | 2 +- p2p/base/stun.h | 622 +----------------- p2p/base/stun_port.cc | 2 +- p2p/base/stun_request.h | 2 +- p2p/base/stun_server.h | 2 +- p2p/base/test_stun_server.h | 2 +- p2p/base/test_turn_server.h | 2 +- p2p/base/turn_port.cc | 2 +- p2p/base/turn_server.cc | 2 +- p2p/stunprober/stun_prober.cc | 2 +- test/fuzzers/BUILD.gn | 4 +- test/fuzzers/stun_parser_fuzzer.cc | 2 +- test/fuzzers/stun_validator_fuzzer.cc | 2 +- 26 files changed, 717 insertions(+), 641 deletions(-) create mode 100644 api/transport/DEPS rename {p2p/base => api/transport}/stun.cc (99%) create mode 100644 api/transport/stun.h rename {p2p/base => api/transport}/stun_unittest.cc (99%) create mode 100644 p2p/base/empty.cc diff --git a/BUILD.gn b/BUILD.gn index 98ff6a039d..61a25a092c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -517,6 +517,7 @@ if (rtc_include_tests) { "api:rtc_api_unittests", "api/audio/test:audio_api_unittests", "api/audio_codecs/test:audio_codecs_api_unittests", + "api/transport:stun_unittest", "api/video/test:rtc_api_video_unittests", "api/video_codecs/test:video_codecs_api_unittests", "call:fake_network_pipe_unittests", diff --git a/api/transport/BUILD.gn b/api/transport/BUILD.gn index 12200a630d..3710aa57e3 100644 --- a/api/transport/BUILD.gn +++ b/api/transport/BUILD.gn @@ -104,6 +104,20 @@ rtc_library("goog_cc") { ] } +rtc_source_set("stun_types") { + visibility = [ "*" ] + sources = [ + "stun.cc", + "stun.h", + ] + + deps = [ + "../../rtc_base:checks", + "../../rtc_base:rtc_base", + "../../rtc_base:rtc_base_approved", + ] +} + if (rtc_include_tests) { rtc_source_set("test_feedback_generator_interface") { testonly = true @@ -130,6 +144,25 @@ if (rtc_include_tests) { } } +if (rtc_include_tests) { + rtc_source_set("stun_unittest") { + visibility = [ "*" ] + testonly = true + sources = [ + "stun_unittest.cc", + ] + deps = [ + ":stun_types", + "../../p2p:stun_types", + "../../rtc_base", + "../../rtc_base:macromagic", + "../../rtc_base:rtc_base_approved", + "../../test:test_support", + "//testing/gtest", + ] + } +} + if (rtc_include_tests) { rtc_source_set("mock_network_control") { testonly = true diff --git a/api/transport/DEPS b/api/transport/DEPS new file mode 100644 index 0000000000..53a68e0e85 --- /dev/null +++ b/api/transport/DEPS @@ -0,0 +1,7 @@ +specific_include_rules = { + "stun\.h": [ + "+rtc_base/byte_buffer.h", + "+rtc_base/ip_address.h", + "+rtc_base/socket_address.h", + ], +} diff --git a/p2p/base/stun.cc b/api/transport/stun.cc similarity index 99% rename from p2p/base/stun.cc rename to api/transport/stun.cc index dba0c4d804..5e00b33c22 100644 --- a/p2p/base/stun.cc +++ b/api/transport/stun.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "p2p/base/stun.h" +#include "api/transport/stun.h" #include diff --git a/api/transport/stun.h b/api/transport/stun.h new file mode 100644 index 0000000000..e19f196d8c --- /dev/null +++ b/api/transport/stun.h @@ -0,0 +1,635 @@ +/* + * Copyright 2004 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 API_TRANSPORT_STUN_H_ +#define API_TRANSPORT_STUN_H_ + +// This file contains classes for dealing with the STUN protocol, as specified +// in RFC 5389, and its descendants. + +#include +#include + +#include +#include +#include + +#include "rtc_base/byte_buffer.h" +#include "rtc_base/ip_address.h" +#include "rtc_base/socket_address.h" + +namespace cricket { + +// These are the types of STUN messages defined in RFC 5389. +enum StunMessageType { + STUN_BINDING_REQUEST = 0x0001, + STUN_BINDING_INDICATION = 0x0011, + STUN_BINDING_RESPONSE = 0x0101, + STUN_BINDING_ERROR_RESPONSE = 0x0111, +}; + +// These are all known STUN attributes, defined in RFC 5389 and elsewhere. +// Next to each is the name of the class (T is StunTAttribute) that implements +// that type. +// RETRANSMIT_COUNT is the number of outstanding pings without a response at +// the time the packet is generated. +enum StunAttributeType { + STUN_ATTR_MAPPED_ADDRESS = 0x0001, // Address + STUN_ATTR_USERNAME = 0x0006, // ByteString + STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, // ByteString, 20 bytes + STUN_ATTR_ERROR_CODE = 0x0009, // ErrorCode + STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, // UInt16List + STUN_ATTR_REALM = 0x0014, // ByteString + STUN_ATTR_NONCE = 0x0015, // ByteString + STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020, // XorAddress + STUN_ATTR_SOFTWARE = 0x8022, // ByteString + STUN_ATTR_ALTERNATE_SERVER = 0x8023, // Address + STUN_ATTR_FINGERPRINT = 0x8028, // UInt32 + STUN_ATTR_ORIGIN = 0x802F, // ByteString + STUN_ATTR_RETRANSMIT_COUNT = 0xFF00 // UInt32 +}; + +// These are the types of the values associated with the attributes above. +// This allows us to perform some basic validation when reading or adding +// attributes. Note that these values are for our own use, and not defined in +// RFC 5389. +enum StunAttributeValueType { + STUN_VALUE_UNKNOWN = 0, + STUN_VALUE_ADDRESS = 1, + STUN_VALUE_XOR_ADDRESS = 2, + STUN_VALUE_UINT32 = 3, + STUN_VALUE_UINT64 = 4, + STUN_VALUE_BYTE_STRING = 5, + STUN_VALUE_ERROR_CODE = 6, + STUN_VALUE_UINT16_LIST = 7 +}; + +// These are the types of STUN addresses defined in RFC 5389. +enum StunAddressFamily { + // NB: UNDEF is not part of the STUN spec. + STUN_ADDRESS_UNDEF = 0, + STUN_ADDRESS_IPV4 = 1, + STUN_ADDRESS_IPV6 = 2 +}; + +// These are the types of STUN error codes defined in RFC 5389. +enum StunErrorCode { + STUN_ERROR_TRY_ALTERNATE = 300, + STUN_ERROR_BAD_REQUEST = 400, + STUN_ERROR_UNAUTHORIZED = 401, + STUN_ERROR_UNKNOWN_ATTRIBUTE = 420, + STUN_ERROR_STALE_CREDENTIALS = 430, // GICE only + STUN_ERROR_STALE_NONCE = 438, + STUN_ERROR_SERVER_ERROR = 500, + STUN_ERROR_GLOBAL_FAILURE = 600 +}; + +// Strings for the error codes above. +extern const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[]; +extern const char STUN_ERROR_REASON_BAD_REQUEST[]; +extern const char STUN_ERROR_REASON_UNAUTHORIZED[]; +extern const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[]; +extern const char STUN_ERROR_REASON_STALE_CREDENTIALS[]; +extern const char STUN_ERROR_REASON_STALE_NONCE[]; +extern const char STUN_ERROR_REASON_SERVER_ERROR[]; + +// The mask used to determine whether a STUN message is a request/response etc. +const uint32_t kStunTypeMask = 0x0110; + +// STUN Attribute header length. +const size_t kStunAttributeHeaderSize = 4; + +// Following values correspond to RFC5389. +const size_t kStunHeaderSize = 20; +const size_t kStunTransactionIdOffset = 8; +const size_t kStunTransactionIdLength = 12; +const uint32_t kStunMagicCookie = 0x2112A442; +constexpr size_t kStunMagicCookieLength = sizeof(kStunMagicCookie); + +// Following value corresponds to an earlier version of STUN from +// RFC3489. +const size_t kStunLegacyTransactionIdLength = 16; + +// STUN Message Integrity HMAC length. +const size_t kStunMessageIntegritySize = 20; + +class StunAddressAttribute; +class StunAttribute; +class StunByteStringAttribute; +class StunErrorCodeAttribute; + +class StunUInt16ListAttribute; +class StunUInt32Attribute; +class StunUInt64Attribute; +class StunXorAddressAttribute; + +// Records a complete STUN/TURN message. Each message consists of a type and +// any number of attributes. Each attribute is parsed into an instance of an +// appropriate class (see above). The Get* methods will return instances of +// that attribute class. +class StunMessage { + public: + StunMessage(); + virtual ~StunMessage(); + + int type() const { return type_; } + size_t length() const { return length_; } + const std::string& transaction_id() const { return transaction_id_; } + uint32_t reduced_transaction_id() const { return reduced_transaction_id_; } + + // Returns true if the message confirms to RFC3489 rather than + // RFC5389. The main difference between two version of the STUN + // protocol is the presence of the magic cookie and different length + // of transaction ID. For outgoing packets version of the protocol + // is determined by the lengths of the transaction ID. + bool IsLegacy() const; + + void SetType(int type) { type_ = static_cast(type); } + bool SetTransactionID(const std::string& str); + + // Gets the desired attribute value, or NULL if no such attribute type exists. + const StunAddressAttribute* GetAddress(int type) const; + const StunUInt32Attribute* GetUInt32(int type) const; + const StunUInt64Attribute* GetUInt64(int type) const; + const StunByteStringAttribute* GetByteString(int type) const; + + // Gets these specific attribute values. + const StunErrorCodeAttribute* GetErrorCode() const; + // Returns the code inside the error code attribute, if present, and + // STUN_ERROR_GLOBAL_FAILURE otherwise. + int GetErrorCodeValue() const; + const StunUInt16ListAttribute* GetUnknownAttributes() const; + + // Takes ownership of the specified attribute and adds it to the message. + void AddAttribute(std::unique_ptr attr); + + // Remove the last occurrence of an attribute. + std::unique_ptr RemoveAttribute(int type); + + // Validates that a raw STUN message has a correct MESSAGE-INTEGRITY value. + // This can't currently be done on a StunMessage, since it is affected by + // padding data (which we discard when reading a StunMessage). + static bool ValidateMessageIntegrity(const char* data, + size_t size, + const std::string& password); + // Adds a MESSAGE-INTEGRITY attribute that is valid for the current message. + bool AddMessageIntegrity(const std::string& password); + bool AddMessageIntegrity(const char* key, size_t keylen); + + // Verifies that a given buffer is STUN by checking for a correct FINGERPRINT. + static bool ValidateFingerprint(const char* data, size_t size); + + // Adds a FINGERPRINT attribute that is valid for the current message. + bool AddFingerprint(); + + // Parses the STUN packet in the given buffer and records it here. The + // return value indicates whether this was successful. + bool Read(rtc::ByteBufferReader* buf); + + // Writes this object into a STUN packet. The return value indicates whether + // this was successful. + bool Write(rtc::ByteBufferWriter* buf) const; + + // Creates an empty message. Overridable by derived classes. + virtual StunMessage* CreateNew() const; + + // Modify the stun magic cookie used for this STUN message. + // This is used for testing. + void SetStunMagicCookie(uint32_t val); + + protected: + // Verifies that the given attribute is allowed for this message. + virtual StunAttributeValueType GetAttributeValueType(int type) const; + + private: + StunAttribute* CreateAttribute(int type, size_t length) /* const*/; + const StunAttribute* GetAttribute(int type) const; + static bool IsValidTransactionId(const std::string& transaction_id); + + uint16_t type_; + uint16_t length_; + std::string transaction_id_; + uint32_t reduced_transaction_id_; + std::vector> attrs_; + uint32_t stun_magic_cookie_; +}; + +// Base class for all STUN/TURN attributes. +class StunAttribute { + public: + virtual ~StunAttribute() {} + + int type() const { return type_; } + size_t length() const { return length_; } + + // Return the type of this attribute. + virtual StunAttributeValueType value_type() const = 0; + + // Only XorAddressAttribute needs this so far. + virtual void SetOwner(StunMessage* owner) {} + + // Reads the body (not the type or length) for this type of attribute from + // the given buffer. Return value is true if successful. + virtual bool Read(rtc::ByteBufferReader* buf) = 0; + + // Writes the body (not the type or length) to the given buffer. Return + // value is true if successful. + virtual bool Write(rtc::ByteBufferWriter* buf) const = 0; + + // Creates an attribute object with the given type and smallest length. + static StunAttribute* Create(StunAttributeValueType value_type, + uint16_t type, + uint16_t length, + StunMessage* owner); + // TODO(?): Allow these create functions to take parameters, to reduce + // the amount of work callers need to do to initialize attributes. + static std::unique_ptr CreateAddress(uint16_t type); + static std::unique_ptr CreateXorAddress( + uint16_t type); + static std::unique_ptr CreateUInt32(uint16_t type); + static std::unique_ptr CreateUInt64(uint16_t type); + static std::unique_ptr CreateByteString( + uint16_t type); + static std::unique_ptr CreateErrorCode(); + static std::unique_ptr CreateUnknownAttributes(); + + protected: + StunAttribute(uint16_t type, uint16_t length); + void SetLength(uint16_t length) { length_ = length; } + void WritePadding(rtc::ByteBufferWriter* buf) const; + void ConsumePadding(rtc::ByteBufferReader* buf) const; + + private: + uint16_t type_; + uint16_t length_; +}; + +// Implements STUN attributes that record an Internet address. +class StunAddressAttribute : public StunAttribute { + public: + static const uint16_t SIZE_UNDEF = 0; + static const uint16_t SIZE_IP4 = 8; + static const uint16_t SIZE_IP6 = 20; + StunAddressAttribute(uint16_t type, const rtc::SocketAddress& addr); + StunAddressAttribute(uint16_t type, uint16_t length); + + StunAttributeValueType value_type() const override; + + StunAddressFamily family() const { + switch (address_.ipaddr().family()) { + case AF_INET: + return STUN_ADDRESS_IPV4; + case AF_INET6: + return STUN_ADDRESS_IPV6; + } + return STUN_ADDRESS_UNDEF; + } + + const rtc::SocketAddress& GetAddress() const { return address_; } + const rtc::IPAddress& ipaddr() const { return address_.ipaddr(); } + uint16_t port() const { return address_.port(); } + + void SetAddress(const rtc::SocketAddress& addr) { + address_ = addr; + EnsureAddressLength(); + } + void SetIP(const rtc::IPAddress& ip) { + address_.SetIP(ip); + EnsureAddressLength(); + } + void SetPort(uint16_t port) { address_.SetPort(port); } + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + void EnsureAddressLength() { + switch (family()) { + case STUN_ADDRESS_IPV4: { + SetLength(SIZE_IP4); + break; + } + case STUN_ADDRESS_IPV6: { + SetLength(SIZE_IP6); + break; + } + default: { + SetLength(SIZE_UNDEF); + break; + } + } + } + rtc::SocketAddress address_; +}; + +// Implements STUN attributes that record an Internet address. When encoded +// in a STUN message, the address contained in this attribute is XORed with the +// transaction ID of the message. +class StunXorAddressAttribute : public StunAddressAttribute { + public: + StunXorAddressAttribute(uint16_t type, const rtc::SocketAddress& addr); + StunXorAddressAttribute(uint16_t type, uint16_t length, StunMessage* owner); + + StunAttributeValueType value_type() const override; + void SetOwner(StunMessage* owner) override; + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + rtc::IPAddress GetXoredIP() const; + StunMessage* owner_; +}; + +// Implements STUN attributes that record a 32-bit integer. +class StunUInt32Attribute : public StunAttribute { + public: + static const uint16_t SIZE = 4; + StunUInt32Attribute(uint16_t type, uint32_t value); + explicit StunUInt32Attribute(uint16_t type); + + StunAttributeValueType value_type() const override; + + uint32_t value() const { return bits_; } + void SetValue(uint32_t bits) { bits_ = bits; } + + bool GetBit(size_t index) const; + void SetBit(size_t index, bool value); + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + uint32_t bits_; +}; + +class StunUInt64Attribute : public StunAttribute { + public: + static const uint16_t SIZE = 8; + StunUInt64Attribute(uint16_t type, uint64_t value); + explicit StunUInt64Attribute(uint16_t type); + + StunAttributeValueType value_type() const override; + + uint64_t value() const { return bits_; } + void SetValue(uint64_t bits) { bits_ = bits; } + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + uint64_t bits_; +}; + +// Implements STUN attributes that record an arbitrary byte string. +class StunByteStringAttribute : public StunAttribute { + public: + explicit StunByteStringAttribute(uint16_t type); + StunByteStringAttribute(uint16_t type, const std::string& str); + StunByteStringAttribute(uint16_t type, const void* bytes, size_t length); + StunByteStringAttribute(uint16_t type, uint16_t length); + ~StunByteStringAttribute() override; + + StunAttributeValueType value_type() const override; + + const char* bytes() const { return bytes_; } + std::string GetString() const { return std::string(bytes_, length()); } + + void CopyBytes(const char* bytes); // uses strlen + void CopyBytes(const void* bytes, size_t length); + + uint8_t GetByte(size_t index) const; + void SetByte(size_t index, uint8_t value); + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + void SetBytes(char* bytes, size_t length); + + char* bytes_; +}; + +// Implements STUN attributes that record an error code. +class StunErrorCodeAttribute : public StunAttribute { + public: + static const uint16_t MIN_SIZE; + StunErrorCodeAttribute(uint16_t type, int code, const std::string& reason); + StunErrorCodeAttribute(uint16_t type, uint16_t length); + ~StunErrorCodeAttribute() override; + + StunAttributeValueType value_type() const override; + + // The combined error and class, e.g. 0x400. + int code() const; + void SetCode(int code); + + // The individual error components. + int eclass() const { return class_; } + int number() const { return number_; } + const std::string& reason() const { return reason_; } + void SetClass(uint8_t eclass) { class_ = eclass; } + void SetNumber(uint8_t number) { number_ = number; } + void SetReason(const std::string& reason); + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + uint8_t class_; + uint8_t number_; + std::string reason_; +}; + +// Implements STUN attributes that record a list of attribute names. +class StunUInt16ListAttribute : public StunAttribute { + public: + StunUInt16ListAttribute(uint16_t type, uint16_t length); + ~StunUInt16ListAttribute() override; + + StunAttributeValueType value_type() const override; + + size_t Size() const; + uint16_t GetType(int index) const; + void SetType(int index, uint16_t value); + void AddType(uint16_t value); + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + std::vector* attr_types_; +}; + +// Returns the (successful) response type for the given request type. +// Returns -1 if |request_type| is not a valid request type. +int GetStunSuccessResponseType(int request_type); + +// Returns the error response type for the given request type. +// Returns -1 if |request_type| is not a valid request type. +int GetStunErrorResponseType(int request_type); + +// Returns whether a given message is a request type. +bool IsStunRequestType(int msg_type); + +// Returns whether a given message is an indication type. +bool IsStunIndicationType(int msg_type); + +// Returns whether a given response is a success type. +bool IsStunSuccessResponseType(int msg_type); + +// Returns whether a given response is an error type. +bool IsStunErrorResponseType(int msg_type); + +// Computes the STUN long-term credential hash. +bool ComputeStunCredentialHash(const std::string& username, + const std::string& realm, + const std::string& password, + std::string* hash); + +// Make a copy af |attribute| and return a new StunAttribute. +// This is useful if you don't care about what kind of attribute you +// are handling. +// +// The implementation copies by calling Write() followed by Read(). +// +// If |tmp_buffer| is supplied this buffer will be used, otherwise +// a buffer will created in the method. +std::unique_ptr CopyStunAttribute( + const StunAttribute& attribute, + rtc::ByteBufferWriter* tmp_buffer_ptr = 0); + +// TODO(?): Move the TURN/ICE stuff below out to separate files. +extern const char TURN_MAGIC_COOKIE_VALUE[4]; + +// "GTURN" STUN methods. +// TODO(?): Rename these methods to GTURN_ to make it clear they aren't +// part of standard STUN/TURN. +enum RelayMessageType { + // For now, using the same defs from TurnMessageType below. + // STUN_ALLOCATE_REQUEST = 0x0003, + // STUN_ALLOCATE_RESPONSE = 0x0103, + // STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, + STUN_SEND_REQUEST = 0x0004, + STUN_SEND_RESPONSE = 0x0104, + STUN_SEND_ERROR_RESPONSE = 0x0114, + STUN_DATA_INDICATION = 0x0115, +}; + +// "GTURN"-specific STUN attributes. +// TODO(?): Rename these attributes to GTURN_ to avoid conflicts. +enum RelayAttributeType { + STUN_ATTR_LIFETIME = 0x000d, // UInt32 + STUN_ATTR_MAGIC_COOKIE = 0x000f, // ByteString, 4 bytes + STUN_ATTR_BANDWIDTH = 0x0010, // UInt32 + STUN_ATTR_DESTINATION_ADDRESS = 0x0011, // Address + STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, // Address + STUN_ATTR_DATA = 0x0013, // ByteString + STUN_ATTR_OPTIONS = 0x8001, // UInt32 +}; + +// A "GTURN" STUN message. +class RelayMessage : public StunMessage { + protected: + StunAttributeValueType GetAttributeValueType(int type) const override; + StunMessage* CreateNew() const override; +}; + +// Defined in TURN RFC 5766. +enum TurnMessageType { + STUN_ALLOCATE_REQUEST = 0x0003, + STUN_ALLOCATE_RESPONSE = 0x0103, + STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, + TURN_REFRESH_REQUEST = 0x0004, + TURN_REFRESH_RESPONSE = 0x0104, + TURN_REFRESH_ERROR_RESPONSE = 0x0114, + TURN_SEND_INDICATION = 0x0016, + TURN_DATA_INDICATION = 0x0017, + TURN_CREATE_PERMISSION_REQUEST = 0x0008, + TURN_CREATE_PERMISSION_RESPONSE = 0x0108, + TURN_CREATE_PERMISSION_ERROR_RESPONSE = 0x0118, + TURN_CHANNEL_BIND_REQUEST = 0x0009, + TURN_CHANNEL_BIND_RESPONSE = 0x0109, + TURN_CHANNEL_BIND_ERROR_RESPONSE = 0x0119, +}; + +enum TurnAttributeType { + STUN_ATTR_CHANNEL_NUMBER = 0x000C, // UInt32 + STUN_ATTR_TURN_LIFETIME = 0x000d, // UInt32 + STUN_ATTR_XOR_PEER_ADDRESS = 0x0012, // XorAddress + // TODO(mallinath) - Uncomment after RelayAttributes are renamed. + // STUN_ATTR_DATA = 0x0013, // ByteString + STUN_ATTR_XOR_RELAYED_ADDRESS = 0x0016, // XorAddress + STUN_ATTR_EVEN_PORT = 0x0018, // ByteString, 1 byte. + STUN_ATTR_REQUESTED_TRANSPORT = 0x0019, // UInt32 + STUN_ATTR_DONT_FRAGMENT = 0x001A, // No content, Length = 0 + STUN_ATTR_RESERVATION_TOKEN = 0x0022, // ByteString, 8 bytes. + // TODO(mallinath) - Rename STUN_ATTR_TURN_LIFETIME to STUN_ATTR_LIFETIME and + // STUN_ATTR_TURN_DATA to STUN_ATTR_DATA. Also rename RelayMessage attributes + // by appending G to attribute name. +}; + +// RFC 5766-defined errors. +enum TurnErrorType { + STUN_ERROR_FORBIDDEN = 403, + STUN_ERROR_ALLOCATION_MISMATCH = 437, + STUN_ERROR_WRONG_CREDENTIALS = 441, + STUN_ERROR_UNSUPPORTED_PROTOCOL = 442 +}; + +extern const int SERVER_NOT_REACHABLE_ERROR; + +extern const char STUN_ERROR_REASON_FORBIDDEN[]; +extern const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[]; +extern const char STUN_ERROR_REASON_WRONG_CREDENTIALS[]; +extern const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[]; +class TurnMessage : public StunMessage { + protected: + StunAttributeValueType GetAttributeValueType(int type) const override; + StunMessage* CreateNew() const override; +}; + +enum IceAttributeType { + // RFC 5245 ICE STUN attributes. + STUN_ATTR_PRIORITY = 0x0024, // UInt32 + STUN_ATTR_USE_CANDIDATE = 0x0025, // No content, Length = 0 + STUN_ATTR_ICE_CONTROLLED = 0x8029, // UInt64 + STUN_ATTR_ICE_CONTROLLING = 0x802A, // UInt64 + // The following attributes are in the comprehension-optional range + // (0xC000-0xFFFF) and are not registered with IANA. These STUN attributes are + // intended for ICE and should NOT be used in generic use cases of STUN + // messages. + // + // Note that the value 0xC001 has already been assigned by IANA to + // ENF-FLOW-DESCRIPTION + // (https://www.iana.org/assignments/stun-parameters/stun-parameters.xml). + STUN_ATTR_NOMINATION = 0xC001, // UInt32 + // UInt32. The higher 16 bits are the network ID. The lower 16 bits are the + // network cost. + STUN_ATTR_NETWORK_INFO = 0xC057, + // Experimental: Transaction ID of the last connectivity check received. + STUN_ATTR_LAST_ICE_CHECK_RECEIVED = 0xC058, +}; + +// RFC 5245-defined errors. +enum IceErrorCode { + STUN_ERROR_ROLE_CONFLICT = 487, +}; +extern const char STUN_ERROR_REASON_ROLE_CONFLICT[]; + +// A RFC 5245 ICE STUN message. +class IceMessage : public StunMessage { + protected: + StunAttributeValueType GetAttributeValueType(int type) const override; + StunMessage* CreateNew() const override; +}; + +} // namespace cricket + +#endif // API_TRANSPORT_STUN_H_ diff --git a/p2p/base/stun_unittest.cc b/api/transport/stun_unittest.cc similarity index 99% rename from p2p/base/stun_unittest.cc rename to api/transport/stun_unittest.cc index 69f6f2da58..667746efd1 100644 --- a/p2p/base/stun_unittest.cc +++ b/api/transport/stun_unittest.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "p2p/base/stun.h" +#include "api/transport/stun.h" #include diff --git a/media/BUILD.gn b/media/BUILD.gn index 8090db8280..c38ce7dc6d 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -82,6 +82,7 @@ rtc_library("rtc_media_base") { "../api/crypto:frame_decryptor_interface", "../api/crypto:frame_encryptor_interface", "../api/crypto:options", + "../api/transport:stun_types", "../api/transport/media:media_transport_interface", "../api/transport/rtp:rtp_source", "../api/video:video_bitrate_allocation", diff --git a/media/base/turn_utils.cc b/media/base/turn_utils.cc index c0f1a28224..c413117fb6 100644 --- a/media/base/turn_utils.cc +++ b/media/base/turn_utils.cc @@ -10,7 +10,7 @@ #include "media/base/turn_utils.h" -#include "p2p/base/stun.h" +#include "api/transport/stun.h" #include "rtc_base/byte_order.h" namespace cricket { diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn index 42afcffdc0..6ed14a8da5 100644 --- a/p2p/BUILD.gn +++ b/p2p/BUILD.gn @@ -15,12 +15,14 @@ group("p2p") { ] } +# TODO(bugs.webrtc.org/11091): Remove this target when downstream is updated. rtc_library("stun_types") { sources = [ - "base/stun.cc", + "base/empty.cc", "base/stun.h", ] deps = [ + "../api/transport:stun_types", "../rtc_base:checks", "../rtc_base:rtc_base", "../rtc_base:rtc_base_approved", @@ -103,6 +105,7 @@ rtc_library("rtc_p2p") { "../api/crypto:options", "../api/rtc_event_log", "../api/transport:enums", + "../api/transport:stun_types", "../logging:ice_log", "../rtc_base", "../rtc_base:checks", @@ -175,6 +178,7 @@ if (rtc_include_tests) { "../api:libjingle_peerconnection_api", "../api:packet_socket_factory", "../api/crypto:options", + "../api/transport:stun_types", "../rtc_base", "../rtc_base:gunit_helpers", "../rtc_base:rtc_base_approved", @@ -203,7 +207,6 @@ if (rtc_include_tests) { "base/stun_port_unittest.cc", "base/stun_request_unittest.cc", "base/stun_server_unittest.cc", - "base/stun_unittest.cc", "base/tcp_port_unittest.cc", "base/transport_description_factory_unittest.cc", "base/turn_port_unittest.cc", @@ -220,6 +223,7 @@ if (rtc_include_tests) { "../api:libjingle_peerconnection_api", "../api:packet_socket_factory", "../api:scoped_refptr", + "../api/transport:stun_types", "../api/units:time_delta", "../rtc_base", "../rtc_base:checks", @@ -251,6 +255,7 @@ rtc_library("p2p_server_utils") { ":rtc_p2p", ":stun_types", "../api:packet_socket_factory", + "../api/transport:stun_types", "../rtc_base", "../rtc_base:checks", "../rtc_base:rtc_base_tests_utils", @@ -270,6 +275,7 @@ rtc_library("libstunprober") { ":rtc_p2p", ":stun_types", "../api:packet_socket_factory", + "../api/transport:stun_types", "../rtc_base", "../rtc_base:checks", "../rtc_base/system:rtc_export", diff --git a/p2p/base/async_stun_tcp_socket.cc b/p2p/base/async_stun_tcp_socket.cc index 5ded8aeafc..b85e25ad14 100644 --- a/p2p/base/async_stun_tcp_socket.cc +++ b/p2p/base/async_stun_tcp_socket.cc @@ -14,7 +14,7 @@ #include #include -#include "p2p/base/stun.h" +#include "api/transport/stun.h" #include "rtc_base/byte_order.h" #include "rtc_base/checks.h" #include "rtc_base/network/sent_packet.h" diff --git a/p2p/base/connection.h b/p2p/base/connection.h index dc9333d807..e0a0ba9f2b 100644 --- a/p2p/base/connection.h +++ b/p2p/base/connection.h @@ -16,10 +16,10 @@ #include "absl/types/optional.h" #include "api/candidate.h" +#include "api/transport/stun.h" #include "logging/rtc_event_log/ice_logger.h" #include "p2p/base/candidate_pair_interface.h" #include "p2p/base/connection_info.h" -#include "p2p/base/stun.h" #include "p2p/base/stun_request.h" #include "p2p/base/transport_description.h" #include "rtc_base/async_packet_socket.h" diff --git a/p2p/base/empty.cc b/p2p/base/empty.cc new file mode 100644 index 0000000000..e7fccda441 --- /dev/null +++ b/p2p/base/empty.cc @@ -0,0 +1,11 @@ +/* + * Copyright 2019 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. + */ + +// TODO(bugs.webrtc.org/11091): nuke this after downstream updated. diff --git a/p2p/base/port.h b/p2p/base/port.h index 5bd59d0e4d..d6099222fa 100644 --- a/p2p/base/port.h +++ b/p2p/base/port.h @@ -22,6 +22,7 @@ #include "api/candidate.h" #include "api/packet_socket_factory.h" #include "api/rtc_error.h" +#include "api/transport/stun.h" #include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h" #include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h" #include "logging/rtc_event_log/ice_logger.h" @@ -30,7 +31,6 @@ #include "p2p/base/connection_info.h" #include "p2p/base/p2p_constants.h" #include "p2p/base/port_interface.h" -#include "p2p/base/stun.h" #include "p2p/base/stun_request.h" #include "rtc_base/async_packet_socket.h" #include "rtc_base/checks.h" diff --git a/p2p/base/port_unittest.cc b/p2p/base/port_unittest.cc index 4103ba41b3..ec2a872acd 100644 --- a/p2p/base/port_unittest.cc +++ b/p2p/base/port_unittest.cc @@ -22,12 +22,12 @@ #include "absl/types/optional.h" #include "api/candidate.h" #include "api/packet_socket_factory.h" +#include "api/transport/stun.h" #include "api/units/time_delta.h" #include "p2p/base/basic_packet_socket_factory.h" #include "p2p/base/p2p_constants.h" #include "p2p/base/port_allocator.h" #include "p2p/base/port_interface.h" -#include "p2p/base/stun.h" #include "p2p/base/stun_port.h" #include "p2p/base/stun_server.h" #include "p2p/base/tcp_port.h" diff --git a/p2p/base/stun.h b/p2p/base/stun.h index 5c1342d373..2249c6516d 100644 --- a/p2p/base/stun.h +++ b/p2p/base/stun.h @@ -11,625 +11,7 @@ #ifndef P2P_BASE_STUN_H_ #define P2P_BASE_STUN_H_ -// This file contains classes for dealing with the STUN protocol, as specified -// in RFC 5389, and its descendants. - -#include -#include - -#include -#include -#include - -#include "rtc_base/byte_buffer.h" -#include "rtc_base/ip_address.h" -#include "rtc_base/socket_address.h" - -namespace cricket { - -// These are the types of STUN messages defined in RFC 5389. -enum StunMessageType { - STUN_BINDING_REQUEST = 0x0001, - STUN_BINDING_INDICATION = 0x0011, - STUN_BINDING_RESPONSE = 0x0101, - STUN_BINDING_ERROR_RESPONSE = 0x0111, -}; - -// These are all known STUN attributes, defined in RFC 5389 and elsewhere. -// Next to each is the name of the class (T is StunTAttribute) that implements -// that type. -// RETRANSMIT_COUNT is the number of outstanding pings without a response at -// the time the packet is generated. -enum StunAttributeType { - STUN_ATTR_MAPPED_ADDRESS = 0x0001, // Address - STUN_ATTR_USERNAME = 0x0006, // ByteString - STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, // ByteString, 20 bytes - STUN_ATTR_ERROR_CODE = 0x0009, // ErrorCode - STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, // UInt16List - STUN_ATTR_REALM = 0x0014, // ByteString - STUN_ATTR_NONCE = 0x0015, // ByteString - STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020, // XorAddress - STUN_ATTR_SOFTWARE = 0x8022, // ByteString - STUN_ATTR_ALTERNATE_SERVER = 0x8023, // Address - STUN_ATTR_FINGERPRINT = 0x8028, // UInt32 - STUN_ATTR_ORIGIN = 0x802F, // ByteString - STUN_ATTR_RETRANSMIT_COUNT = 0xFF00 // UInt32 -}; - -// These are the types of the values associated with the attributes above. -// This allows us to perform some basic validation when reading or adding -// attributes. Note that these values are for our own use, and not defined in -// RFC 5389. -enum StunAttributeValueType { - STUN_VALUE_UNKNOWN = 0, - STUN_VALUE_ADDRESS = 1, - STUN_VALUE_XOR_ADDRESS = 2, - STUN_VALUE_UINT32 = 3, - STUN_VALUE_UINT64 = 4, - STUN_VALUE_BYTE_STRING = 5, - STUN_VALUE_ERROR_CODE = 6, - STUN_VALUE_UINT16_LIST = 7 -}; - -// These are the types of STUN addresses defined in RFC 5389. -enum StunAddressFamily { - // NB: UNDEF is not part of the STUN spec. - STUN_ADDRESS_UNDEF = 0, - STUN_ADDRESS_IPV4 = 1, - STUN_ADDRESS_IPV6 = 2 -}; - -// These are the types of STUN error codes defined in RFC 5389. -enum StunErrorCode { - STUN_ERROR_TRY_ALTERNATE = 300, - STUN_ERROR_BAD_REQUEST = 400, - STUN_ERROR_UNAUTHORIZED = 401, - STUN_ERROR_UNKNOWN_ATTRIBUTE = 420, - STUN_ERROR_STALE_CREDENTIALS = 430, // GICE only - STUN_ERROR_STALE_NONCE = 438, - STUN_ERROR_SERVER_ERROR = 500, - STUN_ERROR_GLOBAL_FAILURE = 600 -}; - -// Strings for the error codes above. -extern const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[]; -extern const char STUN_ERROR_REASON_BAD_REQUEST[]; -extern const char STUN_ERROR_REASON_UNAUTHORIZED[]; -extern const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[]; -extern const char STUN_ERROR_REASON_STALE_CREDENTIALS[]; -extern const char STUN_ERROR_REASON_STALE_NONCE[]; -extern const char STUN_ERROR_REASON_SERVER_ERROR[]; - -// The mask used to determine whether a STUN message is a request/response etc. -const uint32_t kStunTypeMask = 0x0110; - -// STUN Attribute header length. -const size_t kStunAttributeHeaderSize = 4; - -// Following values correspond to RFC5389. -const size_t kStunHeaderSize = 20; -const size_t kStunTransactionIdOffset = 8; -const size_t kStunTransactionIdLength = 12; -const uint32_t kStunMagicCookie = 0x2112A442; -constexpr size_t kStunMagicCookieLength = sizeof(kStunMagicCookie); - -// Following value corresponds to an earlier version of STUN from -// RFC3489. -const size_t kStunLegacyTransactionIdLength = 16; - -// STUN Message Integrity HMAC length. -const size_t kStunMessageIntegritySize = 20; - -class StunAddressAttribute; -class StunAttribute; -class StunByteStringAttribute; -class StunErrorCodeAttribute; - -class StunUInt16ListAttribute; -class StunUInt32Attribute; -class StunUInt64Attribute; -class StunXorAddressAttribute; - -// Records a complete STUN/TURN message. Each message consists of a type and -// any number of attributes. Each attribute is parsed into an instance of an -// appropriate class (see above). The Get* methods will return instances of -// that attribute class. -class StunMessage { - public: - StunMessage(); - virtual ~StunMessage(); - - int type() const { return type_; } - size_t length() const { return length_; } - const std::string& transaction_id() const { return transaction_id_; } - uint32_t reduced_transaction_id() const { return reduced_transaction_id_; } - - // Returns true if the message confirms to RFC3489 rather than - // RFC5389. The main difference between two version of the STUN - // protocol is the presence of the magic cookie and different length - // of transaction ID. For outgoing packets version of the protocol - // is determined by the lengths of the transaction ID. - bool IsLegacy() const; - - void SetType(int type) { type_ = static_cast(type); } - bool SetTransactionID(const std::string& str); - - // Gets the desired attribute value, or NULL if no such attribute type exists. - const StunAddressAttribute* GetAddress(int type) const; - const StunUInt32Attribute* GetUInt32(int type) const; - const StunUInt64Attribute* GetUInt64(int type) const; - const StunByteStringAttribute* GetByteString(int type) const; - - // Gets these specific attribute values. - const StunErrorCodeAttribute* GetErrorCode() const; - // Returns the code inside the error code attribute, if present, and - // STUN_ERROR_GLOBAL_FAILURE otherwise. - int GetErrorCodeValue() const; - const StunUInt16ListAttribute* GetUnknownAttributes() const; - - // Takes ownership of the specified attribute and adds it to the message. - void AddAttribute(std::unique_ptr attr); - - // Remove the last occurrence of an attribute. - std::unique_ptr RemoveAttribute(int type); - - // Validates that a raw STUN message has a correct MESSAGE-INTEGRITY value. - // This can't currently be done on a StunMessage, since it is affected by - // padding data (which we discard when reading a StunMessage). - static bool ValidateMessageIntegrity(const char* data, - size_t size, - const std::string& password); - // Adds a MESSAGE-INTEGRITY attribute that is valid for the current message. - bool AddMessageIntegrity(const std::string& password); - bool AddMessageIntegrity(const char* key, size_t keylen); - - // Verifies that a given buffer is STUN by checking for a correct FINGERPRINT. - static bool ValidateFingerprint(const char* data, size_t size); - - // Adds a FINGERPRINT attribute that is valid for the current message. - bool AddFingerprint(); - - // Parses the STUN packet in the given buffer and records it here. The - // return value indicates whether this was successful. - bool Read(rtc::ByteBufferReader* buf); - - // Writes this object into a STUN packet. The return value indicates whether - // this was successful. - bool Write(rtc::ByteBufferWriter* buf) const; - - // Creates an empty message. Overridable by derived classes. - virtual StunMessage* CreateNew() const; - - // Modify the stun magic cookie used for this STUN message. - // This is used for testing. - void SetStunMagicCookie(uint32_t val); - - protected: - // Verifies that the given attribute is allowed for this message. - virtual StunAttributeValueType GetAttributeValueType(int type) const; - - private: - StunAttribute* CreateAttribute(int type, size_t length) /* const*/; - const StunAttribute* GetAttribute(int type) const; - static bool IsValidTransactionId(const std::string& transaction_id); - - uint16_t type_; - uint16_t length_; - std::string transaction_id_; - uint32_t reduced_transaction_id_; - std::vector> attrs_; - uint32_t stun_magic_cookie_; -}; - -// Base class for all STUN/TURN attributes. -class StunAttribute { - public: - virtual ~StunAttribute() {} - - int type() const { return type_; } - size_t length() const { return length_; } - - // Return the type of this attribute. - virtual StunAttributeValueType value_type() const = 0; - - // Only XorAddressAttribute needs this so far. - virtual void SetOwner(StunMessage* owner) {} - - // Reads the body (not the type or length) for this type of attribute from - // the given buffer. Return value is true if successful. - virtual bool Read(rtc::ByteBufferReader* buf) = 0; - - // Writes the body (not the type or length) to the given buffer. Return - // value is true if successful. - virtual bool Write(rtc::ByteBufferWriter* buf) const = 0; - - // Creates an attribute object with the given type and smallest length. - static StunAttribute* Create(StunAttributeValueType value_type, - uint16_t type, - uint16_t length, - StunMessage* owner); - // TODO(?): Allow these create functions to take parameters, to reduce - // the amount of work callers need to do to initialize attributes. - static std::unique_ptr CreateAddress(uint16_t type); - static std::unique_ptr CreateXorAddress( - uint16_t type); - static std::unique_ptr CreateUInt32(uint16_t type); - static std::unique_ptr CreateUInt64(uint16_t type); - static std::unique_ptr CreateByteString( - uint16_t type); - static std::unique_ptr CreateErrorCode(); - static std::unique_ptr CreateUnknownAttributes(); - - protected: - StunAttribute(uint16_t type, uint16_t length); - void SetLength(uint16_t length) { length_ = length; } - void WritePadding(rtc::ByteBufferWriter* buf) const; - void ConsumePadding(rtc::ByteBufferReader* buf) const; - - private: - uint16_t type_; - uint16_t length_; -}; - -// Implements STUN attributes that record an Internet address. -class StunAddressAttribute : public StunAttribute { - public: - static const uint16_t SIZE_UNDEF = 0; - static const uint16_t SIZE_IP4 = 8; - static const uint16_t SIZE_IP6 = 20; - StunAddressAttribute(uint16_t type, const rtc::SocketAddress& addr); - StunAddressAttribute(uint16_t type, uint16_t length); - - StunAttributeValueType value_type() const override; - - StunAddressFamily family() const { - switch (address_.ipaddr().family()) { - case AF_INET: - return STUN_ADDRESS_IPV4; - case AF_INET6: - return STUN_ADDRESS_IPV6; - } - return STUN_ADDRESS_UNDEF; - } - - const rtc::SocketAddress& GetAddress() const { return address_; } - const rtc::IPAddress& ipaddr() const { return address_.ipaddr(); } - uint16_t port() const { return address_.port(); } - - void SetAddress(const rtc::SocketAddress& addr) { - address_ = addr; - EnsureAddressLength(); - } - void SetIP(const rtc::IPAddress& ip) { - address_.SetIP(ip); - EnsureAddressLength(); - } - void SetPort(uint16_t port) { address_.SetPort(port); } - - bool Read(rtc::ByteBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - private: - void EnsureAddressLength() { - switch (family()) { - case STUN_ADDRESS_IPV4: { - SetLength(SIZE_IP4); - break; - } - case STUN_ADDRESS_IPV6: { - SetLength(SIZE_IP6); - break; - } - default: { - SetLength(SIZE_UNDEF); - break; - } - } - } - rtc::SocketAddress address_; -}; - -// Implements STUN attributes that record an Internet address. When encoded -// in a STUN message, the address contained in this attribute is XORed with the -// transaction ID of the message. -class StunXorAddressAttribute : public StunAddressAttribute { - public: - StunXorAddressAttribute(uint16_t type, const rtc::SocketAddress& addr); - StunXorAddressAttribute(uint16_t type, uint16_t length, StunMessage* owner); - - StunAttributeValueType value_type() const override; - void SetOwner(StunMessage* owner) override; - bool Read(rtc::ByteBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - private: - rtc::IPAddress GetXoredIP() const; - StunMessage* owner_; -}; - -// Implements STUN attributes that record a 32-bit integer. -class StunUInt32Attribute : public StunAttribute { - public: - static const uint16_t SIZE = 4; - StunUInt32Attribute(uint16_t type, uint32_t value); - explicit StunUInt32Attribute(uint16_t type); - - StunAttributeValueType value_type() const override; - - uint32_t value() const { return bits_; } - void SetValue(uint32_t bits) { bits_ = bits; } - - bool GetBit(size_t index) const; - void SetBit(size_t index, bool value); - - bool Read(rtc::ByteBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - private: - uint32_t bits_; -}; - -class StunUInt64Attribute : public StunAttribute { - public: - static const uint16_t SIZE = 8; - StunUInt64Attribute(uint16_t type, uint64_t value); - explicit StunUInt64Attribute(uint16_t type); - - StunAttributeValueType value_type() const override; - - uint64_t value() const { return bits_; } - void SetValue(uint64_t bits) { bits_ = bits; } - - bool Read(rtc::ByteBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - private: - uint64_t bits_; -}; - -// Implements STUN attributes that record an arbitrary byte string. -class StunByteStringAttribute : public StunAttribute { - public: - explicit StunByteStringAttribute(uint16_t type); - StunByteStringAttribute(uint16_t type, const std::string& str); - StunByteStringAttribute(uint16_t type, const void* bytes, size_t length); - StunByteStringAttribute(uint16_t type, uint16_t length); - ~StunByteStringAttribute() override; - - StunAttributeValueType value_type() const override; - - const char* bytes() const { return bytes_; } - std::string GetString() const { return std::string(bytes_, length()); } - - void CopyBytes(const char* bytes); // uses strlen - void CopyBytes(const void* bytes, size_t length); - - uint8_t GetByte(size_t index) const; - void SetByte(size_t index, uint8_t value); - - bool Read(rtc::ByteBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - private: - void SetBytes(char* bytes, size_t length); - - char* bytes_; -}; - -// Implements STUN attributes that record an error code. -class StunErrorCodeAttribute : public StunAttribute { - public: - static const uint16_t MIN_SIZE; - StunErrorCodeAttribute(uint16_t type, int code, const std::string& reason); - StunErrorCodeAttribute(uint16_t type, uint16_t length); - ~StunErrorCodeAttribute() override; - - StunAttributeValueType value_type() const override; - - // The combined error and class, e.g. 0x400. - int code() const; - void SetCode(int code); - - // The individual error components. - int eclass() const { return class_; } - int number() const { return number_; } - const std::string& reason() const { return reason_; } - void SetClass(uint8_t eclass) { class_ = eclass; } - void SetNumber(uint8_t number) { number_ = number; } - void SetReason(const std::string& reason); - - bool Read(rtc::ByteBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - private: - uint8_t class_; - uint8_t number_; - std::string reason_; -}; - -// Implements STUN attributes that record a list of attribute names. -class StunUInt16ListAttribute : public StunAttribute { - public: - StunUInt16ListAttribute(uint16_t type, uint16_t length); - ~StunUInt16ListAttribute() override; - - StunAttributeValueType value_type() const override; - - size_t Size() const; - uint16_t GetType(int index) const; - void SetType(int index, uint16_t value); - void AddType(uint16_t value); - - bool Read(rtc::ByteBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - private: - std::vector* attr_types_; -}; - -// Returns the (successful) response type for the given request type. -// Returns -1 if |request_type| is not a valid request type. -int GetStunSuccessResponseType(int request_type); - -// Returns the error response type for the given request type. -// Returns -1 if |request_type| is not a valid request type. -int GetStunErrorResponseType(int request_type); - -// Returns whether a given message is a request type. -bool IsStunRequestType(int msg_type); - -// Returns whether a given message is an indication type. -bool IsStunIndicationType(int msg_type); - -// Returns whether a given response is a success type. -bool IsStunSuccessResponseType(int msg_type); - -// Returns whether a given response is an error type. -bool IsStunErrorResponseType(int msg_type); - -// Computes the STUN long-term credential hash. -bool ComputeStunCredentialHash(const std::string& username, - const std::string& realm, - const std::string& password, - std::string* hash); - -// Make a copy af |attribute| and return a new StunAttribute. -// This is useful if you don't care about what kind of attribute you -// are handling. -// -// The implementation copies by calling Write() followed by Read(). -// -// If |tmp_buffer| is supplied this buffer will be used, otherwise -// a buffer will created in the method. -std::unique_ptr CopyStunAttribute( - const StunAttribute& attribute, - rtc::ByteBufferWriter* tmp_buffer_ptr = 0); - -// TODO(?): Move the TURN/ICE stuff below out to separate files. -extern const char TURN_MAGIC_COOKIE_VALUE[4]; - -// "GTURN" STUN methods. -// TODO(?): Rename these methods to GTURN_ to make it clear they aren't -// part of standard STUN/TURN. -enum RelayMessageType { - // For now, using the same defs from TurnMessageType below. - // STUN_ALLOCATE_REQUEST = 0x0003, - // STUN_ALLOCATE_RESPONSE = 0x0103, - // STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, - STUN_SEND_REQUEST = 0x0004, - STUN_SEND_RESPONSE = 0x0104, - STUN_SEND_ERROR_RESPONSE = 0x0114, - STUN_DATA_INDICATION = 0x0115, -}; - -// "GTURN"-specific STUN attributes. -// TODO(?): Rename these attributes to GTURN_ to avoid conflicts. -enum RelayAttributeType { - STUN_ATTR_LIFETIME = 0x000d, // UInt32 - STUN_ATTR_MAGIC_COOKIE = 0x000f, // ByteString, 4 bytes - STUN_ATTR_BANDWIDTH = 0x0010, // UInt32 - STUN_ATTR_DESTINATION_ADDRESS = 0x0011, // Address - STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, // Address - STUN_ATTR_DATA = 0x0013, // ByteString - STUN_ATTR_OPTIONS = 0x8001, // UInt32 -}; - -// A "GTURN" STUN message. -class RelayMessage : public StunMessage { - protected: - StunAttributeValueType GetAttributeValueType(int type) const override; - StunMessage* CreateNew() const override; -}; - -// Defined in TURN RFC 5766. -enum TurnMessageType { - STUN_ALLOCATE_REQUEST = 0x0003, - STUN_ALLOCATE_RESPONSE = 0x0103, - STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, - TURN_REFRESH_REQUEST = 0x0004, - TURN_REFRESH_RESPONSE = 0x0104, - TURN_REFRESH_ERROR_RESPONSE = 0x0114, - TURN_SEND_INDICATION = 0x0016, - TURN_DATA_INDICATION = 0x0017, - TURN_CREATE_PERMISSION_REQUEST = 0x0008, - TURN_CREATE_PERMISSION_RESPONSE = 0x0108, - TURN_CREATE_PERMISSION_ERROR_RESPONSE = 0x0118, - TURN_CHANNEL_BIND_REQUEST = 0x0009, - TURN_CHANNEL_BIND_RESPONSE = 0x0109, - TURN_CHANNEL_BIND_ERROR_RESPONSE = 0x0119, -}; - -enum TurnAttributeType { - STUN_ATTR_CHANNEL_NUMBER = 0x000C, // UInt32 - STUN_ATTR_TURN_LIFETIME = 0x000d, // UInt32 - STUN_ATTR_XOR_PEER_ADDRESS = 0x0012, // XorAddress - // TODO(mallinath) - Uncomment after RelayAttributes are renamed. - // STUN_ATTR_DATA = 0x0013, // ByteString - STUN_ATTR_XOR_RELAYED_ADDRESS = 0x0016, // XorAddress - STUN_ATTR_EVEN_PORT = 0x0018, // ByteString, 1 byte. - STUN_ATTR_REQUESTED_TRANSPORT = 0x0019, // UInt32 - STUN_ATTR_DONT_FRAGMENT = 0x001A, // No content, Length = 0 - STUN_ATTR_RESERVATION_TOKEN = 0x0022, // ByteString, 8 bytes. - // TODO(mallinath) - Rename STUN_ATTR_TURN_LIFETIME to STUN_ATTR_LIFETIME and - // STUN_ATTR_TURN_DATA to STUN_ATTR_DATA. Also rename RelayMessage attributes - // by appending G to attribute name. -}; - -// RFC 5766-defined errors. -enum TurnErrorType { - STUN_ERROR_FORBIDDEN = 403, - STUN_ERROR_ALLOCATION_MISMATCH = 437, - STUN_ERROR_WRONG_CREDENTIALS = 441, - STUN_ERROR_UNSUPPORTED_PROTOCOL = 442 -}; - -extern const int SERVER_NOT_REACHABLE_ERROR; - -extern const char STUN_ERROR_REASON_FORBIDDEN[]; -extern const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[]; -extern const char STUN_ERROR_REASON_WRONG_CREDENTIALS[]; -extern const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[]; -class TurnMessage : public StunMessage { - protected: - StunAttributeValueType GetAttributeValueType(int type) const override; - StunMessage* CreateNew() const override; -}; - -enum IceAttributeType { - // RFC 5245 ICE STUN attributes. - STUN_ATTR_PRIORITY = 0x0024, // UInt32 - STUN_ATTR_USE_CANDIDATE = 0x0025, // No content, Length = 0 - STUN_ATTR_ICE_CONTROLLED = 0x8029, // UInt64 - STUN_ATTR_ICE_CONTROLLING = 0x802A, // UInt64 - // The following attributes are in the comprehension-optional range - // (0xC000-0xFFFF) and are not registered with IANA. These STUN attributes are - // intended for ICE and should NOT be used in generic use cases of STUN - // messages. - // - // Note that the value 0xC001 has already been assigned by IANA to - // ENF-FLOW-DESCRIPTION - // (https://www.iana.org/assignments/stun-parameters/stun-parameters.xml). - STUN_ATTR_NOMINATION = 0xC001, // UInt32 - // UInt32. The higher 16 bits are the network ID. The lower 16 bits are the - // network cost. - STUN_ATTR_NETWORK_INFO = 0xC057, - // Experimental: Transaction ID of the last connectivity check received. - STUN_ATTR_LAST_ICE_CHECK_RECEIVED = 0xC058, -}; - -// RFC 5245-defined errors. -enum IceErrorCode { - STUN_ERROR_ROLE_CONFLICT = 487, -}; -extern const char STUN_ERROR_REASON_ROLE_CONFLICT[]; - -// A RFC 5245 ICE STUN message. -class IceMessage : public StunMessage { - protected: - StunAttributeValueType GetAttributeValueType(int type) const override; - StunMessage* CreateNew() const override; -}; - -} // namespace cricket +// TODO(bugs.webrtc.org/11091): Delete this header when downstream is updated. +#include "api/transport/stun.h" #endif // P2P_BASE_STUN_H_ diff --git a/p2p/base/stun_port.cc b/p2p/base/stun_port.cc index 4662b0d17a..e259e8b302 100644 --- a/p2p/base/stun_port.cc +++ b/p2p/base/stun_port.cc @@ -13,10 +13,10 @@ #include #include +#include "api/transport/stun.h" #include "p2p/base/connection.h" #include "p2p/base/p2p_constants.h" #include "p2p/base/port_allocator.h" -#include "p2p/base/stun.h" #include "rtc_base/checks.h" #include "rtc_base/helpers.h" #include "rtc_base/ip_address.h" diff --git a/p2p/base/stun_request.h b/p2p/base/stun_request.h index af2e14e797..b9b7110bec 100644 --- a/p2p/base/stun_request.h +++ b/p2p/base/stun_request.h @@ -17,7 +17,7 @@ #include #include -#include "p2p/base/stun.h" +#include "api/transport/stun.h" #include "rtc_base/message_handler.h" #include "rtc_base/message_queue.h" #include "rtc_base/third_party/sigslot/sigslot.h" diff --git a/p2p/base/stun_server.h b/p2p/base/stun_server.h index 8cfba4d828..60e82485c4 100644 --- a/p2p/base/stun_server.h +++ b/p2p/base/stun_server.h @@ -16,7 +16,7 @@ #include -#include "p2p/base/stun.h" +#include "api/transport/stun.h" #include "rtc_base/async_packet_socket.h" #include "rtc_base/async_udp_socket.h" #include "rtc_base/socket_address.h" diff --git a/p2p/base/test_stun_server.h b/p2p/base/test_stun_server.h index 44e3927ee9..e44e7dbcdd 100644 --- a/p2p/base/test_stun_server.h +++ b/p2p/base/test_stun_server.h @@ -11,7 +11,7 @@ #ifndef P2P_BASE_TEST_STUN_SERVER_H_ #define P2P_BASE_TEST_STUN_SERVER_H_ -#include "p2p/base/stun.h" +#include "api/transport/stun.h" #include "p2p/base/stun_server.h" #include "rtc_base/async_udp_socket.h" #include "rtc_base/socket_address.h" diff --git a/p2p/base/test_turn_server.h b/p2p/base/test_turn_server.h index 3a4067bb86..3a9da85f08 100644 --- a/p2p/base/test_turn_server.h +++ b/p2p/base/test_turn_server.h @@ -14,8 +14,8 @@ #include #include +#include "api/transport/stun.h" #include "p2p/base/basic_packet_socket_factory.h" -#include "p2p/base/stun.h" #include "p2p/base/turn_server.h" #include "rtc_base/async_udp_socket.h" #include "rtc_base/ssl_adapter.h" diff --git a/p2p/base/turn_port.cc b/p2p/base/turn_port.cc index f0795ee5e5..0dc67aa8c1 100644 --- a/p2p/base/turn_port.cc +++ b/p2p/base/turn_port.cc @@ -18,9 +18,9 @@ #include "absl/algorithm/container.h" #include "absl/strings/match.h" #include "absl/types/optional.h" +#include "api/transport/stun.h" #include "p2p/base/connection.h" #include "p2p/base/p2p_constants.h" -#include "p2p/base/stun.h" #include "rtc_base/async_packet_socket.h" #include "rtc_base/byte_order.h" #include "rtc_base/checks.h" diff --git a/p2p/base/turn_server.cc b/p2p/base/turn_server.cc index 386921329d..3a4784ac52 100644 --- a/p2p/base/turn_server.cc +++ b/p2p/base/turn_server.cc @@ -16,8 +16,8 @@ #include "absl/algorithm/container.h" #include "api/packet_socket_factory.h" +#include "api/transport/stun.h" #include "p2p/base/async_stun_tcp_socket.h" -#include "p2p/base/stun.h" #include "rtc_base/bind.h" #include "rtc_base/byte_buffer.h" #include "rtc_base/checks.h" diff --git a/p2p/stunprober/stun_prober.cc b/p2p/stunprober/stun_prober.cc index 49f803f80d..f37f24994a 100644 --- a/p2p/stunprober/stun_prober.cc +++ b/p2p/stunprober/stun_prober.cc @@ -17,7 +17,7 @@ #include #include "api/packet_socket_factory.h" -#include "p2p/base/stun.h" +#include "api/transport/stun.h" #include "rtc_base/async_packet_socket.h" #include "rtc_base/async_resolver_interface.h" #include "rtc_base/bind.h" diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn index b1723e939b..a063d6a62c 100644 --- a/test/fuzzers/BUILD.gn +++ b/test/fuzzers/BUILD.gn @@ -417,8 +417,8 @@ webrtc_fuzzer_test("stun_parser_fuzzer") { "stun_parser_fuzzer.cc", ] deps = [ + "../../api/transport:stun_types", "../../p2p:rtc_p2p", - "../../p2p:stun_types", ] seed_corpus = "corpora/stun-corpus" dict = "corpora/stun.tokens" @@ -429,8 +429,8 @@ webrtc_fuzzer_test("stun_validator_fuzzer") { "stun_validator_fuzzer.cc", ] deps = [ + "../../api/transport:stun_types", "../../p2p:rtc_p2p", - "../../p2p:stun_types", ] seed_corpus = "corpora/stun-corpus" dict = "corpora/stun.tokens" diff --git a/test/fuzzers/stun_parser_fuzzer.cc b/test/fuzzers/stun_parser_fuzzer.cc index 02e42bcbc8..720a699662 100644 --- a/test/fuzzers/stun_parser_fuzzer.cc +++ b/test/fuzzers/stun_parser_fuzzer.cc @@ -11,7 +11,7 @@ #include #include -#include "p2p/base/stun.h" +#include "api/transport/stun.h" namespace webrtc { void FuzzOneInput(const uint8_t* data, size_t size) { diff --git a/test/fuzzers/stun_validator_fuzzer.cc b/test/fuzzers/stun_validator_fuzzer.cc index 9873ff40fb..44252fafbc 100644 --- a/test/fuzzers/stun_validator_fuzzer.cc +++ b/test/fuzzers/stun_validator_fuzzer.cc @@ -11,7 +11,7 @@ #include #include -#include "p2p/base/stun.h" +#include "api/transport/stun.h" namespace webrtc { void FuzzOneInput(const uint8_t* data, size_t size) {