annotate 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
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 };