]> git.sur5r.net Git - openldap/commitdiff
Add LDAP_OPT_CONNECT_CB connection callbacks
authorHoward Chu <hyc@openldap.org>
Thu, 14 Aug 2008 04:54:32 +0000 (04:54 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 14 Aug 2008 04:54:32 +0000 (04:54 +0000)
include/ldap.h
libraries/libldap/ldap-int.h
libraries/libldap/open.c
libraries/libldap/options.c
libraries/libldap/os-ip.c
libraries/libldap/os-local.c
libraries/libldap/request.c
libraries/libldap/unbind.c

index fe2934366bad92276523a07945c03efa0e5472d9..840378c449d6493d00de1e4fd3c3f13f970d1f51 100644 (file)
@@ -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.
index f13de68fd69ab05db202f8f22a8669056d1b4e27..62043d60cd2c561948759908cb9208556c2af976 100644 (file)
@@ -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 */
 };
 
index 6dec230650aacb25152c470402ebbad3ad46202f..8bc8c39350e8dd3151f42ee117b700ea9d772d8c 100644 (file)
@@ -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
index b4224bc1f16b5af5e5d0f986c423dee74733d73f..9f1e9f1bc7ed22c7f183b507f5222f75c05682a0 100644 (file)
@@ -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;
 }
index b70d60dda2908693d06464b6ead819b836e93e14..8946c0561f0ce2e07f5986944be1ed14e4e4ac0e 100644 (file)
@@ -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;
                }
 
index 0f3c1ee34d548387c03b9b734687a50b60437268..c0f21430bb99eae5ee08ef1559669f7405068806 100644 (file)
@@ -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);
        }
index 31d72ca0e2835b810fcc0d39de133b16d4707d3a..8d92aa743d0835cd4baad656ce5623cf9e9f2c02 100644 (file)
@@ -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 ) {
index 42277bb6f11eb377ff20b43c5a9e86837af0838a..ff975856f60bf70603a293c4fc863eaa7bf1b49a 100644 (file)
@@ -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;