Exemple #1
0
int ooh323c_start_stack_thread()
{
   if(ast_pthread_create_background(&ooh323c_thread, NULL, ooh323c_stack_thread, NULL) < 0)
   {
      ast_log(LOG_ERROR, "Unable to start ooh323c thread.\n");
      return -1;
   }
   if(ast_pthread_create_background(&ooh323cmd_thread, NULL, ooh323c_cmd_thread, NULL) < 0)
   {
      ast_log(LOG_ERROR, "Unable to start ooh323cmd thread.\n");
      return -1;
   }
   return 0;
}
/*!
 * The first call to the video code, called by oss_new() or similar.
 * Here we initialize the various components we use, namely SDL for display,
 * ffmpeg for encoding/decoding, and a local video source.
 * We do our best to progress even if some of the components are not
 * available.
 */
void console_video_start(struct video_desc *env, struct ast_channel *owner)
{
	ast_log(LOG_WARNING, "env %p chan %p\n", env, owner);
	if (env == NULL)	/* video not initialized */
		return;
	env->owner = owner;	/* work even if no owner is specified */
	if (env->stayopen)
		return;		/* already initialized, nothing to do */
	init_env(env);
	env->out.enc = map_config_video_format(env->codec_name);

	ast_log(LOG_WARNING, "start video out %s %dx%d\n",
		env->codec_name, env->enc_in.w,  env->enc_in.h);
	/*
	 * Register all codecs supported by the ffmpeg library.
	 * We only need to do it once, but probably doesn't
	 * harm to do it multiple times.
	 */
	avcodec_init();
	avcodec_register_all();
	av_log_set_level(AV_LOG_ERROR);	/* only report errors */

	if (env->out.fps == 0) {
		env->out.fps = 15;
		ast_log(LOG_WARNING, "fps unset, forcing to %d\n", env->out.fps);
	}
	if (env->out.bitrate == 0) {
		env->out.bitrate = 65000;
		ast_log(LOG_WARNING, "bitrate unset, forcing to %d\n", env->out.bitrate);
	}
	ast_pthread_create_background(&env->vthread, NULL, video_thread, env);
	if (env->owner == NULL)
		env->stayopen = 1;	/* manually opened so don't close on hangup */
}
Exemple #3
0
static int start_monitor(void)
{
	/* If we're supposed to be stopped -- stay stopped */
	if (monitor_thread == AST_PTHREADT_STOP)
		return 0;
	ast_mutex_lock(&monlock);
	if (monitor_thread == pthread_self()) {
		ast_mutex_unlock(&monlock);
		ast_log(LOG_WARNING, "Cannot kill myself cdr monitor\n");
		return -1;
	}
	if (monitor_thread != AST_PTHREADT_NULL) {
		/* Wake up the thread */
		pthread_kill(monitor_thread, SIGURG);
	} else {
		/* Start a new monitor */
		if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
			ast_mutex_unlock(&monlock);
			ast_log(LOG_ERROR, "Unable to start cdr monitor thread.\n");
			return -1;
		}
	}
	ast_mutex_unlock(&monlock);

	return 0;
}
static void http_server_start(struct sockaddr_in *sin)
{
	int flags;
	int x = 1;
	
	/* Do nothing if nothing has changed */
	if (!memcmp(&oldsin, sin, sizeof(oldsin))) {
		ast_log(LOG_DEBUG, "Nothing changed in http\n");
		return;
	}
	
	memcpy(&oldsin, sin, sizeof(oldsin));
	
	/* Shutdown a running server if there is one */
	if (master != AST_PTHREADT_NULL) {
		pthread_cancel(master);
		pthread_kill(master, SIGURG);
		pthread_join(master, NULL);
	}
	
	if (httpfd != -1)
		close(httpfd);

	/* If there's no new server, stop here */
	if (!sin->sin_family)
		return;
	
	
	httpfd = socket(AF_INET, SOCK_STREAM, 0);
	if (httpfd < 0) {
		ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
		return;
	}
	
	setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
	if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) {
		ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n",
			ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
			strerror(errno));
		close(httpfd);
		httpfd = -1;
		return;
	}
	if (listen(httpfd, 10)) {
		ast_log(LOG_NOTICE, "Unable to listen!\n");
		close(httpfd);
		httpfd = -1;
		return;
	}
	flags = fcntl(httpfd, F_GETFL);
	fcntl(httpfd, F_SETFL, flags | O_NONBLOCK);
	if (ast_pthread_create_background(&master, NULL, http_root, NULL)) {
		ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n",
				ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
				strerror(errno));
		close(httpfd);
		httpfd = -1;
	}
}
static void *http_root(void *data)
{
	int fd;
	struct sockaddr_in sin;
	socklen_t sinlen;
	struct ast_http_server_instance *ser;
	pthread_t launched;
	pthread_attr_t attr;
	
	for (;;) {
		int flags;

		ast_wait_for_input(httpfd, -1);
		sinlen = sizeof(sin);
		fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen);

		if (fd < 0) {
			if ((errno != EAGAIN) && (errno != EINTR))
				ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
			continue;
		}

		if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
			close(fd);
			continue;
		}

		ser = ast_calloc(1, sizeof(*ser));
		if (!ser) {
			ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
			close(fd);
			ast_atomic_fetchadd_int(&session_count, -1);
			continue;
		}
		flags = fcntl(fd, F_GETFL);
		fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
		ser->fd = fd;
		memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
		if ((ser->f = fdopen(ser->fd, "w+"))) {
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
			
			if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) {
				ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
				fclose(ser->f);
				free(ser);
				ast_atomic_fetchadd_int(&session_count, -1);
			}
			pthread_attr_destroy(&attr);
		} else {
			ast_log(LOG_WARNING, "fdopen failed!\n");
			close(ser->fd);
			free(ser);
			ast_atomic_fetchadd_int(&session_count, -1);
		}
	}
	return NULL;
}
Exemple #6
0
static int init_timing_thread(void)
{
	ast_mutex_init(&timing_thread.lock);
	ast_cond_init(&timing_thread.cond, NULL);

	if (ast_pthread_create_background(&timing_thread.thread, NULL, do_timing, NULL)) {
		ast_log(LOG_ERROR, "Unable to start timing thread.\n");
		return -1;
	}

	return 0;
}
/*!
 * \brief Load the module
 *
 * Module loading including tests for configuration or dependencies.
 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
 * configuration file or other non-critical problem return
 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
 */
