]>
Commit | Line | Data |
---|---|---|
89deb186 | 1 | /* |
ef57eb7b | 2 | * Copyright (C) 1996-2016 The Squid Software Foundation and contributors |
89deb186 AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
f97700a0 AJ |
9 | #ifndef SQUID_SRC_SECURITY_LOCKINGPOINTER_H |
10 | #define SQUID_SRC_SECURITY_LOCKINGPOINTER_H | |
11 | ||
eacc1666 AJ |
12 | #if USE_OPENSSL |
13 | #if HAVE_OPENSSL_CRYPTO_H | |
14 | #include <openssl/crypto.h> | |
15 | #endif | |
16 | ||
17 | // Macro to be used to define the C++ wrapper function of a sk_*_pop_free | |
18 | // openssl family functions. The C++ function suffixed with the _free_wrapper | |
19 | // extension | |
20 | #define sk_free_wrapper(sk_object, argument, freefunction) \ | |
21 | extern "C++" inline void sk_object ## _free_wrapper(argument a) { \ | |
22 | sk_object ## _pop_free(a, freefunction); \ | |
23 | } | |
24 | ||
fdfa0570 | 25 | #endif /* USE_OPENSSL */ |
eacc1666 AJ |
26 | |
27 | // Macro to be used to define the C++ equivalent function of an extern "C" | |
28 | // function. The C++ function suffixed with the _cpp extension | |
29 | #define CtoCpp1(function, argument) \ | |
30 | extern "C++" inline void function ## _cpp(argument a) { \ | |
31 | function(a); \ | |
32 | } | |
33 | ||
f97700a0 AJ |
34 | namespace Security |
35 | { | |
36 | ||
37 | /** | |
d2e36b65 AJ |
38 | * A shared pointer to a reference-counting Object with library-specific |
39 | * absorption, locking, and unlocking implementations. The API largely | |
40 | * follows std::shared_ptr. | |
41 | * | |
42 | * The constructor and the reset() method import a raw Object pointer. | |
43 | * Normally, reset() would lock(), but libraries like OpenSSL | |
44 | * pre-lock objects before they are fed to LockingPointer, necessitating | |
45 | * this customization hook. | |
46 | * | |
47 | * The lock() method increments Object's reference counter. | |
48 | * | |
49 | * The unlock() method decrements Object's reference counter and destroys | |
50 | * the object when the counter reaches zero. | |
89deb186 | 51 | */ |
d2e36b65 | 52 | template <typename T, void (*UnLocker)(T *t), int lockId> |
fdfa0570 | 53 | class LockingPointer |
f97700a0 AJ |
54 | { |
55 | public: | |
fdfa0570 | 56 | /// a helper label to simplify this objects API definitions below |
d2e36b65 | 57 | typedef LockingPointer<T, UnLocker, lockId> SelfType; |
89deb186 | 58 | |
fdfa0570 AJ |
59 | /** |
60 | * Construct directly from a raw pointer. | |
61 | * This action requires that the producer of that pointer has already | |
62 | * created one reference lock for the object pointed to. | |
d2e36b65 | 63 | * Our destructor will do the matching unlock. |
fdfa0570 AJ |
64 | */ |
65 | explicit LockingPointer(T *t = nullptr): raw(t) {} | |
89deb186 | 66 | |
d2e36b65 AJ |
67 | /// use the custom UnLocker to unlock any value still stored. |
68 | ~LockingPointer() { unlock(); } | |
89deb186 | 69 | |
fdfa0570 AJ |
70 | // copy semantics are okay only when adding a lock reference |
71 | explicit LockingPointer(const SelfType &o) : raw(nullptr) { resetAndLock(o.get()); } | |
89deb186 | 72 | SelfType &operator =(const SelfType & o) { |
014a9017 | 73 | resetAndLock(o.get()); |
89deb186 AJ |
74 | return *this; |
75 | } | |
f97700a0 | 76 | |
fdfa0570 AJ |
77 | // move semantics are definitely okay, when possible |
78 | explicit LockingPointer(SelfType &&) = default; | |
7007ee99 AJ |
79 | SelfType &operator =(SelfType &&o) { |
80 | if (o.get() != raw) | |
81 | reset(o.release()); | |
82 | return *this; | |
83 | } | |
89deb186 | 84 | |
fdfa0570 AJ |
85 | bool operator !() const { return !raw; } |
86 | explicit operator bool() const { return raw; } | |
87 | ||
88 | /// Returns raw and possibly nullptr pointer | |
89 | T *get() const { return raw; } | |
90 | ||
d2e36b65 | 91 | /// Reset raw pointer - unlock any previous one and save new one without locking. |
fdfa0570 | 92 | void reset(T *t) { |
d2e36b65 | 93 | unlock(); |
fdfa0570 | 94 | raw = t; |
89deb186 | 95 | } |
f97700a0 | 96 | |
014a9017 | 97 | void resetAndLock(T *t) { |
ccf24f29 AJ |
98 | if (t != get()) { |
99 | reset(t); | |
d2e36b65 | 100 | lock(t); |
f97700a0 AJ |
101 | } |
102 | } | |
fdfa0570 | 103 | |
d2e36b65 | 104 | /// Forget the raw pointer without unlocking it. Become a nil pointer. |
fdfa0570 AJ |
105 | T *release() { |
106 | T *ret = raw; | |
107 | raw = nullptr; | |
108 | return ret; | |
109 | } | |
110 | ||
111 | private: | |
d2e36b65 AJ |
112 | void lock(T *t) { |
113 | #if USE_OPENSSL | |
114 | if (t) | |
115 | CRYPTO_add(&t->references, 1, lockId); | |
116 | #elif USE_GNUTLS | |
117 | // XXX: GnuTLS does not provide locking ? | |
118 | #else | |
119 | assert(false); | |
120 | #endif | |
121 | } | |
122 | ||
123 | /// Unlock the raw pointer. Become a nil pointer. | |
124 | void unlock() { | |
fdfa0570 | 125 | if (raw) |
d2e36b65 | 126 | UnLocker(raw); |
fdfa0570 AJ |
127 | raw = nullptr; |
128 | } | |
129 | ||
130 | T *raw; ///< pointer to T object or nullptr | |
f97700a0 AJ |
131 | }; |
132 | ||
133 | } // namespace Security | |
134 | ||
135 | #endif /* SQUID_SRC_SECURITY_LOCKINGPOINTER_H */ | |
63b8c4d7 | 136 |