]> git.sur5r.net Git - openldap/blob - servers/slapd/cancel.c
96bd7300b51159797e490bb667f7c7b7fa25bdbe
[openldap] / servers / slapd / cancel.c
1 /* cancel.c - LDAP cancel extended operation */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/krb.h>
12 #include <ac/socket.h>
13 #include <ac/string.h>
14 #include <ac/unistd.h>
15
16 #include "slap.h"
17
18 #include <lber_pvt.h>
19 #include <lutil.h>
20
21 int cancel_extop(
22         Connection *conn,
23         Operation *op,
24         const char *reqoid,
25         struct berval *reqdata,
26         char **rspoid,
27         struct berval **rspdata,
28         LDAPControl ***rspctrls,
29         const char **text,
30         BerVarray *refs )
31 {
32         Backend *be;
33         int rc;
34         int found = 0;
35         int opid;
36         BerElement *ber;
37
38         assert( reqoid != NULL );
39         assert( strcmp( LDAP_EXOP_X_CANCEL, reqoid ) == 0 );
40
41         if ( reqdata == NULL ) {
42                 *text = "no message ID supplied";
43                 return LDAP_PROTOCOL_ERROR;
44         }
45
46         ber = ber_init( reqdata );
47         if ( ber == NULL ) {
48                 *text = "internal error";
49                 return LDAP_OTHER;
50         }
51
52         if ( ber_scanf( ber, "{i}", &opid ) == LBER_ERROR ) {
53                 *text = "message ID parse failed";
54                 return LDAP_PROTOCOL_ERROR;
55         }
56
57         (void) ber_free( ber, 1 );
58
59         if ( opid < 0 ) {
60                 *text = "message ID invalid";
61                 return LDAP_PROTOCOL_ERROR;
62         }
63
64         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
65         LDAP_STAILQ_FOREACH( op, &conn->c_pending_ops, o_next ) {
66                 if ( op->o_msgid == opid ) {
67                         LDAP_STAILQ_REMOVE( &conn->c_pending_ops, op, slap_op, o_next );
68                         slap_op_free( op );
69                         found = 1;
70                         break;
71                 }
72         }
73         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
74
75         if ( found )
76                 return LDAP_SUCCESS;
77
78         found = 0;
79         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
80         LDAP_STAILQ_FOREACH( op, &conn->c_ops, o_next ) {
81                 if ( op->o_msgid == opid ) {
82                         found = 1;
83                         break;
84                 }
85         }
86
87         if ( !found ) {
88                 *text = "message ID not found";
89                 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
90                 return LDAP_NO_SUCH_OPERATION;
91         }
92
93         if ( op->o_cancel != LDAP_CANCEL_NONE ) {
94                 *text = "message ID already being cancelled";
95                 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
96                 return LDAP_PROTOCOL_ERROR;
97         }
98
99         op->o_cancel = LDAP_CANCEL_REQ;
100         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
101
102         while ( op->o_cancel == LDAP_CANCEL_REQ ) {
103                 ldap_pvt_thread_yield();
104         }
105
106         if ( op->o_cancel == LDAP_CANCEL_ACK ) {
107                 rc = LDAP_SUCCESS;
108         } else {
109                 rc = op->o_cancel;
110                 op->o_cancel = LDAP_CANCEL_NOTDONE;
111         }
112
113         return rc;
114 }