~ubuntu-branches/ubuntu/trusty/postfix/trusty-updates

« back to all changes in this revision

Viewing changes to src/util/auto_clnt.c

Tags: upstream-2.3.1
ImportĀ upstreamĀ versionĀ 2.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
/* SYNOPSIS
7
7
/*      #include <auto_clnt.h>
8
8
/*
9
 
/*      AUTO_CLNT *auto_clnt_create(max_idle, max_ttl, open_action, context)
 
9
/*      AUTO_CLNT *auto_clnt_create(service, timeout, max_idle, max_ttl)
 
10
/*      const char *service;
 
11
/*      int     timeout;
10
12
/*      int     max_idle;
11
13
/*      int     max_ttl;
12
 
/*      VSTREAM *(open_action)(void *context)
13
 
/*      void    *context;
14
14
/*
15
15
/*      VSTREAM *auto_clnt_access(auto_clnt)
16
16
/*      AUTO_CLNT *auto_clnt;
18
18
/*      void    auto_clnt_recover(auto_clnt)
19
19
/*      AUTO_CLNT *auto_clnt;
20
20
/*
 
21
/*      const char *auto_clnt_name(auto_clnt)
 
22
/*      AUTO_CLNT *auto_clnt;
 
23
/*
21
24
/*      void    auto_clnt_free(auto_clnt)
22
25
/*      AUTO_CLNT *auto_clnt;
23
26
/* DESCRIPTION
26
29
/*      that disconnect after a configurable time to live,
27
30
/*      and that transparently handle most server-initiated disconnects.
28
31
/*
 
32
/*      This module tries each operation only a limited number of
 
33
/*      times and then reports an error.  This is unlike the
 
34
/*      clnt_stream(3) module which will retry forever, so that
 
35
/*      the application never experiences an error.
 
36
/*
29
37
/*      auto_clnt_create() instantiates a client endpoint.
30
38
/*
31
39
/*      auto_clnt_access() returns an open stream to the service specified
35
43
/*      auto_clnt_recover() recovers from a server-initiated disconnect
36
44
/*      that happened in the middle of an I/O operation.
37
45
/*
 
46
/*      auto_clnt_name() returns the name of the specified client endpoint.
 
47
/*
38
48
/*      auto_clnt_free() destroys of the specified client endpoint.
39
49
/*
40
50
/*      Arguments:
 
51
/* .IP service
 
52
/*      The service argument specifies "transport:servername" where
 
53
/*      transport is currently limited to one of the following:
 
54
/* .RS
 
55
/* .IP inet
 
56
/*      servername has the form "host:port".
 
57
/* .IP unix
 
58
/*      servername has the form "private/servicename" or
 
59
/*      "public/servicename".
 
60
/* .RE
 
61
/* .IP timeout
 
62
/*      The time limit for sending, receiving, or for connecting
 
63
/*      to a server. Specify a value <=0 to disable the time limit.
41
64
/* .IP max_idle
42
 
/*      Idle time after which the client disconnects. Specify 0 to disable
43
 
/*      the limit.
 
65
/*      Idle time after which the client disconnects. Specify 0 to
 
66
/*      disable the limit.
44
67
/* .IP max_ttl
45
68
/*      Upper bound on the time that a connection is allowed to persist.
46
69
/*      Specify 0 to disable the limit.
66
89
/* System library. */
67
90
 
68
91
#include <sys_defs.h>
 
92
#include <string.h>
69
93
 
70
94
/* Utility library. */
71
95
 
74
98
#include <vstream.h>
75
99
#include <events.h>
76
100
#include <iostuff.h>
 
101
#include <connect.h>
 
102
#include <split_at.h>
77
103
#include <auto_clnt.h>
78
104
 
79
105
/* Application-specific. */
84
110
  */
85
111
struct AUTO_CLNT {
86
112
    VSTREAM *vstream;                   /* buffered I/O */
 
113
    char   *endpoint;                   /* host:port or pathname */
 
114
    int     timeout;                    /* I/O time limit */
87
115
    int     max_idle;                   /* time before client disconnect */
88
116
    int     max_ttl;                    /* time before client disconnect */
89
 
    VSTREAM *(*open_action) (void *);   /* callback */
90
 
    void   *context;                    /* callback context */
 
117
    int     (*connect) (const char *, int, int);        /* unix, local, inet */
91
118
};
92
119
 
93
120
static void auto_clnt_close(AUTO_CLNT *);
132
159
 
