BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file PacketPassFifoQueue.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stdlib.h>
31  
32 #include <misc/debug.h>
33 #include <misc/offset.h>
34  
35 #include "PacketPassFifoQueue.h"
36  
37 static void schedule (PacketPassFifoQueue *o)
38 {
39 ASSERT(!o->freeing)
40 ASSERT(!o->sending_flow)
41 ASSERT(!LinkedList1_IsEmpty(&o->waiting_flows_list))
42 ASSERT(!BPending_IsSet(&o->schedule_job))
43  
44 // get first waiting flow
45 PacketPassFifoQueueFlow *flow = UPPER_OBJECT(LinkedList1_GetFirst(&o->waiting_flows_list), PacketPassFifoQueueFlow, waiting_flows_list_node);
46 ASSERT(flow->queue == o)
47 ASSERT(flow->is_waiting)
48  
49 // remove it from queue
50 LinkedList1_Remove(&o->waiting_flows_list, &flow->waiting_flows_list_node);
51 flow->is_waiting = 0;
52  
53 // send
54 PacketPassInterface_Sender_Send(o->output, flow->waiting_data, flow->waiting_len);
55 o->sending_flow = flow;
56 }
57  
58 static void schedule_job_handler (PacketPassFifoQueue *o)
59 {
60 DebugObject_Access(&o->d_obj);
61 ASSERT(!o->freeing)
62 ASSERT(!o->sending_flow)
63  
64 if (!LinkedList1_IsEmpty(&o->waiting_flows_list)) {
65 schedule(o);
66 }
67 }
68  
69 static void input_handler_send (PacketPassFifoQueueFlow *o, uint8_t *data, int data_len)
70 {
71 PacketPassFifoQueue *queue = o->queue;
72 DebugObject_Access(&o->d_obj);
73 ASSERT(!o->is_waiting)
74 ASSERT(o != queue->sending_flow)
75 ASSERT(!queue->freeing)
76  
77 // queue flow
78 o->waiting_data = data;
79 o->waiting_len = data_len;
80 LinkedList1_Append(&queue->waiting_flows_list, &o->waiting_flows_list_node);
81 o->is_waiting = 1;
82  
83 // schedule
84 if (!queue->sending_flow && !BPending_IsSet(&queue->schedule_job)) {
85 schedule(queue);
86 }
87 }
88  
89 static void output_handler_done (PacketPassFifoQueue *o)
90 {
91 DebugObject_Access(&o->d_obj);
92 ASSERT(o->sending_flow)
93 ASSERT(!BPending_IsSet(&o->schedule_job))
94 ASSERT(!o->freeing)
95 ASSERT(!o->sending_flow->is_waiting)
96  
97 PacketPassFifoQueueFlow *flow = o->sending_flow;
98  
99 // set no sending flow
100 o->sending_flow = NULL;
101  
102 // schedule schedule job
103 BPending_Set(&o->schedule_job);
104  
105 // done input
106 PacketPassInterface_Done(&flow->input);
107  
108 // call busy handler if set
109 if (flow->handler_busy) {
110 // handler is one-shot, unset it before calling
111 PacketPassFifoQueue_handler_busy handler = flow->handler_busy;
112 flow->handler_busy = NULL;
113  
114 // call handler
115 handler(flow->user);
116 return;
117 }
118 }
119  
120 void PacketPassFifoQueue_Init (PacketPassFifoQueue *o, PacketPassInterface *output, BPendingGroup *pg)
121 {
122 // init arguments
123 o->output = output;
124 o->pg = pg;
125  
126 // init output
127 PacketPassInterface_Sender_Init(output, (PacketPassInterface_handler_done)output_handler_done, o);
128  
129 // init waiting flows list
130 LinkedList1_Init(&o->waiting_flows_list);
131  
132 // set no sending flow
133 o->sending_flow = NULL;
134  
135 // init schedule job
136 BPending_Init(&o->schedule_job, pg, (BPending_handler)schedule_job_handler, o);
137  
138 // set not freeing
139 o->freeing = 0;
140  
141 DebugCounter_Init(&o->d_flows_ctr);
142 DebugObject_Init(&o->d_obj);
143 }
144  
145 void PacketPassFifoQueue_Free (PacketPassFifoQueue *o)
146 {
147 DebugObject_Free(&o->d_obj);
148 DebugCounter_Free(&o->d_flows_ctr);
149 ASSERT(LinkedList1_IsEmpty(&o->waiting_flows_list))
150 ASSERT(!o->sending_flow)
151  
152 // free schedule job
153 BPending_Free(&o->schedule_job);
154 }
155  
156 void PacketPassFifoQueue_PrepareFree (PacketPassFifoQueue *o)
157 {
158 DebugObject_Access(&o->d_obj);
159  
160 // set freeing
161 o->freeing = 1;
162 }
163  
164 void PacketPassFifoQueueFlow_Init (PacketPassFifoQueueFlow *o, PacketPassFifoQueue *queue)
165 {
166 DebugObject_Access(&queue->d_obj);
167 ASSERT(!queue->freeing)
168  
169 // init arguments
170 o->queue = queue;
171  
172 // init input
173 PacketPassInterface_Init(&o->input, PacketPassInterface_GetMTU(queue->output), (PacketPassInterface_handler_send)input_handler_send, o, queue->pg);
174  
175 // set not waiting
176 o->is_waiting = 0;
177  
178 // set no busy handler
179 o->handler_busy = NULL;
180  
181 DebugCounter_Increment(&queue->d_flows_ctr);
182 DebugObject_Init(&o->d_obj);
183 }
184  
185 void PacketPassFifoQueueFlow_Free (PacketPassFifoQueueFlow *o)
186 {
187 PacketPassFifoQueue *queue = o->queue;
188 DebugObject_Free(&o->d_obj);
189 DebugCounter_Decrement(&queue->d_flows_ctr);
190 ASSERT(queue->freeing || o != queue->sending_flow)
191  
192 // remove from sending flow
193 if (o == queue->sending_flow) {
194 queue->sending_flow = NULL;
195 }
196  
197 // remove from waiting flows list
198 if (o->is_waiting) {
199 LinkedList1_Remove(&queue->waiting_flows_list, &o->waiting_flows_list_node);
200 }
201  
202 // free input
203 PacketPassInterface_Free(&o->input);
204 }
205  
206 void PacketPassFifoQueueFlow_AssertFree (PacketPassFifoQueueFlow *o)
207 {
208 PacketPassFifoQueue *queue = o->queue;
209 B_USE(queue)
210 DebugObject_Access(&o->d_obj);
211 ASSERT(queue->freeing || o != queue->sending_flow)
212 }
213  
214 int PacketPassFifoQueueFlow_IsBusy (PacketPassFifoQueueFlow *o)
215 {
216 PacketPassFifoQueue *queue = o->queue;
217 DebugObject_Access(&o->d_obj);
218 ASSERT(!queue->freeing)
219  
220 return (o == queue->sending_flow);
221 }
222  
223 void PacketPassFifoQueueFlow_SetBusyHandler (PacketPassFifoQueueFlow *o, PacketPassFifoQueue_handler_busy handler_busy, void *user)
224 {
225 PacketPassFifoQueue *queue = o->queue;
226 B_USE(queue)
227 DebugObject_Access(&o->d_obj);
228 ASSERT(!queue->freeing)
229 ASSERT(o == queue->sending_flow)
230  
231 // set (or unset) busy handler
232 o->handler_busy = handler_busy;
233 o->user = user;
234 }
235  
236 PacketPassInterface * PacketPassFifoQueueFlow_GetInput (PacketPassFifoQueueFlow *o)
237 {
238 DebugObject_Access(&o->d_obj);
239  
240 return &o->input;
241 }