void SrsServer::destroy() { srs_warn("start destroy server"); _srs_config->unsubscribe(this); close_listeners(SrsListenerRtmpStream); close_listeners(SrsListenerHttpApi); close_listeners(SrsListenerHttpStream); #ifdef SRS_AUTO_INGEST ingester->stop(); #endif #ifdef SRS_AUTO_HTTP_API srs_freep(http_api_handler); #endif #ifdef SRS_AUTO_HTTP_SERVER srs_freep(http_stream_handler); #endif #ifdef SRS_AUTO_HTTP_PARSER srs_freep(http_heartbeat); #endif #ifdef SRS_AUTO_INGEST srs_freep(ingester); #endif if (pid_fd > 0) { ::close(pid_fd); pid_fd = -1; } srs_freep(signal_manager); srs_freep(kbps); for (std::vector<SrsConnection*>::iterator it = conns.begin(); it != conns.end();) { SrsConnection* conn = *it; // remove the connection, then free it, // for the free will remove itself from server, // when erased here, the remove of server will ignore. it = conns.erase(it); srs_freep(conn); } conns.clear(); SrsSource::destroy(); }
SrsServer::~SrsServer() { _srs_config->unsubscribe(this); if (true) { std::vector<SrsConnection*>::iterator it; for (it = conns.begin(); it != conns.end(); ++it) { SrsConnection* conn = *it; srs_freep(conn); } conns.clear(); } close_listeners(); #ifdef SRS_HTTP_API srs_freep(http_api_handler); #endif #ifdef SRS_HTTP_SERVER srs_freep(http_stream_handler); #endif #ifdef SRS_INGEST srs_freep(ingester); #endif }
int SrsServer::on_reload_http_stream_disabled() { int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_SERVER close_listeners(SrsListenerHttpStream); #endif return ret; }
int SrsServer::on_reload_http_api_disabled() { int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_API close_listeners(SrsListenerHttpApi); #endif return ret; }
int SrsServer::listen() { int ret = ERROR_SUCCESS; SrsConfDirective* conf = NULL; // stream service port. conf = _srs_config->get_listen(); srs_assert(conf); close_listeners(); for (int i = 0; i < (int)conf->args.size(); i++) { SrsListener* listener = new SrsListener(this, SrsListenerRtmpStream); listeners.push_back(listener); int port = ::atoi(conf->args.at(i).c_str()); if ((ret = listener->listen(port)) != ERROR_SUCCESS) { srs_error("RTMP stream listen at port %d failed. ret=%d", port, ret); return ret; } } #ifdef SRS_HTTP_API if (_srs_config->get_http_api_enabled()) { SrsListener* listener = new SrsListener(this, SrsListenerHttpApi); listeners.push_back(listener); int port = _srs_config->get_http_api_listen(); if ((ret = listener->listen(port)) != ERROR_SUCCESS) { srs_error("HTTP api listen at port %d failed. ret=%d", port, ret); return ret; } } #endif #ifdef SRS_HTTP_SERVER if (_srs_config->get_http_stream_enabled()) { SrsListener* listener = new SrsListener(this, SrsListenerHttpStream); listeners.push_back(listener); int port = _srs_config->get_http_stream_listen(); if ((ret = listener->listen(port)) != ERROR_SUCCESS) { srs_error("HTTP stream listen at port %d failed. ret=%d", port, ret); return ret; } } #endif return ret; }
int SrsServer::listen_http_stream() { int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HTTP_SERVER close_listeners(SrsListenerHttpStream); if (_srs_config->get_http_stream_enabled()) { SrsListener* listener = new SrsListener(this, SrsListenerHttpStream); listeners.push_back(listener); int port = _srs_config->get_http_stream_listen(); if ((ret = listener->listen(port)) != ERROR_SUCCESS) { srs_error("HTTP stream listen at port %d failed. ret=%d", port, ret); return ret; } } #endif return ret; }
int SrsServer::listen_rtmp() { int ret = ERROR_SUCCESS; // stream service port. SrsConfDirective* conf = _srs_config->get_listen(); srs_assert(conf); close_listeners(SrsListenerRtmpStream); for (int i = 0; i < (int)conf->args.size(); i++) { SrsListener* listener = new SrsListener(this, SrsListenerRtmpStream); listeners.push_back(listener); int port = ::atoi(conf->args.at(i).c_str()); if ((ret = listener->listen(port)) != ERROR_SUCCESS) { srs_error("RTMP stream listen at port %d failed. ret=%d", port, ret); return ret; } } return ret; }
int SrsServer::listen_rtmp() { int ret = ERROR_SUCCESS; // stream service port. std::vector<std::string> ports = _srs_config->get_listen(); srs_assert((int)ports.size() > 0); close_listeners(SrsListenerRtmpStream); for (int i = 0; i < (int)ports.size(); i++) { SrsListener* listener = new SrsListener(this, SrsListenerRtmpStream); listeners.push_back(listener); int port = ::atoi(ports[i].c_str()); if ((ret = listener->listen(port)) != ERROR_SUCCESS) { srs_error("RTMP stream listen at port %d failed. ret=%d", port, ret); return ret; } } return ret; }
static void * slapd_daemon_task( void *ptr ) { int l; time_t last_idle_check = 0; struct timeval idle; time( &starttime ); #define SLAPD_IDLE_CHECK_LIMIT 4 if ( global_idletimeout > 0 ) { last_idle_check = slap_get_time(); /* Set the select timeout. * Don't just truncate, preserve the fractions of * seconds to prevent sleeping for zero time. */ idle.tv_sec = global_idletimeout/SLAPD_IDLE_CHECK_LIMIT; idle.tv_usec = global_idletimeout - idle.tv_sec * SLAPD_IDLE_CHECK_LIMIT; idle.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT; } else { idle.tv_sec = 0; idle.tv_usec = 0; } for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; #ifdef LDAP_CONNECTIONLESS /* Since this is connectionless, the data port is the * listening port. The listen() and accept() calls * are unnecessary. */ if ( slap_listeners[l]->sl_is_udp ) { slapd_add( slap_listeners[l]->sl_sd ); continue; } #endif if ( listen( slap_listeners[l]->sl_sd, SLAPD_LISTEN ) == -1 ) { int err = sock_errno(); #ifdef LDAP_PF_INET6 /* If error is EADDRINUSE, we are trying to listen to INADDR_ANY and * we are already listening to in6addr_any, then we want to ignore * this and continue. */ if ( err == EADDRINUSE ) { int i; struct sockaddr_in sa = slap_listeners[l]->sl_sa.sa_in_addr; struct sockaddr_in6 sa6; if ( sa.sin_family == AF_INET && sa.sin_addr.s_addr == htonl(INADDR_ANY) ) { for ( i = 0 ; i < l; i++ ) { sa6 = slap_listeners[i]->sl_sa.sa_in6_addr; if ( sa6.sin6_family == AF_INET6 && !memcmp( &sa6.sin6_addr, &in6addr_any, sizeof(struct in6_addr) ) ) break; } if ( i < l ) { /* We are already listening to in6addr_any */ #ifdef NEW_LOGGING LDAP_LOG(CONNECTION, WARNING, "slapd_daemon_task: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n", 0, 0, 0 ); #endif slapd_close( slap_listeners[l]->sl_sd ); slap_listeners[l]->sl_sd = AC_SOCKET_INVALID; continue; } } } #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: listen( %s, 5 ) failed errno=%d (%s)\n", slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "daemon: listen(%s, 5) failed errno=%d (%s)\n", slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); #endif return( (void*)-1 ); } slapd_add( slap_listeners[l]->sl_sd ); } #ifdef HAVE_NT_SERVICE_MANAGER if ( started_event != NULL ) { ldap_pvt_thread_cond_signal( &started_event ); } #endif /* initialization complete. Here comes the loop. */ while ( !slapd_shutdown ) { ber_socket_t i; int ns; int at; ber_socket_t nfds; #define SLAPD_EBADF_LIMIT 16 int ebadf = 0; time_t now; fd_set readfds; fd_set writefds; Sockaddr from; struct timeval tv; struct timeval *tvp; now = slap_get_time(); if( ( global_idletimeout > 0 ) && difftime( last_idle_check + global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) { connections_timeout_idle( now ); last_idle_check = now; } tv = idle; #ifdef SIGHUP if( slapd_gentle_shutdown ) { ber_socket_t active; if( slapd_gentle_shutdown == 1 ) { Debug( LDAP_DEBUG_ANY, "slapd gentle shutdown\n", 0, 0, 0 ); close_listeners( 1 ); global_restrictops |= SLAP_RESTRICT_OP_WRITES; slapd_gentle_shutdown = 2; } ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); active = slap_daemon.sd_nactives; ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); if( active == 0 ) { slapd_shutdown = 2; break; } } #endif FD_ZERO( &writefds ); FD_ZERO( &readfds ); at = 0; ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); #ifdef FD_SET_MANUAL_COPY for( s = 0; s < nfds; s++ ) { if(FD_ISSET( &slap_sd_readers, s )) { FD_SET( s, &readfds ); } if(FD_ISSET( &slap_sd_writers, s )) { FD_SET( s, &writefds ); } } #else AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) ); AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) ); #endif assert(!FD_ISSET(wake_sds[0], &readfds)); FD_SET( wake_sds[0], &readfds ); for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; if ( slap_listeners[l]->sl_is_mute ) FD_CLR( slap_listeners[l]->sl_sd, &readfds ); else if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds)) FD_SET( slap_listeners[l]->sl_sd, &readfds ); } #ifndef HAVE_WINSOCK nfds = slap_daemon.sd_nfds; #else nfds = dtblsize; #endif if ( global_idletimeout && slap_daemon.sd_nactives ) at = 1; ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); if ( !at ) at = ldap_pvt_thread_pool_backload(&connection_pool); #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS ) tvp = NULL; #else tvp = at ? &tv : NULL; #endif for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID || slap_listeners[l]->sl_is_mute ) continue; #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL1, "slapd_daemon_task: select: listen=%d " "active_threads=%d tvp=%s\n", slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "idle" ); #else Debug( LDAP_DEBUG_CONNS, "daemon: select: listen=%d active_threads=%d tvp=%s\n", slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "idle" ); #endif } switch(ns = select( nfds, &readfds, #ifdef HAVE_WINSOCK /* don't pass empty fd_set */ ( writefds.fd_count > 0 ? &writefds : NULL ), #else &writefds, #endif NULL, tvp )) { case -1: { /* failure - try again */ int err = sock_errno(); if( err == EBADF #ifdef WSAENOTSOCK /* you'd think this would be EBADF */ || err == WSAENOTSOCK #endif ) { if (++ebadf < SLAPD_EBADF_LIMIT) continue; } if( err != EINTR ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slapd_daemon_task: select failed (%d): %s\n", err, sock_errstr(err), 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: select failed (%d): %s\n", err, sock_errstr(err), 0 ); #endif slapd_shutdown = 2; } } continue; case 0: /* timeout - let threads run */ ebadf = 0; #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: select timeout - yielding\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n", 0, 0, 0 ); #endif ldap_pvt_thread_yield(); continue; default: /* something happened - deal with it */ if( slapd_shutdown ) continue; ebadf = 0; #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: activity on %d descriptors\n", ns, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n", ns, 0, 0 ); #endif /* FALL THRU */ } if( FD_ISSET( wake_sds[0], &readfds ) ) { char c[BUFSIZ]; tcp_read( wake_sds[0], c, sizeof(c) ); #if defined(NO_THREADS) || defined(HAVE_GNU_PTH) waking = 0; #endif continue; } for ( l = 0; slap_listeners[l] != NULL; l++ ) { ber_socket_t s; socklen_t len = sizeof(from); long id; slap_ssf_t ssf = 0; char *authid = NULL; #ifdef SLAPD_RLOOKUPS char hbuf[NI_MAXHOST]; #endif char *dnsname = NULL; char *peeraddr = NULL; #ifdef LDAP_PF_LOCAL char peername[MAXPATHLEN + sizeof("PATH=")]; #elif defined(LDAP_PF_INET6) char peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")]; #else char peername[sizeof("IP=255.255.255.255:65336")]; #endif /* LDAP_PF_LOCAL */ peername[0] = '\0'; if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) ) continue; #ifdef LDAP_CONNECTIONLESS if ( slap_listeners[l]->sl_is_udp ) { /* The first time we receive a query, we set this * up as a "connection". It remains open for the life * of the slapd. */ if ( slap_listeners[l]->sl_is_udp < 2 ) { id = connection_init( slap_listeners[l]->sl_sd, slap_listeners[l], "", "", 2, ssf, authid ); slap_listeners[l]->sl_is_udp++; } continue; } #endif /* Don't need to look at this in the data loops */ FD_CLR( slap_listeners[l]->sl_sd, &readfds ); FD_CLR( slap_listeners[l]->sl_sd, &writefds ); s = accept( slap_listeners[l]->sl_sd, (struct sockaddr *) &from, &len ); if ( s == AC_SOCKET_INVALID ) { int err = sock_errno(); if( #ifdef EMFILE err == EMFILE || #endif #ifdef ENFILE err == ENFILE || #endif 0 ) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); emfile++; /* Stop listening until an existing session closes */ slap_listeners[l]->sl_is_mute = 1; ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); } #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: accept(%ld) failed errno=%d (%s)\n", (long)slap_listeners[l]->sl_sd, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "daemon: accept(%ld) failed errno=%d (%s)\n", (long) slap_listeners[l]->sl_sd, err, sock_errstr(err) ); #endif ldap_pvt_thread_yield(); continue; } #ifndef HAVE_WINSOCK /* make sure descriptor number isn't too great */ if ( s >= dtblsize ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: %ld beyond descriptor table size %ld\n", (long)s, (long)dtblsize, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: %ld beyond descriptor table size %ld\n", (long) s, (long) dtblsize, 0 ); #endif slapd_close(s); ldap_pvt_thread_yield(); continue; } #endif #ifdef LDAP_DEBUG ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); /* newly accepted stream should not be in any of the FD SETS */ assert( !FD_ISSET( s, &slap_daemon.sd_actives) ); assert( !FD_ISSET( s, &slap_daemon.sd_readers) ); assert( !FD_ISSET( s, &slap_daemon.sd_writers) ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); #endif #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) #ifdef LDAP_PF_LOCAL /* for IPv4 and IPv6 sockets only */ if ( from.sa_addr.sa_family != AF_LOCAL ) #endif /* LDAP_PF_LOCAL */ { int rc; int tmp; #ifdef SO_KEEPALIVE /* enable keep alives */ tmp = 1; rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: setsockopt( %ld, SO_KEEPALIVE)" " failed errno=%d (%s)\n", (long)s, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "slapd(%ld): setsockopt(SO_KEEPALIVE) failed " "errno=%d (%s)\n", (long) s, err, sock_errstr(err) ); #endif } #endif #ifdef TCP_NODELAY /* enable no delay */ tmp = 1; rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: setsockopt( %ld, " "TCP_NODELAY) failed errno=%d (%s)\n", (long)s, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "slapd(%ld): setsockopt(TCP_NODELAY) failed " "errno=%d (%s)\n", (long) s, err, sock_errstr(err) ); #endif } #endif } #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL1, "slapd_daemon_task: new connection on %ld\n", (long)s, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n", (long) s, 0, 0 ); #endif switch ( from.sa_addr.sa_family ) { # ifdef LDAP_PF_LOCAL case AF_LOCAL: sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path ); ssf = LDAP_PVT_SASL_LOCAL_SSF; { uid_t uid; gid_t gid; if( getpeereid( s, &uid, &gid ) == 0 ) { authid = ch_malloc( sizeof("uidnumber=4294967295+gidnumber=4294967295," "cn=peercred,cn=external,cn=auth")); sprintf(authid, "uidnumber=%d+gidnumber=%d," "cn=peercred,cn=external,cn=auth", (int) uid, (int) gid); } } dnsname = "local"; break; #endif /* LDAP_PF_LOCAL */ # ifdef LDAP_PF_INET6 case AF_INET6: if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) { peeraddr = inet_ntoa( *((struct in_addr *) &from.sa_in6_addr.sin6_addr.s6_addr[12]) ); sprintf( peername, "IP=%s:%d", peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); } else { char addr[INET6_ADDRSTRLEN]; peeraddr = (char *) inet_ntop( AF_INET6, &from.sa_in6_addr.sin6_addr, addr, sizeof addr ); sprintf( peername, "IP=%s %d", peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); } break; # endif /* LDAP_PF_INET6 */ case AF_INET: peeraddr = inet_ntoa( from.sa_in_addr.sin_addr ); sprintf( peername, "IP=%s:%d", peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in_addr.sin_port ) ); break; default: slapd_close(s); continue; } if ( ( from.sa_addr.sa_family == AF_INET ) #ifdef LDAP_PF_INET6 || ( from.sa_addr.sa_family == AF_INET6 ) #endif ) { #ifdef SLAPD_RLOOKUPS if ( use_reverse_lookup ) { char *herr; if (ldap_pvt_get_hname( (const struct sockaddr *)&from, len, hbuf, sizeof(hbuf), &herr ) == 0) { ldap_pvt_str2lower( hbuf ); dnsname = hbuf; } } #else dnsname = NULL; #endif /* SLAPD_RLOOKUPS */ #ifdef HAVE_TCPD if ( !hosts_ctl("slapd", dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, SLAP_STRING_UNKNOWN )) { /* DENY ACCESS */ Statslog( LDAP_DEBUG_STATS, "fd=%ld DENIED from %s (%s)\n", (long) s, dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, 0, 0 ); slapd_close(s); continue; } #endif /* HAVE_TCPD */ } id = connection_init(s, slap_listeners[l], dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, peername, #ifdef HAVE_TLS slap_listeners[l]->sl_is_tls, #else 0, #endif ssf, authid ); if( authid ) ch_free(authid); if( id < 0 ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slapd_daemon_task: " "connection_init(%ld, %s, %s) " "failed.\n", (long)s, peername, slap_listeners[l]->sl_name.bv_val ); #else Debug( LDAP_DEBUG_ANY, "daemon: connection_init(%ld, %s, %s) " "failed.\n", (long) s, peername, slap_listeners[l]->sl_name.bv_val ); #endif slapd_close(s); continue; } Statslog( LDAP_DEBUG_STATS, "conn=%ld fd=%ld ACCEPT from %s (%s)\n", id, (long) s, peername, slap_listeners[l]->sl_name.bv_val, 0 ); slapd_add( s ); continue; } #ifdef LDAP_DEBUG #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: activity on ", 0, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 ); #endif #ifdef HAVE_WINSOCK for ( i = 0; i < readfds.fd_count; i++ ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, " %d%s", readfds.fd_array[i], "r", 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, " %d%s", readfds.fd_array[i], "r", 0 ); #endif } for ( i = 0; i < writefds.fd_count; i++ ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, " %d%s", writefds.fd_array[i], "w" , 0 ); #else Debug( LDAP_DEBUG_CONNS, " %d%s", writefds.fd_array[i], "w", 0 ); #endif } #else for ( i = 0; i < nfds; i++ ) { int r, w; r = FD_ISSET( i, &readfds ); w = FD_ISSET( i, &writefds ); if ( r || w ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, " %d%s%s", i, r ? "r" : "", w ? "w" : "" ); #else Debug( LDAP_DEBUG_CONNS, " %d%s%s", i, r ? "r" : "", w ? "w" : "" ); #endif } } #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 ); #endif #endif /* loop through the writers */ #ifdef HAVE_WINSOCK for ( i = 0; i < writefds.fd_count; i++ ) #else for ( i = 0; i < nfds; i++ ) #endif { ber_socket_t wd; #ifdef HAVE_WINSOCK wd = writefds.fd_array[i]; #else if( ! FD_ISSET( i, &writefds ) ) { continue; } wd = i; #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: write active on %d\n", wd, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: write active on %d\n", wd, 0, 0 ); #endif /* * NOTE: it is possible that the connection was closed * and that the stream is now inactive. * connection_write() must valid the stream is still * active. */ if ( connection_write( wd ) < 0 ) { FD_CLR( (unsigned) wd, &readfds ); slapd_close( wd ); } } #ifdef HAVE_WINSOCK for ( i = 0; i < readfds.fd_count; i++ ) #else for ( i = 0; i < nfds; i++ ) #endif { ber_socket_t rd; #ifdef HAVE_WINSOCK rd = readfds.fd_array[i]; #else if( ! FD_ISSET( i, &readfds ) ) { continue; } rd = i; #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: read activity on %d\n", rd, 0, 0 ); #else Debug ( LDAP_DEBUG_CONNS, "daemon: read activity on %d\n", rd, 0, 0 ); #endif /* * NOTE: it is possible that the connection was closed * and that the stream is now inactive. * connection_read() must valid the stream is still * active. */ if ( connection_read( rd ) < 0 ) { slapd_close( rd ); } } ldap_pvt_thread_yield(); } if( slapd_shutdown == 1 ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: shutdown requested and initiated.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "daemon: shutdown requested and initiated.\n", 0, 0, 0 ); #endif } else if ( slapd_shutdown == 2 ) { #ifdef HAVE_NT_SERVICE_MANAGER #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: shutdown initiated by Service Manager.\n", 0, 0, 0); #else Debug( LDAP_DEBUG_TRACE, "daemon: shutdown initiated by Service Manager.\n", 0, 0, 0); #endif #else /* !HAVE_NT_SERVICE_MANAGER */ #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: abnormal condition, " "shutdown initiated.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "daemon: abnormal condition, shutdown initiated.\n", 0, 0, 0 ); #endif #endif /* !HAVE_NT_SERVICE_MANAGER */ } else { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: no active streams, shutdown initiated.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "daemon: no active streams, shutdown initiated.\n", 0, 0, 0 ); #endif } if( slapd_gentle_shutdown != 2 ) { close_listeners ( 0 ); } free ( slap_listeners ); slap_listeners = NULL; if( !slapd_gentle_shutdown ) { connections_shutdown(); } #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: shutdown waiting for %d threads to terminate.\n", ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "slapd shutdown: waiting for %d threads to terminate\n", ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 ); #endif ldap_pvt_thread_pool_destroy(&connection_pool, 1); return NULL; }
void accept_thread(void *asdf) { sigset_t sigs_to_block; int e, n; struct pollfd *acceptpfd = NULL; struct listen_t **acceptpl = NULL; int listen_n = 0; int poll_n = 0; struct listen_t *l; pthreads_profiling_reset("accept"); sigemptyset(&sigs_to_block); sigaddset(&sigs_to_block, SIGALRM); sigaddset(&sigs_to_block, SIGINT); sigaddset(&sigs_to_block, SIGTERM); sigaddset(&sigs_to_block, SIGQUIT); sigaddset(&sigs_to_block, SIGHUP); sigaddset(&sigs_to_block, SIGURG); sigaddset(&sigs_to_block, SIGPIPE); sigaddset(&sigs_to_block, SIGUSR1); sigaddset(&sigs_to_block, SIGUSR2); pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL); /* start the accept thread, which will start server threads */ hlog(LOG_INFO, "Accept thread starting..."); /* we allocate a worker structure to be used within the accept thread * for parsing incoming UDP packets and passing them on to the dupecheck * thread. */ udp_worker = worker_alloc(); udp_worker->id = 81; /* we also need a client structure to be used with incoming * HTTP position uploads */ udp_pseudoclient = pseudoclient_setup(81); udp_pseudoclient->flags |= CLFLAGS_UDPSUBMIT; accept_reconfiguring = 1; while (!accept_shutting_down) { if (accept_reconfiguring) { accept_reconfiguring = 0; listen_n -= close_removed_listeners(); /* start listening on the sockets */ listen_n += open_missing_listeners(); if (listen_n < 1) { hlog(LOG_CRIT, "Failed to listen on any ports."); exit(2); } /* reconfiguration must scan old clients against ACL */ rescan_client_acls(); /* how many are we polling */ poll_n = 0; for (l = listen_list; (l); l = l->next) if (!l->corepeer) poll_n++; hlog(LOG_DEBUG, "Generating polling list for %d/%d listeners...", poll_n, listen_n); /* array of FDs for poll() */ if (acceptpfd) hfree(acceptpfd); acceptpfd = hmalloc(poll_n * sizeof(*acceptpfd)); /* array of listeners */ if (acceptpl) hfree(acceptpl); acceptpl = hmalloc(poll_n * sizeof(*acceptpl)); n = 0; for (l = listen_list; (l); l = l->next) { /* The accept thread does not poll() UDP sockets for core peers. * Worker 0 takes care of that, and processes the incoming packets. */ if (l->corepeer) { hlog(LOG_DEBUG, "... %d: fd %d (%s) - not polled, is corepeer", n, (l->udp) ? l->udp->fd : l->fd, l->addr_s); continue; } int fd; if (l->udp) { l->udp->polled = 1; fd = l->udp->fd; } else { fd = l->fd; } hlog(LOG_DEBUG, "... %d: fd %d (%s)", n, fd, l->addr_s); acceptpfd[n].fd = fd; acceptpfd[n].events = POLLIN|POLLPRI|POLLERR|POLLHUP; acceptpl[n] = l; n++; } hlog(LOG_INFO, "Accept thread ready."); /* stop the dupechecking and uplink threads while adjusting * the amount of workers... they walk the worker list, and * might get confused when workers are stopped or started. */ if (workers_running != workers_configured) { uplink_stop(); dupecheck_stop(); workers_start(); dupecheck_start(); uplink_start(); } /* * generate UDP peer clients */ peerip_clients_close(); if (peerip_config) peerip_clients_config(); /* accept liveupgrade clients */ if (liveupgrade_status) accept_liveupgrade_accept(); } /* check for new connections */ e = poll(acceptpfd, poll_n, 200); if (e == 0) continue; if (e < 0) { if (errno == EINTR) continue; hlog(LOG_ERR, "poll() on accept failed: %s (continuing)", strerror(errno)); continue; } /* now, which socket was that on? */ for (n = 0; n < poll_n; n++) { l = acceptpl[n]; if (!(l) || (l->udp ? l->udp->fd : l->fd) != acceptpfd[n].fd) { hlog(LOG_CRIT, "accept_thread: polling list and listener list do mot match!"); exit(1); } if (acceptpfd[n].revents) { if (l->udp) accept_udp_recv(l); /* receive UDP packets */ else do_accept(l); /* accept a single connection */ } } } if (accept_shutting_down == 2) worker_shutdown_clients = cJSON_CreateArray(); hlog(LOG_DEBUG, "Accept thread shutting down listening sockets and worker threads..."); uplink_stop(); close_listeners(); dupecheck_stop(); http_shutting_down = 1; workers_stop(accept_shutting_down); hfree(acceptpfd); hfree(acceptpl); acceptpfd = NULL; acceptpl = NULL; /* free up the pseudo-client */ client_free(udp_pseudoclient); udp_pseudoclient = NULL; /* free up the pseudo-worker structure, after dupecheck is long dead */ worker_free_buffers(udp_worker); hfree(udp_worker); udp_worker = NULL; }
/** Reload the configuration file. * @param cptr Client that requested rehash (if a signal, &me). * @param sig Type of rehash (0 = oper-requested, 1 = signal, 2 = * oper-requested but do not restart resolver) * @return CPTR_KILLED if any client was K/G-lined because of the * rehash; otherwise 0. */ int rehash(struct Client *cptr, int sig) { struct ConfItem** tmp = &GlobalConfList; struct ConfItem* tmp2; struct Client* acptr; int i; int ret = 0; int found_g = 0; if (1 == sig) sendto_opmask_butone(0, SNO_OLDSNO, "Got signal SIGHUP, reloading ircd conf. file"); while ((tmp2 = *tmp)) { if (tmp2->clients) { /* * Configuration entry is still in use by some * local clients, cannot delete it--mark it so * that it will be deleted when the last client * exits... */ if (CONF_CLIENT == (tmp2->status & CONF_CLIENT)) tmp = &tmp2->next; else { *tmp = tmp2->next; tmp2->next = 0; } tmp2->status |= CONF_ILLEGAL; } else { *tmp = tmp2->next; free_conf(tmp2); } } conf_erase_crule_list(); conf_erase_deny_list(); conf_erase_webirc_list(); conf_erase_shost_list(); conf_erase_except_list(); motd_clear(); /* * delete the juped nicks list */ clearNickJupes(); clear_quarantines(); class_mark_delete(); mark_listeners_closing(); auth_mark_closing(); close_mappings(); read_configuration_file(); if (sig != 2) restart_resolver(); log_reopen(); /* reopen log files */ auth_close_unused(); close_listeners(); class_delete_marked(); /* unless it fails */ /* * Flush out deleted I and P lines although still in use. */ for (tmp = &GlobalConfList; (tmp2 = *tmp);) { if (CONF_ILLEGAL == (tmp2->status & CONF_ILLEGAL)) { *tmp = tmp2->next; tmp2->next = NULL; if (!tmp2->clients) free_conf(tmp2); } else tmp = &tmp2->next; } for (i = 0; i <= HighestFd; i++) { if ((acptr = LocalClientArray[i])) { assert(!IsMe(acptr)); if (IsServer(acptr)) det_confs_butmask(acptr, ~(CONF_UWORLD | CONF_ILLEGAL)); /* Because admin's are getting so uppity about people managing to * get past K/G's etc, we'll "fix" the bug by actually explaining * whats going on. */ if ((found_g = find_kill(acptr))) { sendto_opmask_butone(0, found_g > -1 ? SNO_GLINE : SNO_OPERKILL, found_g == -2 ? "G-line active for %s%s" : (found_g == -3 ? "Z-line active for %s%s" : "K-line active for %s%s"), IsUnknown(acptr) ? "Unregistered Client ":"", get_client_name(acptr, SHOW_IP)); if (exit_client(cptr, acptr, &me, found_g == -2 ? "G-lined" : (found_g == -3 ? "Z-lined" : "K-lined")) == CPTR_KILLED) ret = CPTR_KILLED; } } } attach_conf_uworld(&me); geoip_init(); auth_send_event("rehash", NULL); return ret; }