]> git.sur5r.net Git - openldap/blob - libraries/libldap/abandon.c
Cast away const.
[openldap] / libraries / libldap / abandon.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*  Portions
7  *  Copyright (c) 1990 Regents of the University of Michigan.
8  *  All rights reserved.
9  *
10  *  abandon.c
11  */
12
13 /*
14  * An abandon request looks like this:
15  *      AbandonRequest ::= MessageID
16  */
17
18 #include "portable.h"
19
20 #include <stdio.h>
21
22 #include <ac/stdlib.h>
23
24 #include <ac/socket.h>
25 #include <ac/string.h>
26 #include <ac/time.h>
27
28 #include "ldap-int.h"
29
30 static int do_abandon LDAP_P((
31         LDAP *ld,
32         ber_int_t origid,
33         ber_int_t msgid,
34         LDAPControl **sctrls,
35         LDAPControl **cctrls));
36
37 /*
38  * ldap_abandon_ext - perform an ldap extended abandon operation.
39  *
40  * Parameters:
41  *      ld                      LDAP descriptor
42  *      msgid           The message id of the operation to abandon
43  *      scntrls         Server Controls
44  *      ccntrls         Client Controls
45  *
46  * ldap_abandon_ext returns a LDAP error code.
47  *              (LDAP_SUCCESS if everything went ok)
48  *
49  * Example:
50  *      ldap_abandon_ext( ld, msgid, scntrls, ccntrls );
51  */
52 int
53 ldap_abandon_ext(
54         LDAP *ld,
55         int msgid,
56         LDAPControl **sctrls,
57         LDAPControl **cctrls )
58 {
59         int rc;
60 #ifdef NEW_LOGGING
61         LDAP_LOG ( OPERATION, ARGS, "ldap_abandon_ext %d\n", msgid, 0, 0 );
62 #else
63         Debug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 );
64 #endif
65
66         /* check client controls */
67 #ifdef LDAP_R_COMPILE
68         ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
69 #endif
70         rc = ldap_int_client_controls( ld, cctrls );
71         if( rc == LDAP_SUCCESS )
72                 rc = do_abandon( ld, msgid, msgid, sctrls, cctrls );
73
74 #ifdef LDAP_R_COMPILE
75         ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
76 #endif
77         return rc;
78 }
79
80
81 /*
82  * ldap_abandon - perform an ldap abandon operation. Parameters:
83  *
84  *      ld              LDAP descriptor
85  *      msgid           The message id of the operation to abandon
86  *
87  * ldap_abandon returns 0 if everything went ok, -1 otherwise.
88  *
89  * Example:
90  *      ldap_abandon( ld, msgid );
91  */
92 int
93 ldap_abandon( LDAP *ld, int msgid )
94 {
95 #ifdef NEW_LOGGING
96         LDAP_LOG ( OPERATION, ARGS, "ldap_abandon %d\n", msgid, 0, 0 );
97 #else
98         Debug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 );
99 #endif
100         return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS
101                 ? 0 : -1;
102 }
103
104
105 static int
106 do_abandon(
107         LDAP *ld,
108         ber_int_t origid,
109         ber_int_t msgid,
110         LDAPControl **sctrls,
111         LDAPControl **cctrls)
112 {
113         BerElement      *ber;
114         int             i, err, sendabandon;
115         ber_int_t *old_abandon;
116         Sockbuf         *sb;
117         LDAPRequest     *lr;
118
119 #ifdef NEW_LOGGING
120         LDAP_LOG ( OPERATION, ARGS, "do_abandon %d, msgid %d\n", origid, msgid, 0 );
121 #else
122         Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
123                 origid, msgid, 0 );
124 #endif
125
126         sendabandon = 1;
127
128         /* find the request that we are abandoning */
129         for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
130                 if ( lr->lr_msgid == msgid ) {  /* this message */
131                         break;
132                 }
133                 if ( lr->lr_origid == msgid ) {/* child:  abandon it */
134                         (void) do_abandon( ld,
135                                 msgid, lr->lr_msgid, sctrls, cctrls );
136                 }
137         }
138
139         if ( lr != NULL ) {
140                 if ( origid == msgid && lr->lr_parent != NULL ) {
141                         /* don't let caller abandon child requests! */
142                         ld->ld_errno = LDAP_PARAM_ERROR;
143                         return( LDAP_PARAM_ERROR );
144                 }
145                 if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
146                         /* no need to send abandon message */
147                         sendabandon = 0;
148                 }
149         }
150
151 /* ldap_msgdelete locks the res_mutex. Give up the req_mutex
152  * while we're in there.
153  */
154 #ifdef LDAP_R_COMPILE
155         ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
156 #endif
157         err = ldap_msgdelete( ld, msgid );
158 #ifdef LDAP_R_COMPILE
159         ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
160 #endif
161         if ( err == 0 ) {
162                 ld->ld_errno = LDAP_SUCCESS;
163                 return LDAP_SUCCESS;
164         }
165
166         err = 0;
167         if ( sendabandon ) {
168                 if( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
169                         /* not connected */
170                         err = -1;
171                         ld->ld_errno = LDAP_SERVER_DOWN;
172
173                 } else if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
174                         /* BER element alocation failed */
175                         err = -1;
176                         ld->ld_errno = LDAP_NO_MEMORY;
177
178                 } else {
179                         LDAP_NEXT_MSGID(ld, i);
180 #ifdef LDAP_CONNECTIONLESS
181                         if ( LDAP_IS_UDP(ld) ) {
182                             err = ber_write( ber, ld->ld_options.ldo_peer,
183                                 sizeof(struct sockaddr), 0);
184                         }
185                         if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
186                                 LDAP_VERSION2) {
187                             char *dn = ld->ld_options.ldo_cldapdn;
188                             if (!dn) dn = "";
189                             err = ber_printf( ber, "{isti",  /* '}' */
190                                 i, dn,
191                                 LDAP_REQ_ABANDON, msgid );
192                         } else
193 #endif
194                         {
195                             /* create a message to send */
196                             err = ber_printf( ber, "{iti",  /* '}' */
197                                 i,
198                                 LDAP_REQ_ABANDON, msgid );
199                         }
200
201                         if( err == -1 ) {
202                                 /* encoding error */
203                                 ld->ld_errno = LDAP_ENCODING_ERROR;
204
205                         } else {
206                                 /* Put Server Controls */
207                                 if ( ldap_int_put_controls( ld, sctrls, ber )
208                                         != LDAP_SUCCESS )
209                                 {
210                                         err = -1;
211
212                                 } else {
213                                         /* close '{' */
214                                         err = ber_printf( ber, /*{*/ "N}" );
215
216                                         if( err == -1 ) {
217                                                 /* encoding error */
218                                                 ld->ld_errno = LDAP_ENCODING_ERROR;
219                                         }
220                                 }
221                         }
222
223                         if ( err == -1 ) {
224                                 ber_free( ber, 1 );
225
226                         } else {
227                                 /* send the message */
228                                 if ( lr != NULL ) {
229                                         sb = lr->lr_conn->lconn_sb;
230                                 } else {
231                                         sb = ld->ld_sb;
232                                 }
233
234                                 if ( ber_flush( sb, ber, 1 ) != 0 ) {
235                                         ld->ld_errno = LDAP_SERVER_DOWN;
236                                         err = -1;
237                                 } else {
238                                         err = 0;
239                                 }
240                         }
241                 }
242         }
243
244         if ( lr != NULL ) {
245                 if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
246                         ldap_free_connection( ld, lr->lr_conn, 0, 1 );
247                 }
248                 if ( origid == msgid ) {
249                         ldap_free_request( ld, lr );
250                 }
251         }
252
253         i = 0;
254         if ( ld->ld_abandoned != NULL ) {
255                 for ( ; ld->ld_abandoned[i] != -1; i++ )
256                         ;       /* NULL */
257         }
258
259         old_abandon = ld->ld_abandoned;
260
261         ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *)
262                 ld->ld_abandoned, (i + 2) * sizeof(ber_int_t) );
263                 
264         if ( ld->ld_abandoned == NULL ) {
265                 ld->ld_abandoned = old_abandon;
266                 ld->ld_errno = LDAP_NO_MEMORY;
267                 return( ld->ld_errno );
268         }
269
270         ld->ld_abandoned[i] = msgid;
271         ld->ld_abandoned[i + 1] = -1;
272
273         if ( err != -1 ) {
274                 ld->ld_errno = LDAP_SUCCESS;
275         }
276
277         return( ld->ld_errno );
278 }