Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
diff src/io/tx_layer.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_layer.c Sat Feb 20 21:18:28 2010 -0800 1.3 @@ -0,0 +1,150 @@ 1.4 +/* 1.5 + * $Id: tx_layer.c,v 1.7 2004/03/24 06:37:30 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 "io/tx_stack.h" 1.23 +#include "io/tx_layer.h" 1.24 +#include "io/io_buf.h" 1.25 + 1.26 +/*****************************************************************************/ 1.27 + 1.28 +struct tx_layer *gt_tx_layer_new (GtTxStack *stack, const char *name, 1.29 + struct tx_layer_ops *ops) 1.30 +{ 1.31 + struct tx_layer *tx; 1.32 + 1.33 + if (!(tx = NEW (struct tx_layer))) 1.34 + return NULL; 1.35 + 1.36 + tx->ops = ops; 1.37 + tx->name = name; 1.38 + tx->stack = stack; 1.39 + tx->partial_buf = NULL; 1.40 + 1.41 + if (!ops->init (tx)) 1.42 + { 1.43 + free (tx); 1.44 + return NULL; 1.45 + } 1.46 + 1.47 + return tx; 1.48 +} 1.49 + 1.50 +void gt_tx_layer_free (struct tx_layer *layer) 1.51 +{ 1.52 + if (!layer) 1.53 + return; 1.54 + 1.55 + io_buf_free (layer->partial_buf); 1.56 + 1.57 + layer->ops->destroy (layer); 1.58 + 1.59 + FREE (layer); 1.60 +} 1.61 + 1.62 +/*****************************************************************************/ 1.63 + 1.64 +static tx_status_t queue_data (struct tx_layer *tx, struct io_buf *io_buf) 1.65 +{ 1.66 + tx_status_t ret; 1.67 + 1.68 + ret = tx->ops->queue (tx, io_buf); 1.69 + 1.70 + /* 1.71 + * If the message didn't get completely written, buffer the partial 1.72 + * message buffer until it's finished. 1.73 + */ 1.74 + if (ret == TX_PARTIAL) 1.75 + { 1.76 + assert (io_buf_read_avail (io_buf) > 0); 1.77 + 1.78 + tx->partial_buf = io_buf; 1.79 + return TX_OK; 1.80 + } 1.81 + 1.82 + return ret; 1.83 +} 1.84 + 1.85 +/* send a message to the layer underneath this one */ 1.86 +tx_status_t gt_tx_layer_queue (struct tx_layer *tx, struct io_buf *io_buf) 1.87 +{ 1.88 + struct tx_layer *lower = tx->lower; 1.89 + 1.90 + if (lower->partial_buf) 1.91 + return TX_FULL; 1.92 + 1.93 + return queue_data (lower, io_buf); 1.94 +} 1.95 + 1.96 +/* let upper layer know we're writable and get data from it */ 1.97 +tx_status_t gt_tx_layer_ready (struct tx_layer *tx) 1.98 +{ 1.99 + struct tx_layer *upper; 1.100 + tx_status_t ret; 1.101 + 1.102 + upper = tx->upper; 1.103 + 1.104 + /* 1.105 + * If there is a partially written buffer on the layer, try to finish it 1.106 + * off before asking for more data by pretending the upper layer tried to 1.107 + * write it. 1.108 + * 1.109 + * Doing this avoids a special case in each layer where a partial buffer 1.110 + * is kept set aside and checked before calling gt_tx_layer_ready(), leading 1.111 + * to less code. 1.112 + */ 1.113 + if (tx->partial_buf) 1.114 + { 1.115 + struct io_buf *io_buf = tx->partial_buf; 1.116 + 1.117 + tx->partial_buf = NULL; 1.118 + 1.119 + /* this ends up calling this layer's queue func */ 1.120 + ret = queue_data (tx, io_buf); 1.121 + 1.122 + /* 1.123 + * Can't happen because layer wouldn't have invoked us. 1.124 + */ 1.125 + assert (ret != TX_FULL); 1.126 + assert (ret != TX_EMPTY); 1.127 + 1.128 + /* 1.129 + * Upper layer can't be safely invoked again, even if the partial 1.130 + * buffer was completed, because we don't know if the lower layer has 1.131 + * any more room. So, the lower layer must reinvoke tx_layer_ready() 1.132 + * to write more data. 1.133 + */ 1.134 + return ret; 1.135 + } 1.136 + 1.137 + ret = upper->ops->ready (upper); 1.138 + assert (ret != TX_FULL); 1.139 + 1.140 + return ret; 1.141 +} 1.142 + 1.143 +/*****************************************************************************/ 1.144 + 1.145 +void gt_tx_layer_enable (struct tx_layer *layer) 1.146 +{ 1.147 + layer->ops->enable (layer); 1.148 +} 1.149 + 1.150 +void gt_tx_layer_disable (struct tx_layer *layer) 1.151 +{ 1.152 + layer->ops->disable (layer); 1.153 +}