Example #1
0
static int
wait4msg(
	LDAP *ld,
	ber_int_t msgid,
	int all,
	struct timeval *timeout,
	LDAPMessage **result )
{
	int		rc;
	struct timeval	tv = { 0 },
			tv0 = { 0 },
			start_time_tv = { 0 },
			*tvp = NULL;
	LDAPConn	*lc;

	assert( ld != NULL );
	assert( result != NULL );

#ifdef LDAP_R_COMPILE
	LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
#endif

	if ( timeout == NULL && ld->ld_options.ldo_tm_api.tv_sec >= 0 ) {
		tv = ld->ld_options.ldo_tm_api;
		timeout = &tv;
	}

#ifdef LDAP_DEBUG
	if ( timeout == NULL ) {
		Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (infinite timeout)\n",
			(void *)ld, msgid, 0 );
	} else {
		Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (timeout %ld usec)\n",
			(void *)ld, msgid, (long)timeout->tv_sec * 1000000 + timeout->tv_usec );
	}
#endif /* LDAP_DEBUG */

	if ( timeout != NULL ) {
		tv0 = *timeout;
		tv = *timeout;
		tvp = &tv;
#ifdef HAVE_GETTIMEOFDAY
		gettimeofday( &start_time_tv, NULL );
#else /* ! HAVE_GETTIMEOFDAY */
		time( &start_time_tv.tv_sec );
		start_time_tv.tv_usec = 0;
#endif /* ! HAVE_GETTIMEOFDAY */
	}
		    
	rc = LDAP_MSG_X_KEEP_LOOKING;
	while ( rc == LDAP_MSG_X_KEEP_LOOKING ) {
#ifdef LDAP_DEBUG
		if ( ldap_debug & LDAP_DEBUG_TRACE ) {
			Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n",
				(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 );
#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 );
#ifdef LDAP_R_COMPILE
			ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
		}
#endif /* LDAP_DEBUG */

		if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) {
			rc = (*result)->lm_msgtype;

		} else {
			int lc_ready = 0;

#ifdef LDAP_R_COMPILE
			ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
#endif
			for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
				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;
				}
			}
#ifdef LDAP_R_COMPILE
			ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
#endif

			if ( !lc_ready ) {
				rc = ldap_int_select( ld, tvp );
#ifdef LDAP_DEBUG
				if ( rc == -1 ) {
					Debug( LDAP_DEBUG_TRACE,
						"ldap_int_select returned -1: errno %d\n",
						sock_errno(), 0, 0 );
				}
#endif

				if ( rc == 0 || ( rc == -1 && (
					!LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART)
						|| sock_errno() != EINTR ) ) )
				{
					ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
						LDAP_TIMEOUT);
					return( rc );
				}

				if ( rc == -1 ) {
					rc = LDAP_MSG_X_KEEP_LOOKING;	/* select interrupted: loop */

				} else {
					rc = LDAP_MSG_X_KEEP_LOOKING;
#ifdef LDAP_R_COMPILE
					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 );
					}
#ifdef LDAP_R_COMPILE
					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; )
					{
						if ( lc->lconn_status == LDAP_CONNST_CONNECTED &&
							ldap_is_read_ready( ld, lc->lconn_sb ) )
						{
#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
							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
					ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
#endif
				}
			}
		}

		if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
			struct timeval	curr_time_tv = { 0 },
					delta_time_tv = { 0 };

#ifdef HAVE_GETTIMEOFDAY
			gettimeofday( &curr_time_tv, NULL );
#else /* ! HAVE_GETTIMEOFDAY */
			time( &curr_time_tv.tv_sec );
			curr_time_tv.tv_usec = 0;
#endif /* ! HAVE_GETTIMEOFDAY */

			/* delta_time = tmp_time - start_time */
			delta_time_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec;
			delta_time_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
			if ( delta_time_tv.tv_usec < 0 ) {
				delta_time_tv.tv_sec--;
				delta_time_tv.tv_usec += 1000000;
			}

			/* tv0 < delta_time ? */
			if ( ( tv0.tv_sec < delta_time_tv.tv_sec ) ||
			     ( ( tv0.tv_sec == delta_time_tv.tv_sec ) && ( tv0.tv_usec < delta_time_tv.tv_usec ) ) )
			{
				rc = 0; /* timed out */
				ld->ld_errno = LDAP_TIMEOUT;
				break;
			}

			/* tv0 -= delta_time */
			tv0.tv_sec -= delta_time_tv.tv_sec;
			tv0.tv_usec -= delta_time_tv.tv_usec;
			if ( tv0.tv_usec < 0 ) {
				tv0.tv_sec--;
				tv0.tv_usec += 1000000;
			}

			tv.tv_sec = tv0.tv_sec;
			tv.tv_usec = tv0.tv_usec;

			Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld s %ld us to go\n",
				(void *)ld, (long) tv.tv_sec, (long) tv.tv_usec );

			start_time_tv.tv_sec = curr_time_tv.tv_sec;
			start_time_tv.tv_usec = curr_time_tv.tv_usec;
		}
	}

	return( rc );
}
Example #2
0
/* protected by res_mutex */
static int
wait4msg(
	LDAP *ld,
	ber_int_t msgid,
	int all,
	struct timeval *timeout,
	LDAPMessage **result )
{
	int		rc;
	struct timeval	tv = { 0 },
			tv0 = { 0 },
			start_time_tv = { 0 },
			*tvp = NULL;
	LDAPConn	*lc;

	assert( ld != NULL );
	assert( result != NULL );

	LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );

	if ( timeout == NULL && ld->ld_options.ldo_tm_api.tv_sec >= 0 ) {
		tv = ld->ld_options.ldo_tm_api;
		timeout = &tv;
	}

