1 /* $OpenLDAP: pkg/ldap/libraries/librewrite/session.c,v 1.19.2.3 2008/02/11 23:26:42 kurt Exp $ */ 2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 2000-2008 The OpenLDAP Foundation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted only as authorized by the OpenLDAP 9 * Public License. 10 * 11 * A copy of this license is available in the file LICENSE in the 12 * top-level directory of the distribution or, alternatively, at 13 * <http://www.OpenLDAP.org/license.html>. 14 */ 15 /* ACKNOWLEDGEMENT: 16 * This work was initially developed by Pierangelo Masarati for 17 * inclusion in OpenLDAP Software. 18 */ 19 20 #include <portable.h> 21 22 #include "rewrite-int.h" 23 24 /* 25 * Compares two cookies 26 */ 27 static int 28 rewrite_cookie_cmp( 29 const void *c1, 30 const void *c2 31 ) 32 { 33 const struct rewrite_session *s1, *s2; 34 35 s1 = ( const struct rewrite_session * )c1; 36 s2 = ( const struct rewrite_session * )c2; 37 38 assert( s1 != NULL ); 39 assert( s2 != NULL ); 40 assert( s1->ls_cookie != NULL ); 41 assert( s2->ls_cookie != NULL ); 42 43 return ( ( s1->ls_cookie < s2->ls_cookie ) ? -1 : 44 ( ( s1->ls_cookie > s2->ls_cookie ) ? 1 : 0 ) ); 45 } 46 47 /* 48 * Duplicate cookies? 49 */ 50 static int 51 rewrite_cookie_dup( 52 void *c1, 53 void *c2 54 ) 55 { 56 struct rewrite_session *s1, *s2; 57 58 s1 = ( struct rewrite_session * )c1; 59 s2 = ( struct rewrite_session * )c2; 60 61 assert( s1 != NULL ); 62 assert( s2 != NULL ); 63 assert( s1->ls_cookie != NULL ); 64 assert( s2->ls_cookie != NULL ); 65 66 assert( s1->ls_cookie != s2->ls_cookie ); 67 68 return ( ( s1->ls_cookie == s2->ls_cookie ) ? -1 : 0 ); 69 } 70 71 /* 72 * Inits a session 73 */ 74 struct rewrite_session * 75 rewrite_session_init( 76 struct rewrite_info *info, 77 const void *cookie 78 ) 79 { 80 struct rewrite_session *session, tmp; 81 int rc; 82 83 assert( info != NULL ); 84 assert( cookie != NULL ); 85 86 #ifdef USE_REWRITE_LDAP_PVT_THREADS 87 ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); 88 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 89 90 tmp.ls_cookie = ( void * )cookie; 91 session = ( struct rewrite_session * )avl_find( info->li_cookies, 92 ( caddr_t )&tmp, rewrite_cookie_cmp ); 93 if ( session ) { 94 session->ls_count++; 95 #ifdef USE_REWRITE_LDAP_PVT_THREADS 96 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); 97 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 98 return session; 99 } 100 101 session = calloc( sizeof( struct rewrite_session ), 1 ); 102 if ( session == NULL ) { 103 return NULL; 104 } 105 session->ls_cookie = ( void * )cookie; 106 session->ls_count = 1; 107 108 #ifdef USE_REWRITE_LDAP_PVT_THREADS 109 if ( ldap_pvt_thread_mutex_init( &session->ls_mutex ) ) { 110 free( session ); 111 return NULL; 112 } 113 if ( ldap_pvt_thread_rdwr_init( &session->ls_vars_mutex ) ) { 114 ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); 115 free( session ); 116 return NULL; 117 } 118 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 119 120 rc = avl_insert( &info->li_cookies, ( caddr_t )session, 121 rewrite_cookie_cmp, rewrite_cookie_dup ); 122 info->li_num_cookies++; 123 124 #ifdef USE_REWRITE_LDAP_PVT_THREADS 125 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); 126 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 127 128 if ( rc != 0 ) { 129 #ifdef USE_REWRITE_LDAP_PVT_THREADS 130 ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); 131 ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); 132 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 133 134 free( session ); 135 return NULL; 136 } 137 138 return session; 139 } 140 141 /* 142 * Fetches a session 143 */ 144 struct rewrite_session * 145 rewrite_session_find( 146 struct rewrite_info *info, 147 const void *cookie 148 ) 149 { 150 struct rewrite_session *session, tmp; 151 152 assert( info != NULL ); 153 assert( cookie != NULL ); 154 155 tmp.ls_cookie = ( void * )cookie; 156 #ifdef USE_REWRITE_LDAP_PVT_THREADS 157 ldap_pvt_thread_rdwr_rlock( &info->li_cookies_mutex ); 158 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 159 session = ( struct rewrite_session * )avl_find( info->li_cookies, 160 ( caddr_t )&tmp, rewrite_cookie_cmp ); 161 #ifdef USE_REWRITE_LDAP_PVT_THREADS 162 if ( session ) { 163 ldap_pvt_thread_mutex_lock( &session->ls_mutex ); 164 } 165 ldap_pvt_thread_rdwr_runlock( &info->li_cookies_mutex ); 166 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 167 168 return session; 169 } 170 171 /* 172 * Returns a session 173 */ 174 void 175 rewrite_session_return( 176 struct rewrite_info *info, 177 struct rewrite_session *session 178 ) 179 { 180 assert( session != NULL ); 181 ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); 182 } 183 184 /* 185 * Defines and inits a var with session scope 186 */ 187 int 188 rewrite_session_var_set_f( 189 struct rewrite_info *info, 190 const void *cookie, 191 const char *name, 192 const char *value, 193 int flags 194 ) 195 { 196 struct rewrite_session *session; 197 struct rewrite_var *var; 198 199 assert( info != NULL ); 200 assert( cookie != NULL ); 201 assert( name != NULL ); 202 assert( value != NULL ); 203 204 session = rewrite_session_find( info, cookie ); 205 if ( session == NULL ) { 206 session = rewrite_session_init( info, cookie ); 207 if ( session == NULL ) { 208 return REWRITE_ERR; 209 } 210 211 #ifdef USE_REWRITE_LDAP_PVT_THREADS 212 ldap_pvt_thread_mutex_lock( &session->ls_mutex ); 213 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 214 } 215 216 #ifdef USE_REWRITE_LDAP_PVT_THREADS 217 ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); 218 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 219 220 var = rewrite_var_find( session->ls_vars, name ); 221 if ( var != NULL ) { 222 assert( var->lv_value.bv_val != NULL ); 223 224 (void)rewrite_var_replace( var, value, flags ); 225 226 } else { 227 var = rewrite_var_insert_f( &session->ls_vars, name, value, flags ); 228 if ( var == NULL ) { 229 #ifdef USE_REWRITE_LDAP_PVT_THREADS 230 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); 231 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 232 rewrite_session_return( info, session ); 233 return REWRITE_ERR; 234 } 235 } 236 237 #ifdef USE_REWRITE_LDAP_PVT_THREADS 238 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); 239 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 240 241 rewrite_session_return( info, session ); 242 243 return REWRITE_SUCCESS; 244 } 245 246 /* 247 * Gets a var with session scope 248 */ 249 int 250 rewrite_session_var_get( 251 struct rewrite_info *info, 252 const void *cookie, 253 const char *name, 254 struct berval *value 255 ) 256 { 257 struct rewrite_session *session; 258 struct rewrite_var *var; 259 260 assert( info != NULL ); 261 assert( cookie != NULL ); 262 assert( name != NULL ); 263 assert( value != NULL ); 264 265 value->bv_val = NULL; 266 value->bv_len = 0; 267 268 if ( cookie == NULL ) { 269 return REWRITE_ERR; 270 } 271 272 session = rewrite_session_find( info, cookie ); 273 if ( session == NULL ) { 274 return REWRITE_ERR; 275 } 276 277 #ifdef USE_REWRITE_LDAP_PVT_THREADS 278 ldap_pvt_thread_rdwr_rlock( &session->ls_vars_mutex ); 279 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 280 281 var = rewrite_var_find( session->ls_vars, name ); 282 if ( var == NULL ) { 283 284 #ifdef USE_REWRITE_LDAP_PVT_THREADS 285 ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex ); 286 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 287 288 rewrite_session_return( info, session ); 289 290 return REWRITE_ERR; 291 } else { 292 value->bv_val = strdup( var->lv_value.bv_val ); 293 value->bv_len = var->lv_value.bv_len; 294 } 295 296 #ifdef USE_REWRITE_LDAP_PVT_THREADS 297 ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex ); 298 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 299 300 rewrite_session_return( info, session ); 301 302 return REWRITE_SUCCESS; 303 } 304 305 static void 306 rewrite_session_clean( void *v_session ) 307 { 308 struct rewrite_session *session = (struct rewrite_session *)v_session; 309 310 #ifdef USE_REWRITE_LDAP_PVT_THREADS 311 ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); 312 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 313 314 rewrite_var_delete( session->ls_vars ); 315 316 #ifdef USE_REWRITE_LDAP_PVT_THREADS 317 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); 318 ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); 319 ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); 320 ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); 321 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 322 } 323 324 static void 325 rewrite_session_free( void *v_session ) 326 { 327 struct rewrite_session *session = (struct rewrite_session *)v_session; 328 329 ldap_pvt_thread_mutex_lock( &session->ls_mutex ); 330 rewrite_session_clean( v_session ); 331 free( v_session ); 332 } 333 334 /* 335 * Deletes a session 336 */ 337 int 338 rewrite_session_delete( 339 struct rewrite_info *info, 340 const void *cookie 341 ) 342 { 343 struct rewrite_session *session, tmp = { 0 }; 344 345 assert( info != NULL ); 346 assert( cookie != NULL ); 347 348 session = rewrite_session_find( info, cookie ); 349 350 if ( session == NULL ) { 351 return REWRITE_SUCCESS; 352 } 353 354 if ( --session->ls_count > 0 ) { 355 rewrite_session_return( info, session ); 356 return REWRITE_SUCCESS; 357 } 358 359 rewrite_session_clean( session ); 360 361 #ifdef USE_REWRITE_LDAP_PVT_THREADS 362 ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); 363 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 364 365 assert( info->li_num_cookies > 0 ); 366 info->li_num_cookies--; 367 368 /* 369 * There is nothing to delete in the return value 370 */ 371 tmp.ls_cookie = ( void * )cookie; 372 avl_delete( &info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp ); 373 374 free( session ); 375 376 #ifdef USE_REWRITE_LDAP_PVT_THREADS 377 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); 378 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 379 380 return REWRITE_SUCCESS; 381 } 382 383 /* 384 * Destroys the cookie tree 385 */ 386 int 387 rewrite_session_destroy( 388 struct rewrite_info *info 389 ) 390 { 391 int count; 392 393 assert( info != NULL ); 394 395 #ifdef USE_REWRITE_LDAP_PVT_THREADS 396 ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); 397 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 398 399 /* 400 * Should call per-session destruction routine ... 401 */ 402 403 count = avl_free( info->li_cookies, rewrite_session_free ); 404 info->li_cookies = NULL; 405 406 #if 0 407 fprintf( stderr, "count = %d; num_cookies = %d\n", 408 count, info->li_num_cookies ); 409 #endif 410 411 assert( count == info->li_num_cookies ); 412 info->li_num_cookies = 0; 413 414 #ifdef USE_REWRITE_LDAP_PVT_THREADS 415 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex ); 416 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 417 418 return REWRITE_SUCCESS; 419 } 420 421