/* * 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; }