static int load_module(void)
{
    if(!load_config())
        return AST_MODULE_LOAD_DECLINE;

    ast_verb(1, "Loading [Sub]Agent Module\n");

    res_snmp_dont_stop = 1;
    if (res_snmp_enabled)
        return ast_pthread_create_background(&thread, NULL, agent_thread, NULL);
    else
        return 0;
}
Exemple #8
0
int astdb_init(void)
{
	if (db_init()) {
		return -1;
	}

	ast_cond_init(&dbcond, NULL);
	if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
		return -1;
	}

	ast_register_atexit(astdb_atexit);
	ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
	ast_manager_register_xml_core("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
	ast_manager_register_xml_core("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
	ast_manager_register_xml_core("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
	ast_manager_register_xml_core("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);
	return 0;
}
Exemple #9
0
static int load_module(void)
{
	pthread_t thread;
	pthread_attr_t attr;
	int ret;
	snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing");
	if (mkdir(qdir, 0700) && (errno != EEXIST)) {
		ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir);
		return 0;
	}
	snprintf(qdonedir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing_done");
	pthread_attr_init(&attr);
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	if ((ret = ast_pthread_create_background(&thread,&attr,scan_thread, NULL)) != 0) {
		ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
		return -1;
	}
	pthread_attr_destroy(&attr);
	return 0;
}
Exemple #10
0
int astdb_init(void)
{
	ast_cond_init(&dbcond, NULL);
	if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
		return -1;
	}

	ast_mutex_lock(&dblock);
	/* Ignore check_return warning from Coverity for dbinit below */
	dbinit();
	ast_mutex_unlock(&dblock);

	ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
	ast_manager_register_xml("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
	ast_manager_register_xml("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
	ast_manager_register_xml("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
	ast_manager_register_xml("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);

	ast_register_atexit(astdb_shutdown);
	return 0;
}
Exemple #11
0
void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
{
	int flags;
	int x = 1;

	/* Do nothing if nothing has changed */
	if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
		ast_debug(1, "Nothing changed in %s\n", desc->name);
		return;
	}

	/* If we return early, there is no one listening */
	ast_sockaddr_setnull(&desc->old_address);

	/* Shutdown a running server if there is one */
	if (desc->master != AST_PTHREADT_NULL) {
		pthread_cancel(desc->master);
		pthread_kill(desc->master, SIGURG);
		pthread_join(desc->master, NULL);
	}

	if (desc->accept_fd != -1) {
		close(desc->accept_fd);
	}

	/* If there's no new server, stop here */
	if (ast_sockaddr_isnull(&desc->local_address)) {
		ast_debug(2, "Server disabled:  %s\n", desc->name);
		return;
	}

	desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ?
				 AF_INET6 : AF_INET, SOCK_STREAM, 0);
	if (desc->accept_fd < 0) {
		ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
		return;
	}

	setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
	if (ast_bind(desc->accept_fd, &desc->local_address)) {
		ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
			desc->name,
			ast_sockaddr_stringify(&desc->local_address),
			strerror(errno));
		goto error;
	}
	if (listen(desc->accept_fd, 10)) {
		ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
		goto error;
	}
	flags = fcntl(desc->accept_fd, F_GETFL);
	fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
	if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
		ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
			desc->name,
			ast_sockaddr_stringify(&desc->local_address),
			strerror(errno));
		goto error;
	}

	/* Set current info */
	ast_sockaddr_copy(&desc->old_address, &desc->local_address);

	return;

error:
	close(desc->accept_fd);
	desc->accept_fd = -1;
}
Exemple #12
0
void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
{
	int flags;
	int x = 1;
	
	/* Do nothing if nothing has changed */
	if (!memcmp(&desc->old_address, &desc->local_address, sizeof(desc->old_address))) {
		ast_debug(1, "Nothing changed in %s\n", desc->name);
		return;
	}
	
	desc->old_address = desc->local_address;
	
	/* Shutdown a running server if there is one */
	if (desc->master != AST_PTHREADT_NULL) {
		pthread_cancel(desc->master);
		pthread_kill(desc->master, SIGURG);
		pthread_join(desc->master, NULL);
	}
	
	if (desc->accept_fd != -1)
		close(desc->accept_fd);

	/* If there's no new server, stop here */
	if (desc->local_address.sin_family == 0) {
		ast_debug(2, "Server disabled:  %s\n", desc->name);
		return;
	}

	desc->accept_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (desc->accept_fd < 0) {
		ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
		return;
	}
	
	setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
	if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) {
		ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n",
			desc->name,
			ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port),
			strerror(errno));
		goto error;
	}
	if (listen(desc->accept_fd, 10)) {
		ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
		goto error;
	}
	flags = fcntl(desc->accept_fd, F_GETFL);
	fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
	if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
		ast_log(LOG_ERROR, "Unable to launch thread for %s on %s:%d: %s\n",
			desc->name,
			ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port),
			strerror(errno));
		goto error;
	}
	return;

