Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
//信号处理函数
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
}
Beispiel #4
0
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
}
Beispiel #5
0
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;
}
Beispiel #6
0
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
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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");
}
Beispiel #10
0
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
}
Beispiel #11
0
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
}
Beispiel #12
0
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);
}
Beispiel #13
0
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);
}
Beispiel #14
0
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
}
Beispiel #15
0
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 );
}
Beispiel #16
0
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 );
    }
}