Commit 80d1dba9 authored by Howard Chu's avatar Howard Chu
Browse files

Add LDAP_OPT_CONNECT_CB connection callbacks

parent a225b02f
......@@ -123,6 +123,7 @@ LDAP_BEGIN_DECL
#define LDAP_OPT_SOCKBUF 0x5008 /* sockbuf */
#define LDAP_OPT_DEFBASE 0x5009 /* searchbase */
#define LDAP_OPT_CONNECT_ASYNC 0x5010 /* create connections asynchronously */
#define LDAP_OPT_CONNECT_CB 0x5011 /* connection callbacks */
/* OpenLDAP TLS options */
#define LDAP_OPT_X_TLS 0x6000
......@@ -881,6 +882,27 @@ struct ldap_sync_t {
* End of LDAP sync (RFC4533) API
*/
/*
* Connection callbacks...
*/
struct ldap_conncb;
struct sockaddr;
/* Called after a connection is established */
typedef void (ldap_conn_add_f) LDAP_P(( LDAP *ld, Sockbuf *sb, const char *name, struct sockaddr *addr,
struct ldap_conncb *ctx ));
/* Called before a connection is closed */
typedef void (ldap_conn_del_f) LDAP_P(( LDAP *ld, Sockbuf *sb, struct ldap_conncb *ctx ));
/* Callbacks are pushed on a stack. Last one pushed is first one executed. The
* delete callback is called with a NULL Sockbuf just before freeing the LDAP handle.
*/
typedef struct ldap_conncb {
ldap_conn_add_f *lc_add;
ldap_conn_del_f *lc_del;
void *lc_arg;
} ldap_conncb;
/*
* The API draft spec says we should declare (or cause to be declared)
* 'struct timeval'. We don't. See IETF LDAPext discussions.
......
......@@ -159,6 +159,11 @@ struct ldaptls {
};
#endif
typedef struct ldaplist {
struct ldaplist *ll_next;
void *ll_data;
} ldaplist;
/*
* structure representing get/set'able options
* which have global defaults.
......@@ -237,6 +242,9 @@ struct ldapoptions {
LDAP_URLLIST_PROC *ldo_urllist_proc;
void *ldo_urllist_params;
/* LDAP connection callback stack */
ldaplist *ldo_conn_cbs;
LDAP_BOOLEANS ldo_booleans; /* boolean options */
};
......
......@@ -123,6 +123,7 @@ ldap_create( LDAP **ldp )
ld->ld_options.ldo_sctrls = NULL;
ld->ld_options.ldo_cctrls = NULL;
ld->ld_options.ldo_defludp = NULL;
ld->ld_options.ldo_conn_cbs = NULL;
#ifdef HAVE_CYRUS_SASL
ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
......
......@@ -249,7 +249,22 @@ ldap_get_option(
case LDAP_OPT_CONNECT_ASYNC:
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
return LDAP_OPT_SUCCESS;
case LDAP_OPT_CONNECT_CB:
{
/* Getting deletes the specified callback */
ldaplist **ll = &lo->ldo_conn_cbs;
for (;*ll;ll = &(*ll)->ll_next) {
if ((*ll)->ll_data == outvalue) {
ldaplist *lc = *ll;
*ll = lc->ll_next;
LDAP_FREE(lc);
break;
}
}
}
return LDAP_OPT_SUCCESS;
case LDAP_OPT_RESULT_CODE:
if(ld == NULL) {
/* bad param */
......@@ -734,6 +749,17 @@ ldap_set_option(
case LDAP_OPT_DEBUG_LEVEL:
lo->ldo_debug = * (const int *) invalue;
return LDAP_OPT_SUCCESS;
case LDAP_OPT_CONNECT_CB:
{
/* setting pushes the callback */
ldaplist *ll;
ll = LDAP_MALLOC( sizeof( *ll ));
ll->ll_data = (void *)invalue;
ll->ll_next = lo->ldo_conn_cbs;
lo->ldo_conn_cbs = ll;
}
return LDAP_OPT_SUCCESS;
}
return LDAP_OPT_ERROR;
}
......
......@@ -537,7 +537,19 @@ 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;
}
ldap_pvt_close_socket(ld, s);
......@@ -609,7 +621,19 @@ 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;
}
......
......@@ -350,7 +350,19 @@ 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 {
ldap_pvt_close_socket(ld, s);
}
......
......@@ -642,6 +642,28 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
#endif
/* process connection callbacks */
{
struct ldapoptions *lo;
ldaplist *ll;
ldap_conncb *cb;
lo = &ld->ld_options;
if ( lo->ldo_conn_cbs ) {
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
cb = ll->ll_data;
cb->lc_del( ld, lc->lconn_sb, cb );
}
}
lo = LDAP_INT_GLOBAL_OPT();
if ( lo->ldo_conn_cbs ) {
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
cb = ll->ll_data;
cb->lc_del( ld, lc->lconn_sb, cb );
}
}
}
if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
ldap_mark_select_clear( ld, lc->lconn_sb );
if ( unbind ) {
......
......@@ -112,6 +112,18 @@ ldap_ld_free(
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
/* final close callbacks */
{
ldaplist *ll, *next;
for ( ll = ld->ld_options.ldo_conn_cbs; ll; ll = next ) {
ldap_conncb *cb = ll->ll_data;
next = ll->ll_next;
cb->lc_del( ld, NULL, cb );
LDAP_FREE( ll );
}
}
if ( ld->ld_error != NULL ) {
LDAP_FREE( ld->ld_error );
ld->ld_error = NULL;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment