]> git.sur5r.net Git - openldap/blob - servers/slapd/connection.c
Initial check of connection states. Have only implemented
[openldap] / servers / slapd / connection.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/errno.h>
6 #include <ac/signal.h>
7 #include <ac/socket.h>
8 #include <ac/string.h>
9 #include <ac/time.h>
10
11 #include "slap.h"
12
13 struct co_arg {
14         Connection      *co_conn;
15         Operation       *co_op;
16 };
17
18 /*
19  * connection_activity - handle the request operation op on connection
20  * conn.  This routine figures out what kind of operation it is and
21  * calls the appropriate stub to handle it.
22  */
23
24 static void *
25 connection_operation( void *arg_v )
26 {
27         struct co_arg   *arg = arg_v;
28
29         ldap_pvt_thread_mutex_lock( &arg->co_conn->c_opsmutex );
30         arg->co_conn->c_ops_received++;
31         ldap_pvt_thread_mutex_unlock( &arg->co_conn->c_opsmutex );
32
33         ldap_pvt_thread_mutex_lock( &ops_mutex );
34         ops_initiated++;
35         ldap_pvt_thread_mutex_unlock( &ops_mutex );
36
37         switch ( arg->co_op->o_tag ) {
38         case LDAP_REQ_BIND:
39                 do_bind( arg->co_conn, arg->co_op );
40                 break;
41
42 #ifdef LDAP_COMPAT30
43         case LDAP_REQ_UNBIND_30:
44 #endif
45         case LDAP_REQ_UNBIND:
46                 do_unbind( arg->co_conn, arg->co_op );
47                 break;
48
49         case LDAP_REQ_ADD:
50                 do_add( arg->co_conn, arg->co_op );
51                 break;
52
53 #ifdef LDAP_COMPAT30
54         case LDAP_REQ_DELETE_30:
55 #endif
56         case LDAP_REQ_DELETE:
57                 do_delete( arg->co_conn, arg->co_op );
58                 break;
59
60         case LDAP_REQ_MODRDN:
61                 do_modrdn( arg->co_conn, arg->co_op );
62                 break;
63
64         case LDAP_REQ_MODIFY:
65                 do_modify( arg->co_conn, arg->co_op );
66                 break;
67
68         case LDAP_REQ_COMPARE:
69                 do_compare( arg->co_conn, arg->co_op );
70                 break;
71
72         case LDAP_REQ_SEARCH:
73                 do_search( arg->co_conn, arg->co_op );
74                 break;
75
76 #ifdef LDAP_COMPAT30
77         case LDAP_REQ_ABANDON_30:
78 #endif
79         case LDAP_REQ_ABANDON:
80                 do_abandon( arg->co_conn, arg->co_op );
81                 break;
82
83         default:
84                 Debug( LDAP_DEBUG_ANY, "unknown request 0x%lx\n",
85                     arg->co_op->o_tag, 0, 0 );
86                 break;
87         }
88
89         ldap_pvt_thread_mutex_lock( &arg->co_conn->c_opsmutex );
90         arg->co_conn->c_ops_completed++;
91
92         slap_op_delete( &arg->co_conn->c_ops, arg->co_op );
93         arg->co_op = NULL;
94
95         ldap_pvt_thread_mutex_unlock( &arg->co_conn->c_opsmutex );
96
97         arg->co_conn = NULL;
98         free( (char *) arg );
99
100         ldap_pvt_thread_mutex_lock( &ops_mutex );
101         ops_completed++;
102         ldap_pvt_thread_mutex_unlock( &ops_mutex );
103
104         ldap_pvt_thread_mutex_lock( &active_threads_mutex );
105         active_threads--;
106         if( active_threads < 1 ) {
107                 ldap_pvt_thread_cond_signal(&active_threads_cond);
108         }
109         ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
110         return NULL;
111 }
112
113 void
114 connection_activity(
115     Connection *conn
116 )
117 {
118         int status;
119         struct co_arg   *arg;
120         unsigned long   tag, len;
121         long            msgid;
122         BerElement      *ber;
123         char            *tmpdn;
124
125         if ( conn->c_currentber == NULL && (conn->c_currentber = ber_alloc())
126             == NULL ) {
127                 Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
128                 return;
129         }
130
131         errno = 0;
132         if ( (tag = ber_get_next( &conn->c_sb, &len, conn->c_currentber ))
133             != LDAP_TAG_MESSAGE ) {
134                 Debug( LDAP_DEBUG_TRACE,
135                     "ber_get_next on fd %d failed errno %d (%s)\n",
136                     lber_pvt_sb_get_desc(&conn->c_sb), errno, errno > -1 && errno < sys_nerr ?
137                     sys_errlist[errno] : "unknown" );
138                 Debug( LDAP_DEBUG_TRACE, "*** got %ld of %lu so far\n",
139                     (long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
140                     conn->c_currentber->ber_len, 0 );
141
142                 if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
143                         /* log, close and send error */
144                         ber_free( conn->c_currentber, 1 );
145                         conn->c_currentber = NULL;
146
147                         close_connection( conn, conn->c_connid, -1 );
148                 }
149
150                 return;
151         }
152         ber = conn->c_currentber;
153         conn->c_currentber = NULL;
154
155         if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
156                 /* log, close and send error */
157                 Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0,
158                     0 );
159                 ber_free( ber, 1 );
160
161                 close_connection( conn, conn->c_connid, -1 );
162                 return;
163         }
164
165         if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
166                 /* log, close and send error */
167                 Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0,
168                     0 );
169                 ber_free( ber, 1 );
170
171                 close_connection( conn, conn->c_connid, -1 );
172                 return;
173         }
174
175 #ifdef LDAP_COMPAT30
176         if ( conn->c_version == 30 ) {
177                 (void) ber_skip_tag( ber, &len );
178         }
179 #endif
180
181         arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
182         arg->co_conn = conn;
183
184         ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
185         if ( conn->c_dn != NULL ) {
186                 tmpdn = ch_strdup( conn->c_dn );
187         } else {
188                 tmpdn = NULL;
189         }
190         ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
191
192         ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
193         arg->co_op = slap_op_add( &conn->c_ops, ber, msgid, tag, tmpdn,
194             conn->c_ops_received, conn->c_connid );
195         ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
196
197         if ( tmpdn != NULL ) {
198                 free( tmpdn );
199         }
200
201         ldap_pvt_thread_mutex_lock( &active_threads_mutex );
202         active_threads++;
203         ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
204
205         status = ldap_pvt_thread_create( &arg->co_op->o_tid, 1,
206                                          connection_operation, (void *) arg );
207         if ( status != 0 ) {
208                 Debug( LDAP_DEBUG_ANY, "ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
209         }
210 }