133
160
static void auto_clnt_open(AUTO_CLNT *auto_clnt)
134
161
{
 
162
    const char *myname = "auto_clnt_open";
 
163
    int     fd;
135
164
 
136
165
    /*
137
166
     * Sanity check.
148
177
     * connection is not idle. This is to prevent one client from clinging on
149
178
     * to a server forever.
150
179
     */
151
 
    auto_clnt->vstream =
152
 
        auto_clnt->open_action(auto_clnt->context);
 
180
    fd = auto_clnt->connect(auto_clnt->endpoint, BLOCKING, auto_clnt->timeout);
 
181
    if (fd < 0) {
 
182
        msg_warn("connect to %s: %m", auto_clnt->endpoint);
 
183
    } else {
 
184
        if (msg_verbose)
 
185
            msg_info("%s: connected to %s", myname, auto_clnt->endpoint);
 
186
        auto_clnt->vstream = vstream_fdopen(fd, O_RDWR);
 
187
        vstream_control(auto_clnt->vstream,
 
188
                        VSTREAM_CTL_PATH, auto_clnt->endpoint,
 
189
                        VSTREAM_CTL_TIMEOUT, auto_clnt->timeout,
 
190
                        VSTREAM_CTL_END);
 
191
    }
153
192
 
154
193
    if (auto_clnt->vstream != 0) {
155
194
        close_on_exec(vstream_fileno(auto_clnt->vstream), CLOSE_ON_EXEC);
168
207
 
169
208
static void auto_clnt_close(AUTO_CLNT *auto_clnt)
170
209
{
 
210
    const char *myname = "auto_clnt_close";
171
211
 
172
212
    /*
173
213
     * Sanity check.
174
214
     */
175
215
    if (auto_clnt->vstream == 0)
176
 
        msg_panic("auto_clnt_close: stream is closed");
 
216
        msg_panic("%s: stream is closed", myname);
177
217
 
178
218
    /*
179
219
     * Be sure to disable read and timer events.
180
220
     */
181
221
    if (msg_verbose)
182
 
        msg_info("%s stream disconnect", VSTREAM_PATH(auto_clnt->vstream));
 
222
        msg_info("%s: disconnect %s stream",
 
223
                 myname, VSTREAM_PATH(auto_clnt->vstream));
183
224
    event_disable_readwrite(vstream_fileno(auto_clnt->vstream));
184
225
    event_cancel_timer(auto_clnt_event, (char *) auto_clnt);
185
226
    event_cancel_timer(auto_clnt_ttl_event, (char *) auto_clnt);
219
260
    return (auto_clnt->vstream);
220
261
}
221
262
 
222
 
/* auto_clnt_create - create client stream connection */
 
263
/* auto_clnt_create - create client stream object */
223
264
 
224
 
AUTO_CLNT *auto_clnt_create(int max_idle, int max_ttl,
225
 
                       VSTREAM *(*open_action) (void *), void *context)
 
265
AUTO_CLNT *auto_clnt_create(const char *service, int timeout,
 
266
                                    int max_idle, int max_ttl)
226
267
{
 
268
    const char *myname = "auto_clnt_create";
 
269
    char   *transport = mystrdup(service);
 
270
    char   *endpoint;
227
271
    AUTO_CLNT *auto_clnt;
228
272
 
229
273
    /*
230
274
     * Don't open the stream until the caller needs it.
231
275
     */
 
276
    if ((endpoint = split_at(transport, ':')) == 0
 
277
        || *endpoint == 0 || *transport == 0)
 
278
        msg_fatal("need service transport:endpoint instead of \"%s\"", service);
 
279
    if (msg_verbose)
 
280
        msg_info("%s: transport=%s endpoint=%s", myname, transport, endpoint);
232
281
    auto_clnt = (AUTO_CLNT *) mymalloc(sizeof(*auto_clnt));
233
282
    auto_clnt->vstream = 0;
 
283
    auto_clnt->endpoint = mystrdup(endpoint);
 
284
    auto_clnt->timeout = timeout;
234
285
    auto_clnt->max_idle = max_idle;
235
286
    auto_clnt->max_ttl = max_ttl;
236
 
    auto_clnt->open_action = open_action;
237
 
    auto_clnt->context = context;
 
287
    if (strcmp(transport, "inet") == 0) {
 
288
        auto_clnt->connect = inet_connect;
 
289
    } else if (strcmp(transport, "local") == 0) {
 
290
        auto_clnt->connect = LOCAL_CONNECT;
 
291
    } else if (strcmp(transport, "unix") == 0) {
 
292
        auto_clnt->connect = unix_connect;
 
293
    } else {
 
294
        msg_fatal("invalid transport name: %s in service: %s",
 
295
                  transport, service);
 
296
    }
 
297
    myfree(transport);
238
298
    return (auto_clnt);
239
299
}
240
300
 
 
301
/* auto_clnt_name - return client stream name */
 
302
 
 
303
const char *auto_clnt_name(AUTO_CLNT *auto_clnt)
 
304
{
 
305
    return (auto_clnt->endpoint);
 
306
}
 
307
 
241
308
/* auto_clnt_free - destroy client stream instance */
242
309
 
243
310
void    auto_clnt_free(AUTO_CLNT *auto_clnt)
244
311
{
245
312
    if (auto_clnt->vstream)
246
313
        auto_clnt_close(auto_clnt);
 
314
    myfree(auto_clnt->endpoint);
247
315
    myfree((char *) auto_clnt);
248
316
}