1<HTML> 2<HEAD> 3<TITLE>Technical Overview</TITLE> 4</HEAD> 5<BODY> 6<!-- 7$Id: overview.html,v 1.22 2013-11-22 20:51:39 ca Exp $ 8--> 9 10<H1>Technical Overview</H1> 11 12<H2>Contents</H2> 13 14<UL> 15 <LI><A HREF="#Initialization">Initialization</A> 16 <LI><A HREF="#ControlFlow">Control Flow</A> 17 <LI><A HREF="#Multithreading">Multithreading</A> 18 <LI><A HREF="#ResourceManagement">Resource Management</A> 19 <LI><A HREF="#SignalHandling">Signal Handling</A> 20</UL> 21 22<H2><A NAME="Initialization">Initialization</A></H2> 23 24In addition to its own initialization, 25libmilter expects a filter to initialize several parameters 26before calling <A HREF="smfi_main.html">smfi_main</A>: 27<UL> 28 <LI>The callbacks the filter wishes to be called, and the types of 29 message modification it intends to perform (required, see 30 <A HREF="smfi_register.html">smfi_register</A>). 31 32 <LI>The socket address to be used when communicating with the MTA 33 (required, see <A HREF="smfi_setconn.html">smfi_setconn</A>). 34 35 <LI>The number of seconds to wait for MTA connections before 36 timing out (optional, see 37 <A HREF="smfi_settimeout.html">smfi_settimeout</A>). 38</UL> 39<P> 40If the filter fails to initialize libmilter, 41or if one or more of the parameters it has passed are invalid, 42a subsequent call to smfi_main will fail. 43 44<H2><A NAME="ControlFlow">Control Flow</A></H2> 45 46<P> 47The following pseudocode describes the filtering process from the 48perspective of a set of <CODE>N</CODE> MTA's, 49each corresponding to a connection. 50Callbacks are shown beside the processing stages in which they are invoked; 51if no callbacks are defined for a particular stage, 52that stage may be bypassed. 53Though it is not shown, 54processing may be aborted at any time during a message, 55in which case the 56<A HREF="xxfi_abort.html">xxfi_abort</A> callback is invoked and control 57returns to <CODE>MESSAGE</CODE>. 58<P> 59<PRE> 60For each of N connections 61{ 62 For each filter 63 egotiate MTA/milter capabilities/requirements (<A HREF="xxfi_negotiate.html">xxfi_negotiate</A>) 64 For each filter 65 process connection (<A HREF="xxfi_connect.html">xxfi_connect</A>) 66 For each filter 67 process helo/ehlo (<A HREF="xxfi_helo.html">xxfi_helo</A>) 68MESSAGE:For each message in this connection (sequentially) 69 { 70 For each filter 71 process sender (<A HREF="xxfi_envfrom.html">xxfi_envfrom</A>) 72 For each recipient 73 { 74 For each filter 75 process recipient (<A HREF="xxfi_envrcpt.html">xxfi_envrcpt</A>) 76 } 77 For each filter 78 { 79 process DATA (<A HREF="xxfi_data.html">xxfi_data</A>) 80 For each header 81 process header (<A HREF="xxfi_header.html">xxfi_header</A>) 82 process end of headers (<A HREF="xxfi_eoh.html">xxfi_eoh</A>) 83 For each body block 84 process this body block (<A HREF="xxfi_body.html">xxfi_body</A>) 85 process end of message (<A HREF="xxfi_eom.html">xxfi_eom</A>) 86 } 87 } 88 For each filter 89 process end of connection (<A HREF="xxfi_close.html">xxfi_close</A>) 90} 91</PRE> 92 93<P>Note: Filters are contacted in order defined in config file.</P> 94 95<P> 96To write a filter, a vendor supplies callbacks to process relevant 97parts of a message transaction. 98The library then controls all sequencing, threading, 99and protocol exchange with the MTA. 100<A HREF="#figure-3">Figure 3</A> outlines control flow for a filter 101process, showing where different callbacks are invoked. 102</P> 103 104<DIV ALIGN="center"><A NAME="figure-3"></A> 105<TABLE border=1 cellspacing=0 cellpadding=2 width="70%"> 106<TR bgcolor="#dddddd"><TH>SMTP Commands</TH><TH>Milter Callbacks</TH></TR> 107<TR><TD>(open SMTP connection)</TD><TD>xxfi_connect</TD></TR> 108<TR><TD>HELO ...</TD><TD>xxfi_helo</TD></TR> 109<TR><TD>MAIL From: ...</TD><TD>xxfi_envfrom</TD></TR> 110<TR><TD>RCPT To: ...</TD><TD>xxfi_envrcpt</TD></TR> 111<TR><TD>[more RCPTs]</TD><TD>[xxfi_envrcpt]</TD></TR> 112<TR><TD>DATA</TD><TD>xxfi_data</TD></TR> 113<TR><TD>Header: ...</TD><TD>xxfi_header</TD></TR> 114<TR><TD>[more headers]</TD><TD>[xxfi_header]</TD></TR> 115<TR><TD> </TD><TD>xxfi_eoh</TD></TR> 116<TR><TD>body... </TD><TD>xxfi_body</TD></TR> 117<TR><TD>[more body...]</TD><TD>[xxfi_body]</TD></TR> 118<TR><TD>.</TD><TD>xxfi_eom</TD></TR> 119<TR><TD>QUIT</TD><TD>xxfi_close</TD></TR> 120<TR><TD>(close SMTP connection)</TD><TD> </TD></TR> 121</TABLE> 122<B>Figure 3: Milter callbacks related to an SMTP transaction.</B> 123</DIV> 124 125<P> 126Note that although only a single message is shown above, multiple 127messages may be sent in a single connection. 128Note also that a message or connection may be aborted by 129either the remote host or the MTA 130at any point during the SMTP transaction. 131If this occurs during a message (between the MAIL command and the final "."), 132the filter's 133<A HREF="xxfi_abort.html">xxfi_abort</A> routine will be called. 134<A HREF="xxfi_close.html">xxfi_close</A> is called any time the 135connection closes. 136 137<H2><A NAME="Multithreading">Multithreading</A></H2> 138 139<P> 140A single filter process may handle any number of connections 141simultaneously. 142All filtering callbacks must therefore be reentrant, 143and use some appropriate external synchronization methods to access 144global data. 145Furthermore, since there is not a one-to-one correspondence 146between threads and connections 147(N connections mapped onto M threads, M <= N), 148connection-specific data must be accessed 149through the handles provided by the Milter library. 150The programmer cannot rely on library-supplied thread-specific data blocks 151(e.g., <CODE>pthread_getspecific(3)</CODE>) to store connection-specific data. 152See the API documentation for 153<A HREF="smfi_setpriv.html">smfi_setpriv</A> and 154<A HREF="smfi_getpriv.html">smfi_getpriv</A> for details. 155 156<H2><A NAME="ResourceManagement">Resource Management</A></H2> 157 158Since filters are likely to be long-lived, 159and to handle many connections, 160proper deallocation of per-connection resources is important. 161The lifetime of a connection is bracketed by calls to the 162callbacks <A HREF="xxfi_connect.html">xxfi_connect</A> and 163<A HREF="xxfi_close.html">xxfi_close</A>. 164Therefore connection-specific 165resources (accessed via <A HREF="smfi_getpriv.html">smfi_getpriv</A> 166and <A HREF="smfi_setpriv.html">smfi_setpriv</A>) may be allocated in 167<A HREF="xxfi_connect.html">xxfi_connect</A>, 168and should be freed in 169<A HREF="xxfi_close.html">xxfi_close</A>. 170For further information see 171the <A HREF="api.html#conn-msg">discussion</A> of message- versus 172connection-oriented routines. 173In particular, 174note that there is only one connection-specific data pointer per connection. 175<P> 176 177Each message is bracketed by calls to 178<A HREF="xxfi_envfrom.html">xxfi_envfrom</A> and 179<A HREF="xxfi_eom.html">xxfi_eom</A> (or 180<A HREF="xxfi_abort.html">xxfi_abort</A>), 181implying that message-specific resources can be allocated 182and reclaimed in these routines. 183Since the messages in a connection are processed sequentially by each filter, 184there will be only one active message associated with a given 185connection and filter (and connection-private data block). 186These resources must still be accessed through 187<A HREF="smfi_getpriv.html">smfi_getpriv</A> and 188<A HREF="smfi_setpriv.html">smfi_setpriv</A>, 189and must be reclaimed in 190<A HREF="xxfi_abort.html">xxfi_abort</A>. 191 192<H2><A NAME="SignalHandling">Signal Handling</A></H2> 193 194libmilter takes care of signal handling, 195the filters are not influenced directly by signals. 196There are basically two types of signal handlers: 197 198<OL> 199<LI><TT>Stop</TT>: no new connections from the MTA will be accepted, 200but existing connections are allowed to continue. 201<LI><TT>Abort</TT>: all filters will be stopped as soon as the next 202communication with the MTA happens. 203</OL> 204 205Filters are not terminated asynchronously 206(except by signals that can't be caught). 207In the case of <TT>Abort</TT> the 208<A HREF="xxfi_abort.html">xxfi_abort</A> callback is usually invoked 209if there is an active transaction. 210However, if an invoked callback takes too long to execute 211(the maximum time <TT>Abort</TT> waits is currently 5s) 212<!-- XREF: MI_CHK_TIME --> 213then the filter is simply terminated, i.e., 214neither the 215<A HREF="xxfi_abort.html">xxfi_abort</A> callback 216nor the 217<A HREF="xxfi_close.html">xxfi_close</A> callback 218is invoked. 219 220<HR size="1"> 221<FONT size="-1"> 222Copyright (c) 2000, 2001, 2003, 2006, 2018 Proofpoint, Inc. and its suppliers. 223All rights reserved. 224<BR> 225By using this file, you agree to the terms and conditions set 226forth in the LICENSE. 227</FONT> 228</BODY> 229</HTML> 230