7
7
/* #include <auto_clnt.h>
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;
12
/* VSTREAM *(open_action)(void *context)
15
15
/* VSTREAM *auto_clnt_access(auto_clnt)
16
16
/* AUTO_CLNT *auto_clnt;
26
29
/* that disconnect after a configurable time to live,
27
30
/* and that transparently handle most server-initiated disconnects.
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.
29
37
/* auto_clnt_create() instantiates a client endpoint.
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.
46
/* auto_clnt_name() returns the name of the specified client endpoint.
38
48
/* auto_clnt_free() destroys of the specified client endpoint.
52
/* The service argument specifies "transport:servername" where
53
/* transport is currently limited to one of the following:
56
/* servername has the form "host:port".
58
/* servername has the form "private/servicename" or
59
/* "public/servicename".
62
/* The time limit for sending, receiving, or for connecting
63
/* to a server. Specify a value <=0 to disable the time limit.
42
/* Idle time after which the client disconnects. Specify 0 to disable
65
/* Idle time after which the client disconnects. Specify 0 to
45
68
/* Upper bound on the time that a connection is allowed to persist.
46
69
/* Specify 0 to disable the limit.
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 */
93
120
static void auto_clnt_close(AUTO_CLNT *);
148
177
* connection is not idle. This is to prevent one client from clinging on
149
178
* to a server forever.
152
auto_clnt->open_action(auto_clnt->context);
180
fd = auto_clnt->connect(auto_clnt->endpoint, BLOCKING, auto_clnt->timeout);
182
msg_warn("connect to %s: %m", auto_clnt->endpoint);
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,
154
193
if (auto_clnt->vstream != 0) {
155
194
close_on_exec(vstream_fileno(auto_clnt->vstream), CLOSE_ON_EXEC);
169
208
static void auto_clnt_close(AUTO_CLNT *auto_clnt)
210
const char *myname = "auto_clnt_close";
175
215
if (auto_clnt->vstream == 0)
176
msg_panic("auto_clnt_close: stream is closed");
216
msg_panic("%s: stream is closed", myname);
179
219
* Be sure to disable read and timer events.
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);
222
/* auto_clnt_create - create client stream connection */
263
/* auto_clnt_create - create client stream object */
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)
268
const char *myname = "auto_clnt_create";
269
char *transport = mystrdup(service);
227
271
AUTO_CLNT *auto_clnt;
230
274
* Don't open the stream until the caller needs it.
276
if ((endpoint = split_at(transport, ':')) == 0
277
|| *endpoint == 0 || *transport == 0)
278
msg_fatal("need service transport:endpoint instead of \"%s\"", service);
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;
294
msg_fatal("invalid transport name: %s in service: %s",
238
298
return (auto_clnt);
301
/* auto_clnt_name - return client stream name */
303
const char *auto_clnt_name(AUTO_CLNT *auto_clnt)
305
return (auto_clnt->endpoint);
241
308
/* auto_clnt_free - destroy client stream instance */
243
310
void auto_clnt_free(AUTO_CLNT *auto_clnt)
245
312
if (auto_clnt->vstream)
246
313
auto_clnt_close(auto_clnt);
314
myfree(auto_clnt->endpoint);
247
315
myfree((char *) auto_clnt);