Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0428dda7e276 |
---|---|
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 */ | |
16 | |
17 #include "gt_gnutella.h" | |
18 | |
19 #include "rx_layer.h" | |
20 #include "rx_link.h" | |
21 | |
22 /*****************************************************************************/ | |
23 | |
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 }; | |
34 | |
35 /*****************************************************************************/ | |
36 | |
37 /* Some macros for readability */ | |
38 | |
39 #define RX_LINK(rx) \ | |
40 ((struct rx_link *)((rx)->udata)) | |
41 | |
42 #define IO_SOURCE(rx_link) \ | |
43 ((rx_link)->ios) | |
44 | |
45 /*****************************************************************************/ | |
46 | |
47 /* TODO: implement cached allocation */ | |
48 #define RX_LINK_BUFSIZE 512 | |
49 | |
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; | |
62 | |
63 /* we're processing data, we'd better be enabled */ | |
64 assert (rx->enabled); | |
65 | |
66 if (!(io_buf = io_buf_new (RX_LINK_BUFSIZE))) | |
67 { | |
68 gt_rx_stack_abort (rx->stack); | |
69 return; | |
70 } | |
71 | |
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 } | |
82 | |
83 io_buf_free (io_buf); | |
84 gt_rx_stack_abort (rx->stack); | |
85 return; | |
86 } | |
87 | |
88 /* set the data as having been read */ | |
89 io_buf_push (io_buf, n); | |
90 | |
91 /* | |
92 * Pass the data up the stack. | |
93 */ | |
94 gt_rx_layer_recv (rx, io_buf); | |
95 } | |
96 | |
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; | |
106 | |
107 rx = ios->recv_data; | |
108 rx_link = RX_LINK(rx); | |
109 | |
110 /* | |
111 * Pass the data to an upper layer. | |
112 */ | |
113 gt_rx_layer_recv (rx, io_buf); | |
114 | |
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 | |
134 | |
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 } | |
141 | |
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 } | |
154 | |
155 static void rx_link_enable (struct rx_layer *rx) | |
156 { | |
157 struct rx_link *rx_link = RX_LINK(rx); | |
158 | |
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 | |
163 | |
164 init_input (rx, rx_link); | |
165 } | |
166 | |
167 static void rx_link_disable (struct rx_layer *rx) | |
168 { | |
169 struct rx_link *rx_link = RX_LINK(rx); | |
170 | |
171 #if 0 | |
172 io_source_disable (IO_SOURCE(rx_link), IO_SOURCE_OP_RECV); | |
173 #endif | |
174 free_input (rx, rx_link); | |
175 } | |
176 | |
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 */ | |
181 | |
182 if (!(rx_link = NEW (struct rx_link))) | |
183 return FALSE; | |
184 | |
185 /* store the connection which we get from the upper layer...gross */ | |
186 rx_link->c = c; | |
187 | |
188 /* store our data in the rx structure */ | |
189 rx->udata = rx_link; | |
190 | |
191 return TRUE; | |
192 } | |
193 | |
194 static void rx_link_destroy (struct rx_layer *rx) | |
195 { | |
196 struct rx_link *rx_link = RX_LINK(rx); | |
197 | |
198 /* | |
199 * rx_link_disable() should be called first | |
200 */ | |
201 assert (rx_link->id == 0); | |
202 | |
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 | |
210 | |
211 #if 0 | |
212 io_source_free (rx_link->ios); | |
213 #endif | |
214 | |
215 FREE (rx_link); | |
216 } | |
217 | |
218 /*****************************************************************************/ | |
219 | |
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 }; |