Connect callbacks need error recovery checks

This commit is contained in:
Howard Chu 2008-08-15 10:23:29 +00:00
parent 80d1dba901
commit baad2b249d
3 changed files with 69 additions and 42 deletions

View File

@ -531,6 +531,9 @@ LDAP_F (void) ldap_mark_select_clear( LDAP *ld, Sockbuf *sb );
LDAP_F (int) ldap_is_read_ready( LDAP *ld, Sockbuf *sb );
LDAP_F (int) ldap_is_write_ready( LDAP *ld, Sockbuf *sb );
LDAP_F (int) ldap_int_connect_cbs( LDAP *ld, Sockbuf *sb,
ber_socket_t *s, const char *name, struct sockaddr *addr );
/*
* in os-local.c
*/

View File

@ -424,6 +424,56 @@ ldap_pvt_inet_aton( const char *host, struct in_addr *in)
}
#endif
int
ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, const char *host, struct sockaddr *addr)
{
struct ldapoptions *lo;
ldaplist *ll;
ldap_conncb *cb;
int rc;
ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s );
/* Invoke all handle-specific callbacks first */
lo = &ld->ld_options;
for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
cb = ll->ll_data;
rc = cb->lc_add( ld, sb, host, addr, cb );
/* on any failure, call the teardown functions for anything
* that previously succeeded
*/
if ( rc ) {
ldaplist *l2;
for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) {
cb = l2->ll_data;
cb->lc_del( ld, sb, cb );
}
/* a failure might have implicitly closed the fd */
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s );
return rc;
}
}
lo = LDAP_INT_GLOBAL_OPT();
for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
cb = ll->ll_data;
rc = cb->lc_add( ld, sb, host, addr, cb );
if ( rc ) {
ldaplist *l2;
for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) {
cb = l2->ll_data;
cb->lc_del( ld, sb, cb );
}
lo = &ld->ld_options;
for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) {
cb = l2->ll_data;
cb->lc_del( ld, sb, cb );
}
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s );
return rc;
}
}
return 0;
}
int
ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
@ -537,20 +587,11 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
rc = ldap_pvt_connect( ld, s,
sai->ai_addr, sai->ai_addrlen, async );
if ( rc == 0 || rc == -2 ) {
ldaplist *ll;
struct ldapoptions *lo;
ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s );
lo = &ld->ld_options;
for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
ldap_conncb *cb = ll->ll_data;
cb->lc_add( ld, sb, host, sai->ai_addr, cb );
}
lo = LDAP_INT_GLOBAL_OPT();
for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
ldap_conncb *cb = ll->ll_data;
cb->lc_add( ld, sb, host, sai->ai_addr, cb );
}
break;
err = ldap_int_connect_cbs( ld, sb, &s, host, sai->ai_addr );
if ( err )
rc = err;
else
break;
}
ldap_pvt_close_socket(ld, s);
}
@ -621,20 +662,11 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
async);
if ( (rc == 0) || (rc == -2) ) {
ldaplist *ll;
struct ldapoptions *lo;
ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s );
lo = &ld->ld_options;
for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
ldap_conncb *cb = ll->ll_data;
cb->lc_add( ld, sb, host, (struct sockaddr *)&sin, cb );
}
lo = LDAP_INT_GLOBAL_OPT();
for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
ldap_conncb *cb = ll->ll_data;
cb->lc_add( ld, sb, host, (struct sockaddr *)&sin, cb );
}
break;
i = ldap_int_connect_cbs( ld, sb, &s, host, (struct sockaddr *)&sin );
if ( i )
rc = i;
else
break;
}
ldap_pvt_close_socket(ld, s);

View File

@ -350,20 +350,12 @@ ldap_connect_to_path(LDAP *ld, Sockbuf *sb, const char *path, int async)
rc = ldap_pvt_connect(ld, s, &server, async);
if (rc == 0) {
ldaplist *ll;
struct ldapoptions *lo;
ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, (void *)&s );
lo = &ld->ld_options;
for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
ldap_conncb *cb = ll->ll_data;
cb->lc_add( ld, sb, path, (struct sockaddr *)&server, cb );
}
lo = LDAP_INT_GLOBAL_OPT();
for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
ldap_conncb *cb = ll->ll_data;
cb->lc_add( ld, sb, path, (struct sockaddr *)&server, cb );
}
} else {
int err;
err = ldap_int_connect_cbs( ld, sb, &s, path, (struct sockaddr *)&server );
if ( err )
rc = err;
}
if ( rc ) {
ldap_pvt_close_socket(ld, s);
}
return rc;