summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--buffer_iocp.c6
-rw-r--r--bufferevent-internal.h14
-rw-r--r--bufferevent.c38
-rw-r--r--bufferevent_async.c18
-rw-r--r--bufferevent_filter.c19
-rw-r--r--bufferevent_pair.c1
-rw-r--r--bufferevent_sock.c27
-rw-r--r--include/event2/bufferevent.h15
-rw-r--r--iocp-internal.h3
10 files changed, 138 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index ecbd598d..2f1b28d0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/buffer_iocp.c b/buffer_iocp.c
index 620efd8d..b54d1806 100644
--- a/buffer_iocp.c
+++ b/buffer_iocp.c
@@ -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;
+}
diff --git a/bufferevent-internal.h b/bufferevent-internal.h
index d937db3c..7ea92172 100644
--- a/bufferevent-internal.h
+++ b/bufferevent-internal.h
@@ -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;
diff --git a/bufferevent.c b/bufferevent.c
index 2d614dae..06386844 100644
--- a/bufferevent.c
+++ b/bufferevent.c
@@ -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;
+}
diff --git a/bufferevent_async.c b/bufferevent_async.c
index 6d503979..878a8a0f 100644
--- a/bufferevent_async.c
+++ b/bufferevent_async.c
@@ -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;
+ }
+}
diff --git a/bufferevent_filter.c b/bufferevent_filter.c
index fa7c1f54..3c5a1d4a 100644
--- a/bufferevent_filter.c
+++ b/bufferevent_filter.c
@@ -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;
+ }
+}
diff --git a/bufferevent_pair.c b/bufferevent_pair.c
index 15022662..e6924046 100644
--- a/bufferevent_pair.c
+++ b/bufferevent_pair.c
@@ -273,4 +273,5 @@ const struct bufferevent_ops bufferevent_ops_pair = {
be_pair_destruct,
be_pair_adj_timeouts,
be_pair_flush,
+ NULL, /* ctrl */
};
diff --git a/bufferevent_sock.c b/bufferevent_sock.c
index dd1ca3fc..d2723739 100644
--- a/bufferevent_sock.c
+++ b/bufferevent_sock.c
@@ -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;
+ }
+}
diff --git a/include/event2/bufferevent.h b/include/event2/bufferevent.h
index 228ec9a4..80dcbd9d 100644
--- a/include/event2/bufferevent.h
+++ b/include/event2/bufferevent.h
@@ -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.
diff --git a/iocp-internal.h b/iocp-internal.h
index 1470620d..ac76e848 100644
--- a/iocp-internal.h
+++ b/iocp-internal.h
@@ -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