/*
* 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.
*
* $Id: s2q.h,v 1.53 2007/10/19 02:30:19 ca Exp $
*/
#ifndef S2Q_H
#define S2Q_H 1
#include "sm/generic.h"
#include "sm/socket.h"
#include "sm/sockcnf.h"
#include "sm/reccom.h"
#include "statethreads/st.h"
#include "sm/rcbst.h"
#include "sm/qmgrcomm.h"
#include "smtps-str.h"
#include "sm/mta.h"
#ifndef SSQ_DEBUG
# define SSQ_DEBUG 0
#endif
#if SSQ_DEBUG
# include <stdio.h>
# define SSQ_DPRINTF(x) do { \
time_t currt = st_time(); \
sm_io_fprintf(smioerr, "%6ld: ", (long) currt); \
sm_io_fprintf x; \
} while (0)
#else /* SSQ_DEBUG */
# define SSQ_DPRINTF(x)
#endif /* SSQ_DEBUG */
/* basic size for RCB in s2q_ctx */
#define S2Q_RCB_SIZE 8192
struct s2q_ctx_S
{
ss_ctx_P s2q_ss_ctx; /* pointer back to ss_ctx */
int s2q_status; /* status */
st_netfd_t s2q_fd; /* fd for communication */
st_mutex_t s2q_wr_mutex; /* mutex for write */
uint s2q_maxrcbs; /* max. # of outstanding requests */
uint s2q_currcbs; /* current # of outstanding requests */
/*
** Current index of "server". This is used to keep track of
** "server" restarts to avoid using a "stale" connection.
** Problem: as there are multiple s2q_ctx's ss_sess_ctx should
** have multiple q_idx's. However, currently this is only used
** for pmilter, hence only that should be tested.
** A value of S2Q_ID_NONE means "match".
*/
int s2q_q_id;
/* server type (S2Q_T_*): index in ss_sess_ctx->ssse_s2q_id[] */
uint s2q_srv_type;
/*
** The size of the next two arrays is equal to the number of maximum threads.
** Therefore each thread can have one outstanding communication request.
** The arrays are used to associate incoming RCBs with the appropriate
** session (each thread handles one session); each RCB contains a session
** (or transaction) id. Looking it up in s2q_sids leads to the session
** which is stored at the same index in s2q_sess.
** If a session can have more than one outstanding request, then the
** the size of these arrays must be changed appropriately.
** Note: a session uses ssse_s2q_idx to determine whether a reference to
** it is stored in this array. If there are multiple outstanding requests,
** then there needs to be a different way (e.g., multiple indices or some
** other algorithm).
** Note: as long as the 1-1 relation is maintained, we could use the
** thread index of an smtps session context as index into these arrays.
** However, currently an ss_sess_ctx does not have a thread index.
*/
sessta_id_P *s2q_sids; /* array of session/transaction ids */
ss_sess_P *s2q_sess; /* array of session ctx */
};
#define S2Q_ST_OK 0
#define S2Q_ST_IOERR 1
#define S2Q_ST_CLOSED (-1)
/* use flags? */
#define S2Q_IS_IOERR(s2q_ctx) (S2Q_ST_IOERR == (s2q_ctx)->s2q_status)
#define S2Q_SET_IOERR(s2q_ctx) (s2q_ctx)->s2q_status = S2Q_ST_IOERR
#define S2Q_CLR_IOERR(s2q_ctx) (s2q_ctx)->s2q_status = S2Q_ST_OK
#define S2Q_CONN_OK(ss_sess, s2q_ctx) (S2Q_ST_OK == (s2q_ctx)->s2q_status)
/*
** Check connection state (to qmgr/smar/pmilter).
** Note: if you change the error codes in here, you must change
** SSPM_TRY_AGAIN(ss_ctx) in smtps/pmilter.h
** Note: sm_s2q_id_match() checks isn't necessary for a stateless server
** like smar.
*/
#define S2Q_CHK_CONN_R(ss_sess, s2q_ctx) \
do \
{ \
if (S2Q_ST_CLOSED == (s2q_ctx)->s2q_status) \
return sm_error_temp(SM_EM_SMTPS, SM_E_CONN_CLSD); \
if (!S2Q_CONN_OK((ss_sess), (s2q_ctx))) \
return sm_error_temp(SM_EM_SMTPS, EIO); \
if (!sm_s2q_id_match((ss_sess), (s2q_ctx))) \
return sm_error_temp(SM_EM_SMTPS, SM_E_WRONG_ID); \
} while (0)
/* which type of server? */
#define S2Q_T_QMGR SS_COMM_QMGR
#define S2Q_T_SMAR SS_COMM_SMAR
#define S2Q_T_PMILTER SS_COMM_PMILTER
#define S2Q_IS_STATELESS(srv_type) (SS_COMM_SMAR == (srv_type))
bool sm_s2q_id_match(ss_sess_P _ss_sess, s2q_ctx_P _s2q_ctx);
sm_ret_T sm_s2q_create(s2q_ctx_P *_ps2q_ctx, ss_ctx_P _ss_ctx, uint _maxrcbs);
sm_ret_T sm_s2q_open(s2q_ctx_P _s2q_ctx, sockspec_P _sockspec, uint _wait4srv, uint _max_threads, uint _srv_type, uint32_t _flags);
sm_ret_T sm_s2q_init(s2q_ctx_P *_ps2q_ctx, ss_ctx_P _ss_ctx, sockspec_P _sockspec, uint _wait4srv, uint _max_threads, int _smtps_id, uint _maxrcbs, uint _srv_type, uint32_t _flags);
sm_ret_T sm_s2q_init_u(s2q_ctx_P *_ps2q_ctx, ss_ctx_P _ss_ctx, const char *_sockname, uint _wait4srv, uint _max_threads, int _smtps_id, uint _maxrcbs, uint _srv_type, uint32_t _flags);
sm_ret_T sm_s2q_stop(s2q_ctx_P _s2q_ctx);
sm_ret_T sm_s2q_nseid(ss_sess_P _ss_sess, s2q_ctx_P _s2q_ctx, sessta_id_P _sid);
sm_ret_T sm_s2q_cseid(ss_sess_P _ss_sess, s2q_ctx_P _s2q_ctx, sessta_id_P _sid);
sm_ret_T sm_s2q_1taid(ss_sess_P _ss_sess, s2q_ctx_P _s2q_ctx);
#if MTA_USE_PMILTER && 0
sm_ret_T sm_s2q_rcpts(ss_sess_P _ss_sess, s2q_ctx_P _s2q_ctx,
uint _first_idx, uint _last_idx);
#endif
sm_ret_T sm_w4q2s_reply(ss_sess_P _sess, uint _tmo, s2q_ctx_P _s2q_ctx);
sm_ret_T sm_s2a_rcptid(ss_sess_P _ss_sess, s2q_ctx_P _s2a_ctx,
sessta_id_P _tid, int _rcpt_idx,
uint32_t _lt, uint32_t _lfl, sm_str_P _rcpt);
sm_ret_T sm_s2a_addr(ss_sess_P _ss_sess, s2q_ctx_P _s2a_ctx,
sessta_id_P _tid, sm_str_P _addr, uint32_t _what, uint32_t _ltype,
uint32_t _lflags);
sm_ret_T sm_s2a_clt(ss_sess_P _ss_sess, s2q_ctx_P _s2a_ctx,
sessta_id_P _sid, sm_str_P _clt,
uint32_t _what, uint32_t _ltype, uint32_t _lflags);
sm_ret_T sm_s2a_tls(ss_sess_P _ss_sess, s2q_ctx_P _s2a_ctx);
sm_ret_T sm_s2a_str(ss_sess_P _ss_sess, s2q_ctx_P _s2a_ctx, sessta_id_P _sid, sm_str_P _str, uint32_t _rt, uint32_t _lt, uint32_t _lfl);
sm_ret_T ss_clr_sess_rq(s2q_ctx_P _s2q_ctx, ss_sess_P _ss_sess);
sm_ret_T ss_add_rq(ss_sess_P _ss_sess, sessta_id_P _tid, s2q_ctx_P _s2q_ctx, uint *_pi);
sm_ret_T ss_send_rq(ss_sess_P _ss_sess, sessta_id_P _tid, s2q_ctx_P _s2q_ctx, sm_rcb_P _rcb, bool _reply);
#endif /* S2Q_H */
syntax highlighted by Code2HTML, v. 0.9.1