BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file StreamBuffer.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 <misc/balloc.h>
31 #include <misc/minmax.h>
32  
33 #include "StreamBuffer.h"
34  
35 // called when receive operation is complete
36 static void input_handler_done (void *vo, int data_len)
37 {
38 StreamBuffer *o = (StreamBuffer *)vo;
39 ASSERT(data_len > 0)
40 ASSERT(data_len <= o->buf_size - (o->buf_start + o->buf_used))
41  
42 // remember if buffer was empty
43 int was_empty = (o->buf_used == 0);
44  
45 // increment buf_used by the amount that was received
46 o->buf_used += data_len;
47  
48 // start another receive operation unless buffer is full
49 if (o->buf_used < o->buf_size - o->buf_start) {
50 int end = o->buf_start + o->buf_used;
51 StreamRecvInterface_Receiver_Recv(o->input, o->buf + end, o->buf_size - end);
52 }
53 else if (o->buf_used < o->buf_size) {
54 // wrap around
55 StreamRecvInterface_Receiver_Recv(o->input, o->buf, o->buf_start);
56 }
57  
58 // if buffer was empty before, start send operation
59 if (was_empty) {
60 StreamPassInterface_Sender_Send(o->output, o->buf + o->buf_start, o->buf_used);
61 }
62 }
63  
64 // called when send operation is complete
65 static void output_handler_done (void *vo, int data_len)
66 {
67 StreamBuffer *o = (StreamBuffer *)vo;
68 ASSERT(data_len > 0)
69 ASSERT(data_len <= o->buf_used)
70 ASSERT(data_len <= o->buf_size - o->buf_start)
71  
72 // remember if buffer was full
73 int was_full = (o->buf_used == o->buf_size);
74  
75 // increment buf_start and decrement buf_used by the
76 // amount that was sent
77 o->buf_start += data_len;
78 o->buf_used -= data_len;
79  
80 // wrap around buf_start
81 if (o->buf_start == o->buf_size) {
82 o->buf_start = 0;
83 }
84  
85 // start receive operation if buffer was full
86 if (was_full) {
87 int end;
88 int avail;
89 if (o->buf_used >= o->buf_size - o->buf_start) {
90 end = o->buf_used - (o->buf_size - o->buf_start);
91 avail = o->buf_start - end;
92 } else {
93 end = o->buf_start + o->buf_used;
94 avail = o->buf_size - end;
95 }
96 StreamRecvInterface_Receiver_Recv(o->input, o->buf + end, avail);
97 }
98  
99 // start another receive send unless buffer is empty
100 if (o->buf_used > 0) {
101 int to_send = bmin_int(o->buf_used, o->buf_size - o->buf_start);
102 StreamPassInterface_Sender_Send(o->output, o->buf + o->buf_start, to_send);
103 }
104 }
105  
106 int StreamBuffer_Init (StreamBuffer *o, int buf_size, StreamRecvInterface *input, StreamPassInterface *output)
107 {
108 ASSERT(buf_size > 0)
109 ASSERT(input)
110 ASSERT(output)
111  
112 // remember arguments
113 o->buf_size = buf_size;
114 o->input = input;
115 o->output = output;
116  
117 // allocate buffer memory
118 o->buf = (uint8_t *)BAllocSize(bsize_fromint(o->buf_size));
119 if (!o->buf) {
120 goto fail0;
121 }
122  
123 // set initial buffer state
124 o->buf_start = 0;
125 o->buf_used = 0;
126  
127 // set receive and send done callbacks
128 StreamRecvInterface_Receiver_Init(o->input, input_handler_done, o);
129 StreamPassInterface_Sender_Init(o->output, output_handler_done, o);
130  
131 // start receive operation
132 StreamRecvInterface_Receiver_Recv(o->input, o->buf, o->buf_size);
133  
134 DebugObject_Init(&o->d_obj);
135 return 1;
136  
137 fail0:
138 return 0;
139 }
140  
141 void StreamBuffer_Free (StreamBuffer *o)
142 {
143 DebugObject_Free(&o->d_obj);
144  
145 // free buffer memory
146 BFree(o->buf);
147 }