static void ldap_connection_abort_request(struct ldap_op_queue_entry *req) { struct ldap_result res; /* too bad */ if (req->to_abort != NULL) timeout_remove(&req->to_abort); if (req->msgid > -1) ldap_abandon_ext(req->conn->conn, req->msgid, NULL, NULL); memset(&res, 0, sizeof(res)); res.openldap_ret = LDAP_TIMEOUT; res.error_string = "Aborting LDAP request after timeout"; if (req->result_callback != NULL) req->result_callback(&res, req->result_callback_ctx); unsigned int n = aqueue_count(req->conn->request_queue); for (unsigned int i = 0; i < n; i++) { struct ldap_op_queue_entry *const *reqp = array_idx(&(req->conn->request_array), aqueue_idx(req->conn->request_queue, i)); if (req == *reqp) { aqueue_delete(req->conn->request_queue, i); ldap_connection_request_destroy(&req); return; } } i_unreached(); }
static void ldap_connection_send_next(struct ldap_connection *conn) { unsigned int i = 0, n; struct ldap_op_queue_entry *req; if (conn->to_reconnect != NULL) timeout_remove(&(conn->to_reconnect)); if (conn->state == LDAP_STATE_DISCONNECT) { if (ldap_connection_connect(conn) == -1) conn->to_reconnect = timeout_add(1000, ldap_connection_send_next, conn); return; } if (conn->state != LDAP_STATE_CONNECT) { return; } if (conn->pending > 10) return; /* try again later */ req = NULL; /* get next request */ n = aqueue_count(conn->request_queue); for(i=0; i < n; i++) { struct ldap_op_queue_entry *const *reqp = array_idx(&(conn->request_array), aqueue_idx(conn->request_queue, i)); if ((*reqp)->msgid > -1) break; req = *reqp; } i--; /* nothing to actually send */ if (req == NULL) return; i_assert(req->msgid == -1); const char *error; int ret; if ((ret = req->send_request_cb(conn, req, &error)) != LDAP_SUCCESS) { /* did not succeed */ struct ldap_result res; memset(&res, 0, sizeof(res)); res.openldap_ret = ret; if (req->result_callback != NULL) req->result_callback(&res, req->result_callback_ctx); ldap_connection_request_destroy(&req); aqueue_delete(conn->request_queue, i); } else conn->pending++; }
static const char *test_aqueue2(unsigned int initial_size) { ARRAY(unsigned int) aqueue_array; unsigned int i, j, k; for (i = 0; i < N_ELEMENTS(aqueue_input); i++) { for (k = 0; k < N_ELEMENTS(aqueue_input); k++) { struct aqueue *aqueue; t_array_init(&aqueue_array, initial_size); aqueue = aqueue_init(&aqueue_array.arr); aqueue->head = aqueue->tail = initial_size - 1; for (j = 0; j < k; j++) { aqueue_append(aqueue, &aqueue_input[j]); if (aqueue_count(aqueue) != j + 1) { return t_strdup_printf("Wrong count after append %u vs %u)", aqueue_count(aqueue), j + 1); } if (!aqueue_is_ok(aqueue, UINT_MAX)) return "Invalid data after append"; } if (k != 0 && i < k) { aqueue_delete(aqueue, i); if (aqueue_count(aqueue) != k - 1) return "Wrong count after delete"; if (!aqueue_is_ok(aqueue, i)) return "Invalid data after delete"; } aqueue_clear(aqueue); if (aqueue_count(aqueue) != 0) return "aqueue_clear() broken"; aqueue_deinit(&aqueue); } } return NULL; }
void aqueue_delete_tail(struct aqueue *aqueue) { aqueue_delete(aqueue, 0); }
static int ldap_connection_handle_message(struct ldap_connection *conn, LDAPMessage *message) { struct ldap_op_queue_entry *req; unsigned int i = 0; bool finished = FALSE; int err = LDAP_SUCCESS; /* we need to look at who it was for */ req = ldap_connection_find_req_by_msgid(conn, ldap_msgid(message), &i); if (req != NULL) err = req->internal_response_cb(conn, req, message, &finished); ldap_msgfree(message); switch(err) { case LDAP_SUCCESS: break; case LDAP_SERVER_DOWN: #ifdef LDAP_CONNECT_ERROR case LDAP_CONNECT_ERROR: #endif case LDAP_UNAVAILABLE: case LDAP_OPERATIONS_ERROR: case LDAP_BUSY: /* requeue */ ldap_connection_kill(conn); ldap_connection_send_next(conn); finished = FALSE; break; case LDAP_INVALID_CREDENTIALS: { /* fail everything */ ldap_connection_kill(conn); ldap_connection_abort_all_requests(conn); return 0; } case LDAP_SIZELIMIT_EXCEEDED: case LDAP_TIMELIMIT_EXCEEDED: case LDAP_NO_SUCH_ATTRIBUTE: case LDAP_UNDEFINED_TYPE: case LDAP_INAPPROPRIATE_MATCHING: case LDAP_CONSTRAINT_VIOLATION: case LDAP_TYPE_OR_VALUE_EXISTS: case LDAP_INVALID_SYNTAX: case LDAP_NO_SUCH_OBJECT: case LDAP_ALIAS_PROBLEM: case LDAP_INVALID_DN_SYNTAX: case LDAP_IS_LEAF: case LDAP_ALIAS_DEREF_PROBLEM: case LDAP_FILTER_ERROR: case LDAP_LOCAL_ERROR: finished = TRUE; break; default: /* ignore */ break; } if (finished) { i_assert(req != NULL); ldap_connection_request_destroy(&req); conn->pending--; aqueue_delete(conn->request_queue, i); return 1; } return 0; }