示例#1
0
static void start_connect(SESSION *session)
{
    int     fd;
    struct linger linger;

    /*
     * Some systems don't set the socket error when connect() fails early
     * (loopback) so we must deal with the error immediately, rather than
     * retrieving it later with getsockopt(). We can't use MSG_PEEK to
     * distinguish between server disconnect and connection refused.
     */
    if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
        msg_fatal("socket: %m");
    (void) non_blocking(fd, NON_BLOCKING);
    linger.l_onoff = 1;
    linger.l_linger = 0;
    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &linger,
                   sizeof(linger)) < 0)
        msg_warn("setsockopt SO_LINGER %d: %m", linger.l_linger);
    session->stream = vstream_fdopen(fd, O_RDWR);
    event_enable_write(fd, connect_done, (char *) session);
    smtp_timeout_setup(session->stream, var_timeout);
    if (inet_windowsize > 0)
        set_inet_windowsize(fd, inet_windowsize);
    if (sane_connect(fd, sa, sa_length) < 0 && errno != EINPROGRESS)
        fail_connect(session);
}
示例#2
0
void    nbbio_enable_write(NBBIO *np, int timeout)
{
    const char *myname = "nbbio_enable_write";

    /*
     * Sanity checks.
     */
    if (np->flags & NBBIO_MASK_ACTIVE)
	msg_panic("%s: socket fd=%d is enabled for %s",
		  myname, np->fd, NBBIO_OP_NAME(np));
    if (timeout <= 0)
	msg_panic("%s: socket fd=%d bad timeout %d",
		  myname, np->fd, timeout);
    if (np->write_pend <= 0)
	msg_panic("%s: socket fd=%d: empty write buffer",
		  myname, np->fd);

    /*
     * Enable events.
     */
    event_enable_write(np->fd, nbbio_event, (char *) np);
    event_request_timer(nbbio_event, (char *) np, timeout);
    np->flags |= NBBIO_FLAG_WRITE;
}
示例#3
0
static int tlsp_eval_tls_error(TLSP_STATE *state, int err)
{
    int     ciphertext_fd = state->ciphertext_fd;

    /*
     * The ciphertext file descriptor is in non-blocking mode, meaning that
     * each SSL_accept/connect/read/write/shutdown request may return an
     * "error" indication that it needs to read or write more ciphertext. The
     * purpose of this routine is to translate those "error" indications into
     * the appropriate read/write/timeout event requests.
     */
    switch (err) {

    /*
     * No error from SSL_read and SSL_write means that the plaintext
     * output buffer is full and that the plaintext input buffer is
     * empty. Stop read/write events on the ciphertext stream. Keep the
     * timer alive as a safety mechanism for the case that the plaintext
     * pseudothreads get stuck.
     */
    case SSL_ERROR_NONE:
        if (state->ssl_last_err != SSL_ERROR_NONE) {
            event_disable_readwrite(ciphertext_fd);
            event_request_timer(tlsp_ciphertext_event, (void *) state,
                                state->timeout);
            state->ssl_last_err = SSL_ERROR_NONE;
        }
        return (0);

    /*
     * The TLS engine wants to write to the network. Turn on
     * write/timeout events on the ciphertext stream.
     */
    case SSL_ERROR_WANT_WRITE:
        if (state->ssl_last_err == SSL_ERROR_WANT_READ)
            event_disable_readwrite(ciphertext_fd);
        if (state->ssl_last_err != SSL_ERROR_WANT_WRITE) {
            event_enable_write(ciphertext_fd, tlsp_ciphertext_event,
                               (void *) state);
            state->ssl_last_err = SSL_ERROR_WANT_WRITE;
        }
        event_request_timer(tlsp_ciphertext_event, (void *) state,
                            state->timeout);
        return (0);

    /*
     * The TLS engine wants to read from the network. Turn on
     * read/timeout events on the ciphertext stream.
     */
    case SSL_ERROR_WANT_READ:
        if (state->ssl_last_err == SSL_ERROR_WANT_WRITE)
            event_disable_readwrite(ciphertext_fd);
        if (state->ssl_last_err != SSL_ERROR_WANT_READ) {
            event_enable_read(ciphertext_fd, tlsp_ciphertext_event,
                              (void *) state);
            state->ssl_last_err = SSL_ERROR_WANT_READ;
        }
        event_request_timer(tlsp_ciphertext_event, (void *) state,
                            state->timeout);
        return (0);

    /*
     * Some error. Self-destruct. This automagically cleans up all
     * pending read/write and timeout event requests, making state a
     * dangling pointer.
     */
    case SSL_ERROR_SSL:
        tls_print_errors();
    /* FALLTHROUGH */
    default:
        tlsp_state_free(state);
        return (-1);
    }
}