2 * Copyright (c) 1996-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * Author: Hartmut Brandt <harti@freebsd.org>
29 * $Begemot: libunimsg/netnatm/sig/unipriv.h,v 1.17 2004/07/08 08:22:25 brandt Exp $
38 #include <netgraph/atm/uni/ng_uni_cust.h>
48 CU_STAT0, /* AAL connection released */
49 CU_STAT1, /* awaiting establish */
50 CU_STAT2, /* awaiting release */
51 CU_STAT3, /* AAL connection established */
57 #define DEF_COORD_SIGS \
58 DEF_PRIV_SIG(O_SAAL_ESTABLISH_indication, SAAL) \
59 DEF_PRIV_SIG(O_SAAL_ESTABLISH_confirm, SAAL) \
60 DEF_PRIV_SIG(O_SAAL_RELEASE_indication, SAAL) \
61 DEF_PRIV_SIG(O_SAAL_RELEASE_confirm, SAAL) \
62 DEF_PRIV_SIG(O_SAAL_DATA_indication, SAAL) \
63 DEF_PRIV_SIG(O_SAAL_UDATA_indication, SAAL) \
64 DEF_PRIV_SIG(O_T309, Coord) \
65 DEF_PRIV_SIG(O_DATA, Coord) \
66 DEF_PRIV_SIG(O_LINK_ESTABLISH_request, API) \
67 DEF_PRIV_SIG(O_LINK_RELEASE_request, API) \
68 DEF_PRIV_SIG(O_RESET_request, API) \
69 DEF_PRIV_SIG(O_RESET_response, API) \
70 DEF_PRIV_SIG(O_RESET_ERROR_response, API) \
71 DEF_PRIV_SIG(O_SETUP_request, API) \
72 DEF_PRIV_SIG(O_SETUP_response, API) \
73 DEF_PRIV_SIG(O_SETUP_COMPLETE_request, API) \
74 DEF_PRIV_SIG(O_PROCEEDING_request, API) \
75 DEF_PRIV_SIG(O_ALERTING_request, API) \
76 DEF_PRIV_SIG(O_RELEASE_request, API) \
77 DEF_PRIV_SIG(O_RELEASE_response, API) \
78 DEF_PRIV_SIG(O_NOTIFY_request, API) \
79 DEF_PRIV_SIG(O_STATUS_ENQUIRY_request, API) \
80 DEF_PRIV_SIG(O_ADD_PARTY_request, API) \
81 DEF_PRIV_SIG(O_PARTY_ALERTING_request, API) \
82 DEF_PRIV_SIG(O_ADD_PARTY_ACK_request, API) \
83 DEF_PRIV_SIG(O_ADD_PARTY_REJ_request, API) \
84 DEF_PRIV_SIG(O_DROP_PARTY_request, API) \
85 DEF_PRIV_SIG(O_DROP_PARTY_ACK_request, API) \
86 DEF_PRIV_SIG(O_ABORT_CALL_request, API) \
87 DEF_PRIV_SIG(O_CALL_DESTROYED, CallControl) \
88 DEF_PRIV_SIG(O_RESET_indication, ResetRespond) \
89 DEF_PRIV_SIG(O_END, Coord)
91 #define DEF_RESPOND_SIGS \
92 DEF_PRIV_SIG(R_RESTART, Coord) \
93 DEF_PRIV_SIG(R_STATUS, Coord) \
94 DEF_PRIV_SIG(R_RESET_response, Coord) \
95 DEF_PRIV_SIG(R_RESET_ERROR_response, Coord) \
96 DEF_PRIV_SIG(R_T317, ResetRespond) \
97 DEF_PRIV_SIG(R_END, ResetRespond)
99 #define DEF_START_SIGS \
100 DEF_PRIV_SIG(S_RESTART_ACK, Coord) \
101 DEF_PRIV_SIG(S_STATUS, Coord) \
102 DEF_PRIV_SIG(S_RESET_request, Coord) \
103 DEF_PRIV_SIG(S_T316, ResetStart) \
104 DEF_PRIV_SIG(S_END, ResetStart)
106 #define DEF_CALL_SIGS \
107 DEF_PRIV_SIG(C_LINK_ESTABLISH_confirm, Coord) \
108 DEF_PRIV_SIG(C_LINK_ESTABLISH_indication, Coord) \
109 DEF_PRIV_SIG(C_LINK_ESTABLISH_ERROR_indication,Coord) \
110 DEF_PRIV_SIG(C_LINK_RELEASE_indication, Coord) \
111 DEF_PRIV_SIG(C_SETUP_request, Coord) \
112 DEF_PRIV_SIG(C_SETUP_response, Coord) \
113 DEF_PRIV_SIG(C_SETUP_COMPLETE_request, Coord) \
114 DEF_PRIV_SIG(C_PROCEEDING_request, Coord) \
115 DEF_PRIV_SIG(C_ALERTING_request, Coord) \
116 DEF_PRIV_SIG(C_RELEASE_request, Coord) \
117 DEF_PRIV_SIG(C_RELEASE_response, Coord) \
118 DEF_PRIV_SIG(C_NOTIFY_request, Coord) \
119 DEF_PRIV_SIG(C_STATUS_ENQUIRY_request, Coord) \
120 DEF_PRIV_SIG(C_ADD_PARTY_request, Coord) \
121 DEF_PRIV_SIG(C_PARTY_ALERTING_request, Coord) \
122 DEF_PRIV_SIG(C_ADD_PARTY_ACK_request, Coord) \
123 DEF_PRIV_SIG(C_ADD_PARTY_REJ_request, Coord) \
124 DEF_PRIV_SIG(C_DROP_PARTY_request, Coord) \
125 DEF_PRIV_SIG(C_DROP_PARTY_ACK_request, Coord) \
126 DEF_PRIV_SIG(C_ABORT_CALL_request, Coord) \
127 DEF_PRIV_SIG(C_UNKNOWN, Coord) \
128 DEF_PRIV_SIG(C_SETUP, Coord) \
129 DEF_PRIV_SIG(C_CALL_PROC, Coord) \
130 DEF_PRIV_SIG(C_ALERTING, Coord) \
131 DEF_PRIV_SIG(C_CONNECT, Coord) \
132 DEF_PRIV_SIG(C_CONNECT_ACK, Coord) \
133 DEF_PRIV_SIG(C_RELEASE, Coord) \
134 DEF_PRIV_SIG(C_RELEASE_COMPL, Coord) \
135 DEF_PRIV_SIG(C_COBISETUP, Coord) \
136 DEF_PRIV_SIG(C_NOTIFY, Coord) \
137 DEF_PRIV_SIG(C_STATUS, Coord) \
138 DEF_PRIV_SIG(C_STATUS_ENQ, Coord) \
139 DEF_PRIV_SIG(C_ADD_PARTY, Coord) \
140 DEF_PRIV_SIG(C_PARTY_ALERTING, Coord) \
141 DEF_PRIV_SIG(C_ADD_PARTY_ACK, Coord) \
142 DEF_PRIV_SIG(C_ADD_PARTY_REJ, Coord) \
143 DEF_PRIV_SIG(C_DROP_PARTY, Coord) \
144 DEF_PRIV_SIG(C_DROP_PARTY_ACK, Coord) \
145 DEF_PRIV_SIG(C_CALL_DELETE, CallControl) \
146 DEF_PRIV_SIG(C_T301, CallControl) \
147 DEF_PRIV_SIG(C_T303, CallControl) \
148 DEF_PRIV_SIG(C_T308, CallControl) \
149 DEF_PRIV_SIG(C_T310, CallControl) \
150 DEF_PRIV_SIG(C_T313, CallControl) \
151 DEF_PRIV_SIG(C_T322, CallControl) \
152 DEF_PRIV_SIG(C_DROP_PARTY_indication, PartyControl) \
153 DEF_PRIV_SIG(C_SEND_DROP_PARTY, PartyControl) \
154 DEF_PRIV_SIG(C_DROP_PARTY_ACK_indication, PartyControl) \
155 DEF_PRIV_SIG(C_SEND_DROP_PARTY_ACK, PartyControl) \
156 DEF_PRIV_SIG(C_ADD_PARTY_REJ_indication, PartyControl) \
157 DEF_PRIV_SIG(C_SEND_ADD_PARTY_REJ, PartyControl) \
158 DEF_PRIV_SIG(C_SEND_STATUS_ENQ, PartyControl) \
159 DEF_PRIV_SIG(C_PARTY_DESTROYED, PartyControl) \
160 DEF_PRIV_SIG(C_END, CallControl)
162 #define DEF_PARTY_SIGS \
163 DEF_PRIV_SIG(P_SETUP, CallControl) \
164 DEF_PRIV_SIG(P_ALERTING, CallControl) \
165 DEF_PRIV_SIG(P_CONNECT, CallControl) \
166 DEF_PRIV_SIG(P_CONNECT_ACK, CallControl) \
167 DEF_PRIV_SIG(P_RELEASE, CallControl) \
168 DEF_PRIV_SIG(P_RELEASE_COMPL, CallControl) \
169 DEF_PRIV_SIG(P_STATUS, CallControl) \
170 DEF_PRIV_SIG(P_ADD_PARTY, CallControl) \
171 DEF_PRIV_SIG(P_PARTY_ALERTING, CallControl) \
172 DEF_PRIV_SIG(P_ADD_PARTY_ACK, CallControl) \
173 DEF_PRIV_SIG(P_ADD_PARTY_REJ, CallControl) \
174 DEF_PRIV_SIG(P_DROP_PARTY, CallControl) \
175 DEF_PRIV_SIG(P_DROP_PARTY_ACK, CallControl) \
176 DEF_PRIV_SIG(P_SETUP_request, CallControl) \
177 DEF_PRIV_SIG(P_SETUP_response, CallControl) \
178 DEF_PRIV_SIG(P_SETUP_COMPL_request, CallControl) \
179 DEF_PRIV_SIG(P_ALERTING_request, CallControl) \
180 DEF_PRIV_SIG(P_RELEASE_request, CallControl) \
181 DEF_PRIV_SIG(P_RELEASE_response, CallControl) \
182 DEF_PRIV_SIG(P_RELEASE_confirm, CallControl) \
183 DEF_PRIV_SIG(P_STATUS_ENQUIRY_request, CallControl) \
184 DEF_PRIV_SIG(P_ADD_PARTY_request, CallControl) \
185 DEF_PRIV_SIG(P_PARTY_ALERTING_request, CallControl) \
186 DEF_PRIV_SIG(P_ADD_PARTY_ACK_request, CallControl) \
187 DEF_PRIV_SIG(P_ADD_PARTY_REJ_request, CallControl) \
188 DEF_PRIV_SIG(P_DROP_PARTY_request, CallControl) \
189 DEF_PRIV_SIG(P_DROP_PARTY_ACK_request, CallControl) \
190 DEF_PRIV_SIG(P_PARTY_DELETE, PartyControl) \
191 DEF_PRIV_SIG(P_T397, PartyControl) \
192 DEF_PRIV_SIG(P_T398, PartyControl) \
193 DEF_PRIV_SIG(P_T399, PartyControl) \
194 DEF_PRIV_SIG(P_END, PartyControl)
197 #define DEF_PRIV_SIG(NAME, FROM) SIG##NAME,
215 /*************************************************************
217 * SIGNALS and SIGNAL QUEUES
228 TAILQ_ENTRY(sig) link;
229 u_int type; /* one of the above */
230 struct call *call; /* call to send to */
231 struct party *party; /* party to send to */
232 uint32_t sig; /* the signal */
233 uint32_t cookie; /* user cookie */
234 struct uni_msg *msg; /* attached message */
235 struct uni_all *u; /* dito */
237 TAILQ_HEAD(sigqueue, sig);
239 #define SIGQ_CLEAR(Q) \
242 while(!TAILQ_EMPTY(Q)) { \
243 s = TAILQ_FIRST(Q); \
244 TAILQ_REMOVE(Q, s, link); \
245 if(s->msg) uni_msg_destroy(s->msg); \
246 if(s->u) UNI_FREE(s->u); \
251 void uni_sig_party(struct party *, enum party_sig, uint32_t cookie,
252 struct uni_msg *, struct uni_all *);
253 void uni_sig_call(struct call *, enum call_sig, uint32_t cookie,
254 struct uni_msg *, struct uni_all *);
255 void uni_sig_coord(struct uni *, enum coord_sig, uint32_t cookie,
257 void uni_sig_start(struct uni *, enum start_sig, uint32_t cookie,
258 struct uni_msg *, struct uni_all *);
259 void uni_sig_respond(struct uni *, enum respond_sig, uint32_t cookie,
260 struct uni_msg *, struct uni_all *);
262 /*************************************************************
268 TAILQ_ENTRY(party) link;
269 u_int epref; /* endpoint reference */
270 u_int flags; /* flags */
271 enum uni_epstate state; /* party state */
273 struct uni_timer t397; /* T397 */
274 struct uni_timer t398; /* T398 */
275 struct uni_timer t399; /* T399 */
277 #define PARTY_MINE 0x0001 /* must be 1 */
278 #define PARTY_CONNECT 0x0002 /* connect request from this party */
280 TAILQ_HEAD(partyqueue, party);
282 void uni_destroy_party(struct party *, int);
283 struct party *uni_find_party(struct call *, struct uni_ie_epref *);
284 struct party *uni_find_partyx(struct call *, u_int epref, u_int mine);
285 struct party *uni_create_party(struct call *, struct uni_ie_epref *);
286 struct party *uni_create_partyx(struct call *, u_int epref, u_int mine,
288 u_int uni_party_act_count(struct call *, int);
291 CALL_NULL, /* not known yet */
292 CALL_P2P, /* normal point-to-point call */
293 CALL_COBI, /* Q.2932.1 COBI call */
294 CALL_ROOT, /* point-to-multipoint root */
295 CALL_LEAF, /* point-to-multipoint leaf */
300 CALLST_U1, CALLST_U3, CALLST_U4, CALLST_U6, CALLST_U7, CALLST_U8,
301 CALLST_U9, CALLST_U10, CALLST_U11, CALLST_U12,
302 CALLST_N1, CALLST_N3, CALLST_N4, CALLST_N6, CALLST_N7, CALLST_N8,
303 CALLST_N9, CALLST_N10, CALLST_N11, CALLST_N12
307 TAILQ_ENTRY(call) link; /* link between calls */
308 struct uni *uni; /* backpointer to owning UNI */
309 u_int cref; /* call reference value or lij seqno */
310 u_int mine; /* if TRUE this is my call */
311 enum call_type type; /* what call is it */
312 enum call_state cstate; /* the state of the call */
313 struct uni_ie_connid connid; /* the connection ID */
314 struct uni_setup msg_setup; /* retransmission */
315 struct uni_release msg_release; /* retransmission */
316 struct uni_ie_epref stat_epref; /* retransmission */
317 struct partyqueue parties;
318 u_int se_active; /* status enquiry active */
321 struct uni_timer t308; /* T303 */
324 struct uni_timer t303; /* T303 */
327 struct uni_timer t301; /* T301 */
328 struct uni_timer t310; /* T310 */
329 struct uni_timer t313; /* T313 */
331 struct uni_timer t322; /* T322 */
335 TAILQ_HEAD(callqueue, call);
337 struct call *uni_find_call(struct uni *, struct uni_cref *);
338 struct call *uni_find_callx(struct uni *, u_int cref, u_int mine);
339 struct call *uni_create_call(struct uni *, u_int cref, u_int mine,
341 struct call *uni_create_new_call(struct uni *, uint32_t cookie);
342 void uni_destroy_call(struct call *, int);
344 void uni_bad_message(struct call *, struct uni_all *, u_int,
345 struct uni_ie_epref *, int);
347 extern const struct callstates {
349 enum uni_callstate ext;
352 /*************************************************************
357 void *arg; /* user arg */
358 const struct uni_funcs *funcs;
360 enum uni_proto proto; /* protocol */
361 struct unicx cx; /* decoding/coding context */
362 int sb_tb : 1; /* Sb-Tb/Tb point */
364 struct sigqueue workq; /* work queue */
365 struct sigqueue delq; /* delayed signal queue */
370 enum cu_stat custat; /* coordinator state */
371 struct uni_timer t309;
374 enum uni_callstate glob_start;
375 enum uni_callstate glob_respond;
376 struct uni_timer t316;
377 struct uni_timer t317;
378 struct uni_ie_connid connid_start;
379 struct uni_ie_connid connid_respond;
381 struct uni_ie_restart restart_start;
383 struct callqueue calls;
385 struct uni_ie_cause cause; /* working area for verify */
387 /* tuneable parameters */
404 u_int debug[UNI_MAXFACILITY];
407 void uniapi_uni_error(struct uni *uni, uint32_t reason, uint32_t cookie,
409 void uniapi_call_error(struct call *c, uint32_t reason, uint32_t cookie);
410 void uniapi_party_error(struct party *p, uint32_t reason, uint32_t cookie);
412 /*************************************************************
417 /* Enqueue a signal in the working queue */
418 void uni_enq_sig(struct uni *, u_int, struct call *, struct party *,
419 uint32_t, uint32_t, struct uni_msg *, struct uni_all *);
421 /* Enqueue a signal in the delayed queue */
422 void uni_delenq_sig(struct uni *, u_int, struct call *, struct party *,
423 uint32_t, uint32_t, struct uni_msg *, struct uni_all *);
425 /* Enqueue a signal to the coordinator */
426 #define uni_enq_coord(UNI, SIG, COOKIE, MSG) do { \
427 uni_enq_sig((UNI), SIG_COORD, NULL, NULL, \
428 (SIG), (COOKIE), (MSG), NULL); \
431 /* Enqueue a delayed signal to the coordinator */
432 #define uni_delenq_coord(UNI, SIG, COOKIE, MSG) do { \
433 uni_delenq_sig((UNI), SIG_COORD, NULL, NULL, \
434 (SIG), (COOKIE), (MSG), NULL); \
437 /* Enqueue a signal to a call */
438 #define uni_enq_call(CALL, SIG, COOKIE, MSG, U) do { \
439 uni_enq_sig((CALL)->uni, SIG_CALL, (CALL), NULL, \
440 (SIG), (COOKIE), (MSG), (U)); \
443 /* Enqueue a signal to a party */
444 #define uni_enq_party(PARTY, SIG, COOKIE, MSG, U) do { \
445 uni_enq_sig((PARTY)->call->uni, SIG_PARTY, (PARTY)->call, \
446 (PARTY), (SIG), (COOKIE), (MSG), (U)); \
449 /* Enqueue a signal to RESET-START */
450 #define uni_enq_start(UNI, SIG, COOKIE, MSG, U) do { \
451 uni_enq_sig((UNI), SIG_RESET_START, NULL, NULL, \
452 (SIG), (COOKIE), (MSG), (U)); \
455 /* Enqueue a signal to RESET-RESPOND */
456 #define uni_enq_resp(UNI, SIG, COOKIE, MSG, U) do { \
457 uni_enq_sig((UNI), SIG_RESET_RESP, NULL, NULL, \
458 (SIG), (COOKIE), (MSG), (U)); \
461 int uni_send_output(struct uni_all *u, struct uni *uni);
462 void uni_undel(struct uni *, int (*)(struct sig *, void *), void *);
463 void uni_delsig(struct uni *, u_int, struct call *, struct party *);
465 void uni_release_compl(struct call *, struct uni_all *);
467 /*************************************************************/
469 * Message verification.
471 #define MANDATE_IE(UNI,MSG,IE) \
473 if (!IE_ISGOOD(MSG)) \
474 uni_mandate_ie(UNI, IE); \
479 VFY_RAP, /* report and proceed */
480 VFY_RAPU, /* report and proceed becuase of unknown IEs */
482 VFY_CLR, /* clear call */
483 VFY_RAI, /* report and ignore */
484 VFY_RAIM, /* report and ignore because if mandat. IE miss */
487 void uni_mandate_ie(struct uni *, enum uni_ietype);
488 void uni_mandate_epref(struct uni *, struct uni_ie_epref *);
489 enum verify uni_verify(struct uni *, enum uni_msgact);
490 void uni_respond_status_verify(struct uni *, struct uni_cref *,
491 enum uni_callstate, struct uni_ie_epref *, enum uni_epstate);
492 void uni_vfy_remove_unknown(struct uni *);
493 void uni_vfy_remove_cause(struct uni *);
494 void uni_vfy_collect_ies(struct uni *);
497 void uni_respond_status(struct uni *uni, struct uni_cref *cref,
498 enum uni_callstate cs, enum uni_cause c1);
499 void uni_respond_status_mtype(struct uni *uni, struct uni_cref *cref,
500 enum uni_callstate cs, enum uni_cause c1, u_int mtype);
502 #define FOREACH_ERR(E, UNI) \
503 for ((E) = (UNI)->cx.err; (E) < (UNI)->cx.err + (UNI)->cx.errcnt; (E)++)
505 #define ALLOC_API(TYPE,API) \
509 if(((API) = uni_msg_alloc(sizeof(TYPE))) != NULL) { \
510 _tmp = uni_msg_wptr((API), TYPE *); \
511 (API)->b_wptr += sizeof(TYPE); \
512 memset(_tmp, 0, sizeof(TYPE)); \
517 #if defined(__GNUC__) && __GNUC__ < 3
519 #define VERBOSE(UNI, FAC, LEVEL, ARGS...) do { \
520 if ((UNI)->debug[(FAC)] >= (LEVEL)) { \
521 (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC) ,\
526 #define VERBOSE0(UNI, FAC, ARGS...) do { \
527 (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC) , \
533 #define VERBOSE(UNI, FAC, LEVEL, ...) do { \
534 if ((UNI)->debug[(FAC)] >= (LEVEL)) { \
535 (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC), \
540 #define VERBOSE0(UNI, FAC, ...) do { \
541 (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC), \
547 #define TIMER_INIT_UNI(U,T) _TIMER_INIT(U,T)
548 #define TIMER_INIT_CALL(C,T) _TIMER_INIT(C,T)
549 #define TIMER_INIT_PARTY(P,T) _TIMER_INIT(P,T)
551 #define TIMER_DESTROY_UNI(U,T) _TIMER_DESTROY(U, (U)->T)
552 #define TIMER_DESTROY_CALL(C,T) _TIMER_DESTROY((C)->uni, (C)->T)
553 #define TIMER_DESTROY_PARTY(P,T) _TIMER_DESTROY((P)->call->uni, (P)->T)
555 #define TIMER_STOP_UNI(U,T) _TIMER_STOP(U, (U)->T)
556 #define TIMER_STOP_CALL(C,T) _TIMER_STOP((C)->uni, (C)->T)
557 #define TIMER_STOP_PARTY(P,T) _TIMER_STOP((P)->call->uni, (P)->T)
559 #define TIMER_START_UNI(U,T,N) _TIMER_START(U, U, (U)->T, N, _##T##_func)
560 #define TIMER_START_CALL(C,T,N) _TIMER_START(C->uni, C, (C)->T, N, _##T##_func)
561 #define TIMER_START_PARTY(P,T,N) _TIMER_START(P->call->uni, P, (P)->T, N, _##T##_func)