1e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* 2e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 3e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu> 4e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * All rights reserved. 5e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 6e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Redistribution and use in source and binary forms, with or without 7e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * modification, are permitted provided that the following conditions 8e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * are met: 9e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 1. Redistributions of source code must retain the above copyright 10e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * notice, this list of conditions and the following disclaimer. 11e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 2. Redistributions in binary form must reproduce the above copyright 12e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * notice, this list of conditions and the following disclaimer in the 13e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * documentation and/or other materials provided with the distribution. 14e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 3. The name of the author may not be used to endorse or promote products 15e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * derived from this software without specific prior written permission. 16e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 17e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 28e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 29e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/types.h> 30e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 31e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/event-config.h" 32e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 33e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef _EVENT_HAVE_SYS_TIME_H 34e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/time.h> 35e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 36e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 37e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <errno.h> 38e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <stdio.h> 39e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <stdlib.h> 40e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <string.h> 41e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef _EVENT_HAVE_STDARG_H 42e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <stdarg.h> 43e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 44e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef _EVENT_HAVE_UNISTD_H 45e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <unistd.h> 46e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 47e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 48e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef WIN32 49e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <winsock2.h> 50e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <ws2tcpip.h> 51e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 52e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 53e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef _EVENT_HAVE_SYS_SOCKET_H 54e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/socket.h> 55e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 56e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef _EVENT_HAVE_NETINET_IN_H 57e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <netinet/in.h> 58e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 59e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef _EVENT_HAVE_NETINET_IN6_H 60e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <netinet/in6.h> 61e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 62e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 63e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/util.h" 64e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/bufferevent.h" 65e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/buffer.h" 66e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/bufferevent_struct.h" 67e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/bufferevent_compat.h" 68e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/event.h" 69e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "log-internal.h" 70e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "mm-internal.h" 71e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "bufferevent-internal.h" 72e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "util-internal.h" 73e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef WIN32 74e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "iocp-internal.h" 75e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 76e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 77e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* prototypes */ 78e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int be_socket_enable(struct bufferevent *, short); 79e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int be_socket_disable(struct bufferevent *, short); 80e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void be_socket_destruct(struct bufferevent *); 81e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int be_socket_adj_timeouts(struct bufferevent *); 82e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int be_socket_flush(struct bufferevent *, short, enum bufferevent_flush_mode); 83e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int be_socket_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); 84e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 85e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void be_socket_setfd(struct bufferevent *, evutil_socket_t); 86e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 87e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyconst struct bufferevent_ops bufferevent_ops_socket = { 88e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley "socket", 89e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_offsetof(struct bufferevent_private, bev), 90e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_socket_enable, 91e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_socket_disable, 92e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_socket_destruct, 93e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_socket_adj_timeouts, 94e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_socket_flush, 95e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_socket_ctrl, 96e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}; 97e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 98e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define be_socket_add(ev, t) \ 99e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_add_event((ev), (t)) 100e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 101e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 102e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_socket_outbuf_cb(struct evbuffer *buf, 103e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct evbuffer_cb_info *cbinfo, 104e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley void *arg) 105e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 106e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *bufev = arg; 107e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bufev_p = 108e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); 109e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 110e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (cbinfo->n_added && 111e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (bufev->enabled & EV_WRITE) && 112e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley !event_pending(&bufev->ev_write, EV_WRITE, NULL) && 113e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley !bufev_p->write_suspended) { 114e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Somebody added data to the buffer, and we would like to 115e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * write, and we were not writing. So, start writing. */ 116e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) == -1) { 117e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Should we log this? */ 118e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 119e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 120e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 121e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 122e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 123e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_readcb(evutil_socket_t fd, short event, void *arg) 124e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 125e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *bufev = arg; 126e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bufev_p = 127e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); 128e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evbuffer *input; 129e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int res = 0; 130e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley short what = BEV_EVENT_READING; 131e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_ssize_t howmuch = -1, readmax=-1; 132e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 133e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_incref_and_lock(bufev); 134e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 135e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event == EV_TIMEOUT) { 136e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Note that we only check for event==EV_TIMEOUT. If 137e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * event==EV_TIMEOUT|EV_READ, we can safely ignore the 138e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * timeout, since a read has occurred */ 139e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley what |= BEV_EVENT_TIMEOUT; 140e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto error; 141e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 142e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 143e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley input = bufev->input; 144e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 145e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* 146e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * If we have a high watermark configured then we don't want to 147e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * read more data than would make us reach the watermark. 148e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 149e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufev->wm_read.high != 0) { 150e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley howmuch = bufev->wm_read.high - evbuffer_get_length(input); 151e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* we somehow lowered the watermark, stop reading */ 152e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (howmuch <= 0) { 153e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_wm_suspend_read(bufev); 154e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 155e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 156e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 157e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley readmax = _bufferevent_get_read_max(bufev_p); 158e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (howmuch < 0 || howmuch > readmax) /* The use of -1 for "unlimited" 159e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * uglifies this code. XXXX */ 160e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley howmuch = readmax; 161e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufev_p->read_suspended) 162e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 163e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 164e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_unfreeze(input, 0); 165e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res = evbuffer_read(input, fd, (int)howmuch); /* XXXX evbuffer_read would do better to take and return ev_ssize_t */ 166e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(input, 0); 167e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 168e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res == -1) { 169e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int err = evutil_socket_geterror(fd); 170e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (EVUTIL_ERR_RW_RETRIABLE(err)) 171e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto reschedule; 172e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* error case */ 173e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley what |= BEV_EVENT_ERROR; 174e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (res == 0) { 175e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* eof case */ 176e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley what |= BEV_EVENT_EOF; 177e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 178e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 179e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res <= 0) 180e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto error; 181e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 182e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decrement_read_buckets(bufev_p, res); 183e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 184e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Invoke the user callback - must always be called last */ 185e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (evbuffer_get_length(input) >= bufev->wm_read.low) 186e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_readcb(bufev); 187e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 188e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 189e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 190e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley reschedule: 191e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 192e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 193e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley error: 194e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_disable(bufev, EV_READ); 195e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_eventcb(bufev, what); 196e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 197e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley done: 198e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decref_and_unlock(bufev); 199e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 200e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 201e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 202e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_writecb(evutil_socket_t fd, short event, void *arg) 203e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 204e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *bufev = arg; 205e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bufev_p = 206e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); 207e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int res = 0; 208e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley short what = BEV_EVENT_WRITING; 209e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int connected = 0; 210e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_ssize_t atmost = -1; 211e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 212e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_incref_and_lock(bufev); 213e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 214e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event == EV_TIMEOUT) { 215e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Note that we only check for event==EV_TIMEOUT. If 216e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * event==EV_TIMEOUT|EV_WRITE, we can safely ignore the 217e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * timeout, since a read has occurred */ 218e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley what |= BEV_EVENT_TIMEOUT; 219e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto error; 220e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 221e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufev_p->connecting) { 222e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int c = evutil_socket_finished_connecting(fd); 223e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* we need to fake the error if the connection was refused 224e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * immediately - usually connection to localhost on BSD */ 225e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufev_p->connection_refused) { 226e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev_p->connection_refused = 0; 227e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley c = -1; 228e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 229e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 230e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (c == 0) 231e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 232e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 233e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev_p->connecting = 0; 234e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (c < 0) { 235e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_write); 236e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_read); 237e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_eventcb(bufev, BEV_EVENT_ERROR); 238e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 239e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 240e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley connected = 1; 241e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef WIN32 242e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (BEV_IS_ASYNC(bufev)) { 243e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_write); 244e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_async_set_connected(bufev); 245e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_eventcb(bufev, 246e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_EVENT_CONNECTED); 247e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 248e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 249e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 250e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_eventcb(bufev, 251e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_EVENT_CONNECTED); 252e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!(bufev->enabled & EV_WRITE) || 253e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev_p->write_suspended) { 254e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_write); 255e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 256e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 257e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 258e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 259e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 260e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley atmost = _bufferevent_get_write_max(bufev_p); 261e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 262e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufev_p->write_suspended) 263e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 264e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 265e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (evbuffer_get_length(bufev->output)) { 266e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_unfreeze(bufev->output, 1); 267e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res = evbuffer_write_atmost(bufev->output, fd, atmost); 268e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(bufev->output, 1); 269e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res == -1) { 270e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int err = evutil_socket_geterror(fd); 271e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (EVUTIL_ERR_RW_RETRIABLE(err)) 272e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto reschedule; 273e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley what |= BEV_EVENT_ERROR; 274e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (res == 0) { 275e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* eof case 276e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley XXXX Actually, a 0 on write doesn't indicate 277e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley an EOF. An ECONNRESET might be more typical. 278e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 279e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley what |= BEV_EVENT_EOF; 280e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 281e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res <= 0) 282e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto error; 283e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 284e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decrement_write_buckets(bufev_p, res); 285e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 286e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 287e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (evbuffer_get_length(bufev->output) == 0) { 288e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_write); 289e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 290e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 291e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* 292e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Invoke the user callback if our buffer is drained or below the 293e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * low watermark. 294e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 295e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((res || !connected) && 296e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_get_length(bufev->output) <= bufev->wm_write.low) { 297e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_writecb(bufev); 298e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 299e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 300e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 301e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 302e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley reschedule: 303e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (evbuffer_get_length(bufev->output) == 0) { 304e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_write); 305e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 306e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 307e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 308e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley error: 309e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_disable(bufev, EV_WRITE); 310e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_eventcb(bufev, what); 311e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 312e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley done: 313e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decref_and_unlock(bufev); 314e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 315e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 316e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct bufferevent * 317e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_socket_new(struct event_base *base, evutil_socket_t fd, 318e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int options) 319e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 320e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bufev_p; 321e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *bufev; 322e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 323e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef WIN32 324e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (base && event_base_get_iocp(base)) 325e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return bufferevent_async_new(base, fd, options); 326e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 327e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 328e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((bufev_p = mm_calloc(1, sizeof(struct bufferevent_private)))== NULL) 329e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 330e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 331e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufferevent_init_common(bufev_p, base, &bufferevent_ops_socket, 332e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley options) < 0) { 333e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley mm_free(bufev_p); 334e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 335e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 336e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev = &bufev_p->bev; 337e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_set_flags(bufev->output, EVBUFFER_FLAG_DRAINS_TO_FD); 338e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 339e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_assign(&bufev->ev_read, bufev->ev_base, fd, 340e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EV_READ|EV_PERSIST, bufferevent_readcb, bufev); 341e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_assign(&bufev->ev_write, bufev->ev_base, fd, 342e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev); 343e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 344e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_add_cb(bufev->output, bufferevent_socket_outbuf_cb, bufev); 345e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 346e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(bufev->input, 0); 347e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evbuffer_freeze(bufev->output, 1); 348e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 349e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return bufev; 350e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 351e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 352e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 353e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_socket_connect(struct bufferevent *bev, 354e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr *sa, int socklen) 355e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 356e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bufev_p = 357e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bev, struct bufferevent_private, bev); 358e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 359e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_socket_t fd; 360e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r = 0; 361e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int result=-1; 362e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int ownfd = 0; 363e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 364e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_incref_and_lock(bev); 365e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 366e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!bufev_p) 367e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 368e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 369e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley fd = bufferevent_getfd(bev); 370e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (fd < 0) { 371e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!sa) 372e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 373e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley fd = socket(sa->sa_family, SOCK_STREAM, 0); 374e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (fd < 0) 375e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 376e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (evutil_make_socket_nonblocking(fd)<0) 377e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 378e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ownfd = 1; 379e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 380e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (sa) { 381e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef WIN32 382e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufferevent_async_can_connect(bev)) { 383e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_setfd(bev, fd); 384e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = bufferevent_async_connect(bev, fd, sa, socklen); 385e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (r < 0) 386e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto freesock; 387e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev_p->connecting = 1; 388e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley result = 0; 389e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 390e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else 391e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 392e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = evutil_socket_connect(&fd, sa, socklen); 393e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (r < 0) 394e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto freesock; 395e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 396e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef WIN32 397e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* ConnectEx() isn't always around, even when IOCP is enabled. 398e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Here, we borrow the socket object's write handler to fall back 399e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * on a non-blocking connect() when ConnectEx() is unavailable. */ 400e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (BEV_IS_ASYNC(bev)) { 401e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_assign(&bev->ev_write, bev->ev_base, fd, 402e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EV_WRITE|EV_PERSIST, bufferevent_writecb, bev); 403e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 404e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 405e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_setfd(bev, fd); 406e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (r == 0) { 407e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (! be_socket_enable(bev, EV_WRITE)) { 408e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev_p->connecting = 1; 409e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley result = 0; 410e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 411e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 412e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (r == 1) { 413e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* The connect succeeded already. How very BSD of it. */ 414e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley result = 0; 415e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev_p->connecting = 1; 416e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_active(&bev->ev_write, EV_WRITE, 1); 417e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 418e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* The connect failed already. How very BSD of it. */ 419e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev_p->connection_refused = 1; 420e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev_p->connecting = 1; 421e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley result = 0; 422e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_active(&bev->ev_write, EV_WRITE, 1); 423e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 424e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 425e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 426e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 427e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyfreesock: 428e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR); 429e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ownfd) 430e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_closesocket(fd); 431e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* do something about the error? */ 432e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileydone: 433e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decref_and_unlock(bev); 434e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return result; 435e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 436e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 437e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 438e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai, 439e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley void *arg) 440e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 441e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *bev = arg; 442e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bev_p = 443e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bev, struct bufferevent_private, bev); 444e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r; 445e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_LOCK(bev); 446e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 447e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_unsuspend_write(bev, BEV_SUSPEND_LOOKUP); 448e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_unsuspend_read(bev, BEV_SUSPEND_LOOKUP); 449e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 450e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (result != 0) { 451e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bev_p->dns_error = result; 452e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR); 453e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decref_and_unlock(bev); 454e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ai) 455e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_freeaddrinfo(ai); 456e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return; 457e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 458e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 459e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* XXX use the other addrinfos? */ 460e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* XXX use this return value */ 461e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen); 462e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (void)r; 463e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _bufferevent_decref_and_unlock(bev); 464e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_freeaddrinfo(ai); 465e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 466e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 467e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 468e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_socket_connect_hostname(struct bufferevent *bev, 469e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evdns_base *evdns_base, int family, const char *hostname, int port) 470e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 471e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char portbuf[10]; 472e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo hint; 473e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int err; 474e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bev_p = 475e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bev, struct bufferevent_private, bev); 476e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 477e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) 478e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 479e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (port < 1 || port > 65535) 480e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 481e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 482e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_LOCK(bev); 483e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bev_p->dns_error = 0; 484e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_UNLOCK(bev); 485e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 486e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_snprintf(portbuf, sizeof(portbuf), "%d", port); 487e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 488e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&hint, 0, sizeof(hint)); 489e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hint.ai_family = family; 490e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hint.ai_protocol = IPPROTO_TCP; 491e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hint.ai_socktype = SOCK_STREAM; 492e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 493e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_suspend_write(bev, BEV_SUSPEND_LOOKUP); 494e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_suspend_read(bev, BEV_SUSPEND_LOOKUP); 495e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 496e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_incref(bev); 497e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err = evutil_getaddrinfo_async(evdns_base, hostname, portbuf, 498e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley &hint, bufferevent_connect_getaddrinfo_cb, bev); 499e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 500e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (err == 0) { 501e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 502e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 503e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_unsuspend_write(bev, BEV_SUSPEND_LOOKUP); 504e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_unsuspend_read(bev, BEV_SUSPEND_LOOKUP); 505e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 506e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 507e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 508e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 509e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 510e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_socket_get_dns_error(struct bufferevent *bev) 511e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 512e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int rv; 513e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bev_p = 514e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bev, struct bufferevent_private, bev); 515e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 516e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_LOCK(bev); 517e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley rv = bev_p->dns_error; 518e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_UNLOCK(bev); 519e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 520e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return rv; 521e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 522e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 523e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* 524e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Create a new buffered event object. 525e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 526e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * The read callback is invoked whenever we read new data. 527e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * The write callback is invoked whenever the output buffer is drained. 528e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * The error callback is invoked on a write/read error or on EOF. 529e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 530e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Both read and write callbacks maybe NULL. The error callback is not 531e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * allowed to be NULL and have to be provided always. 532e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 533e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 534e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct bufferevent * 535e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_new(evutil_socket_t fd, 536e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_data_cb readcb, bufferevent_data_cb writecb, 537e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_event_cb eventcb, void *cbarg) 538e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 539e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent *bufev; 540e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 541e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!(bufev = bufferevent_socket_new(NULL, fd, 0))) 542e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 543e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 544e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_setcb(bufev, readcb, writecb, eventcb, cbarg); 545e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 546e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return bufev; 547e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 548e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 549e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 550e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 551e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_socket_enable(struct bufferevent *bufev, short event) 552e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 553e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event & EV_READ) { 554e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (be_socket_add(&bufev->ev_read,&bufev->timeout_read) == -1) 555e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 556e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 557e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event & EV_WRITE) { 558e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (be_socket_add(&bufev->ev_write,&bufev->timeout_write) == -1) 559e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 560e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 561e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 562e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 563e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 564e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 565e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_socket_disable(struct bufferevent *bufev, short event) 566e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 567e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bufev_p = 568e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); 569e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event & EV_READ) { 570e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event_del(&bufev->ev_read) == -1) 571e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 572e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 573e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Don't actually disable the write if we are trying to connect. */ 574e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((event & EV_WRITE) && ! bufev_p->connecting) { 575e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event_del(&bufev->ev_write) == -1) 576e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 577e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 578e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 579e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 580e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 581e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 582e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_socket_destruct(struct bufferevent *bufev) 583e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 584e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct bufferevent_private *bufev_p = 585e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); 586e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_socket_t fd; 587e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket); 588e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 589e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley fd = event_get_fd(&bufev->ev_read); 590e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 591e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_read); 592e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_write); 593e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 594e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((bufev_p->options & BEV_OPT_CLOSE_ON_FREE) && fd >= 0) 595e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_CLOSESOCKET(fd); 596e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 597e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 598e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 599e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_socket_adj_timeouts(struct bufferevent *bufev) 600e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 601e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r = 0; 602e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event_pending(&bufev->ev_read, EV_READ, NULL)) 603e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (be_socket_add(&bufev->ev_read, &bufev->timeout_read) < 0) 604e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = -1; 605e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event_pending(&bufev->ev_write, EV_WRITE, NULL)) { 606e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) < 0) 607e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = -1; 608e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 609e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 610e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 611e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 612e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 613e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_socket_flush(struct bufferevent *bev, short iotype, 614e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley enum bufferevent_flush_mode mode) 615e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 616e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 617e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 618e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 619e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 620e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 621e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_socket_setfd(struct bufferevent *bufev, evutil_socket_t fd) 622e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 623e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_LOCK(bufev); 624e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket); 625e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 626e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_read); 627e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_del(&bufev->ev_write); 628e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 629e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_assign(&bufev->ev_read, bufev->ev_base, fd, 630e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EV_READ|EV_PERSIST, bufferevent_readcb, bufev); 631e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_assign(&bufev->ev_write, bufev->ev_base, fd, 632e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev); 633e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 634e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (fd >= 0) 635e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufferevent_enable(bufev, bufev->enabled); 636e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 637e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_UNLOCK(bufev); 638e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 639e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 640e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* XXXX Should non-socket bufferevents support this? */ 641e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 642e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_priority_set(struct bufferevent *bufev, int priority) 643e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 644e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r = -1; 645e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 646e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_LOCK(bufev); 647e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufev->be_ops != &bufferevent_ops_socket) 648e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 649e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 650e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event_priority_set(&bufev->ev_read, priority) == -1) 651e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 652e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (event_priority_set(&bufev->ev_write, priority) == -1) 653e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 654e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 655e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = 0; 656e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileydone: 657e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_UNLOCK(bufev); 658e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 659e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 660e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 661e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* XXXX Should non-socket bufferevents support this? */ 662e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 663e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybufferevent_base_set(struct event_base *base, struct bufferevent *bufev) 664e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 665e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int res = -1; 666e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 667e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_LOCK(bufev); 668e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bufev->be_ops != &bufferevent_ops_socket) 669e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 670e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 671e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley bufev->ev_base = base; 672e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 673e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res = event_base_set(base, &bufev->ev_read); 674e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res == -1) 675e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto done; 676e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 677e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res = event_base_set(base, &bufev->ev_write); 678e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileydone: 679e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley BEV_UNLOCK(bufev); 680e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return res; 681e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 682e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 683e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 684e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileybe_socket_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, 685e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley union bufferevent_ctrl_data *data) 686e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 687e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley switch (op) { 688e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case BEV_CTRL_SET_FD: 689e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley be_socket_setfd(bev, data->fd); 690e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 691e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case BEV_CTRL_GET_FD: 692e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley data->fd = event_get_fd(&bev->ev_read); 693e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 694e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case BEV_CTRL_GET_UNDERLYING: 695e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case BEV_CTRL_CANCEL_ALL: 696e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley default: 697e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 698e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 699e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 700