version 1.124, 2006/03/24 00:18:36
|
version 1.124.2.4, 2006/08/20 17:04:46
|
Line 1
|
Line 1
|
/* result.c - wait for an ldap result */ |
/* result.c - wait for an ldap result */ |
/* $OpenLDAP: pkg/ldap/libraries/libldap/result.c,v 1.123 2006/02/14 22:18:12 kurt Exp $ */ |
/* $OpenLDAP: pkg/ldap/libraries/libldap/result.c,v 1.124.2.3 2006/08/17 23:50:26 kurt Exp $ */ |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
* |
* |
* Copyright 1998-2006 The OpenLDAP Foundation. |
* Copyright 1998-2006 The OpenLDAP Foundation. |
Line 37
|
Line 37
|
* can be found in the file "build/LICENSE-2.0.1" in this distribution |
* can be found in the file "build/LICENSE-2.0.1" in this distribution |
* of OpenLDAP Software. |
* of OpenLDAP Software. |
*/ |
*/ |
/* Portions Copyright (C) The Internet Society (1997) |
/* Portions Copyright (C) The Internet Society (2006) |
* ASN.1 fragments are from RFC 2251; see RFC for full legal notices. |
* ASN.1 fragments are from RFC 4511; see RFC for full legal notices. |
*/ |
*/ |
|
|
/* |
/* |
* LDAPv3 (RFC2251) |
* LDAPv3 (RFC 4511) |
* LDAPResult ::= SEQUENCE { |
* LDAPResult ::= SEQUENCE { |
* resultCode ENUMERATED { ... }, |
* resultCode ENUMERATED { ... }, |
* matchedDN LDAPDN, |
* matchedDN LDAPDN, |
* errorMessage LDAPString, |
* diagnosticMessage LDAPString, |
* referral Referral OPTIONAL |
* referral [3] Referral OPTIONAL |
* } |
* } |
* Referral ::= SEQUENCE OF LDAPURL (one or more) |
* Referral ::= SEQUENCE OF LDAPURL (one or more) |
* LDAPURL ::= LDAPString (limited to URL chars) |
* LDAPURL ::= LDAPString (limited to URL chars) |
Line 140 chkResponseList(
|
Line 140 chkResponseList(
|
int all) |
int all) |
{ |
{ |
LDAPMessage *lm, **lastlm, *nextlm; |
LDAPMessage *lm, **lastlm, *nextlm; |
/* |
|
|
/* |
* Look through the list of responses we have received on |
* Look through the list of responses we have received on |
* this association and see if the response we're interested in |
* this association and see if the response we're interested in |
* is there. If it is, return it. If not, call wait4msg() to |
* is there. If it is, return it. If not, call wait4msg() to |
* wait until it arrives or timeout occurs. |
* wait until it arrives or timeout occurs. |
*/ |
*/ |
|
|
|
#ifdef LDAP_R_COMPILE |
|
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
|
#endif |
|
|
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"ldap_chkResponseList ld %p msgid %d all %d\n", |
"ldap_chkResponseList ld %p msgid %d all %d\n", |
(void *)ld, msgid, all ); |
(void *)ld, msgid, all ); |
|
|
lastlm = &ld->ld_responses; |
lastlm = &ld->ld_responses; |
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { |
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { |
nextlm = lm->lm_next; |
nextlm = lm->lm_next; |
Line 233 wait4msg(
|
Line 239 wait4msg(
|
*tvp; |
*tvp; |
time_t start_time = 0; |
time_t start_time = 0; |
time_t tmp_time; |
time_t tmp_time; |
LDAPConn *lc, *nextlc; |
LDAPConn *lc; |
|
|
assert( ld != NULL ); |
assert( ld != NULL ); |
assert( result != NULL ); |
assert( result != NULL ); |
|
|
|
#ifdef LDAP_R_COMPILE |
|
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
|
#endif |
|
|
#ifdef LDAP_DEBUG |
#ifdef LDAP_DEBUG |
if ( timeout == NULL ) { |
if ( timeout == NULL ) { |
Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (infinite timeout)\n", |
Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (infinite timeout)\n", |
Line 263 wait4msg(
|
Line 273 wait4msg(
|
if ( ldap_debug & LDAP_DEBUG_TRACE ) { |
if ( ldap_debug & LDAP_DEBUG_TRACE ) { |
Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n", |
Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n", |
(void *)ld, msgid, all ); |
(void *)ld, msgid, all ); |
|
#ifdef LDAP_R_COMPILE |
|
ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); |
|
#endif |
ldap_dump_connection( ld, ld->ld_conns, 1 ); |
ldap_dump_connection( ld, ld->ld_conns, 1 ); |
|
#ifdef LDAP_R_COMPILE |
|
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); |
|
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); |
|
#endif |
ldap_dump_requests_and_responses( ld ); |
ldap_dump_requests_and_responses( ld ); |
|
#ifdef LDAP_R_COMPILE |
|
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); |
|
#endif |
} |
} |
#endif /* LDAP_DEBUG */ |
#endif /* LDAP_DEBUG */ |
|
|
if ( (*result = chkResponseList(ld, msgid, all)) != NULL ) { |
if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) { |
rc = (*result)->lm_msgtype; |
rc = (*result)->lm_msgtype; |
|
|
} else { |
} else { |
Line 277 wait4msg(
|
Line 297 wait4msg(
|
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); |
ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); |
#endif |
#endif |
for ( lc = ld->ld_conns; lc != NULL; lc = nextlc ) { |
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { |
nextlc = lc->lconn_next; |
|
if ( ber_sockbuf_ctrl( lc->lconn_sb, |
if ( ber_sockbuf_ctrl( lc->lconn_sb, |
LBER_SB_OPT_DATA_READY, NULL ) ) { |
LBER_SB_OPT_DATA_READY, NULL ) ) |
|
{ |
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); |
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); |
#endif |
#endif |
Line 308 wait4msg(
|
Line 328 wait4msg(
|
|
|
if ( rc == 0 || ( rc == -1 && ( |
if ( rc == 0 || ( rc == -1 && ( |
!LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) |
!LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) |
|| errno != EINTR ))) |
|| errno != EINTR ) ) ) |
{ |
{ |
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : |
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : |
LDAP_TIMEOUT); |
LDAP_TIMEOUT); |
Line 333 wait4msg(
|
Line 353 wait4msg(
|
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); |
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); |
ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); |
ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); |
#endif |
#endif |
for ( lc = ld->ld_conns; rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; |
for ( lc = ld->ld_conns; |
lc = nextlc ) |
rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; ) |
{ |
{ |
nextlc = lc->lconn_next; |
|
if ( lc->lconn_status == LDAP_CONNST_CONNECTED && |
if ( lc->lconn_status == LDAP_CONNST_CONNECTED && |
ldap_is_read_ready( ld, lc->lconn_sb )) |
ldap_is_read_ready( ld, lc->lconn_sb ) ) |
{ |
{ |
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); |
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); |
#endif |
#endif |
rc = try_read1msg( ld, msgid, all, &lc, result ); |
rc = try_read1msg( ld, msgid, all, &lc, result ); |
if ( lc == NULL ) lc = nextlc; |
|
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); |
ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); |
#endif |
#endif |
|
if ( lc == NULL ) { |
|
/* if lc gets free()'d, |
|
* there's no guarantee |
|
* lc->lconn_next is still |
|
* sane; better restart |
|
* (ITS#4405) */ |
|
lc = ld->ld_conns; |
|
|
|
/* don't get to next conn! */ |
|
break; |
|
} |
} |
} |
|
|
|
/* next conn */ |
|
lc = lc->lconn_next; |
} |
} |
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); |
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); |
Line 416 try_read1msg(
|
Line 448 try_read1msg(
|
assert( lcp != NULL ); |
assert( lcp != NULL ); |
assert( *lcp != NULL ); |
assert( *lcp != NULL ); |
|
|
|
#ifdef LDAP_R_COMPILE |
|
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
|
#endif |
|
|
Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n", |
Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n", |
(void *)ld, msgid, all ); |
(void *)ld, msgid, all ); |
|
|
Line 423 try_read1msg(
|
Line 459 try_read1msg(
|
|
|
retry: |
retry: |
if ( lc->lconn_ber == NULL ) { |
if ( lc->lconn_ber == NULL ) { |
lc->lconn_ber = ldap_alloc_ber_with_options(ld); |
lc->lconn_ber = ldap_alloc_ber_with_options( ld ); |
|
|
if( lc->lconn_ber == NULL ) { |
if( lc->lconn_ber == NULL ) { |
return -1; |
return -1; |
Line 439 retry:
|
Line 475 retry:
|
if ( LDAP_IS_UDP(ld) ) { |
if ( LDAP_IS_UDP(ld) ) { |
struct sockaddr from; |
struct sockaddr from; |
ber_int_sb_read( lc->lconn_sb, &from, sizeof(struct sockaddr) ); |
ber_int_sb_read( lc->lconn_sb, &from, sizeof(struct sockaddr) ); |
if (ld->ld_options.ldo_version == LDAP_VERSION2) isv2=1; |
if (ld->ld_options.ldo_version == LDAP_VERSION2) isv2 = 1; |
} |
} |
nextresp3: |
nextresp3: |
#endif |
#endif |
tag = ber_get_next( lc->lconn_sb, &len, ber ); |
tag = ber_get_next( lc->lconn_sb, &len, ber ); |
if ( tag == LDAP_TAG_MESSAGE ) { |
switch ( tag ) { |
|
case LDAP_TAG_MESSAGE: |
/* |
/* |
* We read a complete message. |
* We read a complete message. |
* The connection should no longer need this ber. |
* The connection should no longer need this ber. |
*/ |
*/ |
lc->lconn_ber = NULL; |
lc->lconn_ber = NULL; |
} |
break; |
if ( tag != LDAP_TAG_MESSAGE ) { |
|
if ( tag == LBER_DEFAULT) { |
case LBER_DEFAULT: |
#ifdef LDAP_DEBUG |
#ifdef LDAP_DEBUG |
Debug( LDAP_DEBUG_CONNS, |
Debug( LDAP_DEBUG_CONNS, |
"ber_get_next failed.\n", 0, 0, 0 ); |
"ber_get_next failed.\n", 0, 0, 0 ); |
#endif |
#endif |
#ifdef EWOULDBLOCK |
#ifdef EWOULDBLOCK |
if (errno==EWOULDBLOCK) return LDAP_MSG_X_KEEP_LOOKING; |
if ( errno == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING; |
#endif |
#endif |
#ifdef EAGAIN |
#ifdef EAGAIN |
if (errno == EAGAIN) return LDAP_MSG_X_KEEP_LOOKING; |
if ( errno == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING; |
#endif |
#endif |
ld->ld_errno = LDAP_SERVER_DOWN; |
ld->ld_errno = LDAP_SERVER_DOWN; |
return -1; |
return -1; |
} |
|
|
default: |
ld->ld_errno = LDAP_LOCAL_ERROR; |
ld->ld_errno = LDAP_LOCAL_ERROR; |
return -1; |
return -1; |
} |
} |
Line 493 retry_ber:
|
Line 531 retry_ber:
|
if ( lr == NULL ) { |
if ( lr == NULL ) { |
Debug( LDAP_DEBUG_ANY, |
Debug( LDAP_DEBUG_ANY, |
"no request for response on ld %p msgid %ld (tossing)\n", |
"no request for response on ld %p msgid %ld (tossing)\n", |
(void *)ld, (long) id, 0 ); |
(void *)ld, (long)id, 0 ); |
goto retry_ber; |
goto retry_ber; |
} |
} |
#ifdef LDAP_CONNECTIONLESS |
#ifdef LDAP_CONNECTIONLESS |
Line 546 nextresp2:
|
Line 584 nextresp2:
|
if ( refer_cnt > 0 ) { |
if ( refer_cnt > 0 ) { |
/* sucessfully chased reference */ |
/* sucessfully chased reference */ |
/* If haven't got end search, set chasing referrals */ |
/* If haven't got end search, set chasing referrals */ |
if( lr->lr_status != LDAP_REQST_COMPLETED) { |
if ( lr->lr_status != LDAP_REQST_COMPLETED ) { |
lr->lr_status = LDAP_REQST_CHASINGREFS; |
lr->lr_status = LDAP_REQST_CHASINGREFS; |
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"read1msg: search ref chased, " |
"read1msg: search ref chased, " |
Line 604 nextresp2:
|
Line 642 nextresp2:
|
* Note: refs arrary is freed by ldap_chase_v3referrals |
* Note: refs arrary is freed by ldap_chase_v3referrals |
*/ |
*/ |
refer_cnt = ldap_chase_v3referrals( ld, lr, refs, |
refer_cnt = ldap_chase_v3referrals( ld, lr, refs, |
0, &lr->lr_res_error, &hadref ); |
0, &lr->lr_res_error, &hadref ); |
lr->lr_status = LDAP_REQST_COMPLETED; |
lr->lr_status = LDAP_REQST_COMPLETED; |
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"read1msg: referral chased, mark request completed, ld %p msgid %d\n", |
"read1msg: referral chased, mark request completed, ld %p msgid %d\n", |
Line 657 nextresp2:
|
Line 695 nextresp2:
|
!= LBER_ERROR ) |
!= LBER_ERROR ) |
{ |
{ |
if ( lr_res_error != NULL ) { |
if ( lr_res_error != NULL ) { |
{ |
if ( lr->lr_res_error != NULL ) { |
if ( lr->lr_res_error != NULL ) { |
(void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error ); |
(void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error ); |
LDAP_FREE( (char *)lr_res_error ); |
LDAP_FREE( (char *)lr_res_error ); |
} else { |
} else { |
lr->lr_res_error = lr_res_error; |
lr->lr_res_error = lr_res_error; |
|
} |
|
} |
} |
lr_res_error = NULL; |
lr_res_error = NULL; |
} |
} |
Line 754 nextresp2:
|
Line 790 nextresp2:
|
|
|
/* Check if all requests are finished, lr is now parent */ |
/* Check if all requests are finished, lr is now parent */ |
tmplr = lr; |
tmplr = lr; |
if (tmplr->lr_status == LDAP_REQST_COMPLETED) { |
if ( tmplr->lr_status == LDAP_REQST_COMPLETED ) { |
for ( tmplr=lr->lr_child; |
for ( tmplr=lr->lr_child; |
tmplr != NULL; |
tmplr != NULL; |
tmplr=tmplr->lr_refnext) |
tmplr=tmplr->lr_refnext) |
{ |
{ |
if( tmplr->lr_status != LDAP_REQST_COMPLETED) break; |
if ( tmplr->lr_status != LDAP_REQST_COMPLETED ) break; |
} |
} |
} |
} |
|
|
Line 779 lr->lr_res_matched ? lr->lr_res_matched
|
Line 815 lr->lr_res_matched ? lr->lr_res_matched
|
ber_free( ber, 1 ); |
ber_free( ber, 1 ); |
ber = NULL; |
ber = NULL; |
if ( build_result_ber( ld, &ber, lr ) |
if ( build_result_ber( ld, &ber, lr ) |
== LBER_ERROR ) { |
== LBER_ERROR ) |
|
{ |
rc = -1; /* fatal error */ |
rc = -1; /* fatal error */ |
} |
} |
} |
} |
Line 1159 ldap_msgdelete( LDAP *ld, int msgid )
|
Line 1196 ldap_msgdelete( LDAP *ld, int msgid )
|
|
|
|
|
/* |
/* |
|
* ldap_abandoned |
|
* |
* return 1 if message msgid is waiting to be abandoned, 0 otherwise |
* return 1 if message msgid is waiting to be abandoned, 0 otherwise |
|
* |
|
* expects ld_res_mutex to be locked |
*/ |
*/ |
static int |
static int |
ldap_abandoned( LDAP *ld, ber_int_t msgid ) |
ldap_abandoned( LDAP *ld, ber_int_t msgid ) |
{ |
{ |
int i; |
int i; |
|
|
|
#ifdef LDAP_R_COMPILE |
|
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
|
#endif |
|
|
if ( ld->ld_abandoned == NULL ) |
if ( ld->ld_abandoned == NULL ) |
return( 0 ); |
return( 0 ); |
|
|
Line 1177 ldap_abandoned( LDAP *ld, ber_int_t msgi
|
Line 1222 ldap_abandoned( LDAP *ld, ber_int_t msgi
|
} |
} |
|
|
|
|
|
/* |
|
* ldap_mark_abandoned |
|
* |
|
* expects ld_res_mutex to be locked |
|
*/ |
static int |
static int |
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid ) |
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid ) |
{ |
{ |
int i; |
int i; |
|
|
|
#ifdef LDAP_R_COMPILE |
|
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
|
#endif |
|
|
if ( ld->ld_abandoned == NULL ) |
if ( ld->ld_abandoned == NULL ) |
return( -1 ); |
return( -1 ); |
|
|