/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2007 The OpenLDAP Foundation.
+ * Copyright 1998-2010 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout,
LDAPMessage **result ));
static ber_tag_t try_read1msg LDAP_P(( LDAP *ld, ber_int_t msgid,
- int all, LDAPConn **lc, LDAPMessage **result ));
+ int all, LDAPConn *lc, LDAPMessage **result ));
static ber_tag_t build_result_ber LDAP_P(( LDAP *ld, BerElement **bp, LDAPRequest *lr ));
static void merge_error_info LDAP_P(( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ));
static LDAPMessage * chkResponseList LDAP_P(( LDAP *ld, int msgid, int all));
struct timeval *timeout,
LDAPMessage **result )
{
- LDAPMessage *lm = NULL;
int rc;
assert( ld != NULL );
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
-#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;
- }
+ rc = wait4msg( ld, msgid, all, timeout, result );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
}
#endif /* LDAP_DEBUG */
- if ( timeout != NULL ) {
+ if ( timeout != NULL && timeout->tv_sec != -1 ) {
tv0 = *timeout;
tv = *timeout;
tvp = &tv;
}
#endif /* LDAP_DEBUG */
- if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) {
+ if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) {
rc = (*result)->lm_msgtype;
} else {
if ( ber_sockbuf_ctrl( lc->lconn_sb,
LBER_SB_OPT_DATA_READY, NULL ) )
{
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
-#endif
- rc = try_read1msg( ld, msgid, all, &lc, result );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
-#endif
lc_ready = 1;
break;
}
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
#endif
- if ( !lc_ready ) {
+ if ( !lc_ready ) {
+ int err;
rc = ldap_int_select( ld, tvp );
-#ifdef LDAP_DEBUG
if ( rc == -1 ) {
+ err = sock_errno();
+#ifdef LDAP_DEBUG
Debug( LDAP_DEBUG_TRACE,
"ldap_int_select returned -1: errno %d\n",
- sock_errno(), 0, 0 );
- }
+ err, 0, 0 );
#endif
+ }
if ( rc == 0 || ( rc == -1 && (
!LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART)
- || sock_errno() != EINTR ) ) )
+ || err != EINTR ) ) )
{
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
LDAP_TIMEOUT);
rc = LDAP_MSG_X_KEEP_LOOKING; /* select interrupted: loop */
} else {
- rc = LDAP_MSG_X_KEEP_LOOKING;
+ lc_ready = 1;
+ }
+ }
+ if ( lc_ready ) {
+ LDAPConn *lnext;
+ rc = LDAP_MSG_X_KEEP_LOOKING;
#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+ ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
- if ( ld->ld_requests &&
- ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
- ldap_is_write_ready( ld,
- ld->ld_requests->lr_conn->lconn_sb ) )
- {
- ldap_int_flush_request( ld, ld->ld_requests );
- }
+ if ( ld->ld_requests &&
+ ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
+ ldap_is_write_ready( ld,
+ ld->ld_requests->lr_conn->lconn_sb ) )
+ {
+ ldap_int_flush_request( ld, ld->ld_requests );
+ }
#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
- ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
+ ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+ ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
#endif
- for ( lc = ld->ld_conns;
- rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; )
+ for ( lc = ld->ld_conns;
+ rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL;
+ lc = lnext )
+ {
+ if ( lc->lconn_status == LDAP_CONNST_CONNECTED &&
+ ldap_is_read_ready( ld, lc->lconn_sb ) )
{
- if ( lc->lconn_status == LDAP_CONNST_CONNECTED &&
- ldap_is_read_ready( ld, lc->lconn_sb ) )
- {
+ /* Don't let it get freed out from under us */
+ ++lc->lconn_refcnt;
#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
+ ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
#endif
- rc = try_read1msg( ld, msgid, all, &lc, result );
+ rc = try_read1msg( ld, msgid, all, lc, result );
+ lnext = lc->lconn_next;
+
+ /* Only take locks if we're really freeing */
+ if ( lc->lconn_refcnt <= 1 ) {
#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
+ ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#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;
- }
+ ldap_free_connection( ld, lc, 0, 1 );
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+ } else {
+ --lc->lconn_refcnt;
}
-
- /* next conn */
- lc = lc->lconn_next;
- }
#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
+ ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
#endif
+ } else {
+ lnext = lc->lconn_next;
+ }
}
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
+#endif
}
}
LDAP *ld,
ber_int_t msgid,
int all,
- LDAPConn **lcp,
+ LDAPConn *lc,
LDAPMessage **result )
{
BerElement *ber;
ber_len_t len;
int foundit = 0;
LDAPRequest *lr, *tmplr, dummy_lr = { 0 };
- LDAPConn *lc;
BerElement tmpber;
- int rc, refer_cnt, hadref, simple_request;
+ int rc, refer_cnt, hadref, simple_request, err;
ber_int_t lderr;
#ifdef LDAP_CONNECTIONLESS
#endif
assert( ld != NULL );
- assert( lcp != NULL );
- assert( *lcp != NULL );
+ assert( lc != NULL );
#ifdef LDAP_R_COMPILE
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n",
(void *)ld, msgid, all );
- lc = *lcp;
-
retry:
if ( lc->lconn_ber == NULL ) {
lc->lconn_ber = ldap_alloc_ber_with_options( ld );
break;
case LBER_DEFAULT:
+ err = sock_errno();
#ifdef LDAP_DEBUG
Debug( LDAP_DEBUG_CONNS,
"ber_get_next failed.\n", 0, 0, 0 );
#endif
#ifdef EWOULDBLOCK
- if ( sock_errno() == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
+ if ( err == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
#endif
#ifdef EAGAIN
- if ( sock_errno() == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
+ if ( err == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
#endif
ld->ld_errno = LDAP_SERVER_DOWN;
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
-#endif
- ldap_free_connection( ld, lc, 1, 0 );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
-#endif
- lc = *lcp = NULL;
+ --lc->lconn_refcnt;
+ lc->lconn_status = 0;
return -1;
default:
/* id == 0 iff unsolicited notification message (RFC 4511) */
+ /* id < 0 is invalid, just toss it. FIXME: should we disconnect? */
+ if ( id < 0 ) {
+ goto retry_ber;
+ }
+
/* if it's been abandoned, toss it */
if ( id > 0 ) {
if ( ldap_abandoned( ld, id, &idx ) ) {
}
Debug( LDAP_DEBUG_ANY,
- "abandoned/discarded ld %p msgid %ld message type %s\n",
- (void *)ld, (long)id, ldap_int_msgtype2str( tag ) );
+ "abandoned/discarded ld %p msgid %d message type %s\n",
+ (void *)ld, id, ldap_int_msgtype2str( tag ) );
retry_ber:
ber_free( ber, 1 );
}
Debug( LDAP_DEBUG_ANY,
- "no request for response on ld %p msgid %ld message type %s (tossing)\n",
- (void *)ld, (long)id, msg );
+ "no request for response on ld %p msgid %d message type %s (tossing)\n",
+ (void *)ld, id, msg );
goto retry_ber;
}
ber_scanf(ber, "x{");
}
nextresp2:
+ ;
#endif
}
}
Debug( LDAP_DEBUG_TRACE,
- "read1msg: ld %p msgid %ld message type %s\n",
- (void *)ld, (long)lr->lr_msgid, ldap_int_msgtype2str( tag ) );
+ "read1msg: ld %p msgid %d message type %s\n",
+ (void *)ld, id, ldap_int_msgtype2str( tag ) );
if ( id == 0 ) {
/* unsolicited notification message (RFC 4511) */
return( -1 ); /* fatal error */
}
lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */
+ if ( lr->lr_res_matched ) {
+ LDAP_FREE( lr->lr_res_matched );
+ lr->lr_res_matched = NULL;
+ }
} else {
if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) {
{
id = lr->lr_msgid;
tag = lr->lr_res_msgtype;
- Debug( LDAP_DEBUG_TRACE, "request done: ld %p msgid %ld\n",
- (void *)ld, (long) id, 0 );
+ Debug( LDAP_DEBUG_TRACE, "request done: ld %p msgid %d\n",
+ (void *)ld, id, 0 );
Debug( LDAP_DEBUG_TRACE,
"res_errno: %d, res_error: <%s>, "
"res_matched: <%s>\n",
* shouldn't necessarily end the connection
*/
if ( lc != NULL && id != 0 ) {
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
-#endif
- ldap_free_connection( ld, lc, 0, 1 );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
-#endif
- lc = *lcp = NULL;
+ --lc->lconn_refcnt;
+ lc = NULL;
}
}
}
/* get rid of the connection... */
if ( lc != NULL ) {
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
-#endif
- ldap_free_connection( ld, lc, 0, 1 );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
-#endif
- lc = *lcp = NULL;
+ --lc->lconn_refcnt;
}
/* need to return -1, because otherwise
if ( msgid == LDAP_RES_ANY || id == msgid ) {
if ( all == LDAP_MSG_ONE
|| ( newmsg->lm_msgtype != LDAP_RES_SEARCH_RESULT
- && newmsg->lm_msgtype != LDAP_RES_SEARCH_ENTRY
+ && newmsg->lm_msgtype != LDAP_RES_SEARCH_ENTRY
+ && newmsg->lm_msgtype != LDAP_RES_INTERMEDIATE
&& newmsg->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) )
{
*result = newmsg;
goto exit;
}
- Debug( LDAP_DEBUG_TRACE, "adding response ld %p msgid %ld type %ld:\n",
- (void *)ld, (long) newmsg->lm_msgid, (long) newmsg->lm_msgtype );
+ Debug( LDAP_DEBUG_TRACE, "adding response ld %p msgid %d type %ld:\n",
+ (void *)ld, newmsg->lm_msgid, (long) newmsg->lm_msgtype );
/* part of a search response - add to end of list of entries */
l->lm_chain_tail->lm_chain = newmsg;
assert( idxp != NULL );
assert( msgid >= 0 );
- assert( ld->ld_nabandoned >= 0 );
return ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, idxp );
}
/* NOTE: those assertions are repeated in ldap_int_bisect_delete() */
assert( idx >= 0 );
- assert( idx < ld->ld_nabandoned );
+ assert( (unsigned) idx < ld->ld_nabandoned );
assert( ld->ld_abandoned[ idx ] == msgid );
return ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned,