rev |
line source |
paulo@0
|
1 /*
|
paulo@0
|
2 * $Id: rx_link.c,v 1.7 2004/02/01 08:17:12 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_layer.h"
|
paulo@0
|
20 #include "rx_link.h"
|
paulo@0
|
21
|
paulo@0
|
22 /*****************************************************************************/
|
paulo@0
|
23
|
paulo@0
|
24 struct rx_link
|
paulo@0
|
25 {
|
paulo@0
|
26 /* TODO when the tx stack is implemented also
|
paulo@0
|
27 * right now cleanup is too hard */
|
paulo@0
|
28 #if 0
|
paulo@0
|
29 struct io_source *ios;
|
paulo@0
|
30 #endif
|
paulo@0
|
31 TCPC *c;
|
paulo@0
|
32 input_id id;
|
paulo@0
|
33 };
|
paulo@0
|
34
|
paulo@0
|
35 /*****************************************************************************/
|
paulo@0
|
36
|
paulo@0
|
37 /* Some macros for readability */
|
paulo@0
|
38
|
paulo@0
|
39 #define RX_LINK(rx) \
|
paulo@0
|
40 ((struct rx_link *)((rx)->udata))
|
paulo@0
|
41
|
paulo@0
|
42 #define IO_SOURCE(rx_link) \
|
paulo@0
|
43 ((rx_link)->ios)
|
paulo@0
|
44
|
paulo@0
|
45 /*****************************************************************************/
|
paulo@0
|
46
|
paulo@0
|
47 /* TODO: implement cached allocation */
|
paulo@0
|
48 #define RX_LINK_BUFSIZE 512
|
paulo@0
|
49
|
paulo@0
|
50 /*
|
paulo@0
|
51 * This implementation is for bootstrapping the code onto
|
paulo@0
|
52 * the present system.
|
paulo@0
|
53 *
|
paulo@0
|
54 * The low-level details of what we are actually reading
|
paulo@0
|
55 * from should be abstracted away.
|
paulo@0
|
56 */
|
paulo@0
|
57 static void read_data (int fd, input_id id, struct rx_layer *rx)
|
paulo@0
|
58 {
|
paulo@0
|
59 struct rx_link *rx_link = RX_LINK(rx);
|
paulo@0
|
60 struct io_buf *io_buf;
|
paulo@0
|
61 ssize_t n;
|
paulo@0
|
62
|
paulo@0
|
63 /* we're processing data, we'd better be enabled */
|
paulo@0
|
64 assert (rx->enabled);
|
paulo@0
|
65
|
paulo@0
|
66 if (!(io_buf = io_buf_new (RX_LINK_BUFSIZE)))
|
paulo@0
|
67 {
|
paulo@0
|
68 gt_rx_stack_abort (rx->stack);
|
paulo@0
|
69 return;
|
paulo@0
|
70 }
|
paulo@0
|
71
|
paulo@0
|
72 if ((n = tcp_recv (rx_link->c, io_buf_write_ptr (io_buf),
|
paulo@0
|
73 RX_LINK_BUFSIZE)) <= 0)
|
paulo@0
|
74 {
|
paulo@0
|
75 if (IO_DEBUG)
|
paulo@0
|
76 {
|
paulo@0
|
77 if (n < 0)
|
paulo@0
|
78 GT->DBGSOCK (GT, rx_link->c, "recv error: %s", GIFT_NETERROR());
|
paulo@0
|
79 else
|
paulo@0
|
80 GT->DBGSOCK (GT, rx_link->c, "recv error: socket closed");
|
paulo@0
|
81 }
|
paulo@0
|
82
|
paulo@0
|
83 io_buf_free (io_buf);
|
paulo@0
|
84 gt_rx_stack_abort (rx->stack);
|
paulo@0
|
85 return;
|
paulo@0
|
86 }
|
paulo@0
|
87
|
paulo@0
|
88 /* set the data as having been read */
|
paulo@0
|
89 io_buf_push (io_buf, n);
|
paulo@0
|
90
|
paulo@0
|
91 /*
|
paulo@0
|
92 * Pass the data up the stack.
|
paulo@0
|
93 */
|
paulo@0
|
94 gt_rx_layer_recv (rx, io_buf);
|
paulo@0
|
95 }
|
paulo@0
|
96
|
paulo@0
|
97 #if 0
|
paulo@0
|
98 /*
|
paulo@0
|
99 * Receive data from the I/O source, and pass it up the stack
|
paulo@0
|
100 */
|
paulo@0
|
101 static void recv_data (struct io_source *ios, struct io_buf *io_buf)
|
paulo@0
|
102 {
|
paulo@0
|
103 struct rx_layer *rx;
|
paulo@0
|
104 struct rx_link *rx_link;
|
paulo@0
|
105 ssize_t n;
|
paulo@0
|
106
|
paulo@0
|
107 rx = ios->recv_data;
|
paulo@0
|
108 rx_link = RX_LINK(rx);
|
paulo@0
|
109
|
paulo@0
|
110 /*
|
paulo@0
|
111 * Pass the data to an upper layer.
|
paulo@0
|
112 */
|
paulo@0
|
113 gt_rx_layer_recv (rx, io_buf);
|
paulo@0
|
114
|
paulo@0
|
115 /*
|
paulo@0
|
116 * ?? we have to free io_buf here ?? No.
|
paulo@0
|
117 * gtk-gnutella passes off responsibility to the upper layers,
|
paulo@0
|
118 * but why..
|
paulo@0
|
119 */
|
paulo@0
|
120 #if 0
|
paulo@0
|
121 return n;
|
paulo@0
|
122 #endif
|
paulo@0
|
123 /*
|
paulo@0
|
124 * Think i may understand why gtk-gnutella does it that way now:
|
paulo@0
|
125 * in the partial packet case there may be unread data on the packet,
|
paulo@0
|
126 * so we have to store that partial packet data in the intermediate
|
paulo@0
|
127 * layers.
|
paulo@0
|
128 *
|
paulo@0
|
129 * I still wonder if its possible to use a static buffer at each layer
|
paulo@0
|
130 * though...
|
paulo@0
|
131 */
|
paulo@0
|
132 }
|
paulo@0
|
133 #endif
|
paulo@0
|
134
|
paulo@0
|
135 static void init_input (struct rx_layer *rx, struct rx_link *rx_link)
|
paulo@0
|
136 {
|
paulo@0
|
137 assert (rx_link->id == 0);
|
paulo@0
|
138 rx_link->id = input_add (rx_link->c->fd, rx, INPUT_READ,
|
paulo@0
|
139 (InputCallback)read_data, 0);
|
paulo@0
|
140 }
|
paulo@0
|
141
|
paulo@0
|
142 static void free_input (struct rx_layer *rx, struct rx_link *rx_link)
|
paulo@0
|
143 {
|
paulo@0
|
144 /*
|
paulo@0
|
145 * This could be called multiple times on cleanup,
|
paulo@0
|
146 * so we don't assert the id is 0 here.
|
paulo@0
|
147 */
|
paulo@0
|
148 if (rx_link->id)
|
paulo@0
|
149 {
|
paulo@0
|
150 input_remove (rx_link->id);
|
paulo@0
|
151 rx_link->id = 0;
|
paulo@0
|
152 }
|
paulo@0
|
153 }
|
paulo@0
|
154
|
paulo@0
|
155 static void rx_link_enable (struct rx_layer *rx)
|
paulo@0
|
156 {
|
paulo@0
|
157 struct rx_link *rx_link = RX_LINK(rx);
|
paulo@0
|
158
|
paulo@0
|
159 #if 0
|
paulo@0
|
160 /* set the callback for getting data */
|
paulo@0
|
161 io_source_enable (IO_SOURCE(rx_link), IO_SOURCE_OP_RECV, recv_data, rx);
|
paulo@0
|
162 #endif
|
paulo@0
|
163
|
paulo@0
|
164 init_input (rx, rx_link);
|
paulo@0
|
165 }
|
paulo@0
|
166
|
paulo@0
|
167 static void rx_link_disable (struct rx_layer *rx)
|
paulo@0
|
168 {
|
paulo@0
|
169 struct rx_link *rx_link = RX_LINK(rx);
|
paulo@0
|
170
|
paulo@0
|
171 #if 0
|
paulo@0
|
172 io_source_disable (IO_SOURCE(rx_link), IO_SOURCE_OP_RECV);
|
paulo@0
|
173 #endif
|
paulo@0
|
174 free_input (rx, rx_link);
|
paulo@0
|
175 }
|
paulo@0
|
176
|
paulo@0
|
177 static BOOL rx_link_init (struct rx_layer *rx, void *udata)
|
paulo@0
|
178 {
|
paulo@0
|
179 struct rx_link *rx_link;
|
paulo@0
|
180 TCPC *c = (TCPC *) udata; /* ewwww */
|
paulo@0
|
181
|
paulo@0
|
182 if (!(rx_link = NEW (struct rx_link)))
|
paulo@0
|
183 return FALSE;
|
paulo@0
|
184
|
paulo@0
|
185 /* store the connection which we get from the upper layer...gross */
|
paulo@0
|
186 rx_link->c = c;
|
paulo@0
|
187
|
paulo@0
|
188 /* store our data in the rx structure */
|
paulo@0
|
189 rx->udata = rx_link;
|
paulo@0
|
190
|
paulo@0
|
191 return TRUE;
|
paulo@0
|
192 }
|
paulo@0
|
193
|
paulo@0
|
194 static void rx_link_destroy (struct rx_layer *rx)
|
paulo@0
|
195 {
|
paulo@0
|
196 struct rx_link *rx_link = RX_LINK(rx);
|
paulo@0
|
197
|
paulo@0
|
198 /*
|
paulo@0
|
199 * rx_link_disable() should be called first
|
paulo@0
|
200 */
|
paulo@0
|
201 assert (rx_link->id == 0);
|
paulo@0
|
202
|
paulo@0
|
203 /*
|
paulo@0
|
204 * We would free the connection here, but its shared with
|
paulo@0
|
205 * a GtNode that frees it also at the moment.
|
paulo@0
|
206 */
|
paulo@0
|
207 #if 0
|
paulo@0
|
208 tcp_close (rx->c);
|
paulo@0
|
209 #endif
|
paulo@0
|
210
|
paulo@0
|
211 #if 0
|
paulo@0
|
212 io_source_free (rx_link->ios);
|
paulo@0
|
213 #endif
|
paulo@0
|
214
|
paulo@0
|
215 FREE (rx_link);
|
paulo@0
|
216 }
|
paulo@0
|
217
|
paulo@0
|
218 /*****************************************************************************/
|
paulo@0
|
219
|
paulo@0
|
220 struct rx_layer_ops gt_rx_link_ops =
|
paulo@0
|
221 {
|
paulo@0
|
222 rx_link_init,
|
paulo@0
|
223 rx_link_destroy,
|
paulo@0
|
224 rx_link_enable,
|
paulo@0
|
225 rx_link_disable,
|
paulo@0
|
226 NULL, /* rx_link_recv */
|
paulo@0
|
227 };
|