2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include "internal/event_queue.h"
12 #include "ssl_local.h"
14 struct ossl_event_queue_st {
15 PRIORITY_QUEUE_OF(OSSL_EVENT) *timed_events;
16 PRIORITY_QUEUE_OF(OSSL_EVENT) *now_events;
19 static int event_compare_times(const OSSL_EVENT *a, const OSSL_EVENT *b)
21 return ossl_time_compare(a->when, b->when);
24 static int event_compare_priority(const OSSL_EVENT *a, const OSSL_EVENT *b)
26 if (a->priority > b->priority)
28 if (a->priority < b->priority)
33 OSSL_EVENT_QUEUE *ossl_event_queue_new(void)
35 OSSL_EVENT_QUEUE *r = OPENSSL_malloc(sizeof(*r));
38 r->timed_events = ossl_pqueue_OSSL_EVENT_new(&event_compare_times);
39 r->now_events = ossl_pqueue_OSSL_EVENT_new(&event_compare_priority);
40 if (r->timed_events == NULL || r->now_events == NULL) {
41 ossl_event_queue_free(r);
48 void ossl_event_free(OSSL_EVENT *event)
51 if (event->flag_dynamic)
58 static void event_queue_free(PRIORITY_QUEUE_OF(OSSL_EVENT) *queue)
63 while ((e = ossl_pqueue_OSSL_EVENT_pop(queue)) != NULL)
65 ossl_pqueue_OSSL_EVENT_free(queue);
69 void ossl_event_queue_free(OSSL_EVENT_QUEUE *queue)
72 event_queue_free(queue->now_events);
73 event_queue_free(queue->timed_events);
79 int event_queue_add(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event)
81 PRIORITY_QUEUE_OF(OSSL_EVENT) *pq =
82 ossl_time_compare(event->when, ossl_time_now()) <= 0
84 : queue->timed_events;
86 if (ossl_pqueue_OSSL_EVENT_push(pq, event, &event->ref)) {
94 void ossl_event_set(OSSL_EVENT *event, uint32_t type, uint32_t priority,
95 OSSL_TIME when, void *ctx,
96 void *payload, size_t payload_size)
99 event->priority = priority;
102 event->payload = payload;
103 event->payload_size = payload_size;
106 OSSL_EVENT *ossl_event_queue_add_new(OSSL_EVENT_QUEUE *queue,
107 uint32_t type, uint32_t priority,
108 OSSL_TIME when, void *ctx,
109 void *payload, size_t payload_size)
111 OSSL_EVENT *e = OPENSSL_malloc(sizeof(*e));
113 if (e == NULL || queue == NULL) {
118 ossl_event_set(e, type, priority, when, ctx, payload, payload_size);
120 if (event_queue_add(queue, e))
126 int ossl_event_queue_add(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event,
127 uint32_t type, uint32_t priority,
128 OSSL_TIME when, void *ctx,
129 void *payload, size_t payload_size)
131 if (event == NULL || queue == NULL)
133 ossl_event_set(event, type, priority, when, ctx, payload, payload_size);
134 event->flag_dynamic = 0;
135 return event_queue_add(queue, event);
138 int ossl_event_queue_remove(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event)
140 if (event != NULL && event->queue != NULL) {
141 ossl_pqueue_OSSL_EVENT_remove(event->queue, event->ref);
147 OSSL_TIME ossl_event_time_until(const OSSL_EVENT *event)
150 return ossl_time_infinite();
151 return ossl_time_subtract(event->when, ossl_time_now());
154 OSSL_TIME ossl_event_queue_time_until_next(const OSSL_EVENT_QUEUE *queue)
157 return ossl_time_infinite();
158 if (ossl_pqueue_OSSL_EVENT_num(queue->now_events) > 0)
159 return ossl_time_zero();
160 return ossl_event_time_until(ossl_pqueue_OSSL_EVENT_peek(queue->timed_events));
163 int ossl_event_queue_postpone_until(OSSL_EVENT_QUEUE *queue,
167 if (ossl_event_queue_remove(queue, event)) {
169 return event_queue_add(queue, event);
174 int ossl_event_queue_get1_next_event(OSSL_EVENT_QUEUE *queue,
177 OSSL_TIME now = ossl_time_now();
180 /* Check for expired timer based events and convert them to now events */
181 while ((e = ossl_pqueue_OSSL_EVENT_peek(queue->timed_events)) != NULL
182 && ossl_time_compare(e->when, now) <= 0) {
183 e = ossl_pqueue_OSSL_EVENT_pop(queue->timed_events);
184 if (!ossl_pqueue_OSSL_EVENT_push(queue->now_events, e, &e->ref)) {
191 * Get next event from the now queue.
192 * The pop returns NULL when there is none.
194 *event = ossl_pqueue_OSSL_EVENT_pop(queue->now_events);