From c9e134f0f7e970ea48689b3b6f9055c1b2763e97 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 3 Jul 2003 19:04:18 +0000 Subject: [PATCH] Support for SLAPI plugin extensions API. This API allows a plugin to associate arbitrary context with an internal server object such as a connection or operation. Some documentation is at: http://enterprise.netscape.com/docs/directory/602/plugin/function.htm#1104211 --- servers/slapd/connection.c | 16 ++ servers/slapd/operation.c | 2 + servers/slapd/slap.h | 2 + servers/slapd/slapi/Makefile.in | 6 +- servers/slapd/slapi/plugin.c | 4 + servers/slapd/slapi/proto-slapi.h | 5 + servers/slapd/slapi/slapi.h | 6 + servers/slapd/slapi/slapi_ext.c | 355 ++++++++++++++++++++++++++++++ 8 files changed, 393 insertions(+), 3 deletions(-) create mode 100644 servers/slapd/slapi/slapi_ext.c diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index cd789799f4..2f4d897850 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -19,6 +19,10 @@ #include "lutil.h" #include "slap.h" +#ifdef LDAP_SLAPI +#include "slapi.h" +#endif + /* protected by connections_mutex */ static ldap_pvt_thread_mutex_t connections_mutex; static Connection *connections = NULL; @@ -135,6 +139,9 @@ int connections_destroy(void) ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex ); ldap_pvt_thread_mutex_destroy( &connections[i].c_write_mutex ); ldap_pvt_thread_cond_destroy( &connections[i].c_write_cv ); +#ifdef LDAP_SLAPI + slapi_x_free_object_extensions( SLAPI_X_EXT_CONNECTION, &connections[i] ); +#endif } } @@ -453,6 +460,10 @@ long connection_init( ldap_pvt_thread_mutex_init( &c->c_write_mutex ); ldap_pvt_thread_cond_init( &c->c_write_cv ); +#ifdef LDAP_SLAPI + slapi_x_create_object_extensions( SLAPI_X_EXT_CONNECTION, c ); +#endif + c->c_struct_state = SLAP_C_UNUSED; } @@ -681,6 +692,11 @@ connection_destroy( Connection *c ) c->c_conn_state = SLAP_C_INVALID; c->c_struct_state = SLAP_C_UNUSED; + +#ifdef LDAP_SLAPI + /* call destructors, then constructors; avoids unnecessary allocation */ + slapi_x_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c ); +#endif } int connection_state_closing( Connection *c ) diff --git a/servers/slapd/operation.c b/servers/slapd/operation.c index b2a51370b7..34050fd5fb 100644 --- a/servers/slapd/operation.c +++ b/servers/slapd/operation.c @@ -75,6 +75,7 @@ slap_op_free( Operation *op ) if ( op->o_pb != NULL ) { slapi_pblock_destroy( (Slapi_PBlock *)op->o_pb ); } + slapi_x_free_object_extensions( SLAPI_X_EXT_OPERATION, op ); #endif /* defined( LDAP_SLAPI ) */ memset( op, 0, sizeof(Operation) ); @@ -114,6 +115,7 @@ slap_op_alloc( #if defined( LDAP_SLAPI ) op->o_pb = slapi_pblock_new(); + slapi_x_create_object_extensions( SLAPI_X_EXT_OPERATION, op ); #endif /* defined( LDAP_SLAPI ) */ return( op ); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 0264a48a2e..2daf63148f 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1973,6 +1973,7 @@ typedef struct slap_op { #ifdef LDAP_SLAPI void *o_pb; /* NS-SLAPI plugin */ + void *o_extensions; /* NS-SLAPI plugin */ #endif } Operation; @@ -2091,6 +2092,7 @@ typedef struct slap_conn { long c_n_write; /* num of write calls */ void *c_pb; /* Netscape plugin */ + void *c_extensions; /* Netscape plugin */ /* * These are the "callbacks" that are available for back-ends to diff --git a/servers/slapd/slapi/Makefile.in b/servers/slapd/slapi/Makefile.in index 2eddd5362e..d93f9d9fd2 100644 --- a/servers/slapd/slapi/Makefile.in +++ b/servers/slapd/slapi/Makefile.in @@ -12,16 +12,16 @@ LIBRARY = libslapi.la #XLIBRARY = libtmpslapd.a #all-common: $(LIBRARY) $(PROGRAMS) -# @touch plugin.c slapi_pblock.c slapi_utils.c slapi_ops.c +# @touch plugin.c slapi_pblock.c slapi_utils.c slapi_ops.c slapi_ext.c NT_SRCS = nt_err.c NT_OBJS = nt_err.lo LIB_DEFS = -DSLAPI_LIBRARY -SRCS= plugin.c slapi_pblock.c slapi_utils.c printmsg.c slapi_ops.c \ +SRCS= plugin.c slapi_pblock.c slapi_utils.c printmsg.c slapi_ops.c slapi_ext.c \ $(@PLAT@_SRCS) -OBJS= plugin.lo slapi_pblock.lo slapi_utils.lo printmsg.lo slapi_ops.lo \ +OBJS= plugin.lo slapi_pblock.lo slapi_utils.lo printmsg.lo slapi_ops.lo slapi_ext.lo \ $(@PLAT@_SRCS) XSRCS= version.c diff --git a/servers/slapd/slapi/plugin.c b/servers/slapd/slapi/plugin.c index 5deb326147..8c7e1801ad 100644 --- a/servers/slapd/slapi/plugin.c +++ b/servers/slapd/slapi/plugin.c @@ -744,6 +744,10 @@ slapi_init(void) return -1; } + if ( slapi_x_init_object_extensions() != 0 ) { + return -1; + } + return 0; } diff --git a/servers/slapd/slapi/proto-slapi.h b/servers/slapd/slapi/proto-slapi.h index f697d4e1ae..6b1c35c885 100644 --- a/servers/slapd/slapi/proto-slapi.h +++ b/servers/slapd/slapi/proto-slapi.h @@ -311,6 +311,11 @@ extern int slapi_modifyrdn_changelog(char *olddn, char *newRdn, int delRdn, char *suffix, char *chNum, Operation* op); extern Backend * slapi_cl_get_be(char *dn); +int slapi_x_init_object_extensions(void); +int slapi_x_free_object_extensions(int objecttype, void *object); +int slapi_x_create_object_extensions(int objecttype, void *object); +int slapi_x_clear_object_extensions(int objecttype, void *object); + LDAP_END_DECL #endif /* _PROTO_SLAPI_H */ diff --git a/servers/slapd/slapi/slapi.h b/servers/slapd/slapi/slapi.h index 86d4432877..3b5bd4f6e7 100644 --- a/servers/slapd/slapi/slapi.h +++ b/servers/slapd/slapi/slapi.h @@ -112,6 +112,11 @@ struct _computed_attr_context { #define SLAPI_TYPE_CMP_BASE 1 #define SLAPI_TYPE_CMP_SUBTYPE 2 +typedef enum slapi_extension_e { + SLAPI_X_EXT_CONNECTION = 0, + SLAPI_X_EXT_OPERATION = 1, + SLAPI_X_EXT_MAX = 2 +} slapi_extension_t; /* * Was: slapi_pblock.h @@ -268,6 +273,7 @@ extern Backend * slapi_cl_get_be(char *dn); #define SLAPI_X_CONN_CLIENTPATH 1300 #define SLAPI_X_CONN_SERVERPATH 1301 #define SLAPI_X_CONN_IS_UDP 1302 +#define SLAPI_X_CONN_SSF 1303 #define SLAPD_AUTH_NONE "none" #define SLAPD_AUTH_SIMPLE "simple" diff --git a/servers/slapd/slapi/slapi_ext.c b/servers/slapd/slapi/slapi_ext.c new file mode 100644 index 0000000000..86e4e2a398 --- /dev/null +++ b/servers/slapd/slapi/slapi_ext.c @@ -0,0 +1,355 @@ +/* + * (C) Copyright PADL Software Pty Ltd. 2003 + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that this notice is preserved + * and that due credit is given to PADL Software Pty Ltd. This software + * is provided ``as is'' without express or implied warranty. + */ + +#include "portable.h" + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef LDAP_SLAPI +/* + * Object extensions + * + * We only support two types -- connection and operation extensions. + * Define more types in slapi.h + */ + +/* global state */ +struct slapi_registered_extension_set { + ldap_pvt_thread_mutex_t mutex; + struct slapi_registered_extension { + int active; + int count; + slapi_extension_constructor_fnptr *constructors; + slapi_extension_destructor_fnptr *destructors; + } extensions[SLAPI_X_EXT_MAX]; +} registered_extensions; + +/* per-object state */ +struct slapi_extension_block { + void **extensions; +}; + +static int getExtensionBlock(int objecttype, void *object, struct slapi_extension_block **eblock, void **parent) +{ + switch ((slapi_extension_t) objecttype) { + case SLAPI_X_EXT_CONNECTION: + *eblock = ((Connection *)object)->c_extensions; + *parent = NULL; + break; + case SLAPI_X_EXT_OPERATION: + *eblock = ((Operation *)object)->o_extensions; + *parent = ((Operation *)object)->o_conn; + break; + default: + return -1; + break; + } + + if ( *eblock == NULL ) { + return -1; + } + + return 0; +} + +static int mapExtensionType(const char *objectname, slapi_extension_t *type) +{ + if ( strcasecmp( objectname, SLAPI_EXT_CONNECTION ) == 0 ) { + *type = SLAPI_X_EXT_CONNECTION; + } else if ( strcasecmp( objectname, SLAPI_EXT_OPERATION ) == 0 ) { + *type = SLAPI_X_EXT_OPERATION; + } else { + return -1; + } + + return 0; +} + +static void newExtension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle ) +{ + slapi_extension_constructor_fnptr constructor; + + assert( objecttype < SLAPI_X_EXT_MAX ); + assert( extensionhandle < registered_extensions.extensions[objecttype].count ); + + assert( registered_extensions.extensions[objecttype].constructors != NULL ); + constructor = registered_extensions.extensions[objecttype].constructors[extensionhandle]; + + assert( eblock->extensions[extensionhandle] == NULL ); + + if ( constructor != NULL ) { + eblock->extensions[extensionhandle] = (*constructor)( object, parent ); + } else { + eblock->extensions[extensionhandle] = NULL; + } +} + +static void freeExtension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle ) +{ + slapi_extension_destructor_fnptr destructor; + + assert( objecttype < SLAPI_X_EXT_MAX ); + assert( extensionhandle < registered_extensions.extensions[objecttype].count ); + + if ( eblock->extensions[extensionhandle] != NULL ) { + assert( registered_extensions.extensions[objecttype].destructors != NULL ); + destructor = registered_extensions.extensions[objecttype].destructors[extensionhandle]; + if ( destructor != NULL ) { + (*destructor)( eblock->extensions[extensionhandle], object, parent ); + } + eblock->extensions[extensionhandle] = NULL; + } +} +#endif /* LDAP_SLAPI */ + +void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle) +{ +#ifdef LDAP_SLAPI + struct slapi_extension_block *eblock; + void *parent; + + if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) { + return NULL; + } + + if ( extensionhandle < registered_extensions.extensions[objecttype].count ) { + return eblock->extensions[extensionhandle]; + } + + return NULL; +#else + return NULL; +#endif /* LDAP_SLAPI */ +} + +void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension) +{ +#ifdef LDAP_SLAPI + struct slapi_extension_block *eblock; + void *parent; + + if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) { + return; + } + + if ( extensionhandle < registered_extensions.extensions[objecttype].count ) { + /* free the old one */ + freeExtension( eblock, objecttype, object, parent, extensionhandle ); + + /* constructed by caller */ + eblock->extensions[extensionhandle] = extension; + } +#endif /* LDAP_SLAPI */ +} + +int slapi_register_object_extension( + const char *pluginname, + const char *objectname, + slapi_extension_constructor_fnptr constructor, + slapi_extension_destructor_fnptr destructor, + int *objecttype, + int *extensionhandle) +{ +#ifdef LDAP_SLAPI + int rc; + slapi_extension_t type; + struct slapi_registered_extension *re; + + ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex ); + + rc = mapExtensionType( objectname, &type ); + if ( rc != 0 ) { + ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex ); + return rc; + } + + *objecttype = (int)type; + + re = ®istered_extensions.extensions[*objecttype]; + + *extensionhandle = re->count; + + if ( re->active ) { + /* can't add new extensions after objects have been created */ + ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex ); + return -1; + } + + re->count++; + + if ( re->constructors == NULL ) { + re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count, + sizeof( slapi_extension_constructor_fnptr ) ); + } else { + re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors, + re->count * sizeof( slapi_extension_constructor_fnptr ) ); + } + re->constructors[*extensionhandle] = constructor; + + if ( re->destructors == NULL ) { + re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count, + sizeof( slapi_extension_destructor_fnptr ) ); + } else { + re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors, + re->count * sizeof( slapi_extension_destructor_fnptr ) ); + } + re->destructors[*extensionhandle] = destructor; + + ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex ); + + return 0; +#else + return -1; +#endif /* LDAP_SLAPI */ +} + +int slapi_x_create_object_extensions(int objecttype, void *object) +{ +#ifdef LDAP_SLAPI + int i, rc; + struct slapi_extension_block *eblock; + void **peblock; + void *parent; + + switch ((slapi_extension_t) objecttype) { + case SLAPI_X_EXT_CONNECTION: + peblock = &(((Connection *)object)->c_extensions); + parent = NULL; + break; + case SLAPI_X_EXT_OPERATION: + peblock = &(((Operation *)object)->o_extensions); + parent = ((Operation *)object)->o_conn; + break; + default: + return -1; + break; + } + + *peblock = NULL; + + ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex ); + if ( registered_extensions.extensions[objecttype].active == 0 ) { + /* + * once we've created some extensions, no new extensions can + * be registered. + */ + registered_extensions.extensions[objecttype].active = 1; + } + ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex ); + + eblock = (struct slapi_extension_block *)slapi_ch_calloc( 1, sizeof(*eblock) ); + + if ( registered_extensions.extensions[objecttype].count ) { + eblock->extensions = (void **)slapi_ch_calloc( registered_extensions.extensions[objecttype].count, sizeof(void *) ); + for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) { + newExtension( eblock, objecttype, object, parent, i ); + } + } else { + eblock->extensions = NULL; + } + + *peblock = eblock; + + return 0; +#else + return -1; +#endif +} + +int slapi_x_free_object_extensions(int objecttype, void *object) +{ +#ifdef LDAP_SLAPI + int i, rc; + struct slapi_extension_block *eblock; + void **peblock; + void *parent; + + switch ((slapi_extension_t) objecttype) { + case SLAPI_X_EXT_CONNECTION: + peblock = &(((Connection *)object)->c_extensions); + parent = NULL; + break; + case SLAPI_X_EXT_OPERATION: + peblock = &(((Operation *)object)->o_extensions); + parent = ((Operation *)object)->o_conn; + break; + default: + return -1; + break; + } + + eblock = (struct slapi_extension_block *)*peblock; + + if ( eblock->extensions != NULL ) { + for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) { + freeExtension( eblock, objecttype, object, parent, i ); + } + + slapi_ch_free( (void **)&eblock->extensions ); + } + + slapi_ch_free( peblock ); + + return 0; +#else + return -1; +#endif +} + +/* for reusable object types */ +int slapi_x_clear_object_extensions(int objecttype, void *object) +{ +#ifdef LDAP_SLAPI + int i, rc; + struct slapi_extension_block *eblock; + void *parent; + + if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) { + return -1; + } + + if ( eblock->extensions == NULL ) { + /* no extensions */ + return 0; + } + + for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) { + freeExtension( eblock, objecttype, object, parent, i ); + } + + for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) { + newExtension( eblock, objecttype, object, parent, i ); + } + + return 0; +#else + return -1; +#endif +} + +int slapi_x_init_object_extensions(void) +{ +#ifdef LDAP_SLAPI + memset( ®istered_extensions, 0, sizeof( registered_extensions ) ); + + if ( ldap_pvt_thread_mutex_init( ®istered_extensions.mutex ) != 0 ) { + return -1; + } + + return 0; +#else + return -1; +#endif +} -- 2.39.5