1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, 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 http://curl.haxx.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 ***************************************************************************/ 22 23#include "setup.h" 24#include <stdarg.h> 25#include <stdlib.h> 26#include <string.h> 27#include <curl/curl.h> 28#include "urldata.h" 29#include "share.h" 30#include "curl_memory.h" 31 32/* The last #include file should be: */ 33#include "memdebug.h" 34 35CURLSH * 36curl_share_init(void) 37{ 38 struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); 39 if(share) 40 share->specifier |= (1<<CURL_LOCK_DATA_SHARE); 41 42 return share; 43} 44 45#undef curl_share_setopt 46CURLSHcode 47curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) 48{ 49 struct Curl_share *share = (struct Curl_share *)sh; 50 va_list param; 51 int type; 52 curl_lock_function lockfunc; 53 curl_unlock_function unlockfunc; 54 void *ptr; 55 56 if(share->dirty) 57 /* don't allow setting options while one or more handles are already 58 using this share */ 59 return CURLSHE_IN_USE; 60 61 va_start(param, option); 62 63 switch(option) { 64 case CURLSHOPT_SHARE: 65 /* this is a type this share will share */ 66 type = va_arg(param, int); 67 share->specifier |= (1<<type); 68 switch( type ) { 69 case CURL_LOCK_DATA_DNS: 70 if(!share->hostcache) { 71 share->hostcache = Curl_mk_dnscache(); 72 if(!share->hostcache) 73 return CURLSHE_NOMEM; 74 } 75 break; 76 77#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 78 case CURL_LOCK_DATA_COOKIE: 79 if(!share->cookies) { 80 share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE ); 81 if(!share->cookies) 82 return CURLSHE_NOMEM; 83 } 84 break; 85#endif /* CURL_DISABLE_HTTP */ 86 87 case CURL_LOCK_DATA_SSL_SESSION: /* not supported (yet) */ 88 case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ 89 90 default: 91 return CURLSHE_BAD_OPTION; 92 } 93 break; 94 95 case CURLSHOPT_UNSHARE: 96 /* this is a type this share will no longer share */ 97 type = va_arg(param, int); 98 share->specifier &= ~(1<<type); 99 switch( type ) { 100 case CURL_LOCK_DATA_DNS: 101 if(share->hostcache) { 102 Curl_hash_destroy(share->hostcache); 103 share->hostcache = NULL; 104 } 105 break; 106 107#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 108 case CURL_LOCK_DATA_COOKIE: 109 if(share->cookies) { 110 Curl_cookie_cleanup(share->cookies); 111 share->cookies = NULL; 112 } 113 break; 114#endif /* CURL_DISABLE_HTTP */ 115 116 case CURL_LOCK_DATA_SSL_SESSION: 117 break; 118 119 case CURL_LOCK_DATA_CONNECT: 120 break; 121 122 default: 123 return CURLSHE_BAD_OPTION; 124 } 125 break; 126 127 case CURLSHOPT_LOCKFUNC: 128 lockfunc = va_arg(param, curl_lock_function); 129 share->lockfunc = lockfunc; 130 break; 131 132 case CURLSHOPT_UNLOCKFUNC: 133 unlockfunc = va_arg(param, curl_unlock_function); 134 share->unlockfunc = unlockfunc; 135 break; 136 137 case CURLSHOPT_USERDATA: 138 ptr = va_arg(param, void *); 139 share->clientdata = ptr; 140 break; 141 142 default: 143 return CURLSHE_BAD_OPTION; 144 } 145 146 return CURLSHE_OK; 147} 148 149CURLSHcode 150curl_share_cleanup(CURLSH *sh) 151{ 152 struct Curl_share *share = (struct Curl_share *)sh; 153 154 if(share == NULL) 155 return CURLSHE_INVALID; 156 157 if(share->lockfunc) 158 share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, 159 share->clientdata); 160 161 if(share->dirty) { 162 if(share->unlockfunc) 163 share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); 164 return CURLSHE_IN_USE; 165 } 166 167 if(share->hostcache) { 168 Curl_hash_destroy(share->hostcache); 169 share->hostcache = NULL; 170 } 171 172 if(share->cookies) 173 Curl_cookie_cleanup(share->cookies); 174 175 if(share->unlockfunc) 176 share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); 177 free(share); 178 179 return CURLSHE_OK; 180} 181 182 183CURLSHcode 184Curl_share_lock(struct SessionHandle *data, curl_lock_data type, 185 curl_lock_access accesstype) 186{ 187 struct Curl_share *share = data->share; 188 189 if(share == NULL) 190 return CURLSHE_INVALID; 191 192 if(share->specifier & (1<<type)) { 193 if(share->lockfunc) /* only call this if set! */ 194 share->lockfunc(data, type, accesstype, share->clientdata); 195 } 196 /* else if we don't share this, pretend successful lock */ 197 198 return CURLSHE_OK; 199} 200 201CURLSHcode 202Curl_share_unlock(struct SessionHandle *data, curl_lock_data type) 203{ 204 struct Curl_share *share = data->share; 205 206 if(share == NULL) 207 return CURLSHE_INVALID; 208 209 if(share->specifier & (1<<type)) { 210 if(share->unlockfunc) /* only call this if set! */ 211 share->unlockfunc (data, type, share->clientdata); 212 } 213 214 return CURLSHE_OK; 215} 216