## Client library

Client library — milterを実装するためのクライアントライブラリ。

## Functions

void | milter_client_init ()
void | milter_client_quit ()
GOptionGroup * | milter_client_get_option_group ()

## 説明

milter-clientライブラリはクライアント側のすべてのmilterプロトコルを処理する機能を提供します。「クライアント側」というのは「milter側」ということで、「MTA側」ではありません。

milter-clientライブラリでの主要なクラスは`MilterClient`と`MilterClientContext`です。`MilterClient`はMTAからの複数の接続を受け付け、各接続は`MilterClientContext`が処理します。

#### 使用法概観

You need to set connection spec and connect “connection-established” signal before entering mail loop.

接続指定はMTAが`MilterClient`に接続するためのエントリポイントです。接続指定は「プロトコル:情報」という形式になっています。IPv4ソケットでは「inet:ポート番号」、「inet:ポート番号@ホスト名」、「inet:ポート番号@[IPv4アドレス]」が正しい形式です。IPv6ソケットでは、「inet6:ポート番号」、「inet6:ポート番号@ホスト名」、「inet6:ポート番号@[IPv6アドレス]」が正しい形式です。UNIXドメインソケットでは「unix:パス」が正しい形式です。

`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`.

milter-clientライブラリを使った例です。tool/milter-test-client.cも見てください。milter-test-client.cはmilter-clientライブラリを使ったmilterの実装例です。

    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;
    }

#### 処理モデル

Sendmailが提供するlibmilterは各接続毎にスレッドを生成するモデルです。しかし、milter-clientライブラリはこのモデルを使いません。milter-clientライブラリは2つのスレッドを使います。1つのスレッドは`MilterClient`用のスレッドで、もう1つのスレッドは`MilterClientContext`用のスレッドです。1つ目のスレッドでは`MilterClient`がMTAからの接続を受け付けて、それを割り振るだけです。`MilterClientContext`に関連付けられた各接続は、2つ目のスレッド内で処理を行います。milter-clientライブラリのモデルはmemcachedのモデルと同じです。（memcachedはイベントループのバックエンドにlibeventを使っていますが、milter-clientライブラリはGLibの`GMainLoop`を使っています。）

libmilterのモデルは接続を受け付けるためにmilter-clientライブラリのモデルよりも多くコストがかかります。これは、libmilterのモデルがスレッドを生成するのに対して、milter-clientライブラリは単に`MilterClientContext`オブジェクトを生成するだけだからです。ただし、多くの場合、この違いはボトルネックとはなりません。:-|

## Functions

### milter_client_init ()

    void
    milter_client_init (void);

Call this function before using any other the milter-client library functions.

### milter_client_quit ()

    void
    milter_client_quit (void);

Call this function after the milter-client library use.

### milter_client_get_option_group ()

    GOptionGroup *
    milter_client_get_option_group (MilterClient *client);

Gets a `GOptionGroup` for the `client` . The option group has common milter client options.

#### Parameters

client | `MilterClient`。 |

#### Returns

a new `GOptionGroup` for `client` .