aboutsummaryrefslogtreecommitdiff
path: root/webrtc/p2p/base/dtlstransportchannel.cc
diff options
context:
space:
mode:
authordeadbeef <deadbeef@webrtc.org>2015-10-26 17:23:29 -0700
committerCommit bot <commit-bot@chromium.org>2015-10-27 00:23:34 +0000
commit2b5586774ca71b19cbebc38c96d1476ccb3dfdb4 (patch)
tree637c63b4a0ac517a38bb3c2d10a8cc7f6b7818b4 /webrtc/p2p/base/dtlstransportchannel.cc
parentb0bb77fd615c5ce413b16f6157b2ffc25898631f (diff)
downloadwebrtc-2b5586774ca71b19cbebc38c96d1476ccb3dfdb4.tar.gz
Exposing DTLS transport state from TransportChannel.
This is necessary in order to support the RTCPeerConnectionState enum in the future, as well as a correct RTCIceConnectionState (which isn't a combination ICE and DTLS state). Review URL: https://codereview.webrtc.org/1414363002 Cr-Commit-Position: refs/heads/master@{#10419}
Diffstat (limited to 'webrtc/p2p/base/dtlstransportchannel.cc')
-rw-r--r--webrtc/p2p/base/dtlstransportchannel.cc212
1 files changed, 100 insertions, 112 deletions
diff --git a/webrtc/p2p/base/dtlstransportchannel.cc b/webrtc/p2p/base/dtlstransportchannel.cc
index 148a19108d..0c063e0323 100644
--- a/webrtc/p2p/base/dtlstransportchannel.cc
+++ b/webrtc/p2p/base/dtlstransportchannel.cc
@@ -94,7 +94,6 @@ DtlsTransportChannelWrapper::DtlsTransportChannelWrapper(
worker_thread_(rtc::Thread::Current()),
channel_(channel),
downward_(NULL),
- dtls_state_(STATE_NONE),
ssl_role_(rtc::SSL_CLIENT),
ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_10) {
channel_->SignalWritableState.connect(this,
@@ -124,15 +123,13 @@ DtlsTransportChannelWrapper::~DtlsTransportChannelWrapper() {
void DtlsTransportChannelWrapper::Connect() {
// We should only get a single call to Connect.
- ASSERT(dtls_state_ == STATE_NONE ||
- dtls_state_ == STATE_OFFERED ||
- dtls_state_ == STATE_ACCEPTED);
+ ASSERT(dtls_state() == DTLS_TRANSPORT_NEW);
channel_->Connect();
}
bool DtlsTransportChannelWrapper::SetLocalCertificate(
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
- if (dtls_state_ != STATE_NONE) {
+ if (dtls_active_) {
if (certificate == local_certificate_) {
// This may happen during renegotiation.
LOG_J(LS_INFO, this) << "Ignoring identical DTLS identity";
@@ -145,7 +142,7 @@ bool DtlsTransportChannelWrapper::SetLocalCertificate(
if (certificate) {
local_certificate_ = certificate;
- dtls_state_ = STATE_OFFERED;
+ dtls_active_ = true;
} else {
LOG_J(LS_INFO, this) << "NULL DTLS identity supplied. Not doing DTLS";
}
@@ -160,7 +157,7 @@ DtlsTransportChannelWrapper::GetLocalCertificate() const {
bool DtlsTransportChannelWrapper::SetSslMaxProtocolVersion(
rtc::SSLProtocolVersion version) {
- if (dtls_state_ != STATE_NONE) {
+ if (dtls_active_) {
LOG(LS_ERROR) << "Not changing max. protocol version "
<< "while DTLS is negotiating";
return false;
@@ -171,7 +168,7 @@ bool DtlsTransportChannelWrapper::SetSslMaxProtocolVersion(
}
bool DtlsTransportChannelWrapper::SetSslRole(rtc::SSLRole role) {
- if (dtls_state_ == STATE_OPEN) {
+ if (dtls_state() == DTLS_TRANSPORT_CONNECTED) {
if (ssl_role_ != role) {
LOG(LS_ERROR) << "SSL Role can't be reversed after the session is setup.";
return false;
@@ -189,7 +186,7 @@ bool DtlsTransportChannelWrapper::GetSslRole(rtc::SSLRole* role) const {
}
bool DtlsTransportChannelWrapper::GetSslCipherSuite(int* cipher) {
- if (dtls_state_ != STATE_OPEN) {
+ if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
return false;
}
@@ -202,8 +199,7 @@ bool DtlsTransportChannelWrapper::SetRemoteFingerprint(
size_t digest_len) {
rtc::Buffer remote_fingerprint_value(digest, digest_len);
- if (dtls_state_ != STATE_NONE &&
- remote_fingerprint_value_ == remote_fingerprint_value &&
+ if (dtls_active_ && remote_fingerprint_value_ == remote_fingerprint_value &&
!digest_alg.empty()) {
// This may happen during renegotiation.
LOG_J(LS_INFO, this) << "Ignoring identical remote DTLS fingerprint";
@@ -212,15 +208,14 @@ bool DtlsTransportChannelWrapper::SetRemoteFingerprint(
// Allow SetRemoteFingerprint with a NULL digest even if SetLocalCertificate
// hasn't been called.
- if (dtls_state_ > STATE_OFFERED ||
- (dtls_state_ == STATE_NONE && !digest_alg.empty())) {
+ if (dtls_ || (!dtls_active_ && !digest_alg.empty())) {
LOG_J(LS_ERROR, this) << "Can't set DTLS remote settings in this state.";
return false;
}
if (digest_alg.empty()) {
LOG_J(LS_INFO, this) << "Other side didn't support DTLS.";
- dtls_state_ = STATE_NONE;
+ dtls_active_ = false;
return true;
}
@@ -229,18 +224,18 @@ bool DtlsTransportChannelWrapper::SetRemoteFingerprint(
remote_fingerprint_algorithm_ = digest_alg;
if (!SetupDtls()) {
- dtls_state_ = STATE_CLOSED;
+ set_dtls_state(DTLS_TRANSPORT_FAILED);
return false;
}
- dtls_state_ = STATE_ACCEPTED;
return true;
}
bool DtlsTransportChannelWrapper::GetRemoteSSLCertificate(
rtc::SSLCertificate** cert) const {
- if (!dtls_)
+ if (!dtls_) {
return false;
+ }
return dtls_->GetPeerCertificate(cert);
}
@@ -277,7 +272,7 @@ bool DtlsTransportChannelWrapper::SetupDtls() {
return false;
}
} else {
- LOG_J(LS_INFO, this) << "Not using DTLS.";
+ LOG_J(LS_INFO, this) << "Not using DTLS-SRTP.";
}
LOG_J(LS_INFO, this) << "DTLS setup complete.";
@@ -286,15 +281,16 @@ bool DtlsTransportChannelWrapper::SetupDtls() {
bool DtlsTransportChannelWrapper::SetSrtpCiphers(
const std::vector<std::string>& ciphers) {
- if (srtp_ciphers_ == ciphers)
+ if (srtp_ciphers_ == ciphers) {
return true;
+ }
- if (dtls_state_ == STATE_STARTED) {
+ if (dtls_state() == DTLS_TRANSPORT_CONNECTING) {
LOG(LS_WARNING) << "Ignoring new SRTP ciphers while DTLS is negotiating";
return true;
}
- if (dtls_state_ == STATE_OPEN) {
+ if (dtls_state() == DTLS_TRANSPORT_CONNECTED) {
// We don't support DTLS renegotiation currently. If new set of srtp ciphers
// are different than what's being used currently, we will not use it.
// So for now, let's be happy (or sad) with a warning message.
@@ -320,10 +316,7 @@ bool DtlsTransportChannelWrapper::SetSrtpCiphers(
return true;
}
- if (dtls_state_ != STATE_NONE &&
- dtls_state_ != STATE_OFFERED &&
- dtls_state_ != STATE_ACCEPTED) {
- ASSERT(false);
+ if (!VERIFY(dtls_state() == DTLS_TRANSPORT_NEW)) {
return false;
}
@@ -332,7 +325,7 @@ bool DtlsTransportChannelWrapper::SetSrtpCiphers(
}
bool DtlsTransportChannelWrapper::GetSrtpCryptoSuite(std::string* cipher) {
- if (dtls_state_ != STATE_OPEN) {
+ if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
return false;
}
@@ -344,45 +337,40 @@ bool DtlsTransportChannelWrapper::GetSrtpCryptoSuite(std::string* cipher) {
int DtlsTransportChannelWrapper::SendPacket(
const char* data, size_t size,
const rtc::PacketOptions& options, int flags) {
- int result = -1;
-
- switch (dtls_state_) {
- case STATE_OFFERED:
- // We don't know if we are doing DTLS yet, so we can't send a packet.
- // TODO(ekr@rtfm.com): assert here?
- result = -1;
- break;
-
- case STATE_STARTED:
- case STATE_ACCEPTED:
- // Can't send data until the connection is active
- result = -1;
- break;
+ if (!dtls_active_) {
+ // Not doing DTLS.
+ return channel_->SendPacket(data, size, options);
+ }
- case STATE_OPEN:
+ switch (dtls_state()) {
+ case DTLS_TRANSPORT_NEW:
+ // Can't send data until the connection is active.
+ // TODO(ekr@rtfm.com): assert here if dtls_ is NULL?
+ return -1;
+ case DTLS_TRANSPORT_CONNECTING:
+ // Can't send data until the connection is active.
+ return -1;
+ case DTLS_TRANSPORT_CONNECTED:
if (flags & PF_SRTP_BYPASS) {
ASSERT(!srtp_ciphers_.empty());
if (!IsRtpPacket(data, size)) {
- result = -1;
- break;
+ return -1;
}
- result = channel_->SendPacket(data, size, options);
+ return channel_->SendPacket(data, size, options);
} else {
- result = (dtls_->WriteAll(data, size, NULL, NULL) ==
- rtc::SR_SUCCESS) ? static_cast<int>(size) : -1;
+ return (dtls_->WriteAll(data, size, NULL, NULL) == rtc::SR_SUCCESS)
+ ? static_cast<int>(size)
+ : -1;
}
- break;
- // Not doing DTLS.
- case STATE_NONE:
- result = channel_->SendPacket(data, size, options);
- break;
-
- case STATE_CLOSED: // Can't send anything when we're closed.
+ case DTLS_TRANSPORT_FAILED:
+ case DTLS_TRANSPORT_CLOSED:
+ // Can't send anything when we're closed.
+ return -1;
+ default:
+ ASSERT(false);
return -1;
}
-
- return result;
}
// The state transition logic here is as follows:
@@ -402,37 +390,35 @@ void DtlsTransportChannelWrapper::OnWritableState(TransportChannel* channel) {
<< "DTLSTransportChannelWrapper: channel writable state changed to "
<< channel_->writable();
- switch (dtls_state_) {
- case STATE_NONE:
- case STATE_OPEN:
- set_writable(channel_->writable());
- // Note: SignalWritableState fired by set_writable.
- break;
+ if (!dtls_active_) {
+ // Not doing DTLS.
+ // Note: SignalWritableState fired by set_writable.
+ set_writable(channel_->writable());
+ return;
+ }
- case STATE_OFFERED:
- // Do nothing
+ switch (dtls_state()) {
+ case DTLS_TRANSPORT_NEW:
+ // This should never fail:
+ // Because we are operating in a nonblocking mode and all
+ // incoming packets come in via OnReadPacket(), which rejects
+ // packets in this state, the incoming queue must be empty. We
+ // ignore write errors, thus any errors must be because of
+ // configuration and therefore are our fault.
+ // Note that in non-debug configurations, failure in
+ // MaybeStartDtls() changes the state to DTLS_TRANSPORT_FAILED.
+ VERIFY(MaybeStartDtls());
break;
-
- case STATE_ACCEPTED:
- if (!MaybeStartDtls()) {
- // This should never happen:
- // Because we are operating in a nonblocking mode and all
- // incoming packets come in via OnReadPacket(), which rejects
- // packets in this state, the incoming queue must be empty. We
- // ignore write errors, thus any errors must be because of
- // configuration and therefore are our fault.
- // Note that in non-debug configurations, failure in
- // MaybeStartDtls() changes the state to STATE_CLOSED.
- ASSERT(false);
- }
+ case DTLS_TRANSPORT_CONNECTED:
+ // Note: SignalWritableState fired by set_writable.
+ set_writable(channel_->writable());
break;
-
- case STATE_STARTED:
- // Do nothing
+ case DTLS_TRANSPORT_CONNECTING:
+ // Do nothing.
break;
-
- case STATE_CLOSED:
- // Should not happen. Do nothing
+ case DTLS_TRANSPORT_FAILED:
+ case DTLS_TRANSPORT_CLOSED:
+ // Should not happen. Do nothing.
break;
}
}
@@ -443,7 +429,7 @@ void DtlsTransportChannelWrapper::OnReceivingState(TransportChannel* channel) {
LOG_J(LS_VERBOSE, this)
<< "DTLSTransportChannelWrapper: channel receiving state changed to "
<< channel_->receiving();
- if (dtls_state_ == STATE_NONE || dtls_state_ == STATE_OPEN) {
+ if (!dtls_active_ || dtls_state() == DTLS_TRANSPORT_CONNECTED) {
// Note: SignalReceivingState fired by set_receiving.
set_receiving(channel_->receiving());
}
@@ -456,28 +442,29 @@ void DtlsTransportChannelWrapper::OnReadPacket(
ASSERT(channel == channel_);
ASSERT(flags == 0);
- switch (dtls_state_) {
- case STATE_NONE:
- // We are not doing DTLS
- SignalReadPacket(this, data, size, packet_time, 0);
- break;
-
- case STATE_OFFERED:
- // Currently drop the packet, but we might in future
- // decide to take this as evidence that the other
- // side is ready to do DTLS and start the handshake
- // on our end
- LOG_J(LS_WARNING, this) << "Received packet before we know if we are "
- << "doing DTLS or not; dropping.";
- break;
+ if (!dtls_active_) {
+ // Not doing DTLS.
+ SignalReadPacket(this, data, size, packet_time, 0);
+ return;
+ }
- case STATE_ACCEPTED:
- // Drop packets received before DTLS has actually started
- LOG_J(LS_INFO, this) << "Dropping packet received before DTLS started.";
+ switch (dtls_state()) {
+ case DTLS_TRANSPORT_NEW:
+ if (dtls_) {
+ // Drop packets received before DTLS has actually started.
+ LOG_J(LS_INFO, this) << "Dropping packet received before DTLS started.";
+ } else {
+ // Currently drop the packet, but we might in future
+ // decide to take this as evidence that the other
+ // side is ready to do DTLS and start the handshake
+ // on our end.
+ LOG_J(LS_WARNING, this) << "Received packet before we know if we are "
+ << "doing DTLS or not; dropping.";
+ }
break;
- case STATE_STARTED:
- case STATE_OPEN:
+ case DTLS_TRANSPORT_CONNECTING:
+ case DTLS_TRANSPORT_CONNECTED:
// We should only get DTLS or SRTP packets; STUN's already been demuxed.
// Is this potentially a DTLS packet?
if (IsDtlsPacket(data, size)) {
@@ -487,7 +474,7 @@ void DtlsTransportChannelWrapper::OnReadPacket(
}
} else {
// Not a DTLS packet; our handshake should be complete by now.
- if (dtls_state_ != STATE_OPEN) {
+ if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
LOG_J(LS_ERROR, this) << "Received non-DTLS packet before DTLS "
<< "complete.";
return;
@@ -506,8 +493,9 @@ void DtlsTransportChannelWrapper::OnReadPacket(
SignalReadPacket(this, data, size, packet_time, PF_SRTP_BYPASS);
}
break;
- case STATE_CLOSED:
- // This shouldn't be happening. Drop the packet
+ case DTLS_TRANSPORT_FAILED:
+ case DTLS_TRANSPORT_CLOSED:
+ // This shouldn't be happening. Drop the packet.
break;
}
}
@@ -536,7 +524,7 @@ void DtlsTransportChannelWrapper::OnDtlsEvent(rtc::StreamInterface* dtls,
if (dtls_->GetState() == rtc::SS_OPEN) {
// The check for OPEN shouldn't be necessary but let's make
// sure we don't accidentally frob the state if it's closed.
- dtls_state_ = STATE_OPEN;
+ set_dtls_state(DTLS_TRANSPORT_CONNECTED);
set_writable(true);
}
}
@@ -549,27 +537,27 @@ void DtlsTransportChannelWrapper::OnDtlsEvent(rtc::StreamInterface* dtls,
}
if (sig & rtc::SE_CLOSE) {
ASSERT(sig == rtc::SE_CLOSE); // SE_CLOSE should be by itself.
+ set_writable(false);
if (!err) {
LOG_J(LS_INFO, this) << "DTLS channel closed";
+ set_dtls_state(DTLS_TRANSPORT_CLOSED);
} else {
LOG_J(LS_INFO, this) << "DTLS channel error, code=" << err;
+ set_dtls_state(DTLS_TRANSPORT_FAILED);
}
- set_writable(false);
- dtls_state_ = STATE_CLOSED;
}
}
bool DtlsTransportChannelWrapper::MaybeStartDtls() {
- if (channel_->writable()) {
+ if (dtls_ && channel_->writable()) {
if (dtls_->StartSSLWithPeer()) {
LOG_J(LS_ERROR, this) << "Couldn't start DTLS handshake";
- dtls_state_ = STATE_CLOSED;
+ set_dtls_state(DTLS_TRANSPORT_FAILED);
return false;
}
LOG_J(LS_INFO, this)
<< "DtlsTransportChannelWrapper: Started DTLS handshake";
-
- dtls_state_ = STATE_STARTED;
+ set_dtls_state(DTLS_TRANSPORT_CONNECTING);
}
return true;
}