error:
	close(desc->accept_fd);
	desc->accept_fd = -1;
}
Exemple #13
0
static void launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags,
				  int readvol, int writevol, const char *post_process) 
{
	pthread_attr_t attr;
	pthread_t thread;
	struct mixmonitor *mixmonitor;
	char postprocess2[1024] = "";
	size_t len;

	len = sizeof(*mixmonitor) + strlen(chan->name) + strlen(filename) + 2;

	/* If a post process system command is given attach it to the structure */
	if (!ast_strlen_zero(post_process)) {
		char *p1, *p2;

		p1 = ast_strdupa(post_process);
		for (p2 = p1; *p2 ; p2++) {
			if (*p2 == '^' && *(p2+1) == '{') {
				*p2 = '$';
			}
		}

		pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1);
		if (!ast_strlen_zero(postprocess2))
			len += strlen(postprocess2) + 1;
	}

	/* Pre-allocate mixmonitor structure and spy */
	if (!(mixmonitor = calloc(1, len))) {
		return;
	}

	/* Copy over flags and channel name */
	mixmonitor->flags = flags;
	if (setup_mixmonitor_ds(mixmonitor, chan)) {
		return;
	}
	mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
	strcpy(mixmonitor->name, chan->name);
	if (!ast_strlen_zero(postprocess2)) {
		mixmonitor->post_process = mixmonitor->name + strlen(mixmonitor->name) + strlen(filename) + 2;
		strcpy(mixmonitor->post_process, postprocess2);
	}

	mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor) + strlen(chan->name) + 1;
	strcpy(mixmonitor->filename, filename);

	/* Setup the actual spy before creating our thread */
	if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) {
		free(mixmonitor);
		return;
	}
	
	ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
	
	if (readvol)
		mixmonitor->audiohook.options.read_volume = readvol;
	if (writevol)
		mixmonitor->audiohook.options.write_volume = writevol;

	if (startmon(chan, &mixmonitor->audiohook)) {
		ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
			mixmonitor_spy_type, chan->name);
		/* Since we couldn't add ourselves - bail out! */
		ast_audiohook_destroy(&mixmonitor->audiohook);
		free(mixmonitor);
		return;
	}

	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	ast_pthread_create_background(&thread, &attr, mixmonitor_thread, mixmonitor);
	pthread_attr_destroy(&attr);
}
Exemple #14
0
void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
{
    int flags;
    int x = 1;
    int tls_changed = 0;

    if (desc->tls_cfg) {
        char hash[41];
        char *str = NULL;
        struct stat st;

        /* Store the hashes of the TLS certificate etc. */
        if (stat(desc->tls_cfg->certfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->certfile))) {
            memset(hash, 0, 41);
        } else {
            ast_sha1_hash(hash, str);
        }
        ast_free(str);
        str = NULL;
        memcpy(desc->tls_cfg->certhash, hash, 41);
        if (stat(desc->tls_cfg->pvtfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->pvtfile))) {
            memset(hash, 0, 41);
        } else {
            ast_sha1_hash(hash, str);
        }
        ast_free(str);
        str = NULL;
        memcpy(desc->tls_cfg->pvthash, hash, 41);
        if (stat(desc->tls_cfg->cafile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->cafile))) {
            memset(hash, 0, 41);
        } else {
            ast_sha1_hash(hash, str);
        }
        ast_free(str);
        str = NULL;
        memcpy(desc->tls_cfg->cahash, hash, 41);

        /* Check whether TLS configuration has changed */
        if (!desc->old_tls_cfg) { /* No previous configuration */
            tls_changed = 1;
            desc->old_tls_cfg = ast_calloc(1, sizeof(*desc->old_tls_cfg));
        } else if (memcmp(desc->tls_cfg->certhash, desc->old_tls_cfg->certhash, 41)) {
            tls_changed = 1;
        } else if (memcmp(desc->tls_cfg->pvthash, desc->old_tls_cfg->pvthash, 41)) {
            tls_changed = 1;
        } else if (strcmp(desc->tls_cfg->cipher, desc->old_tls_cfg->cipher)) {
            tls_changed = 1;
        } else if (memcmp(desc->tls_cfg->cahash, desc->old_tls_cfg->cahash, 41)) {
            tls_changed = 1;
        } else if (strcmp(desc->tls_cfg->capath, desc->old_tls_cfg->capath)) {
            tls_changed = 1;
        } else if (memcmp(&desc->tls_cfg->flags, &desc->old_tls_cfg->flags, sizeof(desc->tls_cfg->flags))) {
            tls_changed = 1;
        }

        if (tls_changed) {
            ast_debug(1, "Changed parameters for %s found\n", desc->name);
        }
    }

    /* Do nothing if nothing has changed */
    if (!tls_changed && !ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
        ast_debug(1, "Nothing changed in %s\n", desc->name);
        return;
    }

    /* If we return early, there is no one listening */
    ast_sockaddr_setnull(&desc->old_address);

    /* Shutdown a running server if there is one */
    if (desc->master != AST_PTHREADT_NULL) {
        pthread_cancel(desc->master);
        pthread_kill(desc->master, SIGURG);
        pthread_join(desc->master, NULL);
    }

    if (desc->accept_fd != -1) {
        close(desc->accept_fd);
    }

    /* If there's no new server, stop here */
    if (ast_sockaddr_isnull(&desc->local_address)) {
        ast_debug(2, "Server disabled:  %s\n", desc->name);
        return;
    }

    desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ?
                             AF_INET6 : AF_INET, SOCK_STREAM, 0);
    if (desc->accept_fd < 0) {
        ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
        return;
    }

    setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
    if (ast_bind(desc->accept_fd, &desc->local_address)) {
        ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
                desc->name,
                ast_sockaddr_stringify(&desc->local_address),
                strerror(errno));
        goto error;
    }
    if (listen(desc->accept_fd, 10)) {
        ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
        goto error;
    }
    flags = fcntl(desc->accept_fd, F_GETFL);
    fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
    if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
        ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
                desc->name,
                ast_sockaddr_stringify(&desc->local_address),
                strerror(errno));
        goto error;
    }

    /* Set current info */
    ast_sockaddr_copy(&desc->old_address, &desc->local_address);
    if (desc->old_tls_cfg) {
        ast_free(desc->old_tls_cfg->certfile);
        ast_free(desc->old_tls_cfg->pvtfile);
        ast_free(desc->old_tls_cfg->cipher);
        ast_free(desc->old_tls_cfg->cafile);
        ast_free(desc->old_tls_cfg->capath);
        desc->old_tls_cfg->certfile = ast_strdup(desc->tls_cfg->certfile);
        desc->old_tls_cfg->pvtfile = ast_strdup(desc->tls_cfg->pvtfile);
        desc->old_tls_cfg->cipher = ast_strdup(desc->tls_cfg->cipher);
        desc->old_tls_cfg->cafile = ast_strdup(desc->tls_cfg->cafile);
        desc->old_tls_cfg->capath = ast_strdup(desc->tls_cfg->capath);
        memcpy(desc->old_tls_cfg->certhash, desc->tls_cfg->certhash, 41);
        memcpy(desc->old_tls_cfg->pvthash, desc->tls_cfg->pvthash, 41);
        memcpy(desc->old_tls_cfg->cahash, desc->tls_cfg->cahash, 41);
        memcpy(&desc->old_tls_cfg->flags, &desc->tls_cfg->flags, sizeof(desc->old_tls_cfg->flags));
    }

    return;

error:
    close(desc->accept_fd);
    desc->accept_fd = -1;
}