Move pqueue into ssl
[openssl.git] / ssl / pqueue.c
1 /* crypto/pqueue/pqueue.c */
2 /*
3  * DTLS implementation written by Nagendra Modadugu
4  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5  */
6 /* ====================================================================
7  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    openssl-core@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This product includes cryptographic software written by Eric Young
55  * (eay@cryptsoft.com).  This product includes software written by Tim
56  * Hudson (tjh@cryptsoft.com).
57  *
58  */
59
60 #include "ssl_locl.h"
61 #include <openssl/bn.h>
62
63 struct pqueue_st {
64     pitem *items;
65     int count;
66 };
67
68 pitem *pitem_new(unsigned char *prio64be, void *data)
69 {
70     pitem *item = OPENSSL_malloc(sizeof(*item));
71     if (item == NULL)
72         return NULL;
73
74     memcpy(item->priority, prio64be, sizeof(item->priority));
75
76     item->data = data;
77     item->next = NULL;
78
79     return item;
80 }
81
82 void pitem_free(pitem *item)
83 {
84     OPENSSL_free(item);
85 }
86
87 pqueue *pqueue_new()
88 {
89     pqueue *pq = OPENSSL_zalloc(sizeof(*pq));
90
91     return pq;
92 }
93
94 void pqueue_free(pqueue *pq)
95 {
96     OPENSSL_free(pq);
97 }
98
99 pitem *pqueue_insert(pqueue *pq, pitem *item)
100 {
101     pitem *curr, *next;
102
103     if (pq->items == NULL) {
104         pq->items = item;
105         return item;
106     }
107
108     for (curr = NULL, next = pq->items;
109          next != NULL; curr = next, next = next->next) {
110         /*
111          * we can compare 64-bit value in big-endian encoding with memcmp:-)
112          */
113         int cmp = memcmp(next->priority, item->priority, 8);
114         if (cmp > 0) {          /* next > item */
115             item->next = next;
116
117             if (curr == NULL)
118                 pq->items = item;
119             else
120                 curr->next = item;
121
122             return item;
123         }
124
125         else if (cmp == 0)      /* duplicates not allowed */
126             return NULL;
127     }
128
129     item->next = NULL;
130     curr->next = item;
131
132     return item;
133 }
134
135 pitem *pqueue_peek(pqueue *pq)
136 {
137     return pq->items;
138 }
139
140 pitem *pqueue_pop(pqueue *pq)
141 {
142     pitem *item = pq->items;
143
144     if (pq->items != NULL)
145         pq->items = pq->items->next;
146
147     return item;
148 }
149
150 pitem *pqueue_find(pqueue *pq, unsigned char *prio64be)
151 {
152     pitem *next;
153     pitem *found = NULL;
154
155     if (pq->items == NULL)
156         return NULL;
157
158     for (next = pq->items; next->next != NULL; next = next->next) {
159         if (memcmp(next->priority, prio64be, 8) == 0) {
160             found = next;
161             break;
162         }
163     }
164
165     /* check the one last node */
166     if (memcmp(next->priority, prio64be, 8) == 0)
167         found = next;
168
169     if (!found)
170         return NULL;
171
172     return found;
173 }
174
175 void pqueue_print(pqueue *pq)
176 {
177     pitem *item = pq->items;
178
179     while (item != NULL) {
180         printf("item\t%02x%02x%02x%02x%02x%02x%02x%02x\n",
181                item->priority[0], item->priority[1],
182                item->priority[2], item->priority[3],
183                item->priority[4], item->priority[5],
184                item->priority[6], item->priority[7]);
185         item = item->next;
186     }
187 }
188
189 pitem *pqueue_iterator(pqueue *pq)
190 {
191     return pqueue_peek(pq);
192 }
193
194 pitem *pqueue_next(pitem **item)
195 {
196     pitem *ret;
197
198     if (item == NULL || *item == NULL)
199         return NULL;
200
201     /* *item != NULL */
202     ret = *item;
203     *item = (*item)->next;
204
205     return ret;
206 }
207
208 int pqueue_size(pqueue *pq)
209 {
210     pitem *item = pq->items;
211     int count = 0;
212
213     while (item != NULL) {
214         count++;
215         item = item->next;
216     }
217     return count;
218 }