]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/abandon.c
Sync with HEAD
[openldap] / libraries / libldap / abandon.c
index 0541dd93cc6e34934c65d02f0bbd62bf756de469..551940d1b1655dbbe13d3584db06cf2be8dd05ae 100644 (file)
@@ -1,13 +1,23 @@
+/* abandon.c */
 /* $OpenLDAP$ */
-/*
- * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
- */
-/*  Portions
- *  Copyright (c) 1990 Regents of the University of Michigan.
- *  All rights reserved.
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2006 The OpenLDAP Foundation.
+ * All rights reserved.
  *
- *  abandon.c
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* 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.
  */
 
 /*
@@ -56,9 +66,21 @@ ldap_abandon_ext(
        LDAPControl **sctrls,
        LDAPControl **cctrls )
 {
+       int rc;
        Debug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 );
 
-       return do_abandon( ld, msgid, msgid, sctrls, cctrls );
+       /* check client controls */
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
+       rc = ldap_int_client_controls( ld, cctrls );
+       if( rc == LDAP_SUCCESS )
+               rc = do_abandon( ld, msgid, msgid, sctrls, cctrls );
+
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+       return rc;
 }
 
 
@@ -77,7 +99,7 @@ int
 ldap_abandon( LDAP *ld, int msgid )
 {
        Debug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 );
-       return do_abandon( ld, msgid, msgid, NULL, NULL ) == LDAP_SUCCESS
+       return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS
                ? 0 : -1;
 }
 
@@ -88,11 +110,11 @@ do_abandon(
        ber_int_t origid,
        ber_int_t msgid,
        LDAPControl **sctrls,
-       LDAPControl **cctrls)
+       LDAPControl **cctrls )
 {
        BerElement      *ber;
        int             i, err, sendabandon;
-       ber_int_t *old_abandon;
+       ber_int_t       *old_abandon;
        Sockbuf         *sb;
        LDAPRequest     *lr;
 
@@ -108,7 +130,7 @@ do_abandon(
                }
                if ( lr->lr_origid == msgid ) {/* child:  abandon it */
                        (void) do_abandon( ld,
-                               msgid, lr->lr_msgid, sctrls, cctrls );
+                               lr->lr_origid, lr->lr_msgid, sctrls, cctrls );
                }
        }
 
@@ -124,30 +146,69 @@ do_abandon(
                }
        }
 
-       if ( ldap_msgdelete( ld, msgid ) == 0 ) {
+/* ldap_msgdelete locks the res_mutex. Give up the req_mutex
+ * while we're in there.
+ */
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+       err = ldap_msgdelete( ld, msgid );
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
+       if ( err == 0 ) {
                ld->ld_errno = LDAP_SUCCESS;
                return LDAP_SUCCESS;
        }
 
+       /* fetch again the request that we are abandoning */
+       if ( lr != NULL ) {
+               for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
+                       if ( lr->lr_msgid == msgid ) {  /* this message */
+                               break;
+                       }
+               }
+       }
+
        err = 0;
        if ( sendabandon ) {
-               /* create a message to send */
-               if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
+               if( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
+                       /* not connected */
+                       err = -1;
+                       ld->ld_errno = LDAP_SERVER_DOWN;
+
+               } else if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
+                       /* BER element alocation failed */
                        err = -1;
                        ld->ld_errno = LDAP_NO_MEMORY;
 
                } else {
+       /*
+        * We already have the mutex in LDAP_R_COMPILE, so
+        * don't try to get it again.
+        *              LDAP_NEXT_MSGID(ld, i);
+        */
+                       i = ++(ld)->ld_msgid;
 #ifdef LDAP_CONNECTIONLESS
-                       if ( ld->ld_cldapnaddr > 0 ) {
-                               err = ber_printf( ber, "{isti", /* '}' */
-                                   ++ld->ld_msgid, ld->ld_cldapdn,
-                                   LDAP_REQ_ABANDON, msgid );
+                       if ( LDAP_IS_UDP(ld) ) {
+                               err = ber_write( ber, ld->ld_options.ldo_peer,
+                                       sizeof(struct sockaddr), 0);
+                       }
+                       if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
+                               LDAP_VERSION2 )
+                       {
+                               char *dn = ld->ld_options.ldo_cldapdn;
+                               if (!dn) dn = "";
+                               err = ber_printf( ber, "{isti",  /* '}' */
+                                       i, dn,
+                                       LDAP_REQ_ABANDON, msgid );
                        } else
-#endif /* LDAP_CONNECTIONLESS */
+#endif
                        {
+                               /* create a message to send */
                                err = ber_printf( ber, "{iti",  /* '}' */
-                                       ++ld->ld_msgid,
-                                   LDAP_REQ_ABANDON, msgid );
+                                       i,
+                                       LDAP_REQ_ABANDON, msgid );
                        }
 
                        if( err == -1 ) {
@@ -163,7 +224,7 @@ do_abandon(
 
                                } else {
                                        /* close '{' */
-                                       err = ber_printf( ber, /*{*/ "}" );
+                                       err = ber_printf( ber, /*{*/ "N}" );
 
                                        if( err == -1 ) {
                                                /* encoding error */
@@ -178,12 +239,13 @@ do_abandon(
                        } else {
                                /* send the message */
                                if ( lr != NULL ) {
+                                       assert( lr->lr_conn != NULL );
                                        sb = lr->lr_conn->lconn_sb;
                                } else {
-                                       sb = &ld->ld_sb;
+                                       sb = ld->ld_sb;
                                }
 
-                               if ( ber_flush( sb, ber, 1 ) != 0 ) {
+                               if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) {
                                        ld->ld_errno = LDAP_SERVER_DOWN;
                                        err = -1;
                                } else {
@@ -194,7 +256,7 @@ do_abandon(
        }
 
        if ( lr != NULL ) {
-               if ( sendabandon ) {
+               if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
                        ldap_free_connection( ld, lr->lr_conn, 0, 1 );
                }
                if ( origid == msgid ) {
@@ -202,6 +264,12 @@ do_abandon(
                }
        }
 
+#ifdef LDAP_R_COMPILE
+       /* ld_abandoned is actually protected by the ld_res_mutex;
+        * give up the ld_req_mutex and get the other */
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+       ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
+#endif
        i = 0;
        if ( ld->ld_abandoned != NULL ) {
                for ( ; ld->ld_abandoned[i] != -1; i++ )
@@ -216,7 +284,7 @@ do_abandon(
        if ( ld->ld_abandoned == NULL ) {
                ld->ld_abandoned = old_abandon;
                ld->ld_errno = LDAP_NO_MEMORY;
-               return( ld->ld_errno );
+               goto done;
        }
 
        ld->ld_abandoned[i] = msgid;
@@ -226,5 +294,10 @@ do_abandon(
                ld->ld_errno = LDAP_SUCCESS;
        }
 
+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 );
 }