share.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "curl_setup.h"
  25. #include <curl/curl.h>
  26. #include "urldata.h"
  27. #include "connect.h"
  28. #include "share.h"
  29. #include "psl.h"
  30. #include "vtls/vtls.h"
  31. #include "vtls/vtls_scache.h"
  32. #include "hsts.h"
  33. #include "url.h"
  34. /* The last 3 #include files should be in this order */
  35. #include "curl_printf.h"
  36. #include "curl_memory.h"
  37. #include "memdebug.h"
  38. CURLSH *
  39. curl_share_init(void)
  40. {
  41. struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
  42. if(share) {
  43. share->magic = CURL_GOOD_SHARE;
  44. share->specifier |= (1 << CURL_LOCK_DATA_SHARE);
  45. Curl_init_dnscache(&share->hostcache, 23);
  46. }
  47. return share;
  48. }
  49. #undef curl_share_setopt
  50. CURLSHcode
  51. curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
  52. {
  53. va_list param;
  54. int type;
  55. curl_lock_function lockfunc;
  56. curl_unlock_function unlockfunc;
  57. void *ptr;
  58. CURLSHcode res = CURLSHE_OK;
  59. struct Curl_share *share = sh;
  60. if(!GOOD_SHARE_HANDLE(share))
  61. return CURLSHE_INVALID;
  62. if(share->dirty)
  63. /* do not allow setting options while one or more handles are already
  64. using this share */
  65. return CURLSHE_IN_USE;
  66. va_start(param, option);
  67. switch(option) {
  68. case CURLSHOPT_SHARE:
  69. /* this is a type this share will share */
  70. type = va_arg(param, int);
  71. switch(type) {
  72. case CURL_LOCK_DATA_DNS:
  73. break;
  74. case CURL_LOCK_DATA_COOKIE:
  75. #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
  76. if(!share->cookies) {
  77. share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE);
  78. if(!share->cookies)
  79. res = CURLSHE_NOMEM;
  80. }
  81. #else /* CURL_DISABLE_HTTP */
  82. res = CURLSHE_NOT_BUILT_IN;
  83. #endif
  84. break;
  85. case CURL_LOCK_DATA_HSTS:
  86. #ifndef CURL_DISABLE_HSTS
  87. if(!share->hsts) {
  88. share->hsts = Curl_hsts_init();
  89. if(!share->hsts)
  90. res = CURLSHE_NOMEM;
  91. }
  92. #else /* CURL_DISABLE_HSTS */
  93. res = CURLSHE_NOT_BUILT_IN;
  94. #endif
  95. break;
  96. case CURL_LOCK_DATA_SSL_SESSION:
  97. #ifdef USE_SSL
  98. if(!share->ssl_scache) {
  99. /* There is no way (yet) for the application to configure the
  100. * session cache size, shared between many transfers. As for curl
  101. * itself, a high session count will impact startup time. Also, the
  102. * scache is not optimized for several hundreds of peers. So,
  103. * keep it at a reasonable level. */
  104. if(Curl_ssl_scache_create(25, 2, &share->ssl_scache))
  105. res = CURLSHE_NOMEM;
  106. }
  107. #else
  108. res = CURLSHE_NOT_BUILT_IN;
  109. #endif
  110. break;
  111. case CURL_LOCK_DATA_CONNECT:
  112. /* It is safe to set this option several times on a share. */
  113. if(!share->cpool.idata) {
  114. if(Curl_cpool_init(&share->cpool, Curl_on_disconnect,
  115. NULL, share, 103))
  116. res = CURLSHE_NOMEM;
  117. }
  118. break;
  119. case CURL_LOCK_DATA_PSL:
  120. #ifndef USE_LIBPSL
  121. res = CURLSHE_NOT_BUILT_IN;
  122. #endif
  123. break;
  124. default:
  125. res = CURLSHE_BAD_OPTION;
  126. }
  127. if(!res)
  128. share->specifier |= (unsigned int)(1 << type);
  129. break;
  130. case CURLSHOPT_UNSHARE:
  131. /* this is a type this share will no longer share */
  132. type = va_arg(param, int);
  133. share->specifier &= ~(unsigned int)(1 << type);
  134. switch(type) {
  135. case CURL_LOCK_DATA_DNS:
  136. break;
  137. case CURL_LOCK_DATA_COOKIE:
  138. #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
  139. if(share->cookies) {
  140. Curl_cookie_cleanup(share->cookies);
  141. share->cookies = NULL;
  142. }
  143. #else /* CURL_DISABLE_HTTP */
  144. res = CURLSHE_NOT_BUILT_IN;
  145. #endif
  146. break;
  147. case CURL_LOCK_DATA_HSTS:
  148. #ifndef CURL_DISABLE_HSTS
  149. if(share->hsts) {
  150. Curl_hsts_cleanup(&share->hsts);
  151. }
  152. #else /* CURL_DISABLE_HSTS */
  153. res = CURLSHE_NOT_BUILT_IN;
  154. #endif
  155. break;
  156. case CURL_LOCK_DATA_SSL_SESSION:
  157. #ifdef USE_SSL
  158. if(share->ssl_scache) {
  159. Curl_ssl_scache_destroy(share->ssl_scache);
  160. share->ssl_scache = NULL;
  161. }
  162. #else
  163. res = CURLSHE_NOT_BUILT_IN;
  164. #endif
  165. break;
  166. case CURL_LOCK_DATA_CONNECT:
  167. break;
  168. default:
  169. res = CURLSHE_BAD_OPTION;
  170. break;
  171. }
  172. break;
  173. case CURLSHOPT_LOCKFUNC:
  174. lockfunc = va_arg(param, curl_lock_function);
  175. share->lockfunc = lockfunc;
  176. break;
  177. case CURLSHOPT_UNLOCKFUNC:
  178. unlockfunc = va_arg(param, curl_unlock_function);
  179. share->unlockfunc = unlockfunc;
  180. break;
  181. case CURLSHOPT_USERDATA:
  182. ptr = va_arg(param, void *);
  183. share->clientdata = ptr;
  184. break;
  185. default:
  186. res = CURLSHE_BAD_OPTION;
  187. break;
  188. }
  189. va_end(param);
  190. return res;
  191. }
  192. CURLSHcode
  193. curl_share_cleanup(CURLSH *sh)
  194. {
  195. struct Curl_share *share = sh;
  196. if(!GOOD_SHARE_HANDLE(share))
  197. return CURLSHE_INVALID;
  198. if(share->lockfunc)
  199. share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
  200. share->clientdata);
  201. if(share->dirty) {
  202. if(share->unlockfunc)
  203. share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
  204. return CURLSHE_IN_USE;
  205. }
  206. if(share->specifier & (1 << CURL_LOCK_DATA_CONNECT)) {
  207. Curl_cpool_destroy(&share->cpool);
  208. }
  209. Curl_hash_destroy(&share->hostcache);
  210. #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
  211. Curl_cookie_cleanup(share->cookies);
  212. #endif
  213. #ifndef CURL_DISABLE_HSTS
  214. Curl_hsts_cleanup(&share->hsts);
  215. #endif
  216. #ifdef USE_SSL
  217. if(share->ssl_scache) {
  218. Curl_ssl_scache_destroy(share->ssl_scache);
  219. share->ssl_scache = NULL;
  220. }
  221. #endif
  222. Curl_psl_destroy(&share->psl);
  223. if(share->unlockfunc)
  224. share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
  225. share->magic = 0;
  226. free(share);
  227. return CURLSHE_OK;
  228. }
  229. CURLSHcode
  230. Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
  231. curl_lock_access accesstype)
  232. {
  233. struct Curl_share *share = data->share;
  234. if(!share)
  235. return CURLSHE_INVALID;
  236. if(share->specifier & (unsigned int)(1 << type)) {
  237. if(share->lockfunc) /* only call this if set! */
  238. share->lockfunc(data, type, accesstype, share->clientdata);
  239. }
  240. /* else if we do not share this, pretend successful lock */
  241. return CURLSHE_OK;
  242. }
  243. CURLSHcode
  244. Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
  245. {
  246. struct Curl_share *share = data->share;
  247. if(!share)
  248. return CURLSHE_INVALID;
  249. if(share->specifier & (unsigned int)(1 << type)) {
  250. if(share->unlockfunc) /* only call this if set! */
  251. share->unlockfunc (data, type, share->clientdata);
  252. }
  253. return CURLSHE_OK;
  254. }