BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file DPRelay.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 #include <string.h>
32  
33 #include <misc/offset.h>
34 #include <base/BLog.h>
35  
36 #include <client/DPRelay.h>
37  
38 #include <generated/blog_channel_DPRelay.h>
39  
40 static void flow_inactivity_handler (struct DPRelay_flow *flow);
41  
42 static struct DPRelay_flow * create_flow (DPRelaySource *src, DPRelaySink *sink, int num_packets, int inactivity_time)
43 {
44 ASSERT(num_packets > 0)
45  
46 // allocate structure
47 struct DPRelay_flow *flow = (struct DPRelay_flow *)malloc(sizeof(*flow));
48 if (!flow) {
49 BLog(BLOG_ERROR, "relay flow %d->%d: malloc failed", (int)src->source_id, (int)sink->dest_id);
50 goto fail0;
51 }
52  
53 // set src and sink
54 flow->src = src;
55 flow->sink = sink;
56  
57 // init DataProtoFlow
58 if (!DataProtoFlow_Init(&flow->dp_flow, &src->router->dp_source, src->source_id, sink->dest_id, num_packets, inactivity_time, flow, (DataProtoFlow_handler_inactivity)flow_inactivity_handler)) {
59 BLog(BLOG_ERROR, "relay flow %d->%d: DataProtoFlow_Init failed", (int)src->source_id, (int)sink->dest_id);
60 goto fail1;
61 }
62  
63 // insert to source list
64 LinkedList1_Append(&src->flows_list, &flow->src_list_node);
65  
66 // insert to sink list
67 LinkedList1_Append(&sink->flows_list, &flow->sink_list_node);
68  
69 // attach flow if needed
70 if (sink->dp_sink) {
71 DataProtoFlow_Attach(&flow->dp_flow, sink->dp_sink);
72 }
73  
74 BLog(BLOG_INFO, "relay flow %d->%d: created", (int)src->source_id, (int)sink->dest_id);
75  
76 return flow;
77  
78 fail1:
79 free(flow);
80 fail0:
81 return NULL;
82 }
83  
84 static void free_flow (struct DPRelay_flow *flow)
85 {
86 // detach flow if needed
87 if (flow->sink->dp_sink) {
88 DataProtoFlow_Detach(&flow->dp_flow);
89 }
90  
91 // remove posible router reference
92 if (flow->src->router->current_flow == flow) {
93 flow->src->router->current_flow = NULL;
94 }
95  
96 // remove from sink list
97 LinkedList1_Remove(&flow->sink->flows_list, &flow->sink_list_node);
98  
99 // remove from source list
100 LinkedList1_Remove(&flow->src->flows_list, &flow->src_list_node);
101  
102 // free DataProtoFlow
103 DataProtoFlow_Free(&flow->dp_flow);
104  
105 // free structore
106 free(flow);
107 }
108  
109 static void flow_inactivity_handler (struct DPRelay_flow *flow)
110 {
111 BLog(BLOG_INFO, "relay flow %d->%d: timed out", (int)flow->src->source_id, (int)flow->sink->dest_id);
112  
113 free_flow(flow);
114 }
115  
116 static struct DPRelay_flow * source_find_flow (DPRelaySource *o, DPRelaySink *sink)
117 {
118 for (LinkedList1Node *node = LinkedList1_GetFirst(&o->flows_list); node; node = LinkedList1Node_Next(node)) {
119 struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, src_list_node);
120 ASSERT(flow->src == o)
121 if (flow->sink == sink) {
122 return flow;
123 }
124 }
125  
126 return NULL;
127 }
128  
129 static void router_dp_source_handler (DPRelayRouter *o, const uint8_t *frame, int frame_len)
130 {
131 DebugObject_Access(&o->d_obj);
132  
133 if (!o->current_flow) {
134 return;
135 }
136  
137 // route frame to current flow
138 DataProtoFlow_Route(&o->current_flow->dp_flow, 0);
139  
140 // set no current flow
141 o->current_flow = NULL;
142 }
143  
144 int DPRelayRouter_Init (DPRelayRouter *o, int frame_mtu, BReactor *reactor)
145 {
146 ASSERT(frame_mtu >= 0)
147 ASSERT(frame_mtu <= INT_MAX - DATAPROTO_MAX_OVERHEAD)
148  
149 // init arguments
150 o->frame_mtu = frame_mtu;
151  
152 // init BufferWriter
153 BufferWriter_Init(&o->writer, frame_mtu, BReactor_PendingGroup(reactor));
154  
155 // init DataProtoSource
156 if (!DataProtoSource_Init(&o->dp_source, BufferWriter_GetOutput(&o->writer), (DataProtoSource_handler)router_dp_source_handler, o, reactor)) {
157 BLog(BLOG_ERROR, "DataProtoSource_Init failed");
158 goto fail1;
159 }
160  
161 // have no current flow
162 o->current_flow = NULL;
163  
164 DebugCounter_Init(&o->d_ctr);
165 DebugObject_Init(&o->d_obj);
166 return 1;
167  
168 fail1:
169 BufferWriter_Free(&o->writer);
170 return 0;
171 }
172  
173 void DPRelayRouter_Free (DPRelayRouter *o)
174 {
175 DebugObject_Free(&o->d_obj);
176 DebugCounter_Free(&o->d_ctr);
177 ASSERT(!o->current_flow) // have no sources
178  
179 // free DataProtoSource
180 DataProtoSource_Free(&o->dp_source);
181  
182 // free BufferWriter
183 BufferWriter_Free(&o->writer);
184 }
185  
186 void DPRelayRouter_SubmitFrame (DPRelayRouter *o, DPRelaySource *src, DPRelaySink *sink, uint8_t *data, int data_len, int num_packets, int inactivity_time)
187 {
188 DebugObject_Access(&o->d_obj);
189 DebugObject_Access(&src->d_obj);
190 DebugObject_Access(&sink->d_obj);
191 ASSERT(!o->current_flow)
192 ASSERT(src->router == o)
193 ASSERT(data_len >= 0)
194 ASSERT(data_len <= o->frame_mtu)
195 ASSERT(num_packets > 0)
196  
197 // get memory location
198 uint8_t *out;
199 if (!BufferWriter_StartPacket(&o->writer, &out)) {
200 BLog(BLOG_ERROR, "BufferWriter_StartPacket failed for frame %d->%d !?", (int)src->source_id, (int)sink->dest_id);
201 return;
202 }
203  
204 // write frame
205 memcpy(out, data, data_len);
206  
207 // submit frame
208 BufferWriter_EndPacket(&o->writer, data_len);
209  
210 // get a flow
211 // this comes _after_ writing the packet, in case flow initialization schedules jobs
212 struct DPRelay_flow *flow = source_find_flow(src, sink);
213 if (!flow) {
214 if (!(flow = create_flow(src, sink, num_packets, inactivity_time))) {
215 return;
216 }
217 }
218  
219 // remember flow so we know where to route the frame in router_dp_source_handler
220 o->current_flow = flow;
221 }
222  
223 void DPRelaySource_Init (DPRelaySource *o, DPRelayRouter *router, peerid_t source_id, BReactor *reactor)
224 {
225 DebugObject_Access(&router->d_obj);
226  
227 // init arguments
228 o->router = router;
229 o->source_id = source_id;
230  
231 // init flows list
232 LinkedList1_Init(&o->flows_list);
233  
234 DebugCounter_Increment(&o->router->d_ctr);
235 DebugObject_Init(&o->d_obj);
236 }
237  
238 void DPRelaySource_Free (DPRelaySource *o)
239 {
240 DebugObject_Free(&o->d_obj);
241 DebugCounter_Decrement(&o->router->d_ctr);
242  
243 // free flows, detaching them if needed
244 LinkedList1Node *node;
245 while (node = LinkedList1_GetFirst(&o->flows_list)) {
246 struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, src_list_node);
247 free_flow(flow);
248 }
249 }
250  
251 void DPRelaySink_Init (DPRelaySink *o, peerid_t dest_id)
252 {
253 // init arguments
254 o->dest_id = dest_id;
255  
256 // init flows list
257 LinkedList1_Init(&o->flows_list);
258  
259 // have no sink
260 o->dp_sink = NULL;
261  
262 DebugObject_Init(&o->d_obj);
263 }
264  
265 void DPRelaySink_Free (DPRelaySink *o)
266 {
267 DebugObject_Free(&o->d_obj);
268 ASSERT(!o->dp_sink)
269  
270 // free flows
271 LinkedList1Node *node;
272 while (node = LinkedList1_GetFirst(&o->flows_list)) {
273 struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, sink_list_node);
274 free_flow(flow);
275 }
276 }
277  
278 void DPRelaySink_Attach (DPRelaySink *o, DataProtoSink *dp_sink)
279 {
280 DebugObject_Access(&o->d_obj);
281 ASSERT(!o->dp_sink)
282 ASSERT(dp_sink)
283  
284 // attach flows
285 for (LinkedList1Node *node = LinkedList1_GetFirst(&o->flows_list); node; node = LinkedList1Node_Next(node)) {
286 struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, sink_list_node);
287 DataProtoFlow_Attach(&flow->dp_flow, dp_sink);
288 }
289  
290 // set sink
291 o->dp_sink = dp_sink;
292 }
293  
294 void DPRelaySink_Detach (DPRelaySink *o)
295 {
296 DebugObject_Access(&o->d_obj);
297 ASSERT(o->dp_sink)
298  
299 // detach flows
300 for (LinkedList1Node *node = LinkedList1_GetFirst(&o->flows_list); node; node = LinkedList1Node_Next(node)) {
301 struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, sink_list_node);
302 DataProtoFlow_Detach(&flow->dp_flow);
303 }
304  
305 // set no sink
306 o->dp_sink = NULL;
307 }