+static ldap_pvt_thread_t listener_tid;
+static volatile sig_atomic_t slapd_listener = 0;
+
+static struct slap_daemon {
+ ldap_pvt_thread_mutex_t sd_mutex;
+
+ int sd_nactives;
+
+#ifndef HAVE_WINSOCK
+ /* In winsock, accept() returns values higher than dtblsize
+ so don't bother with this optimization */
+ int sd_nfds;
+#endif
+
+ fd_set sd_actives;
+ fd_set sd_readers;
+ fd_set sd_writers;
+} slap_daemon;
+
+/*
+ * Add a descriptor to daemon control
+ */
+static void slapd_add(ber_socket_t s) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+
+ assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
+ assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
+ assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
+
+#ifndef HAVE_WINSOCK
+ if (s >= slap_daemon.sd_nfds) {
+ slap_daemon.sd_nfds = s + 1;
+ }
+#endif
+
+ FD_SET( s, &slap_daemon.sd_actives );
+ FD_SET( s, &slap_daemon.sd_readers );
+
+ Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
+ (long) s,
+ FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
+ FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+}
+
+/*
+ * Remove the descriptor from daemon control
+ */
+void slapd_remove(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
+ (long) s,
+ FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
+ FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
+
+ FD_CLR( s, &slap_daemon.sd_actives );
+ FD_CLR( s, &slap_daemon.sd_readers );
+ FD_CLR( s, &slap_daemon.sd_writers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+}
+
+void slapd_clr_write(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+ FD_CLR( s, &slap_daemon.sd_writers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ if( wake ) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+}
+
+void slapd_set_write(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+ FD_SET( (unsigned) s, &slap_daemon.sd_writers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ if( wake ) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+}
+
+void slapd_clr_read(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+ FD_CLR( s, &slap_daemon.sd_readers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ if( wake ) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+}
+
+void slapd_set_read(ber_socket_t s, int wake) {
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ WAKE_LISTENER(wake);
+
+ assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+ FD_SET( s, &slap_daemon.sd_readers );
+
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+ if( wake ) {
+ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+ }
+}
+
+static void slapd_close(ber_socket_t s) {
+ Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
+ (long) s, 0, 0 );
+ tcp_close(s);
+}
+
+
+Listener *
+open_listener(
+ const char* url,
+ int port,
+ int tls_port )