7 /* single-item session cache
11 /* SCACHE *scache_single_create()
13 /* This module implements an in-memory, single-session cache.
15 /* scache_single_create() creates a session cache instance
16 /* that stores a single session.
18 /* Fatal error: memory allocation problem;
19 /* panic: internal consistency failure.
21 /* scache(3), generic session cache API
25 /* The Secure Mailer license must be distributed with this software.
28 /* IBM T.J. Watson Research
30 /* Yorktown Heights, NY 10598, USA
39 /* Utility library. */
46 /*#define msg_verbose 1*/
52 /* Application-specific. */
55 * Data structure for one saved connection. It is left up to the application
56 * to serialize attributes upon passivation, and to de-serialize them upon
60 VSTRING
*endp_label
; /* physical endpoint name */
61 VSTRING
*endp_prop
; /* endpoint properties, serialized */
62 int fd
; /* the session */
66 * Data structure for a logical name to physical endpoint binding. It is
67 * left up to the application to serialize attributes upon passivation, and
68 * to de-serialize then upon re-activation.
71 VSTRING
*dest_label
; /* logical destination name */
72 VSTRING
*dest_prop
; /* binding properties, serialized */
73 VSTRING
*endp_label
; /* physical endpoint name */
77 * SCACHE_SINGLE is a derived type from the SCACHE super-class.
80 SCACHE scache
[1]; /* super-class */
81 SCACHE_SINGLE_ENDP endp
; /* one cached session */
82 SCACHE_SINGLE_DEST dest
; /* one cached binding */
85 static void scache_single_expire_endp(int, char *);
86 static void scache_single_expire_dest(int, char *);
88 #define SCACHE_SINGLE_ENDP_BUSY(sp) (VSTRING_LEN(sp->endp.endp_label) > 0)
89 #define SCACHE_SINGLE_DEST_BUSY(sp) (VSTRING_LEN(sp->dest.dest_label) > 0)
91 #define STR(x) vstring_str(x)
93 /* scache_single_free_endp - discard endpoint */
95 static void scache_single_free_endp(SCACHE_SINGLE
*sp
)
97 const char *myname
= "scache_single_free_endp";
100 msg_info("%s: %s", myname
, STR(sp
->endp
.endp_label
));
102 event_cancel_timer(scache_single_expire_endp
, (char *) sp
);
103 if (sp
->endp
.fd
>= 0 && close(sp
->endp
.fd
) < 0)
104 msg_warn("close session endpoint %s: %m", STR(sp
->endp
.endp_label
));
105 VSTRING_RESET(sp
->endp
.endp_label
);
106 VSTRING_TERMINATE(sp
->endp
.endp_label
);
107 VSTRING_RESET(sp
->endp
.endp_prop
);
108 VSTRING_TERMINATE(sp
->endp
.endp_prop
);
112 /* scache_single_expire_endp - discard expired session */
114 static void scache_single_expire_endp(int unused_event
, char *context
)
116 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) context
;
118 scache_single_free_endp(sp
);
121 /* scache_single_save_endp - save endpoint */
123 static void scache_single_save_endp(SCACHE
*scache
, int endp_ttl
,
124 const char *endp_label
,
125 const char *endp_prop
, int fd
)
127 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) scache
;
128 const char *myname
= "scache_single_save_endp";
131 msg_panic("%s: bad endp_ttl: %d", myname
, endp_ttl
);
133 if (SCACHE_SINGLE_ENDP_BUSY(sp
))
134 scache_single_free_endp(sp
); /* dump the cached fd */
136 vstring_strcpy(sp
->endp
.endp_label
, endp_label
);
137 vstring_strcpy(sp
->endp
.endp_prop
, endp_prop
);
139 event_request_timer(scache_single_expire_endp
, (char *) sp
, endp_ttl
);
142 msg_info("%s: %s fd=%d", myname
, endp_label
, fd
);
145 /* scache_single_find_endp - look up cached session */
147 static int scache_single_find_endp(SCACHE
*scache
, const char *endp_label
,
150 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) scache
;
151 const char *myname
= "scache_single_find_endp";
154 if (!SCACHE_SINGLE_ENDP_BUSY(sp
)) {
156 msg_info("%s: no endpoint cache: %s", myname
, endp_label
);
159 if (strcmp(STR(sp
->endp
.endp_label
), endp_label
) == 0) {
160 vstring_strcpy(endp_prop
, STR(sp
->endp
.endp_prop
));
163 scache_single_free_endp(sp
);
165 msg_info("%s: found: %s fd=%d", myname
, endp_label
, fd
);
169 msg_info("%s: not found: %s", myname
, endp_label
);
173 /* scache_single_free_dest - discard destination/endpoint association */
175 static void scache_single_free_dest(SCACHE_SINGLE
*sp
)
177 const char *myname
= "scache_single_free_dest";
180 msg_info("%s: %s -> %s", myname
, STR(sp
->dest
.dest_label
),
181 STR(sp
->dest
.endp_label
));
183 event_cancel_timer(scache_single_expire_dest
, (char *) sp
);
184 VSTRING_RESET(sp
->dest
.dest_label
);
185 VSTRING_TERMINATE(sp
->dest
.dest_label
);
186 VSTRING_RESET(sp
->dest
.dest_prop
);
187 VSTRING_TERMINATE(sp
->dest
.dest_prop
);
188 VSTRING_RESET(sp
->dest
.endp_label
);
189 VSTRING_TERMINATE(sp
->dest
.endp_label
);
192 /* scache_single_expire_dest - discard expired destination/endpoint binding */
194 static void scache_single_expire_dest(int unused_event
, char *context
)
196 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) context
;
198 scache_single_free_dest(sp
);
201 /* scache_single_save_dest - create destination/endpoint association */
203 static void scache_single_save_dest(SCACHE
*scache
, int dest_ttl
,
204 const char *dest_label
,
205 const char *dest_prop
,
206 const char *endp_label
)
208 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) scache
;
209 const char *myname
= "scache_single_save_dest";
213 msg_panic("%s: bad dest_ttl: %d", myname
, dest_ttl
);
216 * Optimize: reset timer only, if nothing has changed.
219 (SCACHE_SINGLE_DEST_BUSY(sp
)
220 && strcmp(STR(sp
->dest
.dest_label
), dest_label
) == 0
221 && strcmp(STR(sp
->dest
.dest_prop
), dest_prop
) == 0
222 && strcmp(STR(sp
->dest
.endp_label
), endp_label
) == 0);
225 vstring_strcpy(sp
->dest
.dest_label
, dest_label
);
226 vstring_strcpy(sp
->dest
.dest_prop
, dest_prop
);
227 vstring_strcpy(sp
->dest
.endp_label
, endp_label
);
229 event_request_timer(scache_single_expire_dest
, (char *) sp
, dest_ttl
);
232 msg_info("%s: %s -> %s%s", myname
, dest_label
, endp_label
,
233 refresh
? " (refreshed)" : "");
236 /* scache_single_find_dest - look up cached session */
238 static int scache_single_find_dest(SCACHE
*scache
, const char *dest_label
,
239 VSTRING
*dest_prop
, VSTRING
*endp_prop
)
241 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) scache
;
242 const char *myname
= "scache_single_find_dest";
245 if (!SCACHE_SINGLE_DEST_BUSY(sp
)) {
247 msg_info("%s: no destination cache: %s", myname
, dest_label
);
250 if (strcmp(STR(sp
->dest
.dest_label
), dest_label
) == 0) {
252 msg_info("%s: found: %s", myname
, dest_label
);
253 if ((fd
= scache_single_find_endp(scache
, STR(sp
->dest
.endp_label
), endp_prop
)) >= 0) {
254 vstring_strcpy(dest_prop
, STR(sp
->dest
.dest_prop
));
259 msg_info("%s: not found: %s", myname
, dest_label
);
263 /* scache_single_size - size of single-element cache :-) */
265 static void scache_single_size(SCACHE
*scache
, SCACHE_SIZE
*size
)
267 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) scache
;
269 size
->dest_count
= (!SCACHE_SINGLE_DEST_BUSY(sp
) ? 0 : 1);
270 size
->endp_count
= (!SCACHE_SINGLE_ENDP_BUSY(sp
) ? 0 : 1);
271 size
->sess_count
= (sp
->endp
.fd
< 0 ? 0 : 1);
274 /* scache_single_free - destroy single-element cache object */
276 static void scache_single_free(SCACHE
*scache
)
278 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) scache
;
280 vstring_free(sp
->endp
.endp_label
);
281 vstring_free(sp
->endp
.endp_prop
);
282 if (sp
->endp
.fd
>= 0)
285 vstring_free(sp
->dest
.dest_label
);
286 vstring_free(sp
->dest
.dest_prop
);
287 vstring_free(sp
->dest
.endp_label
);
292 /* scache_single_create - initialize */
294 SCACHE
*scache_single_create(void)
296 SCACHE_SINGLE
*sp
= (SCACHE_SINGLE
*) mymalloc(sizeof(*sp
));
298 sp
->scache
->save_endp
= scache_single_save_endp
;
299 sp
->scache
->find_endp
= scache_single_find_endp
;
300 sp
->scache
->save_dest
= scache_single_save_dest
;
301 sp
->scache
->find_dest
= scache_single_find_dest
;
302 sp
->scache
->size
= scache_single_size
;
303 sp
->scache
->free
= scache_single_free
;
305 sp
->endp
.endp_label
= vstring_alloc(10);
306 sp
->endp
.endp_prop
= vstring_alloc(10);
309 sp
->dest
.dest_label
= vstring_alloc(10);
310 sp
->dest
.dest_prop
= vstring_alloc(10);
311 sp
->dest
.endp_label
= vstring_alloc(10);