static void bufferevent_run_deferred_callbacks_locked(struct deferred_cb *_, void *arg) { struct bufferevent_private *bufev_private = arg; struct bufferevent *bufev = &bufev_private->bev; BEV_LOCK(bufev); if ((bufev_private->eventcb_pending & BEV_EVENT_CONNECTED) && bufev->errorcb) { /* The "connected" happened before any reads or writes, so send it first. */ bufev_private->eventcb_pending &= ~BEV_EVENT_CONNECTED; bufev->errorcb(bufev, BEV_EVENT_CONNECTED, bufev->cbarg); } if (bufev_private->readcb_pending && bufev->readcb) { bufev_private->readcb_pending = 0; bufev->readcb(bufev, bufev->cbarg); } if (bufev_private->writecb_pending && bufev->writecb) { bufev_private->writecb_pending = 0; bufev->writecb(bufev, bufev->cbarg); } if (bufev_private->eventcb_pending && bufev->errorcb) { short what = bufev_private->eventcb_pending; int err = bufev_private->errno_pending; bufev_private->eventcb_pending = 0; bufev_private->errno_pending = 0; EVUTIL_SET_SOCKET_ERROR(err); bufev->errorcb(bufev, what, bufev->cbarg); } _bufferevent_decref_and_unlock(bufev); }
evutil_socket_t bind_socket_ai_(struct evutil_addrinfo* ai, int reuse) { evutil_socket_t fd; int on = 1, r; int serrno; fd = socket(ai ? ai->ai_family : AF_INET, SOCK_STREAM, 0); if (fd == -1) return -1; if (evutil_make_socket_nonblocking(fd) < 0) goto out; if (evutil_make_socket_closeonexec(fd) < 0) goto out; setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); if (reuse) evutil_make_listen_socket_reuseable(fd); if (ai != NULL) { r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen); if (r == -1) goto out; } return (fd); out: serrno = EVUTIL_SOCKET_ERROR(); evutil_closesocket(fd); EVUTIL_SET_SOCKET_ERROR(serrno); return -1; }
//信号处理函数 static void __cdecl evsig_handler(int sig) { int save_errno = errno; #ifdef WIN32 int socket_errno = EVUTIL_SOCKET_ERROR(); #endif ev_uint8_t msg; if (evsig_base == NULL) { event_warnx( "%s: received signal %d, but have no base configured", __func__, sig); return; } #ifndef _EVENT_HAVE_SIGACTION signal(sig, evsig_handler); #endif /* Wake up our notification mechanism */ msg = sig; send(evsig_base_fd, (char*)&msg, 1, 0);//将激活的信号发送给base errno = save_errno; #ifdef WIN32 EVUTIL_SET_SOCKET_ERROR(socket_errno); #endif }
static void __cdecl evsig_handler(int sig) { int save_errno = errno; #ifdef _WIN32 int socket_errno = EVUTIL_SOCKET_ERROR(); #endif ev_uint8_t msg; if (evsig_base == NULL) { event_warnx( "%s: received signal %d, but have no base configured", __func__, sig); return; } #ifndef EVENT__HAVE_SIGACTION signal(sig, evsig_handler); #endif /* Wake up our notification mechanism */ msg = sig; #ifdef _WIN32 send(evsig_base_fd, (char*)&msg, 1, 0); #else { int r = write(evsig_base_fd, (char*)&msg, 1); (void)r; /* Suppress 'unused return value' and 'unused var' */ } #endif errno = save_errno; #ifdef _WIN32 EVUTIL_SET_SOCKET_ERROR(socket_errno); #endif }
static int tr_peerIoTryWrite( tr_peerIo * io, size_t howmuch ) { int n = 0; if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_UP, howmuch ))) { int e; EVUTIL_SET_SOCKET_ERROR( 0 ); n = tr_evbuffer_write( io, io->socket, howmuch ); e = EVUTIL_SOCKET_ERROR( ); if( n > 0 ) didWriteWrapper( io, n ); if( ( n < 0 ) && ( io->gotError ) && ( e != EPIPE ) && ( e != EAGAIN ) && ( e != EINTR ) && ( e != EINPROGRESS ) ) { char errstr[512]; const short what = EVBUFFER_WRITE | EVBUFFER_ERROR; tr_net_strerror( errstr, sizeof( errstr ), e ); dbgmsg( io, "tr_peerIoTryWrite got an error. res is %d, what is %hd, errno is %d (%s)", n, what, e, errstr ); if( io->gotError != NULL ) io->gotError( io, what, io->userData ); } } return n; }
static void evsig_handler(int sig) { int save_errno = errno; #ifdef WIN32 int socket_errno = EVUTIL_SOCKET_ERROR(); #endif if (evsig_base == NULL) { event_warn( "%s: received signal %d, but have no base configured", __func__, sig); return; } evsig_base->sig.evsigcaught[sig]++; evsig_base->sig.evsig_caught = 1; #ifndef _EVENT_HAVE_SIGACTION signal(sig, evsig_handler); #endif /* Wake up our notification mechanism */ send(evsig_base->sig.ev_signal_pair[0], "a", 1, 0); errno = save_errno; #ifdef WIN32 EVUTIL_SET_SOCKET_ERROR(socket_errno); #endif }
static int tr_peerIoTryRead( tr_peerIo * io, size_t howmuch ) { int res = 0; if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch ))) { int e; EVUTIL_SET_SOCKET_ERROR( 0 ); res = evbuffer_read( io->inbuf, io->socket, (int)howmuch ); e = EVUTIL_SOCKET_ERROR( ); dbgmsg( io, "read %d from peer (%s)", res, (res==-1?strerror(e):"") ); if( EVBUFFER_LENGTH( io->inbuf ) ) canReadWrapper( io ); if( ( res <= 0 ) && ( io->gotError ) && ( e != EAGAIN ) && ( e != EINTR ) && ( e != EINPROGRESS ) ) { char errstr[512]; short what = EVBUFFER_READ | EVBUFFER_ERROR; if( res == 0 ) what |= EVBUFFER_EOF; tr_net_strerror( errstr, sizeof( errstr ), e ); dbgmsg( io, "tr_peerIoTryRead got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, errstr ); io->gotError( io, what, io->userData ); } } return res; }
static int tr_evbuffer_write( tr_peerIo * io, int fd, size_t howmuch ) { int e; int n; char errstr[256]; struct evbuffer * buffer = io->outbuf; howmuch = MIN( EVBUFFER_LENGTH( buffer ), howmuch ); EVUTIL_SET_SOCKET_ERROR( 0 ); #ifdef WIN32 n = (int) send(fd, buffer->buffer, howmuch, 0 ); #else n = (int) write(fd, buffer->buffer, howmuch ); #endif e = EVUTIL_SOCKET_ERROR( ); dbgmsg( io, "wrote %d to peer (%s)", n, (n==-1?tr_net_strerror(errstr,sizeof(errstr),e):"") ); if( n > 0 ) evbuffer_drain( buffer, (size_t)n ); /* keep the iobuf's excess capacity from growing too large */ if( EVBUFFER_LENGTH( io->outbuf ) == 0 ) { evbuffer_free( io->outbuf ); io->outbuf = evbuffer_new( ); } return n; }
static void sock_err_fn(void) { evutil_socket_t fd = socket(AF_INET, SOCK_STREAM, 0); #ifdef _WIN32 EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else errno = EAGAIN; #endif event_sock_err(20, fd, "Unhappy socket"); }
static void bufferevent_run_deferred_callbacks_unlocked(struct deferred_cb *_, void *arg) { struct bufferevent_private *bufev_private = arg; struct bufferevent *bufev = &bufev_private->bev; BEV_LOCK(bufev); #define UNLOCKED(stmt) \ do { BEV_UNLOCK(bufev); stmt; BEV_LOCK(bufev); } while(0) if ((bufev_private->eventcb_pending & BEV_EVENT_CONNECTED) && bufev->errorcb) { /* The "connected" happened before any reads or writes, so send it first. */ bufferevent_event_cb errorcb = bufev->errorcb; void *cbarg = bufev->cbarg; bufev_private->eventcb_pending &= ~BEV_EVENT_CONNECTED; UNLOCKED(errorcb(bufev, BEV_EVENT_CONNECTED, cbarg)); } if (bufev_private->readcb_pending && bufev->readcb) { bufferevent_data_cb readcb = bufev->readcb; void *cbarg = bufev->cbarg; bufev_private->readcb_pending = 0; UNLOCKED(readcb(bufev, cbarg)); } if (bufev_private->writecb_pending && bufev->writecb) { bufferevent_data_cb writecb = bufev->writecb; void *cbarg = bufev->cbarg; bufev_private->writecb_pending = 0; UNLOCKED(writecb(bufev, cbarg)); } if (bufev_private->eventcb_pending && bufev->errorcb) { bufferevent_event_cb errorcb = bufev->errorcb; void *cbarg = bufev->cbarg; short what = bufev_private->eventcb_pending; int err = bufev_private->errno_pending; bufev_private->eventcb_pending = 0; bufev_private->errno_pending = 0; EVUTIL_SET_SOCKET_ERROR(err); UNLOCKED(errorcb(bufev,what,cbarg)); } _bufferevent_decref_and_unlock(bufev); #undef UNLOCKED }
int evutil_socketpair(int family, int type, int protocol, int fd[2]) { #ifndef WIN32 return socketpair(family, type, protocol, fd); #else /* This code is originally from Tor. Used with permission. */ /* This socketpair does not work when localhost is down. So * it's really not the same thing at all. But it's close enough * for now, and really, when localhost is down sometimes, we * have other problems too. */ int listener = -1; int connector = -1; int acceptor = -1; struct sockaddr_in listen_addr; struct sockaddr_in connect_addr; int size; int saved_errno = -1; if (protocol #ifdef AF_UNIX || family != AF_UNIX #endif ) { EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT); return -1; } if (!fd) { EVUTIL_SET_SOCKET_ERROR(WSAEINVAL); return -1; } listener = socket(AF_INET, type, 0); if (listener < 0) return -1; memset(&listen_addr, 0, sizeof(listen_addr)); listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); listen_addr.sin_port = 0; /* kernel chooses port. */ if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) == -1) goto tidy_up_and_fail; if (listen(listener, 1) == -1) goto tidy_up_and_fail; connector = socket(AF_INET, type, 0); if (connector < 0) goto tidy_up_and_fail; /* We want to find out the port number to connect to. */ size = sizeof(connect_addr); if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) goto tidy_up_and_fail; if (size != sizeof (connect_addr)) goto abort_tidy_up_and_fail; if (connect(connector, (struct sockaddr *) &connect_addr, sizeof(connect_addr)) == -1) goto tidy_up_and_fail; size = sizeof(listen_addr); acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); if (acceptor < 0) goto tidy_up_and_fail; if (size != sizeof(listen_addr)) goto abort_tidy_up_and_fail; EVUTIL_CLOSESOCKET(listener); /* Now check we are talking to ourself by matching port and host on the two sockets. */ if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) goto tidy_up_and_fail; if (size != sizeof (connect_addr) || listen_addr.sin_family != connect_addr.sin_family || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr || listen_addr.sin_port != connect_addr.sin_port) goto abort_tidy_up_and_fail; fd[0] = connector; fd[1] = acceptor; return 0; abort_tidy_up_and_fail: saved_errno = WSAECONNABORTED; tidy_up_and_fail: if (saved_errno < 0) saved_errno = WSAGetLastError(); if (listener != -1) EVUTIL_CLOSESOCKET(listener); if (connector != -1) EVUTIL_CLOSESOCKET(connector); if (acceptor != -1) EVUTIL_CLOSESOCKET(acceptor); EVUTIL_SET_SOCKET_ERROR(saved_errno); return -1; #endif }
static void test_evutil_log(void *ptr) { evutil_socket_t fd = -1; char buf[128]; event_set_log_callback(logfn); event_set_fatal_callback(fatalfn); #define RESET() do { \ logsev = 0; \ if (logmsg) free(logmsg); \ logmsg = NULL; \ } while (0) #define LOGEQ(sev,msg) do { \ tt_int_op(logsev,==,sev); \ tt_assert(logmsg != NULL); \ tt_str_op(logmsg,==,msg); \ } while (0) #ifdef CAN_CHECK_ERR /* We need to disable these tests for now. Previously, the logging * module didn't enforce the requirement that a fatal callback * actually exit. Now, it exits no matter what, so if we wan to * reinstate these tests, we'll need to fork for each one. */ check_error_logging(errx_fn, 2, EVENT_LOG_ERR, "Fatal error; too many kumquats (5)"); RESET(); #endif event_warnx("Far too many %s (%d)", "wombats", 99); LOGEQ(EVENT_LOG_WARN, "Far too many wombats (99)"); RESET(); event_msgx("Connecting lime to coconut"); LOGEQ(EVENT_LOG_MSG, "Connecting lime to coconut"); RESET(); event_debug(("A millisecond passed! We should log that!")); #ifdef USE_DEBUG LOGEQ(EVENT_LOG_DEBUG, "A millisecond passed! We should log that!"); #else tt_int_op(logsev,==,0); tt_ptr_op(logmsg,==,NULL); #endif RESET(); /* Try with an errno. */ errno = ENOENT; event_warn("Couldn't open %s", "/bad/file"); evutil_snprintf(buf, sizeof(buf), "Couldn't open /bad/file: %s",strerror(ENOENT)); LOGEQ(EVENT_LOG_WARN,buf); RESET(); #ifdef CAN_CHECK_ERR evutil_snprintf(buf, sizeof(buf), "Couldn't open /very/bad/file: %s",strerror(ENOENT)); check_error_logging(err_fn, 5, EVENT_LOG_ERR, buf); RESET(); #endif /* Try with a socket errno. */ fd = socket(AF_INET, SOCK_STREAM, 0); #ifdef _WIN32 evutil_snprintf(buf, sizeof(buf), "Unhappy socket: %s", evutil_socket_error_to_string(WSAEWOULDBLOCK)); EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else evutil_snprintf(buf, sizeof(buf), "Unhappy socket: %s", strerror(EAGAIN)); errno = EAGAIN; #endif event_sock_warn(fd, "Unhappy socket"); LOGEQ(EVENT_LOG_WARN, buf); RESET(); #ifdef CAN_CHECK_ERR check_error_logging(sock_err_fn, 20, EVENT_LOG_ERR, buf); RESET(); #endif #undef RESET #undef LOGEQ end: if (logmsg) free(logmsg); if (fd >= 0) evutil_closesocket(fd); }
static void test_evutil_log(void *ptr) { evutil_socket_t fd = -1; char buf[128]; event_set_log_callback(logfn); event_set_fatal_callback(fatalfn); #define RESET() do { \ logsev = exited = exitcode = 0; \ if (logmsg) free(logmsg); \ logmsg = NULL; \ } while (0) #define LOGEQ(sev,msg) do { \ tt_int_op(logsev,==,sev); \ tt_assert(logmsg != NULL); \ tt_str_op(logmsg,==,msg); \ } while (0) event_errx(2, "Fatal error; too many kumquats (%d)", 5); LOGEQ(_EVENT_LOG_ERR, "Fatal error; too many kumquats (5)"); tt_int_op(exitcode,==,2); RESET(); event_warnx("Far too many %s (%d)", "wombats", 99); LOGEQ(_EVENT_LOG_WARN, "Far too many wombats (99)"); tt_int_op(exited,==,0); RESET(); event_msgx("Connecting lime to coconut"); LOGEQ(_EVENT_LOG_MSG, "Connecting lime to coconut"); tt_int_op(exited,==,0); RESET(); event_debug(("A millisecond passed! We should log that!")); #ifdef USE_DEBUG LOGEQ(_EVENT_LOG_DEBUG, "A millisecond passed! We should log that!"); #else tt_int_op(logsev,==,0); tt_ptr_op(logmsg,==,NULL); #endif RESET(); /* Try with an errno. */ errno = ENOENT; event_warn("Couldn't open %s", "/bad/file"); evutil_snprintf(buf, sizeof(buf), "Couldn't open /bad/file: %s",strerror(ENOENT)); LOGEQ(_EVENT_LOG_WARN,buf); tt_int_op(exited, ==, 0); RESET(); errno = ENOENT; event_err(5,"Couldn't open %s", "/very/bad/file"); evutil_snprintf(buf, sizeof(buf), "Couldn't open /very/bad/file: %s",strerror(ENOENT)); LOGEQ(_EVENT_LOG_ERR,buf); tt_int_op(exitcode, ==, 5); RESET(); /* Try with a socket errno. */ fd = socket(AF_INET, SOCK_STREAM, 0); #ifdef WIN32 evutil_snprintf(buf, sizeof(buf), "Unhappy socket: %s", evutil_socket_error_to_string(WSAEWOULDBLOCK)); EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else evutil_snprintf(buf, sizeof(buf), "Unhappy socket: %s", strerror(EAGAIN)); errno = EAGAIN; #endif event_sock_warn(fd, "Unhappy socket"); LOGEQ(_EVENT_LOG_WARN, buf); tt_int_op(exited,==,0); RESET(); #ifdef WIN32 EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else errno = EAGAIN; #endif event_sock_err(200, fd, "Unhappy socket"); LOGEQ(_EVENT_LOG_ERR, buf); tt_int_op(exitcode,==,200); RESET(); #undef RESET #undef LOGEQ end: if (logmsg) free(logmsg); if (fd >= 0) EVUTIL_CLOSESOCKET(fd); }
int evutil_socketpair(int family, int type, int protocol, int fd[2]) { #ifndef WIN32 return socketpair(family, type, protocol, fd); #else int listener = -1; int connector = -1; int acceptor = -1; struct sockaddr_in listen_addr; struct sockaddr_in connect_addr; int size; int saved_errno = -1; if (protocol #ifdef AF_UNIX || family != AF_UNIX #endif ) { EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT); return -1; } if (!fd) { EVUTIL_SET_SOCKET_ERROR(WSAEINVAL); return -1; } listener = socket(AF_INET, type, 0); if (listener < 0) return -1; memset(&listen_addr, 0, sizeof(listen_addr)); listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); listen_addr.sin_port = 0; if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) == -1) goto tidy_up_and_fail; if (listen(listener, 1) == -1) goto tidy_up_and_fail; connector = socket(AF_INET, type, 0); if (connector < 0) goto tidy_up_and_fail; size = sizeof(connect_addr); if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) goto tidy_up_and_fail; if (size != sizeof (connect_addr)) goto abort_tidy_up_and_fail; if (connect(connector, (struct sockaddr *) &connect_addr, sizeof(connect_addr)) == -1) goto tidy_up_and_fail; size = sizeof(listen_addr); acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); if (acceptor < 0) goto tidy_up_and_fail; if (size != sizeof(listen_addr)) goto abort_tidy_up_and_fail; EVUTIL_CLOSESOCKET(listener); if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) goto tidy_up_and_fail; if (size != sizeof (connect_addr) || listen_addr.sin_family != connect_addr.sin_family || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr || listen_addr.sin_port != connect_addr.sin_port) goto abort_tidy_up_and_fail; fd[0] = connector; fd[1] = acceptor; return 0; abort_tidy_up_and_fail: saved_errno = WSAECONNABORTED; tidy_up_and_fail: if (saved_errno < 0) saved_errno = WSAGetLastError(); if (listener != -1) EVUTIL_CLOSESOCKET(listener); if (connector != -1) EVUTIL_CLOSESOCKET(connector); if (acceptor != -1) EVUTIL_CLOSESOCKET(acceptor); EVUTIL_SET_SOCKET_ERROR(saved_errno); return -1; #endif }
static void event_write_cb( int fd, short event UNUSED, void * vio ) { int res = 0; int e; short what = EVBUFFER_WRITE; tr_peerIo * io = vio; size_t howmuch; const tr_direction dir = TR_UP; assert( tr_isPeerIo( io ) ); io->hasFinishedConnecting = TRUE; io->pendingEvents &= ~EV_WRITE; dbgmsg( io, "libevent says this peer is ready to write" ); /* Write as much as possible, since the socket is non-blocking, write() will * return if it can't write any more data without blocking */ howmuch = tr_bandwidthClamp( &io->bandwidth, dir, EVBUFFER_LENGTH( io->outbuf ) ); /* if we don't have any bandwidth left, stop writing */ if( howmuch < 1 ) { tr_peerIoSetEnabled( io, dir, FALSE ); return; } EVUTIL_SET_SOCKET_ERROR( 0 ); res = tr_evbuffer_write( io, fd, howmuch ); e = EVUTIL_SOCKET_ERROR( ); if (res == -1) { if (e == EAGAIN || e == EINTR || e == EINPROGRESS) goto reschedule; /* error case */ what |= EVBUFFER_ERROR; } else if (res == 0) { /* eof case */ what |= EVBUFFER_EOF; } if (res <= 0) goto error; if( EVBUFFER_LENGTH( io->outbuf ) ) tr_peerIoSetEnabled( io, dir, TRUE ); didWriteWrapper( io, res ); return; reschedule: if( EVBUFFER_LENGTH( io->outbuf ) ) tr_peerIoSetEnabled( io, dir, TRUE ); return; error: dbgmsg( io, "event_write_cb got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, strerror( e ) ); if( io->gotError != NULL ) io->gotError( io, what, io->userData ); }
static void event_read_cb( int fd, short event UNUSED, void * vio ) { int res; int e; tr_peerIo * io = vio; /* Limit the input buffer to 256K, so it doesn't grow too large */ unsigned int howmuch; unsigned int curlen; const tr_direction dir = TR_DOWN; const unsigned int max = 256 * 1024; assert( tr_isPeerIo( io ) ); io->hasFinishedConnecting = TRUE; io->pendingEvents &= ~EV_READ; curlen = EVBUFFER_LENGTH( io->inbuf ); howmuch = curlen >= max ? 0 : max - curlen; howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch ); dbgmsg( io, "libevent says this peer is ready to read" ); /* if we don't have any bandwidth left, stop reading */ if( howmuch < 1 ) { tr_peerIoSetEnabled( io, dir, FALSE ); return; } EVUTIL_SET_SOCKET_ERROR( 0 ); res = evbuffer_read( io->inbuf, fd, (int)howmuch ); e = EVUTIL_SOCKET_ERROR( ); if( res > 0 ) { tr_peerIoSetEnabled( io, dir, TRUE ); /* Invoke the user callback - must always be called last */ canReadWrapper( io ); } else { char errstr[512]; short what = EVBUFFER_READ; if( res == 0 ) /* EOF */ what |= EVBUFFER_EOF; else if( res == -1 ) { if( e == EAGAIN || e == EINTR ) { tr_peerIoSetEnabled( io, dir, TRUE ); return; } what |= EVBUFFER_ERROR; } tr_net_strerror( errstr, sizeof( errstr ), e ); dbgmsg( io, "event_read_cb got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, errstr ); if( io->gotError != NULL ) io->gotError( io, what, io->userData ); } }