Commit 6416d833 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

add ldap_int_discard(); use it in proxies (ITS#4717)

parent 0aebe8af
......@@ -37,12 +37,13 @@
#include "ldap-int.h"
static int do_abandon LDAP_P((
static int
do_abandon(
LDAP *ld,
ber_int_t origid,
ber_int_t msgid,
LDAPControl **sctrls,
LDAPControl **cctrls));
int sendabandon );
/*
* ldap_abandon_ext - perform an ldap extended abandon operation.
......@@ -66,20 +67,24 @@ ldap_abandon_ext(
LDAPControl **sctrls,
LDAPControl **cctrls )
{
int rc;
int rc;
Debug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 );
/* check client controls */
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
rc = ldap_int_client_controls( ld, cctrls );
if( rc == LDAP_SUCCESS )
rc = do_abandon( ld, msgid, msgid, sctrls, cctrls );
if ( rc == LDAP_SUCCESS ) {
rc = do_abandon( ld, msgid, msgid, sctrls, 1 );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
return rc;
}
......@@ -104,25 +109,43 @@ ldap_abandon( LDAP *ld, int msgid )
}
int
ldap_int_discard(
LDAP *ld,
ber_int_t msgid )
{
int rc;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
rc = do_abandon( ld, msgid, msgid, NULL, 0 );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
return rc;
}
static int
do_abandon(
LDAP *ld,
ber_int_t origid,
ber_int_t msgid,
LDAPControl **sctrls,
LDAPControl **cctrls )
int sendabandon )
{
BerElement *ber;
int i, err, sendabandon;
int i, err;
ber_int_t *old_abandon;
Sockbuf *sb;
LDAPRequest *lr;
Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
Debug( LDAP_DEBUG_TRACE, "ldap_int_discard origid %d, msgid %d\n",
origid, msgid, 0 );
sendabandon = 1;
/* find the request that we are abandoning */
start_again:;
lr = ld->ld_requests;
......@@ -132,8 +155,8 @@ start_again:;
}
if ( lr->lr_origid == msgid ) {/* child: abandon it */
(void)do_abandon( ld,
lr->lr_origid, lr->lr_msgid, sctrls, cctrls );
(void)do_abandon( ld, lr->lr_origid, lr->lr_msgid,
sctrls, sendabandon );
/* restart, as lr may now be dangling... */
goto start_again;
......@@ -154,9 +177,9 @@ start_again:;
}
}
/* ldap_msgdelete locks the res_mutex. Give up the req_mutex
* while we're in there.
*/
/* ldap_msgdelete locks the res_mutex. Give up the req_mutex
* while we're in there.
*/
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
......@@ -172,7 +195,8 @@ start_again:;
/* fetch again the request that we are abandoning */
if ( lr != NULL ) {
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
if ( lr->lr_msgid == msgid ) { /* this message */
/* this message */
if ( lr->lr_msgid == msgid ) {
break;
}
}
......@@ -180,22 +204,23 @@ start_again:;
err = 0;
if ( sendabandon ) {
if( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
/* not connected */
err = -1;
ld->ld_errno = LDAP_SERVER_DOWN;
} else if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
/* BER element alocation failed */
} else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) {
/* BER element allocation failed */
err = -1;
ld->ld_errno = LDAP_NO_MEMORY;
} else {
/*
* We already have the mutex in LDAP_R_COMPILE, so
* don't try to get it again.
* LDAP_NEXT_MSGID(ld, i);
*/
/*
* We already have the mutex in LDAP_R_COMPILE, so
* don't try to get it again.
* LDAP_NEXT_MSGID(ld, i);
*/
i = ++(ld)->ld_msgid;
#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_UDP(ld) ) {
......@@ -219,7 +244,7 @@ start_again:;
LDAP_REQ_ABANDON, msgid );
}
if( err == -1 ) {
if ( err == -1 ) {
/* encoding error */
ld->ld_errno = LDAP_ENCODING_ERROR;
......@@ -234,7 +259,7 @@ start_again:;
/* close '{' */
err = ber_printf( ber, /*{*/ "N}" );
if( err == -1 ) {
if ( err == -1 ) {
/* encoding error */
ld->ld_errno = LDAP_ENCODING_ERROR;
}
......@@ -267,6 +292,7 @@ start_again:;
if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
ldap_free_connection( ld, lr->lr_conn, 0, 1 );
}
if ( origid == msgid ) {
ldap_free_request( ld, lr );
}
......@@ -278,25 +304,70 @@ start_again:;
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
/* use bisection */
i = 0;
if ( ld->ld_abandoned != NULL ) {
for ( ; ld->ld_abandoned[i] != -1; i++ )
; /* NULL */
}
int begin,
end;
assert( ld->ld_nabandoned >= 0 );
begin = 0;
end = ld->ld_nabandoned - 1;
old_abandon = ld->ld_abandoned;
if ( ld->ld_nabandoned == 0 || ld->ld_abandoned[ begin ] > msgid ) {
i = 0;
ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *)
ld->ld_abandoned, (i + 2) * sizeof(ber_int_t) );
if ( ld->ld_abandoned == NULL ) {
ld->ld_abandoned = old_abandon;
ld->ld_errno = LDAP_NO_MEMORY;
goto done;
} else if ( ld->ld_abandoned[ end ] < msgid ) {
i = ld->ld_nabandoned;
} else {
int pos, curid;
while ( end >= begin ) {
pos = (begin + end)/2;
curid = ld->ld_abandoned[ pos ];
if ( msgid < curid ) {
end = pos - 1;
} else if ( msgid > curid ) {
begin = pos + 1;
} else {
/* already abandoned? */
i = -1;
break;
}
}
if ( i == 0 ) {
i = pos;
}
}
}
ld->ld_abandoned[i] = msgid;
ld->ld_abandoned[i + 1] = -1;
if ( i != -1 ) {
int pos = i;
old_abandon = ld->ld_abandoned;
ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *)ld->ld_abandoned,
( ld->ld_nabandoned + 1 ) * sizeof( ber_int_t ) );
if ( ld->ld_abandoned == NULL ) {
ld->ld_abandoned = old_abandon;
ld->ld_errno = LDAP_NO_MEMORY;
goto done;
}
for ( i = ld->ld_nabandoned; i > pos; i-- ) {
ld->ld_abandoned[ i ] = ld->ld_abandoned[ i - 1 ];
}
ld->ld_abandoned[ pos ] = msgid;
++ld->ld_nabandoned;
}
if ( err != -1 ) {
ld->ld_errno = LDAP_SUCCESS;
......
......@@ -365,7 +365,8 @@ struct ldap {
ldap_pvt_thread_mutex_t ld_res_mutex;
#endif
ber_int_t *ld_abandoned; /* array of abandoned requests */
ber_len_t ld_nabandoned;
ber_int_t *ld_abandoned; /* array of abandoned requests */
LDAPCache *ld_cache; /* non-null if cache is initialized */
......@@ -396,6 +397,11 @@ LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_sasl_mutex;
#define LDAP_NEXT_MSGID(ld, id) id = ++(ld)->ld_msgid
#endif
LDAP_F ( int )
ldap_int_discard LDAP_P((
LDAP *ld,
ber_int_t msgid ));
/*
* in init.c
*/
......
......@@ -68,7 +68,8 @@
#include "ldap-int.h"
#include "ldap_log.h"
static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid ));
static int ldap_abandoned_idx LDAP_P(( LDAP *ld, ber_int_t msgid ));
#define ldap_abandoned(ld, msgid) ( ldap_abandoned_idx((ld), (msgid)) > -1 )
static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid ));
static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout,
LDAPMessage **result ));
......@@ -107,8 +108,8 @@ ldap_result(
struct timeval *timeout,
LDAPMessage **result )
{
LDAPMessage *lm;
int rc;
LDAPMessage *lm = NULL;
int rc;
assert( ld != NULL );
assert( result != NULL );
......@@ -118,19 +119,26 @@ ldap_result(
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
lm = chkResponseList(ld, msgid, all);
#if 0
/* this is already done inside wait4msg(), right?... */
lm = chkResponseList( ld, msgid, all );
#endif
if ( lm == NULL ) {
rc = wait4msg( ld, msgid, all, timeout, result );
} else {
*result = lm;
ld->ld_errno = LDAP_SUCCESS;
rc = lm->lm_msgtype;
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
return( rc );
return rc;
}
static LDAPMessage *
......@@ -140,6 +148,7 @@ chkResponseList(
int all)
{
LDAPMessage *lm, **lastlm, *nextlm;
int cnt = 0;
/*
* Look through the list of responses we have received on
......@@ -159,11 +168,12 @@ chkResponseList(
lastlm = &ld->ld_responses;
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) {
nextlm = lm->lm_next;
++cnt;
if ( ldap_abandoned( ld, lm->lm_msgid ) ) {
Debug( LDAP_DEBUG_TRACE,
"ldap_chkResponseList msg abandoned, msgid %d\n",
msgid, 0, 0 );
msgid, 0, 0 );
ldap_mark_abandoned( ld, lm->lm_msgid );
/* Remove this entry from list */
......@@ -178,14 +188,16 @@ chkResponseList(
LDAPMessage *tmp;
if ( all == LDAP_MSG_ONE || all == LDAP_MSG_RECEIVED ||
msgid == LDAP_RES_UNSOLICITED ) {
msgid == LDAP_RES_UNSOLICITED )
{
break;
}
tmp = lm->lm_chain_tail;
if ((tmp->lm_msgtype == LDAP_RES_SEARCH_ENTRY) ||
if ( (tmp->lm_msgtype == LDAP_RES_SEARCH_ENTRY) ||
(tmp->lm_msgtype == LDAP_RES_SEARCH_REFERENCE) ||
(tmp->lm_msgtype == LDAP_RES_INTERMEDIATE)) {
(tmp->lm_msgtype == LDAP_RES_INTERMEDIATE) )
{
tmp = NULL;
}
......@@ -198,28 +210,38 @@ chkResponseList(
lastlm = &lm->lm_next;
}
if ( lm != NULL ) {
#if 0
{
char buf[ BUFSIZ ];
snprintf( buf, sizeof( buf ), "ld=%p msgid=%d%s cnt=%d",
ld, msgid, all ? " all" : "", cnt );
Debug( LDAP_DEBUG_TRACE, "+++ chkResponseList %s\n", buf, 0, 0 );
}
#endif
if ( lm != NULL ) {
/* Found an entry, remove it from the list */
if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) {
if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) {
*lastlm = lm->lm_chain;
lm->lm_chain->lm_next = lm->lm_next;
lm->lm_chain->lm_chain_tail = ( lm->lm_chain_tail != lm ) ? lm->lm_chain_tail : lm->lm_chain;
lm->lm_chain = NULL;
lm->lm_chain_tail = NULL;
} else {
} else {
*lastlm = lm->lm_next;
}
lm->lm_next = NULL;
}
lm->lm_next = NULL;
}
#ifdef LDAP_DEBUG
if( lm == NULL) {
if ( lm == NULL) {
Debug( LDAP_DEBUG_TRACE,
"ldap_chkResponseList returns ld %p NULL\n", (void *)ld, 0, 0);
} else {
Debug( LDAP_DEBUG_TRACE,
"ldap_chkResponseList returns ld %p msgid %d, type 0x%02lu\n",
(void *)ld, lm->lm_msgid, (unsigned long) lm->lm_msgtype);
(void *)ld, lm->lm_msgid, (unsigned long) lm->lm_msgtype );
}
#endif
return lm;
......@@ -1158,7 +1180,7 @@ ldap_msgfree( LDAPMessage *lm )
LDAP_FREE( (char *) lm );
}
return( type );
return type;
}
/*
......@@ -1174,62 +1196,95 @@ ldap_msgdelete( LDAP *ld, int msgid )
assert( ld != NULL );
Debug( LDAP_DEBUG_TRACE, "ldap_msgdelete\n", 0, 0, 0 );
Debug( LDAP_DEBUG_TRACE, "ldap_msgdelete ld=%p msgid=%d\n",
(void *)ld, msgid, 0 );
prev = NULL;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
prev = NULL;
for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) {
if ( lm->lm_msgid == msgid )
if ( lm->lm_msgid == msgid ) {
break;
}
prev = lm;
}
if ( lm == NULL ) {
rc = -1;
} else {
if ( prev == NULL )
if ( prev == NULL ) {
ld->ld_responses = lm->lm_next;
else
} else {
prev->lm_next = lm->lm_next;
}
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
if ( lm && ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY )
if ( lm && ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY ) {
rc = -1;
}
return( rc );
return rc;
}
/*
* ldap_abandoned
* ldap_abandoned_idx
*
* return 1 if message msgid is waiting to be abandoned, 0 otherwise
* return the location of the message id in the array of abandoned
* message ids, or -1
*
* expects ld_res_mutex to be locked
*/
static int
ldap_abandoned( LDAP *ld, ber_int_t msgid )
ldap_abandoned_idx( LDAP *ld, ber_int_t msgid )
{
int i;
int begin,
end;
#ifdef LDAP_R_COMPILE
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
#endif
if ( ld->ld_abandoned == NULL )
return( 0 );
assert( ld->ld_nabandoned >= 0 );
for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
if ( ld->ld_abandoned[i] == msgid )
return( 1 );
if ( ld->ld_abandoned == NULL || ld->ld_nabandoned == 0 ) {
return -1;
}
return( 0 );
}
begin = 0;
end = ld->ld_nabandoned - 1;
/* use bisection */
if ( msgid < ld->ld_abandoned[ begin ] ) {
return -1;
}
if ( msgid > ld->ld_abandoned[ end ] ) {
return -1;
}
while ( end >= begin ) {
int pos = (begin + end)/2;
int curid = ld->ld_abandoned[ pos ];
if ( msgid < curid ) {
end = pos - 1;
} else if ( msgid > curid ) {
begin = pos + 1;
} else {
return pos;
}
}
/* not abandoned */
return -1;
}
/*
* ldap_mark_abandoned
......@@ -1239,25 +1294,22 @@ ldap_abandoned( LDAP *ld, ber_int_t msgid )
static int
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid )
{
int i;
int i, idx;
#ifdef LDAP_R_COMPILE
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
#endif
if ( ld->ld_abandoned == NULL )
return( -1 );
for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
if ( ld->ld_abandoned[i] == msgid )
break;
if ( ld->ld_abandoned[i] == -1 )
return( -1 );
idx = ldap_abandoned_idx( ld, msgid );
if ( idx == -1 ) {
return -1;
}
for ( ; ld->ld_abandoned[i] != -1; i++ ) {
ld->ld_abandoned[i] = ld->ld_abandoned[i + 1];
--ld->ld_nabandoned;
assert( ld->ld_nabandoned >= 0 );
for ( i = idx; i < ld->ld_nabandoned; i++ ) {
ld->ld_abandoned[ i ] = ld->ld_abandoned[ i + 1 ];
}
return( 0 );
return 0;
}
......@@ -1342,7 +1342,7 @@ ldap_back_cancel(
}
if ( LDAP_BACK_IGNORE( li ) ) {
return LDAP_SUCCESS;
return ldap_int_discard( lc->lc_ld, msgid );
}
if ( LDAP_BACK_CANCEL( li ) ) {
......
......@@ -865,7 +865,7 @@ meta_back_cancel(
rc = ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
} else if ( META_BACK_TGT_IGNORE( mt ) ) {
rc = LDAP_SUCCESS;
rc = ldap_int_discard( msc->msc_ld, msgid );
} else if ( META_BACK_TGT_CANCEL( mt ) ) {
rc = ldap_cancel_s( msc->msc_ld, msgid, NULL, NULL );
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment