]> git.ipfire.org Git - thirdparty/openssl.git/blame - ssl/event_queue.c
Copyright year updates
[thirdparty/openssl.git] / ssl / event_queue.c
CommitLineData
e6be47e4 1/*
da1c088f 2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
e6be47e4
P
3 *
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
8 */
9
10#include <stdlib.h>
11#include "internal/event_queue.h"
12#include "crypto/sparse_array.h"
13#include "ssl_local.h"
14
15struct ossl_event_queue_st {
16 PRIORITY_QUEUE_OF(OSSL_EVENT) *timed_events;
17 PRIORITY_QUEUE_OF(OSSL_EVENT) *now_events;
18};
19
20static int event_compare_times(const OSSL_EVENT *a, const OSSL_EVENT *b)
21{
22 return ossl_time_compare(a->when, b->when);
23}
24
25static int event_compare_priority(const OSSL_EVENT *a, const OSSL_EVENT *b)
26{
27 if (a->priority > b->priority)
28 return -1;
29 if (a->priority < b->priority)
30 return 1;
31 return 0;
32}
33
34OSSL_EVENT_QUEUE *ossl_event_queue_new(void)
35{
36 OSSL_EVENT_QUEUE *r = OPENSSL_malloc(sizeof(*r));
37
38 if (r != NULL) {
39 r->timed_events = ossl_pqueue_OSSL_EVENT_new(&event_compare_times);
40 r->now_events = ossl_pqueue_OSSL_EVENT_new(&event_compare_priority);
41 if (r->timed_events == NULL || r->now_events == NULL) {
42 ossl_event_queue_free(r);
43 return NULL;
44 }
45 }
46 return r;
47}
48
49void ossl_event_free(OSSL_EVENT *event)
50{
51 if (event != NULL) {
52 if (event->flag_dynamic)
53 OPENSSL_free(event);
54 else
55 event->queue = NULL;
56 }
57}
58
59static void event_queue_free(PRIORITY_QUEUE_OF(OSSL_EVENT) *queue)
60{
61 OSSL_EVENT *e;
62
63 if (queue != NULL) {
64 while ((e = ossl_pqueue_OSSL_EVENT_pop(queue)) != NULL)
65 ossl_event_free(e);
66 ossl_pqueue_OSSL_EVENT_free(queue);
67 }
68}
69
70void ossl_event_queue_free(OSSL_EVENT_QUEUE *queue)
71{
72 if (queue != NULL) {
73 event_queue_free(queue->now_events);
74 event_queue_free(queue->timed_events);
75 OPENSSL_free(queue);
76 }
77}
78
79static ossl_inline
80int event_queue_add(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event)
81{
82 PRIORITY_QUEUE_OF(OSSL_EVENT) *pq =
83 ossl_time_compare(event->when, ossl_time_now()) <= 0
84 ? queue->now_events
85 : queue->timed_events;
86
87 if (ossl_pqueue_OSSL_EVENT_push(pq, event, &event->ref)) {
88 event->queue = pq;
89 return 1;
90 }
91 return 0;
92}
93
94static ossl_inline
95void ossl_event_set(OSSL_EVENT *event, uint32_t type, uint32_t priority,
96 OSSL_TIME when, void *ctx,
97 void *payload, size_t payload_size)
98{
99 event->type = type;
100 event->priority = priority;
101 event->when = when;
102 event->ctx = ctx;
103 event->payload = payload;
104 event->payload_size = payload_size;
105}
106
107OSSL_EVENT *ossl_event_queue_add_new(OSSL_EVENT_QUEUE *queue,
108 uint32_t type, uint32_t priority,
109 OSSL_TIME when, void *ctx,
110 void *payload, size_t payload_size)
111{
112 OSSL_EVENT *e = OPENSSL_malloc(sizeof(*e));
113
77a66117
HL
114 if (e == NULL || queue == NULL) {
115 OPENSSL_free(e);
e6be47e4 116 return NULL;
77a66117
HL
117 }
118
e6be47e4
P
119 ossl_event_set(e, type, priority, when, ctx, payload, payload_size);
120 e->flag_dynamic = 1;
121 if (event_queue_add(queue, e))
122 return e;
123 OPENSSL_free(e);
124 return NULL;
125}
126
127int ossl_event_queue_add(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event,
128 uint32_t type, uint32_t priority,
129 OSSL_TIME when, void *ctx,
130 void *payload, size_t payload_size)
131{
132 if (event == NULL || queue == NULL)
133 return 0;
134 ossl_event_set(event, type, priority, when, ctx, payload, payload_size);
135 event->flag_dynamic = 0;
136 return event_queue_add(queue, event);
137}
138
139int ossl_event_queue_remove(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event)
140{
141 if (event != NULL && event->queue != NULL) {
142 ossl_pqueue_OSSL_EVENT_remove(event->queue, event->ref);
143 event->queue = NULL;
144 }
145 return 1;
146}
147
148OSSL_TIME ossl_event_time_until(const OSSL_EVENT *event)
149{
150 if (event == NULL)
d13c8b77 151 return ossl_time_infinite();
e6be47e4
P
152 return ossl_time_subtract(event->when, ossl_time_now());
153}
154
155OSSL_TIME ossl_event_queue_time_until_next(const OSSL_EVENT_QUEUE *queue)
156{
157 if (queue == NULL)
d13c8b77 158 return ossl_time_infinite();
e6be47e4 159 if (ossl_pqueue_OSSL_EVENT_num(queue->now_events) > 0)
d13c8b77 160 return ossl_time_zero();
e6be47e4
P
161 return ossl_event_time_until(ossl_pqueue_OSSL_EVENT_peek(queue->timed_events));
162}
163
164int ossl_event_queue_postpone_until(OSSL_EVENT_QUEUE *queue,
165 OSSL_EVENT *event,
166 OSSL_TIME when)
167{
168 if (ossl_event_queue_remove(queue, event)) {
169 event->when = when;
170 return event_queue_add(queue, event);
171 }
172 return 0;
173}
174
175int ossl_event_queue_get1_next_event(OSSL_EVENT_QUEUE *queue,
176 OSSL_EVENT **event)
177{
178 OSSL_TIME now = ossl_time_now();
179 OSSL_EVENT *e;
180
181 /* Check for expired timer based events and convert them to now events */
182 while ((e = ossl_pqueue_OSSL_EVENT_peek(queue->timed_events)) != NULL
183 && ossl_time_compare(e->when, now) <= 0) {
184 e = ossl_pqueue_OSSL_EVENT_pop(queue->timed_events);
185 if (!ossl_pqueue_OSSL_EVENT_push(queue->now_events, e, &e->ref)) {
186 e->queue = NULL;
187 return 0;
188 }
189 }
190
191 /*
192 * Get next event from the now queue.
193 * The pop returns NULL when there is none.
194 */
195 *event = ossl_pqueue_OSSL_EVENT_pop(queue->now_events);
196 return 1;
197}