view src/io/rx_link.c @ 0:d39e1d0d75b6

initial add
author paulo@hit-nxdomain.opendns.com
date Sat, 20 Feb 2010 21:18:28 -0800
parents
children
line source
1 /*
2 * $Id: rx_link.c,v 1.7 2004/02/01 08:17:12 hipnod Exp $
3 *
4 * Copyright (C) 2003 giFT project (gift.sourceforge.net)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 */
17 #include "gt_gnutella.h"
19 #include "rx_layer.h"
20 #include "rx_link.h"
22 /*****************************************************************************/
24 struct rx_link
25 {
26 /* TODO when the tx stack is implemented also
27 * right now cleanup is too hard */
28 #if 0
29 struct io_source *ios;
30 #endif
31 TCPC *c;
32 input_id id;
33 };
35 /*****************************************************************************/
37 /* Some macros for readability */
39 #define RX_LINK(rx) \
40 ((struct rx_link *)((rx)->udata))
42 #define IO_SOURCE(rx_link) \
43 ((rx_link)->ios)
45 /*****************************************************************************/
47 /* TODO: implement cached allocation */
48 #define RX_LINK_BUFSIZE 512
50 /*
51 * This implementation is for bootstrapping the code onto
52 * the present system.
53 *
54 * The low-level details of what we are actually reading
55 * from should be abstracted away.
56 */
57 static void read_data (int fd, input_id id, struct rx_layer *rx)
58 {
59 struct rx_link *rx_link = RX_LINK(rx);
60 struct io_buf *io_buf;
61 ssize_t n;
63 /* we're processing data, we'd better be enabled */
64 assert (rx->enabled);
66 if (!(io_buf = io_buf_new (RX_LINK_BUFSIZE)))
67 {
68 gt_rx_stack_abort (rx->stack);
69 return;
70 }
72 if ((n = tcp_recv (rx_link->c, io_buf_write_ptr (io_buf),
73 RX_LINK_BUFSIZE)) <= 0)
74 {
75 if (IO_DEBUG)
76 {
77 if (n < 0)
78 GT->DBGSOCK (GT, rx_link->c, "recv error: %s", GIFT_NETERROR());
79 else
80 GT->DBGSOCK (GT, rx_link->c, "recv error: socket closed");
81 }
83 io_buf_free (io_buf);
84 gt_rx_stack_abort (rx->stack);
85 return;
86 }
88 /* set the data as having been read */
89 io_buf_push (io_buf, n);
91 /*
92 * Pass the data up the stack.
93 */
94 gt_rx_layer_recv (rx, io_buf);
95 }
97 #if 0
98 /*
99 * Receive data from the I/O source, and pass it up the stack
100 */
101 static void recv_data (struct io_source *ios, struct io_buf *io_buf)
102 {
103 struct rx_layer *rx;
104 struct rx_link *rx_link;
105 ssize_t n;
107 rx = ios->recv_data;
108 rx_link = RX_LINK(rx);
110 /*
111 * Pass the data to an upper layer.
112 */
113 gt_rx_layer_recv (rx, io_buf);
115 /*
116 * ?? we have to free io_buf here ?? No.
117 * gtk-gnutella passes off responsibility to the upper layers,
118 * but why..
119 */
120 #if 0
121 return n;
122 #endif
123 /*
124 * Think i may understand why gtk-gnutella does it that way now:
125 * in the partial packet case there may be unread data on the packet,
126 * so we have to store that partial packet data in the intermediate
127 * layers.
128 *
129 * I still wonder if its possible to use a static buffer at each layer
130 * though...
131 */
132 }
133 #endif
135 static void init_input (struct rx_layer *rx, struct rx_link *rx_link)
136 {
137 assert (rx_link->id == 0);
138 rx_link->id = input_add (rx_link->c->fd, rx, INPUT_READ,
139 (InputCallback)read_data, 0);
140 }
142 static void free_input (struct rx_layer *rx, struct rx_link *rx_link)
143 {
144 /*
145 * This could be called multiple times on cleanup,
146 * so we don't assert the id is 0 here.
147 */
148 if (rx_link->id)
149 {
150 input_remove (rx_link->id);
151 rx_link->id = 0;
152 }
153 }
155 static void rx_link_enable (struct rx_layer *rx)
156 {
157 struct rx_link *rx_link = RX_LINK(rx);
159 #if 0
160 /* set the callback for getting data */
161 io_source_enable (IO_SOURCE(rx_link), IO_SOURCE_OP_RECV, recv_data, rx);
162 #endif
164 init_input (rx, rx_link);
165 }
167 static void rx_link_disable (struct rx_layer *rx)
168 {
169 struct rx_link *rx_link = RX_LINK(rx);
171 #if 0
172 io_source_disable (IO_SOURCE(rx_link), IO_SOURCE_OP_RECV);
173 #endif
174 free_input (rx, rx_link);
175 }
177 static BOOL rx_link_init (struct rx_layer *rx, void *udata)
178 {
179 struct rx_link *rx_link;
180 TCPC *c = (TCPC *) udata; /* ewwww */
182 if (!(rx_link = NEW (struct rx_link)))
183 return FALSE;
185 /* store the connection which we get from the upper layer...gross */
186 rx_link->c = c;
188 /* store our data in the rx structure */
189 rx->udata = rx_link;
191 return TRUE;
192 }
194 static void rx_link_destroy (struct rx_layer *rx)
195 {
196 struct rx_link *rx_link = RX_LINK(rx);
198 /*
199 * rx_link_disable() should be called first
200 */
201 assert (rx_link->id == 0);
203 /*
204 * We would free the connection here, but its shared with
205 * a GtNode that frees it also at the moment.
206 */
207 #if 0
208 tcp_close (rx->c);
209 #endif
211 #if 0
212 io_source_free (rx_link->ios);
213 #endif
215 FREE (rx_link);
216 }
218 /*****************************************************************************/
220 struct rx_layer_ops gt_rx_link_ops =
221 {
222 rx_link_init,
223 rx_link_destroy,
224 rx_link_enable,
225 rx_link_disable,
226 NULL, /* rx_link_recv */
227 };