Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/io/rx_link.c Sat Feb 20 21:18:28 2010 -0800 1.3 @@ -0,0 +1,227 @@ 1.4 +/* 1.5 + * $Id: rx_link.c,v 1.7 2004/02/01 08:17:12 hipnod Exp $ 1.6 + * 1.7 + * Copyright (C) 2003 giFT project (gift.sourceforge.net) 1.8 + * 1.9 + * This program is free software; you can redistribute it and/or modify it 1.10 + * under the terms of the GNU General Public License as published by the 1.11 + * Free Software Foundation; either version 2, or (at your option) any 1.12 + * later version. 1.13 + * 1.14 + * This program is distributed in the hope that it will be useful, but 1.15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + * General Public License for more details. 1.18 + */ 1.19 + 1.20 +#include "gt_gnutella.h" 1.21 + 1.22 +#include "rx_layer.h" 1.23 +#include "rx_link.h" 1.24 + 1.25 +/*****************************************************************************/ 1.26 + 1.27 +struct rx_link 1.28 +{ 1.29 + /* TODO when the tx stack is implemented also 1.30 + * right now cleanup is too hard */ 1.31 +#if 0 1.32 + struct io_source *ios; 1.33 +#endif 1.34 + TCPC *c; 1.35 + input_id id; 1.36 +}; 1.37 + 1.38 +/*****************************************************************************/ 1.39 + 1.40 +/* Some macros for readability */ 1.41 + 1.42 +#define RX_LINK(rx) \ 1.43 + ((struct rx_link *)((rx)->udata)) 1.44 + 1.45 +#define IO_SOURCE(rx_link) \ 1.46 + ((rx_link)->ios) 1.47 + 1.48 +/*****************************************************************************/ 1.49 + 1.50 +/* TODO: implement cached allocation */ 1.51 +#define RX_LINK_BUFSIZE 512 1.52 + 1.53 +/* 1.54 + * This implementation is for bootstrapping the code onto 1.55 + * the present system. 1.56 + * 1.57 + * The low-level details of what we are actually reading 1.58 + * from should be abstracted away. 1.59 + */ 1.60 +static void read_data (int fd, input_id id, struct rx_layer *rx) 1.61 +{ 1.62 + struct rx_link *rx_link = RX_LINK(rx); 1.63 + struct io_buf *io_buf; 1.64 + ssize_t n; 1.65 + 1.66 + /* we're processing data, we'd better be enabled */ 1.67 + assert (rx->enabled); 1.68 + 1.69 + if (!(io_buf = io_buf_new (RX_LINK_BUFSIZE))) 1.70 + { 1.71 + gt_rx_stack_abort (rx->stack); 1.72 + return; 1.73 + } 1.74 + 1.75 + if ((n = tcp_recv (rx_link->c, io_buf_write_ptr (io_buf), 1.76 + RX_LINK_BUFSIZE)) <= 0) 1.77 + { 1.78 + if (IO_DEBUG) 1.79 + { 1.80 + if (n < 0) 1.81 + GT->DBGSOCK (GT, rx_link->c, "recv error: %s", GIFT_NETERROR()); 1.82 + else 1.83 + GT->DBGSOCK (GT, rx_link->c, "recv error: socket closed"); 1.84 + } 1.85 + 1.86 + io_buf_free (io_buf); 1.87 + gt_rx_stack_abort (rx->stack); 1.88 + return; 1.89 + } 1.90 + 1.91 + /* set the data as having been read */ 1.92 + io_buf_push (io_buf, n); 1.93 + 1.94 + /* 1.95 + * Pass the data up the stack. 1.96 + */ 1.97 + gt_rx_layer_recv (rx, io_buf); 1.98 +} 1.99 + 1.100 +#if 0 1.101 +/* 1.102 + * Receive data from the I/O source, and pass it up the stack 1.103 + */ 1.104 +static void recv_data (struct io_source *ios, struct io_buf *io_buf) 1.105 +{ 1.106 + struct rx_layer *rx; 1.107 + struct rx_link *rx_link; 1.108 + ssize_t n; 1.109 + 1.110 + rx = ios->recv_data; 1.111 + rx_link = RX_LINK(rx); 1.112 + 1.113 + /* 1.114 + * Pass the data to an upper layer. 1.115 + */ 1.116 + gt_rx_layer_recv (rx, io_buf); 1.117 + 1.118 + /* 1.119 + * ?? we have to free io_buf here ?? No. 1.120 + * gtk-gnutella passes off responsibility to the upper layers, 1.121 + * but why.. 1.122 + */ 1.123 +#if 0 1.124 + return n; 1.125 +#endif 1.126 + /* 1.127 + * Think i may understand why gtk-gnutella does it that way now: 1.128 + * in the partial packet case there may be unread data on the packet, 1.129 + * so we have to store that partial packet data in the intermediate 1.130 + * layers. 1.131 + * 1.132 + * I still wonder if its possible to use a static buffer at each layer 1.133 + * though... 1.134 + */ 1.135 +} 1.136 +#endif 1.137 + 1.138 +static void init_input (struct rx_layer *rx, struct rx_link *rx_link) 1.139 +{ 1.140 + assert (rx_link->id == 0); 1.141 + rx_link->id = input_add (rx_link->c->fd, rx, INPUT_READ, 1.142 + (InputCallback)read_data, 0); 1.143 +} 1.144 + 1.145 +static void free_input (struct rx_layer *rx, struct rx_link *rx_link) 1.146 +{ 1.147 + /* 1.148 + * This could be called multiple times on cleanup, 1.149 + * so we don't assert the id is 0 here. 1.150 + */ 1.151 + if (rx_link->id) 1.152 + { 1.153 + input_remove (rx_link->id); 1.154 + rx_link->id = 0; 1.155 + } 1.156 +} 1.157 + 1.158 +static void rx_link_enable (struct rx_layer *rx) 1.159 +{ 1.160 + struct rx_link *rx_link = RX_LINK(rx); 1.161 + 1.162 +#if 0 1.163 + /* set the callback for getting data */ 1.164 + io_source_enable (IO_SOURCE(rx_link), IO_SOURCE_OP_RECV, recv_data, rx); 1.165 +#endif 1.166 + 1.167 + init_input (rx, rx_link); 1.168 +} 1.169 + 1.170 +static void rx_link_disable (struct rx_layer *rx) 1.171 +{ 1.172 + struct rx_link *rx_link = RX_LINK(rx); 1.173 + 1.174 +#if 0 1.175 + io_source_disable (IO_SOURCE(rx_link), IO_SOURCE_OP_RECV); 1.176 +#endif 1.177 + free_input (rx, rx_link); 1.178 +} 1.179 + 1.180 +static BOOL rx_link_init (struct rx_layer *rx, void *udata) 1.181 +{ 1.182 + struct rx_link *rx_link; 1.183 + TCPC *c = (TCPC *) udata; /* ewwww */ 1.184 + 1.185 + if (!(rx_link = NEW (struct rx_link))) 1.186 + return FALSE; 1.187 + 1.188 + /* store the connection which we get from the upper layer...gross */ 1.189 + rx_link->c = c; 1.190 + 1.191 + /* store our data in the rx structure */ 1.192 + rx->udata = rx_link; 1.193 + 1.194 + return TRUE; 1.195 +} 1.196 + 1.197 +static void rx_link_destroy (struct rx_layer *rx) 1.198 +{ 1.199 + struct rx_link *rx_link = RX_LINK(rx); 1.200 + 1.201 + /* 1.202 + * rx_link_disable() should be called first 1.203 + */ 1.204 + assert (rx_link->id == 0); 1.205 + 1.206 + /* 1.207 + * We would free the connection here, but its shared with 1.208 + * a GtNode that frees it also at the moment. 1.209 + */ 1.210 +#if 0 1.211 + tcp_close (rx->c); 1.212 +#endif 1.213 + 1.214 +#if 0 1.215 + io_source_free (rx_link->ios); 1.216 +#endif 1.217 + 1.218 + FREE (rx_link); 1.219 +} 1.220 + 1.221 +/*****************************************************************************/ 1.222 + 1.223 +struct rx_layer_ops gt_rx_link_ops = 1.224 +{ 1.225 + rx_link_init, 1.226 + rx_link_destroy, 1.227 + rx_link_enable, 1.228 + rx_link_disable, 1.229 + NULL, /* rx_link_recv */ 1.230 +};