예제 #1
0
파일: ioev.c 프로젝트: Vaelatern/OpenSMTPD
void
io_dispatch_connect(int fd, short ev, void *humppa)
{
	struct io	*io = humppa;
	int		 r, e;
	socklen_t	 sl;

	io_frame_enter("io_dispatch_connect", io, ev);

	if (ev == EV_TIMEOUT) {
		close(fd);
		io->sock = -1;
		io_callback(io, IO_TIMEOUT);
	} else {
		sl = sizeof(e);
		r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &e, &sl);
		if (r == -1)  {
			warn("io_dispatch_connect: getsockopt");
			e = errno;
		}
		if (e) {
			close(fd);
			io->sock = -1;
			io->error = strerror(e);
			io_callback(io, e == ETIMEDOUT ? IO_TIMEOUT : IO_ERROR);
		}
		else {
			io->state = IO_STATE_UP;
			io_callback(io, IO_CONNECTED);
		}
	}

	io_frame_leave(io);
}
예제 #2
0
파일: ioev.c 프로젝트: OpenSMTPD/OpenSMTPD
void
io_dispatch(int fd, short ev, void *humppa)
{
	struct io	*io = humppa;
	size_t		 w;
	ssize_t		 n;
	int		 saved_errno;

	io_frame_enter("io_dispatch", io, ev);

	if (ev == EV_TIMEOUT) {
		io_callback(io, IO_TIMEOUT);
		goto leave;
	}

	if (ev & EV_WRITE && (w = io_queued(io))) {
		if ((n = iobuf_write(&io->iobuf, io->sock)) < 0) {
			if (n == IOBUF_WANT_WRITE) /* kqueue bug? */
				goto read;
			if (n == IOBUF_CLOSED)
				io_callback(io, IO_DISCONNECTED);
			else {
				saved_errno = errno;
				io->error = strerror(errno);
				errno = saved_errno;
				io_callback(io, IO_ERROR);
			}
			goto leave;
		}
		if (w > io->lowat && w - n <= io->lowat)
			io_callback(io, IO_LOWAT);
	}
    read:

	if (ev & EV_READ) {
		iobuf_normalize(&io->iobuf);
		if ((n = iobuf_read(&io->iobuf, io->sock)) < 0) {
			if (n == IOBUF_CLOSED)
				io_callback(io, IO_DISCONNECTED);
			else {
				saved_errno = errno;
				io->error = strerror(errno);
				errno = saved_errno;
				io_callback(io, IO_ERROR);
			}
			goto leave;
		}
		if (n)
			io_callback(io, IO_DATAIN);
	}

leave:
	io_frame_leave(io);
}
예제 #3
0
파일: ioev.c 프로젝트: Vaelatern/OpenSMTPD
void
io_dispatch_write_ssl(int fd, short event, void *humppa)
{
	struct io	*io = humppa;
	int		 n, saved_errno;
	size_t		 w2, w;

	io_frame_enter("io_dispatch_write_ssl", io, event);

	if (event == EV_TIMEOUT) {
		io_callback(io, IO_TIMEOUT);
		goto leave;
	}

	w = io_queued(io);
	switch ((n = iobuf_write_ssl(io->iobuf, (SSL*)io->ssl))) {
	case IOBUF_WANT_READ:
		io_reset(io, EV_READ, io_dispatch_write_ssl);
		break;
	case IOBUF_WANT_WRITE:
		io_reset(io, EV_WRITE, io_dispatch_write_ssl);
		break;
	case IOBUF_CLOSED:
		io_callback(io, IO_DISCONNECTED);
		break;
	case IOBUF_ERROR:
		saved_errno = errno;
		io->error = strerror(errno);
		errno = saved_errno;
		io_callback(io, IO_ERROR);
		break;
	case IOBUF_SSLERROR:
		io->error = io_ssl_error();
		ssl_error("io_dispatch_write_ssl:SSL_write");
		io_callback(io, IO_ERROR);
		break;
	default:
		io_debug("io_dispatch_write_ssl(...) -> w=%d\n", n);
		w2 = io_queued(io);
		if (w > io->lowat && w2 <= io->lowat)
			io_callback(io, IO_LOWAT);
		break;
	}

    leave:
	io_frame_leave(io);
}
예제 #4
0
파일: ioev.c 프로젝트: OpenSMTPD/OpenSMTPD
void
io_dispatch_read_ssl(int fd, short event, void *humppa)
{
	struct io	*io = humppa;
	int		 n, saved_errno;

	io_frame_enter("io_dispatch_read_ssl", io, event);

	if (event == EV_TIMEOUT) {
		io_callback(io, IO_TIMEOUT);
		goto leave;
	}

again:
	iobuf_normalize(&io->iobuf);
	switch ((n = iobuf_read_ssl(&io->iobuf, (SSL*)io->ssl))) {
	case IOBUF_WANT_READ:
		io_reset(io, EV_READ, io_dispatch_read_ssl);
		break;
	case IOBUF_WANT_WRITE:
		io_reset(io, EV_WRITE, io_dispatch_read_ssl);
		break;
	case IOBUF_CLOSED:
		io_callback(io, IO_DISCONNECTED);
		break;
	case IOBUF_ERROR:
		saved_errno = errno;
		io->error = strerror(errno);
		errno = saved_errno;
		io_callback(io, IO_ERROR);
		break;
	case IOBUF_SSLERROR:
		io->error = io_ssl_error();
		ssl_error("io_dispatch_read_ssl:SSL_read");
		io_callback(io, IO_ERROR);
		break;
	default:
		io_debug("io_dispatch_read_ssl(...) -> r=%d\n", n);
		io_callback(io, IO_DATAIN);
		if (current == io && IO_READING(io) && SSL_pending(io->ssl))
			goto again;
	}

    leave:
	io_frame_leave(io);
}
예제 #5
0
파일: ioev.c 프로젝트: Vaelatern/OpenSMTPD
void
io_dispatch_connect_ssl(int fd, short event, void *humppa)
{
	struct io	*io = humppa;
	int		 e, ret;

	io_frame_enter("io_dispatch_connect_ssl", io, event);

	if (event == EV_TIMEOUT) {
		io_callback(io, IO_TIMEOUT);
		goto leave;
	}

	if ((ret = SSL_connect(io->ssl)) > 0) {
		io->state = IO_STATE_UP;
		io_callback(io, IO_TLSREADY);
		goto leave;
	}

	switch ((e = SSL_get_error(io->ssl, ret))) {
	case SSL_ERROR_WANT_READ:
		io_reset(io, EV_READ, io_dispatch_connect_ssl);
		break;
	case SSL_ERROR_WANT_WRITE:
		io_reset(io, EV_WRITE, io_dispatch_connect_ssl);
		break;
	default:
		io->error = io_ssl_error();
		ssl_error("io_dispatch_connect_ssl:SSL_connect");
		io_callback(io, IO_TLSERROR);
		break;
	}

    leave:
	io_frame_leave(io);
}