Asterisk - The Open Source Telephony Project  18.5.0
isdn_msg_parser.c
Go to the documentation of this file.
1 /*
2  * Chan_Misdn -- Channel Driver for Asterisk
3  *
4  * Interface to mISDN
5  *
6  * Copyright (C) 2004, Christian Richter
7  *
8  * Christian Richter <[email protected]>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13 
14 /*! \file
15  * \brief Interface to mISDN - message parser
16  * \author Christian Richter <[email protected]>
17  */
18 
19 /*** MODULEINFO
20  <support_level>extended</support_level>
21  ***/
22 
23 #include "isdn_lib_intern.h"
24 
25 
26 #include "isdn_lib.h"
27 
28 #include "ie.c"
29 
30 /*!
31  * \internal
32  * \brief Build the name, number, name/number display message string
33  *
34  * \param display Display buffer to fill in
35  * \param display_length Length of the display buffer to fill in
36  * \param display_format Display format enumeration
37  * \param name Name string to use
38  * \param number Number string to use
39  *
40  * \return Nothing
41  */
42 static void build_display_str(char *display, size_t display_length, int display_format, const char *name, const char *number)
43 {
44  display[0] = 0;
45  switch (display_format) {
46  default:
47  case 0: /* none */
48  break;
49 
50  case 1: /* name */
51  snprintf(display, display_length, "%s", name);
52  break;
53 
54  case 2: /* number */
55  snprintf(display, display_length, "%s", number);
56  break;
57 
58  case 3: /* both */
59  if (name[0] || number[0]) {
60  snprintf(display, display_length, "\"%s\" <%s>", name, number);
61  }
62  break;
63  }
64 }
65 
66 /*!
67  * \internal
68  * \brief Encode the Facility IE and put it into the message structure.
69  *
70  * \param ntmode Where the encoded facility was put when in NT mode.
71  * \param msg General message structure
72  * \param fac Data to encode into the facility ie.
73  * \param nt TRUE if in NT mode.
74  *
75  * \return Nothing
76  */
77 static void enc_ie_facility(unsigned char **ntmode, msg_t *msg, struct FacParm *fac, int nt)
78 {
79  int len;
80  Q931_info_t *qi;
81  unsigned char *p;
82  unsigned char buf[256];
83 
84  len = encodeFac(buf, fac);
85  if (len <= 0) {
86  /*
87  * mISDN does not know how to build the requested facility structure
88  * Clear facility information
89  */
90  fac->Function = Fac_None;
91  return;
92  }
93 
94  p = msg_put(msg, len);
95  if (nt) {
96  *ntmode = p + 1;
97  } else {
98  qi = (Q931_info_t *) (msg->data + mISDN_HEADER_LEN);
99  qi->QI_ELEMENT(facility) = p - (unsigned char *) qi - sizeof(Q931_info_t);
100  }
101 
102  memcpy(p, buf, len);
103 
104  /* Clear facility information */
105  fac->Function = Fac_None;
106 }
107 
108 /*!
109  * \internal
110  * \brief Decode the Facility IE.
111  *
112  * \param p Encoded facility ie data to decode. (NT mode)
113  * \param qi Encoded facility ie data to decode. (TE mode)
114  * \param fac Where to put the decoded facility ie data if it is available.
115  * \param nt TRUE if in NT mode.
116  * \param bc Associated B channel
117  *
118  * \return Nothing
119  */
120 static void dec_ie_facility(unsigned char *p, Q931_info_t *qi, struct FacParm *fac, int nt, struct misdn_bchannel *bc)
121 {
122  fac->Function = Fac_None;
123 
124  if (!nt) {
125  p = NULL;
126  if (qi->QI_ELEMENT(facility)) {
127  p = (unsigned char *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
128  }
129  }
130  if (!p) {
131  return;
132  }
133 
134  if (decodeFac(p, fac)) {
135  cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
136  }
137 }
138 
139 
140 
141 static void set_channel(struct misdn_bchannel *bc, int channel)
142 {
143 
144  cb_log(3,bc->port,"set_channel: bc->channel:%d channel:%d\n", bc->channel, channel);
145 
146 
147  if (channel==0xff) {
148  /* any channel */
149  channel=-1;
150  }
151 
152  /* ALERT: is that everytime true ? */
153  if (channel > 0 && bc->nt ) {
154 
155  if (bc->channel && ( bc->channel != 0xff) ) {
156  cb_log(0,bc->port,"We already have a channel (%d)\n", bc->channel);
157  } else {
158  bc->channel = channel;
160  }
161  }
162 
163  if (channel > 0 && !bc->nt ) {
164  bc->channel = channel;
166  }
167 }
168 
169 static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
170 {
171  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
172  CALL_PROCEEDING_t *proceeding = (CALL_PROCEEDING_t *) (msg->data + HEADER_LEN);
173  //struct misdn_stack *stack=get_stack_by_bc(bc);
174 
175  {
176  int exclusive, channel;
177  dec_ie_channel_id(proceeding->CHANNEL_ID, (Q931_info_t *)proceeding, &exclusive, &channel, nt,bc);
178 
179  set_channel(bc,channel);
180 
181  }
182 
183  dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
184 
185  dec_ie_facility(proceeding->FACILITY, (Q931_info_t *) proceeding, &bc->fac_in, nt, bc);
186 
187  /* dec_ie_redir_dn */
188 
189 #ifdef DEBUG
190  printf("Parsing PROCEEDING Msg\n");
191 #endif
192 }
193 static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
194 {
195  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
196  CALL_PROCEEDING_t *proceeding;
197  msg_t *msg =(msg_t*)create_l3msg(CC_PROCEEDING | REQUEST, MT_CALL_PROCEEDING, bc?bc->l3_id:-1, sizeof(CALL_PROCEEDING_t) ,nt);
198 
199  proceeding=(CALL_PROCEEDING_t*)((msg->data+HEADER_LEN));
200 
201  enc_ie_channel_id(&proceeding->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
202 
203  if (nt)
204  enc_ie_progress(&proceeding->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
205 
206  if (bc->fac_out.Function != Fac_None) {
207  enc_ie_facility(&proceeding->FACILITY, msg, &bc->fac_out, nt);
208  }
209 
210  /* enc_ie_redir_dn */
211 
212 #ifdef DEBUG
213  printf("Building PROCEEDING Msg\n");
214 #endif
215  return msg;
216 }
217 
218 static void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
219 {
220  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
221  ALERTING_t *alerting = (ALERTING_t *) (msg->data + HEADER_LEN);
222  //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
223 
224  dec_ie_facility(alerting->FACILITY, (Q931_info_t *) alerting, &bc->fac_in, nt, bc);
225 
226  /* dec_ie_redir_dn */
227 
228  dec_ie_progress(alerting->PROGRESS, (Q931_info_t *)alerting, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
229 
230 #ifdef DEBUG
231  printf("Parsing ALERTING Msg\n");
232 #endif
233 
234 
235 }
236 
237 static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
238 {
239  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
240  ALERTING_t *alerting;
241  msg_t *msg =(msg_t*)create_l3msg(CC_ALERTING | REQUEST, MT_ALERTING, bc?bc->l3_id:-1, sizeof(ALERTING_t) ,nt);
242 
243  alerting=(ALERTING_t*)((msg->data+HEADER_LEN));
244 
245  enc_ie_channel_id(&alerting->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
246 
247  if (nt)
248  enc_ie_progress(&alerting->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
249 
250  if (bc->fac_out.Function != Fac_None) {
251  enc_ie_facility(&alerting->FACILITY, msg, &bc->fac_out, nt);
252  }
253 
254  /* enc_ie_redir_dn */
255 
256 #ifdef DEBUG
257  printf("Building ALERTING Msg\n");
258 #endif
259  return msg;
260 }
261 
262 
263 static void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
264 {
265  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
266  PROGRESS_t *progress = (PROGRESS_t *) (msg->data + HEADER_LEN);
267  //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
268 
269  dec_ie_progress(progress->PROGRESS, (Q931_info_t *)progress, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
270 
271  dec_ie_facility(progress->FACILITY, (Q931_info_t *) progress, &bc->fac_in, nt, bc);
272 
273 #ifdef DEBUG
274  printf("Parsing PROGRESS Msg\n");
275 #endif
276 }
277 
278 static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
279 {
280  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
281  PROGRESS_t *progress;
282  msg_t *msg =(msg_t*)create_l3msg(CC_PROGRESS | REQUEST, MT_PROGRESS, bc?bc->l3_id:-1, sizeof(PROGRESS_t) ,nt);
283 
284  progress=(PROGRESS_t*)((msg->data+HEADER_LEN));
285 
286  enc_ie_progress(&progress->PROGRESS, msg, 0, nt ? 1 : 5, 8, nt, bc);
287 
288  if (bc->fac_out.Function != Fac_None) {
289  enc_ie_facility(&progress->FACILITY, msg, &bc->fac_out, nt);
290  }
291 
292 #ifdef DEBUG
293  printf("Building PROGRESS Msg\n");
294 #endif
295  return msg;
296 }
297 
298 #if defined(AST_MISDN_ENHANCEMENTS)
299 /*!
300  * \internal
301  * \brief Extract the SETUP message's BC, HLC, and LLC encoded ie contents.
302  *
303  * \param setup Indexed setup message contents
304  * \param nt TRUE if in NT mode.
305  * \param bc Associated B channel
306  *
307  * \return Nothing
308  */
309 static void extract_setup_Bc_Hlc_Llc(SETUP_t *setup, int nt, struct misdn_bchannel *bc)
310 {
311  __u8 *p;
312  Q931_info_t *qi;
313 
314  qi = (Q931_info_t *) setup;
315 
316  /* Extract Bearer Capability */
317  if (nt) {
318  p = (__u8 *) setup->BEARER;
319  } else {
320  if (qi->QI_ELEMENT(bearer_capability)) {
321  p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1;
322  } else {
323  p = NULL;
324  }
325  }
326  if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Bc.Contents) < *p) {
327  bc->setup_bc_hlc_llc.Bc.Length = 0;
328  } else {
329  bc->setup_bc_hlc_llc.Bc.Length = *p;
330  memcpy(bc->setup_bc_hlc_llc.Bc.Contents, p + 1, *p);
331  }
332 
333  /* Extract Low Layer Compatibility */
334  if (nt) {
335  p = (__u8 *) setup->LLC;
336  } else {
337  if (qi->QI_ELEMENT(llc)) {
338  p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
339  } else {
340  p = NULL;
341  }
342  }
343  if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Llc.Contents) < *p) {
344  bc->setup_bc_hlc_llc.Llc.Length = 0;
345  } else {
346  bc->setup_bc_hlc_llc.Llc.Length = *p;
347  memcpy(bc->setup_bc_hlc_llc.Llc.Contents, p + 1, *p);
348  }
349 
350  /* Extract High Layer Compatibility */
351  if (nt) {
352  p = (__u8 *) setup->HLC;
353  } else {
354  if (qi->QI_ELEMENT(hlc)) {
355  p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(hlc) + 1;
356  } else {
357  p = NULL;
358  }
359  }
360  if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Hlc.Contents) < *p) {
361  bc->setup_bc_hlc_llc.Hlc.Length = 0;
362  } else {
363  bc->setup_bc_hlc_llc.Hlc.Length = *p;
364  memcpy(bc->setup_bc_hlc_llc.Hlc.Contents, p + 1, *p);
365  }
366 }
367 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
368 
369 static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
370 {
371  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
372  SETUP_t *setup = (SETUP_t *) (msg->data + HEADER_LEN);
373  Q931_info_t *qi = (Q931_info_t *) (msg->data + HEADER_LEN);
374  int type;
375  int plan;
376  int present;
377  int screen;
378  int reason;
379 
380 #ifdef DEBUG
381  printf("Parsing SETUP Msg\n");
382 #endif
383 
384  dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, bc->caller.number, sizeof(bc->caller.number), nt, bc);
385  bc->caller.number_type = type;
386  bc->caller.number_plan = plan;
387  switch (present) {
388  default:
389  case 0:
390  bc->caller.presentation = 0; /* presentation allowed */
391  break;
392  case 1:
393  bc->caller.presentation = 1; /* presentation restricted */
394  break;
395  case 2:
396  bc->caller.presentation = 2; /* Number not available */
397  break;
398  }
399  if (0 <= screen) {
400  bc->caller.screening = screen;
401  } else {
402  bc->caller.screening = 0; /* Unscreened */
403  }
404 
405  dec_ie_facility(setup->FACILITY, (Q931_info_t *) setup, &bc->fac_in, nt, bc);
406 
407  dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number), nt, bc);
408  bc->dialed.number_type = type;
409  bc->dialed.number_plan = plan;
410 
411  dec_ie_keypad(setup->KEYPAD, (Q931_info_t *) setup, bc->keypad, sizeof(bc->keypad), nt, bc);
412 
413  dec_ie_complete(setup->COMPLETE, (Q931_info_t *) setup, &bc->sending_complete, nt, bc);
414 
415  dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *) setup, &type, &plan, &present, &screen, &reason, bc->redirecting.from.number, sizeof(bc->redirecting.from.number), nt, bc);
417  bc->redirecting.from.number_plan = plan;
418  switch (present) {
419  default:
420  case 0:
421  bc->redirecting.from.presentation = 0; /* presentation allowed */
422  break;
423  case 1:
424  bc->redirecting.from.presentation = 1; /* presentation restricted */
425  break;
426  case 2:
427  bc->redirecting.from.presentation = 2; /* Number not available */
428  break;
429  }
430  if (0 <= screen) {
431  bc->redirecting.from.screening = screen;
432  } else {
433  bc->redirecting.from.screening = 0; /* Unscreened */
434  }
435  if (0 <= reason) {
436  bc->redirecting.reason = reason;
437  } else {
439  }
440 
441  {
442  int coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity;
443 
444  dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc);
445  switch (capability) {
447  break;
449  break;
450  case 18: bc->capability=INFO_CAPABILITY_VIDEO;
451  break;
453  bc->user1 = user;
454  bc->urate = urate;
455 
456  bc->rate = rate;
457  bc->mode = mode;
458  break;
460  break;
461  default:
462  break;
463  }
464 
465  switch(user) {
466  case 2:
467  bc->law=INFO_CODEC_ULAW;
468  break;
469  case 3:
470  bc->law=INFO_CODEC_ALAW;
471  break;
472  default:
473  bc->law=INFO_CODEC_ALAW;
474 
475  }
476 
477  bc->capability=capability;
478  }
479  {
480  int exclusive, channel;
481  dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)setup, &exclusive, &channel, nt,bc);
482 
483  set_channel(bc,channel);
484  }
485 
486  {
487  int protocol ;
488  dec_ie_useruser(setup->USER_USER, (Q931_info_t *)setup, &protocol, bc->uu, &bc->uulen, nt,bc);
489  if (bc->uulen) cb_log(1, bc->port, "USERUSERINFO:%s\n", bc->uu);
490  else
491  cb_log(1, bc->port, "NO USERUSERINFO\n");
492  }
493 
494  dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
495 
496 #if defined(AST_MISDN_ENHANCEMENTS)
497  extract_setup_Bc_Hlc_Llc(setup, nt, bc);
498 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
499 }
500 
501 #define ANY_CHANNEL 0xff /* IE attribute for 'any channel' */
502 static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
503 {
504  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
505  SETUP_t *setup;
506  msg_t *msg =(msg_t*)create_l3msg(CC_SETUP | REQUEST, MT_SETUP, bc?bc->l3_id:-1, sizeof(SETUP_t) ,nt);
507  int is_ptp;
508  enum FacFunction fac_type;
509 
510  setup=(SETUP_t*)((msg->data+HEADER_LEN));
511 
512  if (bc->channel == 0 || bc->channel == ANY_CHANNEL || bc->channel==-1)
513  enc_ie_channel_id(&setup->CHANNEL_ID, msg, 0, bc->channel, nt,bc);
514  else
515  enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
516 
517  fac_type = bc->fac_out.Function;
518  if (fac_type != Fac_None) {
519  enc_ie_facility(&setup->FACILITY, msg, &bc->fac_out, nt);
520  }
521 
522  enc_ie_calling_pn(&setup->CALLING_PN, msg, bc->caller.number_type, bc->caller.number_plan,
523  bc->caller.presentation, bc->caller.screening, bc->caller.number, nt, bc);
524 
525  if (bc->dialed.number[0]) {
526  enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dialed.number_type, bc->dialed.number_plan, bc->dialed.number, nt, bc);
527  }
528 
529  switch (bc->outgoing_colp) {
530  case 0:/* pass */
531  case 1:/* restricted */
532  is_ptp = misdn_lib_is_ptp(bc->port);
533  if (bc->redirecting.from.number[0]
534  && ((!is_ptp && nt)
535  || (is_ptp
536 #if defined(AST_MISDN_ENHANCEMENTS)
537  /*
538  * There is no need to send out this ie when we are also sending
539  * a Fac_DivertingLegInformation2 as well. The
540  * Fac_DivertingLegInformation2 supercedes the information in
541  * this ie.
542  */
543  && fac_type != Fac_DivertingLegInformation2
544 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
545  ))) {
546 #if 1
547  /* ETSI and Q.952 do not define the screening field */
548  enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type,
550  bc->redirecting.reason, bc->redirecting.from.number, nt, bc);
551 #else
552  /* Q.931 defines the screening field */
553  enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type,
556  bc->redirecting.from.number, nt, bc);
557 #endif
558  }
559  break;
560  default:
561  break;
562  }
563 
564  if (bc->keypad[0]) {
565  enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
566  }
567 
568 
569 
570  if (*bc->display) {
571  enc_ie_display(&setup->DISPLAY, msg, bc->display, nt, bc);
572  } else if (nt && bc->caller.presentation == 0) {
573  char display[sizeof(bc->display)];
574 
575  /* Presentation is allowed */
576  build_display_str(display, sizeof(display), bc->display_setup, bc->caller.name, bc->caller.number);
577  if (display[0]) {
578  enc_ie_display(&setup->DISPLAY, msg, display, nt, bc);
579  }
580  }
581 
582  {
583  int coding = 0;
584  int capability;
585  int mode = 0; /* 2 for packet! */
586  int user;
587  int rate = 0x10;
588 
589  switch (bc->law) {
590  case INFO_CODEC_ULAW: user=2;
591  break;
592  case INFO_CODEC_ALAW: user=3;
593  break;
594  default:
595  user=3;
596  }
597 
598  switch (bc->capability) {
599  case INFO_CAPABILITY_SPEECH: capability = 0;
600  break;
601  case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: capability = 8;
602  user=-1;
603  mode=bc->mode;
604  rate=bc->rate;
605  break;
606  case INFO_CAPABILITY_DIGITAL_RESTRICTED: capability = 9;
607  user=-1;
608  break;
609  default:
610  capability=bc->capability;
611  }
612 
613  enc_ie_bearer(&setup->BEARER, msg, coding, capability, mode, rate, -1, user, nt,bc);
614  }
615 
616  if (bc->sending_complete) {
617  enc_ie_complete(&setup->COMPLETE,msg, bc->sending_complete, nt, bc);
618  }
619 
620  if (bc->uulen) {
621  int protocol=4;
622  enc_ie_useruser(&setup->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
623  cb_log(1, bc->port, "ENCODING USERUSERINFO:%s\n", bc->uu);
624  }
625 
626 #if defined(AST_MISDN_ENHANCEMENTS)
627  extract_setup_Bc_Hlc_Llc(setup, nt, bc);
628 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
629 
630 #ifdef DEBUG
631  printf("Building SETUP Msg\n");
632 #endif
633  return msg;
634 }
635 
636 static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
637 {
638  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
639  CONNECT_t *connect = (CONNECT_t *) (msg->data + HEADER_LEN);
640  int type;
641  int plan;
642  int pres;
643  int screen;
644 
645  bc->ces = connect->ces;
646 
647  dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
648 
649  dec_ie_connected_pn(connect->CONNECT_PN, (Q931_info_t *) connect, &type, &plan,
650  &pres, &screen, bc->connected.number, sizeof(bc->connected.number), nt, bc);
651  bc->connected.number_type = type;
652  bc->connected.number_plan = plan;
653  switch (pres) {
654  default:
655  case 0:
656  bc->connected.presentation = 0; /* presentation allowed */
657  break;
658  case 1:
659  bc->connected.presentation = 1; /* presentation restricted */
660  break;
661  case 2:
662  bc->connected.presentation = 2; /* Number not available */
663  break;
664  }
665  if (0 <= screen) {
666  bc->connected.screening = screen;
667  } else {
668  bc->connected.screening = 0; /* Unscreened */
669  }
670 
671  dec_ie_facility(connect->FACILITY, (Q931_info_t *) connect, &bc->fac_in, nt, bc);
672 
673  /*
674  cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type);
675  */
676 
677 #ifdef DEBUG
678  printf("Parsing CONNECT Msg\n");
679 #endif
680 }
681 
682 static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
683 {
684  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
685  CONNECT_t *connect;
686  msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt);
687 
688  cb_log(6,bc->port,"BUILD_CONNECT: bc:%p bc->l3id:%d, nt:%d\n",bc,bc->l3_id,nt);
689 
690  connect=(CONNECT_t*)((msg->data+HEADER_LEN));
691 
692  if (nt) {
693  time_t now;
694  time(&now);
695  enc_ie_date(&connect->DATE, msg, now, nt,bc);
696  }
697 
698  switch (bc->outgoing_colp) {
699  case 0:/* pass */
700  case 1:/* restricted */
701  enc_ie_connected_pn(&connect->CONNECT_PN, msg, bc->connected.number_type,
703  bc->connected.screening, bc->connected.number, nt, bc);
704  break;
705  default:
706  break;
707  }
708 
709  if (nt && bc->connected.presentation == 0) {
710  char display[sizeof(bc->display)];
711 
712  /* Presentation is allowed */
713  build_display_str(display, sizeof(display), bc->display_connected, bc->connected.name, bc->connected.number);
714  if (display[0]) {
715  enc_ie_display(&connect->DISPLAY, msg, display, nt, bc);
716  }
717  }
718 
719  if (bc->fac_out.Function != Fac_None) {
720  enc_ie_facility(&connect->FACILITY, msg, &bc->fac_out, nt);
721  }
722 
723 #ifdef DEBUG
724  printf("Building CONNECT Msg\n");
725 #endif
726  return msg;
727 }
728 
729 static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
730 {
731  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
732  SETUP_ACKNOWLEDGE_t *setup_acknowledge = (SETUP_ACKNOWLEDGE_t *) (msg->data + HEADER_LEN);
733 
734  {
735  int exclusive, channel;
736  dec_ie_channel_id(setup_acknowledge->CHANNEL_ID, (Q931_info_t *)setup_acknowledge, &exclusive, &channel, nt,bc);
737 
738 
739  set_channel(bc, channel);
740  }
741 
742  dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
743 
744  dec_ie_facility(setup_acknowledge->FACILITY, (Q931_info_t *) setup_acknowledge, &bc->fac_in, nt, bc);
745 
746 #ifdef DEBUG
747  printf("Parsing SETUP_ACKNOWLEDGE Msg\n");
748 #endif
749 
750 
751 }
752 
753 static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
754 {
755  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
756  SETUP_ACKNOWLEDGE_t *setup_acknowledge;
757  msg_t *msg =(msg_t*)create_l3msg(CC_SETUP_ACKNOWLEDGE | REQUEST, MT_SETUP_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SETUP_ACKNOWLEDGE_t) ,nt);
758 
759  setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
760 
761  enc_ie_channel_id(&setup_acknowledge->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
762 
763  if (nt)
764  enc_ie_progress(&setup_acknowledge->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
765 
766  if (bc->fac_out.Function != Fac_None) {
767  enc_ie_facility(&setup_acknowledge->FACILITY, msg, &bc->fac_out, nt);
768  }
769 
770 #ifdef DEBUG
771  printf("Building SETUP_ACKNOWLEDGE Msg\n");
772 #endif
773  return msg;
774 }
775 
776 static void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
777 {
778 #ifdef DEBUG
779  printf("Parsing CONNECT_ACKNOWLEDGE Msg\n");
780 #endif
781 
782 
783 }
784 
785 static msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
786 {
787  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
788  CONNECT_ACKNOWLEDGE_t *connect_acknowledge;
789  msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | RESPONSE, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_ACKNOWLEDGE_t) ,nt);
790 
791  connect_acknowledge=(CONNECT_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
792 
793  enc_ie_channel_id(&connect_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
794 
795 #ifdef DEBUG
796  printf("Building CONNECT_ACKNOWLEDGE Msg\n");
797 #endif
798  return msg;
799 }
800 
801 static void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
802 {
803 #ifdef DEBUG
804  printf("Parsing USER_INFORMATION Msg\n");
805 #endif
806 
807 
808 }
809 
810 static msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
811 {
812  msg_t *msg =(msg_t*)create_l3msg(CC_USER_INFORMATION | REQUEST, MT_USER_INFORMATION, bc?bc->l3_id:-1, sizeof(USER_INFORMATION_t) ,nt);
813 
814 #ifdef DEBUG
815  printf("Building USER_INFORMATION Msg\n");
816 #endif
817  return msg;
818 }
819 
820 static void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
821 {
822 #ifdef DEBUG
823  printf("Parsing SUSPEND_REJECT Msg\n");
824 #endif
825 
826 
827 }
828 
829 static msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
830 {
831  msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT, bc?bc->l3_id:-1, sizeof(SUSPEND_REJECT_t) ,nt);
832 
833 #ifdef DEBUG
834  printf("Building SUSPEND_REJECT Msg\n");
835 #endif
836  return msg;
837 }
838 
839 static void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
840 {
841 #ifdef DEBUG
842  printf("Parsing RESUME_REJECT Msg\n");
843 #endif
844 
845 
846 }
847 
848 static msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
849 {
850  msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_REJECT | REQUEST, MT_RESUME_REJECT, bc?bc->l3_id:-1, sizeof(RESUME_REJECT_t) ,nt);
851 
852 #ifdef DEBUG
853  printf("Building RESUME_REJECT Msg\n");
854 #endif
855  return msg;
856 }
857 
858 static void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
859 {
860 #ifdef DEBUG
861  printf("Parsing HOLD Msg\n");
862 #endif
863 
864 
865 }
866 
867 static msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
868 {
869  msg_t *msg =(msg_t*)create_l3msg(CC_HOLD | REQUEST, MT_HOLD, bc?bc->l3_id:-1, sizeof(HOLD_t) ,nt);
870 
871 #ifdef DEBUG
872  printf("Building HOLD Msg\n");
873 #endif
874  return msg;
875 }
876 
877 static void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
878 {
879 #ifdef DEBUG
880  printf("Parsing SUSPEND Msg\n");
881 #endif
882 
883 
884 }
885 
886 static msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
887 {
888  msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND | REQUEST, MT_SUSPEND, bc?bc->l3_id:-1, sizeof(SUSPEND_t) ,nt);
889 
890 #ifdef DEBUG
891  printf("Building SUSPEND Msg\n");
892 #endif
893  return msg;
894 }
895 
896 static void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
897 {
898 #ifdef DEBUG
899  printf("Parsing RESUME Msg\n");
900 #endif
901 
902 
903 }
904 
905 static msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
906 {
907  msg_t *msg =(msg_t*)create_l3msg(CC_RESUME | REQUEST, MT_RESUME, bc?bc->l3_id:-1, sizeof(RESUME_t) ,nt);
908 
909 #ifdef DEBUG
910  printf("Building RESUME Msg\n");
911 #endif
912  return msg;
913 }
914 
915 static void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
916 {
917 #ifdef DEBUG
918  printf("Parsing HOLD_ACKNOWLEDGE Msg\n");
919 #endif
920 
921 
922 }
923 
924 static msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
925 {
926  msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_ACKNOWLEDGE | REQUEST, MT_HOLD_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(HOLD_ACKNOWLEDGE_t) ,nt);
927 
928 #ifdef DEBUG
929  printf("Building HOLD_ACKNOWLEDGE Msg\n");
930 #endif
931  return msg;
932 }
933 
934 static void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
935 {
936 #ifdef DEBUG
937  printf("Parsing SUSPEND_ACKNOWLEDGE Msg\n");
938 #endif
939 
940 
941 }
942 
943 static msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
944 {
945  msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_ACKNOWLEDGE | REQUEST, MT_SUSPEND_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SUSPEND_ACKNOWLEDGE_t) ,nt);
946 
947 #ifdef DEBUG
948  printf("Building SUSPEND_ACKNOWLEDGE Msg\n");
949 #endif
950  return msg;
951 }
952 
953 static void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
954 {
955 #ifdef DEBUG
956  printf("Parsing RESUME_ACKNOWLEDGE Msg\n");
957 #endif
958 
959 
960 }
961 
962 static msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
963 {
964  msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_ACKNOWLEDGE | REQUEST, MT_RESUME_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RESUME_ACKNOWLEDGE_t) ,nt);
965 
966 #ifdef DEBUG
967  printf("Building RESUME_ACKNOWLEDGE Msg\n");
968 #endif
969  return msg;
970 }
971 
972 static void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
973 {
974 #ifdef DEBUG
975  printf("Parsing HOLD_REJECT Msg\n");
976 #endif
977 
978 
979 }
980 
981 static msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
982 {
983  msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_REJECT | REQUEST, MT_HOLD_REJECT, bc?bc->l3_id:-1, sizeof(HOLD_REJECT_t) ,nt);
984 
985 #ifdef DEBUG
986  printf("Building HOLD_REJECT Msg\n");
987 #endif
988  return msg;
989 }
990 
991 static void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
992 {
993 #ifdef DEBUG
994  printf("Parsing RETRIEVE Msg\n");
995 #endif
996 
997 
998 }
999 
1000 static msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1001 {
1002  msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE | REQUEST, MT_RETRIEVE, bc?bc->l3_id:-1, sizeof(RETRIEVE_t) ,nt);
1003 
1004 #ifdef DEBUG
1005  printf("Building RETRIEVE Msg\n");
1006 #endif
1007  return msg;
1008 }
1009 
1010 static void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1011 {
1012 #ifdef DEBUG
1013  printf("Parsing RETRIEVE_ACKNOWLEDGE Msg\n");
1014 #endif
1015 
1016 
1017 }
1018 
1019 static msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1020 {
1021  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1022  RETRIEVE_ACKNOWLEDGE_t *retrieve_acknowledge;
1023  msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_ACKNOWLEDGE | REQUEST, MT_RETRIEVE_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RETRIEVE_ACKNOWLEDGE_t) ,nt);
1024 
1025  retrieve_acknowledge=(RETRIEVE_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
1026 
1027  enc_ie_channel_id(&retrieve_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
1028 #ifdef DEBUG
1029  printf("Building RETRIEVE_ACKNOWLEDGE Msg\n");
1030 #endif
1031  return msg;
1032 }
1033 
1034 static void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1035 {
1036 #ifdef DEBUG
1037  printf("Parsing RETRIEVE_REJECT Msg\n");
1038 #endif
1039 
1040 
1041 }
1042 
1043 static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1044 {
1045  msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_REJECT | REQUEST, MT_RETRIEVE_REJECT, bc?bc->l3_id:-1, sizeof(RETRIEVE_REJECT_t) ,nt);
1046 
1047 #ifdef DEBUG
1048  printf("Building RETRIEVE_REJECT Msg\n");
1049 #endif
1050  return msg;
1051 }
1052 
1053 static void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1054 {
1055  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1056  DISCONNECT_t *disconnect = (DISCONNECT_t *) (msg->data + HEADER_LEN);
1057  int location;
1058  int cause;
1059  dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)(disconnect), &location, &cause, nt,bc);
1060  if (cause>0) bc->cause=cause;
1061 
1062  dec_ie_facility(disconnect->FACILITY, (Q931_info_t *) disconnect, &bc->fac_in, nt, bc);
1063 
1064  dec_ie_progress(disconnect->PROGRESS, (Q931_info_t *)disconnect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
1065 #ifdef DEBUG
1066  printf("Parsing DISCONNECT Msg\n");
1067 #endif
1068 
1069 
1070 }
1071 
1072 static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1073 {
1074  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1075  DISCONNECT_t *disconnect;
1076  msg_t *msg =(msg_t*)create_l3msg(CC_DISCONNECT | REQUEST, MT_DISCONNECT, bc?bc->l3_id:-1, sizeof(DISCONNECT_t) ,nt);
1077 
1078  disconnect=(DISCONNECT_t*)((msg->data+HEADER_LEN));
1079 
1080  enc_ie_cause(&disconnect->CAUSE, msg, (nt)?1:0, bc->out_cause,nt,bc);
1081  if (nt) {
1082  enc_ie_progress(&disconnect->PROGRESS, msg, 0, nt ? 1 : 5, 8, nt, bc);
1083  }
1084 
1085  if (bc->fac_out.Function != Fac_None) {
1086  enc_ie_facility(&disconnect->FACILITY, msg, &bc->fac_out, nt);
1087  }
1088 
1089  if (bc->uulen) {
1090  int protocol=4;
1091  enc_ie_useruser(&disconnect->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
1092  cb_log(1, bc->port, "ENCODING USERUSERINFO:%s\n", bc->uu);
1093  }
1094 
1095 #ifdef DEBUG
1096  printf("Building DISCONNECT Msg\n");
1097 #endif
1098  return msg;
1099 }
1100 
1101 static void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1102 {
1103  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1104  RESTART_t *restart = (RESTART_t *) (msg->data + HEADER_LEN);
1105 
1106  struct misdn_stack *stack=get_stack_by_bc(bc);
1107 
1108 #ifdef DEBUG
1109  printf("Parsing RESTART Msg\n");
1110 #endif
1111 
1112  {
1113  int exclusive;
1114  dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc);
1115  cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n", bc->restart_channel);
1116  }
1117 
1118 }
1119 
1120 static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1121 {
1122  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1123  RESTART_t *restart;
1124  msg_t *msg =(msg_t*)create_l3msg(CC_RESTART | REQUEST, MT_RESTART, bc?bc->l3_id:-1, sizeof(RESTART_t) ,nt);
1125 
1126  restart=(RESTART_t*)((msg->data+HEADER_LEN));
1127 
1128 #ifdef DEBUG
1129  printf("Building RESTART Msg\n");
1130 #endif
1131 
1132  if (bc->channel > 0) {
1133  enc_ie_channel_id(&restart->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
1134  enc_ie_restart_ind(&restart->RESTART_IND, msg, 0x80, nt, bc);
1135  } else {
1136  enc_ie_restart_ind(&restart->RESTART_IND, msg, 0x87, nt, bc);
1137  }
1138 
1139  cb_log(0,bc->port, "Restarting channel %d\n", bc->channel);
1140  return msg;
1141 }
1142 
1143 static void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1144 {
1145  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1146  RELEASE_t *release = (RELEASE_t *) (msg->data + HEADER_LEN);
1147  int location;
1148  int cause;
1149 
1150  dec_ie_cause(release->CAUSE, (Q931_info_t *)(release), &location, &cause, nt,bc);
1151  if (cause>0) bc->cause=cause;
1152 
1153  dec_ie_facility(release->FACILITY, (Q931_info_t *) release, &bc->fac_in, nt, bc);
1154 
1155 #ifdef DEBUG
1156  printf("Parsing RELEASE Msg\n");
1157 #endif
1158 
1159 
1160 }
1161 
1162 static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1163 {
1164  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1165  RELEASE_t *release;
1166  msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, bc?bc->l3_id:-1, sizeof(RELEASE_t) ,nt);
1167 
1168  release=(RELEASE_t*)((msg->data+HEADER_LEN));
1169 
1170  if (bc->out_cause>= 0)
1171  enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
1172 
1173  if (bc->fac_out.Function != Fac_None) {
1174  enc_ie_facility(&release->FACILITY, msg, &bc->fac_out, nt);
1175  }
1176 
1177  if (bc->uulen) {
1178  int protocol=4;
1179  enc_ie_useruser(&release->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
1180  cb_log(1, bc->port, "ENCODING USERUSERINFO:%s\n", bc->uu);
1181  }
1182 
1183 #ifdef DEBUG
1184  printf("Building RELEASE Msg\n");
1185 #endif
1186  return msg;
1187 }
1188 
1189 static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1190 {
1191  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1192  RELEASE_COMPLETE_t *release_complete = (RELEASE_COMPLETE_t *) (msg->data + HEADER_LEN);
1193  int location;
1194  int cause;
1195  iframe_t *frm = (iframe_t*) msg->data;
1196 
1197  struct misdn_stack *stack=get_stack_by_bc(bc);
1198  mISDNuser_head_t *hh;
1199  hh=(mISDNuser_head_t*)msg->data;
1200 
1201  /*hh=(mISDN_head_t*)msg->data;
1202  mISDN_head_t *hh;*/
1203 
1204  if (nt) {
1205  if (hh->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
1206  cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] \n");
1207  return;
1208  }
1209  } else {
1210  if (frm->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
1211  cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] \n");
1212  return;
1213  }
1214  }
1215  dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &cause, nt,bc);
1216  if (cause>0) bc->cause=cause;
1217 
1218  dec_ie_facility(release_complete->FACILITY, (Q931_info_t *) release_complete, &bc->fac_in, nt, bc);
1219 
1220 #ifdef DEBUG
1221  printf("Parsing RELEASE_COMPLETE Msg\n");
1222 #endif
1223 }
1224 
1225 static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1226 {
1227  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1228  RELEASE_COMPLETE_t *release_complete;
1229  msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, bc?bc->l3_id:-1, sizeof(RELEASE_COMPLETE_t) ,nt);
1230 
1231  release_complete=(RELEASE_COMPLETE_t*)((msg->data+HEADER_LEN));
1232 
1233  enc_ie_cause(&release_complete->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
1234 
1235  if (bc->fac_out.Function != Fac_None) {
1236  enc_ie_facility(&release_complete->FACILITY, msg, &bc->fac_out, nt);
1237  }
1238 
1239  if (bc->uulen) {
1240  int protocol=4;
1241  enc_ie_useruser(&release_complete->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
1242  cb_log(1, bc->port, "ENCODING USERUSERINFO:%s\n", bc->uu);
1243  }
1244 
1245 #ifdef DEBUG
1246  printf("Building RELEASE_COMPLETE Msg\n");
1247 #endif
1248  return msg;
1249 }
1250 
1251 static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1252 {
1253  int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1254  FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
1255  Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN);
1256  unsigned char *p = NULL;
1257 #if defined(AST_MISDN_ENHANCEMENTS)
1258  int description_code;
1259  int type;
1260  int plan;
1261  int present;
1262  char number[sizeof(bc->redirecting.to.number)];
1263 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1264 
1265 #ifdef DEBUG
1266  printf("Parsing FACILITY Msg\n");
1267 #endif
1268 
1269  bc->fac_in.Function = Fac_None;
1270 
1271  if (!bc->nt) {
1272  if (qi->QI_ELEMENT(facility))
1273  p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
1274  } else {
1275  p = facility->FACILITY;
1276  }
1277  if (!p)
1278  return;
1279 
1280  if (decodeFac(p, &bc->fac_in)) {
1281  cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
1282  }
1283 
1284 #if defined(AST_MISDN_ENHANCEMENTS)
1285  dec_ie_notify(facility->NOTIFY, qi, &description_code, nt, bc);
1286  if (description_code < 0) {
1288  } else {
1289  bc->notify_description_code = description_code;
1290  }
1291 
1292  dec_ie_redir_dn(facility->REDIR_DN, qi, &type, &plan, &present, number, sizeof(number), nt, bc);
1293  if (0 <= type) {
1294  bc->redirecting.to_changed = 1;
1295 
1297  bc->redirecting.to.number_plan = plan;
1298  switch (present) {
1299  default:
1300  case 0:
1301  bc->redirecting.to.presentation = 0; /* presentation allowed */
1302  break;
1303  case 1:
1304  bc->redirecting.to.presentation = 1; /* presentation restricted */
1305  break;
1306  case 2:
1307  bc->redirecting.to.presentation = 2; /* Number not available */
1308  break;
1309  }
1310  bc->redirecting.to.screening = 0; /* Unscreened */
1311  strcpy(bc->redirecting.to.number, number);
1312  }
1313 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1314 }
1315 
1316 static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1317 {
1318  int len;
1319  int HEADER_LEN;
1320  unsigned char *ie_fac;
1321  unsigned char fac_tmp[256];
1322  msg_t *msg;
1323  FACILITY_t *facility;
1324  Q931_info_t *qi;
1325 
1326 #ifdef DEBUG
1327  printf("Building FACILITY Msg\n");
1328 #endif
1329 
1330  len = encodeFac(fac_tmp, &(bc->fac_out));
1331  if (len <= 0) {
1332  /*
1333  * mISDN does not know how to build the requested facility structure
1334  * Clear facility information
1335  */
1336  bc->fac_out.Function = Fac_None;
1337 
1338 #if defined(AST_MISDN_ENHANCEMENTS)
1339  /* Clear other one shot information. */
1341  bc->redirecting.to_changed = 0;
1342 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1343  return NULL;
1344  }
1345 
1346  msg = (msg_t *) create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc ? bc->l3_id : -1, sizeof(FACILITY_t), nt);
1347  HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1348  facility = (FACILITY_t *) (msg->data + HEADER_LEN);
1349 
1350  ie_fac = msg_put(msg, len);
1351  if (bc->nt) {
1352  facility->FACILITY = ie_fac + 1;
1353  } else {
1354  qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1355  qi->QI_ELEMENT(facility) = ie_fac - (unsigned char *)qi - sizeof(Q931_info_t);
1356  }
1357 
1358  memcpy(ie_fac, fac_tmp, len);
1359 
1360  /* Clear facility information */
1361  bc->fac_out.Function = Fac_None;
1362 
1363  if (*bc->display) {
1364 #ifdef DEBUG
1365  printf("Sending %s as Display\n", bc->display);
1366 #endif
1367  enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc);
1368  }
1369 
1370 #if defined(AST_MISDN_ENHANCEMENTS)
1372  enc_ie_notify(&facility->NOTIFY, msg, bc->notify_description_code, nt, bc);
1374  }
1375 
1376  if (bc->redirecting.to_changed) {
1377  bc->redirecting.to_changed = 0;
1378  switch (bc->outgoing_colp) {
1379  case 0:/* pass */
1380  case 1:/* restricted */
1381  enc_ie_redir_dn(&facility->REDIR_DN, msg, bc->redirecting.to.number_type,
1383  bc->redirecting.to.number, nt, bc);
1384  break;
1385  default:
1386  break;
1387  }
1388  }
1389 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1390 
1391  return msg;
1392 }
1393 
1394 #if defined(AST_MISDN_ENHANCEMENTS)
1395 /*!
1396  * \internal
1397  * \brief Parse a received REGISTER message
1398  *
1399  * \param msgs Search table entry that called us.
1400  * \param msg Received message contents
1401  * \param bc Associated B channel
1402  * \param nt TRUE if in NT mode.
1403  *
1404  * \return Nothing
1405  */
1406 static void parse_register(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1407 {
1408  int HEADER_LEN;
1409  REGISTER_t *reg;
1410 
1411  HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1412  reg = (REGISTER_t *) (msg->data + HEADER_LEN);
1413 
1414  /*
1415  * A facility ie is optional.
1416  * The peer may just be establishing a connection to send
1417  * messages later.
1418  */
1419  dec_ie_facility(reg->FACILITY, (Q931_info_t *) reg, &bc->fac_in, nt, bc);
1420 }
1421 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1422 
1423 #if defined(AST_MISDN_ENHANCEMENTS)
1424 /*!
1425  * \internal
1426  * \brief Construct a REGISTER message
1427  *
1428  * \param msgs Search table entry that called us.
1429  * \param bc Associated B channel
1430  * \param nt TRUE if in NT mode.
1431  *
1432  * \return Allocated built message
1433  */
1434 static msg_t *build_register(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1435 {
1436  int HEADER_LEN;
1437  REGISTER_t *reg;
1438  msg_t *msg;
1439 
1440  msg = (msg_t *) create_l3msg(CC_REGISTER | REQUEST, MT_REGISTER, bc ? bc->l3_id : -1, sizeof(REGISTER_t), nt);
1441  HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1442  reg = (REGISTER_t *) (msg->data + HEADER_LEN);
1443 
1444  if (bc->fac_out.Function != Fac_None) {
1445  enc_ie_facility(&reg->FACILITY, msg, &bc->fac_out, nt);
1446  }
1447 
1448  return msg;
1449 }
1450 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1451 
1452 static void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1453 {
1454  int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1455  NOTIFY_t *notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
1456  int description_code;
1457  int type;
1458  int plan;
1459  int present;
1460  char number[sizeof(bc->redirecting.to.number)];
1461 
1462 #ifdef DEBUG
1463  printf("Parsing NOTIFY Msg\n");
1464 #endif
1465 
1466  dec_ie_notify(notify->NOTIFY, (Q931_info_t *) notify, &description_code, nt, bc);
1467  if (description_code < 0) {
1469  } else {
1470  bc->notify_description_code = description_code;
1471  }
1472 
1473  dec_ie_redir_dn(notify->REDIR_DN, (Q931_info_t *) notify, &type, &plan, &present, number, sizeof(number), nt, bc);
1474  if (0 <= type) {
1475  bc->redirecting.to_changed = 1;
1476 
1478  bc->redirecting.to.number_plan = plan;
1479  switch (present) {
1480  default:
1481  case 0:
1482  bc->redirecting.to.presentation = 0; /* presentation allowed */
1483  break;
1484  case 1:
1485  bc->redirecting.to.presentation = 1; /* presentation restricted */
1486  break;
1487  case 2:
1488  bc->redirecting.to.presentation = 2; /* Number not available */
1489  break;
1490  }
1491  bc->redirecting.to.screening = 0; /* Unscreened */
1492  strcpy(bc->redirecting.to.number, number);
1493  }
1494 }
1495 
1496 static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1497 {
1498  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1499  NOTIFY_t *notify;
1500  msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY, bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt);
1501 
1502 #ifdef DEBUG
1503  printf("Building NOTIFY Msg\n");
1504 #endif
1505 
1506  notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
1507 
1508  enc_ie_notify(&notify->NOTIFY, msg, bc->notify_description_code, nt, bc);
1510 
1511  if (bc->redirecting.to_changed) {
1512  bc->redirecting.to_changed = 0;
1513  switch (bc->outgoing_colp) {
1514  case 0:/* pass */
1515  case 1:/* restricted */
1516  enc_ie_redir_dn(&notify->REDIR_DN, msg, bc->redirecting.to.number_type,
1518  bc->redirecting.to.number, nt, bc);
1519  break;
1520  default:
1521  break;
1522  }
1523  }
1524  return msg;
1525 }
1526 
1527 static void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1528 {
1529 #ifdef DEBUG
1530  printf("Parsing STATUS_ENQUIRY Msg\n");
1531 #endif
1532 }
1533 
1534 static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1535 {
1536  msg_t *msg =(msg_t*)create_l3msg(CC_STATUS_ENQUIRY | REQUEST, MT_STATUS_ENQUIRY, bc?bc->l3_id:-1, sizeof(STATUS_ENQUIRY_t) ,nt);
1537 
1538 #ifdef DEBUG
1539  printf("Building STATUS_ENQUIRY Msg\n");
1540 #endif
1541  return msg;
1542 }
1543 
1544 static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1545 {
1546  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1547  INFORMATION_t *information = (INFORMATION_t *) (msg->data + HEADER_LEN);
1548  int type, plan;
1549 
1550  dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *) information, &type, &plan, bc->info_dad, sizeof(bc->info_dad), nt, bc);
1551  dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad), nt, bc);
1552 
1553 #ifdef DEBUG
1554  printf("Parsing INFORMATION Msg\n");
1555 #endif
1556 }
1557 
1558 static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1559 {
1560  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1561  INFORMATION_t *information;
1562  msg_t *msg =(msg_t*)create_l3msg(CC_INFORMATION | REQUEST, MT_INFORMATION, bc?bc->l3_id:-1, sizeof(INFORMATION_t) ,nt);
1563 
1564  information=(INFORMATION_t*)((msg->data+HEADER_LEN));
1565 
1566  enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
1567 
1568  {
1569  if (*bc->display) {
1570 #ifdef DEBUG
1571  printf("Sending %s as Display\n", bc->display);
1572 #endif
1573  enc_ie_display(&information->DISPLAY, msg, bc->display, nt,bc);
1574  }
1575  }
1576 
1577 #ifdef DEBUG
1578  printf("Building INFORMATION Msg\n");
1579 #endif
1580  return msg;
1581 }
1582 
1583 static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1584 {
1585  int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1586  STATUS_t *status = (STATUS_t *) (msg->data + HEADER_LEN);
1587  int location;
1588  int cause;
1589 
1590  dec_ie_cause(status->CAUSE, (Q931_info_t *)(status), &location, &cause, nt,bc);
1591  if (cause>0) bc->cause=cause;
1592 
1593 #ifdef DEBUG
1594  printf("Parsing STATUS Msg\n");
1595 #endif
1596 }
1597 
1598 static msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1599 {
1600  msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
1601 
1602 #ifdef DEBUG
1603  printf("Building STATUS Msg\n");
1604 #endif
1605  return msg;
1606 }
1607 
1608 static void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1609 {
1610 #ifdef DEBUG
1611  printf("Parsing STATUS Msg\n");
1612 #endif
1613 }
1614 
1615 static msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1616 {
1617  msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
1618 
1619 #ifdef DEBUG
1620  printf("Building STATUS Msg\n");
1621 #endif
1622  return msg;
1623 }
1624 
1625 
1626 /************************************/
1627 
1628 
1629 
1630 
1631 /** Msg Array **/
1632 
1633 struct isdn_msg msgs_g[] = {
1634 /* *INDENT-OFF* */
1635  /* misdn_msg, event, msg_parser, msg_builder, info */
1636  { CC_PROCEEDING, EVENT_PROCEEDING, parse_proceeding, build_proceeding, "PROCEEDING" },
1637  { CC_ALERTING, EVENT_ALERTING, parse_alerting, build_alerting, "ALERTING" },
1638  { CC_PROGRESS, EVENT_PROGRESS, parse_progress, build_progress, "PROGRESS" },
1639  { CC_SETUP, EVENT_SETUP, parse_setup, build_setup, "SETUP" },
1640 #if defined(AST_MISDN_ENHANCEMENTS)
1641  { CC_REGISTER, EVENT_REGISTER, parse_register, build_register, "REGISTER" },
1642 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1643  { CC_CONNECT, EVENT_CONNECT, parse_connect, build_connect, "CONNECT" },
1644  { CC_SETUP_ACKNOWLEDGE, EVENT_SETUP_ACKNOWLEDGE, parse_setup_acknowledge, build_setup_acknowledge, "SETUP_ACKNOWLEDGE" },
1645  { CC_CONNECT_ACKNOWLEDGE, EVENT_CONNECT_ACKNOWLEDGE, parse_connect_acknowledge, build_connect_acknowledge, "CONNECT_ACKNOWLEDGE " },
1646  { CC_USER_INFORMATION, EVENT_USER_INFORMATION, parse_user_information, build_user_information, "USER_INFORMATION" },
1647  { CC_SUSPEND_REJECT, EVENT_SUSPEND_REJECT, parse_suspend_reject, build_suspend_reject, "SUSPEND_REJECT" },
1648  { CC_RESUME_REJECT, EVENT_RESUME_REJECT, parse_resume_reject, build_resume_reject, "RESUME_REJECT" },
1649  { CC_HOLD, EVENT_HOLD, parse_hold, build_hold, "HOLD" },
1650  { CC_SUSPEND, EVENT_SUSPEND, parse_suspend, build_suspend, "SUSPEND" },
1651  { CC_RESUME, EVENT_RESUME, parse_resume, build_resume, "RESUME" },
1652  { CC_HOLD_ACKNOWLEDGE, EVENT_HOLD_ACKNOWLEDGE, parse_hold_acknowledge, build_hold_acknowledge, "HOLD_ACKNOWLEDGE" },
1653  { CC_SUSPEND_ACKNOWLEDGE, EVENT_SUSPEND_ACKNOWLEDGE, parse_suspend_acknowledge, build_suspend_acknowledge, "SUSPEND_ACKNOWLEDGE" },
1654  { CC_RESUME_ACKNOWLEDGE, EVENT_RESUME_ACKNOWLEDGE, parse_resume_acknowledge, build_resume_acknowledge, "RESUME_ACKNOWLEDGE" },
1655  { CC_HOLD_REJECT, EVENT_HOLD_REJECT, parse_hold_reject, build_hold_reject, "HOLD_REJECT" },
1656  { CC_RETRIEVE, EVENT_RETRIEVE, parse_retrieve, build_retrieve, "RETRIEVE" },
1657  { CC_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_ACKNOWLEDGE, parse_retrieve_acknowledge, build_retrieve_acknowledge, "RETRIEVE_ACKNOWLEDGE" },
1658  { CC_RETRIEVE_REJECT, EVENT_RETRIEVE_REJECT, parse_retrieve_reject, build_retrieve_reject, "RETRIEVE_REJECT" },
1659  { CC_DISCONNECT, EVENT_DISCONNECT, parse_disconnect, build_disconnect, "DISCONNECT" },
1660  { CC_RESTART, EVENT_RESTART, parse_restart, build_restart, "RESTART" },
1661  { CC_RELEASE, EVENT_RELEASE, parse_release, build_release, "RELEASE" },
1662  { CC_RELEASE_COMPLETE, EVENT_RELEASE_COMPLETE, parse_release_complete, build_release_complete, "RELEASE_COMPLETE" },
1663  { CC_FACILITY, EVENT_FACILITY, parse_facility, build_facility, "FACILITY" },
1664  { CC_NOTIFY, EVENT_NOTIFY, parse_notify, build_notify, "NOTIFY" },
1665  { CC_STATUS_ENQUIRY, EVENT_STATUS_ENQUIRY, parse_status_enquiry, build_status_enquiry, "STATUS_ENQUIRY" },
1666  { CC_INFORMATION, EVENT_INFORMATION, parse_information, build_information, "INFORMATION" },
1667  { CC_STATUS, EVENT_STATUS, parse_status, build_status, "STATUS" },
1668  { CC_TIMEOUT, EVENT_TIMEOUT, parse_timeout, build_timeout, "TIMEOUT" },
1669  { 0, 0, NULL, NULL, NULL }
1670 /* *INDENT-ON* */
1671 };
1672 
1673 #define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg))
1674 
1675 /** INTERFACE FCTS ***/
1676 int isdn_msg_get_index(struct isdn_msg msgs[], msg_t *msg, int nt)
1677 {
1678  int i;
1679 
1680  if (nt){
1681  mISDNuser_head_t *hh = (mISDNuser_head_t*)msg->data;
1682 
1683  for (i=0; i< msgs_max -1; i++) {
1684  if ( (hh->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
1685  }
1686 
1687  } else {
1688  iframe_t *frm = (iframe_t*)msg->data;
1689 
1690  for (i=0; i< msgs_max -1; i++)
1691  if ( (frm->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
1692  }
1693 
1694  return -1;
1695 }
1696 
1697 int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int nt)
1698 {
1699  int i;
1700  for (i=0; i< msgs_max; i++)
1701  if ( event == msgs[i].event) return i;
1702 
1703  cb_log(10,0, "get_index: event not found!\n");
1704 
1705  return -1;
1706 }
1707 
1708 enum event_e isdn_msg_get_event(struct isdn_msg msgs[], msg_t *msg, int nt)
1709 {
1710  int i=isdn_msg_get_index(msgs, msg, nt);
1711  if(i>=0) return msgs[i].event;
1712  return EVENT_UNKNOWN;
1713 }
1714 
1715 char * isdn_msg_get_info(struct isdn_msg msgs[], msg_t *msg, int nt)
1716 {
1717  int i=isdn_msg_get_index(msgs, msg, nt);
1718  if(i>=0) return msgs[i].info;
1719  return NULL;
1720 }
1721 
1722 
1723 char EVENT_CLEAN_INFO[] = "CLEAN_UP";
1724 char EVENT_DTMF_TONE_INFO[] = "DTMF_TONE";
1725 char EVENT_NEW_L3ID_INFO[] = "NEW_L3ID";
1726 char EVENT_NEW_BC_INFO[] = "NEW_BC";
1727 char EVENT_PORT_ALARM_INFO[] = "ALARM";
1728 char EVENT_NEW_CHANNEL_INFO[] = "NEW_CHANNEL";
1729 char EVENT_BCHAN_DATA_INFO[] = "BCHAN_DATA";
1730 char EVENT_BCHAN_ACTIVATED_INFO[] = "BCHAN_ACTIVATED";
1731 char EVENT_TONE_GENERATE_INFO[] = "TONE_GENERATE";
1732 char EVENT_BCHAN_ERROR_INFO[] = "BCHAN_ERROR";
1733 
1734 char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
1735 {
1736  int i=isdn_msg_get_index_by_event(msgs, event, nt);
1737 
1738  if(i>=0) return msgs[i].info;
1739 
1740  if (event == EVENT_CLEANUP) return EVENT_CLEAN_INFO;
1741  if (event == EVENT_DTMF_TONE) return EVENT_DTMF_TONE_INFO;
1742  if (event == EVENT_NEW_L3ID) return EVENT_NEW_L3ID_INFO;
1743  if (event == EVENT_NEW_BC) return EVENT_NEW_BC_INFO;
1744  if (event == EVENT_NEW_CHANNEL) return EVENT_NEW_CHANNEL_INFO;
1745  if (event == EVENT_BCHAN_DATA) return EVENT_BCHAN_DATA_INFO;
1747  if (event == EVENT_TONE_GENERATE) return EVENT_TONE_GENERATE_INFO;
1748  if (event == EVENT_PORT_ALARM) return EVENT_PORT_ALARM_INFO;
1749  if (event == EVENT_BCHAN_ERROR) return EVENT_BCHAN_ERROR_INFO;
1750 
1751  return NULL;
1752 }
1753 
1754 int isdn_msg_parse_event(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1755 {
1756  int i=isdn_msg_get_index(msgs, msg, nt);
1757  if(i<0) return -1;
1758 
1759  msgs[i].msg_parser(msgs, msg, bc, nt);
1760  return 0;
1761 }
1762 
1763 msg_t * isdn_msg_build_event(struct isdn_msg msgs[], struct misdn_bchannel *bc, enum event_e event, int nt)
1764 {
1765  int i=isdn_msg_get_index_by_event(msgs, event, nt);
1766  if(i<0) return NULL;
1767 
1768  return msgs[i].msg_builder(msgs, bc, nt);
1769 }
static char user[512]
static void parse_resume_reject(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, char *user, int user_len, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1324
static void parse_suspend_reject(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static const char type[]
Definition: chan_ooh323.c:109
char keypad[MISDN_MAX_KEYPAD_LEN]
Q.931 Keypad Facility IE contents.
Definition: isdn_lib.h:647
static msg_t * build_restart(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int display_setup
Put a display ie in the SETUP message.
Definition: isdn_lib.h:585
static void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt, struct misdn_bchannel *bc)
Definition: ie.c:998
static void enc_ie_calling_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, char *number, int nt, struct misdn_bchannel *bc)
Definition: ie.c:416
struct FacParm fac_out
Outbound FACILITY message function type and contents.
Definition: isdn_lib.h:512
static void parse_release(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static msg_t * build_timeout(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
char number[MISDN_MAX_NUMBER_LEN]
Phone number (Address)
Definition: isdn_lib.h:298
static void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
Definition: ie.c:471
static void parse_resume_acknowledge(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static msg_t * build_retrieve_reject(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static void parse_information(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
#define msgs_max
static msg_t * build_resume(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#define bc
int uulen
User-User information string length in uu[].
Definition: isdn_lib.h:666
#define ANY_CHANNEL
char uu[256]
User-User information string.
Definition: isdn_lib.h:663
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, char *keypad, size_t keypad_len, int nt, struct misdn_bchannel *bc)
Definition: ie.c:973
static void dec_ie_complete(unsigned char *p, Q931_info_t *qi, int *complete, int nt, struct misdn_bchannel *bc)
Definition: ie.c:83
#define mISDNUSER_HEAD_SIZE
int restart_channel
B channel to restart if received a RESTART message.
Definition: isdn_lib.h:408
static msg_t * build_hold_reject(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static void enc_ie_connected_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, char *number, int nt, struct misdn_bchannel *bc)
Definition: ie.c:518
int ces
Not used. Saved mISDN stack CONNECT_t ces value.
Definition: isdn_lib.h:405
static void parse_alerting(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
int mode
Q.931 Bearer Capability IE Transfer Mode field. Initialized to 0 (Circuit). Altered by incoming SETUP...
Definition: isdn_lib.h:619
static void enc_ie_restart_ind(unsigned char **ntmode, msg_t *msg, unsigned char rind, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1399
char * info
static msg_t * build_information(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
char EVENT_DTMF_TONE_INFO[]
enum event_response_e(* cb_event)(enum event_e event, struct misdn_bchannel *bc, void *user_data)
Definition: isdn_lib.c:30
B channel control structure.
Definition: isdn_lib.h:324
int outgoing_colp
Select what to do with outgoing COLP information.
Definition: isdn_lib.h:594
int presentation
Number presentation restriction code 0=Allowed, 1=Restricted, 2=Unavailable.
Definition: isdn_lib.h:277
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
static msg_t * build_proceeding(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int sending_complete
TRUE if all digits necessary to complete the call are available. No more INFORMATION messages are nee...
Definition: isdn_lib.h:470
#define HEADER_LEN
Definition: astman.c:222
char EVENT_NEW_L3ID_INFO[]
static void parse_hold(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
char EVENT_BCHAN_ACTIVATED_INFO[]
int capability
SETUP message bearer capability field code value.
Definition: isdn_lib.h:609
Definition: muted.c:95
#define NULL
Definition: resample.c:96
Definition: dsp.c:117
static void parse_facility(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, char *number, int nt, struct misdn_bchannel *bc)
Definition: ie.c:351
char EVENT_NEW_CHANNEL_INFO[]
static void parse_restart(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
struct misdn_party_id to
Where the call is being redirected toward (Sent to the calling party)
Definition: isdn_lib.h:310
static void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int channel, int nt, struct misdn_bchannel *bc)
Definition: ie.c:691
int progress_location
Progress Indicator IE location field.
Definition: isdn_lib.h:487
static void parse_retrieve(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void parse_hold_acknowledge(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void enc_ie_keypad(unsigned char **ntmode, msg_t *msg, char *keypad, int nt, struct misdn_bchannel *bc)
Definition: ie.c:947
static void parse_suspend(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
msg_t * create_l3msg(int prim, int mt, int dinfo, int size, int ntmode)
Definition: isdn_lib.c:371
Number structure.
Definition: app_followme.c:154
int isdn_msg_parse_event(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static msg_t * build_status_enquiry(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user, int *async, int *urate, int *stopbits, int *dbits, int *parity, int nt, struct misdn_bchannel *bc)
Definition: ie.c:160
static void dec_ie_progress(unsigned char *p, Q931_info_t *qi, int *coding, int *location, int *progress, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1084
static msg_t * build_setup_acknowledge(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static msg_t * build_setup(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static void dec_ie_facility(unsigned char *p, Q931_info_t *qi, struct FacParm *fac, int nt, struct misdn_bchannel *bc)
static void parse_setup_acknowledge(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
char number[MISDN_MAX_NUMBER_LEN]
Dialed/Called Phone Number (Address)
Definition: isdn_lib.h:266
char display[84]
Display message that can be displayed by the user phone.
Definition: isdn_lib.h:642
Interface to mISDN.
static msg_t * build_notify(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, char *number, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1235
static void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
Definition: ie.c:387
static msg_t * build_alerting(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int nt
TRUE if NT side of protocol (TE otherwise)
Definition: isdn_lib.h:364
enum mISDN_NUMBER_TYPE number_type
Type-of-number in ISDN terms for the number.
Definition: isdn_lib.h:285
msg_t *(* msg_builder)(struct isdn_msg *msgs, struct misdn_bchannel *bc, int nt)
struct isdn_msg msgs_g[]
static msg_t * build_connect_acknowledge(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int display_connected
Put a display ie in the CONNECT message.
Definition: isdn_lib.h:573
static void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, char *user, int *user_len, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1365
static void build_display_str(char *display, size_t display_length, int display_format, const char *name, const char *number)
struct misdn_party_id caller
Originating/Caller ID information struct.
Definition: isdn_lib.h:343
char name[MISDN_MAX_NAME_LEN]
Subscriber Name.
Definition: isdn_lib.h:295
static void parse_user_information(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
Definition: ie.c:573
struct misdn_stack * get_stack_by_bc(struct misdn_bchannel *bc)
Definition: isdn_lib.c:152
int progress_coding
Progress Indicator IE coding standard field.
Definition: isdn_lib.h:482
Interface to mISDN.
static msg_t * build_user_information(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static msg_t * build_release_complete(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int misdn_lib_is_ptp(int port)
Definition: isdn_lib.c:128
struct misdn_party_id connected
Connected-Party/Connected-Line ID information struct.
Definition: isdn_lib.h:353
struct misdn_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: isdn_lib.h:307
static void dec_ie_cause(unsigned char *p, Q931_info_t *qi, int *location, int *cause, int nt, struct misdn_bchannel *bc)
Definition: ie.c:664
static msg_t * build_suspend(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
enum event_e event
enum mISDN_NUMBER_TYPE number_type
Type-of-number in ISDN terms for the dialed/called number.
Definition: isdn_lib.h:260
static void parse_status(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void enc_ie_redir_nr(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, int reason, char *number, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1114
char EVENT_BCHAN_ERROR_INFO[]
static void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1023
static void parse_setup(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void parse_status_enquiry(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int nt)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int isdn_msg_get_index(struct isdn_msg msgs[], msg_t *msg, int nt)
struct misdn_party_redirecting redirecting
Redirecting information struct (Where a call diversion or transfer was invoked)
Definition: isdn_lib.h:358
char EVENT_NEW_BC_INFO[]
int port
Logical Layer 1 port associated with this B channel.
Definition: isdn_lib.h:370
static void parse_retrieve_acknowledge(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, int *reason, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1188
int urate
Q.931 Bearer Capability IE Layer 1 User Rate field.
Definition: isdn_lib.h:629
static msg_t * build_suspend_acknowledge(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
struct misdn_party_dialing dialed
Dialed/Called information struct.
Definition: isdn_lib.h:337
static void enc_ie_complete(unsigned char **ntmode, msg_t *msg, int complete, int nt, struct misdn_bchannel *bc)
Definition: ie.c:56
char EVENT_PORT_ALARM_INFO[]
static void set_channel(struct misdn_bchannel *bc, int channel)
static void enc_ie_display(unsigned char **ntmode, msg_t *msg, char *display, int nt, struct misdn_bchannel *bc)
Definition: ie.c:888
char EVENT_BCHAN_DATA_INFO[]
static const char name[]
Definition: cdr_mysql.c:74
int nt
TRUE if NT side of protocol (TE otherwise)
static void enc_ie_facility(unsigned char **ntmode, msg_t *msg, struct FacParm *fac, int nt)
static void parse_connect(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void parse_progress(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static msg_t * build_facility(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
void(* msg_parser)(struct isdn_msg *msgs, msg_t *msg, struct misdn_bchannel *bc, int nt)
static msg_t * build_suspend_reject(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
unsigned long misdn_msg
static void parse_connect_acknowledge(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static msg_t * build_retrieve(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static msg_t * build_progress(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int to_changed
TRUE if the redirecting.to information has changed.
Definition: isdn_lib.h:319
static void parse_release_complete(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
char * isdn_msg_get_info(struct isdn_msg msgs[], msg_t *msg, int nt)
int channel
Assigned B channel number B1, B2... 0 if not assigned.
Definition: isdn_lib.h:411
char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
static msg_t * build_disconnect(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int out_cause
Q.931 Cause for disconnection code (sent)
Definition: isdn_lib.h:677
static void parse_timeout(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
enum mISDN_REDIRECTING_REASON reason
Reason a call is being redirected (Q.931 field value)
Definition: isdn_lib.h:313
static void parse_resume(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static msg_t * build_connect(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
msg_t * isdn_msg_build_event(struct isdn_msg msgs[], struct misdn_bchannel *bc, enum event_e event, int nt)
static void parse_retrieve_reject(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
int user1
Q.931 Bearer Capability IE User Information Layer 1 Protocol field code.
Definition: isdn_lib.h:624
enum mISDN_NOTIFY_CODE notify_description_code
Notification indicator ie description code.
Definition: isdn_lib.h:606
static void enc_ie_bearer(unsigned char **ntmode, msg_t *msg, int coding, int capability, int mode, int rate, int multi, int user, int nt, struct misdn_bchannel *bc)
Definition: ie.c:100
static msg_t * build_hold(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static void enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int nt, struct misdn_bchannel *bc)
Definition: ie.c:860
int progress_indicator
Progress Indicator IE progress description field. Used to determine if there is an inband audio messa...
Definition: isdn_lib.h:492
static void parse_suspend_acknowledge(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
int rate
Q.931 Bearer Capability IE Information Transfer Rate field. Initialized to 0x10 (64kbit). Altered by incoming SETUP messages.
Definition: isdn_lib.h:616
char EVENT_TONE_GENERATE_INFO[]
static void parse_hold_reject(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
int cause
Q.931 Cause for disconnection code (received)
Definition: isdn_lib.h:671
char info_dad[MISDN_MAX_NUMBER_LEN]
Current overlap dialing digits to/from INFORMATION messages.
Definition: isdn_lib.h:650
static void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1286
int port
Logical Layer 1 port associated with this stack.
static void parse_proceeding(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
static void parse_notify(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
char EVENT_CLEAN_INFO[]
static void enc_ie_cause(unsigned char **ntmode, msg_t *msg, int location, int cause, int nt, struct misdn_bchannel *bc)
Definition: ie.c:617
int screening
Number screening code 0=Unscreened, 1=Passed Screen, 2=Failed Screen, 3=Network Number.
Definition: isdn_lib.h:282
static void parse_disconnect(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
enum event_e isdn_msg_get_event(struct isdn_msg msgs[], msg_t *msg, int nt)
static msg_t * build_release(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static msg_t * build_retrieve_acknowledge(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int law
Companding ALaw/uLaw encoding (INFO_CODEC_ALAW / INFO_CODEC_ULAW)
Definition: isdn_lib.h:612
void(* cb_log)(int level, int port, char *tmpl,...)
Definition: isdn_lib.c:32
struct FacParm fac_in
Inbound FACILITY message function type and contents.
Definition: isdn_lib.h:507
static msg_t * build_resume_reject(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static msg_t * build_hold_acknowledge(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static void enc_ie_progress(unsigned char **ntmode, msg_t *msg, int coding, int location, int progress, int nt, struct misdn_bchannel *bc)
Definition: ie.c:1048
static msg_t * build_resume_acknowledge(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
static void dec_ie_channel_id(unsigned char *p, Q931_info_t *qi, int *exclusive, int *channel, int nt, struct misdn_bchannel *bc)
Definition: ie.c:766
enum mISDN_NUMBER_PLAN number_plan
Type-of-number numbering plan.
Definition: isdn_lib.h:288
enum mISDN_NUMBER_PLAN number_plan
Type-of-number numbering plan.
Definition: isdn_lib.h:263
int l3_id
Layer 3 process ID.
Definition: isdn_lib.h:399
jack_status_t status
Definition: app_jack.c:146
event_e
Definition: isdn_lib.h:119
static msg_t * build_status(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)