/*
* Copyright (c) 2003-2006 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: smar_li.c,v 1.15 2006/04/02 06:34:20 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/memops.h"
#include "smar.h"
#include "sm/qmgr-int.h"
#include "log.h"
/*
** SMAR_LI -- Handle new connections
**
** Parameters:
** tsk -- evthr task
**
** Returns:
** EVTHR_WAITQ
**
** Last code review:
** Last code change: 2006-03-10 06:27:33
*/
sm_ret_T
smar_li(sm_evthr_task_P tsk)
{
int fd, r, i;
uint32_t j;
sm_ret_T ret;
sm_evthr_task_P task;
smar_ctx_P smar_ctx;
smar_clt_ctx_P smar_clt_ctx;
SM_IS_EVTHR_TSK(tsk);
SM_REQUIRE(tsk->evthr_t_nc != NULL);
smar_ctx = (smar_ctx_P) tsk->evthr_t_actx;
SM_IS_SMAR_CTX(smar_ctx);
SMAR_LEV_DPRINTF(5, (SMAR_DEBFP, "sev=DBG, func=smar_li, new connection\n"));
fd = tsk->evthr_t_nc->evthr_a_fd;
if (!is_valid_fd(fd))
{
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERROR, 6,
"sev=ERROR, func=smar_li, fd=%d", fd);
return EVTHR_WAITQ;
}
/* add the new connection */
r = pthread_mutex_lock(&smar_ctx->smar_mutex);
SM_LOCK_OK(r);
if (r != 0)
{
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_CRIT, 1,
"sev=CRIT, func=smar_li, lock=%d",
r);
goto error;
}
SMAR_LEV_DPRINTF(6, (SMAR_DEBFP, "sev=DBG, func=smar_li, got lock\n"));
/* search for free client context */
for (j = 1, i = 0; i < SMAR_MAX_CLTS; i++, j *= 2)
{
if ((smar_ctx->smar_clt_used & j) == 0)
{
smar_ctx->smar_clt_used |= j;
smar_clt_ctx = smar_ctx->smar_clt_ctx[i];
SM_IS_SMAR_CLT_CTX(smar_clt_ctx);
smar_clt_ctx->smac_status = SMAC_ST_NONE;
smar_clt_ctx->smac_bit = j;
smar_clt_ctx->smac_idx = i;
break;
}
}
if (i >= SMAR_MAX_CLTS)
{
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERROR, 4,
"sev=ERROR, func=smar_li, status=too_many_connections");
goto err2;
}
SMAR_LEV_DPRINTF(5, (SMAR_DEBFP, "sev=DBG, func=smar_li, i=%d, clt_ctx=%p\n", i, smar_clt_ctx));
ret = sm_rcb_open_rcv(smar_clt_ctx->smac_com_ctx.rcbcom_rdrcb);
if (sm_is_err(ret))
{
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERROR, 4,
"sev=ERROR, func=smar_li, sm_rcb_open_rcv=%m"
, ret);
goto err2;
}
ret = sm_fd_nonblock(fd, true);
if (sm_is_err(ret))
{
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERROR, 4,
"sev=ERROR, func=smar_li, sm_fd_nonblock=%m"
, ret);
goto err2;
}
/* start a task for the new client */
ret = evthr_task_new(smar_ctx->smar_ev_ctx, &task,
EVTHR_EV_RD, fd, NULL, smar_clt,
(void *) smar_clt_ctx);
if (sm_is_err(ret))
{
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERROR, 4,
"sev=ERROR, func=smar_li, evthr_task_new=%m"
, ret);
goto err2;
}
SM_IS_EVTHR_TSK(task);
EVTHRT_SET_FLAG(task, EVTHRT_FL_BLK_RD);
smar_clt_ctx->smac_com_ctx.rcbcom_tsk = task;
SMAR_LEV_DPRINTF(6, (SMAR_DEBFP, "sev=DBG, func=smar_li, new tsk=%p, fd=%d\n", task, task->evthr_t_fd));
r = pthread_mutex_unlock(&smar_ctx->smar_mutex);
return EVTHR_WAITQ;
err2:
r = pthread_mutex_unlock(&smar_ctx->smar_mutex);
error:
if (is_valid_fd(fd))
close(fd);
return EVTHR_WAITQ;
}
syntax highlighted by Code2HTML, v. 0.9.1