]>
Commit | Line | Data |
---|---|---|
94b18763 FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "rgw_http_client_curl.h" | |
5 | #include <mutex> | |
6 | #include <vector> | |
7 | #include <curl/curl.h> | |
8 | ||
9 | #include "rgw_common.h" | |
10 | #define dout_context g_ceph_context | |
11 | #define dout_subsys ceph_subsys_rgw | |
12 | ||
13 | #ifdef WITH_CURL_OPENSSL | |
14 | #include <openssl/crypto.h> | |
15 | #endif | |
16 | ||
17 | #if defined(WITH_CURL_OPENSSL) && OPENSSL_API_COMPAT < 0x10100000L | |
18 | namespace openssl { | |
19 | ||
20 | class RGWSSLSetup | |
21 | { | |
22 | std::vector <std::mutex> locks; | |
23 | public: | |
24 | RGWSSLSetup(int n) : locks (n){} | |
25 | ||
26 | void set_lock(int id){ | |
27 | try { | |
28 | locks.at(id).lock(); | |
29 | } catch (std::out_of_range& e) { | |
30 | dout(0) << __func__ << "failed to set locks" << dendl; | |
31 | } | |
32 | } | |
33 | ||
34 | void clear_lock(int id){ | |
35 | try { | |
36 | locks.at(id).unlock(); | |
37 | } catch (std::out_of_range& e) { | |
38 | dout(0) << __func__ << "failed to unlock" << dendl; | |
39 | } | |
40 | } | |
41 | }; | |
42 | ||
43 | ||
44 | void rgw_ssl_locking_callback(int mode, int id, const char *file, int line) | |
45 | { | |
46 | static RGWSSLSetup locks(CRYPTO_num_locks()); | |
47 | if (mode & CRYPTO_LOCK) | |
48 | locks.set_lock(id); | |
49 | else | |
50 | locks.clear_lock(id); | |
51 | } | |
52 | ||
53 | unsigned long rgw_ssl_thread_id_callback(){ | |
54 | return (unsigned long)pthread_self(); | |
55 | } | |
56 | ||
57 | void init_ssl(){ | |
58 | CRYPTO_set_id_callback((unsigned long (*) ()) rgw_ssl_thread_id_callback); | |
59 | CRYPTO_set_locking_callback(rgw_ssl_locking_callback); | |
60 | } | |
61 | ||
62 | } /* namespace openssl */ | |
63 | #endif // WITH_CURL_OPENSSL | |
64 | ||
65 | ||
66 | namespace rgw { | |
67 | namespace curl { | |
68 | ||
69 | static void check_curl() | |
70 | { | |
71 | #ifndef HAVE_CURL_MULTI_WAIT | |
72 | derr << "WARNING: libcurl doesn't support curl_multi_wait()" << dendl; | |
73 | derr << "WARNING: cross zone / region transfer performance may be affected" << dendl; | |
74 | #endif | |
75 | } | |
76 | ||
77 | #if defined(WITH_CURL_OPENSSL) && OPENSSL_API_COMPAT < 0x10100000L | |
78 | void init_ssl() { | |
79 | ::openssl::init_ssl(); | |
80 | } | |
81 | ||
82 | bool fe_inits_ssl(boost::optional <const fe_map_t&> m, long& curl_global_flags){ | |
83 | if (m) { | |
84 | for (const auto& kv: *m){ | |
85 | if (kv.first == "civetweb" || kv.first == "beast"){ | |
86 | std::string cert; | |
87 | kv.second->get_val("ssl_certificate","", &cert); | |
88 | if (!cert.empty()){ | |
89 | /* TODO this flag is no op for curl > 7.57 */ | |
90 | curl_global_flags &= ~CURL_GLOBAL_SSL; | |
91 | return true; | |
92 | } | |
93 | } | |
94 | } | |
95 | } | |
96 | return false; | |
97 | } | |
98 | #endif // WITH_CURL_OPENSSL | |
99 | ||
100 | std::once_flag curl_init_flag; | |
101 | ||
102 | void setup_curl(boost::optional<const fe_map_t&> m) { | |
103 | check_curl(); | |
104 | ||
105 | long curl_global_flags = CURL_GLOBAL_ALL; | |
106 | ||
107 | #if defined(WITH_CURL_OPENSSL) && OPENSSL_API_COMPAT < 0x10100000L | |
108 | if (!fe_inits_ssl(m, curl_global_flags)) | |
109 | init_ssl(); | |
110 | #endif | |
111 | ||
112 | std::call_once(curl_init_flag, curl_global_init, curl_global_flags); | |
113 | rgw_setup_saved_curl_handles(); | |
114 | } | |
115 | ||
116 | void cleanup_curl() { | |
117 | rgw_release_all_curl_handles(); | |
118 | curl_global_cleanup(); | |
119 | } | |
120 | ||
121 | } /* namespace curl */ | |
122 | } /* namespace rgw */ |