svn cleanup
[anytun.git] / openvpn / mbuf.c
blob871bdbabf87a15c2a0c68049f76828a406b2c536
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #ifdef WIN32
26 #include "config-win32.h"
27 #else
28 #include "config.h"
29 #endif
31 #include "syshead.h"
33 #if P2MP
35 #include "buffer.h"
36 #include "error.h"
37 #include "misc.h"
38 #include "mbuf.h"
40 #include "memdbg.h"
42 struct mbuf_set *
43 mbuf_init (unsigned int size)
45 struct mbuf_set *ret;
46 ALLOC_OBJ_CLEAR (ret, struct mbuf_set);
47 mutex_init (&ret->mutex);
48 ret->capacity = adjust_power_of_2 (size);
49 ALLOC_ARRAY (ret->array, struct mbuf_item, ret->capacity);
50 return ret;
53 void
54 mbuf_free (struct mbuf_set *ms)
56 if (ms)
58 int i;
59 for (i = 0; i < (int) ms->len; ++i)
61 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
62 mbuf_free_buf (item->buffer);
64 free (ms->array);
65 mutex_destroy (&ms->mutex);
66 free (ms);
70 struct mbuf_buffer *
71 mbuf_alloc_buf (const struct buffer *buf)
73 struct mbuf_buffer *ret;
74 ALLOC_OBJ (ret, struct mbuf_buffer);
75 ret->buf = clone_buf (buf);
76 ret->refcount = 1;
77 ret->flags = 0;
78 return ret;
81 void
82 mbuf_free_buf (struct mbuf_buffer *mb)
84 if (mb)
86 if (--mb->refcount <= 0)
88 free_buf (&mb->buf);
89 free (mb);
94 void
95 mbuf_add_item (struct mbuf_set *ms, const struct mbuf_item *item)
97 ASSERT (ms);
98 mutex_lock (&ms->mutex);
99 if (ms->len == ms->capacity)
101 struct mbuf_item rm;
102 ASSERT (mbuf_extract_item (ms, &rm, false));
103 mbuf_free_buf (rm.buffer);
104 msg (D_MULTI_DROPPED, "MBUF: mbuf packet dropped");
107 ASSERT (ms->len < ms->capacity);
109 ms->array[MBUF_INDEX(ms->head, ms->len, ms->capacity)] = *item;
110 if (++ms->len > ms->max_queued)
111 ms->max_queued = ms->len;
112 ++item->buffer->refcount;
113 mutex_unlock (&ms->mutex);
116 bool
117 mbuf_extract_item (struct mbuf_set *ms, struct mbuf_item *item, const bool lock)
119 bool ret = false;
120 if (ms)
122 if (lock)
123 mutex_lock (&ms->mutex);
124 while (ms->len)
126 *item = ms->array[ms->head];
127 ms->head = MBUF_INDEX(ms->head, 1, ms->capacity);
128 --ms->len;
129 if (item->instance) /* ignore dereferenced instances */
131 ret = true;
132 break;
135 if (lock)
136 mutex_unlock (&ms->mutex);
138 return ret;
141 struct multi_instance *
142 mbuf_peek_dowork (struct mbuf_set *ms)
144 struct multi_instance *ret = NULL;
145 if (ms)
147 int i;
148 mutex_lock (&ms->mutex);
149 for (i = 0; i < (int) ms->len; ++i)
151 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
152 if (item->instance)
154 ret = item->instance;
155 break;
158 mutex_unlock (&ms->mutex);
160 return ret;
163 void
164 mbuf_dereference_instance (struct mbuf_set *ms, struct multi_instance *mi)
166 if (ms)
168 int i;
169 mutex_lock (&ms->mutex);
170 for (i = 0; i < (int) ms->len; ++i)
172 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
173 if (item->instance == mi)
175 mbuf_free_buf (item->buffer);
176 item->buffer = NULL;
177 item->instance = NULL;
178 msg (D_MBUF, "MBUF: dereferenced queued packet");
181 mutex_unlock (&ms->mutex);
185 #else
186 static void dummy(void) {}
187 #endif /* P2MP */