struct evconnlistener * evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, int socklen) { struct evconnlistener *listener; evutil_socket_t fd; int on = 1; int family = sa ? sa->sa_family : AF_UNSPEC; int socktype = SOCK_STREAM | EVUTIL_SOCK_NONBLOCK; if (backlog == 0) return NULL; if (flags & LEV_OPT_CLOSE_ON_EXEC) socktype |= EVUTIL_SOCK_CLOEXEC; fd = evutil_socket_(family, socktype, 0); if (fd == -1) return NULL; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0) goto err; if (flags & LEV_OPT_REUSEABLE) { if (evutil_make_listen_socket_reuseable(fd) < 0) goto err; } if (flags & LEV_OPT_REUSEABLE_PORT) { if (evutil_make_listen_socket_reuseable_port(fd) < 0) goto err; } if (flags & LEV_OPT_DEFERRED_ACCEPT) { if (evutil_make_tcp_listen_socket_deferred(fd) < 0) goto err; } if (sa) { if (bind(fd, sa, socklen)<0) goto err; } listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd); if (!listener) goto err; return listener; err: evutil_closesocket(fd); return NULL; }
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *sa, int socklen) { struct bufferevent_private *bufev_p = EVUTIL_UPCAST(bev, struct bufferevent_private, bev); evutil_socket_t fd; int r = 0; int result=-1; int ownfd = 0; bufferevent_incref_and_lock_(bev); if (!bufev_p) goto done; fd = bufferevent_getfd(bev); if (fd < 0) { if (!sa) goto done; fd = evutil_socket_(sa->sa_family, SOCK_STREAM|EVUTIL_SOCK_NONBLOCK, 0); if (fd < 0) goto done; ownfd = 1; } if (sa) { #ifdef _WIN32 if (bufferevent_async_can_connect_(bev)) { bufferevent_setfd(bev, fd); r = bufferevent_async_connect_(bev, fd, sa, socklen); if (r < 0) goto freesock; bufev_p->connecting = 1; result = 0; goto done; } else #endif r = evutil_socket_connect_(&fd, sa, socklen); if (r < 0) goto freesock; } #ifdef _WIN32 /* ConnectEx() isn't always around, even when IOCP is enabled. * Here, we borrow the socket object's write handler to fall back * on a non-blocking connect() when ConnectEx() is unavailable. */ if (BEV_IS_ASYNC(bev)) { event_assign(&bev->ev_write, bev->ev_base, fd, EV_WRITE|EV_PERSIST, bufferevent_writecb, bev); } #endif bufferevent_setfd(bev, fd); if (r == 0) { if (! be_socket_enable(bev, EV_WRITE)) { bufev_p->connecting = 1; result = 0; goto done; } } else if (r == 1) { /* The connect succeeded already. How very BSD of it. */ result = 0; bufev_p->connecting = 1; event_active(&bev->ev_write, EV_WRITE, 1); } else { /* The connect failed already. How very BSD of it. */ bufev_p->connection_refused = 1; bufev_p->connecting = 1; result = 0; event_active(&bev->ev_write, EV_WRITE, 1); } goto done; freesock: bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR); if (ownfd) evutil_closesocket(fd); /* do something about the error? */ done: bufferevent_decref_and_unlock_(bev); return result; }