Log how often DTLS negotiation failed because of incompatible ciphersuites.

Log the DTLS handshake error code in OpenSSLStreamAdapter.
Forward the error code to WebRTCSession with the Signals.
This part is only for the WebRTC native code.
To make it work, need another CL for Chromium.

BUG=webrtc:5959

Review-Url: https://codereview.webrtc.org/2167363002
Cr-Commit-Position: refs/heads/master@{#13940}
This commit is contained in:
zhihuang 2016-08-26 11:25:05 -07:00 committed by Commit bot
parent 3026ee81d3
commit d82eee0675
11 changed files with 54 additions and 3 deletions

View File

@ -32,6 +32,7 @@ enum PeerConnectionEnumCounterType {
kEnumCounterVideoSslCipher,
kEnumCounterDataSrtpCipher,
kEnumCounterDataSslCipher,
kEnumCounterDtlsHandshakeError,
kPeerConnectionEnumCounterMax
};

View File

@ -493,6 +493,8 @@ WebRtcSession::WebRtcSession(
this, &WebRtcSession::OnTransportControllerCandidatesGathered);
transport_controller_->SignalCandidatesRemoved.connect(
this, &WebRtcSession::OnTransportControllerCandidatesRemoved);
transport_controller_->SignalDtlsHandshakeError.connect(
this, &WebRtcSession::OnDtlsHandshakeError);
}
WebRtcSession::~WebRtcSession() {
@ -2073,4 +2075,12 @@ const std::string WebRtcSession::GetTransportName(
}
return channel->transport_name();
}
void WebRtcSession::OnDtlsHandshakeError(rtc::SSLHandshakeError error) {
if (metrics_observer_) {
metrics_observer_->IncrementEnumCounter(
webrtc::kEnumCounterDtlsHandshakeError, static_cast<int>(error),
static_cast<int>(rtc::SSLHandshakeError::MAX_VALUE));
}
}
} // namespace webrtc

View File

@ -461,6 +461,8 @@ class WebRtcSession :
const std::string GetTransportName(const std::string& content_name);
void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
rtc::Thread* const network_thread_;
rtc::Thread* const worker_thread_;
rtc::Thread* const signaling_thread_;

View File

@ -839,6 +839,12 @@ int OpenSSLStreamAdapter::ContinueSSL() {
case SSL_ERROR_ZERO_RETURN:
default:
LOG(LS_VERBOSE) << " -- error " << code;
SSLHandshakeError ssl_handshake_err = SSLHandshakeError::UNKNOWN;
int err_code = ERR_peek_last_error();
if (err_code != 0 && ERR_GET_REASON(err_code) == SSL_R_NO_SHARED_CIPHER) {
ssl_handshake_err = SSLHandshakeError::INCOMPATIBLE_CIPHERSUITE;
}
SignalSSLHandshakeError(ssl_handshake_err);
return (ssl_error != 0) ? ssl_error : -1;
}

View File

@ -108,6 +108,13 @@ SSLStreamAdapter* SSLStreamAdapter::Create(StreamInterface* stream) {
#endif // SSL_USE_OPENSSL
}
SSLStreamAdapter::SSLStreamAdapter(StreamInterface* stream)
: StreamAdapterInterface(stream),
ignore_bad_cert_(false),
client_auth_enabled_(true) {}
SSLStreamAdapter::~SSLStreamAdapter() {}
bool SSLStreamAdapter::GetSslCipherSuite(int* cipher_suite) {
return false;
}

View File

