Hi David and others, I was gone attending a conference and could not reply earlier.
David, I believe I am following your advise. Trying to connect and wait only when SSL tells me to do so. So here is what I have been doing, followed by the code. 1) Open a socket and make it non-blocking. 2) Add socket to epoll testing for writability. 3) When epoll returns, first do a TCP connect. If TCP connect completes, move on to the next stage. Otherwise, monitor socket for both readability and writeability and wait on epoll. When epoll returns, tcp connect better be finished. 4) When TCP connect finishes, monitor the socket for writeability and wait for epoll to return before I *start* the SSL connect. I am dealing with many sockets so before I start SSL connect on the current socket, I want to see if there is anything to do with some of the other sockets (like reading/processing data). 5) Now, when epoll returns, I set up SSL specific parameters. Call SSL_connect. If there is an error, call SSL_get_error. If it returns *_WRITE/*_READ, I monitor the socket for EPOLLOUT/EPOLLIN and go back and wait. 6) When epoll returns, I go back and try SSL_connect again. Here is the code: int main(int argc, char **argv) { sock = socket(AF_INET, SOCK_STREAM, 0); // Set the socket as non-blocking mode = fcntl(sock, F_GETFL, 0); mode |= O_NONBLOCK; mode = fcntl(sock, F_SETFL, mode); // Set up epoll to be writeable ev.events = EPOLLOUT; ev.data.fd = sock; res = epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev); state = TCP_CONNECT; while (!done) { num_fd = epoll_wait(epfd, events, MAXEVENTS, timeout_msec); action(); } } //------------------------------------------------------------------------------ void action() { switch (state) { case TCP_CONNECT: if (tcp_connect()) state = SSL_CONNECT; break; case SSL_CONNECT: if (ssl_connect()) done = TRUE; break; } } //------------------------------------------------------------------------------ BOOL tcp_connect() { struct sockaddr_in server_addr; int r_code, addrlen; if (first_time) { server_addr.sin_family = AF_INET; server_addr.sin_port = htons(443); server_addr.sin_addr.s_addr = some_addr; bzero(&(server_addr.sin_zero), 8); addrlen = sizeof(struct sockaddr); r_code = connect(sock, (struct sockaddr *)&server_addr, addrlen); if (r_code == 0) return TRUE; if (errno == EINPROGRESS) { ev.events = EPOLLIN | EPOLLOUT; ev.data.fd = sock; epoll_ctl(epfd, EPOLL_CTL_MOD, sock, &ev); } else exit(0); return FALSE; } r_code = getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen); if (r_code < 0 || optval != 0) return FALSE; /* Get ready for SSL connect */ ev.events = EPOLLOUT; ev.data.fd = sock; epoll_ctl(epfd, EPOLL_CTL_MOD, sock, &ev); return TRUE; } //------------------------------------------------------------------------------ BOOL ssl_connect() { BIO *sbio; int r_code; if (first_time) // First time coming here { ssl = SSL_new(ctx); sbio = BIO_new_socket(sock, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); } r_code = SSL_connect(ssl); if (r_code == 1) return TRUE; switch(SSL_get_error(ssl, r_code)) { case SSL_ERROR_WANT_WRITE: epoll_control(s_epfd, EPOLL_CTL_MOD, handle->sock, EPOLLOUT); break; case SSL_ERROR_WANT_READ: epoll_control(s_epfd, EPOLL_CTL_MOD, handle->sock, EPOLLIN); break; } return FALSE; } Any thoughts? -Rij ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org