mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-08 20:07:56 -04:00
Add a "ctrl" mechanism to bufferevents for property access.
OpenSSL uses something like this to implement get/set access for properties on its BIOs, so that it doesn't need to add a pair of get/set functions to the vtable struct for every new abstract property it provides an accessor for. Doing this lets us make bufferevent_setfd abstract, and implement an abstract bufferevent_getfd. svn:r1284
This commit is contained in:
parent
83f46e51d7
commit
31d89f274b
@ -22,6 +22,8 @@ Changes in 2.0.2-alpha:
|
||||
o Rename the evbuffercb and everrorcb callbacks to bufferevent_data_cb and bufferevent_event_cb respectively. The old names are available in bufferevent_compat.h.
|
||||
o Rename the EVBUFFER_* codes used by bufferevent event callbacks to BEV_EVENT_*, to avoid namespace collision with evbuffer flags. The old names are available in bufferevent_compat.h.
|
||||
o Move the EVBUFFER_INPUT and EVBUFFER_OUTPUT macros to bufferevent_compat.h
|
||||
o Add a bufferevent_getfd() function to mirror bufferevent_setfd()
|
||||
o Make bufferevent_setfd() return an error code if the operation is not successful.
|
||||
|
||||
Changes in 2.0.1-alpha:
|
||||
o free minheap on event_base_free(); from Christopher Layne
|
||||
|
@ -300,3 +300,9 @@ done:
|
||||
return r;
|
||||
}
|
||||
|
||||
evutil_socket_t
|
||||
_evbuffer_overlapped_get_fd(struct evbuffer *buf)
|
||||
{
|
||||
struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
|
||||
return buf_o ? buf_o->fd : -1;
|
||||
}
|
||||
|
@ -60,6 +60,17 @@ struct bufferevent_private {
|
||||
void *lock;
|
||||
};
|
||||
|
||||
enum bufferevent_ctrl_op {
|
||||
BEV_CTRL_SET_FD,
|
||||
BEV_CTRL_GET_FD,
|
||||
BEV_CTRL_GET_UNDERLYING,
|
||||
};
|
||||
|
||||
union bufferevent_ctrl_data {
|
||||
void *ptr;
|
||||
evutil_socket_t fd;
|
||||
};
|
||||
|
||||
/**
|
||||
Implementation table for a bufferevent: holds function pointers and other
|
||||
information to make the various bufferevent types work.
|
||||
@ -101,6 +112,9 @@ struct bufferevent_ops {
|
||||
|
||||
/** Called to flush data. */
|
||||
int (*flush)(struct bufferevent *, short, enum bufferevent_flush_mode);
|
||||
|
||||
/** Called to access miscellaneous fields. */
|
||||
int (*ctrl)(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||
};
|
||||
|
||||
extern const struct bufferevent_ops bufferevent_ops_socket;
|
||||
|
@ -531,3 +531,41 @@ bufferevent_enable_locking(struct bufferevent *bufev, void *lock)
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_setfd(struct bufferevent *bev, evutil_socket_t fd)
|
||||
{
|
||||
union bufferevent_ctrl_data d;
|
||||
int res = -1;
|
||||
d.fd = fd;
|
||||
BEV_LOCK(bev);
|
||||
if (bev->be_ops->ctrl)
|
||||
res = bev->be_ops->ctrl(bev, BEV_CTRL_SET_FD, &d);
|
||||
BEV_UNLOCK(bev);
|
||||
return res;
|
||||
}
|
||||
|
||||
evutil_socket_t
|
||||
bufferevent_getfd(struct bufferevent *bev)
|
||||
{
|
||||
union bufferevent_ctrl_data d;
|
||||
int res = -1;
|
||||
d.fd = -1;
|
||||
BEV_LOCK(bev);
|
||||
if (bev->be_ops->ctrl)
|
||||
res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_FD, &d);
|
||||
BEV_UNLOCK(bev);
|
||||
return (res<0) ? -1 : d.fd;
|
||||
}
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_get_underlying(struct bufferevent *bev)
|
||||
{
|
||||
union bufferevent_ctrl_data d;
|
||||
int res = -1;
|
||||
d.ptr = NULL;
|
||||
BEV_LOCK(bev);
|
||||
if (bev->be_ops->ctrl)
|
||||
res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_UNDERLYING, &d);
|
||||
BEV_UNLOCK(bev);
|
||||
return (res<0) ? NULL : d.ptr;
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ static int be_async_disable(struct bufferevent *, short);
|
||||
static void be_async_destruct(struct bufferevent *);
|
||||
static void be_async_adj_timeouts(struct bufferevent *);
|
||||
static int be_async_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
|
||||
static int be_async_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||
|
||||
const struct bufferevent_ops bufferevent_ops_async = {
|
||||
"socket_async",
|
||||
@ -74,9 +75,9 @@ const struct bufferevent_ops bufferevent_ops_async = {
|
||||
be_async_destruct,
|
||||
be_async_adj_timeouts,
|
||||
be_async_flush,
|
||||
be_async_ctrl,
|
||||
};
|
||||
|
||||
|
||||
struct bufferevent_async {
|
||||
struct bufferevent_private bev;
|
||||
unsigned read_in_progress : 1;
|
||||
@ -285,3 +286,18 @@ err:
|
||||
bufferevent_free(&bev_a->bev.bev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
|
||||
union bufferevent_ctrl_data *data)
|
||||
{
|
||||
switch (op) {
|
||||
case BEV_CTRL_GET_FD:
|
||||
data->fd = _evbuffer_overlapped_get_fd(bev->input);
|
||||
return 0;
|
||||
case BEV_CTRL_SET_FD:
|
||||
case BEV_CTRL_GET_UNDERLYING:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ static void be_filter_writecb(struct bufferevent *, void *);
|
||||
static void be_filter_errorcb(struct bufferevent *, short, void *);
|
||||
static int be_filter_flush(struct bufferevent *bufev,
|
||||
short iotype, enum bufferevent_flush_mode mode);
|
||||
static int be_filter_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||
|
||||
static void bufferevent_filtered_outbuf_cb(struct evbuffer *buf,
|
||||
const struct evbuffer_cb_info *info, void *arg);
|
||||
@ -104,6 +105,7 @@ const struct bufferevent_ops bufferevent_ops_filter = {
|
||||
be_filter_destruct,
|
||||
be_filter_adj_timeouts,
|
||||
be_filter_flush,
|
||||
be_filter_ctrl,
|
||||
};
|
||||
|
||||
/* Given a bufferevent that's really the bev filter of a bufferevent_filtered,
|
||||
@ -441,3 +443,20 @@ be_filter_flush(struct bufferevent *bufev,
|
||||
|
||||
return processed_any;
|
||||
}
|
||||
|
||||
static int
|
||||
be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
|
||||
union bufferevent_ctrl_data *data)
|
||||
{
|
||||
struct bufferevent_filtered *bevf;
|
||||
switch(op) {
|
||||
case BEV_CTRL_GET_UNDERLYING:
|
||||
bevf = upcast(bev);
|
||||
data->ptr = bevf->underlying;
|
||||
return 0;
|
||||
case BEV_CTRL_GET_FD:
|
||||
case BEV_CTRL_SET_FD:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -273,4 +273,5 @@ const struct bufferevent_ops bufferevent_ops_pair = {
|
||||
be_pair_destruct,
|
||||
be_pair_adj_timeouts,
|
||||
be_pair_flush,
|
||||
NULL, /* ctrl */
|
||||
};
|
||||
|
@ -73,6 +73,9 @@ static int be_socket_disable(struct bufferevent *, short);
|
||||
static void be_socket_destruct(struct bufferevent *);
|
||||
static void be_socket_adj_timeouts(struct bufferevent *);
|
||||
static int be_socket_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
|
||||
static int be_socket_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||
|
||||
static void be_socket_setfd(struct bufferevent *, evutil_socket_t);
|
||||
|
||||
const struct bufferevent_ops bufferevent_ops_socket = {
|
||||
"socket",
|
||||
@ -82,6 +85,7 @@ const struct bufferevent_ops bufferevent_ops_socket = {
|
||||
be_socket_destruct,
|
||||
be_socket_adj_timeouts,
|
||||
be_socket_flush,
|
||||
be_socket_ctrl,
|
||||
};
|
||||
|
||||
static int
|
||||
@ -287,7 +291,7 @@ bufferevent_socket_connect(struct bufferevent *bev,
|
||||
EVUTIL_CLOSESOCKET(fd);
|
||||
return -1;
|
||||
}
|
||||
bufferevent_setfd(bev, fd);
|
||||
be_socket_setfd(bev, fd);
|
||||
}
|
||||
|
||||
if (connect(fd, sa, socklen)<0) {
|
||||
@ -400,8 +404,8 @@ be_socket_flush(struct bufferevent *bev, short iotype,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd)
|
||||
static void
|
||||
be_socket_setfd(struct bufferevent *bufev, evutil_socket_t fd)
|
||||
{
|
||||
BEV_LOCK(bufev);
|
||||
assert(bufev->be_ops == &bufferevent_ops_socket);
|
||||
@ -458,3 +462,20 @@ done:
|
||||
BEV_UNLOCK(bufev);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
be_socket_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
|
||||
union bufferevent_ctrl_data *data)
|
||||
{
|
||||
switch (op) {
|
||||
case BEV_CTRL_SET_FD:
|
||||
be_socket_setfd(bev, data->fd);
|
||||
return 0;
|
||||
case BEV_CTRL_GET_FD:
|
||||
data->fd = event_get_fd(&bev->ev_read);
|
||||
return 0;
|
||||
case BEV_CTRL_GET_UNDERLYING:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -207,11 +207,24 @@ void bufferevent_setcb(struct bufferevent *bufev,
|
||||
|
||||
/**
|
||||
Changes the file descriptor on which the bufferevent operates.
|
||||
Not supported for all bufferevent types.
|
||||
|
||||
@param bufev the bufferevent object for which to change the file descriptor
|
||||
@param fd the file descriptor to operate on
|
||||
*/
|
||||
void bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd);
|
||||
int bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd);
|
||||
|
||||
/**
|
||||
Returns the file descriptor associated with a bufferevent, or -1 if
|
||||
no file descriptor is associated with the bufferevent.
|
||||
*/
|
||||
evutil_socket_t bufferevent_getfd(struct bufferevent *bufev);
|
||||
|
||||
/**
|
||||
Returns the underlying bufferevent associated with a bufferevent (if
|
||||
the bufferevent is a wrapper), or NULL if there is no underlying bufferevent.
|
||||
*/
|
||||
struct bufferevent *bufferevent_get_underlying(struct bufferevent *bufev);
|
||||
|
||||
/**
|
||||
Write data to a bufferevent buffer.
|
||||
|
@ -97,6 +97,9 @@ void event_overlapped_init(struct event_overlapped *, iocp_callback cb);
|
||||
*/
|
||||
struct evbuffer *evbuffer_overlapped_new(evutil_socket_t fd);
|
||||
|
||||
/** XXXX Document (nickm) */
|
||||
evutil_socket_t _evbuffer_overlapped_get_fd(struct evbuffer *buf);
|
||||
|
||||
/** Start reading data onto the end of an overlapped evbuffer.
|
||||
|
||||
An evbuffer can only have one read pending at a time. While the read
|
||||
|
Loading…
x
Reference in New Issue
Block a user