Index: webrtc/p2p/base/dtlstransport.h |
diff --git a/webrtc/p2p/base/dtlstransport.h b/webrtc/p2p/base/dtlstransport.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e59472d7f9df4bf5ea9c0d9a7db817a11ff9ca11 |
--- /dev/null |
+++ b/webrtc/p2p/base/dtlstransport.h |
@@ -0,0 +1,163 @@ |
+/* |
+ * Copyright 2012 The WebRTC Project Authors. All rights reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#ifndef WEBRTC_P2P_BASE_DTLSTRANSPORT_H_ |
+#define WEBRTC_P2P_BASE_DTLSTRANSPORT_H_ |
+ |
+#include <memory> |
+ |
+#include "webrtc/p2p/base/dtlstransportchannel.h" |
+#include "webrtc/p2p/base/transport.h" |
+ |
+namespace rtc { |
+class SSLIdentity; |
+} |
+ |
+namespace cricket { |
+ |
+class PortAllocator; |
+ |
+// Base should be a descendant of cricket::Transport and have a constructor |
+// that takes a transport name and PortAllocator. |
+// |
+// Everything in this class should be called on the network thread. |
+template<class Base> |
+class DtlsTransport : public Base { |
+ public: |
+ DtlsTransport(const std::string& name, |
+ PortAllocator* allocator, |
+ const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) |
+ : Base(name, allocator), |
+ certificate_(certificate), |
+ secure_role_(rtc::SSL_CLIENT), |
+ ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_12) {} |
+ |
+ ~DtlsTransport() { |
+ Base::DestroyAllChannels(); |
+ } |
+ |
+ void SetLocalCertificate( |
+ const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override { |
+ certificate_ = certificate; |
+ } |
+ bool GetLocalCertificate( |
+ rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override { |
+ if (!certificate_) |
+ return false; |
+ |
+ *certificate = certificate_; |
+ return true; |
+ } |
+ |
+ bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override { |
+ ssl_max_version_ = version; |
+ return true; |
+ } |
+ |
+ bool ApplyLocalTransportDescription(TransportChannelImpl* channel, |
+ std::string* error_desc) override { |
+ rtc::SSLFingerprint* local_fp = |
+ Base::local_description()->identity_fingerprint.get(); |
+ |
+ if (!local_fp) { |
+ certificate_ = nullptr; |
+ } else if (!Base::VerifyCertificateFingerprint(certificate_.get(), local_fp, |
+ error_desc)) { |
+ return false; |
+ } |
+ |
+ if (!channel->SetLocalCertificate(certificate_)) { |
+ return BadTransportDescription("Failed to set local identity.", |
+ error_desc); |
+ } |
+ |
+ // Apply the description in the base class. |
+ return Base::ApplyLocalTransportDescription(channel, error_desc); |
+ } |
+ |
+ bool NegotiateTransportDescription(ContentAction local_role, |
+ std::string* error_desc) override { |
+ if (!Base::local_description() || !Base::remote_description()) { |
+ const std::string msg = "Local and Remote description must be set before " |
+ "transport descriptions are negotiated"; |
+ return BadTransportDescription(msg, error_desc); |
+ } |
+ rtc::SSLFingerprint* local_fp = |
+ Base::local_description()->identity_fingerprint.get(); |
+ rtc::SSLFingerprint* remote_fp = |
+ Base::remote_description()->identity_fingerprint.get(); |
+ if (remote_fp && local_fp) { |
+ remote_fingerprint_.reset(new rtc::SSLFingerprint(*remote_fp)); |
+ if (!Base::NegotiateRole(local_role, &secure_role_, error_desc)) { |
+ return false; |
+ } |
+ } else if (local_fp && (local_role == CA_ANSWER)) { |
+ return BadTransportDescription( |
+ "Local fingerprint supplied when caller didn't offer DTLS.", |
+ error_desc); |
+ } else { |
+ // We are not doing DTLS |
+ remote_fingerprint_.reset(new rtc::SSLFingerprint("", nullptr, 0)); |
+ } |
+ // Now run the negotiation for the base class. |
+ return Base::NegotiateTransportDescription(local_role, error_desc); |
+ } |
+ |
+ DtlsTransportChannelWrapper* CreateTransportChannel(int component) override { |
+ DtlsTransportChannelWrapper* channel = new DtlsTransportChannelWrapper( |
+ Base::CreateTransportChannel(component)); |
+ channel->SetSslMaxProtocolVersion(ssl_max_version_); |
+ return channel; |
+ } |
+ |
+ void DestroyTransportChannel(TransportChannelImpl* channel) override { |
+ // Kind of ugly, but this lets us do the exact inverse of the create. |
+ DtlsTransportChannelWrapper* dtls_channel = |
+ static_cast<DtlsTransportChannelWrapper*>(channel); |
+ TransportChannelImpl* base_channel = dtls_channel->channel(); |
+ delete dtls_channel; |
+ Base::DestroyTransportChannel(base_channel); |
+ } |
+ |
+ bool GetSslRole(rtc::SSLRole* ssl_role) const override { |
+ ASSERT(ssl_role != NULL); |
+ *ssl_role = secure_role_; |
+ return true; |
+ } |
+ |
+ private: |
+ bool ApplyNegotiatedTransportDescription(TransportChannelImpl* channel, |
+ std::string* error_desc) override { |
+ // Set ssl role. Role must be set before fingerprint is applied, which |
+ // initiates DTLS setup. |
+ if (!channel->SetSslRole(secure_role_)) { |
+ return BadTransportDescription("Failed to set ssl role for the channel.", |
+ error_desc); |
+ } |
+ // Apply remote fingerprint. |
+ if (!channel->SetRemoteFingerprint(remote_fingerprint_->algorithm, |
+ reinterpret_cast<const uint8_t*>( |
+ remote_fingerprint_->digest.data()), |
+ remote_fingerprint_->digest.size())) { |
+ return BadTransportDescription("Failed to apply remote fingerprint.", |
+ error_desc); |
+ } |
+ return Base::ApplyNegotiatedTransportDescription(channel, error_desc); |
+ } |
+ |
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate_; |
+ rtc::SSLRole secure_role_; |
+ rtc::SSLProtocolVersion ssl_max_version_; |
+ std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint_; |
+}; |
+ |
+} // namespace cricket |
+ |
+#endif // WEBRTC_P2P_BASE_DTLSTRANSPORT_H_ |