#endif /* HAVE_TLS */
+#ifdef LDAP_DEVEL
+#define LDAP_USE_NON_BLOCKING_TLS
+#endif /* LDAP_DEVEL */
+
/* RFC2459 minimum required set of supported attribute types
* in a certificate DN
*/
Sockbuf *sb;
char *host;
void *ssl;
+ int ret;
+#ifdef LDAP_USE_NON_BLOCKING_TLS
+ struct timeval start_time_tv, tv, tv0;
+ ber_socket_t sd = AC_SOCKET_ERROR;
+#endif /* LDAP_USE_NON_BLOCKING_TLS */
if ( !conn )
return LDAP_PARAM_ERROR;
(void) tls_init( tls_imp );
+#ifdef LDAP_USE_NON_BLOCKING_TLS
/*
- * Fortunately, the lib uses blocking io...
+ * Use non-blocking io during SSL Handshake when a timeout is configured
*/
- if ( ldap_int_tls_connect( ld, conn ) < 0 ) {
- ld->ld_errno = LDAP_CONNECT_ERROR;
+ if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_SET_NONBLOCK, sb );
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+ tv = ld->ld_options.ldo_tm_net;
+ tv0 = tv;
+#ifdef HAVE_GETTIMEOFDAY
+ gettimeofday( &start_time_tv, NULL );
+#else /* ! HAVE_GETTIMEOFDAY */
+ time( &start_time_tv.tv_sec );
+ start_time_tv.tv_usec = 0;
+#endif /* ! HAVE_GETTIMEOFDAY */
+ }
+
+#endif /* LDAP_USE_NON_BLOCKING_TLS */
+
+ ld->ld_errno = LDAP_SUCCESS;
+ ret = ldap_int_tls_connect( ld, conn );
+
+#ifdef LDAP_USE_NON_BLOCKING_TLS
+ while ( ret > 0 ) { /* this should only happen for non-blocking io */
+ int wr=0;
+
+ if ( sb->sb_trans_needs_read ) {
+ wr=0;
+ } else if ( sb->sb_trans_needs_write ) {
+ wr=1;
+ }
+ Debug( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ldap_int_tls_connect needs %s\n",
+ wr ? "write": "read", 0, 0);
+
+ ret = ldap_int_poll( ld, sd, &tv, wr);
+ if ( ret < 0 ) {
+ ld->ld_errno = LDAP_TIMEOUT;
+ break;
+ } else {
+ /* ldap_int_poll called ldap_pvt_ndelay_off */
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_SET_NONBLOCK, sb );
+ ret = ldap_int_tls_connect( ld, conn );
+ if ( ret > 0 ) { /* need to call tls_connect once more */
+ struct timeval curr_time_tv, delta_tv;
+
+ /* This is mostly copied from result.c:wait4msg(), should
+ * probably be moved into a separate function */
+#ifdef HAVE_GETTIMEOFDAY
+ gettimeofday( &curr_time_tv, NULL );
+#else /* ! HAVE_GETTIMEOFDAY */
+ time( &curr_time_tv.tv_sec );
+ curr_time_tv.tv_usec = 0;
+#endif /* ! HAVE_GETTIMEOFDAY */
+
+ /* delta = curr - start */
+ delta_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec;
+ delta_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
+ if ( delta_tv.tv_usec < 0 ) {
+ delta_tv.tv_sec--;
+ delta_tv.tv_usec += 1000000;
+ }
+
+ /* tv0 < delta ? */
+ if ( ( tv0.tv_sec < delta_tv.tv_sec ) ||
+ ( ( tv0.tv_sec == delta_tv.tv_sec ) &&
+ ( tv0.tv_usec < delta_tv.tv_usec ) ) )
+ {
+ ret = -1;
+ ld->ld_errno = LDAP_TIMEOUT;
+ break;
+ } else {
+ /* timeout -= delta_time */
+ tv0.tv_sec -= delta_tv.tv_sec;
+ tv0.tv_usec -= delta_tv.tv_usec;
+ if ( tv0.tv_usec < 0 ) {
+ tv0.tv_sec--;
+ tv0.tv_usec += 1000000;
+ }
+ start_time_tv.tv_sec = curr_time_tv.tv_sec;
+ start_time_tv.tv_usec = curr_time_tv.tv_usec;
+ }
+ tv = tv0;
+ Debug( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ld %p %ld s %ld us to go\n",
+ (void *)ld, (long) tv.tv_sec, (long) tv.tv_usec );
+ }
+ }
+ }
+ if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_SET_NONBLOCK, NULL );
+ }
+#endif /* LDAP_USE_NON_BLOCKING_TLS */
+
+ if ( ret < 0 ) {
+ if ( ld->ld_errno == LDAP_SUCCESS )
+ ld->ld_errno = LDAP_CONNECT_ERROR;
return (ld->ld_errno);
}