mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-30 13:30:57 +08:00
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
This commit is contained in:
parent
9936694960
commit
c9e134f0f7
@ -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 )
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -744,6 +744,10 @@ slapi_init(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( slapi_x_init_object_extensions() != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
355
servers/slapd/slapi/slapi_ext.c
Normal file
355
servers/slapd/slapi/slapi_ext.c
Normal file
@ -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 <ac/string.h>
|
||||
#include <ac/stdarg.h>
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/unistd.h>
|
||||
#include <ldap_pvt.h>
|
||||
|
||||
#include <slap.h>
|
||||
#include <slapi.h>
|
||||
|
||||
#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
|
||||
}
|
Loading…
Reference in New Issue
Block a user