diff --git a/bufferevent_async.c b/bufferevent_async.c index 1521d896..d2eefed4 100644 --- a/bufferevent_async.c +++ b/bufferevent_async.c @@ -100,6 +100,27 @@ const struct bufferevent_ops bufferevent_ops_async = { be_async_ctrl, }; +static inline void +be_async_run_eventcb(struct bufferevent *bev, short what, int options) +{ bufferevent_run_eventcb_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); } + +static inline void +be_async_trigger_nolock(struct bufferevent *bev, short what, int options) +{ bufferevent_trigger_nolock_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); } + +static inline int +fatal_error(int err) +{ + switch (err) { + /* We may have already associated this fd with a port. + * Let's hope it's this port, and that the error code + * for doing this neer changes. */ + case ERROR_INVALID_PARAMETER: + return 0; + } + return 1; +} + static inline struct bufferevent_async * upcast(struct bufferevent *bev) { @@ -217,7 +238,7 @@ bev_async_consider_writing(struct bufferevent_async *beva) &beva->write_overlapped)) { bufferevent_decref_(bev); beva->ok = 0; - bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, 0); + be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0); } else { beva->write_in_progress = at_most; bufferevent_decrement_write_buckets_(&beva->bev, at_most); @@ -270,7 +291,7 @@ bev_async_consider_reading(struct bufferevent_async *beva) bufferevent_incref_(bev); if (evbuffer_launch_read_(bev->input, at_most, &beva->read_overlapped)) { beva->ok = 0; - bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, 0); + be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0); bufferevent_decref_(bev); } else { beva->read_in_progress = at_most; @@ -428,8 +449,7 @@ connect_complete(struct event_overlapped *eo, ev_uintptr_t key, else bev_async_set_wsa_error(bev, eo); - bufferevent_run_eventcb_(bev, - ok? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR, 0); + be_async_run_eventcb(bev, ok ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR, 0); event_base_del_virtual_(bev->ev_base); @@ -459,16 +479,16 @@ read_complete(struct event_overlapped *eo, ev_uintptr_t key, if (bev_a->ok) { if (ok && nbytes) { BEV_RESET_GENERIC_READ_TIMEOUT(bev); - bufferevent_trigger_nolock_(bev, EV_READ, 0); + be_async_trigger_nolock(bev, EV_READ, 0); bev_async_consider_reading(bev_a); } else if (!ok) { what |= BEV_EVENT_ERROR; bev_a->ok = 0; - bufferevent_run_eventcb_(bev, what, 0); + be_async_run_eventcb(bev, what, 0); } else if (!nbytes) { what |= BEV_EVENT_EOF; bev_a->ok = 0; - bufferevent_run_eventcb_(bev, what, 0); + be_async_run_eventcb(bev, what, 0); } } @@ -502,16 +522,16 @@ write_complete(struct event_overlapped *eo, ev_uintptr_t key, if (bev_a->ok) { if (ok && nbytes) { BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); - bufferevent_trigger_nolock_(bev, EV_WRITE, 0); + be_async_trigger_nolock(bev, EV_WRITE, 0); bev_async_consider_writing(bev_a); } else if (!ok) { what |= BEV_EVENT_ERROR; bev_a->ok = 0; - bufferevent_run_eventcb_(bev, what, 0); + be_async_run_eventcb(bev, what, 0); } else if (!nbytes) { what |= BEV_EVENT_EOF; bev_a->ok = 0; - bufferevent_run_eventcb_(bev, what, 0); + be_async_run_eventcb(bev, what, 0); } } @@ -532,11 +552,7 @@ bufferevent_async_new_(struct event_base *base, return NULL; if (fd >= 0 && event_iocp_port_associate_(iocp, fd, 1)<0) { - int err = GetLastError(); - /* We may have alrady associated this fd with a port. - * Let's hope it's this port, and that the error code - * for doing this neer changes. */ - if (err != ERROR_INVALID_PARAMETER) + if (fatal_error(GetLastError())) return NULL; } @@ -580,7 +596,6 @@ bufferevent_async_set_connected_(struct bufferevent *bev) { struct bufferevent_async *bev_async = upcast(bev); bev_async->ok = 1; - bufferevent_init_generic_timeout_cbs_(bev); /* Now's a good time to consider reading/writing */ be_async_enable(bev, bev->enabled); } @@ -654,16 +669,20 @@ be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, data->fd = evbuffer_overlapped_get_fd_(bev->input); return 0; case BEV_CTRL_SET_FD: { + struct bufferevent_async *bev_a = upcast(bev); struct event_iocp_port *iocp; if (data->fd == evbuffer_overlapped_get_fd_(bev->input)) return 0; if (!(iocp = event_base_get_iocp_(bev->ev_base))) return -1; - if (event_iocp_port_associate_(iocp, data->fd, 1) < 0) - return -1; + if (event_iocp_port_associate_(iocp, data->fd, 1) < 0) { + if (fatal_error(GetLastError())) + return -1; + } evbuffer_overlapped_set_fd_(bev->input, data->fd); evbuffer_overlapped_set_fd_(bev->output, data->fd); + bev_a->ok = data->fd >= 0; return 0; } case BEV_CTRL_CANCEL_ALL: { diff --git a/test/regress.h b/test/regress.h index b5347268..643b82ba 100644 --- a/test/regress.h +++ b/test/regress.h @@ -43,6 +43,7 @@ extern struct testcase_t bufferevent_iocp_testcases[]; extern struct testcase_t util_testcases[]; extern struct testcase_t signal_testcases[]; extern struct testcase_t http_testcases[]; +extern struct testcase_t http_iocp_testcases[]; extern struct testcase_t dns_testcases[]; extern struct testcase_t rpc_testcases[]; extern struct testcase_t edgetriggered_testcases[]; diff --git a/test/regress_http.c b/test/regress_http.c index 86120259..c13987f1 100644 --- a/test/regress_http.c +++ b/test/regress_http.c @@ -4786,3 +4786,8 @@ struct testcase_t http_testcases[] = { END_OF_TESTCASES }; +struct testcase_t http_iocp_testcases[] = { + { "simple", http_simple_test, TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL }, + { "https_simple", https_simple_test, TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL }, + END_OF_TESTCASES +}; diff --git a/test/regress_main.c b/test/regress_main.c index d3c6c3ce..c9372825 100644 --- a/test/regress_main.c +++ b/test/regress_main.c @@ -384,6 +384,7 @@ struct testgroup_t testgroups[] = { { "iocp/", iocp_testcases }, { "iocp/bufferevent/", bufferevent_iocp_testcases }, { "iocp/listener/", listener_iocp_testcases }, + { "iocp/http/", http_iocp_testcases }, #endif #ifdef EVENT__HAVE_OPENSSL { "ssl/", ssl_testcases },