Top | ![]() |
![]() |
![]() |
![]() |
Functions
void | milter_client_init () |
void | milter_client_quit () |
GOptionGroup * | milter_client_get_option_group () |
Description
The milter-client library provides full milter protocol processing features on client-side. "client-side" means milter-side not MTA-side.
MilterClient
and MilterClientContext
is the main
classes in the milter-client library. MilterClient
accepts n-connections from MTA and each connection is
processed by MilterClientContext
.
Usage overview
You need to set connection spec and connect “connection-established” signal before entering mail loop.
Connection spec is a entry point of MilterClient
for
MTA. It has 'PROTOCOL:INFORMATION' format. For IPv4
socket, 'inet:PORT', 'inet:PORT@HOST' or
'inet:PORT@[ADDRESS]' are valid formats. For IPv6
socket, 'inet6:PORT', 'inet6:PORT@HOST' or
'inet6:PORT@[ADDRESS]' are valid formats. For UNIX
domain socket, 'unix:PATH' is a valid format.
MilterClient
emits “connection-established”
signal. MilterClientContext
setup should be done in the
signal. In many cases, you just connect callbacks to
the passed MilterClientContext
. See MilterClientContext
for available signals.
milter_client_run() is running main loop function. You
can enter into main loop after you finish to prepare your
MilterClient
.
Here is an example codes that uses the milter-client library. See also tool/milter-test-client.c. It is an example milter implementation using the milter-client library.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <stdlib.h> #include <milter/client.h> static void cb_connection_established (MilterClient *client, MilterClientContext *context, gpointer user_data) { connect_to_your_interesting_signals(client, context, user_data); } int main (int argc, char **argv) { gboolean success; const gchar spec[] = "inet:10025@localhost"; MilterClient *client; GError *error = NULL; milter_init(); milter_client_init(); client = milter_client_new(); if (!milter_client_set_connection_spec(client, spec, &error)) { g_print("%s\n", error->message); g_error_free(error); return EXIT_FAILURE; } g_signal_connect(client, "connection-established", G_CALLBACK(cb_connection_established), NULL); milter_client_run(client); milter_client_quit(); milter_quit(); return success ? EXIT_SUCCESS : EXIT_FAILURE; } |
Processing model
The libmilter provided by Sendmail uses a thread for each
connection model. But the milter-client library doesn't
use it. The milter-client library uses two threads. One
thread is for MilterClient
and other thread is for
MilterClientContext
s. MilterClient
just
accepting connections from MTA and dispatches it in the
first thread. Each connection is associated with
MilterClientContext
and they are processed in the second
thread. The milter-client library's model is the same
model of memcached. (memcached uses libevent as its event
loop backend but the milter-client library uses GLib's
GMainLoop
for it.)
The libmilter's model will have more cost to accept a
connection rather than the milter-client library's
model. Because the libmilter's model creates a thread but
the milter-client library just allocate
MilterClientContext
. But in many case, this difference
is not bottleneck. :-|