1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/cast_channel/logger.h"
6 
7 #include <stdint.h>
8 
9 #include <string>
10 #include <utility>
11 
12 #include "base/strings/string_util.h"
13 #include "components/cast_channel/cast_auth_util.h"
14 #include "components/cast_channel/cast_socket.h"
15 #include "net/base/net_errors.h"
16 
17 namespace cast_channel {
18 
19 using net::IPEndPoint;
20 
21 namespace {
22 
AuthErrorToChallengeReplyError(AuthResult::ErrorType error_type)23 ChallengeReplyError AuthErrorToChallengeReplyError(
24     AuthResult::ErrorType error_type) {
25   switch (error_type) {
26     case AuthResult::ERROR_NONE:
27       return ChallengeReplyError::NONE;
28     case AuthResult::ERROR_PEER_CERT_EMPTY:
29       return ChallengeReplyError::PEER_CERT_EMPTY;
30     case AuthResult::ERROR_WRONG_PAYLOAD_TYPE:
31       return ChallengeReplyError::WRONG_PAYLOAD_TYPE;
32     case AuthResult::ERROR_NO_PAYLOAD:
33       return ChallengeReplyError::NO_PAYLOAD;
34     case AuthResult::ERROR_PAYLOAD_PARSING_FAILED:
35       return ChallengeReplyError::PAYLOAD_PARSING_FAILED;
36     case AuthResult::ERROR_MESSAGE_ERROR:
37       return ChallengeReplyError::MESSAGE_ERROR;
38     case AuthResult::ERROR_NO_RESPONSE:
39       return ChallengeReplyError::NO_RESPONSE;
40     case AuthResult::ERROR_FINGERPRINT_NOT_FOUND:
41       return ChallengeReplyError::FINGERPRINT_NOT_FOUND;
42     case AuthResult::ERROR_CERT_PARSING_FAILED:
43       return ChallengeReplyError::CERT_PARSING_FAILED;
44     case AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA:
45       return ChallengeReplyError::CERT_NOT_SIGNED_BY_TRUSTED_CA;
46     case AuthResult::ERROR_CANNOT_EXTRACT_PUBLIC_KEY:
47       return ChallengeReplyError::CANNOT_EXTRACT_PUBLIC_KEY;
48     case AuthResult::ERROR_SIGNED_BLOBS_MISMATCH:
49       return ChallengeReplyError::SIGNED_BLOBS_MISMATCH;
50     case AuthResult::ERROR_TLS_CERT_VALIDITY_PERIOD_TOO_LONG:
51       return ChallengeReplyError::TLS_CERT_VALIDITY_PERIOD_TOO_LONG;
52     case AuthResult::ERROR_TLS_CERT_VALID_START_DATE_IN_FUTURE:
53       return ChallengeReplyError::TLS_CERT_VALID_START_DATE_IN_FUTURE;
54     case AuthResult::ERROR_TLS_CERT_EXPIRED:
55       return ChallengeReplyError::TLS_CERT_EXPIRED;
56     case AuthResult::ERROR_CRL_INVALID:
57       return ChallengeReplyError::CRL_INVALID;
58     case AuthResult::ERROR_CERT_REVOKED:
59       return ChallengeReplyError::CERT_REVOKED;
60     case AuthResult::ERROR_SENDER_NONCE_MISMATCH:
61       return ChallengeReplyError::SENDER_NONCE_MISMATCH;
62     case AuthResult::ERROR_SIGNATURE_EMPTY:
63       return ChallengeReplyError::SIGNATURE_EMPTY;
64     case AuthResult::ERROR_DIGEST_UNSUPPORTED:
65       return ChallengeReplyError::DIGEST_UNSUPPORTED;
66     default:
67       NOTREACHED();
68       return ChallengeReplyError::NONE;
69   }
70 }
71 
72 }  // namespace
73 
LastError()74 LastError::LastError()
75     : channel_event(ChannelEvent::UNKNOWN),
76       challenge_reply_error(ChallengeReplyError::NONE),
77       net_return_value(net::OK) {}
78 
~LastError()79 LastError::~LastError() {}
80 
Logger()81 Logger::Logger() {
82   // Logger may not be necessarily be created on the IO thread, but logging
83   // happens exclusively there.
84   DETACH_FROM_THREAD(thread_checker_);
85 }
86 
~Logger()87 Logger::~Logger() {}
88 
LogSocketEventWithRv(int channel_id,ChannelEvent channel_event,int rv)89 void Logger::LogSocketEventWithRv(int channel_id,
90                                   ChannelEvent channel_event,
91                                   int rv) {
92   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
93   MaybeSetLastError(channel_id, channel_event, rv, ChallengeReplyError::NONE);
94 }
95 
LogSocketChallengeReplyEvent(int channel_id,const AuthResult & auth_result)96 void Logger::LogSocketChallengeReplyEvent(int channel_id,
97                                           const AuthResult& auth_result) {
98   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
99   MaybeSetLastError(channel_id, ChannelEvent::AUTH_CHALLENGE_REPLY, net::OK,
100                     AuthErrorToChallengeReplyError(auth_result.error_type));
101 }
102 
GetLastError(int channel_id) const103 LastError Logger::GetLastError(int channel_id) const {
104   const auto it = last_errors_.find(channel_id);
105   return it != last_errors_.end() ? it->second : LastError();
106 }
107 
ClearLastError(int channel_id)108 void Logger::ClearLastError(int channel_id) {
109   last_errors_.erase(channel_id);
110 }
111 
MaybeSetLastError(int channel_id,ChannelEvent channel_event,int rv,ChallengeReplyError challenge_reply_error)112 void Logger::MaybeSetLastError(int channel_id,
113                                ChannelEvent channel_event,
114                                int rv,
115                                ChallengeReplyError challenge_reply_error) {
116   auto it = last_errors_.find(channel_id);
117   if (it == last_errors_.end())
118     last_errors_[channel_id] = LastError();
119 
120   LastError* last_error = &last_errors_[channel_id];
121   if (rv < net::ERR_IO_PENDING) {
122     last_error->net_return_value = rv;
123     last_error->channel_event = channel_event;
124   }
125 
126   if (challenge_reply_error != ChallengeReplyError::NONE) {
127     last_error->challenge_reply_error = challenge_reply_error;
128     last_error->channel_event = channel_event;
129   }
130 }
131 
132 }  // namespace cast_channel
133