@ -110,6 +110,9 @@ enum SSLProtocolVersion {
// Errors for Read -- in the high range so no conflict with OpenSSL.
enum { SSE_MSG_TRUNC = 0xff0001 };
// Used to send back UMA histogram value. Logged when Dtls handshake fails.
enum class SSLHandshakeError { UNKNOWN, INCOMPATIBLE_CIPHERSUITE, MAX_VALUE };
class SSLStreamAdapter : public StreamAdapterInterface {
public:
// Instantiate an SSLStreamAdapter wrapping the given stream,
@ -117,9 +120,8 @@ class SSLStreamAdapter : public StreamAdapterInterface {
// Caller is responsible for freeing the returned object.
static SSLStreamAdapter* Create(StreamInterface* stream);
explicit SSLStreamAdapter(StreamInterface* stream)
: StreamAdapterInterface(stream), ignore_bad_cert_(false),
client_auth_enabled_(true) { }
explicit SSLStreamAdapter(StreamInterface* stream);
~SSLStreamAdapter() override;
void set_ignore_bad_cert(bool ignore) { ignore_bad_cert_ = ignore; }
bool ignore_bad_cert() const { return ignore_bad_cert_; }
@ -225,6 +227,8 @@ class SSLStreamAdapter : public StreamAdapterInterface {
// depending on specific SSL implementation.
static std::string SslCipherSuiteToName(int cipher_suite);
sigslot::signal1<SSLHandshakeError> SignalSSLHandshakeError;
private:
// If true, the server certificate need not match the configured
// server_name, and in fact missing certificate authority and other

View File

@ -280,6 +280,8 @@ bool DtlsTransportChannelWrapper::SetupDtls() {
dtls_->SetMaxProtocolVersion(ssl_max_version_);
dtls_->SetServerRole(ssl_role_);
dtls_->SignalEvent.connect(this, &DtlsTransportChannelWrapper::OnDtlsEvent);
dtls_->SignalSSLHandshakeError.connect(
this, &DtlsTransportChannelWrapper::OnDtlsHandshakeError);
if (!dtls_->SetPeerCertificateDigest(
remote_fingerprint_algorithm_,
reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
@ -676,4 +678,9 @@ void DtlsTransportChannelWrapper::OnChannelStateChanged(
SignalStateChanged(this);
}
void DtlsTransportChannelWrapper::OnDtlsHandshakeError(
rtc::SSLHandshakeError error) {
SignalDtlsHandshakeError(error);
}
} // namespace cricket

View File

@ -220,6 +220,7 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl {
int last_sent_packet_id,
bool ready_to_send);
void OnChannelStateChanged(TransportChannelImpl* channel);
void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
rtc::Thread* worker_thread_; // Everything should occur on this thread.
// Underlying channel, not owned by this class.

View File

@ -100,6 +100,9 @@ class TransportChannelImpl : public TransportChannel {
// Emitted whenever the transport channel state changed.
sigslot::signal1<TransportChannelImpl*> SignalStateChanged;
// Emitted whenever the Dtls handshake failed on some transport channel.
sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
private:
RTC_DISALLOW_COPY_AND_ASSIGN(TransportChannelImpl);
};

View File

@ -191,6 +191,8 @@ TransportChannel* TransportController::CreateTransportChannel_n(
this, &TransportController::OnChannelRoleConflict_n);
channel->SignalStateChanged.connect(
this, &TransportController::OnChannelStateChanged_n);
channel->SignalDtlsHandshakeError.connect(
this, &TransportController::OnDtlsHandshakeError);
channels_.insert(channels_.end(), RefCountedChannel(channel))->AddRef();
// Adding a channel could cause aggregate state to change.
UpdateAggregateStates_n();
@ -685,4 +687,8 @@ void TransportController::UpdateAggregateStates_n() {
}
}
void TransportController::OnDtlsHandshakeError(rtc::SSLHandshakeError error) {
SignalDtlsHandshakeError(error);
}
} // namespace cricket

View File

@ -119,6 +119,8 @@ class TransportController : public sigslot::has_slots<>,
// for unit test
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate_for_testing();
sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
protected:
// Protected and virtual so we can override it in unit tests.
virtual Transport* CreateTransport_n(const std::string& transport_name);
@ -202,6 +204,8 @@ class TransportController : public sigslot::has_slots<>,
void UpdateAggregateStates_n();
void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
rtc::Thread* const signaling_thread_ = nullptr;
rtc::Thread* const network_thread_ = nullptr;
typedef std::map<std::string, Transport*> TransportMap;