Line data Source code
1 : /*
2 : * Copyright (c) 2022 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #include <http/http_buffer.h>
17 : #include <http/http.h>
18 :
19 : static http_buffer_vft_t buf_vfts[HTTP_BUFFER_PTR + 1];
20 :
21 : #define HTTP_BUFFER_REGISTER_VFT(type, vft) \
22 : static void __attribute__ ((constructor)) http_buf_init_##type (void) \
23 : { \
24 : buf_vfts[type] = vft; \
25 : }
26 :
27 : typedef struct http_buffer_fifo_
28 : {
29 : svm_fifo_t *src;
30 : svm_fifo_seg_t *segs;
31 : u64 len;
32 : u64 offset;
33 : } http_buffer_fifo_t;
34 :
35 : STATIC_ASSERT (sizeof (http_buffer_fifo_t) <= HTTP_BUFFER_DATA_SZ, "buf data");
36 :
37 : static void
38 0 : buf_fifo_init (http_buffer_t *hb, void *data, u64 len)
39 : {
40 0 : svm_fifo_t *f = (svm_fifo_t *) data;
41 : http_buffer_fifo_t *bf;
42 :
43 0 : bf = (http_buffer_fifo_t *) &hb->data;
44 :
45 0 : bf->len = len;
46 0 : bf->offset = 0;
47 0 : bf->src = f;
48 0 : bf->segs = 0;
49 0 : }
50 :
51 : static void
52 0 : buf_fifo_free (http_buffer_t *hb)
53 : {
54 0 : http_buffer_fifo_t *bf = (http_buffer_fifo_t *) &hb->data;
55 :
56 0 : bf->src = 0;
57 0 : vec_free (bf->segs);
58 0 : }
59 :
60 : static svm_fifo_seg_t *
61 0 : buf_fifo_get_segs (http_buffer_t *hb, u32 max_len, u32 *n_segs)
62 : {
63 0 : http_buffer_fifo_t *bf = (http_buffer_fifo_t *) &hb->data;
64 :
65 0 : u32 _n_segs = 5;
66 : int len;
67 :
68 0 : max_len = clib_min (bf->len - bf->offset, (u64) max_len);
69 :
70 0 : vec_validate (bf->segs, _n_segs);
71 :
72 0 : len = svm_fifo_segments (bf->src, 0, bf->segs, &_n_segs, max_len);
73 0 : if (len < 0)
74 0 : return 0;
75 :
76 0 : *n_segs = _n_segs;
77 :
78 : HTTP_DBG (1, "available to send %u n_segs %u", len, *n_segs);
79 :
80 0 : return bf->segs;
81 : }
82 :
83 : static u32
84 0 : buf_fifo_drain (http_buffer_t *hb, u32 len)
85 : {
86 0 : http_buffer_fifo_t *bf = (http_buffer_fifo_t *) &hb->data;
87 :
88 0 : bf->offset += len;
89 0 : svm_fifo_dequeue_drop (bf->src, len);
90 : HTTP_DBG (1, "drained %u len %u offset %u", len, bf->len, bf->offset);
91 :
92 0 : return len;
93 : }
94 :
95 : static u8
96 0 : buf_fifo_is_drained (http_buffer_t *hb)
97 : {
98 0 : http_buffer_fifo_t *bf = (http_buffer_fifo_t *) &hb->data;
99 :
100 0 : ASSERT (bf->offset <= bf->len);
101 0 : return (bf->offset == bf->len);
102 : }
103 :
104 : const static http_buffer_vft_t buf_fifo_vft = {
105 : .init = buf_fifo_init,
106 : .free = buf_fifo_free,
107 : .get_segs = buf_fifo_get_segs,
108 : .drain = buf_fifo_drain,
109 : .is_drained = buf_fifo_is_drained,
110 : };
111 :
112 575 : HTTP_BUFFER_REGISTER_VFT (HTTP_BUFFER_FIFO, buf_fifo_vft);
113 :
114 : typedef struct http_buffer_ptr_
115 : {
116 : svm_fifo_seg_t *segs;
117 : svm_fifo_t *f;
118 : } http_buffer_ptr_t;
119 :
120 : STATIC_ASSERT (sizeof (http_buffer_ptr_t) <= HTTP_BUFFER_DATA_SZ, "buf data");
121 :
122 : static void
123 0 : buf_ptr_init (http_buffer_t *hb, void *data, u64 len)
124 : {
125 0 : svm_fifo_t *f = (svm_fifo_t *) data;
126 : http_buffer_ptr_t *bf;
127 : uword ptr;
128 : int rv;
129 :
130 0 : bf = (http_buffer_ptr_t *) &hb->data;
131 :
132 : /* Peek the pointer, do not drain the fifo until done with transfer */
133 0 : rv = svm_fifo_peek (f, 0, sizeof (ptr), (u8 *) &ptr);
134 0 : ASSERT (rv == sizeof (ptr));
135 :
136 0 : bf->f = f;
137 0 : bf->segs = 0;
138 0 : vec_validate (bf->segs, 1);
139 :
140 0 : bf->segs[0].data = uword_to_pointer (ptr, u8 *);
141 0 : bf->segs[0].len = len;
142 :
143 0 : bf->segs[1] = bf->segs[0];
144 0 : }
145 :
146 : static void
147 0 : buf_ptr_free (http_buffer_t *hb)
148 : {
149 0 : http_buffer_ptr_t *bf = (http_buffer_ptr_t *) &hb->data;
150 :
151 0 : bf->f = 0;
152 0 : vec_free (bf->segs);
153 0 : }
154 :
155 : static svm_fifo_seg_t *
156 0 : buf_ptr_get_segs (http_buffer_t *hb, u32 max_len, u32 *n_segs)
157 : {
158 0 : http_buffer_ptr_t *bf = (http_buffer_ptr_t *) &hb->data;
159 :
160 0 : *n_segs = 1;
161 0 : bf->segs[1].len = clib_min (bf->segs[0].len, max_len);
162 :
163 0 : return &bf->segs[1];
164 : }
165 :
166 : static u32
167 0 : buf_ptr_drain (http_buffer_t *hb, u32 len)
168 : {
169 0 : http_buffer_ptr_t *bf = (http_buffer_ptr_t *) &hb->data;
170 :
171 0 : ASSERT (bf->segs[0].len >= len);
172 :
173 0 : bf->segs[1].data += len;
174 0 : bf->segs[0].len -= len;
175 :
176 : HTTP_DBG (1, "drained %u left %u", len, bf->segs[1].len);
177 :
178 0 : if (!bf->segs[0].len)
179 : {
180 0 : svm_fifo_dequeue_drop (bf->f, sizeof (uword));
181 0 : return sizeof (uword);
182 : }
183 :
184 0 : return 0;
185 : }
186 :
187 : static u8
188 0 : buf_ptr_is_drained (http_buffer_t *hb)
189 : {
190 0 : http_buffer_ptr_t *bf = (http_buffer_ptr_t *) &hb->data;
191 :
192 0 : return (bf->segs[0].len == 0);
193 : }
194 :
195 : const static http_buffer_vft_t buf_ptr_vft = {
196 : .init = buf_ptr_init,
197 : .free = buf_ptr_free,
198 : .get_segs = buf_ptr_get_segs,
199 : .drain = buf_ptr_drain,
200 : .is_drained = buf_ptr_is_drained,
201 : };
202 :
203 575 : HTTP_BUFFER_REGISTER_VFT (HTTP_BUFFER_PTR, buf_ptr_vft);
204 :
205 : void
206 0 : http_buffer_init (http_buffer_t *hb, http_buffer_type_t type, svm_fifo_t *f,
207 : u64 data_len)
208 : {
209 0 : hb->vft = &buf_vfts[type];
210 0 : hb->vft->init (hb, f, data_len);
211 0 : }
212 :
213 : /*
214 : * fd.io coding-style-patch-verification: ON
215 : *
216 : * Local Variables:
217 : * eval: (c-set-style "gnu")
218 : * End:
219 : */
|