rev |
line source |
paulo@0
|
1 /*
|
paulo@0
|
2 * $Id: rx_packet.c,v 1.7 2004/02/15 04:53:38 hipnod Exp $
|
paulo@0
|
3 *
|
paulo@0
|
4 * Copyright (C) 2003 giFT project (gift.sourceforge.net)
|
paulo@0
|
5 *
|
paulo@0
|
6 * This program is free software; you can redistribute it and/or modify it
|
paulo@0
|
7 * under the terms of the GNU General Public License as published by the
|
paulo@0
|
8 * Free Software Foundation; either version 2, or (at your option) any
|
paulo@0
|
9 * later version.
|
paulo@0
|
10 *
|
paulo@0
|
11 * This program is distributed in the hope that it will be useful, but
|
paulo@0
|
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
|
paulo@0
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
paulo@0
|
14 * General Public License for more details.
|
paulo@0
|
15 */
|
paulo@0
|
16
|
paulo@0
|
17 #include "gt_gnutella.h"
|
paulo@0
|
18
|
paulo@0
|
19 #include "rx_stack.h"
|
paulo@0
|
20 #include "rx_layer.h"
|
paulo@0
|
21
|
paulo@0
|
22 #include "gt_packet.h"
|
paulo@0
|
23 #include "rx_packet.h"
|
paulo@0
|
24
|
paulo@0
|
25 /*****************************************************************************/
|
paulo@0
|
26
|
paulo@0
|
27 struct rx_packet
|
paulo@0
|
28 {
|
paulo@0
|
29 struct io_buf *partial;
|
paulo@0
|
30 rx_packet_handler_t handler;
|
paulo@0
|
31 void *udata;
|
paulo@0
|
32 };
|
paulo@0
|
33
|
paulo@0
|
34 /*****************************************************************************/
|
paulo@0
|
35
|
paulo@0
|
36 #define RX_PACKET(rx) \
|
paulo@0
|
37 ((struct rx_packet *) ((rx)->udata))
|
paulo@0
|
38
|
paulo@0
|
39 /*****************************************************************************/
|
paulo@0
|
40
|
paulo@0
|
41 static void null_packet_handler (void *udata, GtPacket *packet)
|
paulo@0
|
42 {
|
paulo@0
|
43 gt_packet_free (packet);
|
paulo@0
|
44 }
|
paulo@0
|
45
|
paulo@0
|
46 static BOOL rx_packet_init (struct rx_layer *rx, void *udata)
|
paulo@0
|
47 {
|
paulo@0
|
48 struct rx_packet *rx_packet;
|
paulo@0
|
49
|
paulo@0
|
50 if (!(rx_packet = NEW (struct rx_packet)))
|
paulo@0
|
51 return FALSE;
|
paulo@0
|
52
|
paulo@0
|
53 rx->udata = rx_packet;
|
paulo@0
|
54
|
paulo@0
|
55 /* discard the packets received */
|
paulo@0
|
56 rx_packet->handler = null_packet_handler;
|
paulo@0
|
57 return TRUE;
|
paulo@0
|
58 }
|
paulo@0
|
59
|
paulo@0
|
60 static void rx_packet_destroy (struct rx_layer *rx)
|
paulo@0
|
61 {
|
paulo@0
|
62 struct rx_packet *rx_packet = RX_PACKET(rx);
|
paulo@0
|
63
|
paulo@0
|
64 io_buf_free (rx_packet->partial);
|
paulo@0
|
65 FREE (rx_packet);
|
paulo@0
|
66 }
|
paulo@0
|
67
|
paulo@0
|
68 static void rx_packet_disable (struct rx_layer *rx)
|
paulo@0
|
69 {
|
paulo@0
|
70 /* NOP: lower layer will stop sending us data -- it'd better
|
paulo@0
|
71 * stop now */
|
paulo@0
|
72 }
|
paulo@0
|
73
|
paulo@0
|
74 static void rx_packet_enable (struct rx_layer *rx)
|
paulo@0
|
75 {
|
paulo@0
|
76 /* NOP: the lower layer will start sending us data again */
|
paulo@0
|
77 }
|
paulo@0
|
78
|
paulo@0
|
79 /*****************************************************************************/
|
paulo@0
|
80
|
paulo@0
|
81 static GtPacket *make_packet (struct rx_layer *rx, struct rx_packet *rx_packet,
|
paulo@0
|
82 size_t packet_size)
|
paulo@0
|
83 {
|
paulo@0
|
84 GtPacket *packet;
|
paulo@0
|
85 struct io_buf *pbuf = rx_packet->partial;
|
paulo@0
|
86
|
paulo@0
|
87 assert (io_buf_len (pbuf) == packet_size);
|
paulo@0
|
88 assert (packet_size < GT_PACKET_MAX);
|
paulo@0
|
89
|
paulo@0
|
90 /* construct a complete packet from the data in the binary buf */
|
paulo@0
|
91 packet = gt_packet_unserialize (pbuf->data, packet_size);
|
paulo@0
|
92
|
paulo@0
|
93 /*
|
paulo@0
|
94 * TODO: gt_packet_unserialize() currently copies the data, but should
|
paulo@0
|
95 * really take ownership of the data in place. That would also allow the
|
paulo@0
|
96 * null terminator in the io_buf to terminate the last string in the
|
paulo@0
|
97 * packet, if any.
|
paulo@0
|
98 */
|
paulo@0
|
99 io_buf_free (pbuf);
|
paulo@0
|
100 rx_packet->partial = NULL;
|
paulo@0
|
101
|
paulo@0
|
102 if (!packet)
|
paulo@0
|
103 {
|
paulo@0
|
104 gt_rx_stack_abort (rx->stack);
|
paulo@0
|
105 return NULL;
|
paulo@0
|
106 }
|
paulo@0
|
107
|
paulo@0
|
108 return packet;
|
paulo@0
|
109 }
|
paulo@0
|
110
|
paulo@0
|
111 static BOOL fill_up_to (struct rx_layer *rx, struct io_buf *dst,
|
paulo@0
|
112 struct io_buf *src, size_t fill_size)
|
paulo@0
|
113 {
|
paulo@0
|
114 size_t new_len;
|
paulo@0
|
115 size_t old_len;
|
paulo@0
|
116 size_t len_to_read;
|
paulo@0
|
117
|
paulo@0
|
118 old_len = io_buf_len (dst);
|
paulo@0
|
119 new_len = io_buf_len (src);
|
paulo@0
|
120
|
paulo@0
|
121 /* skip if we already have enough */
|
paulo@0
|
122 if (old_len >= fill_size)
|
paulo@0
|
123 return TRUE;
|
paulo@0
|
124
|
paulo@0
|
125 len_to_read = MIN (fill_size - old_len, new_len);
|
paulo@0
|
126
|
paulo@0
|
127 /* ensure the packet has enough room */
|
paulo@0
|
128 if (!io_buf_resize (dst, old_len + len_to_read))
|
paulo@0
|
129 {
|
paulo@0
|
130 gt_rx_stack_abort (rx->stack);
|
paulo@0
|
131 return FALSE;
|
paulo@0
|
132 }
|
paulo@0
|
133
|
paulo@0
|
134 io_buf_copy (dst, src, len_to_read);
|
paulo@0
|
135
|
paulo@0
|
136 if (io_buf_len (dst) >= fill_size)
|
paulo@0
|
137 return TRUE;
|
paulo@0
|
138
|
paulo@0
|
139 return FALSE;
|
paulo@0
|
140 }
|
paulo@0
|
141
|
paulo@0
|
142 static BOOL fill_header (struct rx_layer *rx, struct rx_packet *rx_packet,
|
paulo@0
|
143 struct io_buf *io_buf)
|
paulo@0
|
144 {
|
paulo@0
|
145 struct io_buf *dst = rx_packet->partial;
|
paulo@0
|
146 struct io_buf *src = io_buf;
|
paulo@0
|
147
|
paulo@0
|
148 if (!fill_up_to (rx, dst, src, GNUTELLA_HDR_LEN))
|
paulo@0
|
149 {
|
paulo@0
|
150 /* this would fail if there was an alloc failure */
|
paulo@0
|
151 assert (io_buf_read_avail (io_buf) == 0);
|
paulo@0
|
152 return FALSE;
|
paulo@0
|
153 }
|
paulo@0
|
154
|
paulo@0
|
155 return TRUE;
|
paulo@0
|
156 }
|
paulo@0
|
157
|
paulo@0
|
158 /*
|
paulo@0
|
159 * We must read all the data the lower layer has sent and buffer
|
paulo@0
|
160 * partial packets, because otherwise we would poll the CPU if the
|
paulo@0
|
161 * packet were bigger than the buffer size of one of the layer
|
paulo@0
|
162 * layers under this one.
|
paulo@0
|
163 */
|
paulo@0
|
164 static BOOL read_packet (struct rx_layer *rx, struct rx_packet *rx_packet,
|
paulo@0
|
165 struct io_buf *io_buf, GtPacket **ret)
|
paulo@0
|
166 {
|
paulo@0
|
167 uint32_t payload_len;
|
paulo@0
|
168 size_t partial_len;
|
paulo@0
|
169 uint32_t packet_size;
|
paulo@0
|
170 struct io_buf *partial = rx_packet->partial;
|
paulo@0
|
171 GtPacket *pkt;
|
paulo@0
|
172
|
paulo@0
|
173 *ret = NULL;
|
paulo@0
|
174
|
paulo@0
|
175 partial_len = io_buf_len (partial);
|
paulo@0
|
176 assert (partial_len >= GNUTELLA_HDR_LEN);
|
paulo@0
|
177
|
paulo@0
|
178 /*
|
paulo@0
|
179 * The partial packet is now at least 23 bytes. Look in the header for
|
paulo@0
|
180 * the payload length so we know how much we need to read before the
|
paulo@0
|
181 * packet is complete.
|
paulo@0
|
182 */
|
paulo@0
|
183 payload_len = get_payload_len (partial->data);
|
paulo@0
|
184 packet_size = payload_len + GNUTELLA_HDR_LEN;
|
paulo@0
|
185
|
paulo@0
|
186 /*
|
paulo@0
|
187 * Check for wraparound, and reset the packet size to its payload len.
|
paulo@0
|
188 * Its likely we've experienced a protocol de-sync here. Set the size so
|
paulo@0
|
189 * the connection will be closed.
|
paulo@0
|
190 */
|
paulo@0
|
191 if (packet_size < GNUTELLA_HDR_LEN)
|
paulo@0
|
192 packet_size = GT_PACKET_MAX;
|
paulo@0
|
193
|
paulo@0
|
194 if (packet_size >= GT_PACKET_MAX)
|
paulo@0
|
195 {
|
paulo@0
|
196 if (IO_DEBUG)
|
paulo@0
|
197 GT->dbg (GT, "received too large packet(%d)", packet_size);
|
paulo@0
|
198
|
paulo@0
|
199 /* TODO: should send a BYE message here */
|
paulo@0
|
200 gt_rx_stack_abort (rx->stack);
|
paulo@0
|
201 return FALSE;
|
paulo@0
|
202 }
|
paulo@0
|
203
|
paulo@0
|
204 if (!fill_up_to (rx, partial, io_buf, packet_size))
|
paulo@0
|
205 {
|
paulo@0
|
206 /* this would fail if there was an alloc failure */
|
paulo@0
|
207 assert (io_buf_read_avail (io_buf) == 0);
|
paulo@0
|
208 return FALSE;
|
paulo@0
|
209 }
|
paulo@0
|
210
|
paulo@0
|
211 /* yay, read a packet */
|
paulo@0
|
212 pkt = make_packet (rx, rx_packet, packet_size);
|
paulo@0
|
213 *ret = pkt;
|
paulo@0
|
214
|
paulo@0
|
215 return (pkt == NULL ? FALSE : TRUE);
|
paulo@0
|
216 }
|
paulo@0
|
217
|
paulo@0
|
218 /*
|
paulo@0
|
219 * Receive a message buffer from the lower layer, parse it into as many
|
paulo@0
|
220 * packets as it contains, and pass those to our handler function.
|
paulo@0
|
221 *
|
paulo@0
|
222 * This is meant to be the top layer of the rx stack only.
|
paulo@0
|
223 *
|
paulo@0
|
224 * TODO: A handler could be implemented as another layer, should think
|
paulo@0
|
225 * about this approach instead.
|
paulo@0
|
226 */
|
paulo@0
|
227 static void rx_packet_recv (struct rx_layer *rx, struct io_buf *io_buf)
|
paulo@0
|
228 {
|
paulo@0
|
229 GtPacket *packet = NULL;
|
paulo@0
|
230 struct rx_packet *rx_packet;
|
paulo@0
|
231
|
paulo@0
|
232 rx_packet = RX_PACKET(rx);
|
paulo@0
|
233
|
paulo@0
|
234 while (rx->enabled && io_buf_read_avail (io_buf) > 0)
|
paulo@0
|
235 {
|
paulo@0
|
236 /* allocate a new partial buffer, if one is not present yet */
|
paulo@0
|
237 if (!rx_packet->partial &&
|
paulo@0
|
238 !(rx_packet->partial = io_buf_new (GNUTELLA_HDR_LEN)))
|
paulo@0
|
239 {
|
paulo@0
|
240 gt_rx_stack_abort (rx->stack);
|
paulo@0
|
241 break;
|
paulo@0
|
242 }
|
paulo@0
|
243
|
paulo@0
|
244 /* try to read the first 23 bytes */
|
paulo@0
|
245 if (!fill_header (rx, rx_packet, io_buf))
|
paulo@0
|
246 break;
|
paulo@0
|
247
|
paulo@0
|
248 /*
|
paulo@0
|
249 * Read the payload. If there arent enough bytes to complete the
|
paulo@0
|
250 * packet, we finish it later.
|
paulo@0
|
251 */
|
paulo@0
|
252 if (!read_packet (rx, rx_packet, io_buf, &packet))
|
paulo@0
|
253 {
|
paulo@0
|
254 assert (packet == NULL);
|
paulo@0
|
255 break;
|
paulo@0
|
256 }
|
paulo@0
|
257
|
paulo@0
|
258 assert (packet != NULL);
|
paulo@0
|
259 (*rx_packet->handler) (rx_packet->udata, packet);
|
paulo@0
|
260
|
paulo@0
|
261 /* freeing the packet here means the callback must make its own
|
paulo@0
|
262 * provisions for storing the packet's data */
|
paulo@0
|
263 gt_packet_free (packet);
|
paulo@0
|
264 packet = NULL;
|
paulo@0
|
265 }
|
paulo@0
|
266
|
paulo@0
|
267 io_buf_free (io_buf);
|
paulo@0
|
268 }
|
paulo@0
|
269
|
paulo@0
|
270 /*****************************************************************************/
|
paulo@0
|
271
|
paulo@0
|
272 struct rx_layer_ops gt_rx_packet_ops =
|
paulo@0
|
273 {
|
paulo@0
|
274 rx_packet_init,
|
paulo@0
|
275 rx_packet_destroy,
|
paulo@0
|
276 rx_packet_enable,
|
paulo@0
|
277 rx_packet_disable,
|
paulo@0
|
278 rx_packet_recv,
|
paulo@0
|
279 };
|
paulo@0
|
280
|
paulo@0
|
281 void gt_rx_packet_set_handler (struct rx_layer *rx,
|
paulo@0
|
282 rx_packet_handler_t handler,
|
paulo@0
|
283 void *udata)
|
paulo@0
|
284 {
|
paulo@0
|
285 struct rx_packet *rx_packet = RX_PACKET(rx);
|
paulo@0
|
286
|
paulo@0
|
287 rx_packet->handler = handler;
|
paulo@0
|
288 rx_packet->udata = udata;
|
paulo@0
|
289 }
|