1131826Sharti/* 2131826Sharti* Copyright (c) 2004 3131826Sharti* Hartmut Brandt 4131826Sharti* All rights reserved. 5131826Sharti* 6131826Sharti* Author: Harti Brandt <harti@freebsd.org> 7131826Sharti* 8131826Sharti* Redistribution of this software and documentation and use in source and 9131826Sharti* binary forms, with or without modification, are permitted provided that 10131826Sharti* the following conditions are met: 11131826Sharti* 12131826Sharti* 1. Redistributions of source code or documentation must retain the above 13131826Sharti* copyright notice, this list of conditions and the following disclaimer. 14131826Sharti* 2. Redistributions in binary form must reproduce the above copyright 15131826Sharti* notice, this list of conditions and the following disclaimer in the 16131826Sharti* documentation and/or other materials provided with the distribution. 17131826Sharti* 18131826Sharti* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR 19131826Sharti* AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 20131826Sharti* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21131826Sharti* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22131826Sharti* THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23131826Sharti* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24131826Sharti* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 25131826Sharti* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26131826Sharti* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27131826Sharti* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28131826Sharti* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29131826Sharti* 30131826Sharti* $Begemot: libunimsg/netnatm/api/cc_sig.c,v 1.1 2004/07/08 08:21:54 brandt Exp $ 31131826Sharti* 32131826Sharti* ATM API as defined per af-saa-0108 33131826Sharti* 34131826Sharti* Generic signal handling 35131826Sharti*/ 36131826Sharti#include <netnatm/unimsg.h> 37131826Sharti#include <netnatm/msg/unistruct.h> 38131826Sharti#include <netnatm/msg/unimsglib.h> 39131826Sharti#include <netnatm/api/unisap.h> 40131826Sharti#include <netnatm/sig/unidef.h> 41131826Sharti#include <netnatm/api/atmapi.h> 42131826Sharti#include <netnatm/api/ccatm.h> 43131826Sharti#include <netnatm/api/ccpriv.h> 44131826Sharti 45131826Shartienum { 46131826Sharti SIG_USER, 47131826Sharti SIG_CONN, 48131826Sharti}; 49131826Sharti 50131826Shartistruct ccsig { 51131826Sharti u_char type; /* type of target */ 52131826Sharti u_char has_msg; /* arg1 is a message */ 53131826Sharti void *target; /* target instance */ 54131826Sharti u_int sig; /* signal */ 55131826Sharti void *arg1; /* argument */ 56131826Sharti u_int arg2; /* argument */ 57131826Sharti TAILQ_ENTRY(ccsig) link; 58131826Sharti}; 59131826Sharti 60131826Sharti#if defined(__GNUC__) && __GNUC__ < 3 61131826Sharti#define cc_sig_log(CC, FMT, ARGS...) do { \ 62131826Sharti if ((CC)->log & CCLOG_SIGS) \ 63131826Sharti (CC)->funcs->log("%s: " FMT, __FUNCTION__ , ## ARGS); \ 64131826Sharti } while (0) 65131826Sharti#else 66131826Sharti#define cc_sig_log(CC, FMT, ...) do { \ 67131826Sharti if ((CC)->log & CCLOG_SIGS) \ 68131826Sharti (CC)->funcs->log("%s: " FMT, __func__, __VA_ARGS__); \ 69131826Sharti } while (0) 70131826Sharti#endif 71131826Sharti 72131826Sharti 73131826Sharticonst char *const cc_user_sigtab[] = { 74131826Sharti#define DEF(N) [USER_SIG_##N] = #N, 75131826ShartiUSER_SIGS 76131826Sharti#undef DEF 77131826Sharti}; 78131826Sharti 79131826Sharticonst char *const cc_conn_sigtab[] = { 80131826Sharti#define DEF(N) [CONN_SIG_##N] = #N, 81131826ShartiCONN_SIGS 82131826Sharti#undef DEF 83131826Sharti}; 84131826Sharti 85131826Sharti 86131826Sharti/* 87131826Sharti * Allocate and populate a signal 88131826Sharti */ 89131826Shartistatic /* __inline */ struct ccsig * 90131826Shartisig_alloc(struct ccdata *cc, u_int type, void *target, u_int has_msg, 91131826Sharti u_int sig, void *arg1, u_int arg2) 92131826Sharti{ 93131826Sharti struct ccsig *s; 94131826Sharti 95131826Sharti if ((s = TAILQ_FIRST(&cc->free_sigs)) == NULL) { 96131826Sharti s = CCZALLOC(sizeof(struct ccsig)); 97131826Sharti if (s == NULL) { 98131826Sharti cc_log(cc, "signal %u/%u lost - ENOMEM", type, sig); 99131826Sharti return (NULL); 100131826Sharti } 101131826Sharti } else 102131826Sharti TAILQ_REMOVE(&cc->free_sigs, s, link); 103131826Sharti 104131826Sharti s->type = type; 105131826Sharti s->has_msg = has_msg; 106131826Sharti s->target = target; 107131826Sharti s->sig = sig; 108131826Sharti s->arg1 = arg1; 109131826Sharti s->arg2 = arg2; 110131826Sharti 111131826Sharti return (s); 112131826Sharti} 113131826Sharti 114131826Sharti/* 115131826Sharti * Queue a signal to this user 116131826Sharti */ 117131826Shartiint 118131826Sharticc_user_sig(struct ccuser *user, enum user_sig sig, void *arg1, u_int arg2) 119131826Sharti{ 120131826Sharti struct ccsig *s; 121131826Sharti 122131826Sharti s = sig_alloc(user->cc, SIG_USER, user, 0, sig, arg1, arg2); 123131826Sharti if (s == NULL) 124131826Sharti return (ENOMEM); 125131826Sharti TAILQ_INSERT_TAIL(&user->cc->sigs, s, link); 126131826Sharti cc_sig_log(user->cc, "queuing sig %s to user %p", cc_user_sigtab[sig], 127131826Sharti user); 128131826Sharti return (0); 129131826Sharti} 130131826Sharti 131131826Sharti/* Queue a signal with message to this user */ 132131826Shartiint 133131826Sharticc_user_sig_msg(struct ccuser *user, enum user_sig sig, struct uni_msg *msg) 134131826Sharti{ 135131826Sharti struct ccsig *s; 136131826Sharti 137131826Sharti s = sig_alloc(user->cc, SIG_USER, user, msg != NULL, sig, msg, 0); 138131826Sharti if (s == NULL) 139131826Sharti return (ENOMEM); 140131826Sharti TAILQ_INSERT_TAIL(&user->cc->sigs, s, link); 141131826Sharti cc_sig_log(user->cc, "queuing sig %s to user %p", cc_user_sigtab[sig], 142131826Sharti user); 143131826Sharti return (0); 144131826Sharti} 145131826Sharti 146131826Sharti/* 147131826Sharti * Signal to connection 148131826Sharti */ 149131826Shartistatic int 150131826Shartisig_conn(struct ccconn *conn, enum conn_sig sig, u_int has_msg, void *arg) 151131826Sharti{ 152131826Sharti struct ccsig *s; 153131826Sharti const struct ccreq *r = NULL; 154131826Sharti 155131826Sharti s = sig_alloc(conn->cc, SIG_CONN, conn, has_msg, sig, arg, 0); 156131826Sharti if (s == NULL) 157131826Sharti return (ENOMEM); 158131826Sharti 159131826Sharti if (conn->port != NULL) { 160131826Sharti /* argh */ 161131826Sharti TAILQ_FOREACH(r, &conn->port->cookies, link) 162131826Sharti if (r->conn == conn) 163131826Sharti break; 164131826Sharti } 165131826Sharti if (r == NULL) { 166131826Sharti TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link); 167131826Sharti cc_sig_log(conn->cc, "queuing sig %s to conn %p", 168131826Sharti cc_conn_sigtab[sig], conn); 169131826Sharti } else { 170131826Sharti TAILQ_INSERT_TAIL(&conn->cc->def_sigs, s, link); 171131826Sharti cc_sig_log(conn->cc, "queuing defered sig %s to conn %p", 172131826Sharti cc_conn_sigtab[sig], conn); 173131826Sharti } 174131826Sharti return (0); 175131826Sharti} 176131826Sharti 177131826Sharti/* 178131826Sharti * Queue a signal to a connection. 179131826Sharti */ 180131826Shartiint 181131826Sharticc_conn_sig(struct ccconn *conn, enum conn_sig sig, void *arg1) 182131826Sharti{ 183131826Sharti 184131826Sharti return (sig_conn(conn, sig, 0, arg1)); 185131826Sharti} 186131826Sharti 187131826Sharti/* 188131826Sharti * signal with message to connection 189131826Sharti */ 190131826Shartiint 191131826Sharticc_conn_sig_msg(struct ccconn *conn, enum conn_sig sig, struct uni_msg *msg) 192131826Sharti{ 193131826Sharti 194131826Sharti return (sig_conn(conn, sig, (msg != NULL), msg)); 195131826Sharti} 196131826Shartiint 197131826Sharticc_conn_sig_msg_nodef(struct ccconn *conn, enum conn_sig sig, 198131826Sharti struct uni_msg *msg) 199131826Sharti{ 200131826Sharti struct ccsig *s; 201131826Sharti 202131826Sharti s = sig_alloc(conn->cc, SIG_CONN, conn, (msg != NULL), sig, msg, 0); 203131826Sharti if (s == NULL) 204131826Sharti return (ENOMEM); 205131826Sharti 206131826Sharti TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link); 207131826Sharti cc_sig_log(conn->cc, "queuing sig %s to conn %p", 208131826Sharti cc_conn_sigtab[sig], conn); 209131826Sharti 210131826Sharti return (0); 211131826Sharti} 212131826Sharti 213131826Sharti/* 214131826Sharti * Queue a response signal to a connection. 215131826Sharti */ 216131826Shartiint 217131826Sharticc_conn_resp(struct ccconn *conn, enum conn_sig sig, u_int cookie __unused, 218131826Sharti u_int reason, u_int state) 219131826Sharti{ 220131826Sharti struct ccsig *s, *s1, *s2; 221131826Sharti 222131826Sharti s = sig_alloc(conn->cc, SIG_CONN, conn, 0, sig, NULL, 223131826Sharti ((reason & 0xffff) << 16) | (state & 0xffff)); 224131826Sharti if (s == NULL) 225131826Sharti return (ENOMEM); 226131826Sharti 227131826Sharti TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link); 228131826Sharti 229131826Sharti cc_sig_log(conn->cc, "queuing response %s to conn %p", 230131826Sharti cc_conn_sigtab[sig], conn); 231131826Sharti 232131826Sharti s1 = TAILQ_FIRST(&conn->cc->def_sigs); 233131826Sharti while (s1 != NULL) { 234131826Sharti s2 = TAILQ_NEXT(s1, link); 235131826Sharti if (s1->type == SIG_CONN && s1->target == conn) { 236131826Sharti TAILQ_REMOVE(&conn->cc->def_sigs, s1, link); 237131826Sharti TAILQ_INSERT_AFTER(&conn->cc->sigs, s, s1, link); 238131826Sharti cc_sig_log(conn->cc, "undefering sig %s to conn %p", 239131826Sharti cc_conn_sigtab[s1->sig], conn); 240131826Sharti s = s1; 241131826Sharti } 242131826Sharti s1 = s2; 243131826Sharti } 244131826Sharti 245131826Sharti return (0); 246131826Sharti} 247131826Sharti 248131826Sharti/* 249131826Sharti * Flush all signals to a given target from both queues 250131826Sharti */ 251131826Shartistatic /* __inline */ void 252131826Shartisig_flush(struct ccdata *cc, u_int type, void *target) 253131826Sharti{ 254131826Sharti struct ccsig *s, *s1; 255131826Sharti 256131826Sharti s = TAILQ_FIRST(&cc->sigs); 257131826Sharti while (s != NULL) { 258131826Sharti s1 = TAILQ_NEXT(s, link); 259131826Sharti if (s->type == type && s->target == target) { 260131826Sharti if (s->has_msg) 261131826Sharti uni_msg_destroy((struct uni_msg *)s->arg1); 262131826Sharti TAILQ_REMOVE(&cc->sigs, s, link); 263131826Sharti TAILQ_INSERT_HEAD(&cc->free_sigs, s, link); 264131826Sharti } 265131826Sharti s = s1; 266131826Sharti } 267131826Sharti 268131826Sharti s = TAILQ_FIRST(&cc->def_sigs); 269131826Sharti while (s != NULL) { 270131826Sharti s1 = TAILQ_NEXT(s, link); 271131826Sharti if (s->type == type && s->target == target) { 272131826Sharti if (s->has_msg) 273131826Sharti uni_msg_destroy((struct uni_msg *)s->arg1); 274131826Sharti TAILQ_REMOVE(&cc->def_sigs, s, link); 275131826Sharti TAILQ_INSERT_HEAD(&cc->free_sigs, s, link); 276131826Sharti } 277131826Sharti s = s1; 278131826Sharti } 279131826Sharti} 280131826Sharti 281131826Sharti/* 282131826Sharti * Flush all signals to this user 283131826Sharti */ 284131826Shartivoid 285131826Sharticc_user_sig_flush(struct ccuser *user) 286131826Sharti{ 287131826Sharti 288131826Sharti cc_sig_log(user->cc, "flushing signals to user %p", user); 289131826Sharti sig_flush(user->cc, SIG_USER, user); 290131826Sharti} 291131826Sharti 292131826Sharti/* 293131826Sharti * Flush all signals to this connection 294131826Sharti */ 295131826Shartivoid 296131826Sharticc_conn_sig_flush(struct ccconn *conn) 297131826Sharti{ 298131826Sharti 299131826Sharti cc_sig_log(conn->cc, "flushing signals to conn %p", conn); 300131826Sharti sig_flush(conn->cc, SIG_CONN, conn); 301131826Sharti} 302131826Sharti 303131826Sharti/* 304131826Sharti * Do the work 305131826Sharti */ 306131826Shartivoid 307131826Sharticc_work(struct ccdata *cc) 308131826Sharti{ 309131826Sharti struct ccsig *s; 310131826Sharti 311131826Sharti cc_sig_log(cc, "start %s", "work"); 312131826Sharti while ((s = TAILQ_FIRST(&cc->sigs)) != NULL) { 313131826Sharti TAILQ_REMOVE(&cc->sigs, s, link); 314131826Sharti if (s->type == SIG_USER) 315131826Sharti cc_user_sig_handle(s->target, s->sig, s->arg1, s->arg2); 316131826Sharti else { 317131826Sharti cc_conn_sig_handle(s->target, s->sig, s->arg1, s->arg2); 318131826Sharti if (s->has_msg) 319131826Sharti uni_msg_destroy(s->arg1); 320131826Sharti } 321131826Sharti TAILQ_INSERT_HEAD(&cc->free_sigs, s, link); 322131826Sharti } 323131826Sharti cc_sig_log(cc, "end %s", "work"); 324131826Sharti} 325131826Sharti 326131826Sharti/* 327131826Sharti * flush all signals 328131826Sharti */ 329131826Shartivoid 330131826Sharticc_sig_flush_all(struct ccdata *cc) 331131826Sharti{ 332131826Sharti struct ccsig *s; 333131826Sharti 334131826Sharti while ((s = TAILQ_FIRST(&cc->sigs)) != NULL) { 335131826Sharti if (s->has_msg) 336131826Sharti uni_msg_destroy((struct uni_msg *)s->arg1); 337131826Sharti TAILQ_REMOVE(&cc->sigs, s, link); 338131826Sharti CCFREE(s); 339131826Sharti } 340131826Sharti while ((s = TAILQ_FIRST(&cc->def_sigs)) != NULL) { 341131826Sharti if (s->has_msg) 342131826Sharti uni_msg_destroy((struct uni_msg *)s->arg1); 343131826Sharti TAILQ_REMOVE(&cc->def_sigs, s, link); 344131826Sharti CCFREE(s); 345131826Sharti } 346131826Sharti while ((s = TAILQ_FIRST(&cc->free_sigs)) != NULL) { 347131826Sharti TAILQ_REMOVE(&cc->free_sigs, s, link); 348131826Sharti CCFREE(s); 349131826Sharti } 350131826Sharti} 351