Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
diff src/io/tx_stack.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/tx_stack.c Sat Feb 20 21:18:28 2010 -0800 1.3 @@ -0,0 +1,255 @@ 1.4 +/* 1.5 + * $Id: tx_stack.c,v 1.12 2004/04/17 06:07:33 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 +#include "gt_packet.h" /* gt_packet_log XXX */ 1.22 + 1.23 +#include "io/tx_stack.h" 1.24 +#include "io/tx_layer.h" 1.25 +#include "io/io_buf.h" 1.26 + 1.27 +/*****************************************************************************/ 1.28 + 1.29 +extern struct tx_layer_ops gt_tx_packet_ops; 1.30 +extern struct tx_layer_ops gt_tx_deflate_ops; 1.31 +extern struct tx_layer_ops gt_tx_link_ops; 1.32 + 1.33 +/*****************************************************************************/ 1.34 + 1.35 +static struct use_tx_layer 1.36 +{ 1.37 + const char *name; 1.38 + struct tx_layer_ops *ops; 1.39 +} tx_layers[] = 1.40 +{ 1.41 + { "tx_link", >_tx_link_ops, }, 1.42 + { "tx_deflate", >_tx_deflate_ops }, 1.43 + { "tx_packet", >_tx_packet_ops }, 1.44 +}; 1.45 + 1.46 +/*****************************************************************************/ 1.47 + 1.48 +static void foreach_tx_child (struct tx_layer *tx, 1.49 + void (*exec) (struct tx_layer *tx)) 1.50 +{ 1.51 + struct tx_layer *next; 1.52 + 1.53 + while (tx != NULL) 1.54 + { 1.55 + /* grab the next element first so the callback can call free */ 1.56 + next = tx->lower; 1.57 + 1.58 + exec (tx); 1.59 + 1.60 + tx = next; 1.61 + } 1.62 +} 1.63 + 1.64 +static struct tx_layer *tx_push_layer (struct tx_layer *below, 1.65 + struct tx_layer *above) 1.66 +{ 1.67 + if (above) 1.68 + above->lower = below; 1.69 + 1.70 + if (below) 1.71 + below->upper = above; 1.72 + 1.73 + return above; 1.74 +} 1.75 + 1.76 +static void destroy_tx (struct tx_layer *tx) 1.77 +{ 1.78 + gt_tx_layer_free (tx); 1.79 +} 1.80 + 1.81 +static void disable_tx (struct tx_layer *tx) 1.82 +{ 1.83 + gt_tx_layer_disable (tx); 1.84 +} 1.85 + 1.86 +static void disable_all_tx_layers (struct tx_layer *layers) 1.87 +{ 1.88 + if (!layers) 1.89 + return; 1.90 + 1.91 + assert (layers->upper == NULL); 1.92 + 1.93 + foreach_tx_child (layers, disable_tx); 1.94 +} 1.95 + 1.96 +static void free_all_tx_layers (struct tx_layer *layers) 1.97 +{ 1.98 + if (!layers) 1.99 + return; 1.100 + 1.101 + disable_all_tx_layers (layers); 1.102 + foreach_tx_child (layers, destroy_tx); 1.103 +} 1.104 + 1.105 +static struct tx_layer *alloc_tx_layers (GtTxStack *stack, BOOL tx_deflated) 1.106 +{ 1.107 + struct tx_layer *new_layer; 1.108 + struct tx_layer *layer = NULL; 1.109 + int i; 1.110 + 1.111 + for (i = 0; i < sizeof(tx_layers) / sizeof(tx_layers[0]); i++) 1.112 + { 1.113 + if (!strcmp (tx_layers[i].name, "tx_deflate") && !tx_deflated) 1.114 + continue; 1.115 + 1.116 + if (!(new_layer = gt_tx_layer_new (stack, tx_layers[i].name, 1.117 + tx_layers[i].ops))) 1.118 + { 1.119 + foreach_tx_child (layer, destroy_tx); 1.120 + return NULL; 1.121 + } 1.122 + 1.123 + layer = tx_push_layer (layer, new_layer); 1.124 + } 1.125 + 1.126 + return layer; 1.127 +} 1.128 + 1.129 +GtTxStack *gt_tx_stack_new (TCPC *c, BOOL tx_deflated) 1.130 +{ 1.131 + struct gt_tx_stack *stack; 1.132 + int size; 1.133 + 1.134 + if (!(stack = NEW (struct gt_tx_stack))) 1.135 + return NULL; 1.136 + 1.137 + if (!(stack->layers = alloc_tx_layers (stack, tx_deflated))) 1.138 + { 1.139 + free (stack); 1.140 + return NULL; 1.141 + } 1.142 + 1.143 + /* set the send buffer to a not too high value */ 1.144 + size = 256; 1.145 + 1.146 + if (setsockopt (c->fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) != 0) 1.147 + GT->DBGSOCK (GT, c, "Error setting sndbuf size: %s", GIFT_NETERROR()); 1.148 + 1.149 + stack->c = c; 1.150 + stack->start_time = time (NULL); 1.151 + 1.152 + return stack; 1.153 +} 1.154 + 1.155 +/*****************************************************************************/ 1.156 + 1.157 +void gt_tx_stack_free (GtTxStack *stack) 1.158 +{ 1.159 + if (!stack) 1.160 + return; 1.161 + 1.162 + free_all_tx_layers (stack->layers); 1.163 + FREE (stack); 1.164 +} 1.165 + 1.166 +void gt_tx_stack_abort (GtTxStack *stack) 1.167 +{ 1.168 + stack->cleanup (stack, stack->udata); 1.169 +} 1.170 + 1.171 +/*****************************************************************************/ 1.172 + 1.173 +static void activate_tx (struct tx_layer *tx) 1.174 +{ 1.175 + tx->ops->toggle (tx, FALSE); 1.176 +} 1.177 + 1.178 +/* 1.179 + * Start sending data down the stack. Called asynchronously by the topmost 1.180 + * layer. 1.181 + */ 1.182 +void gt_tx_stack_activate (GtTxStack *stack) 1.183 +{ 1.184 + foreach_tx_child (stack->layers, activate_tx); 1.185 +} 1.186 + 1.187 +static void deactivate_tx (struct tx_layer *tx) 1.188 +{ 1.189 + tx->ops->toggle (tx, TRUE); 1.190 +} 1.191 + 1.192 +void gt_tx_stack_deactivate (GtTxStack *stack) 1.193 +{ 1.194 + foreach_tx_child (stack->layers, deactivate_tx); 1.195 +} 1.196 + 1.197 +/*****************************************************************************/ 1.198 + 1.199 +BOOL gt_tx_stack_queue (GtTxStack *stack, const uint8_t *data, size_t len) 1.200 +{ 1.201 + struct io_buf *io_buf; 1.202 + struct tx_layer *tx; 1.203 + uint8_t *ptr; 1.204 + tx_status_t ret; 1.205 + GtPacket pkt; 1.206 + 1.207 + if (!(io_buf = io_buf_new (len))) 1.208 + return FALSE; 1.209 + 1.210 + ptr = io_buf_write_ptr (io_buf); 1.211 + 1.212 + memcpy (ptr, data, len); 1.213 + io_buf_push (io_buf, len); 1.214 + 1.215 + tx = stack->layers; 1.216 + 1.217 + /* send the data on its way down the stack */ 1.218 + if ((ret = tx->ops->queue (tx, io_buf)) != TX_OK) 1.219 + { 1.220 + GT->DBGSOCK (GT, stack->c, "bad txstatus: %d", ret); 1.221 + gt_tx_stack_abort (stack); 1.222 + return FALSE; 1.223 + } 1.224 + 1.225 + pkt.data = (unsigned char *)data; 1.226 + pkt.len = len; 1.227 + 1.228 + gt_packet_log (&pkt, stack->c, TRUE); 1.229 + 1.230 + /* 1.231 + * Activate the stack if not active already. NOTE: this actually 1.232 + * sucks bad when using compression because we end up enabling, then 1.233 + * disabling right away until some data is compressed by nagle timer. 1.234 + */ 1.235 + gt_tx_stack_activate (stack); 1.236 + 1.237 + return TRUE; 1.238 +} 1.239 + 1.240 +int gt_tx_stack_send (GtTxStack *stack, const uint8_t *data, size_t len) 1.241 +{ 1.242 + int ret; 1.243 + 1.244 + /* check if the file descriptor has an error */ 1.245 + if (net_sock_error (stack->c->fd)) 1.246 + return -1; 1.247 + 1.248 + ret = tcp_send (stack->c, (unsigned char *)data, len); 1.249 + 1.250 + return ret; 1.251 +} 1.252 + 1.253 +void gt_tx_stack_set_handler (GtTxStack *stack, GtTxStackCleanup cleanup, 1.254 + void *udata) 1.255 +{ 1.256 + stack->cleanup = cleanup; 1.257 + stack->udata = udata; 1.258 +}