/* * 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 # 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 */