#ifdef LDAP_DEBUG
	if ( timeout == NULL ) {
		Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (infinite timeout)\n",
			(void *)ld, msgid, 0 );
	} else {
		Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (timeout %ld usec)\n",
			(void *)ld, msgid, (long)timeout->tv_sec * 1000000 + timeout->tv_usec );
	}
#endif /* LDAP_DEBUG */

	if ( timeout != NULL && timeout->tv_sec != -1 ) {
		tv0 = *timeout;
		tv = *timeout;
		tvp = &tv;
#ifdef HAVE_GETTIMEOFDAY
		gettimeofday( &start_time_tv, NULL );
#else /* ! HAVE_GETTIMEOFDAY */
		start_time_tv.tv_sec = time( NULL );
		start_time_tv.tv_usec = 0;
#endif /* ! HAVE_GETTIMEOFDAY */
	}
		    
	rc = LDAP_MSG_X_KEEP_LOOKING;
	while ( rc == LDAP_MSG_X_KEEP_LOOKING ) {
#ifdef LDAP_DEBUG
		if ( ldap_debug & LDAP_DEBUG_TRACE ) {
			Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n",
				(void *)ld, msgid, all );
			ldap_dump_connection( ld, ld->ld_conns, 1 );
			LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
			ldap_dump_requests_and_responses( ld );
			LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
		}
#endif /* LDAP_DEBUG */

		if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) {
			rc = (*result)->lm_msgtype;

		} else {
			int lc_ready = 0;

			LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
			for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
				if ( ber_sockbuf_ctrl( lc->lconn_sb,
					LBER_SB_OPT_DATA_READY, NULL ) )
				{
					lc_ready = 2;	/* ready at ber level, not socket level */
					break;
				}
			}

			if ( !lc_ready ) {
				int err;
				rc = ldap_int_select( ld, tvp );
				if ( rc == -1 ) {
					err = sock_errno();
#ifdef LDAP_DEBUG
					Debug( LDAP_DEBUG_TRACE,
						"ldap_int_select returned -1: errno %d\n",
						err, 0, 0 );
#endif
				}

				if ( rc == 0 || ( rc == -1 && (
					!LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART)
						|| err != EINTR ) ) )
				{
					ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
						LDAP_TIMEOUT);
					LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
					return( rc );
				}

				if ( rc == -1 ) {
					rc = LDAP_MSG_X_KEEP_LOOKING;	/* select interrupted: loop */

				} else {
					lc_ready = 1;
				}
			}
			if ( lc_ready ) {
				LDAPConn *lnext;
				int serviced = 0;
				rc = LDAP_MSG_X_KEEP_LOOKING;
				LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
				if ( ld->ld_requests &&
					ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
					ldap_is_write_ready( ld,
						ld->ld_requests->lr_conn->lconn_sb ) )
				{
					serviced = 1;
					ldap_int_flush_request( ld, ld->ld_requests );
				}
				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 ) )
					{
						serviced = 1;
						/* Don't let it get freed out from under us */
						++lc->lconn_refcnt;
						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 ) {
							ldap_free_connection( ld, lc, 0, 1 );
						} else {
							--lc->lconn_refcnt;
						}
					} else {
						lnext = lc->lconn_next;
					}
				}
				LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
				/* Quit looping if no one handled any socket events */
				if (!serviced && lc_ready == 1)
					rc = -1;
			}
			LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
		}

		if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
			struct timeval	curr_time_tv = { 0 },
					delta_time_tv = { 0 };

#ifdef HAVE_GETTIMEOFDAY
			gettimeofday( &curr_time_tv, NULL );
#else /* ! HAVE_GETTIMEOFDAY */
			curr_time_tv.tv_sec = time( NULL );
			curr_time_tv.tv_usec = 0;
#endif /* ! HAVE_GETTIMEOFDAY */

			/* delta_time = tmp_time - start_time */
			delta_time_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec;
			delta_time_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
			if ( delta_time_tv.tv_usec < 0 ) {
				delta_time_tv.tv_sec--;
				delta_time_tv.tv_usec += 1000000;
			}

			/* tv0 < delta_time ? */
			if ( ( tv0.tv_sec < delta_time_tv.tv_sec ) ||
			     ( ( tv0.tv_sec == delta_time_tv.tv_sec ) && ( tv0.tv_usec < delta_time_tv.tv_usec ) ) )
			{
				rc = 0; /* timed out */
				ld->ld_errno = LDAP_TIMEOUT;
				break;
			}

			/* tv0 -= delta_time */
			tv0.tv_sec -= delta_time_tv.tv_sec;
			tv0.tv_usec -= delta_time_tv.tv_usec;
			if ( tv0.tv_usec < 0 ) {
				tv0.tv_sec--;
				tv0.tv_usec += 1000000;
			}

			tv.tv_sec = tv0.tv_sec;
			tv.tv_usec = tv0.tv_usec;

			Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld s %ld us to go\n",
				(void *)ld, (long) tv.tv_sec, (long) tv.tv_usec );

			start_time_tv.tv_sec = curr_time_tv.tv_sec;
			start_time_tv.tv_usec = curr_time_tv.tv_usec;
		}
	}

	return( rc );
}