1e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* 2e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Copyright (c) 2009-2012 Niels Provos, Nick Mathewson 3e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 4e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Redistribution and use in source and binary forms, with or without 5e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * modification, are permitted provided that the following conditions 6e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * are met: 7e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 1. Redistributions of source code must retain the above copyright 8e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * notice, this list of conditions and the following disclaimer. 9e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 2. Redistributions in binary form must reproduce the above copyright 10e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * notice, this list of conditions and the following disclaimer in the 11e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * documentation and/or other materials provided with the distribution. 12e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 3. The name of the author may not be used to endorse or promote products 13e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * derived from this software without specific prior written permission. 14e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 15e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 26e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 27e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/types.h> 28e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 29e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef WIN32 30e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <winsock2.h> 31e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 32e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 33e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/event-config.h" 34e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 35e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/util.h" 36e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/buffer.h" 37e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/bufferevent.h" 38e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/bufferevent_struct.h" 39e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/event.h" 40e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "defer-internal.h" 41e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "bufferevent-internal.h" 42e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "mm-internal.h" 43e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "util-internal.h" 44e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 45e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct bufferevent_pair { 46e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private bev; 47e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *partner; 48e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}; 49e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 50e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 51e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Given a bufferevent that's really a bev part of a bufferevent_pair, 52e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * return that bufferevent_filtered. Returns NULL otherwise.*/ 53e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline struct bufferevent_pair * 54e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyupcast(struct bufferevent *bev) 55e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 56e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bev_p; 57e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bev->be_ops != &bufferevent_ops_pair) 58e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 59e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bev_p = EVUTIL_UPCAST(bev, struct bufferevent_pair, bev.bev); 60e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(bev_p->bev.bev.be_ops == &bufferevent_ops_pair); 61e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return bev_p; 62e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 63e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 64e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define downcast(bev_pair) (&(bev_pair)->bev.bev) 65e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 66e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline void 67e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyincref_and_lock(struct bufferevent *b) 68e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 69e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bevp; 70e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_incref_and_lock(b); 71e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bevp = upcast(b); 72e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bevp->partner) 73e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_incref_and_lock(downcast(bevp->partner)); 74e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 75e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 76e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline void 77e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileydecref_and_unlock(struct bufferevent *b) 78e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 79e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bevp = upcast(b); 80e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bevp->partner) 81e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decref_and_unlock(downcast(bevp->partner)); 82e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decref_and_unlock(b); 83e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 84e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 85e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* XXX Handle close */ 86e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 87e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void be_pair_outbuf_cb(struct evbuffer *, 88e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct evbuffer_cb_info *, void *); 89e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 90e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic struct bufferevent_pair * 91e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_pair_elt_new(struct event_base *base, 92e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int options) 93e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 94e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bufev; 95e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (! (bufev = mm_calloc(1, sizeof(struct bufferevent_pair)))) 96e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 97e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufferevent_init_common(&bufev->bev, base, &bufferevent_ops_pair, 98e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley options)) { 99e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley mm_free(bufev); 100e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 101e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 102e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!evbuffer_add_cb(bufev->bev.bev.output, be_pair_outbuf_cb, bufev)) { 103e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_free(downcast(bufev)); 104e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 105e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 106e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 107e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_init_generic_timeout_cbs(&bufev->bev.bev); 108e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 109e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return bufev; 110e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 111e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 112e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 113e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_pair_new(struct event_base *base, int options, 114e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *pair[2]) 115e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 116e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bufev1 = NULL, *bufev2 = NULL; 117e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int tmp_options; 118e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 119e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley options |= BEV_OPT_DEFER_CALLBACKS; 120e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley tmp_options = options & ~BEV_OPT_THREADSAFE; 121e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 122e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev1 = bufferevent_pair_elt_new(base, options); 123e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!bufev1) 124e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 125e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev2 = bufferevent_pair_elt_new(base, tmp_options); 126e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!bufev2) { 127e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_free(downcast(bufev1)); 128e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 129e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 130e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 131e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (options & BEV_OPT_THREADSAFE) { 132e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /*XXXX check return */ 133e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_enable_locking(downcast(bufev2), bufev1->bev.lock); 134e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 135e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 136e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev1->partner = bufev2; 137e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev2->partner = bufev1; 138e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 139e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(downcast(bufev1)->input, 0); 140e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(downcast(bufev1)->output, 1); 141e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(downcast(bufev2)->input, 0); 142e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(downcast(bufev2)->output, 1); 143e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 144e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley pair[0] = downcast(bufev1); 145e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley pair[1] = downcast(bufev2); 146e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 147e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 148e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 149e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 150e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 151e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_pair_transfer(struct bufferevent *src, struct bufferevent *dst, 152e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int ignore_wm) 153e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 154e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley size_t src_size, dst_size; 155e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley size_t n; 156e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 157e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_unfreeze(src->output, 1); 158e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_unfreeze(dst->input, 0); 159e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 160e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (dst->wm_read.high) { 161e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley dst_size = evbuffer_get_length(dst->input); 162e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (dst_size < dst->wm_read.high) { 163e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley n = dst->wm_read.high - dst_size; 164e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_remove_buffer(src->output, dst->input, n); 165e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 166e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!ignore_wm) 167e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 168e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley n = evbuffer_get_length(src->output); 169e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_add_buffer(dst->input, src->output); 170e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 171e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 172e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley n = evbuffer_get_length(src->output); 173e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_add_buffer(dst->input, src->output); 174e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 175e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 176e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (n) { 177e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_RESET_GENERIC_READ_TIMEOUT(dst); 178e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 179e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (evbuffer_get_length(dst->output)) 180e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_RESET_GENERIC_WRITE_TIMEOUT(dst); 181e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else 182e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_DEL_GENERIC_WRITE_TIMEOUT(dst); 183e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 184e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 185e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley src_size = evbuffer_get_length(src->output); 186e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley dst_size = evbuffer_get_length(dst->input); 187e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 188e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (dst_size >= dst->wm_read.low) { 189e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_readcb(dst); 190e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 191e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (src_size <= src->wm_write.low) { 192e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_writecb(src); 193e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 194e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileydone: 195e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(src->output, 1); 196e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(dst->input, 0); 197e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 198e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 199e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline int 200e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_pair_wants_to_talk(struct bufferevent_pair *src, 201e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *dst) 202e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 203e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return (downcast(src)->enabled & EV_WRITE) && 204e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (downcast(dst)->enabled & EV_READ) && 205e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley !dst->bev.read_suspended && 206e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_get_length(downcast(src)->output); 207e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 208e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 209e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 210e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_pair_outbuf_cb(struct evbuffer *outbuf, 211e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct evbuffer_cb_info *info, void *arg) 212e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 213e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bev_pair = arg; 214e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *partner = bev_pair->partner; 215e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 216e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley incref_and_lock(downcast(bev_pair)); 217e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 218e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (info->n_added > info->n_deleted && partner) { 219e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We got more data. If the other side's reading, then 220e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hand it over. */ 221e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (be_pair_wants_to_talk(bev_pair, partner)) { 222e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_transfer(downcast(bev_pair), downcast(partner), 0); 223e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 224e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 225e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 226e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley decref_and_unlock(downcast(bev_pair)); 227e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 228e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 229e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 230e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_pair_enable(struct bufferevent *bufev, short events) 231e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 232e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bev_p = upcast(bufev); 233e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *partner = bev_p->partner; 234e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 235e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley incref_and_lock(bufev); 236e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 237e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (events & EV_READ) { 238e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_RESET_GENERIC_READ_TIMEOUT(bufev); 239e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 240e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((events & EV_WRITE) && evbuffer_get_length(bufev->output)) 241e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_RESET_GENERIC_WRITE_TIMEOUT(bufev); 242e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 243e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We're starting to read! Does the other side have anything to write?*/ 244e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((events & EV_READ) && partner && 245e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_wants_to_talk(partner, bev_p)) { 246e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_transfer(downcast(partner), bufev, 0); 247e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 248e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We're starting to write! Does the other side want to read? */ 249e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((events & EV_WRITE) && partner && 250e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_wants_to_talk(bev_p, partner)) { 251e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_transfer(bufev, downcast(partner), 0); 252e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 253e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley decref_and_unlock(bufev); 254e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 255e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 256e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 257e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 258e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_pair_disable(struct bufferevent *bev, short events) 259e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 260e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (events & EV_READ) { 261e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_DEL_GENERIC_READ_TIMEOUT(bev); 262e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 263e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (events & EV_WRITE) 264e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_DEL_GENERIC_WRITE_TIMEOUT(bev); 265e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 266e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 267e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 268e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 269e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_pair_destruct(struct bufferevent *bev) 270e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 271e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bev_p = upcast(bev); 272e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 273e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bev_p->partner) { 274e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bev_p->partner->partner = NULL; 275e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bev_p->partner = NULL; 276e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 277e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 278e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_del_generic_timeout_cbs(bev); 279e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 280e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 281e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 282e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_pair_flush(struct bufferevent *bev, short iotype, 283e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley enum bufferevent_flush_mode mode) 284e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 285e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bev_p = upcast(bev); 286e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *partner; 287e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley incref_and_lock(bev); 288e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!bev_p->partner) 289e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 290e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 291e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley partner = downcast(bev_p->partner); 292e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 293e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (mode == BEV_NORMAL) 294e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 295e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 296e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((iotype & EV_READ) != 0) 297e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_transfer(partner, bev, 1); 298e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 299e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((iotype & EV_WRITE) != 0) 300e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_transfer(bev, partner, 1); 301e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 302e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (mode == BEV_FINISHED) { 303e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_eventcb(partner, iotype|BEV_EVENT_EOF); 304e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 305e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley decref_and_unlock(bev); 306e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 307e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 308e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 309e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct bufferevent * 310e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_pair_get_partner(struct bufferevent *bev) 311e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 312e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_pair *bev_p; 313e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *partner = NULL; 314e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bev_p = upcast(bev); 315e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (! bev_p) 316e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 317e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 318e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley incref_and_lock(bev); 319e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bev_p->partner) 320e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley partner = downcast(bev_p->partner); 321e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley decref_and_unlock(bev); 322e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return partner; 323e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 324e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 325e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyconst struct bufferevent_ops bufferevent_ops_pair = { 326e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley "pair_elt", 327e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_offsetof(struct bufferevent_pair, bev.bev), 328e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_enable, 329e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_disable, 330e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_destruct, 331e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_generic_adj_timeouts, 332e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_pair_flush, 333e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley NULL, /* ctrl */ 334e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}; 335