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