]> git.sur5r.net Git - openldap/blob - libraries/libldap/abandon.c
125e4bdee6b6cad28fda3347d13c1c10159e1894
[openldap] / libraries / libldap / abandon.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /*  Portions
6  *  Copyright (c) 1990 Regents of the University of Michigan.
7  *  All rights reserved.
8  *
9  *  abandon.c
10  */
11
12 #include "portable.h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16
17 #include <ac/socket.h>
18 #include <ac/string.h>
19 #include <ac/time.h>
20
21 #include "ldap-int.h"
22
23 static int do_abandon LDAP_P((
24         LDAP *ld,
25         int origid,
26         int msgid,
27         LDAPControl **sctrls,
28         LDAPControl **cctrls));
29
30 /*
31  * ldap_abandon_ext - perform an ldap extended abandon operation.
32  *
33  * Parameters:
34  *      ld                      LDAP descriptor
35  *      msgid           The message id of the operation to abandon
36  *      scntrls         Server Controls
37  *      ccntrls         Client Controls
38  *
39  * ldap_abandon_ext returns a LDAP error code.
40  *              (LDAP_SUCCESS if everything went ok)
41  *
42  * Example:
43  *      ldap_abandon_ext( ld, msgid, scntrls, ccntrls );
44  */
45 int
46 ldap_abandon_ext(
47         LDAP *ld,
48         int msgid,
49         LDAPControl **sctrls,
50         LDAPControl **cctrls )
51 {
52         Debug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 );
53
54         return do_abandon( ld, msgid, msgid, sctrls, cctrls );
55 }
56
57
58 /*
59  * ldap_abandon - perform an ldap abandon operation. Parameters:
60  *
61  *      ld              LDAP descriptor
62  *      msgid           The message id of the operation to abandon
63  *
64  * ldap_abandon returns 0 if everything went ok, -1 otherwise.
65  *
66  * Example:
67  *      ldap_abandon( ld, msgid );
68  */
69 int
70 ldap_abandon( LDAP *ld, int msgid )
71 {
72         Debug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 );
73         return do_abandon( ld, msgid, msgid, NULL, NULL ) == LDAP_SUCCESS
74                 ? 0 : -1;
75 }
76
77
78 static int
79 do_abandon(
80         LDAP *ld,
81         int origid,
82         int msgid,
83         LDAPControl **sctrls,
84         LDAPControl **cctrls)
85 {
86         BerElement      *ber;
87         int             i, err, sendabandon;
88         unsigned int *old_abandon;
89         Sockbuf         *sb;
90         LDAPRequest     *lr;
91
92         /*
93          * An abandon request looks like this:
94          *      AbandonRequest ::= MessageID
95          */
96
97         Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
98                 origid, msgid, 0 );
99
100         sendabandon = 1;
101
102         /* find the request that we are abandoning */
103         for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
104                 if ( lr->lr_msgid == msgid ) {  /* this message */
105                         break;
106                 }
107                 if ( lr->lr_origid == msgid ) {/* child:  abandon it */
108                         (void) do_abandon( ld,
109                                 msgid, lr->lr_msgid, sctrls, cctrls );
110                 }
111         }
112
113         if ( lr != NULL ) {
114                 if ( origid == msgid && lr->lr_parent != NULL ) {
115                         /* don't let caller abandon child requests! */
116                         ld->ld_errno = LDAP_PARAM_ERROR;
117                         return( LDAP_PARAM_ERROR );
118                 }
119                 if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
120                         /* no need to send abandon message */
121                         sendabandon = 0;
122                 }
123         }
124
125         if ( ldap_msgdelete( ld, msgid ) == 0 ) {
126                 ld->ld_errno = LDAP_SUCCESS;
127                 return LDAP_SUCCESS;
128         }
129
130         err = 0;
131         if ( sendabandon ) {
132                 /* create a message to send */
133                 if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
134                         err = -1;
135                         ld->ld_errno = LDAP_NO_MEMORY;
136
137                 } else {
138 #ifdef LDAP_CONNECTIONLESS
139                         if ( ld->ld_cldapnaddr > 0 ) {
140                                 err = ber_printf( ber, "{isti", /* leave open '}' */
141                                     ++ld->ld_msgid, ld->ld_cldapdn,
142                                     LDAP_REQ_ABANDON, msgid );
143                         } else
144 #endif /* LDAP_CONNECTIONLESS */
145                         {
146                                 err = ber_printf( ber, "{iti",  /* leave open '}' */
147                                         ++ld->ld_msgid,
148                                     LDAP_REQ_ABANDON, msgid );
149                         }
150
151                         if( err == -1 ) {
152                                 /* encoding error */
153                                 ld->ld_errno = LDAP_ENCODING_ERROR;
154
155                         } else {
156                                 /* Put Server Controls */
157                                 if ( ldap_int_put_controls( ld, sctrls, ber )
158                                         != LDAP_SUCCESS )
159                                 {
160                                         err = -1;
161
162                                 } else {
163                                         /* close '{' */
164                                         err = ber_printf( ber, "}" );
165
166                                         if( err == -1 ) {
167                                                 /* encoding error */
168                                                 ld->ld_errno = LDAP_ENCODING_ERROR;
169                                         }
170                                 }
171                         }
172
173                         if ( err == -1 ) {
174                                 ber_free( ber, 1 );
175
176                         } else {
177                                 /* send the message */
178                                 if ( lr != NULL ) {
179                                         sb = lr->lr_conn->lconn_sb;
180                                 } else {
181                                         sb = &ld->ld_sb;
182                                 }
183
184                                 if ( ber_flush( sb, ber, 1 ) != 0 ) {
185                                         ld->ld_errno = LDAP_SERVER_DOWN;
186                                         err = -1;
187                                 } else {
188                                         err = 0;
189                                 }
190                         }
191                 }
192         }
193
194         if ( lr != NULL ) {
195                 if ( sendabandon ) {
196                         ldap_free_connection( ld, lr->lr_conn, 0, 1 );
197                 }
198                 if ( origid == msgid ) {
199                         ldap_free_request( ld, lr );
200                 }
201         }
202
203         i = 0;
204         if ( ld->ld_abandoned != NULL ) {
205                 for ( ; ld->ld_abandoned[i] != -1; i++ )
206                         ;       /* NULL */
207         }
208
209         old_abandon = ld->ld_abandoned;
210
211         ld->ld_abandoned = (int *) LDAP_REALLOC( (char *)
212                 ld->ld_abandoned, (i + 2) * sizeof(int) );
213                 
214         if ( ld->ld_abandoned == NULL ) {
215                 ld->ld_abandoned = old_abandon;
216                 ld->ld_errno = LDAP_NO_MEMORY;
217                 return( ld->ld_errno );
218         }
219
220         ld->ld_abandoned[i] = msgid;
221         ld->ld_abandoned[i + 1] = -1;
222
223         if ( err != -1 ) {
224                 ld->ld_errno = LDAP_SUCCESS;
225         }
226
227         return( ld->ld_errno );
228 }