/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2008 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/* Portions Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*/
-/* Portions Copyright (C) The Internet Society (1997).
- * ASN.1 fragments are from RFC 2251; see RFC for full legal notices.
- */
-
-/*
- * An abandon request looks like this:
- * AbandonRequest ::= MessageID
- */
#include "portable.h"
#include "ldap-int.h"
+/*
+ * An abandon request looks like this:
+ * AbandonRequest ::= [APPLICATION 16] MessageID
+ * and has no response. (Source: RFC 4511)
+ */
+#include "lutil.h"
+
static int
do_abandon(
LDAP *ld,
int
-ldap_int_discard(
+ldap_pvt_discard(
LDAP *ld,
ber_int_t msgid )
{
{
BerElement *ber;
int i, err;
- ber_int_t *old_abandon;
Sockbuf *sb;
LDAPRequest *lr;
- Debug( LDAP_DEBUG_TRACE, "ldap_int_discard origid %d, msgid %d\n",
+ Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
origid, msgid, 0 );
/* find the request that we are abandoning */
start_again:;
lr = ld->ld_requests;
while ( lr != NULL ) {
- if ( lr->lr_msgid == msgid ) { /* this message */
+ /* this message */
+ if ( lr->lr_msgid == msgid ) {
break;
}
- if ( lr->lr_origid == msgid ) {/* child: abandon it */
+ /* child: abandon it */
+ if ( lr->lr_origid == msgid && !lr->lr_abandoned ) {
(void)do_abandon( ld, lr->lr_origid, lr->lr_msgid,
sctrls, sendabandon );
i = ++(ld)->ld_msgid;
#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_UDP(ld) ) {
- err = ber_write( ber, ld->ld_options.ldo_peer,
- sizeof(struct sockaddr), 0);
+ struct sockaddr sa = {0};
+ /* dummy, filled with ldo_peer in request.c */
+ err = ber_write( ber, &sa, sizeof(sa), 0 );
}
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
LDAP_VERSION2 )
if ( origid == msgid ) {
ldap_free_request( ld, lr );
+
+ } else {
+ lr->lr_abandoned = 1;
}
}
/* use bisection */
i = 0;
- if ( ld->ld_abandoned != NULL ) {
- int begin,
- end;
-
- assert( ld->ld_nabandoned >= 0 );
+ if ( ld->ld_nabandoned == 0 ||
+ ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 )
+ {
+ ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i );
+ }
- begin = 0;
- end = ld->ld_nabandoned - 1;
+ if ( err != -1 ) {
+ ld->ld_errno = LDAP_SUCCESS;
+ }
- if ( ld->ld_nabandoned == 0 || ld->ld_abandoned[ begin ] > msgid ) {
- i = 0;
+#ifdef LDAP_R_COMPILE
+ ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
+ ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
+ return( ld->ld_errno );
+}
- } else if ( ld->ld_abandoned[ end ] < msgid ) {
- i = ld->ld_nabandoned;
+/*
+ * ldap_int_bisect_find
+ *
+ * args:
+ * v: array of length n (in)
+ * n: length of array v (in)
+ * id: value to look for (in)
+ * idxp: pointer to location of value/insert point
+ *
+ * return:
+ * 0: not found
+ * 1: found
+ * -1: error
+ */
+int
+ldap_int_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp )
+{
+ int begin,
+ end,
+ rc = 0;
- } else {
- int pos, curid;
+ assert( n >= 0 );
+ assert( id >= 0 );
- while ( end >= begin ) {
- pos = (begin + end)/2;
- curid = ld->ld_abandoned[ pos ];
+ begin = 0;
+ end = n - 1;
- if ( msgid < curid ) {
- end = pos - 1;
+ if ( n <= 0 || id < v[ begin ] ) {
+ *idxp = 0;
- } else if ( msgid > curid ) {
- begin = pos + 1;
+ } else if ( id > v[ end ] ) {
+ *idxp = n;
+ } else {
+ int pos;
+ ber_int_t curid;
+
+ do {
+ pos = (begin + end)/2;
+ curid = v[ pos ];
+
+ if ( id < curid ) {
+ end = pos - 1;
+
+ } else if ( id > curid ) {
+ begin = ++pos;
+
} else {
/* already abandoned? */
- i = -1;
+ rc = 1;
break;
}
- }
-
- if ( i == 0 ) {
- i = pos;
- }
+ } while ( end >= begin );
+
+ *idxp = pos;
}
- }
- if ( i != -1 ) {
- int pos = i;
+ return rc;
+}
- old_abandon = ld->ld_abandoned;
+/*
+ * ldap_int_bisect_insert
+ *
+ * args:
+ * vp: pointer to array of length *np (in/out)
+ * np: pointer to length of array *vp (in/out)
+ * id: value to insert (in)
+ * idx: location of insert point (as computed by ldap_int_bisect_find())
+ *
+ * return:
+ * 0: inserted
+ * -1: error
+ */
+int
+ldap_int_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx )
+{
+ ber_int_t *v;
+ ber_len_t n;
+ int i;
- ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *)ld->ld_abandoned,
- ( ld->ld_nabandoned + 1 ) * sizeof( ber_int_t ) );
+ assert( vp != NULL );
+ assert( np != NULL );
+ assert( *np >= 0 );
+ assert( idx >= 0 );
+ assert( idx <= *np );
- if ( ld->ld_abandoned == NULL ) {
- ld->ld_abandoned = old_abandon;
- ld->ld_errno = LDAP_NO_MEMORY;
- goto done;
- }
+ n = *np;
- for ( i = ld->ld_nabandoned; i > pos; i-- ) {
- ld->ld_abandoned[ i ] = ld->ld_abandoned[ i - 1 ];
- }
- ld->ld_abandoned[ pos ] = msgid;
- ++ld->ld_nabandoned;
+ v = ber_memrealloc( *vp, sizeof( ber_int_t ) * ( n + 1 ) );
+ if ( v == NULL ) {
+ return -1;
}
+ *vp = v;
- if ( err != -1 ) {
- ld->ld_errno = LDAP_SUCCESS;
+ for ( i = n; i > idx; i-- ) {
+ v[ i ] = v[ i - 1 ];
}
+ v[ idx ] = id;
+ ++(*np);
-done:;
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
- ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
-#endif
- return( ld->ld_errno );
+ return 0;
+}
+
+/*
+ * ldap_int_bisect_delete
+ *
+ * args:
+ * vp: pointer to array of length *np (in/out)
+ * np: pointer to length of array *vp (in/out)
+ * id: value to delete (in)
+ * idx: location of value to delete (as computed by ldap_int_bisect_find())
+ *
+ * return:
+ * 0: deleted
+ */
+int
+ldap_int_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx )
+{
+ ber_int_t *v;
+ ber_len_t n;
+ int i;
+
+ assert( vp != NULL );
+ assert( np != NULL );
+ assert( *np >= 0 );
+ assert( idx >= 0 );
+ assert( idx < *np );
+
+ v = *vp;
+
+ assert( v[ idx ] == id );
+
+ --(*np);
+ n = *np;
+
+ for ( i = idx; i < n; i++ ) {
+ v[ i ] = v[ i + 1 ];
+ }
+
+ return 0;
}
+