aboutsummaryrefslogtreecommitdiffstats
path: root/src/algo_factory/algo_cache.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/algo_factory/algo_cache.h')
-rw-r--r--src/algo_factory/algo_cache.h91
1 files changed, 68 insertions, 23 deletions
diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h
index 699078b03..17ea9964a 100644
--- a/src/algo_factory/algo_cache.h
+++ b/src/algo_factory/algo_cache.h
@@ -5,25 +5,46 @@
#ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
#define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
-#include <botan/scan_name.h>
#include <botan/mutex.h>
+#include <botan/stl_util.h>
#include <string>
+#include <vector>
#include <map>
namespace Botan {
/**
+* @param prov_name a provider name
+* @return weight for this provider
+*/
+u32bit static_provider_weight(const std::string& prov_name);
+
+/**
* Algorithm_Cache (used by Algorithm_Factory)
*/
template<typename T>
class Algorithm_Cache
{
public:
- const T* get(const SCAN_Name& request);
+ const T* get(const std::string& algo_spec,
+ const std::string& pref_provider);
+
+ /**
+ * Add a new algorithm implementation to the cache
+ */
void add(T* algo,
const std::string& requested_name,
- const std::string& provider);
+ const std::string& provider_name);
+
+ /**
+ * Set the preferred provider
+ */
+ void set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider);
+ /**
+ * Return the list of providers of this algorithm
+ */
std::vector<std::string> providers_of(const std::string& algo_name);
Algorithm_Cache(Mutex* m) : mutex(m) {}
@@ -38,17 +59,18 @@ class Algorithm_Cache
Mutex* mutex;
std::map<std::string, std::string> aliases;
+ std::map<std::string, std::string> pref_providers;
std::map<std::string, std::map<std::string, T*> > algorithms;
};
/**
* Look for an algorithm implementation in the cache, also checking aliases
+* Assumes object lock is held
*/
template<typename T>
typename Algorithm_Cache<T>::algorithms_iterator
Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec)
{
- // Assumes mutex is held
algorithms_iterator algo = algorithms.find(algo_spec);
// Not found? Check if a known alias
@@ -65,40 +87,51 @@ Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec)
}
/**
-* Look for an algorithm implementation in the cache
+* Look for an algorithm implementation by a particular provider
*/
template<typename T>
-const T* Algorithm_Cache<T>::get(const SCAN_Name& request)
+const T* Algorithm_Cache<T>::get(const std::string& algo_spec,
+ const std::string& requested_provider)
{
Mutex_Holder lock(mutex);
- algorithms_iterator algo = find_algorithm(request.as_string());
- if(algo == algorithms.end()) // not found at all
+ algorithms_iterator algo = find_algorithm(algo_spec);
+ if(algo == algorithms.end()) // algo not found at all (no providers)
return 0;
- const std::string requested_provider = request.provider();
-
+ // If a provider is requested specifically, return it or fail entirely
if(requested_provider != "")
{
- provider_iterator provider = algo->second.find(requested_provider);
-
- if(provider != algo->second.end())
- return provider->second;
+ provider_iterator prov = algo->second.find(requested_provider);
+ if(prov != algo->second.end())
+ return prov->second;
+ return 0;
}
- else // no specific provider requested: pick one
+
+ const T* prototype = 0;
+ std::string prototype_provider;
+ u32bit prototype_prov_weight = 0;
+
+ const std::string pref_provider = search_map(pref_providers, algo_spec);
+
+ for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i)
{
- provider_iterator provider = algo->second.begin();
+ const std::string prov_name = i->first;
+ const u32bit prov_weight = static_provider_weight(prov_name);
- while(provider != algo->second.end())
- ++provider;
+ // preferred prov exists, return immediately
+ if(prov_name == pref_provider)
+ return i->second;
- provider = algo->second.begin();
- // @fixme: Just picks the lexicographically first one
- if(provider != algo->second.end())
- return provider->second;
+ if(prototype == 0 || prov_weight > prototype_prov_weight)
+ {
+ prototype = i->second;
+ prototype_provider = i->first;
+ prototype_prov_weight = prov_weight;
+ }
}
- return 0; // cache miss
+ return prototype;
}
/**
@@ -151,6 +184,18 @@ Algorithm_Cache<T>::providers_of(const std::string& algo_name)
}
/**
+* Set the preferred provider for an algorithm
+*/
+template<typename T>
+void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ Mutex_Holder lock(mutex);
+
+ pref_providers[algo_spec] = provider;
+ }
+
+/**
* Algorithm_Cache<T> Destructor
*/
template<typename T>