Postfix3.3.1
scache_single.c
[詳解]
1 /*++
2 /* NAME
3 /* scache_single 3
4 /* SUMMARY
5 /* single-item session cache
6 /* SYNOPSIS
7 /* #include <scache.h>
8 /* DESCRIPTION
9 /* SCACHE *scache_single_create()
10 /* DESCRIPTION
11 /* This module implements an in-memory, single-session cache.
12 /*
13 /* scache_single_create() creates a session cache instance
14 /* that stores a single session.
15 /* DIAGNOSTICS
16 /* Fatal error: memory allocation problem;
17 /* panic: internal consistency failure.
18 /* SEE ALSO
19 /* scache(3), generic session cache API
20 /* LICENSE
21 /* .ad
22 /* .fi
23 /* The Secure Mailer license must be distributed with this software.
24 /* AUTHOR(S)
25 /* Wietse Venema
26 /* IBM T.J. Watson Research
27 /* P.O. Box 704
28 /* Yorktown Heights, NY 10598, USA
29 /*--*/
30 
31 /* System library. */
32 
33 #include <sys_defs.h>
34 #include <unistd.h>
35 #include <string.h>
36 
37 /* Utility library. */
38 
39 #include <msg.h>
40 #include <vstring.h>
41 #include <mymalloc.h>
42 #include <events.h>
43 
44 /*#define msg_verbose 1*/
45 
46 /* Global library. */
47 
48 #include <scache.h>
49 
50 /* Application-specific. */
51 
52  /*
53  * Data structure for one saved connection. It is left up to the application
54  * to serialize attributes upon passivation, and to de-serialize them upon
55  * re-activation.
56  */
57 typedef struct {
58  VSTRING *endp_label; /* physical endpoint name */
59  VSTRING *endp_prop; /* endpoint properties, serialized */
60  int fd; /* the session */
62 
63  /*
64  * Data structure for a logical name to physical endpoint binding. It is
65  * left up to the application to serialize attributes upon passivation, and
66  * to de-serialize then upon re-activation.
67  */
68 typedef struct {
69  VSTRING *dest_label; /* logical destination name */
70  VSTRING *dest_prop; /* binding properties, serialized */
71  VSTRING *endp_label; /* physical endpoint name */
73 
74  /*
75  * SCACHE_SINGLE is a derived type from the SCACHE super-class.
76  */
77 typedef struct {
78  SCACHE scache[1]; /* super-class */
79  SCACHE_SINGLE_ENDP endp; /* one cached session */
80  SCACHE_SINGLE_DEST dest; /* one cached binding */
82 
83 static void scache_single_expire_endp(int, void *);
84 static void scache_single_expire_dest(int, void *);
85 
86 #define SCACHE_SINGLE_ENDP_BUSY(sp) (VSTRING_LEN(sp->endp.endp_label) > 0)
87 #define SCACHE_SINGLE_DEST_BUSY(sp) (VSTRING_LEN(sp->dest.dest_label) > 0)
88 
89 #define STR(x) vstring_str(x)
90 
91 /* scache_single_free_endp - discard endpoint */
92 
93 static void scache_single_free_endp(SCACHE_SINGLE *sp)
94 {
95  const char *myname = "scache_single_free_endp";
96 
97  if (msg_verbose)
98  msg_info("%s: %s", myname, STR(sp->endp.endp_label));
99 
100  event_cancel_timer(scache_single_expire_endp, (void *) sp);
101  if (sp->endp.fd >= 0 && close(sp->endp.fd) < 0)
102  msg_warn("close session endpoint %s: %m", STR(sp->endp.endp_label));
107  sp->endp.fd = -1;
108 }
109 
110 /* scache_single_expire_endp - discard expired session */
111 
112 static void scache_single_expire_endp(int unused_event, void *context)
113 {
114  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) context;
115 
116  scache_single_free_endp(sp);
117 }
118 
119 /* scache_single_save_endp - save endpoint */
120 
121 static void scache_single_save_endp(SCACHE *scache, int endp_ttl,
122  const char *endp_label,
123  const char *endp_prop, int fd)
124 {
125  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
126  const char *myname = "scache_single_save_endp";
127 
128  if (endp_ttl <= 0)
129  msg_panic("%s: bad endp_ttl: %d", myname, endp_ttl);
130 
131  if (SCACHE_SINGLE_ENDP_BUSY(sp))
132  scache_single_free_endp(sp); /* dump the cached fd */
133 
134  vstring_strcpy(sp->endp.endp_label, endp_label);
135  vstring_strcpy(sp->endp.endp_prop, endp_prop);
136  sp->endp.fd = fd;
137  event_request_timer(scache_single_expire_endp, (void *) sp, endp_ttl);
138 
139  if (msg_verbose)
140  msg_info("%s: %s fd=%d", myname, endp_label, fd);
141 }
142 
143 /* scache_single_find_endp - look up cached session */
144 
145 static int scache_single_find_endp(SCACHE *scache, const char *endp_label,
146  VSTRING *endp_prop)
147 {
148  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
149  const char *myname = "scache_single_find_endp";
150  int fd;
151 
152  if (!SCACHE_SINGLE_ENDP_BUSY(sp)) {
153  if (msg_verbose)
154  msg_info("%s: no endpoint cache: %s", myname, endp_label);
155  return (-1);
156  }
157  if (strcmp(STR(sp->endp.endp_label), endp_label) == 0) {
158  vstring_strcpy(endp_prop, STR(sp->endp.endp_prop));
159  fd = sp->endp.fd;
160  sp->endp.fd = -1;
161  scache_single_free_endp(sp);
162  if (msg_verbose)
163  msg_info("%s: found: %s fd=%d", myname, endp_label, fd);
164  return (fd);
165  }
166  if (msg_verbose)
167  msg_info("%s: not found: %s", myname, endp_label);
168  return (-1);
169 }
170 
171 /* scache_single_free_dest - discard destination/endpoint association */
172 
173 static void scache_single_free_dest(SCACHE_SINGLE *sp)
174 {
175  const char *myname = "scache_single_free_dest";
176 
177  if (msg_verbose)
178  msg_info("%s: %s -> %s", myname, STR(sp->dest.dest_label),
179  STR(sp->dest.endp_label));
180 
181  event_cancel_timer(scache_single_expire_dest, (void *) sp);
188 }
189 
190 /* scache_single_expire_dest - discard expired destination/endpoint binding */
191 
192 static void scache_single_expire_dest(int unused_event, void *context)
193 {
194  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) context;
195 
196  scache_single_free_dest(sp);
197 }
198 
199 /* scache_single_save_dest - create destination/endpoint association */
200 
201 static void scache_single_save_dest(SCACHE *scache, int dest_ttl,
202  const char *dest_label,
203  const char *dest_prop,
204  const char *endp_label)
205 {
206  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
207  const char *myname = "scache_single_save_dest";
208  int refresh;
209 
210  if (dest_ttl <= 0)
211  msg_panic("%s: bad dest_ttl: %d", myname, dest_ttl);
212 
213  /*
214  * Optimize: reset timer only, if nothing has changed.
215  */
216  refresh =
218  && strcmp(STR(sp->dest.dest_label), dest_label) == 0
219  && strcmp(STR(sp->dest.dest_prop), dest_prop) == 0
220  && strcmp(STR(sp->dest.endp_label), endp_label) == 0);
221 
222  if (refresh == 0) {
223  vstring_strcpy(sp->dest.dest_label, dest_label);
224  vstring_strcpy(sp->dest.dest_prop, dest_prop);
225  vstring_strcpy(sp->dest.endp_label, endp_label);
226  }
227  event_request_timer(scache_single_expire_dest, (void *) sp, dest_ttl);
228 
229  if (msg_verbose)
230  msg_info("%s: %s -> %s%s", myname, dest_label, endp_label,
231  refresh ? " (refreshed)" : "");
232 }
233 
234 /* scache_single_find_dest - look up cached session */
235 
236 static int scache_single_find_dest(SCACHE *scache, const char *dest_label,
237  VSTRING *dest_prop, VSTRING *endp_prop)
238 {
239  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
240  const char *myname = "scache_single_find_dest";
241  int fd;
242 
243  if (!SCACHE_SINGLE_DEST_BUSY(sp)) {
244  if (msg_verbose)
245  msg_info("%s: no destination cache: %s", myname, dest_label);
246  return (-1);
247  }
248  if (strcmp(STR(sp->dest.dest_label), dest_label) == 0) {
249  if (msg_verbose)
250  msg_info("%s: found: %s", myname, dest_label);
251  if ((fd = scache_single_find_endp(scache, STR(sp->dest.endp_label), endp_prop)) >= 0) {
252  vstring_strcpy(dest_prop, STR(sp->dest.dest_prop));
253  return (fd);
254  }
255  }
256  if (msg_verbose)
257  msg_info("%s: not found: %s", myname, dest_label);
258  return (-1);
259 }
260 
261 /* scache_single_size - size of single-element cache :-) */
262 
263 static void scache_single_size(SCACHE *scache, SCACHE_SIZE *size)
264 {
265  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
266 
267  size->dest_count = (!SCACHE_SINGLE_DEST_BUSY(sp) ? 0 : 1);
268  size->endp_count = (!SCACHE_SINGLE_ENDP_BUSY(sp) ? 0 : 1);
269  size->sess_count = (sp->endp.fd < 0 ? 0 : 1);
270 }
271 
272 /* scache_single_free - destroy single-element cache object */
273 
274 static void scache_single_free(SCACHE *scache)
275 {
276  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
277 
280  if (sp->endp.fd >= 0)
281  close(sp->endp.fd);
282 
286 
287  myfree((void *) sp);
288 }
289 
290 /* scache_single_create - initialize */
291 
293 {
294  SCACHE_SINGLE *sp = (SCACHE_SINGLE *) mymalloc(sizeof(*sp));
295 
296  sp->scache->save_endp = scache_single_save_endp;
297  sp->scache->find_endp = scache_single_find_endp;
298  sp->scache->save_dest = scache_single_save_dest;
299  sp->scache->find_dest = scache_single_find_dest;
300  sp->scache->size = scache_single_size;
301  sp->scache->free = scache_single_free;
302 
303  sp->endp.endp_label = vstring_alloc(10);
304  sp->endp.endp_prop = vstring_alloc(10);
305  sp->endp.fd = -1;
306 
307  sp->dest.dest_label = vstring_alloc(10);
308  sp->dest.dest_prop = vstring_alloc(10);
309  sp->dest.endp_label = vstring_alloc(10);
310 
311  return (sp->scache);
312 }
SCACHE scache[1]
Definition: scache_single.c:78
int msg_verbose
Definition: msg.c:177
#define SCACHE_SINGLE_DEST_BUSY(sp)
Definition: scache_single.c:87
void myfree(void *ptr)
Definition: mymalloc.c:207
int dest_count
Definition: scache.h:94
void(* size)(struct SCACHE *, SCACHE_SIZE *)
Definition: scache.h:108
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
VSTRING * dest_label
Definition: scache_single.c:69
#define SCACHE_SINGLE_ENDP_BUSY(sp)
Definition: scache_single.c:86
SCACHE_SINGLE_ENDP endp
Definition: scache_single.c:79
SCACHE_SINGLE_DEST dest
Definition: scache_single.c:80
SCACHE * scache_single_create(void)
SCACHE_FIND_DEST_FN find_dest
Definition: scache.h:107
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
VSTRING * endp_label
Definition: scache_single.c:58
int sess_count
Definition: scache.h:96
#define VSTRING_RESET(vp)
Definition: vstring.h:77
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
SCACHE_SAVE_ENDP_FN save_endp
Definition: scache.h:104
SCACHE_SAVE_DEST_FN save_dest
Definition: scache.h:106
#define STR(x)
Definition: scache_single.c:89
int endp_count
Definition: scache.h:95
SCACHE_FIND_ENDP_FN find_endp
Definition: scache.h:105
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
time_t event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
Definition: events.c:894
Definition: scache.h:103
void(* free)(struct SCACHE *)
Definition: scache.h:109
VSTRING * endp_label
Definition: scache_single.c:71
int event_cancel_timer(EVENT_NOTIFY_TIME_FN callback, void *context)
Definition: events.c:965
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
void msg_info(const char *fmt,...)
Definition: msg.c:199