X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fresult.c;h=16189ef36e2246ed9218a774f48043cc63054438;hb=b4243bc119b2f88318103176c7c671662c9ff371;hp=3b2a0812206c60959e208b8df1003c64133cf898;hpb=8e6062eb828028b62b3ddbb899fd82c58b17dbcc;p=openldap diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index 3b2a081220..16189ef36e 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -74,9 +74,11 @@ static LDAPMessage * chkResponseList LDAP_P(( LDAP *ld, int msgid, int all)); * with msgid. If all is LDAP_MSG_ONE (0) the first message with id * msgid will be accepted, otherwise, ldap_result will wait for all * responses with id msgid and then return a pointer to the entire list - * of messages. This is only useful for search responses, which can be - * of two message types (zero or more entries, followed by an - * ldap result). The type of the first message received is returned. + * of messages. In general, this is only useful for search responses, + * which can be of three message types (zero or more entries, zero or + * search references, followed by an ldap result). An extension to + * LDAPv3 allows partial extended responses to be returned in response + * to any request. The type of the first message received is returned. * When waiting, any messages that have been abandoned are discarded. * * Example: @@ -118,9 +120,10 @@ ldap_result( } static LDAPMessage * -chkResponseList( LDAP *ld, - int msgid, - int all) +chkResponseList( + LDAP *ld, + int msgid, + int all) { LDAPMessage *lm, *lastlm, *nextlm; /* @@ -130,14 +133,21 @@ chkResponseList( LDAP *ld, * wait until it arrives or timeout occurs. */ + Debug( LDAP_DEBUG_TRACE, + "ldap_chkResponseList for msgid=%d, all=%d\n", + msgid, all, 0 ); lastlm = NULL; for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { nextlm = lm->lm_next; if ( ldap_abandoned( ld, lm->lm_msgid ) ) { + Debug( LDAP_DEBUG_TRACE, + "ldap_chkResponseList msg abandoned, msgid %d\n", + msgid, 0, 0 ); ldap_mark_abandoned( ld, lm->lm_msgid ); if ( lastlm == NULL ) { + /* Remove first entry in list */ ld->ld_responses = lm->lm_next; } else { lastlm->lm_next = nextlm; @@ -151,16 +161,17 @@ chkResponseList( LDAP *ld, if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { LDAPMessage *tmp; - if ( all == LDAP_MSG_ONE - || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT - && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE /* LDAPv3 */ - && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY - && lm->lm_msgtype != LDAP_RES_EXTENDED_PARTIAL) ) + if ( all == LDAP_MSG_ONE || msgid == LDAP_RES_UNSOLICITED ) { break; + } for ( tmp = lm; tmp != NULL; tmp = tmp->lm_chain ) { - if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) + if ( tmp->lm_msgtype != LDAP_RES_SEARCH_ENTRY + && tmp->lm_msgtype != LDAP_RES_SEARCH_REFERENCE + && tmp->lm_msgtype != LDAP_RES_EXTENDED_PARTIAL ) + { break; + } } if ( tmp == NULL ) { @@ -171,7 +182,9 @@ chkResponseList( LDAP *ld, } lastlm = lm; } + if ( lm != NULL ) { + /* Found an entry, remove it from the list */ if ( lastlm == NULL ) { ld->ld_responses = (all == LDAP_MSG_ONE && lm->lm_chain != NULL ? lm->lm_chain : lm->lm_next); @@ -179,15 +192,26 @@ chkResponseList( LDAP *ld, lastlm->lm_next = (all == LDAP_MSG_ONE && lm->lm_chain != NULL ? lm->lm_chain : lm->lm_next); } - if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) - { + if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) { lm->lm_chain->lm_next = lm->lm_next; lm->lm_chain = NULL; } lm->lm_next = NULL; } + +#ifdef LDAP_DEBUG + if( lm == NULL) { + Debug( LDAP_DEBUG_TRACE, + "ldap_chkResponseList returns NULL\n", 0, 0, 0); + } else { + Debug( LDAP_DEBUG_TRACE, + "ldap_chkResponseList returns msgid %d, type 0x%02lu\n", + lm->lm_msgid, (unsigned long) lm->lm_msgtype, 0); + } +#endif return lm; } + static int wait4msg( LDAP *ld, @@ -226,61 +250,65 @@ wait4msg( rc = -2; while ( rc == -2 ) { #ifdef LDAP_DEBUG + Debug( LDAP_DEBUG_TRACE, "wait4msg continue, msgid %d, all %d\n", + msgid, all, 0 ); if ( ldap_debug & LDAP_DEBUG_TRACE ) { ldap_dump_connection( ld, ld->ld_conns, 1 ); ldap_dump_requests_and_responses( ld ); } #endif /* LDAP_DEBUG */ - for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { - if ( ber_sockbuf_ctrl( lc->lconn_sb, - LBER_SB_OPT_DATA_READY, NULL ) ) { - if( (*result = chkResponseList(ld, msgid, all)) == NULL ) { - rc = try_read1msg( ld, msgid, all, lc->lconn_sb, - lc, result ); - } else { - rc = (*result)->lm_msgtype; - } - break; - } - } - if ( lc == NULL ) { - rc = do_ldap_select( ld, tvp ); + if( (*result = chkResponseList(ld, msgid, all)) != NULL ) { + rc = (*result)->lm_msgtype; + } else { + + for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { + if ( ber_sockbuf_ctrl( lc->lconn_sb, + LBER_SB_OPT_DATA_READY, NULL ) ) { + rc = try_read1msg( ld, msgid, all, lc->lconn_sb, + lc, result ); + break; + } + } + + if ( lc == NULL ) { + rc = ldap_int_select( ld, tvp ); #ifdef LDAP_DEBUG - if ( rc == -1 ) { - Debug( LDAP_DEBUG_TRACE, - "do_ldap_select returned -1: errno %d\n", - errno, 0, 0 ); - } + if ( rc == -1 ) { + Debug( LDAP_DEBUG_TRACE, + "ldap_int_select returned -1: errno %d\n", + errno, 0, 0 ); + } #endif - if ( rc == 0 || ( rc == -1 && ( - !LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) - || errno != EINTR ))) - { - ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : - LDAP_TIMEOUT); - return( rc ); - } - - if ( rc == -1 ) { - rc = -2; /* select interrupted: loop */ - } else { - rc = -2; - for ( lc = ld->ld_conns; rc == -2 && lc != NULL; - lc = nextlc ) { - nextlc = lc->lconn_next; - if ( lc->lconn_status == - LDAP_CONNST_CONNECTED && - ldap_is_read_ready( ld, - lc->lconn_sb )) { - rc = try_read1msg( ld, msgid, all, - lc->lconn_sb, lc, result ); - } - } - } + if ( rc == 0 || ( rc == -1 && ( + !LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) + || errno != EINTR ))) + { + ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : + LDAP_TIMEOUT); + return( rc ); + } + + if ( rc == -1 ) { + rc = -2; /* select interrupted: loop */ + } else { + rc = -2; + for ( lc = ld->ld_conns; rc == -2 && lc != NULL; + lc = nextlc ) { + nextlc = lc->lconn_next; + if ( lc->lconn_status == + LDAP_CONNST_CONNECTED && + ldap_is_read_ready( ld, + lc->lconn_sb )) { + rc = try_read1msg( ld, msgid, all, + lc->lconn_sb, lc, result ); + } + } + } + } } if ( rc == -2 && tvp != NULL ) { @@ -307,7 +335,7 @@ try_read1msg( ber_int_t msgid, int all, Sockbuf *sb, - LDAPConn *lc, + LDAPConn *lc, LDAPMessage **result ) { BerElement *ber; @@ -340,10 +368,16 @@ try_read1msg( } ber = lc->lconn_ber; - assert( BER_VALID (ber) ); + assert( LBER_VALID (ber) ); /* get the next message */ errno = 0; +#ifdef LDAP_CONNECTIONLESS + if ( LDAP_IS_UDP(ld) ) { + struct sockaddr from; + ber_int_sb_read(sb, &from, sizeof(struct sockaddr)); + } +#endif if ( (tag = ber_get_next( sb, &len, ber )) != LDAP_TAG_MESSAGE ) { if ( tag == LBER_DEFAULT) { @@ -391,7 +425,12 @@ try_read1msg( ber_free( ber, 1 ); return( -2 ); /* continue looking */ } - +#ifdef LDAP_CONNECTIONLESS + if (LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) { + struct berval blank; + ber_scanf(ber, "m{", &blank); + } +#endif /* the message type */ if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; @@ -399,7 +438,8 @@ try_read1msg( return( -1 ); } - Debug( LDAP_DEBUG_TRACE, "ldap_read: message type %s msgid %ld, original id %ld\n", + Debug( LDAP_DEBUG_TRACE, + "ldap_read: message type %s msgid %ld, original id %ld\n", ldap_int_msgtype2str( tag ), (long) lr->lr_msgid, (long) lr->lr_origid ); @@ -507,14 +547,13 @@ try_read1msg( tmpber = *ber; /* struct copy */ if ( v3ref == 1 ) { ; /* V3 search reference or V3 referral sucessfully chased */ - } else - if ( ber_scanf( &tmpber, "{iaa}", &lderr, + } else if ( ber_scanf( &tmpber, "{iaa}", &lderr, &lr->lr_res_matched, &lr->lr_res_error ) != LBER_ERROR ) { if ( lderr != LDAP_SUCCESS ) { /* referrals are in error string */ refer_cnt = ldap_chase_referrals( ld, lr, - &lr->lr_res_error, &hadref ); + &lr->lr_res_error, -1, &hadref ); lr->lr_status = LDAP_REQST_COMPLETED; Debug( LDAP_DEBUG_TRACE, "read1msg: V2 referral chased, mark request completed, id = %d\n", lr->lr_msgid, 0, 0); @@ -570,9 +609,12 @@ Debug( LDAP_DEBUG_TRACE, } /* Check if all requests are finished, lr is now parent */ - for(tmplr=lr ; tmplr != NULL; tmplr=tmplr->lr_refnext) { + tmplr = lr; + if (tmplr->lr_status == LDAP_REQST_COMPLETED) { + for(tmplr=lr->lr_child; tmplr != NULL; tmplr=tmplr->lr_refnext) { if( tmplr->lr_status != LDAP_REQST_COMPLETED) { break; + } } }