/* * 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: rcb.h,v 1.67 2007/01/31 04:18:17 ca Exp $ */ #ifndef SM_RCB_H #define SM_RCB_H 1 /* ** Notice: This is almost a copy of sm/str.h */ #include "sm/generic.h" #include "sm/types.h" #include "sm/error.h" #include "sm/magic.h" #include "sm/rpool.h" #include "sm/str.h" #if SM_RCB_ST # include "statethreads/st.h" #endif #if !SM_NO_CSTR # include "sm/cstr.h" #endif #ifndef SM_STR_READ # define SM_STR_READ 1 #endif #ifndef MTA_USE_RCBV_INT2 # define MTA_USE_RCBV_INT2 1 #endif #ifndef MTA_USE_RCBV_INTN # define MTA_USE_RCBV_INTN 1 #endif #ifndef MTA_USE_RCBV_STRN # define MTA_USE_RCBV_STRN 0 #endif #if SM_STR_CHECK # ifndef SM_RCB_CHECK # define SM_RCB_CHECK 1 # endif #endif #ifndef SM_RCB_END_RCB /* activate code to mark end of RCB: currently broken! */ # define SM_RCB_END_RCB 0 #endif typedef struct sm_rcb_S sm_rcb_T, *sm_rcb_P; /* ** sm_rcb_T -- Stores rcb data and length information. ** ** Members: ** sm_rcb_base -- uchar * to data (doesn't need to end with '\0'). ** sm_rcb_size -- Total bytes allocated. ** sm_rcb_len -- Total number of characters in rcb. ** sm_rcb_max -- Maximum number of characters in rcb. ** sm_rcb_rpool -- rpool to allocate from. ** sm_rcb_rw -- read index/space left to write. ** ** Invariants: ** both modes: ** sm_rcb_len <= sm_rcb_size <= sm_rcb_max ** read mode: ** sm_rcb_rw <= sm_str_len ** write mode: ** no length specified: sm_rcb_rw < 0 ** length specified: sm_rcb_rw > sizeof(data) to put into RCB ** ** Notices: ** See sm/str.h ** ** Content of an RCB: ** first 4 bytes: total length of RCB ** then a sequence of records: ** 4 bytes: length of "payload" of record: value "l" ** 4 bytes: record type ** l bytes: "payload" of record: l bytes ** records are aligned to 4 bytes. */ struct sm_rcb_S { sm_magic_T sm_magic; uchar *sm_rcb_base; uint sm_rcb_len; uint sm_rcb_size; uint sm_rcb_max; int sm_rcb_rw; /* read index, must be last to match str */ sm_rpool_P sm_rcb_rpool; #if SM_STR_CHECK uint sm_rcb_state; #endif }; sm_rcb_P sm_rcb_new(sm_rpool_P _rpool, uint _len, uint _max); #if 0 sm_rcb_P sm_rcb_crt(sm_rpool_P rpool, uchar *rcb, uint len, uint maxlen); #endif /* defines for rcb_putv() */ #define SM_RCBV_INT 1 #if MTA_USE_RCBV_INT2 # define SM_RCBV_INT2 2 #endif #define SM_RCBV_INT64 3 #define SM_RCBV_STR 4 #define SM_RCBV_CSTR 5 #define SM_RCBV_BUF 6 #define SM_RCBV_RDSTR 7 #if MTA_USE_RCBV_INTN # define SM_RCBV_INTN 8 # define SM_RCBV_INTA 9 #endif #if MTA_USE_RCBV_STRN # define SM_RCBV_STRA 10 #endif #define SM_RCBV_END 11 #if SIZEOF_OFF_T == 4 #define SM_RCBV_OFF SM_RCBV_INT #elif SIZEOF_OFF_T == 8 #define SM_RCBV_OFF SM_RCBV_INT64 #else ERROR _SIZEOF_OFF_T is neither 4 not 8: SIZEOF_OFF_T #endif #if SM_RCB_ST # define rcb_fd_T st_netfd_t #else # define rcb_fd_T int #endif sm_ret_T sm_rcb_put(sm_rcb_P _rcb, uchar _c); #if SM_STR_CHECK int sm_rcb_get(sm_rcb_P _rcb); #define SM_RCB_PUT(rcb, c) sm_rcb_put((rcb), (c)) #define SM_RCB_GET(rcb) sm_rcb_get(rcb) #else /* SM_STR_CHECK */ #define SM_RCB_GET(rcb) (((rcb)->sm_rcb_len <= (rcb)->sm_rcb_rw) \ ? sm_error_perm(SM_EM_RECCOM, SM_E_OVFLW_NS) \ : (rcb)->sm_rcb_base[(rcb)->sm_rcb_rw++]) #define SM_RCB_PUT(rcb, c) (((rcb)->sm_rcb_len == (rcb)->sm_rcb_size) ? \ sm_rcb_put((rcb), (c)) : \ ((rcb)->sm_rcb_base[(rcb)->sm_rcb_len++] = (c)), SM_SUCCESS) #endif /* SM_STR_CHECK */ #if SM_RCB_END_RCB /* end of RCB marker length: l + record type + value: 3 * sizeof(uint32_t) */ #define SM_RCB_EORCB_LEN 12 #define SM_RCB_ISEOB(rcb) ((rcb)->sm_rcb_len <= (rcb)->sm_rcb_rw + SM_RCB_EORCB_LEN) #else /* SM_RCB_END_RCB */ #define SM_RCB_EORCB_LEN 0 #define SM_RCB_ISEOB(rcb) ((int) (rcb)->sm_rcb_len <= (rcb)->sm_rcb_rw) #endif /* SM_RCB_END_RCB */ sm_ret_T sm_rcb_putuint32(sm_rcb_P _rcb, uint32_t _n); sm_ret_T sm_rcb_putuint64(sm_rcb_P _rcb, uint64_t _u); sm_ret_T sm_rcb_put2uint32(sm_rcb_P _rcb, uint32_t _n1, uint32_t _n2); sm_ret_T sm_rcb_put3uint32(sm_rcb_P _rcb, uint32_t _n1, uint32_t _n2, uint32_t _n3); #if MTA_USE_RCBV_INT2 sm_ret_T sm_rcb_put4uint32(sm_rcb_P _rcb, uint32_t _n1, uint32_t _n2, uint32_t _n3, uint32_t _n4); #endif sm_ret_T sm_rcb_put3uint64(sm_rcb_P _rcb, uint32_t _n1, uint32_t _n2, uint64_t _u); #if MTA_USE_RCBV_INTN sm_ret_T sm_rcb_putnuint32(sm_rcb_P _rcb, uint32_t _rt, uint _n, ...); sm_ret_T sm_rcb_putauint32(sm_rcb_P _rcb, uint32_t _rt, uint _n, uint32_t *_av); #endif #if MTA_USE_RCBV_STRN sm_ret_T sm_rcb_putastr(sm_rcb_P _rcb, uint32_t _rt, uint _n, sm_str_P *_strv); #endif #if SIZEOF_OFF_T == 4 # define sm_rcb_putoff_t(rcb, n) sm_rcb_putuint32((rcb), (uint32_t) (n)) # define sm_rcb_put3off_t(rcb, n1, n2, n3) sm_rcb_put3uint32((rcb), (n1), (n2), (uint32_t) (n3)) # define sm_rcb_getoff_t(rcb, pv1) sm_rcb_getuint32((rcb), (uint32_t *) (pv1)) # define sm_rcb_get3off_t(rcb, pv1, pv2, pv3) sm_rcb_get3uint32((rcb), (pv1), (pv2), (uint32_t *) (pv3)) #elif SIZEOF_OFF_T == 8 # define sm_rcb_putoff_t(rcb, n) sm_rcb_putuint64((rcb), (uint64_t) (n)) # define sm_rcb_put3off_t(rcb, n1, n2, n3) sm_rcb_put3uint64((rcb), (n1), (n2), (uint64_t) (n3)) # define sm_rcb_getoff_t(rcb, pv1) sm_rcb_getuint64((rcb), (uint64_t *) (pv1)) # define sm_rcb_get3off_t(rcb, pv1, pv2, pv3) sm_rcb_get3uint64((rcb), (pv1), (pv2), (uint64_t *) (pv3)) #else ERROR _SIZEOF_OFF_T is neither 4 not 8: SIZEOF_OFF_T #endif /* flag values for sm_rcb_putv() */ #define RCB_PUTV_NONE 0x00 #define RCB_PUTV_FIRST 0x01 #define RCB_PUTV_OPEN 0x02 #define RCB_PUTV_CLOSE 0x04 /* flag values for sm_rcb_putrec() */ #define RCB_PUTR_NONE 0x00 /* do nothing special */ #define RCB_PUTR_FIRST 0x01 #define RCB_PUTR_OPEN 0x02 #define RCB_PUTR_CLOSE 0x04 #define RCB_PUTR_DFLT 0x07 /* default */ sm_ret_T sm_rcb_putv(sm_rcb_P _rcb, uint _flags, ...); sm_ret_T sm_rcb_putrec(sm_rcb_P _rcb, uint _flags, uint32_t _sz, int _n, ...); sm_ret_T sm_rcb_putstr(sm_rcb_P _dst, const sm_rcb_P _src); sm_ret_T sm_rcb_getuint32(sm_rcb_P _rcb, uint32_t *_pval); sm_ret_T sm_rcb_getuint64(sm_rcb_P _rcb, uint64_t *_pu); sm_ret_T sm_rcb_get2uint32(sm_rcb_P _rcb, uint32_t *_pv1, uint32_t *_pv2); sm_ret_T sm_rcb_get3uint32(sm_rcb_P _rcb, uint32_t *_pv1, uint32_t *_pv2, uint32_t *_pv3); #if MTA_USE_RCBV_INT2 sm_ret_T sm_rcb_get4uint32(sm_rcb_P _rcb, uint32_t *_pv1, uint32_t *_pv2, uint32_t *_pv3, uint32_t *_pv4); #endif sm_ret_T sm_rcb_get3uint64(sm_rcb_P _rcb, uint32_t *_pv1, uint32_t *_pv2, uint64_t *_pu); sm_ret_T sm_rcb_peek2uint32(sm_rcb_P _rcb, uint32_t *_pv1, uint32_t *_pv2); #if MTA_USE_RCBV_INTN sm_ret_T sm_rcb_getauint32(sm_rcb_P _rcb, uint _nmax, uint *_pn, uint32_t *_prt, uint32_t *_pv); #endif sm_ret_T sm_rcb_putn(sm_rcb_P _rcb, const uchar *_put, uint n); sm_ret_T sm_rcb_getn(sm_rcb_P _rcb, uchar *_get, uint _n); sm_ret_T sm_rcb_getstr(sm_rcb_P _rcb, sm_str_P _str, uint _n); sm_ret_T sm_rcb_getnstr(sm_rcb_P _rcb, sm_str_P *_str, uint _n); sm_ret_T sm_rcb_getn0str(sm_rcb_P _rcb, sm_str_P *_str, uint _n); sm_ret_T sm_rcb_getdata(sm_rcb_P _rcb, const uchar **_data, uint _n); #if !SM_NO_CSTR sm_ret_T sm_rcb_getncstr(sm_rcb_P _rcb, sm_cstr_P *_cstr, uint _n); #endif sm_ret_T sm_rcb_skip(sm_rcb_P _rcb, uint _n); sm_ret_T sm_rcb_resize_data(sm_rcb_P _rcb, uint _len); #if SM_STR_CHECK uint sm_rcb_getlen(sm_rcb_P _rcb); uint sm_rcb_getsize(sm_rcb_P _rcb); int sm_rcb_setmax(sm_rcb_P _rcb, uint _max); uint sm_rcb_getmax(sm_rcb_P _rcb); uchar sm_rcb_elem(sm_rcb_P _rcb, uint _i); uint sm_rcb_space(sm_rcb_P _rcb, uint _new_len); #else /* SM_STR_CHECK */ # define sm_rcb_getrd(rcb) ((rcb)->sm_rcb_rw) # define sm_rcb_getlen(rcb) ((rcb)->sm_rcb_len) # define sm_rcb_getsize(rcb) ((rcb)->sm_rcb_size) # define sm_rcb_setmax(rcb, m) (rcb)->sm_rcb_max = (m) # define sm_rcb_getmax(rcb) (rcb)->sm_rcb_max # define sm_rcb_elem(rcb, i) ((rcb)->sm_rcb_base[i]) # define sm_rcb_space(rcb, new_len) \ (((new_len) <= (rcb)->sm_rcb_size) ? (rcb)->sm_rcb_size \ : sm_rcb_resize_data((rcb), (new_len))) #endif /* SM_STR_CHECK */ /* XXX Careful: filled externally, e.g., reuse RCB and fill buffer directly */ #define sm_rcb_setlen(rcb, len) ((rcb)->sm_rcb_len) = (len) #define sm_rcb_data(rcb) ((rcb)->sm_rcb_base) void sm_rcb_free(sm_rcb_P _rcb); #define SM_RCB_FREE(ptr) do { \ if ((ptr) != NULL) { \ sm_rcb_free(ptr); \ (ptr) = NULL; \ } \ } while (0) #if SM_STR_CHECK void sm_rcb_clr(sm_rcb_P _rcb); # define SM_RCB_CLR(rcb) sm_rcb_clr(rcb) #else # define SM_RCB_CLR(rcb) do { \ (rcb)->sm_rcb_len = 0; \ (rcb)->sm_rcb_rw = 0; \ } while (0) #endif /* SM_STR_CHECK */ # define sm_rcb_getinit(rcb) (rcb)->sm_rcb_rw = 0 sm_ret_T sm_rcb_putinit(sm_rcb_P _rcb, int _n); #if SM_RCB_ST sm_ret_T sm_rcb_rcv(rcb_fd_T _fd, sm_rcb_P _rcb, uint _rs, st_utime_t _timeout); sm_ret_T sm_rcb_snd(rcb_fd_T _fd, sm_rcb_P _rcb, st_utime_t _timeout); #else sm_ret_T sm_rcb_rcv(rcb_fd_T _fd, sm_rcb_P _rcb, uint _rs); sm_ret_T sm_rcb_snd(rcb_fd_T _fd, sm_rcb_P _rcb); #endif sm_ret_T sm_rcb_open_rcv(sm_rcb_P _rcb); sm_ret_T sm_rcb_open_dec(sm_rcb_P _rcb); sm_ret_T sm_rcb_open_enc(sm_rcb_P _rcb, int _n); sm_ret_T sm_rcb_open_snd(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_rcv(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_dec(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_enc(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_snd(sm_rcb_P _rcb); sm_ret_T sm_rcb_open_rcvn(sm_rcb_P _rcb); sm_ret_T sm_rcb_open_decn(sm_rcb_P _rcb); sm_ret_T sm_rcb_open_encn(sm_rcb_P _rcb, int _n); sm_ret_T sm_rcb_open_sndn(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_rcvn(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_decn(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_encn(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_sndn(sm_rcb_P _rcb); sm_ret_T sm_rcb_close_n(sm_rcb_P _rcb); #if SM_STR_CHECK # define SM_RCB_NONE 0 # define SM_RCB_RCV 1 # define SM_RCB_DEC 2 # define SM_RCB_ENC 4 # define SM_RCB_SND 8 #endif /* SM_STR_CHECK */ #ifndef SM_MIN_RCB_SIZE # define SM_MIN_RCB_SIZE 64 #endif #ifndef SM_MIN_BUF_SIZE # define SM_MIN_BUF_SIZE SM_MIN_RCB_SIZE #endif #ifndef SM_RCB_MAX_LEN # define SM_RCB_MAX_LEN 65536 #endif #ifndef SM_STR_MAX_LEN # define SM_STR_MAX_LEN SM_RCB_MAX_LEN #endif #define SM_IS_RCB(rcb) SM_REQUIRE_ISA((rcb), SM_RCB_MAGIC) #endif /* SM_RCB_H */