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