/*
 * Copyright (c) 2002-2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: qm_qss_ctx.c,v 1.33 2006/11/05 17:23:32 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/io.h"
#include "sm/rcb.h"
#include "sm/qmgr.h"
#include "sm/qmgr-int.h"
#include "sm/rcbcomm.h"
#include "qmgr.h"
#include "log.h"

/*
**  QSS_CTX_NEW -- Allocate a new QMGR - SMTPS context
**
**	Parameters:
**		qmgr_ctx -- QMGR context
**		pqss_ctx -- QMGR/SMTPS context (output)
**
**	Returns:
**		usual sm_error code
**
**	Last code review: 2003-10-17 15:51:17
*/

sm_ret_T
qss_ctx_new(qmgr_ctx_P qmgr_ctx, qss_ctx_P *pqss_ctx)
{
	qss_ctx_P qss_ctx;
	sm_ret_T ret;

	SM_IS_QMGR_CTX(qmgr_ctx);
	SM_REQUIRE(pqss_ctx != NULL);
	qss_ctx = (qss_ctx_P) sm_zalloc(sizeof(*qss_ctx));
	if (qss_ctx == NULL)
		return sm_error_temp(SM_EM_Q_Q2SS, ENOMEM);
	qss_ctx->qss_qmgr_ctx = qmgr_ctx;
	ret = sm_rcbcom_open(&qss_ctx->qss_com);
	if (sm_is_err(ret))
		goto error;
	qss_ctx->qss_status = QSS_ST_NONE;
	qss_ctx->qss_id = QSS_ID_NONE;
	qss_ctx->sm_magic = SM_QSS_CTX_MAGIC;
	*pqss_ctx = qss_ctx;
	return SM_SUCCESS;

  error:
	SM_FREE_SIZE(qss_ctx, sizeof(*qss_ctx));
	return ret;
}

/*
**  QSS_CTX_FREE -- Free a QMGR - SMTPS context
**
**	Parameters:
**		qss_ctx -- QMGR/SMTPS context
**
**	Returns:
**		usual sm_error code (always SM_SUCCESS)
**
**	Locking: qss_ctx must be under control of the caller.
**
**	Last code review: 2003-10-17 15:52:26, see below
*/

sm_ret_T
qss_ctx_free(qss_ctx_P qss_ctx)
{
	if (qss_ctx == NULL)
		return SM_SUCCESS;
	(void) sm_rcbcom_close(&qss_ctx->qss_com);
	qss_ctx->sm_magic = SM_MAGIC_NULL;
	sm_free_size(qss_ctx, sizeof(*qss_ctx));
	return SM_SUCCESS;
}

/*
**  IQDB_CLOSE_SS -- close all data for one smtps (callback for "walk" function)
**
**	Parameters:
**		key -- ignored
**		value -- value in IQDB
**		ctx -- qmgr context
**		walk_ctx -- qss_ctx
**		type -- type of entry
**
**	Returns:
**		none
**
**	Locking: none (up to caller)
**
**	Last code review:
**	Last code change:
*/

static void
iqdb_close_ss(const char *key, const void *value, void *ctx, void *walk_ctx, uint type)
{
	qss_ta_P qss_ta;
	qss_ctx_P qss_ctx;
	qss_sess_P qss_sess;
	qmgr_ctx_P qmgr_ctx;
	int ss_id2close, ss_id;

	qmgr_ctx = (qmgr_ctx_P) ctx;
	SM_IS_QMGR_CTX(qmgr_ctx);
	qss_ctx = (qss_ctx_P) walk_ctx;
	ss_id2close = qss_ctx->qss_id;

	switch (type)
	{
	  case IQDB_T_SESS:
		qss_sess = (qss_sess_P) value;
		SM_IS_QS_SE(qss_sess);
		ss_id = sm_getsmtpsid(qss_sess->qsses_id);
		if (ss_id != ss_id2close)
			break;

		(void) iqdb_session_rm(qmgr_ctx->qmgr_iqdb, qss_sess->qsses_id,
				SMTP_STID_SIZE, THR_NO_LOCK);
		(void) qss_sess_free(qss_sess);
		break;

	  case IQDB_T_TA:
		qss_ta = (qss_ta_P) value;
		SM_IS_QS_TA(qss_ta);
		ss_id = sm_getsmtpsid(qss_ta->qssta_id);
		if (ss_id != ss_id2close)
			break;
		if (QSS_TA_IS_FLAG(qss_ta, QSS_TA_FL_AQ))
		{
			/* already in AQ? */
			sm_log_write(qmgr_ctx->qmgr_lctx,
				QM_LCAT_CLEANUP, QM_LMOD_CLEANUP,
				SM_LOG_WARN, 7,
				"sev=WARN, func=iqdb_close_ss, qss_ta=%p, flags=%#x, ta_id=%s, status=in_AQ"
				, qss_ta, qss_ta->qssta_flags, qss_ta->qssta_id);
			break;
		}
		(void) qm_ss_dtaid(qss_ctx, qss_ta, QSS_IQDB_NOLOCK);
		break;
#if 0
	  case IQDB_T_RCPT:
		/* will be removed when qss_ta is removed */
#endif
	}
}

/*
**  QSS_CTX_CLOSE -- Close a QMGR - SMTPS context
**
**	Parameters:
**		qss_ctx -- QMGR/SMTPS context
**
**	Returns:
**		usual sm_error code (always SM_SUCCESS)
**
**	Locking: qss_ctx must be under control of the caller.
**
**	Last code review:
*/

sm_ret_T
qss_ctx_close(qss_ctx_P qss_ctx)
{
	qmgr_ctx_P qmgr_ctx;

	if (qss_ctx == NULL)
		return SM_SUCCESS;
	SM_IS_QSS_CTX(qss_ctx);
	if (qss_ctx->qss_status == QSS_ST_NONE || qss_ctx->qss_id == QSS_ID_NONE)
		return SM_SUCCESS;
	qmgr_ctx = qss_ctx->qss_qmgr_ctx;
	SM_IS_QMGR_CTX(qmgr_ctx);
	iqdb_walk(qmgr_ctx->qmgr_iqdb, iqdb_close_ss, (void *) qss_ctx,
		THR_LOCK_UNLOCK);
	if (QMGR_IS_RFLAG_I(qmgr_ctx, QMGR_RFL_IQD))
	{
		(void) qm_resource(qmgr_ctx, QMGR_UN_THROTTLE,
				iqdb_usage(qmgr_ctx->qmgr_iqdb),
				QMGR_RFL_IQD);
	}
	return SM_SUCCESS;
}


syntax highlighted by Code2HTML, v. 0.9.1