1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "context_pool.h" 17 18 #include <mutex> 19 #include <set> 20 #include <singleton.h> 21 #include <unordered_map> 22 23 #include <openssl/rand.h> 24 25 #include "iam_logger.h" 26 27 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA 28 29 namespace OHOS { 30 namespace UserIam { 31 namespace UserAuth { 32 class ContextPoolImpl final : public ContextPool, public Singleton<ContextPoolImpl> { 33 public: 34 bool Insert(const std::shared_ptr<Context> &context) override; 35 bool Delete(uint64_t contextId) override; 36 std::weak_ptr<Context> Select(uint64_t contextId) const override; 37 std::vector<std::weak_ptr<Context>> Select(ContextType contextType) const override; 38 std::shared_ptr<ScheduleNode> SelectScheduleNodeByScheduleId(uint64_t scheduleId) override; 39 bool RegisterContextPoolListener(const std::shared_ptr<ContextPoolListener> &listener) override; 40 bool DeregisterContextPoolListener(const std::shared_ptr<ContextPoolListener> &listener) override; 41 42 private: 43 mutable std::mutex poolMutex_; 44 std::unordered_map<uint64_t, std::shared_ptr<Context>> contextMap_; 45 std::set<std::shared_ptr<ContextPoolListener>> listenerSet_; 46 }; 47 Insert(const std::shared_ptr<Context> & context)48bool ContextPoolImpl::Insert(const std::shared_ptr<Context> &context) 49 { 50 if (context == nullptr) { 51 IAM_LOGE("context is nullptr"); 52 return false; 53 } 54 std::lock_guard<std::mutex> lock(poolMutex_); 55 uint64_t contextId = context->GetContextId(); 56 auto result = contextMap_.try_emplace(contextId, context); 57 if (!result.second) { 58 return false; 59 } 60 for (const auto &listener : listenerSet_) { 61 if (listener != nullptr) { 62 listener->OnContextPoolInsert(context); 63 } 64 } 65 return true; 66 } 67 Delete(uint64_t contextId)68bool ContextPoolImpl::Delete(uint64_t contextId) 69 { 70 std::lock_guard<std::mutex> lock(poolMutex_); 71 auto iter = contextMap_.find(contextId); 72 if (iter == contextMap_.end()) { 73 IAM_LOGE("context not found"); 74 return false; 75 } 76 auto tempContext = iter->second; 77 contextMap_.erase(iter); 78 for (const auto &listener : listenerSet_) { 79 if (listener != nullptr) { 80 listener->OnContextPoolDelete(tempContext); 81 } 82 } 83 return true; 84 } 85 Select(uint64_t contextId) const86std::weak_ptr<Context> ContextPoolImpl::Select(uint64_t contextId) const 87 { 88 std::lock_guard<std::mutex> lock(poolMutex_); 89 std::weak_ptr<Context> result; 90 auto iter = contextMap_.find(contextId); 91 if (iter != contextMap_.end()) { 92 result = iter->second; 93 } 94 return result; 95 } 96 Select(ContextType contextType) const97std::vector<std::weak_ptr<Context>> ContextPoolImpl::Select(ContextType contextType) const 98 { 99 std::lock_guard<std::mutex> lock(poolMutex_); 100 std::vector<std::weak_ptr<Context>> result; 101 for (const auto &context : contextMap_) { 102 if (context.second == nullptr) { 103 continue; 104 } 105 if (context.second->GetContextType() == contextType) { 106 result.emplace_back(context.second); 107 } 108 } 109 return result; 110 } 111 SelectScheduleNodeByScheduleId(uint64_t scheduleId)112std::shared_ptr<ScheduleNode> ContextPoolImpl::SelectScheduleNodeByScheduleId(uint64_t scheduleId) 113 { 114 std::lock_guard<std::mutex> lock(poolMutex_); 115 for (const auto &context : contextMap_) { 116 if (context.second == nullptr) { 117 continue; 118 } 119 auto node = context.second->GetScheduleNode(scheduleId); 120 if (node != nullptr) { 121 return node; 122 } 123 } 124 return nullptr; 125 } 126 RegisterContextPoolListener(const std::shared_ptr<ContextPoolListener> & listener)127bool ContextPoolImpl::RegisterContextPoolListener(const std::shared_ptr<ContextPoolListener> &listener) 128 { 129 if (listener == nullptr) { 130 IAM_LOGE("listener is nullptr"); 131 return false; 132 } 133 std::lock_guard<std::mutex> lock(poolMutex_); 134 listenerSet_.insert(listener); 135 return true; 136 } 137 DeregisterContextPoolListener(const std::shared_ptr<ContextPoolListener> & listener)138bool ContextPoolImpl::DeregisterContextPoolListener(const std::shared_ptr<ContextPoolListener> &listener) 139 { 140 std::lock_guard<std::mutex> lock(poolMutex_); 141 return listenerSet_.erase(listener) == 1; 142 } 143 Instance()144ContextPool &ContextPool::Instance() 145 { 146 return ContextPoolImpl::GetInstance(); 147 } 148 GetNewContextId()149uint64_t ContextPool::GetNewContextId() 150 { 151 static constexpr uint32_t MAX_TRY_TIMES = 10; 152 static std::mutex mutex; 153 std::lock_guard<std::mutex> lock(mutex); 154 uint64_t contextId = 0; 155 unsigned char *contextIdPtr = static_cast<unsigned char *>(static_cast<void *>(&contextId)); 156 for (uint32_t i = 0; i < MAX_TRY_TIMES; i++) { 157 RAND_bytes(contextIdPtr, sizeof(uint64_t)); 158 if (contextId == 0 || ContextPool::Instance().Select(contextId).lock() != nullptr) { 159 IAM_LOGE("invalid or duplicate context id"); 160 continue; 161 } 162 } 163 return contextId; 164 } 165 } // namespace UserAuth 166 } // namespace UserIam 167 } // namespace OHOS 168