Wed Jan 8 2020 09:49:44

Asterisk developer's documentation


chan_misdn.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2006, Christian Richter
5  *
6  * Christian Richter <crich@beronet.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  *
18  */
19 
20 /*!
21  * \file
22  *
23  * \brief the chan_misdn channel driver for Asterisk
24  *
25  * \author Christian Richter <crich@beronet.com>
26  *
27  * \extref MISDN http://www.misdn.org/
28  *
29  * \ingroup channel_drivers
30  */
31 
32 /*!
33  * \note
34  * To use the CCBS/CCNR supplementary service feature and other
35  * supplementary services using FACILITY messages requires a
36  * modified version of mISDN.
37  *
38  * \note
39  * The latest modified mISDN v1.1.x based version is available at:
40  * http://svn.digium.com/svn/thirdparty/mISDN/trunk
41  * http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
42  *
43  * \note
44  * Taged versions of the modified mISDN code are available under:
45  * http://svn.digium.com/svn/thirdparty/mISDN/tags
46  * http://svn.digium.com/svn/thirdparty/mISDNuser/tags
47  */
48 
49 /* Define to enable cli commands to generate canned CCBS messages. */
50 // #define CCBS_TEST_MESSAGES 1
51 
52 /*** MODULEINFO
53  <depend>isdnnet</depend>
54  <depend>misdn</depend>
55  <depend>suppserv</depend>
56  <support_level>extended</support_level>
57  ***/
58 
59 #include "asterisk.h"
60 
61 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 398235 $")
62 
63 #include <pthread.h>
64 #include <sys/socket.h>
65 #include <sys/time.h>
66 #include <arpa/inet.h>
67 #include <fcntl.h>
68 #include <sys/ioctl.h>
69 #include <signal.h>
70 #include <sys/file.h>
71 #include <semaphore.h>
72 #include <ctype.h>
73 #include <time.h>
74 
75 #include "asterisk/channel.h"
76 #include "asterisk/config.h"
77 #include "asterisk/module.h"
78 #include "asterisk/pbx.h"
79 #include "asterisk/io.h"
80 #include "asterisk/frame.h"
81 #include "asterisk/translate.h"
82 #include "asterisk/cli.h"
83 #include "asterisk/musiconhold.h"
84 #include "asterisk/dsp.h"
85 #include "asterisk/file.h"
86 #include "asterisk/callerid.h"
87 #include "asterisk/indications.h"
88 #include "asterisk/app.h"
89 #include "asterisk/features.h"
90 #include "asterisk/term.h"
91 #include "asterisk/sched.h"
92 #include "asterisk/stringfields.h"
93 #include "asterisk/abstract_jb.h"
94 #include "asterisk/causes.h"
95 
96 #include "chan_misdn_config.h"
97 #include "isdn_lib.h"
98 
99 static char global_tracefile[BUFFERSIZE + 1];
100 
101 static int g_config_initialized = 0;
102 
103 struct misdn_jb{
104  int size;
106  char *samples, *ok;
107  int wp,rp;
113 };
114 
115 /*! \brief allocates the jb-structure and initialize the elements */
116 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
117 
118 /*! \brief frees the data and destroys the given jitterbuffer struct */
119 void misdn_jb_destroy(struct misdn_jb *jb);
120 
121 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
122 error (buffer overrun). */
123 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
124 
125 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
126 available data is returned and the return value indicates the number
127 of data. */
128 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
129 
130 static char *complete_ch(struct ast_cli_args *a);
131 static char *complete_debug_port(struct ast_cli_args *a);
132 static char *complete_show_config(struct ast_cli_args *a);
133 
134 /* BEGIN: chan_misdn.h */
135 
136 #if defined(AST_MISDN_ENHANCEMENTS)
137 /*
138  * This timeout duration is to clean up any call completion records that
139  * are forgotten about by the switch.
140  */
141 #define MISDN_CC_RECORD_AGE_MAX (6UL * 60 * 60) /* seconds */
142 
143 #define MISDN_CC_REQUEST_WAIT_MAX 5 /* seconds */
144 
145 /*!
146  * \brief Caller that initialized call completion services
147  *
148  * \details
149  * This data is the payload for a datastore that is put on the channel that
150  * initializes call completion services. This datastore is set to be inherited
151  * by the outbound mISDN channel. When one of these channels hangs up, the
152  * channel pointer will be set to NULL. That way, we can ensure that we do not
153  * touch this channel after it gets destroyed.
154  */
155 struct misdn_cc_caller {
156  /*! \brief The channel that initialized call completion services */
157  struct ast_channel *chan;
158 };
159 
160 struct misdn_cc_notify {
161  /*! \brief Dialplan: Notify extension priority */
162  int priority;
163 
164  /*! \brief Dialplan: Notify extension context */
165  char context[AST_MAX_CONTEXT];
166 
167  /*! \brief Dialplan: Notify extension number (User-A) */
168  char exten[AST_MAX_EXTENSION];
169 };
170 
171 /*! \brief mISDN call completion record */
172 struct misdn_cc_record {
173  /*! \brief Call completion record linked list */
174  AST_LIST_ENTRY(misdn_cc_record) list;
175 
176  /*! \brief Time the record was created. */
177  time_t time_created;
178 
179  /*! \brief MISDN_CC_RECORD_ID value */
180  long record_id;
181 
182  /*!
183  * \brief Logical Layer 1 port associated with this
184  * call completion record
185  */
186  int port;
187 
188  /*! \brief TRUE if point-to-point mode (CCBS-T/CCNR-T mode) */
189  int ptp;
190 
191  /*! \brief Mode specific parameters */
192  union {
193  /*! \brief point-to-point specific parameters. */
194  struct {
195  /*!
196  * \brief Call-completion signaling link.
197  * NULL if signaling link not established.
198  */
199  struct misdn_bchannel *bc;
200 
201  /*!
202  * \brief TRUE if we requested the request retention option
203  * to be enabled.
204  */
205  int requested_retention;
206 
207  /*!
208  * \brief TRUE if the request retention option is enabled.
209  */
210  int retention_enabled;
211  } ptp;
212 
213  /*! \brief point-to-multi-point specific parameters. */
214  struct {
215  /*! \brief CallLinkageID (valid when port determined) */
216  int linkage_id;
217 
218  /*! \breif CCBSReference (valid when activated is TRUE) */
219  int reference_id;
220 
221  /*! \brief globalRecall(0), specificRecall(1) */
222  int recall_mode;
223  } ptmp;
224  } mode;
225 
226  /*! \brief TRUE if call completion activated */
227  int activated;
228 
229  /*! \brief Outstanding message ID (valid when outstanding_message) */
230  int invoke_id;
231 
232  /*! \brief TRUE if waiting for a response from a message (invoke_id is valid) */
233  int outstanding_message;
234 
235  /*! \brief TRUE if activation has been requested */
236  int activation_requested;
237 
238  /*!
239  * \brief TRUE if User-A is free
240  * \note PTMP - Used to answer CCBSStatusRequest.
241  * PTP - Determines how to respond to CCBS_T_RemoteUserFree.
242  */
243  int party_a_free;
244 
245  /*! \brief Error code received from last outstanding message. */
246  enum FacErrorCode error_code;
247 
248  /*! \brief Reject code received from last outstanding message. */
249  enum FacRejectCode reject_code;
250 
251  /*!
252  * \brief Saved struct misdn_bchannel call information when
253  * attempted to call User-B
254  */
255  struct {
256  /*! \brief User-A caller id information */
257  struct misdn_party_id caller;
258 
259  /*! \brief User-B number information */
260  struct misdn_party_dialing dialed;
261 
262  /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */
263  struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
264 
265  /*! \brief SETUP message bearer capability field code value */
266  int capability;
267 
268  /*! \brief TRUE if call made in digital HDLC mode */
269  int hdlc;
270  } redial;
271 
272  /*! \brief Dialplan location to indicate User-B free and User-A is free */
273  struct misdn_cc_notify remote_user_free;
274 
275  /*! \brief Dialplan location to indicate User-B free and User-A is busy */
276  struct misdn_cc_notify b_free;
277 };
278 
279 /*! \brief mISDN call completion record database */
280 static AST_LIST_HEAD_STATIC(misdn_cc_records_db, misdn_cc_record);
281 /*! \brief Next call completion record ID to use */
282 static __u16 misdn_cc_record_id;
283 /*! \brief Next invoke ID to use */
284 static __s16 misdn_invoke_id;
285 
286 static const char misdn_no_response_from_network[] = "No response from network";
287 static const char misdn_cc_record_not_found[] = "Call completion record not found";
288 
289 /* mISDN channel variable names */
290 #define MISDN_CC_RECORD_ID "MISDN_CC_RECORD_ID"
291 #define MISDN_CC_STATUS "MISDN_CC_STATUS"
292 #define MISDN_ERROR_MSG "MISDN_ERROR_MSG"
293 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
294 
296 
298  MISDN_NOTHING = 0, /*!< at beginning */
299  MISDN_WAITING4DIGS, /*!< when waiting for info */
300  MISDN_EXTCANTMATCH, /*!< when asterisk couldn't match our ext */
301  MISDN_INCOMING_SETUP, /*!< for incoming setup */
302  MISDN_DIALING, /*!< when pbx_start */
303  MISDN_PROGRESS, /*!< we have progress */
304  MISDN_PROCEEDING, /*!< we have progress */
305  MISDN_CALLING, /*!< when misdn_call is called */
306  MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
307  MISDN_ALERTING, /*!< when Alerting */
308  MISDN_BUSY, /*!< when BUSY */
309  MISDN_CONNECTED, /*!< when connected */
310  MISDN_DISCONNECTED, /*!< when connected */
311  MISDN_CLEANING, /*!< when hangup from * but we were connected before */
312 };
313 
314 /*! Asterisk created the channel (outgoing call) */
315 #define ORG_AST 1
316 /*! mISDN created the channel (incoming call) */
317 #define ORG_MISDN 2
318 
320  MISDN_HOLD_IDLE, /*!< HOLD not active */
321  MISDN_HOLD_ACTIVE, /*!< Call is held */
322  MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
323  MISDN_HOLD_DISCONNECT, /*!< Held call is being disconnected */
324 };
325 struct hold_info {
326  /*!
327  * \brief Call HOLD state.
328  */
330  /*!
331  * \brief Logical port the channel call record is HELD on
332  * because the B channel is no longer associated.
333  */
334  int port;
335 
336  /*!
337  * \brief Original B channel number the HELD call was using.
338  * \note Used only for debug display messages.
339  */
340  int channel;
341 };
342 
343 #define chan_list_ref(obj, debug) (ao2_t_ref((obj), +1, (debug)), (obj))
344 #define chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL)
345 
346 /*!
347  * \brief Channel call record structure
348  */
349 struct chan_list {
350  /*!
351  * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
352  */
354 
355  /*!
356  * \brief State of the channel
357  */
359 
360  /*!
361  * \brief TRUE if a hangup needs to be queued
362  * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
363  */
365 
366  /*!
367  * \brief TRUE if a channel can be hung up by calling asterisk directly when done.
368  */
370 
371  /*!
372  * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
373  */
375 
376  /*!
377  * \brief Who originally created this channel. ORG_AST or ORG_MISDN
378  */
380 
381  /*!
382  * \brief TRUE of we are not to respond immediately to a SETUP message. Check the dialplan first.
383  * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
384  */
386 
387  int norxtone; /*!< Boolean assigned values but the value is not used. */
388 
389  /*!
390  * \brief TRUE if we are not to generate tones (Playtones)
391  */
392  int notxtone;
393 
394  /*!
395  * \brief TRUE if echo canceller is enabled. Value is toggled.
396  */
398 
399  /*!
400  * \brief TRUE if you want to send Tone Indications to an incoming
401  * ISDN channel on a TE Port.
402  * \note The "incoming_early_audio" boolean read in from /etc/asterisk/misdn.conf
403  */
405 
406  /*!
407  * \brief TRUE if DTMF digits are to be passed inband only.
408  * \note It is settable by the misdn_set_opt() application.
409  */
411 
412  /*!
413  * \brief Pipe file descriptor handles array.
414  * Read from pipe[0], write to pipe[1]
415  */
416  int pipe[2];
417 
418  /*!
419  * \brief Read buffer for inbound audio from pipe[0]
420  */
421  char ast_rd_buf[4096];
422 
423  /*!
424  * \brief Inbound audio frame returned by misdn_read().
425  */
426  struct ast_frame frame;
427 
428  /*!
429  * \brief Fax detection option. (0:no 1:yes 2:yes+nojump)
430  * \note The "faxdetect" option string read in from /etc/asterisk/misdn.conf
431  * \note It is settable by the misdn_set_opt() application.
432  */
434 
435  /*!
436  * \brief Number of seconds to detect a Fax machine when detection enabled.
437  * \note 0 disables the timeout.
438  * \note The "faxdetect_timeout" value read in from /etc/asterisk/misdn.conf
439  */
441 
442  /*!
443  * \brief Starting time of fax detection with timeout when nonzero.
444  */
445  struct timeval faxdetect_tv;
446 
447  /*!
448  * \brief TRUE if a fax has been detected.
449  */
451 
452  /*!
453  * \brief TRUE if we will use the Asterisk DSP to detect DTMF/Fax
454  * \note The "astdtmf" boolean read in from /etc/asterisk/misdn.conf
455  */
456  int ast_dsp;
457 
458  /*!
459  * \brief Jitterbuffer length
460  * \note The "jitterbuffer" value read in from /etc/asterisk/misdn.conf
461  */
462  int jb_len;
463 
464  /*!
465  * \brief Jitterbuffer upper threshold
466  * \note The "jitterbuffer_upper_threshold" value read in from /etc/asterisk/misdn.conf
467  */
469 
470  /*!
471  * \brief Allocated jitterbuffer controller
472  * \note misdn_jb_init() creates the jitterbuffer.
473  * \note Must use misdn_jb_destroy() to clean up.
474  */
475  struct misdn_jb *jb;
476 
477  /*!
478  * \brief Allocated DSP controller
479  * \note ast_dsp_new() creates the DSP controller.
480  * \note Must use ast_dsp_free() to clean up.
481  */
482  struct ast_dsp *dsp;
483 
484  /*!
485  * \brief Associated Asterisk channel structure.
486  */
487  struct ast_channel * ast;
488 
489  /*!
490  * \brief Associated B channel structure.
491  */
493 
494 #if defined(AST_MISDN_ENHANCEMENTS)
495  /*!
496  * \brief Peer channel for which call completion was initialized.
497  */
498  struct misdn_cc_caller *peer;
499 
500  /*! \brief Associated call completion record ID (-1 if not associated) */
501  long record_id;
502 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
503 
504  /*!
505  * \brief HELD channel call information
506  */
507  struct hold_info hold;
508 
509  /*!
510  * \brief From associated B channel: Layer 3 process ID
511  * \note Used to find the HELD channel call record when retrieving a call.
512  */
513  unsigned int l3id;
514 
515  /*!
516  * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
517  * \note Used only for debug display messages.
518  */
519  int addr;
520 
521  /*!
522  * \brief Incoming call dialplan context identifier.
523  * \note The "context" string read in from /etc/asterisk/misdn.conf
524  */
526 
527  /*!
528  * \brief The configured music-on-hold class to use for this call.
529  * \note The "musicclass" string read in from /etc/asterisk/misdn.conf
530  */
532 
533  /*!
534  * \brief Number of outgoing audio frames dropped since last debug gripe message.
535  */
537 
538  /*!
539  * \brief TRUE if we must do the ringback tones.
540  * \note The "far_alerting" boolean read in from /etc/asterisk/misdn.conf
541  */
543 
544  /*!
545  * \brief TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
546  * \note The "nttimeout" boolean read in from /etc/asterisk/misdn.conf
547  */
549 
550  /*!
551  * \brief Tone zone sound used for dialtone generation.
552  * \note Used as a boolean. Non-NULL to prod generation if enabled.
553  */
555 
556  /*!
557  * \brief Enables overlap dialing for the set amount of seconds. (0 = Disabled)
558  * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
559  */
561 
562  /*!
563  * \brief Overlap dialing timeout Task ID. -1 if not running.
564  */
566 
567  /*!
568  * \brief overlap_tv access lock.
569  */
571 
572  /*!
573  * \brief Overlap timer start time. Timer restarted for every digit received.
574  */
575  struct timeval overlap_tv;
576 
577  /*!
578  * \brief Next channel call record in the list.
579  */
580  struct chan_list *next;
581 };
582 
583 
584 int MAXTICS = 8;
585 
586 
587 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
588 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
589 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
590 
591 struct robin_list {
592  char *group;
593  int port;
594  int channel;
595  struct robin_list *next;
596  struct robin_list *prev;
597 };
598 static struct robin_list *robin = NULL;
599 
600 
601 static void free_robin_list(void)
602 {
603  struct robin_list *r;
604  struct robin_list *next;
605 
606  for (r = robin, robin = NULL; r; r = next) {
607  next = r->next;
608  ast_free(r->group);
609  ast_free(r);
610  }
611 }
612 
613 static struct robin_list *get_robin_position(char *group)
614 {
615  struct robin_list *new;
616  struct robin_list *iter = robin;
617  for (; iter; iter = iter->next) {
618  if (!strcasecmp(iter->group, group)) {
619  return iter;
620  }
621  }
622  new = ast_calloc(1, sizeof(*new));
623  if (!new) {
624  return NULL;
625  }
626  new->group = ast_strdup(group);
627  if (!new->group) {
628  ast_free(new);
629  return NULL;
630  }
631  new->channel = 1;
632  if (robin) {
633  new->next = robin;
634  robin->prev = new;
635  }
636  robin = new;
637  return robin;
638 }
639 
640 
641 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
642 static struct sched_context *misdn_tasks = NULL;
643 static pthread_t misdn_tasks_thread;
644 
645 static int *misdn_ports;
646 
647 static void chan_misdn_log(int level, int port, char *tmpl, ...)
648  __attribute__((format(printf, 3, 4)));
649 
650 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, const char *linkedid, int port, int c);
651 static void send_digit_to_chan(struct chan_list *cl, char digit);
652 
653 static int pbx_start_chan(struct chan_list *ch);
654 
655 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
656 
657 #include "asterisk/strings.h"
658 
659 /* #define MISDN_DEBUG 1 */
660 
661 static const char misdn_type[] = "mISDN";
662 
663 static int tracing = 0;
664 
665 /*! \brief Only alaw and mulaw is allowed for now */
666 static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
667 
668 static int *misdn_debug;
669 static int *misdn_debug_only;
670 static int max_ports;
671 
672 static int *misdn_in_calls;
673 static int *misdn_out_calls;
674 
675 /*!
676  * \brief Global channel call record list head.
677  */
678 static struct chan_list *cl_te=NULL;
680 
681 static enum event_response_e
682 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
683 
684 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
685 
686 static void cl_queue_chan(struct chan_list *chan);
687 
688 static int dialtone_indicate(struct chan_list *cl);
689 static void hanguptone_indicate(struct chan_list *cl);
690 static int stop_indicate(struct chan_list *cl);
691 
692 static int start_bc_tones(struct chan_list *cl);
693 static int stop_bc_tones(struct chan_list *cl);
694 static void release_chan_early(struct chan_list *ch);
695 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc);
696 
697 #if defined(AST_MISDN_ENHANCEMENTS)
698 static const char misdn_command_name[] = "misdn_command";
699 static int misdn_command_exec(struct ast_channel *chan, const char *data);
700 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
701 static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
702 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
703 static int misdn_facility_exec(struct ast_channel *chan, const char *data);
704 
705 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
706 
707 void debug_numtype(int port, int numtype, char *type);
708 
709 int add_out_calls(int port);
710 int add_in_calls(int port);
711 
712 
713 #ifdef MISDN_1_2
714 static int update_pipeline_config(struct misdn_bchannel *bc);
715 #else
716 static int update_ec_config(struct misdn_bchannel *bc);
717 #endif
718 
719 
720 
721 /*************** Helpers *****************/
722 
723 static int misdn_chan_is_valid(struct chan_list *ch)
724 {
725  struct chan_list *list;
726 
727  ast_mutex_lock(&cl_te_lock);
728  for (list = cl_te; list; list = list->next) {
729  if (list == ch) {
730  ast_mutex_unlock(&cl_te_lock);
731  return 1;
732  }
733  }
734  ast_mutex_unlock(&cl_te_lock);
735 
736  return 0;
737 }
738 
739 /*! Returns a reference to the found chan_list. */
740 static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
741 {
742  struct chan_list *tmp;
743 
744  ast_mutex_lock(&cl_te_lock);
745  for (tmp = cl_te; tmp; tmp = tmp->next) {
746  if (tmp->ast == ast) {
747  chan_list_ref(tmp, "Found chan_list by ast");
748  ast_mutex_unlock(&cl_te_lock);
749  return tmp;
750  }
751  }
752  ast_mutex_unlock(&cl_te_lock);
753 
754  return NULL;
755 }
756 
757 /*! Returns a reference to the found chan_list. */
758 static struct chan_list *get_chan_by_ast_name(const char *name)
759 {
760  struct chan_list *tmp;
761 
762  ast_mutex_lock(&cl_te_lock);
763  for (tmp = cl_te; tmp; tmp = tmp->next) {
764  if (tmp->ast && strcmp(tmp->ast->name, name) == 0) {
765  chan_list_ref(tmp, "Found chan_list by ast name");
766  ast_mutex_unlock(&cl_te_lock);
767  return tmp;
768  }
769  }
770  ast_mutex_unlock(&cl_te_lock);
771 
772  return NULL;
773 }
774 
775 #if defined(AST_MISDN_ENHANCEMENTS)
776 /*!
777  * \internal
778  * \brief Destroy the misdn_cc_ds_info datastore payload
779  *
780  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
781  *
782  * \details
783  * Since the payload is a reference to an astobj2 object, we just decrement its
784  * reference count. Before doing so, we NULL out the channel pointer inside of
785  * the misdn_cc_caller instance. This function will be called in one of two
786  * cases. In both cases, we no longer need the channel pointer:
787  *
788  * - The original channel that initialized call completion services, the same
789  * channel that is stored here, has been destroyed early. This could happen
790  * if it transferred the mISDN channel, for example.
791  *
792  * - The mISDN channel that had this datastore inherited on to it is now being
793  * destroyed. If this is the case, then the call completion events have
794  * already occurred and the appropriate channel variables have already been
795  * set on the original channel that requested call completion services.
796  *
797  * \return Nothing
798  */
799 static void misdn_cc_ds_destroy(void *data)
800 {
801  struct misdn_cc_caller *cc_caller = data;
802 
803  ao2_lock(cc_caller);
804  cc_caller->chan = NULL;
805  ao2_unlock(cc_caller);
806 
807  ao2_ref(cc_caller, -1);
808 }
809 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
810 
811 #if defined(AST_MISDN_ENHANCEMENTS)
812 /*!
813  * \internal
814  * \brief Duplicate the misdn_cc_ds_info datastore payload
815  *
816  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
817  *
818  * \details
819  * All we need to do is bump the reference count and return the same instance.
820  *
821  * \return A reference to an instance of a misdn_cc_caller
822  */
823 static void *misdn_cc_ds_duplicate(void *data)
824 {
825  struct misdn_cc_caller *cc_caller = data;
826 
827  ao2_ref(cc_caller, +1);
828 
829  return cc_caller;
830 }
831 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
832 
833 #if defined(AST_MISDN_ENHANCEMENTS)
834 static const struct ast_datastore_info misdn_cc_ds_info = {
835  .type = "misdn_cc",
836  .destroy = misdn_cc_ds_destroy,
837  .duplicate = misdn_cc_ds_duplicate,
838 };
839 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
840 
841 #if defined(AST_MISDN_ENHANCEMENTS)
842 /*!
843  * \internal
844  * \brief Set a channel var on the peer channel for call completion services
845  *
846  * \param[in] peer The peer that initialized call completion services
847  * \param[in] var The variable name to set
848  * \param[in] value The variable value to set
849  *
850  * This function may be called from outside of the channel thread. It handles
851  * the fact that the peer channel may be hung up and destroyed at any time.
852  *
853  * \return nothing
854  */
855 static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
856  const char *value)
857 {
858  ao2_lock(peer);
859 
860  /*! \todo XXX This nastiness can go away once ast_channel is ref counted! */
861  while (peer->chan && ast_channel_trylock(peer->chan)) {
862  ao2_unlock(peer);
863  sched_yield();
864  ao2_lock(peer);
865  }
866 
867  if (peer->chan) {
868  pbx_builtin_setvar_helper(peer->chan, var, value);
869  ast_channel_unlock(peer->chan);
870  }
871 
872  ao2_unlock(peer);
873 }
874 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
875 
876 #if defined(AST_MISDN_ENHANCEMENTS)
877 /*!
878  * \internal
879  * \brief Get a reference to the CC caller if it exists
880  */
881 static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
882 {
883  struct ast_datastore *datastore;
884  struct misdn_cc_caller *cc_caller;
885 
886  ast_channel_lock(chan);
887 
888  if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
889  ast_channel_unlock(chan);
890  return NULL;
891  }
892 
893  ao2_ref(datastore->data, +1);
894  cc_caller = datastore->data;
895 
896  ast_channel_unlock(chan);
897 
898  return cc_caller;
899 }
900 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
901 
902 #if defined(AST_MISDN_ENHANCEMENTS)
903 /*!
904  * \internal
905  * \brief Find the call completion record given the record id.
906  *
907  * \param record_id
908  *
909  * \retval pointer to found call completion record
910  * \retval NULL if not found
911  *
912  * \note Assumes the misdn_cc_records_db lock is already obtained.
913  */
914 static struct misdn_cc_record *misdn_cc_find_by_id(long record_id)
915 {
916  struct misdn_cc_record *current;
917 
918  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
919  if (current->record_id == record_id) {
920  /* Found the record */
921  break;
922  }
923  }
924 
925  return current;
926 }
927 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
928 
929 #if defined(AST_MISDN_ENHANCEMENTS)
930 /*!
931  * \internal
932  * \brief Find the call completion record given the port and call linkage id.
933  *
934  * \param port Logical port number
935  * \param linkage_id Call linkage ID number from switch.
936  *
937  * \retval pointer to found call completion record
938  * \retval NULL if not found
939  *
940  * \note Assumes the misdn_cc_records_db lock is already obtained.
941  */
942 static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
943 {
944  struct misdn_cc_record *current;
945 
946  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
947  if (current->port == port
948  && !current->ptp
949  && current->mode.ptmp.linkage_id == linkage_id) {
950  /* Found the record */
951  break;
952  }
953  }
954 
955  return current;
956 }
957 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
958 
959 #if defined(AST_MISDN_ENHANCEMENTS)
960 /*!
961  * \internal
962  * \brief Find the call completion record given the port and outstanding invocation id.
963  *
964  * \param port Logical port number
965  * \param invoke_id Outstanding message invocation ID number.
966  *
967  * \retval pointer to found call completion record
968  * \retval NULL if not found
969  *
970  * \note Assumes the misdn_cc_records_db lock is already obtained.
971  */
972 static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
973 {
974  struct misdn_cc_record *current;
975 
976  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
977  if (current->outstanding_message
978  && current->invoke_id == invoke_id
979  && current->port == port) {
980  /* Found the record */
981  break;
982  }
983  }
984 
985  return current;
986 }
987 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
988 
989 #if defined(AST_MISDN_ENHANCEMENTS)
990 /*!
991  * \internal
992  * \brief Find the call completion record given the port and CCBS reference id.
993  *
994  * \param port Logical port number
995  * \param reference_id CCBS reference ID number from switch.
996  *
997  * \retval pointer to found call completion record
998  * \retval NULL if not found
999  *
1000  * \note Assumes the misdn_cc_records_db lock is already obtained.
1001  */
1002 static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
1003 {
1004  struct misdn_cc_record *current;
1005 
1006  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1007  if (current->activated
1008  && current->port == port
1009  && !current->ptp
1010  && current->mode.ptmp.reference_id == reference_id) {
1011  /* Found the record */
1012  break;
1013  }
1014  }
1015 
1016  return current;
1017 }
1018 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1019 
1020 #if defined(AST_MISDN_ENHANCEMENTS)
1021 /*!
1022  * \internal
1023  * \brief Find the call completion record given the B channel pointer
1024  *
1025  * \param bc B channel control structure pointer.
1026  *
1027  * \retval pointer to found call completion record
1028  * \retval NULL if not found
1029  *
1030  * \note Assumes the misdn_cc_records_db lock is already obtained.
1031  */
1032 static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
1033 {
1034  struct misdn_cc_record *current;
1035 
1036  if (bc) {
1037  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1038  if (current->ptp
1039  && current->mode.ptp.bc == bc) {
1040  /* Found the record */
1041  break;
1042  }
1043  }
1044  } else {
1045  current = NULL;
1046  }
1047 
1048  return current;
1049 }
1050 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1051 
1052 #if defined(AST_MISDN_ENHANCEMENTS)
1053 /*!
1054  * \internal
1055  * \brief Delete the given call completion record
1056  *
1057  * \param doomed Call completion record to destroy
1058  *
1059  * \return Nothing
1060  *
1061  * \note Assumes the misdn_cc_records_db lock is already obtained.
1062  */
1063 static void misdn_cc_delete(struct misdn_cc_record *doomed)
1064 {
1065  struct misdn_cc_record *current;
1066 
1067  AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1068  if (current == doomed) {
1070  ast_free(current);
1071  return;
1072  }
1073  }
1075 
1076  /* The doomed node is not in the call completion database */
1077 }
1078 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1079 
1080 #if defined(AST_MISDN_ENHANCEMENTS)
1081 /*!
1082  * \internal
1083  * \brief Delete all old call completion records
1084  *
1085  * \return Nothing
1086  *
1087  * \note Assumes the misdn_cc_records_db lock is already obtained.
1088  */
1089 static void misdn_cc_remove_old(void)
1090 {
1091  struct misdn_cc_record *current;
1092  time_t now;
1093 
1094  now = time(NULL);
1095  AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1096  if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
1097  if (current->ptp && current->mode.ptp.bc) {
1098  /* Close the old call-completion signaling link */
1099  current->mode.ptp.bc->fac_out.Function = Fac_None;
1100  current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
1101  misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
1102  }
1103 
1104  /* Remove the old call completion record */
1106  ast_free(current);
1107  }
1108  }
1110 }
1111 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1112 
1113 #if defined(AST_MISDN_ENHANCEMENTS)
1114 /*!
1115  * \internal
1116  * \brief Allocate the next record id.
1117  *
1118  * \retval New record id on success.
1119  * \retval -1 on error.
1120  *
1121  * \note Assumes the misdn_cc_records_db lock is already obtained.
1122  */
1123 static long misdn_cc_record_id_new(void)
1124 {
1125  long record_id;
1126  long first_id;
1127 
1128  record_id = ++misdn_cc_record_id;
1129  first_id = record_id;
1130  while (misdn_cc_find_by_id(record_id)) {
1131  record_id = ++misdn_cc_record_id;
1132  if (record_id == first_id) {
1133  /*
1134  * We have a resource leak.
1135  * We should never need to allocate 64k records.
1136  */
1137  chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
1138  record_id = -1;
1139  break;
1140  }
1141  }
1142 
1143  return record_id;
1144 }
1145 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1146 
1147 #if defined(AST_MISDN_ENHANCEMENTS)
1148 /*!
1149  * \internal
1150  * \brief Create a new call completion record
1151  *
1152  * \retval pointer to new call completion record
1153  * \retval NULL if failed
1154  *
1155  * \note Assumes the misdn_cc_records_db lock is already obtained.
1156  */
1157 static struct misdn_cc_record *misdn_cc_new(void)
1158 {
1159  struct misdn_cc_record *cc_record;
1160  long record_id;
1161 
1162  misdn_cc_remove_old();
1163 
1164  cc_record = ast_calloc(1, sizeof(*cc_record));
1165  if (cc_record) {
1166  record_id = misdn_cc_record_id_new();
1167  if (record_id < 0) {
1168  ast_free(cc_record);
1169  return NULL;
1170  }
1171 
1172  /* Initialize the new record */
1173  cc_record->record_id = record_id;
1174  cc_record->port = -1;/* Invalid port so it will never be found this way */
1175  cc_record->invoke_id = ++misdn_invoke_id;
1176  cc_record->party_a_free = 1;/* Default User-A as free */
1177  cc_record->error_code = FacError_None;
1178  cc_record->reject_code = FacReject_None;
1179  cc_record->time_created = time(NULL);
1180 
1181  /* Insert the new record into the database */
1182  AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
1183  }
1184  return cc_record;
1185 }
1186 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1187 
1188 #if defined(AST_MISDN_ENHANCEMENTS)
1189 /*!
1190  * \internal
1191  * \brief Destroy the call completion record database
1192  *
1193  * \return Nothing
1194  */
1195 static void misdn_cc_destroy(void)
1196 {
1197  struct misdn_cc_record *current;
1198 
1199  while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
1200  /* Do a misdn_cc_delete(current) inline */
1201  ast_free(current);
1202  }
1203 }
1204 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1205 
1206 #if defined(AST_MISDN_ENHANCEMENTS)
1207 /*!
1208  * \internal
1209  * \brief Initialize the call completion record database
1210  *
1211  * \return Nothing
1212  */
1213 static void misdn_cc_init(void)
1214 {
1215  misdn_cc_record_id = 0;
1216 }
1217 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1218 
1219 #if defined(AST_MISDN_ENHANCEMENTS)
1220 /*!
1221  * \internal
1222  * \brief Check the status of an outstanding invocation request.
1223  *
1224  * \param data Points to an integer containing the call completion record id.
1225  *
1226  * \retval 0 if got a response.
1227  * \retval -1 if no response yet.
1228  */
1229 static int misdn_cc_response_check(void *data)
1230 {
1231  int not_responded;
1232  struct misdn_cc_record *cc_record;
1233 
1234  AST_LIST_LOCK(&misdn_cc_records_db);
1235  cc_record = misdn_cc_find_by_id(*(long *) data);
1236  if (cc_record) {
1237  if (cc_record->outstanding_message) {
1238  not_responded = -1;
1239  } else {
1240  not_responded = 0;
1241  }
1242  } else {
1243  /* No record so there is no response to check. */
1244  not_responded = 0;
1245  }
1246  AST_LIST_UNLOCK(&misdn_cc_records_db);
1247 
1248  return not_responded;
1249 }
1250 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1251 
1252 #if defined(AST_MISDN_ENHANCEMENTS)
1253 /*!
1254  * \internal
1255  * \brief Wait for a response from the switch for an outstanding
1256  * invocation request.
1257  *
1258  * \param chan Asterisk channel to operate upon.
1259  * \param wait_seconds Number of seconds to wait
1260  * \param record_id Call completion record ID.
1261  *
1262  * \return Nothing
1263  */
1264 static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
1265 {
1266  unsigned count;
1267 
1268  for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
1269  /* Sleep in 500 ms increments */
1270  if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
1271  /* We got hung up or our response came in. */
1272  break;
1273  }
1274  }
1275 }
1276 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1277 
1278 #if defined(AST_MISDN_ENHANCEMENTS)
1279 /*!
1280  * \internal
1281  * \brief Convert the mISDN reject code to a string
1282  *
1283  * \param code mISDN reject code.
1284  *
1285  * \return The mISDN reject code as a string
1286  */
1287 static const char *misdn_to_str_reject_code(enum FacRejectCode code)
1288 {
1289  static const struct {
1290  enum FacRejectCode code;
1291  char *name;
1292  } arr[] = {
1293 /* *INDENT-OFF* */
1294  { FacReject_None, "No reject occurred" },
1295  { FacReject_Unknown, "Unknown reject code" },
1296 
1297  { FacReject_Gen_UnrecognizedComponent, "General: Unrecognized Component" },
1298  { FacReject_Gen_MistypedComponent, "General: Mistyped Component" },
1299  { FacReject_Gen_BadlyStructuredComponent, "General: Badly Structured Component" },
1300 
1301  { FacReject_Inv_DuplicateInvocation, "Invoke: Duplicate Invocation" },
1302  { FacReject_Inv_UnrecognizedOperation, "Invoke: Unrecognized Operation" },
1303  { FacReject_Inv_MistypedArgument, "Invoke: Mistyped Argument" },
1304  { FacReject_Inv_ResourceLimitation, "Invoke: Resource Limitation" },
1305  { FacReject_Inv_InitiatorReleasing, "Invoke: Initiator Releasing" },
1306  { FacReject_Inv_UnrecognizedLinkedID, "Invoke: Unrecognized Linked ID" },
1307  { FacReject_Inv_LinkedResponseUnexpected, "Invoke: Linked Response Unexpected" },
1308  { FacReject_Inv_UnexpectedChildOperation, "Invoke: Unexpected Child Operation" },
1309 
1310  { FacReject_Res_UnrecognizedInvocation, "Result: Unrecognized Invocation" },
1311  { FacReject_Res_ResultResponseUnexpected, "Result: Result Response Unexpected" },
1312  { FacReject_Res_MistypedResult, "Result: Mistyped Result" },
1313 
1314  { FacReject_Err_UnrecognizedInvocation, "Error: Unrecognized Invocation" },
1315  { FacReject_Err_ErrorResponseUnexpected, "Error: Error Response Unexpected" },
1316  { FacReject_Err_UnrecognizedError, "Error: Unrecognized Error" },
1317  { FacReject_Err_UnexpectedError, "Error: Unexpected Error" },
1318  { FacReject_Err_MistypedParameter, "Error: Mistyped Parameter" },
1319 /* *INDENT-ON* */
1320  };
1321 
1322  unsigned index;
1323 
1324  for (index = 0; index < ARRAY_LEN(arr); ++index) {
1325  if (arr[index].code == code) {
1326  return arr[index].name;
1327  }
1328  }
1329 
1330  return "unknown";
1331 }
1332 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1333 
1334 #if defined(AST_MISDN_ENHANCEMENTS)
1335 /*!
1336  * \internal
1337  * \brief Convert the mISDN error code to a string
1338  *
1339  * \param code mISDN error code.
1340  *
1341  * \return The mISDN error code as a string
1342  */
1343 static const char *misdn_to_str_error_code(enum FacErrorCode code)
1344 {
1345  static const struct {
1346  enum FacErrorCode code;
1347  char *name;
1348  } arr[] = {
1349 /* *INDENT-OFF* */
1350  { FacError_None, "No error occurred" },
1351  { FacError_Unknown, "Unknown OID error code" },
1352 
1353  { FacError_Gen_NotSubscribed, "General: Not Subscribed" },
1354  { FacError_Gen_NotAvailable, "General: Not Available" },
1355  { FacError_Gen_NotImplemented, "General: Not Implemented" },
1356  { FacError_Gen_InvalidServedUserNr, "General: Invalid Served User Number" },
1357  { FacError_Gen_InvalidCallState, "General: Invalid Call State" },
1358  { FacError_Gen_BasicServiceNotProvided, "General: Basic Service Not Provided" },
1359  { FacError_Gen_NotIncomingCall, "General: Not Incoming Call" },
1360  { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
1361  { FacError_Gen_ResourceUnavailable, "General: Resource Unavailable" },
1362 
1363  { FacError_Div_InvalidDivertedToNr, "Diversion: Invalid Diverted To Number" },
1364  { FacError_Div_SpecialServiceNr, "Diversion: Special Service Number" },
1365  { FacError_Div_DiversionToServedUserNr, "Diversion: Diversion To Served User Number" },
1366  { FacError_Div_IncomingCallAccepted, "Diversion: Incoming Call Accepted" },
1367  { FacError_Div_NumberOfDiversionsExceeded, "Diversion: Number Of Diversions Exceeded" },
1368  { FacError_Div_NotActivated, "Diversion: Not Activated" },
1369  { FacError_Div_RequestAlreadyAccepted, "Diversion: Request Already Accepted" },
1370 
1371  { FacError_AOC_NoChargingInfoAvailable, "AOC: No Charging Info Available" },
1372 
1373  { FacError_CCBS_InvalidCallLinkageID, "CCBS: Invalid Call Linkage ID" },
1374  { FacError_CCBS_InvalidCCBSReference, "CCBS: Invalid CCBS Reference" },
1375  { FacError_CCBS_LongTermDenial, "CCBS: Long Term Denial" },
1376  { FacError_CCBS_ShortTermDenial, "CCBS: Short Term Denial" },
1377  { FacError_CCBS_IsAlreadyActivated, "CCBS: Is Already Activated" },
1378  { FacError_CCBS_AlreadyAccepted, "CCBS: Already Accepted" },
1379  { FacError_CCBS_OutgoingCCBSQueueFull, "CCBS: Outgoing CCBS Queue Full" },
1380  { FacError_CCBS_CallFailureReasonNotBusy, "CCBS: Call Failure Reason Not Busy" },
1381  { FacError_CCBS_NotReadyForCall, "CCBS: Not Ready For Call" },
1382 
1383  { FacError_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
1384  { FacError_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
1385 
1386  { FacError_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
1387 /* *INDENT-ON* */
1388  };
1389 
1390  unsigned index;
1391 
1392  for (index = 0; index < ARRAY_LEN(arr); ++index) {
1393  if (arr[index].code == code) {
1394  return arr[index].name;
1395  }
1396  }
1397 
1398  return "unknown";
1399 }
1400 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1401 
1402 #if defined(AST_MISDN_ENHANCEMENTS)
1403 /*!
1404  * \internal
1405  * \brief Convert mISDN redirecting reason to diversion reason.
1406  *
1407  * \param reason mISDN redirecting reason code.
1408  *
1409  * \return Supported diversion reason code.
1410  */
1411 static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
1412 {
1413  unsigned diversion_reason;
1414 
1415  switch (reason) {
1417  diversion_reason = 1;/* cfu */
1418  break;
1420  diversion_reason = 2;/* cfb */
1421  break;
1423  diversion_reason = 3;/* cfnr */
1424  break;
1425  default:
1426  diversion_reason = 0;/* unknown */
1427  break;
1428  }
1429 
1430  return diversion_reason;
1431 }
1432 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1433 
1434 #if defined(AST_MISDN_ENHANCEMENTS)
1435 /*!
1436  * \internal
1437  * \brief Convert diversion reason to mISDN redirecting reason
1438  *
1439  * \param diversion_reason Diversion reason to convert
1440  *
1441  * \return Supported redirecting reason code.
1442  */
1443 static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
1444 {
1445  enum mISDN_REDIRECTING_REASON reason;
1446 
1447  switch (diversion_reason) {
1448  case 1:/* cfu */
1450  break;
1451  case 2:/* cfb */
1453  break;
1454  case 3:/* cfnr */
1456  break;
1457  default:
1459  break;
1460  }
1461 
1462  return reason;
1463 }
1464 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1465 
1466 #if defined(AST_MISDN_ENHANCEMENTS)
1467 /*!
1468  * \internal
1469  * \brief Convert the mISDN presentation to PresentedNumberUnscreened type
1470  *
1471  * \param presentation mISDN presentation to convert
1472  * \param number_present TRUE if the number is present
1473  *
1474  * \return PresentedNumberUnscreened type
1475  */
1476 static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
1477 {
1478  unsigned type;
1479 
1480  switch (presentation) {
1481  case 0:/* allowed */
1482  if (number_present) {
1483  type = 0;/* presentationAllowedNumber */
1484  } else {
1485  type = 2;/* numberNotAvailableDueToInterworking */
1486  }
1487  break;
1488  case 1:/* restricted */
1489  if (number_present) {
1490  type = 3;/* presentationRestrictedNumber */
1491  } else {
1492  type = 1;/* presentationRestricted */
1493  }
1494  break;
1495  default:
1496  type = 2;/* numberNotAvailableDueToInterworking */
1497  break;
1498  }
1499 
1500  return type;
1501 }
1502 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1503 
1504 #if defined(AST_MISDN_ENHANCEMENTS)
1505 /*!
1506  * \internal
1507  * \brief Convert the PresentedNumberUnscreened type to mISDN presentation
1508  *
1509  * \param type PresentedNumberUnscreened type
1510  *
1511  * \return mISDN presentation
1512  */
1513 static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
1514 {
1515  int presentation;
1516 
1517  switch (type) {
1518  default:
1519  case 0:/* presentationAllowedNumber */
1520  presentation = 0;/* allowed */
1521  break;
1522 
1523  case 1:/* presentationRestricted */
1524  case 3:/* presentationRestrictedNumber */
1525  presentation = 1;/* restricted */
1526  break;
1527 
1528  case 2:/* numberNotAvailableDueToInterworking */
1529  presentation = 2;/* unavailable */
1530  break;
1531  }
1532 
1533  return presentation;
1534 }
1535 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1536 
1537 #if defined(AST_MISDN_ENHANCEMENTS)
1538 /*!
1539  * \internal
1540  * \brief Convert the mISDN numbering plan to PartyNumber numbering plan
1541  *
1542  * \param number_plan mISDN numbering plan
1543  *
1544  * \return PartyNumber numbering plan
1545  */
1546 static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
1547 {
1548  unsigned party_plan;
1549 
1550  switch (number_plan) {
1551  default:
1552  case NUMPLAN_UNKNOWN:
1553  party_plan = 0;/* unknown */
1554  break;
1555 
1556  case NUMPLAN_ISDN:
1557  party_plan = 1;/* public */
1558  break;
1559 
1560  case NUMPLAN_DATA:
1561  party_plan = 3;/* data */
1562  break;
1563 
1564  case NUMPLAN_TELEX:
1565  party_plan = 4;/* telex */
1566  break;
1567 
1568  case NUMPLAN_NATIONAL:
1569  party_plan = 8;/* nationalStandard */
1570  break;
1571 
1572  case NUMPLAN_PRIVATE:
1573  party_plan = 5;/* private */
1574  break;
1575  }
1576 
1577  return party_plan;
1578 }
1579 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1580 
1581 #if defined(AST_MISDN_ENHANCEMENTS)
1582 /*!
1583  * \internal
1584  * \brief Convert PartyNumber numbering plan to mISDN numbering plan
1585  *
1586  * \param party_plan PartyNumber numbering plan
1587  *
1588  * \return mISDN numbering plan
1589  */
1590 static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
1591 {
1592  enum mISDN_NUMBER_PLAN number_plan;
1593 
1594  switch (party_plan) {
1595  default:
1596  case 0:/* unknown */
1597  number_plan = NUMPLAN_UNKNOWN;
1598  break;
1599  case 1:/* public */
1600  number_plan = NUMPLAN_ISDN;
1601  break;
1602  case 3:/* data */
1603  number_plan = NUMPLAN_DATA;
1604  break;
1605  case 4:/* telex */
1606  number_plan = NUMPLAN_TELEX;
1607  break;
1608  case 8:/* nationalStandard */
1609  number_plan = NUMPLAN_NATIONAL;
1610  break;
1611  case 5:/* private */
1612  number_plan = NUMPLAN_PRIVATE;
1613  break;
1614  }
1615 
1616  return number_plan;
1617 }
1618 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1619 
1620 #if defined(AST_MISDN_ENHANCEMENTS)
1621 /*!
1622  * \internal
1623  * \brief Convert mISDN type-of-number to PartyNumber public type-of-number
1624  *
1625  * \param ton mISDN type-of-number
1626  *
1627  * \return PartyNumber public type-of-number
1628  */
1629 static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
1630 {
1631  unsigned party_ton;
1632 
1633  switch (ton) {
1634  default:
1635  case NUMTYPE_UNKNOWN:
1636  party_ton = 0;/* unknown */
1637  break;
1638 
1639  case NUMTYPE_INTERNATIONAL:
1640  party_ton = 1;/* internationalNumber */
1641  break;
1642 
1643  case NUMTYPE_NATIONAL:
1644  party_ton = 2;/* nationalNumber */
1645  break;
1646 
1648  party_ton = 3;/* networkSpecificNumber */
1649  break;
1650 
1651  case NUMTYPE_SUBSCRIBER:
1652  party_ton = 4;/* subscriberNumber */
1653  break;
1654 
1655  case NUMTYPE_ABBREVIATED:
1656  party_ton = 6;/* abbreviatedNumber */
1657  break;
1658  }
1659 
1660  return party_ton;
1661 }
1662 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1663 
1664 #if defined(AST_MISDN_ENHANCEMENTS)
1665 /*!
1666  * \internal
1667  * \brief Convert the PartyNumber public type-of-number to mISDN type-of-number
1668  *
1669  * \param party_ton PartyNumber public type-of-number
1670  *
1671  * \return mISDN type-of-number
1672  */
1673 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
1674 {
1675  enum mISDN_NUMBER_TYPE ton;
1676 
1677  switch (party_ton) {
1678  default:
1679  case 0:/* unknown */
1680  ton = NUMTYPE_UNKNOWN;
1681  break;
1682 
1683  case 1:/* internationalNumber */
1684  ton = NUMTYPE_INTERNATIONAL;
1685  break;
1686 
1687  case 2:/* nationalNumber */
1688  ton = NUMTYPE_NATIONAL;
1689  break;
1690 
1691  case 3:/* networkSpecificNumber */
1693  break;
1694 
1695  case 4:/* subscriberNumber */
1696  ton = NUMTYPE_SUBSCRIBER;
1697  break;
1698 
1699  case 6:/* abbreviatedNumber */
1700  ton = NUMTYPE_ABBREVIATED;
1701  break;
1702  }
1703 
1704  return ton;
1705 }
1706 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1707 
1708 #if defined(AST_MISDN_ENHANCEMENTS)
1709 /*!
1710  * \internal
1711  * \brief Convert mISDN type-of-number to PartyNumber private type-of-number
1712  *
1713  * \param ton mISDN type-of-number
1714  *
1715  * \return PartyNumber private type-of-number
1716  */
1717 static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
1718 {
1719  unsigned party_ton;
1720 
1721  switch (ton) {
1722  default:
1723  case NUMTYPE_UNKNOWN:
1724  party_ton = 0;/* unknown */
1725  break;
1726 
1727  case NUMTYPE_INTERNATIONAL:
1728  party_ton = 1;/* level2RegionalNumber */
1729  break;
1730 
1731  case NUMTYPE_NATIONAL:
1732  party_ton = 2;/* level1RegionalNumber */
1733  break;
1734 
1736  party_ton = 3;/* pTNSpecificNumber */
1737  break;
1738 
1739  case NUMTYPE_SUBSCRIBER:
1740  party_ton = 4;/* localNumber */
1741  break;
1742 
1743  case NUMTYPE_ABBREVIATED:
1744  party_ton = 6;/* abbreviatedNumber */
1745  break;
1746  }
1747 
1748  return party_ton;
1749 }
1750 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1751 
1752 #if defined(AST_MISDN_ENHANCEMENTS)
1753 /*!
1754  * \internal
1755  * \brief Convert the PartyNumber private type-of-number to mISDN type-of-number
1756  *
1757  * \param party_ton PartyNumber private type-of-number
1758  *
1759  * \return mISDN type-of-number
1760  */
1761 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
1762 {
1763  enum mISDN_NUMBER_TYPE ton;
1764 
1765  switch (party_ton) {
1766  default:
1767  case 0:/* unknown */
1768  ton = NUMTYPE_UNKNOWN;
1769  break;
1770 
1771  case 1:/* level2RegionalNumber */
1772  ton = NUMTYPE_INTERNATIONAL;
1773  break;
1774 
1775  case 2:/* level1RegionalNumber */
1776  ton = NUMTYPE_NATIONAL;
1777  break;
1778 
1779  case 3:/* pTNSpecificNumber */
1781  break;
1782 
1783  case 4:/* localNumber */
1784  ton = NUMTYPE_SUBSCRIBER;
1785  break;
1786 
1787  case 6:/* abbreviatedNumber */
1788  ton = NUMTYPE_ABBREVIATED;
1789  break;
1790  }
1791 
1792  return ton;
1793 }
1794 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1795 
1796 /*!
1797  * \internal
1798  * \brief Convert the mISDN type of number code to a string
1799  *
1800  * \param number_type mISDN type of number code.
1801  *
1802  * \return The mISDN type of number code as a string
1803  */
1804 static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
1805 {
1806  const char *str;
1807 
1808  switch (number_type) {
1809  default:
1810  case NUMTYPE_UNKNOWN:
1811  str = "Unknown";
1812  break;
1813 
1814  case NUMTYPE_INTERNATIONAL:
1815  str = "International";
1816  break;
1817 
1818  case NUMTYPE_NATIONAL:
1819  str = "National";
1820  break;
1821 
1823  str = "Network Specific";
1824  break;
1825 
1826  case NUMTYPE_SUBSCRIBER:
1827  str = "Subscriber";
1828  break;
1829 
1830  case NUMTYPE_ABBREVIATED:
1831  str = "Abbreviated";
1832  break;
1833  }
1834 
1835  return str;
1836 }
1837 
1838 /*!
1839  * \internal
1840  * \brief Convert the mISDN type of number code to Asterisk type of number code
1841  *
1842  * \param number_type mISDN type of number code.
1843  *
1844  * \return Asterisk type of number code
1845  */
1846 static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
1847 {
1848  int ast_number_type;
1849 
1850  switch (number_type) {
1851  default:
1852  case NUMTYPE_UNKNOWN:
1853  ast_number_type = NUMTYPE_UNKNOWN << 4;
1854  break;
1855 
1856  case NUMTYPE_INTERNATIONAL:
1857  ast_number_type = NUMTYPE_INTERNATIONAL << 4;
1858  break;
1859 
1860  case NUMTYPE_NATIONAL:
1861  ast_number_type = NUMTYPE_NATIONAL << 4;
1862  break;
1863 
1865  ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
1866  break;
1867 
1868  case NUMTYPE_SUBSCRIBER:
1869  ast_number_type = NUMTYPE_SUBSCRIBER << 4;
1870  break;
1871 
1872  case NUMTYPE_ABBREVIATED:
1873  ast_number_type = NUMTYPE_ABBREVIATED << 4;
1874  break;
1875  }
1876 
1877  return ast_number_type;
1878 }
1879 
1880 /*!
1881  * \internal
1882  * \brief Convert the Asterisk type of number code to mISDN type of number code
1883  *
1884  * \param ast_number_type Asterisk type of number code.
1885  *
1886  * \return mISDN type of number code
1887  */
1888 static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
1889 {
1890  enum mISDN_NUMBER_TYPE number_type;
1891 
1892  switch ((ast_number_type >> 4) & 0x07) {
1893  default:
1894  case NUMTYPE_UNKNOWN:
1895  number_type = NUMTYPE_UNKNOWN;
1896  break;
1897 
1898  case NUMTYPE_INTERNATIONAL:
1899  number_type = NUMTYPE_INTERNATIONAL;
1900  break;
1901 
1902  case NUMTYPE_NATIONAL:
1903  number_type = NUMTYPE_NATIONAL;
1904  break;
1905 
1907  number_type = NUMTYPE_NETWORK_SPECIFIC;
1908  break;
1909 
1910  case NUMTYPE_SUBSCRIBER:
1911  number_type = NUMTYPE_SUBSCRIBER;
1912  break;
1913 
1914  case NUMTYPE_ABBREVIATED:
1915  number_type = NUMTYPE_ABBREVIATED;
1916  break;
1917  }
1918 
1919  return number_type;
1920 }
1921 
1922 /*!
1923  * \internal
1924  * \brief Convert the mISDN numbering plan code to a string
1925  *
1926  * \param number_plan mISDN numbering plan code.
1927  *
1928  * \return The mISDN numbering plan code as a string
1929  */
1930 static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
1931 {
1932  const char *str;
1933 
1934  switch (number_plan) {
1935  default:
1936  case NUMPLAN_UNKNOWN:
1937  str = "Unknown";
1938  break;
1939 
1940  case NUMPLAN_ISDN:
1941  str = "ISDN";
1942  break;
1943 
1944  case NUMPLAN_DATA:
1945  str = "Data";
1946  break;
1947 
1948  case NUMPLAN_TELEX:
1949  str = "Telex";
1950  break;
1951 
1952  case NUMPLAN_NATIONAL:
1953  str = "National";
1954  break;
1955 
1956  case NUMPLAN_PRIVATE:
1957  str = "Private";
1958  break;
1959  }
1960 
1961  return str;
1962 }
1963 
1964 /*!
1965  * \internal
1966  * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
1967  *
1968  * \param number_plan mISDN numbering plan code.
1969  *
1970  * \return Asterisk numbering plan code
1971  */
1972 static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
1973 {
1974  int ast_number_plan;
1975 
1976  switch (number_plan) {
1977  default:
1978  case NUMPLAN_UNKNOWN:
1979  ast_number_plan = NUMPLAN_UNKNOWN;
1980  break;
1981 
1982  case NUMPLAN_ISDN:
1983  ast_number_plan = NUMPLAN_ISDN;
1984  break;
1985 
1986  case NUMPLAN_DATA:
1987  ast_number_plan = NUMPLAN_DATA;
1988  break;
1989 
1990  case NUMPLAN_TELEX:
1991  ast_number_plan = NUMPLAN_TELEX;
1992  break;
1993 
1994  case NUMPLAN_NATIONAL:
1995  ast_number_plan = NUMPLAN_NATIONAL;
1996  break;
1997 
1998  case NUMPLAN_PRIVATE:
1999  ast_number_plan = NUMPLAN_PRIVATE;
2000  break;
2001  }
2002 
2003  return ast_number_plan;
2004 }
2005 
2006 /*!
2007  * \internal
2008  * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
2009  *
2010  * \param ast_number_plan Asterisk numbering plan code.
2011  *
2012  * \return mISDN numbering plan code
2013  */
2014 static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
2015 {
2016  enum mISDN_NUMBER_PLAN number_plan;
2017 
2018  switch (ast_number_plan & 0x0F) {
2019  default:
2020  case NUMPLAN_UNKNOWN:
2021  number_plan = NUMPLAN_UNKNOWN;
2022  break;
2023 
2024  case NUMPLAN_ISDN:
2025  number_plan = NUMPLAN_ISDN;
2026  break;
2027 
2028  case NUMPLAN_DATA:
2029  number_plan = NUMPLAN_DATA;
2030  break;
2031 
2032  case NUMPLAN_TELEX:
2033  number_plan = NUMPLAN_TELEX;
2034  break;
2035 
2036  case NUMPLAN_NATIONAL:
2037  number_plan = NUMPLAN_NATIONAL;
2038  break;
2039 
2040  case NUMPLAN_PRIVATE:
2041  number_plan = NUMPLAN_PRIVATE;
2042  break;
2043  }
2044 
2045  return number_plan;
2046 }
2047 
2048 /*!
2049  * \internal
2050  * \brief Convert the mISDN presentation code to a string
2051  *
2052  * \param presentation mISDN number presentation restriction code.
2053  *
2054  * \return The mISDN presentation code as a string
2055  */
2056 static const char *misdn_to_str_pres(int presentation)
2057 {
2058  const char *str;
2059 
2060  switch (presentation) {
2061  case 0:
2062  str = "Allowed";
2063  break;
2064 
2065  case 1:
2066  str = "Restricted";
2067  break;
2068 
2069  case 2:
2070  str = "Unavailable";
2071  break;
2072 
2073  default:
2074  str = "Unknown";
2075  break;
2076  }
2077 
2078  return str;
2079 }
2080 
2081 /*!
2082  * \internal
2083  * \brief Convert the mISDN presentation code to Asterisk presentation code
2084  *
2085  * \param presentation mISDN number presentation restriction code.
2086  *
2087  * \return Asterisk presentation code
2088  */
2089 static int misdn_to_ast_pres(int presentation)
2090 {
2091  switch (presentation) {
2092  default:
2093  case 0:
2094  presentation = AST_PRES_ALLOWED;
2095  break;
2096 
2097  case 1:
2098  presentation = AST_PRES_RESTRICTED;
2099  break;
2100 
2101  case 2:
2102  presentation = AST_PRES_UNAVAILABLE;
2103  break;
2104  }
2105 
2106  return presentation;
2107 }
2108 
2109 /*!
2110  * \internal
2111  * \brief Convert the Asterisk presentation code to mISDN presentation code
2112  *
2113  * \param presentation Asterisk number presentation restriction code.
2114  *
2115  * \return mISDN presentation code
2116  */
2117 static int ast_to_misdn_pres(int presentation)
2118 {
2119  switch (presentation & AST_PRES_RESTRICTION) {
2120  default:
2121  case AST_PRES_ALLOWED:
2122  presentation = 0;
2123  break;
2124 
2125  case AST_PRES_RESTRICTED:
2126  presentation = 1;
2127  break;
2128 
2129  case AST_PRES_UNAVAILABLE:
2130  presentation = 2;
2131  break;
2132  }
2133 
2134  return presentation;
2135 }
2136 
2137 /*!
2138  * \internal
2139  * \brief Convert the mISDN screening code to a string
2140  *
2141  * \param screening mISDN number screening code.
2142  *
2143  * \return The mISDN screening code as a string
2144  */
2145 static const char *misdn_to_str_screen(int screening)
2146 {
2147  const char *str;
2148 
2149  switch (screening) {
2150  case 0:
2151  str = "Unscreened";
2152  break;
2153 
2154  case 1:
2155  str = "Passed Screen";
2156  break;
2157 
2158  case 2:
2159  str = "Failed Screen";
2160  break;
2161 
2162  case 3:
2163  str = "Network Number";
2164  break;
2165 
2166  default:
2167  str = "Unknown";
2168  break;
2169  }
2170 
2171  return str;
2172 }
2173 
2174 /*!
2175  * \internal
2176  * \brief Convert the mISDN screening code to Asterisk screening code
2177  *
2178  * \param screening mISDN number screening code.
2179  *
2180  * \return Asterisk screening code
2181  */
2182 static int misdn_to_ast_screen(int screening)
2183 {
2184  switch (screening) {
2185  default:
2186  case 0:
2187  screening = AST_PRES_USER_NUMBER_UNSCREENED;
2188  break;
2189 
2190  case 1:
2192  break;
2193 
2194  case 2:
2196  break;
2197 
2198  case 3:
2199  screening = AST_PRES_NETWORK_NUMBER;
2200  break;
2201  }
2202 
2203  return screening;
2204 }
2205 
2206 /*!
2207  * \internal
2208  * \brief Convert the Asterisk screening code to mISDN screening code
2209  *
2210  * \param screening Asterisk number screening code.
2211  *
2212  * \return mISDN screening code
2213  */
2214 static int ast_to_misdn_screen(int screening)
2215 {
2216  switch (screening & AST_PRES_NUMBER_TYPE) {
2217  default:
2219  screening = 0;
2220  break;
2221 
2223  screening = 1;
2224  break;
2225 
2227  screening = 2;
2228  break;
2229 
2231  screening = 3;
2232  break;
2233  }
2234 
2235  return screening;
2236 }
2237 
2238 /*!
2239  * \internal
2240  * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
2241  *
2242  * \param ast Asterisk redirecting reason code.
2243  *
2244  * \return mISDN reason code
2245  */
2247 {
2248  unsigned index;
2249 
2250  static const struct misdn_reasons {
2251  enum AST_REDIRECTING_REASON ast;
2252  enum mISDN_REDIRECTING_REASON q931;
2253  } misdn_reason_table[] = {
2254  /* *INDENT-OFF* */
2267  /* *INDENT-ON* */
2268  };
2269 
2270  for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
2271  if (misdn_reason_table[index].ast == ast) {
2272  return misdn_reason_table[index].q931;
2273  }
2274  }
2276 }
2277 
2278 /*!
2279  * \internal
2280  * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
2281  *
2282  * \param q931 mISDN redirecting reason code.
2283  *
2284  * \return Asterisk redirecting reason code
2285  */
2287 {
2288  enum AST_REDIRECTING_REASON ast;
2289 
2290  switch (q931) {
2291  default:
2294  break;
2295 
2298  break;
2299 
2302  break;
2303 
2306  break;
2307 
2310  break;
2311 
2314  break;
2315 
2318  break;
2319  }
2320 
2321  return ast;
2322 }
2323 
2324 
2325 
2327  char *name; /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
2328  char *display; /*!< Bearer capability displayable name */
2329  int cap; /*!< SETUP message bearer capability field code value */
2330  int deprecated; /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
2331 };
2332 
2333 /* *INDENT-OFF* */
2334 static const struct allowed_bearers allowed_bearers_array[] = {
2335  /* Name, Displayable Name Bearer Capability, Deprecated */
2336  { "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
2337  { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
2338  { "digital_unrestricted", "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
2339  { "digital_restricted", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 0 },
2340  { "digital_restriced", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 1 }, /* Allow misspelling for backwards compatibility */
2341  { "video", "Video", INFO_CAPABILITY_VIDEO, 0 }
2342 };
2343 /* *INDENT-ON* */
2344 
2345 static const char *bearer2str(int cap)
2346 {
2347  unsigned index;
2348 
2349  for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
2350  if (allowed_bearers_array[index].cap == cap) {
2351  return allowed_bearers_array[index].display;
2352  }
2353  }
2354 
2355  return "Unknown Bearer";
2356 }
2357 
2358 #if defined(AST_MISDN_ENHANCEMENTS)
2359 /*!
2360  * \internal
2361  * \brief Fill in facility PartyNumber information
2362  *
2363  * \param party PartyNumber structure to fill in.
2364  * \param id Information to put in PartyNumber structure.
2365  *
2366  * \return Nothing
2367  */
2368 static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
2369 {
2370  ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
2371  party->LengthOfNumber = strlen((char *) party->Number);
2372  party->Type = misdn_to_PartyNumber_plan(id->number_plan);
2373  switch (party->Type) {
2374  case 1:/* public */
2375  party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
2376  break;
2377  case 5:/* private */
2378  party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
2379  break;
2380  default:
2381  party->TypeOfNumber = 0;/* Don't care */
2382  break;
2383  }
2384 }
2385 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2386 
2387 #if defined(AST_MISDN_ENHANCEMENTS)
2388 /*!
2389  * \internal
2390  * \brief Extract the information from PartyNumber
2391  *
2392  * \param id Where to put extracted PartyNumber information
2393  * \param party PartyNumber information to extract
2394  *
2395  * \return Nothing
2396  */
2397 static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
2398 {
2399  if (party->LengthOfNumber) {
2400  ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
2401  id->number_plan = PartyNumber_to_misdn_plan(party->Type);
2402  switch (party->Type) {
2403  case 1:/* public */
2404  id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
2405  break;
2406  case 5:/* private */
2407  id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
2408  break;
2409  default:
2410  id->number_type = NUMTYPE_UNKNOWN;
2411  break;
2412  }
2413  } else {
2414  /* Number not present */
2415  id->number_type = NUMTYPE_UNKNOWN;
2416  id->number_plan = NUMPLAN_ISDN;
2417  id->number[0] = 0;
2418  }
2419 }
2420 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2421 
2422 #if defined(AST_MISDN_ENHANCEMENTS)
2423 /*!
2424  * \internal
2425  * \brief Fill in facility Address information
2426  *
2427  * \param Address Address structure to fill in.
2428  * \param id Information to put in Address structure.
2429  *
2430  * \return Nothing
2431  */
2432 static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
2433 {
2434  misdn_PartyNumber_fill(&Address->Party, id);
2435 
2436  /* Subaddresses are not supported yet */
2437  Address->Subaddress.Length = 0;
2438 }
2439 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2440 
2441 #if defined(AST_MISDN_ENHANCEMENTS)
2442 /*!
2443  * \internal
2444  * \brief Fill in facility PresentedNumberUnscreened information
2445  *
2446  * \param presented PresentedNumberUnscreened structure to fill in.
2447  * \param id Information to put in PresentedNumberUnscreened structure.
2448  *
2449  * \return Nothing
2450  */
2451 static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
2452 {
2453  presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
2454  misdn_PartyNumber_fill(&presented->Unscreened, id);
2455 }
2456 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2457 
2458 #if defined(AST_MISDN_ENHANCEMENTS)
2459 /*!
2460  * \internal
2461  * \brief Extract the information from PartyNumber
2462  *
2463  * \param id Where to put extracted PresentedNumberUnscreened information
2464  * \param presented PresentedNumberUnscreened information to extract
2465  *
2466  * \return Nothing
2467  */
2468 static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
2469 {
2470  id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
2471  id->screening = 0;/* unscreened */
2472  switch (presented->Type) {
2473  case 0:/* presentationAllowedNumber */
2474  case 3:/* presentationRestrictedNumber */
2475  misdn_PartyNumber_extract(id, &presented->Unscreened);
2476  break;
2477  case 1:/* presentationRestricted */
2478  case 2:/* numberNotAvailableDueToInterworking */
2479  default:
2480  /* Number not present (And uninitialized so do not even look at it!) */
2481  id->number_type = NUMTYPE_UNKNOWN;
2482  id->number_plan = NUMPLAN_ISDN;
2483  id->number[0] = 0;
2484  break;
2485  }
2486 }
2487 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2488 
2489 #if defined(AST_MISDN_ENHANCEMENTS)
2490 static const char Level_Spacing[] = " ";/* Work for up to 10 levels */
2491 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2492 
2493 #if defined(AST_MISDN_ENHANCEMENTS)
2494 static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2495 {
2496  if (Party->LengthOfNumber) {
2497  const char *Spacing;
2498 
2499  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2500  chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
2501  Spacing, Party->Type);
2502  switch (Party->Type) {
2503  case 0: /* Unknown PartyNumber */
2504  chan_misdn_log(1, bc->port, " -->%s Unknown: %s\n",
2505  Spacing, Party->Number);
2506  break;
2507  case 1: /* Public PartyNumber */
2508  chan_misdn_log(1, bc->port, " -->%s Public TON:%d %s\n",
2509  Spacing, Party->TypeOfNumber, Party->Number);
2510  break;
2511  case 2: /* NSAP encoded PartyNumber */
2512  chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
2513  Spacing, Party->Number);
2514  break;
2515  case 3: /* Data PartyNumber (Not used) */
2516  chan_misdn_log(1, bc->port, " -->%s Data: %s\n",
2517  Spacing, Party->Number);
2518  break;
2519  case 4: /* Telex PartyNumber (Not used) */
2520  chan_misdn_log(1, bc->port, " -->%s Telex: %s\n",
2521  Spacing, Party->Number);
2522  break;
2523  case 5: /* Private PartyNumber */
2524  chan_misdn_log(1, bc->port, " -->%s Private TON:%d %s\n",
2525  Spacing, Party->TypeOfNumber, Party->Number);
2526  break;
2527  case 8: /* National Standard PartyNumber (Not used) */
2528  chan_misdn_log(1, bc->port, " -->%s National: %s\n",
2529  Spacing, Party->Number);
2530  break;
2531  default:
2532  break;
2533  }
2534  }
2535 }
2536 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2537 
2538 #if defined(AST_MISDN_ENHANCEMENTS)
2539 static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
2540 {
2541  if (Subaddress->Length) {
2542  const char *Spacing;
2543 
2544  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2545  chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
2546  Spacing, Subaddress->Type);
2547  switch (Subaddress->Type) {
2548  case 0: /* UserSpecified */
2549  if (Subaddress->u.UserSpecified.OddCountPresent) {
2550  chan_misdn_log(1, bc->port, " -->%s User BCD OddCount:%d NumOctets:%d\n",
2551  Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
2552  } else {
2553  chan_misdn_log(1, bc->port, " -->%s User: %s\n",
2554  Spacing, Subaddress->u.UserSpecified.Information);
2555  }
2556  break;
2557  case 1: /* NSAP */
2558  chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
2559  Spacing, Subaddress->u.Nsap);
2560  break;
2561  default:
2562  break;
2563  }
2564  }
2565 }
2566 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2567 
2568 #if defined(AST_MISDN_ENHANCEMENTS)
2569 static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
2570 {
2571  print_facility_PartyNumber(Level, &Address->Party, bc);
2572  print_facility_Subaddress(Level, &Address->Subaddress, bc);
2573 }
2574 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2575 
2576 #if defined(AST_MISDN_ENHANCEMENTS)
2577 static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, const struct misdn_bchannel *bc)
2578 {
2579  const char *Spacing;
2580 
2581  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2582  chan_misdn_log(1, bc->port, " -->%s Unscreened Type:%d\n", Spacing, Presented->Type);
2583  switch (Presented->Type) {
2584  case 0: /* presentationAllowedNumber */
2585  chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
2586  print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2587  break;
2588  case 1: /* presentationRestricted */
2589  chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
2590  break;
2591  case 2: /* numberNotAvailableDueToInterworking */
2592  chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
2593  break;
2594  case 3: /* presentationRestrictedNumber */
2595  chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
2596  print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2597  break;
2598  default:
2599  break;
2600  }
2601 }
2602 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2603 
2604 #if defined(AST_MISDN_ENHANCEMENTS)
2605 static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
2606 {
2607  const char *Spacing;
2608 
2609  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2610  chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
2611  print_facility_PartyNumber(Level, &Address->Party, bc);
2612  print_facility_Subaddress(Level, &Address->Subaddress, bc);
2613 }
2614 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2615 
2616 #if defined(AST_MISDN_ENHANCEMENTS)
2617 static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, const struct misdn_bchannel *bc)
2618 {
2619  const char *Spacing;
2620 
2621  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2622  chan_misdn_log(1, bc->port, " -->%s Screened Type:%d\n", Spacing, Presented->Type);
2623  switch (Presented->Type) {
2624  case 0: /* presentationAllowedAddress */
2625  chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
2626  print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2627  break;
2628  case 1: /* presentationRestricted */
2629  chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
2630  break;
2631  case 2: /* numberNotAvailableDueToInterworking */
2632  chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
2633  break;
2634  case 3: /* presentationRestrictedAddress */
2635  chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
2636  print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2637  break;
2638  default:
2639  break;
2640  }
2641 }
2642 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2643 
2644 #if defined(AST_MISDN_ENHANCEMENTS)
2645 static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
2646 {
2647  const char *Spacing;
2648 
2649  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2650  chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2651  if (Q931ie->Bc.Length) {
2652  chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2653  }
2654  if (Q931ie->Hlc.Length) {
2655  chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2656  }
2657  if (Q931ie->Llc.Length) {
2658  chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2659  }
2660 }
2661 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2662 
2663 #if defined(AST_MISDN_ENHANCEMENTS)
2664 static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
2665 {
2666  const char *Spacing;
2667 
2668  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2669  chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2670  if (Q931ie->Bc.Length) {
2671  chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2672  }
2673  if (Q931ie->Hlc.Length) {
2674  chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2675  }
2676  if (Q931ie->Llc.Length) {
2677  chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2678  }
2679  if (Q931ie->UserInfo.Length) {
2680  chan_misdn_log(1, bc->port, " -->%s UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
2681  }
2682 }
2683 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2684 
2685 #if defined(AST_MISDN_ENHANCEMENTS)
2686 static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
2687 {
2688  const char *Spacing;
2689 
2690  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2691  chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
2692  Spacing, CallInfo->CCBSReference);
2693  chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
2694  print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
2695  print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
2696  if (CallInfo->SubaddressOfA.Length) {
2697  chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
2698  print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
2699  }
2700 }
2701 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2702 
2703 #if defined(AST_MISDN_ENHANCEMENTS)
2704 static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2705 {
2706  const char *Spacing;
2707 
2708  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2709  if (Party->LengthOfNumber) {
2710  print_facility_PartyNumber(Level, Party, bc);
2711  } else {
2712  chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
2713  }
2714 }
2715 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2716 
2717 #if defined(AST_MISDN_ENHANCEMENTS)
2718 static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
2719 {
2720  const char *Spacing;
2721 
2722  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2723  chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
2724  Spacing,
2725  ForwardingRecord->Procedure,
2726  ForwardingRecord->BasicService);
2727  chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
2728  print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
2729  chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
2730  print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
2731 }
2732 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2733 
2734 static void print_facility(const struct FacParm *fac, const struct misdn_bchannel *bc)
2735 {
2736 #if defined(AST_MISDN_ENHANCEMENTS)
2737  unsigned Index;
2738 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2739 
2740  switch (fac->Function) {
2741 #if defined(AST_MISDN_ENHANCEMENTS)
2742  case Fac_ActivationDiversion:
2743  chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
2744  fac->u.ActivationDiversion.InvokeID);
2745  switch (fac->u.ActivationDiversion.ComponentType) {
2746  case FacComponent_Invoke:
2747  chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2748  fac->u.ActivationDiversion.Component.Invoke.Procedure,
2749  fac->u.ActivationDiversion.Component.Invoke.BasicService);
2750  chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
2751  print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
2752  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2753  print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
2754  break;
2755  case FacComponent_Result:
2756  chan_misdn_log(1, bc->port, " --> Result\n");
2757  break;
2758  default:
2759  break;
2760  }
2761  break;
2762  case Fac_DeactivationDiversion:
2763  chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
2764  fac->u.DeactivationDiversion.InvokeID);
2765  switch (fac->u.DeactivationDiversion.ComponentType) {
2766  case FacComponent_Invoke:
2767  chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2768  fac->u.DeactivationDiversion.Component.Invoke.Procedure,
2769  fac->u.DeactivationDiversion.Component.Invoke.BasicService);
2770  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2771  print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
2772  break;
2773  case FacComponent_Result:
2774  chan_misdn_log(1, bc->port, " --> Result\n");
2775  break;
2776  default:
2777  break;
2778  }
2779  break;
2780  case Fac_ActivationStatusNotificationDiv:
2781  chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2782  fac->u.ActivationStatusNotificationDiv.InvokeID,
2783  fac->u.ActivationStatusNotificationDiv.Procedure,
2784  fac->u.ActivationStatusNotificationDiv.BasicService);
2785  chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
2786  print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
2787  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2788  print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
2789  break;
2790  case Fac_DeactivationStatusNotificationDiv:
2791  chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2792  fac->u.DeactivationStatusNotificationDiv.InvokeID,
2793  fac->u.DeactivationStatusNotificationDiv.Procedure,
2794  fac->u.DeactivationStatusNotificationDiv.BasicService);
2795  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2796  print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
2797  break;
2798  case Fac_InterrogationDiversion:
2799  chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
2800  fac->u.InterrogationDiversion.InvokeID);
2801  switch (fac->u.InterrogationDiversion.ComponentType) {
2802  case FacComponent_Invoke:
2803  chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2804  fac->u.InterrogationDiversion.Component.Invoke.Procedure,
2805  fac->u.InterrogationDiversion.Component.Invoke.BasicService);
2806  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2807  print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
2808  break;
2809  case FacComponent_Result:
2810  chan_misdn_log(1, bc->port, " --> Result:\n");
2811  if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
2812  for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
2813  chan_misdn_log(1, bc->port, " --> IntResult[%d]:\n", Index);
2814  print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
2815  }
2816  }
2817  break;
2818  default:
2819  break;
2820  }
2821  break;
2822  case Fac_DiversionInformation:
2823  chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
2824  fac->u.DiversionInformation.InvokeID,
2825  fac->u.DiversionInformation.DiversionReason,
2826  fac->u.DiversionInformation.BasicService);
2827  if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
2828  chan_misdn_log(1, bc->port, " --> ServedUserSubaddress:\n");
2829  print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
2830  }
2831  if (fac->u.DiversionInformation.CallingAddressPresent) {
2832  chan_misdn_log(1, bc->port, " --> CallingAddress:\n");
2833  print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
2834  }
2835  if (fac->u.DiversionInformation.OriginalCalledPresent) {
2836  chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
2837  print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
2838  }
2839  if (fac->u.DiversionInformation.LastDivertingPresent) {
2840  chan_misdn_log(1, bc->port, " --> LastDivertingNr:\n");
2841  print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
2842  }
2843  if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
2844  chan_misdn_log(1, bc->port, " --> LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
2845  }
2846  if (fac->u.DiversionInformation.UserInfo.Length) {
2847  chan_misdn_log(1, bc->port, " --> UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
2848  }
2849  break;
2850  case Fac_CallDeflection:
2851  chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
2852  fac->u.CallDeflection.InvokeID);
2853  switch (fac->u.CallDeflection.ComponentType) {
2854  case FacComponent_Invoke:
2855  chan_misdn_log(1, bc->port, " --> Invoke:\n");
2856  if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
2857  chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
2858  fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
2859  }
2860  chan_misdn_log(1, bc->port, " --> DeflectionAddress:\n");
2861  print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
2862  break;
2863  case FacComponent_Result:
2864  chan_misdn_log(1, bc->port, " --> Result\n");
2865  break;
2866  default:
2867  break;
2868  }
2869  break;
2870  case Fac_CallRerouteing:
2871  chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
2872  fac->u.CallRerouteing.InvokeID);
2873  switch (fac->u.CallRerouteing.ComponentType) {
2874  case FacComponent_Invoke:
2875  chan_misdn_log(1, bc->port, " --> Invoke: Reason:%d Counter:%d\n",
2876  fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
2877  fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
2878  chan_misdn_log(1, bc->port, " --> CalledAddress:\n");
2879  print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
2880  print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
2881  chan_misdn_log(1, bc->port, " --> LastReroutingNr:\n");
2882  print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
2883  chan_misdn_log(1, bc->port, " --> SubscriptionOption:%d\n",
2884  fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
2885  if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
2886  chan_misdn_log(1, bc->port, " --> CallingParty:\n");
2887  print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
2888  }
2889  break;
2890  case FacComponent_Result:
2891  chan_misdn_log(1, bc->port, " --> Result\n");
2892  break;
2893  default:
2894  break;
2895  }
2896  break;
2897  case Fac_InterrogateServedUserNumbers:
2898  chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
2899  fac->u.InterrogateServedUserNumbers.InvokeID);
2900  switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
2901  case FacComponent_Invoke:
2902  chan_misdn_log(1, bc->port, " --> Invoke\n");
2903  break;
2904  case FacComponent_Result:
2905  chan_misdn_log(1, bc->port, " --> Result:\n");
2906  if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
2907  for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
2908  chan_misdn_log(1, bc->port, " --> ServedUserNr[%d]:\n", Index);
2909  print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
2910  }
2911  }
2912  break;
2913  default:
2914  break;
2915  }
2916  break;
2917  case Fac_DivertingLegInformation1:
2918  chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
2919  fac->u.DivertingLegInformation1.InvokeID,
2920  fac->u.DivertingLegInformation1.DiversionReason,
2921  fac->u.DivertingLegInformation1.SubscriptionOption);
2922  if (fac->u.DivertingLegInformation1.DivertedToPresent) {
2923  chan_misdn_log(1, bc->port, " --> DivertedToNr:\n");
2924  print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
2925  }
2926  break;
2927  case Fac_DivertingLegInformation2:
2928  chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
2929  fac->u.DivertingLegInformation2.InvokeID,
2930  fac->u.DivertingLegInformation2.DiversionReason,
2931  fac->u.DivertingLegInformation2.DiversionCounter);
2932  if (fac->u.DivertingLegInformation2.DivertingPresent) {
2933  chan_misdn_log(1, bc->port, " --> DivertingNr:\n");
2934  print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
2935  }
2936  if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
2937  chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
2938  print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
2939  }
2940  break;
2941  case Fac_DivertingLegInformation3:
2942  chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
2943  fac->u.DivertingLegInformation3.InvokeID,
2944  fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
2945  break;
2946 
2947 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
2948 
2949  case Fac_CD:
2950  chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
2951  fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
2952  break;
2953 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
2954  case Fac_AOCDCurrency:
2955  if (fac->u.AOCDcur.chargeNotAvailable) {
2956  chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
2957  } else if (fac->u.AOCDcur.freeOfCharge) {
2958  chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
2959  } else if (fac->u.AOCDchu.billingId >= 0) {
2960  chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
2961  fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2962  (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
2963  } else {
2964  chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
2965  fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2966  (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
2967  }
2968  break;
2969  case Fac_AOCDChargingUnit:
2970  if (fac->u.AOCDchu.chargeNotAvailable) {
2971  chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
2972  } else if (fac->u.AOCDchu.freeOfCharge) {
2973  chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
2974  } else if (fac->u.AOCDchu.billingId >= 0) {
2975  chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
2976  fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
2977  } else {
2978  chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
2979  fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
2980  }
2981  break;
2982 #if defined(AST_MISDN_ENHANCEMENTS)
2983  case Fac_ERROR:
2984  chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
2985  fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
2986  break;
2987  case Fac_RESULT:
2988  chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
2989  fac->u.RESULT.InvokeID);
2990  break;
2991  case Fac_REJECT:
2992  if (fac->u.REJECT.InvokeIDPresent) {
2993  chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
2994  fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
2995  } else {
2996  chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
2997  fac->u.REJECT.Code);
2998  }
2999  break;
3000  case Fac_EctExecute:
3001  chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
3002  fac->u.EctExecute.InvokeID);
3003  break;
3004  case Fac_ExplicitEctExecute:
3005  chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
3006  fac->u.ExplicitEctExecute.InvokeID,
3007  fac->u.ExplicitEctExecute.LinkID);
3008  break;
3009  case Fac_RequestSubaddress:
3010  chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
3011  fac->u.RequestSubaddress.InvokeID);
3012  break;
3013  case Fac_SubaddressTransfer:
3014  chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
3015  fac->u.SubaddressTransfer.InvokeID);
3016  print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
3017  break;
3018  case Fac_EctLinkIdRequest:
3019  chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
3020  fac->u.EctLinkIdRequest.InvokeID);
3021  switch (fac->u.EctLinkIdRequest.ComponentType) {
3022  case FacComponent_Invoke:
3023  chan_misdn_log(1, bc->port, " --> Invoke\n");
3024  break;
3025  case FacComponent_Result:
3026  chan_misdn_log(1, bc->port, " --> Result: LinkID:%d\n",
3027  fac->u.EctLinkIdRequest.Component.Result.LinkID);
3028  break;
3029  default:
3030  break;
3031  }
3032  break;
3033  case Fac_EctInform:
3034  chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
3035  fac->u.EctInform.InvokeID,
3036  fac->u.EctInform.Status);
3037  if (fac->u.EctInform.RedirectionPresent) {
3038  chan_misdn_log(1, bc->port, " --> Redirection Number\n");
3039  print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
3040  }
3041  break;
3042  case Fac_EctLoopTest:
3043  chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
3044  fac->u.EctLoopTest.InvokeID);
3045  switch (fac->u.EctLoopTest.ComponentType) {
3046  case FacComponent_Invoke:
3047  chan_misdn_log(1, bc->port, " --> Invoke: CallTransferID:%d\n",
3048  fac->u.EctLoopTest.Component.Invoke.CallTransferID);
3049  break;
3050  case FacComponent_Result:
3051  chan_misdn_log(1, bc->port, " --> Result: LoopResult:%d\n",
3052  fac->u.EctLoopTest.Component.Result.LoopResult);
3053  break;
3054  default:
3055  break;
3056  }
3057  break;
3058  case Fac_StatusRequest:
3059  chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
3060  fac->u.StatusRequest.InvokeID);
3061  switch (fac->u.StatusRequest.ComponentType) {
3062  case FacComponent_Invoke:
3063  chan_misdn_log(1, bc->port, " --> Invoke: Compatibility:%d\n",
3064  fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
3065  break;
3066  case FacComponent_Result:
3067  chan_misdn_log(1, bc->port, " --> Result: Status:%d\n",
3068  fac->u.StatusRequest.Component.Result.Status);
3069  break;
3070  default:
3071  break;
3072  }
3073  break;
3074  case Fac_CallInfoRetain:
3075  chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
3076  fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
3077  break;
3078  case Fac_CCBSDeactivate:
3079  chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
3080  fac->u.CCBSDeactivate.InvokeID);
3081  switch (fac->u.CCBSDeactivate.ComponentType) {
3082  case FacComponent_Invoke:
3083  chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d\n",
3084  fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
3085  break;
3086  case FacComponent_Result:
3087  chan_misdn_log(1, bc->port, " --> Result\n");
3088  break;
3089  default:
3090  break;
3091  }
3092  break;
3093  case Fac_CCBSErase:
3094  chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
3095  fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
3096  fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
3097  chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3098  print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
3099  print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
3100  break;
3101  case Fac_CCBSRemoteUserFree:
3102  chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3103  fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
3104  fac->u.CCBSRemoteUserFree.RecallMode);
3105  chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3106  print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
3107  print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
3108  break;
3109  case Fac_CCBSCall:
3110  chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
3111  fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
3112  break;
3113  case Fac_CCBSStatusRequest:
3114  chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
3115  fac->u.CCBSStatusRequest.InvokeID);
3116  switch (fac->u.CCBSStatusRequest.ComponentType) {
3117  case FacComponent_Invoke:
3118  chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d RecallMode:%d\n",
3119  fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
3120  fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
3121  print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
3122  break;
3123  case FacComponent_Result:
3124  chan_misdn_log(1, bc->port, " --> Result: Free:%d\n",
3125  fac->u.CCBSStatusRequest.Component.Result.Free);
3126  break;
3127  default:
3128  break;
3129  }
3130  break;
3131  case Fac_CCBSBFree:
3132  chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3133  fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
3134  fac->u.CCBSBFree.RecallMode);
3135  chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3136  print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
3137  print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
3138  break;
3139  case Fac_EraseCallLinkageID:
3140  chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
3141  fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
3142  break;
3143  case Fac_CCBSStopAlerting:
3144  chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
3145  fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
3146  break;
3147  case Fac_CCBSRequest:
3148  chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
3149  fac->u.CCBSRequest.InvokeID);
3150  switch (fac->u.CCBSRequest.ComponentType) {
3151  case FacComponent_Invoke:
3152  chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
3153  fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
3154  break;
3155  case FacComponent_Result:
3156  chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
3157  fac->u.CCBSRequest.Component.Result.CCBSReference,
3158  fac->u.CCBSRequest.Component.Result.RecallMode);
3159  break;
3160  default:
3161  break;
3162  }
3163  break;
3164  case Fac_CCBSInterrogate:
3165  chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
3166  fac->u.CCBSInterrogate.InvokeID);
3167  switch (fac->u.CCBSInterrogate.ComponentType) {
3168  case FacComponent_Invoke:
3169  chan_misdn_log(1, bc->port, " --> Invoke\n");
3170  if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
3171  chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
3172  fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
3173  }
3174  if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3175  chan_misdn_log(1, bc->port, " --> AParty\n");
3176  print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
3177  }
3178  break;
3179  case FacComponent_Result:
3180  chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
3181  fac->u.CCBSInterrogate.Component.Result.RecallMode);
3182  if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
3183  for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
3184  chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
3185  print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
3186  }
3187  }
3188  break;
3189  default:
3190  break;
3191  }
3192  break;
3193  case Fac_CCNRRequest:
3194  chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
3195  fac->u.CCNRRequest.InvokeID);
3196  switch (fac->u.CCNRRequest.ComponentType) {
3197  case FacComponent_Invoke:
3198  chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
3199  fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
3200  break;
3201  case FacComponent_Result:
3202  chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
3203  fac->u.CCNRRequest.Component.Result.CCBSReference,
3204  fac->u.CCNRRequest.Component.Result.RecallMode);
3205  break;
3206  default:
3207  break;
3208  }
3209  break;
3210  case Fac_CCNRInterrogate:
3211  chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
3212  fac->u.CCNRInterrogate.InvokeID);
3213  switch (fac->u.CCNRInterrogate.ComponentType) {
3214  case FacComponent_Invoke:
3215  chan_misdn_log(1, bc->port, " --> Invoke\n");
3216  if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
3217  chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
3218  fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
3219  }
3220  if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3221  chan_misdn_log(1, bc->port, " --> AParty\n");
3222  print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
3223  }
3224  break;
3225  case FacComponent_Result:
3226  chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
3227  fac->u.CCNRInterrogate.Component.Result.RecallMode);
3228  if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
3229  for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
3230  chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
3231  print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
3232  }
3233  }
3234  break;
3235  default:
3236  break;
3237  }
3238  break;
3239  case Fac_CCBS_T_Call:
3240  chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
3241  fac->u.CCBS_T_Call.InvokeID);
3242  break;
3243  case Fac_CCBS_T_Suspend:
3244  chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
3245  fac->u.CCBS_T_Suspend.InvokeID);
3246  break;
3247  case Fac_CCBS_T_Resume:
3248  chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
3249  fac->u.CCBS_T_Resume.InvokeID);
3250  break;
3251  case Fac_CCBS_T_RemoteUserFree:
3252  chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
3253  fac->u.CCBS_T_RemoteUserFree.InvokeID);
3254  break;
3255  case Fac_CCBS_T_Available:
3256  chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
3257  fac->u.CCBS_T_Available.InvokeID);
3258  break;
3259  case Fac_CCBS_T_Request:
3260  chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
3261  fac->u.CCBS_T_Request.InvokeID);
3262  switch (fac->u.CCBS_T_Request.ComponentType) {
3263  case FacComponent_Invoke:
3264  chan_misdn_log(1, bc->port, " --> Invoke\n");
3265  chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
3266  print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
3267  print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
3268  if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
3269  chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
3270  }
3271  if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
3272  chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
3273  fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);
3274  }
3275  if (fac->u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
3276  chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
3277  print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Originating, bc);
3278  }
3279  break;
3280  case FacComponent_Result:
3281  chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
3282  fac->u.CCBS_T_Request.Component.Result.RetentionSupported);
3283  break;
3284  default:
3285  break;
3286  }
3287  break;
3288  case Fac_CCNR_T_Request:
3289  chan_misdn_log(1, bc->port, " --> CCNR_T_Request: InvokeID:%d\n",
3290  fac->u.CCNR_T_Request.InvokeID);
3291  switch (fac->u.CCNR_T_Request.ComponentType) {
3292  case FacComponent_Invoke:
3293  chan_misdn_log(1, bc->port, " --> Invoke\n");
3294  chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
3295  print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Destination, bc);
3296  print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCNR_T_Request.Component.Invoke.Q931ie, bc);
3297  if (fac->u.CCNR_T_Request.Component.Invoke.RetentionSupported) {
3298  chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
3299  }
3300  if (fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
3301  chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
3302  fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicator);
3303  }
3304  if (fac->u.CCNR_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
3305  chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
3306  print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Originating, bc);
3307  }
3308  break;
3309  case FacComponent_Result:
3310  chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
3311  fac->u.CCNR_T_Request.Component.Result.RetentionSupported);
3312  break;
3313  default:
3314  break;
3315  }
3316  break;
3317 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
3318  case Fac_None:
3319  /* No facility so print nothing */
3320  break;
3321  default:
3322  chan_misdn_log(1, bc->port, " --> unknown facility\n");
3323  break;
3324  }
3325 }
3326 
3327 static void print_bearer(struct misdn_bchannel *bc)
3328 {
3329  chan_misdn_log(2, bc->port, " --> Bearer: %s\n", bearer2str(bc->capability));
3330 
3331  switch(bc->law) {
3332  case INFO_CODEC_ALAW:
3333  chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
3334  break;
3335  case INFO_CODEC_ULAW:
3336  chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
3337  break;
3338  }
3339 }
3340 
3341 /*!
3342  * \internal
3343  * \brief Prefix a string to another string in place.
3344  *
3345  * \param str_prefix String to prefix to the main string.
3346  * \param str_main String to get the prefix added to it.
3347  * \param size Buffer size of the main string (Includes null terminator).
3348  *
3349  * \note The str_main buffer size must be greater than one.
3350  *
3351  * \return Nothing
3352  */
3353 static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
3354 {
3355  size_t len_over;
3356  size_t len_total;
3357  size_t len_main;
3358  size_t len_prefix;
3359 
3360  len_prefix = strlen(str_prefix);
3361  if (!len_prefix) {
3362  /* There is no prefix to prepend. */
3363  return;
3364  }
3365  len_main = strlen(str_main);
3366  len_total = len_prefix + len_main;
3367  if (size <= len_total) {
3368  /* We need to truncate since the buffer is too small. */
3369  len_over = len_total + 1 - size;
3370  if (len_over <= len_main) {
3371  len_main -= len_over;
3372  } else {
3373  len_over -= len_main;
3374  len_main = 0;
3375  len_prefix -= len_over;
3376  }
3377  }
3378  if (len_main) {
3379  memmove(str_main + len_prefix, str_main, len_main);
3380  }
3381  memcpy(str_main, str_prefix, len_prefix);
3382  str_main[len_prefix + len_main] = '\0';
3383 }
3384 
3385 /*!
3386  * \internal
3387  * \brief Add a configured prefix to the given number.
3388  *
3389  * \param port Logical port number
3390  * \param number_type Type-of-number passed in.
3391  * \param number Given number string to add prefix
3392  * \param size Buffer size number string occupies.
3393  *
3394  * \return Nothing
3395  */
3396 static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
3397 {
3398  enum misdn_cfg_elements type_prefix;
3399  char num_prefix[MISDN_MAX_NUMBER_LEN];
3400 
3401  /* Get prefix string. */
3402  switch (number_type) {
3403  case NUMTYPE_UNKNOWN:
3404  type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
3405  break;
3406  case NUMTYPE_INTERNATIONAL:
3407  type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
3408  break;
3409  case NUMTYPE_NATIONAL:
3410  type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
3411  break;
3414  break;
3415  case NUMTYPE_SUBSCRIBER:
3416  type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
3417  break;
3418  case NUMTYPE_ABBREVIATED:
3419  type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
3420  break;
3421  default:
3422  /* Type-of-number does not have a prefix that can be added. */
3423  return;
3424  }
3425  misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
3426 
3427  misdn_prefix_string(num_prefix, number, size);
3428 }
3429 
3430 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
3431 {
3432  char buf[128];
3433 
3434  if (!bc->AOCD_need_export || !ast) {
3435  return;
3436  }
3437 
3438  if (originator == ORG_AST) {
3439  ast = ast_bridged_channel(ast);
3440  if (!ast) {
3441  return;
3442  }
3443  }
3444 
3445  switch (bc->AOCDtype) {
3446  case Fac_AOCDCurrency:
3447  pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
3448  if (bc->AOCD.currency.chargeNotAvailable) {
3449  pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
3450  } else {
3451  pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
3452  if (bc->AOCD.currency.freeOfCharge) {
3453  pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
3454  } else {
3455  pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
3456  if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
3457  pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
3458  if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf)) {
3459  pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
3460  }
3461  }
3462  }
3463  }
3464  break;
3465  case Fac_AOCDChargingUnit:
3466  pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
3467  if (bc->AOCD.chargingUnit.chargeNotAvailable) {
3468  pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
3469  } else {
3470  pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
3471  if (bc->AOCD.chargingUnit.freeOfCharge) {
3472  pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
3473  } else {
3474  pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
3475  if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
3476  pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
3477  if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf)) {
3478  pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
3479  }
3480  }
3481  }
3482  }
3483  break;
3484  default:
3485  break;
3486  }
3487 
3488  bc->AOCD_need_export = 0;
3489 }
3490 
3491 /*************** Helpers END *************/
3492 
3493 static void sighandler(int sig)
3494 {
3495 }
3496 
3497 static void *misdn_tasks_thread_func(void *data)
3498 {
3499  int wait;
3500  struct sigaction sa;
3501 
3502  sa.sa_handler = sighandler;
3503  sa.sa_flags = SA_NODEFER;
3504  sigemptyset(&sa.sa_mask);
3505  sigaddset(&sa.sa_mask, SIGUSR1);
3506  sigaction(SIGUSR1, &sa, NULL);
3507 
3508  sem_post((sem_t *)data);
3509 
3510  while (1) {
3511  wait = ast_sched_wait(misdn_tasks);
3512  if (wait < 0) {
3513  wait = 8000;
3514  }
3515  if (poll(NULL, 0, wait) < 0) {
3516  chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
3517  }
3518  ast_sched_runq(misdn_tasks);
3519  }
3520  return NULL;
3521 }
3522 
3523 static void misdn_tasks_init(void)
3524 {
3525  sem_t blocker;
3526  int i = 5;
3527 
3528  if (sem_init(&blocker, 0, 0)) {
3529  perror("chan_misdn: Failed to initialize semaphore!");
3530  exit(1);
3531  }
3532 
3533  chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
3534 
3535  misdn_tasks = sched_context_create();
3536  pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
3537 
3538  while (sem_wait(&blocker) && --i) {
3539  }
3540  sem_destroy(&blocker);
3541 }
3542 
3543 static void misdn_tasks_destroy(void)
3544 {
3545  if (misdn_tasks) {
3546  chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
3547  if (pthread_cancel(misdn_tasks_thread) == 0) {
3548  cb_log(4, 0, "Joining misdn_tasks thread\n");
3549  pthread_join(misdn_tasks_thread, NULL);
3550  }
3551  sched_context_destroy(misdn_tasks);
3552  }
3553 }
3554 
3555 static inline void misdn_tasks_wakeup(void)
3556 {
3557  pthread_kill(misdn_tasks_thread, SIGUSR1);
3558 }
3559 
3560 static inline int _misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data, int variable)
3561 {
3562  int task_id;
3563 
3564  if (!misdn_tasks) {
3565  misdn_tasks_init();
3566  }
3567  task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
3569 
3570  return task_id;
3571 }
3572 
3573 static int misdn_tasks_add(int timeout, ast_sched_cb callback, const void *data)
3574 {
3575  return _misdn_tasks_add_variable(timeout, callback, data, 0);
3576 }
3577 
3578 static int misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data)
3579 {
3580  return _misdn_tasks_add_variable(timeout, callback, data, 1);
3581 }
3582 
3583 static void misdn_tasks_remove(int task_id)
3584 {
3585  AST_SCHED_DEL(misdn_tasks, task_id);
3586 }
3587 
3588 static int misdn_l1_task(const void *vdata)
3589 {
3590  const int *data = vdata;
3591 
3592  misdn_lib_isdn_l1watcher(*data);
3593  chan_misdn_log(5, *data, "L1watcher timeout\n");
3594  return 1;
3595 }
3596 
3597 static int misdn_overlap_dial_task(const void *data)
3598 {
3599  struct timeval tv_end, tv_now;
3600  int diff;
3601  struct chan_list *ch = (struct chan_list *) data;
3602  char *dad;
3603 
3604  chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
3605 
3606  if (ch->state != MISDN_WAITING4DIGS) {
3607  ch->overlap_dial_task = -1;
3608  return 0;
3609  }
3610 
3612  tv_end = ch->overlap_tv;
3614 
3615  tv_end.tv_sec += ch->overlap_dial;
3616  tv_now = ast_tvnow();
3617 
3618  diff = ast_tvdiff_ms(tv_end, tv_now);
3619  if (100 < diff) {
3620  return diff;
3621  }
3622 
3623  /* if we are 100ms near the timeout, we are satisfied.. */
3624  stop_indicate(ch);
3625 
3626  if (ast_strlen_zero(ch->bc->dialed.number)) {
3627  dad = "s";
3628  strcpy(ch->ast->exten, dad);
3629  } else {
3630  dad = ch->bc->dialed.number;
3631  }
3632 
3633  if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
3634  ch->state = MISDN_DIALING;
3635  if (pbx_start_chan(ch) < 0) {
3636  chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
3637  goto misdn_overlap_dial_task_disconnect;
3638  }
3639  } else {
3640 misdn_overlap_dial_task_disconnect:
3641  hanguptone_indicate(ch);
3643  ch->state = MISDN_CLEANING;
3645  }
3646  ch->overlap_dial_task = -1;
3647  return 0;
3648 }
3649 
3650 static void send_digit_to_chan(struct chan_list *cl, char digit)
3651 {
3652  static const char * const dtmf_tones[] = {
3653 /* *INDENT-OFF* */
3654  "!941+1336/100,!0/100", /* 0 */
3655  "!697+1209/100,!0/100", /* 1 */
3656  "!697+1336/100,!0/100", /* 2 */
3657  "!697+1477/100,!0/100", /* 3 */
3658  "!770+1209/100,!0/100", /* 4 */
3659  "!770+1336/100,!0/100", /* 5 */
3660  "!770+1477/100,!0/100", /* 6 */
3661  "!852+1209/100,!0/100", /* 7 */
3662  "!852+1336/100,!0/100", /* 8 */
3663  "!852+1477/100,!0/100", /* 9 */
3664  "!697+1633/100,!0/100", /* A */
3665  "!770+1633/100,!0/100", /* B */
3666  "!852+1633/100,!0/100", /* C */
3667  "!941+1633/100,!0/100", /* D */
3668  "!941+1209/100,!0/100", /* * */
3669  "!941+1477/100,!0/100", /* # */
3670 /* *INDENT-ON* */
3671  };
3672  struct ast_channel *chan = cl->ast;
3673 
3674  if (digit >= '0' && digit <='9') {
3675  ast_playtones_start(chan, 0, dtmf_tones[digit - '0'], 0);
3676  } else if (digit >= 'A' && digit <= 'D') {
3677  ast_playtones_start(chan, 0, dtmf_tones[digit - 'A' + 10], 0);
3678  } else if (digit == '*') {
3679  ast_playtones_start(chan, 0, dtmf_tones[14], 0);
3680  } else if (digit == '#') {
3681  ast_playtones_start(chan, 0, dtmf_tones[15], 0);
3682  } else {
3683  /* not handled */
3684  ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
3685  }
3686 }
3687 
3688 /*** CLI HANDLING ***/
3689 static char *handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3690 {
3691  int level;
3692 
3693  switch (cmd) {
3694  case CLI_INIT:
3695  e->command = "misdn set debug [on|off]";
3696  e->usage =
3697  "Usage: misdn set debug {on|off|<level>} [only] | [port <port> [only]]\n"
3698  " Set the debug level of the mISDN channel.\n";
3699  return NULL;
3700  case CLI_GENERATE:
3701  return complete_debug_port(a);
3702  }
3703 
3704  if (a->argc < 4 || a->argc > 7) {
3705  return CLI_SHOWUSAGE;
3706  }
3707 
3708  if (!strcasecmp(a->argv[3], "on")) {
3709  level = 1;
3710  } else if (!strcasecmp(a->argv[3], "off")) {
3711  level = 0;
3712  } else if (isdigit(a->argv[3][0])) {
3713  level = atoi(a->argv[3]);
3714  } else {
3715  return CLI_SHOWUSAGE;
3716  }
3717 
3718  switch (a->argc) {
3719  case 4:
3720  case 5:
3721  {
3722  int i;
3723  int only = 0;
3724  if (a->argc == 5) {
3725  if (strncasecmp(a->argv[4], "only", strlen(a->argv[4]))) {
3726  return CLI_SHOWUSAGE;
3727  } else {
3728  only = 1;
3729  }
3730  }
3731 
3732  for (i = 0; i <= max_ports; i++) {
3733  misdn_debug[i] = level;
3734  misdn_debug_only[i] = only;
3735  }
3736  ast_cli(a->fd, "changing debug level for all ports to %d%s\n", misdn_debug[0], only ? " (only)" : "");
3737  }
3738  break;
3739  case 6:
3740  case 7:
3741  {
3742  int port;
3743  if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
3744  return CLI_SHOWUSAGE;
3745  port = atoi(a->argv[5]);
3746  if (port <= 0 || port > max_ports) {
3747  switch (max_ports) {
3748  case 0:
3749  ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
3750  break;
3751  case 1:
3752  ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
3753  break;
3754  default:
3755  ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
3756  }
3757  return 0;
3758  }
3759  if (a->argc == 7) {
3760  if (strncasecmp(a->argv[6], "only", strlen(a->argv[6]))) {
3761  return CLI_SHOWUSAGE;
3762  } else {
3763  misdn_debug_only[port] = 1;
3764  }
3765  } else {
3766  misdn_debug_only[port] = 0;
3767  }
3768  misdn_debug[port] = level;
3769  ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port] ? " (only)" : "", port);
3770  }
3771  }
3772 
3773  return CLI_SUCCESS;
3774 }
3775 
3776 static char *handle_cli_misdn_set_crypt_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3777 {
3778  switch (cmd) {
3779  case CLI_INIT:
3780  e->command = "misdn set crypt debug";
3781  e->usage =
3782  "Usage: misdn set crypt debug <level>\n"
3783  " Set the crypt debug level of the mISDN channel. Level\n"
3784  " must be 1 or 2.\n";
3785  return NULL;
3786  case CLI_GENERATE:
3787  return NULL;
3788  }
3789 
3790  if (a->argc != 5) {
3791  return CLI_SHOWUSAGE;
3792  }
3793 
3794  /* XXX Is this supposed to not do anything? XXX */
3795 
3796  return CLI_SUCCESS;
3797 }
3798 
3799 static char *handle_cli_misdn_port_block(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3800 {
3801  switch (cmd) {
3802  case CLI_INIT:
3803  e->command = "misdn port block";
3804  e->usage =
3805  "Usage: misdn port block <port>\n"
3806  " Block the specified port by <port>.\n";
3807  return NULL;
3808  case CLI_GENERATE:
3809  return NULL;
3810  }
3811 
3812  if (a->argc != 4) {
3813  return CLI_SHOWUSAGE;
3814  }
3815 
3816  misdn_lib_port_block(atoi(a->argv[3]));
3817 
3818  return CLI_SUCCESS;
3819 }
3820 
3821 static char *handle_cli_misdn_port_unblock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3822 {
3823  switch (cmd) {
3824  case CLI_INIT:
3825  e->command = "misdn port unblock";
3826  e->usage =
3827  "Usage: misdn port unblock <port>\n"
3828  " Unblock the port specified by <port>.\n";
3829  return NULL;
3830  case CLI_GENERATE:
3831  return NULL;
3832  }
3833 
3834  if (a->argc != 4) {
3835  return CLI_SHOWUSAGE;
3836  }
3837 
3838  misdn_lib_port_unblock(atoi(a->argv[3]));
3839 
3840  return CLI_SUCCESS;
3841 }
3842 
3843 static char *handle_cli_misdn_restart_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3844 {
3845  switch (cmd) {
3846  case CLI_INIT:
3847  e->command = "misdn restart port";
3848  e->usage =
3849  "Usage: misdn restart port <port>\n"
3850  " Restart the given port.\n";
3851  return NULL;
3852  case CLI_GENERATE:
3853  return NULL;
3854  }
3855 
3856  if (a->argc != 4) {
3857  return CLI_SHOWUSAGE;
3858  }
3859 
3860  misdn_lib_port_restart(atoi(a->argv[3]));
3861 
3862  return CLI_SUCCESS;
3863 }
3864 
3865 static char *handle_cli_misdn_restart_pid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3866 {
3867  switch (cmd) {
3868  case CLI_INIT:
3869  e->command = "misdn restart pid";
3870  e->usage =
3871  "Usage: misdn restart pid <pid>\n"
3872  " Restart the given pid\n";
3873  return NULL;
3874  case CLI_GENERATE:
3875  return NULL;
3876  }
3877 
3878  if (a->argc != 4) {
3879  return CLI_SHOWUSAGE;
3880  }
3881 
3882  misdn_lib_pid_restart(atoi(a->argv[3]));
3883 
3884  return CLI_SUCCESS;
3885 }
3886 
3887 static char *handle_cli_misdn_port_up(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3888 {
3889  switch (cmd) {
3890  case CLI_INIT:
3891  e->command = "misdn port up";
3892  e->usage =
3893  "Usage: misdn port up <port>\n"
3894  " Try to establish L1 on the given port.\n";
3895  return NULL;
3896  case CLI_GENERATE:
3897  return NULL;
3898  }
3899 
3900  if (a->argc != 4) {
3901  return CLI_SHOWUSAGE;
3902  }
3903 
3904  misdn_lib_get_port_up(atoi(a->argv[3]));
3905 
3906  return CLI_SUCCESS;
3907 }
3908 
3909 static char *handle_cli_misdn_port_down(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3910 {
3911  switch (cmd) {
3912  case CLI_INIT:
3913  e->command = "misdn port down";
3914  e->usage =
3915  "Usage: misdn port down <port>\n"
3916  " Try to deactivate the L1 on the given port.\n";
3917  return NULL;
3918  case CLI_GENERATE:
3919  return NULL;
3920  }
3921 
3922  if (a->argc != 4) {
3923  return CLI_SHOWUSAGE;
3924  }
3925 
3926  misdn_lib_get_port_down(atoi(a->argv[3]));
3927 
3928  return CLI_SUCCESS;
3929 }
3930 
3931 static inline void show_config_description(int fd, enum misdn_cfg_elements elem)
3932 {
3933  char section[BUFFERSIZE];
3934  char name[BUFFERSIZE];
3935  char desc[BUFFERSIZE];
3936  char def[BUFFERSIZE];
3937  char tmp[BUFFERSIZE];
3938 
3939  misdn_cfg_get_name(elem, tmp, sizeof(tmp));
3940  term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
3941  misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
3942 
3943  if (elem < MISDN_CFG_LAST) {
3944  term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
3945  } else {
3946  term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
3947  }
3948 
3949  if (*def) {
3950  ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc);
3951  } else {
3952  ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
3953  }
3954 }
3955 
3956 static char *handle_cli_misdn_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3957 {
3958  char buffer[BUFFERSIZE];
3959  enum misdn_cfg_elements elem;
3960  int linebreak;
3961  int onlyport = -1;
3962  int ok = 0;
3963 
3964  switch (cmd) {
3965  case CLI_INIT:
3966  e->command = "misdn show config";
3967  e->usage =
3968  "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
3969  " Use 0 for <port> to only print the general config.\n";
3970  return NULL;
3971  case CLI_GENERATE:
3972  return complete_show_config(a);
3973  }
3974 
3975  if (a->argc >= 4) {
3976  if (!strcmp(a->argv[3], "description")) {
3977  if (a->argc == 5) {
3978  enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
3979  if (elem == MISDN_CFG_FIRST) {
3980  ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
3981  } else {
3982  show_config_description(a->fd, elem);
3983  }
3984  return CLI_SUCCESS;
3985  }
3986  return CLI_SHOWUSAGE;
3987  } else if (!strcmp(a->argv[3], "descriptions")) {
3988  if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
3989  for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
3990  show_config_description(a->fd, elem);
3991  ast_cli(a->fd, "\n");
3992  }
3993  ok = 1;
3994  }
3995  if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
3996  for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
3997  show_config_description(a->fd, elem);
3998  ast_cli(a->fd, "\n");
3999  }
4000  ok = 1;
4001  }
4002  return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
4003  } else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
4004  ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
4005  return CLI_SHOWUSAGE;
4006  }
4007  }
4008 
4009  if (a->argc == 3 || onlyport == 0) {
4010  ast_cli(a->fd, "mISDN General-Config:\n");
4011  for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
4012  misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
4013  ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
4014  }
4015  ast_cli(a->fd, "\n");
4016  }
4017 
4018  if (onlyport < 0) {
4019  int port = misdn_cfg_get_next_port(0);
4020 
4021  for (; port > 0; port = misdn_cfg_get_next_port(port)) {
4022  ast_cli(a->fd, "\n[PORT %d]\n", port);
4023  for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
4024  misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
4025  ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
4026  }
4027  ast_cli(a->fd, "\n");
4028  }
4029  }
4030 
4031  if (onlyport > 0) {
4032  if (misdn_cfg_is_port_valid(onlyport)) {
4033  ast_cli(a->fd, "[PORT %d]\n", onlyport);
4034  for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
4035  misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
4036  ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
4037  }
4038  ast_cli(a->fd, "\n");
4039  } else {
4040  ast_cli(a->fd, "Port %d is not active!\n", onlyport);
4041  }
4042  }
4043 
4044  return CLI_SUCCESS;
4045 }
4046 
4049  char txt[255];
4050 };
4051 
4052 static const struct state_struct state_array[] = {
4053 /* *INDENT-OFF* */
4054  { MISDN_NOTHING, "NOTHING" }, /* at beginning */
4055  { MISDN_WAITING4DIGS, "WAITING4DIGS" }, /* when waiting for infos */
4056  { MISDN_EXTCANTMATCH, "EXTCANTMATCH" }, /* when asterisk couldn't match our ext */
4057  { MISDN_INCOMING_SETUP, "INCOMING SETUP" }, /* when pbx_start */
4058  { MISDN_DIALING, "DIALING" }, /* when pbx_start */
4059  { MISDN_PROGRESS, "PROGRESS" }, /* when pbx_start */
4060  { MISDN_PROCEEDING, "PROCEEDING" }, /* when pbx_start */
4061  { MISDN_CALLING, "CALLING" }, /* when misdn_call is called */
4062  { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" }, /* when misdn_call is called */
4063  { MISDN_ALERTING, "ALERTING" }, /* when Alerting */
4064  { MISDN_BUSY, "BUSY" }, /* when BUSY */
4065  { MISDN_CONNECTED, "CONNECTED" }, /* when connected */
4066  { MISDN_DISCONNECTED, "DISCONNECTED" }, /* when connected */
4067  { MISDN_CLEANING, "CLEANING" }, /* when hangup from * but we were connected before */
4068 /* *INDENT-ON* */
4069 };
4070 
4071 static const char *misdn_get_ch_state(struct chan_list *p)
4072 {
4073  int i;
4074  static char state[8];
4075 
4076  if (!p) {
4077  return NULL;
4078  }
4079 
4080  for (i = 0; i < ARRAY_LEN(state_array); i++) {
4081  if (state_array[i].state == p->state) {
4082  return state_array[i].txt;
4083  }
4084  }
4085 
4086  snprintf(state, sizeof(state), "%d", p->state) ;
4087 
4088  return state;
4089 }
4090 
4091 
4092 static void reload_config(void)
4093 {
4094  int i, cfg_debug;
4095 
4096  if (!g_config_initialized) {
4097  ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
4098  return ;
4099  }
4100 
4101  free_robin_list();
4102  misdn_cfg_reload();
4104  misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
4105  misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
4106 
4107  for (i = 0; i <= max_ports; i++) {
4108  misdn_debug[i] = cfg_debug;
4109  misdn_debug_only[i] = 0;
4110  }
4111 }
4112 
4113 static char *handle_cli_misdn_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4114 {
4115  switch (cmd) {
4116  case CLI_INIT:
4117  e->command = "misdn reload";
4118  e->usage =
4119  "Usage: misdn reload\n"
4120  " Reload internal mISDN config, read from the config\n"
4121  " file.\n";
4122  return NULL;
4123  case CLI_GENERATE:
4124  return NULL;
4125  }
4126 
4127  if (a->argc != 2) {
4128  return CLI_SHOWUSAGE;
4129  }
4130 
4131  ast_cli(a->fd, "Reloading mISDN configuration\n");
4132  reload_config();
4133  return CLI_SUCCESS;
4134 }
4135 
4136 static void print_bc_info(int fd, struct chan_list *help, struct misdn_bchannel *bc)
4137 {
4138  struct ast_channel *ast = help->ast;
4139 
4140  ast_cli(fd,
4141  "* Pid:%d Port:%d Ch:%d Mode:%s Orig:%s dialed:%s\n"
4142  " --> caller:\"%s\" <%s>\n"
4143  " --> redirecting-from:\"%s\" <%s>\n"
4144  " --> redirecting-to:\"%s\" <%s>\n"
4145  " --> context:%s state:%s\n",
4146  bc->pid,
4147  bc->port,
4148  bc->channel,
4149  bc->nt ? "NT" : "TE",
4150  help->originator == ORG_AST ? "*" : "I",
4151  ast ? ast->exten : "",
4152  (ast && ast->caller.id.name.valid && ast->caller.id.name.str)
4153  ? ast->caller.id.name.str : "",
4154  (ast && ast->caller.id.number.valid && ast->caller.id.number.str)
4155  ? ast->caller.id.number.str : "",
4156  bc->redirecting.from.name,
4157  bc->redirecting.from.number,
4158  bc->redirecting.to.name,
4159  bc->redirecting.to.number,
4160  ast ? ast->context : "",
4161  misdn_get_ch_state(help));
4162  if (misdn_debug[bc->port] > 0) {
4163  ast_cli(fd,
4164  " --> astname: %s\n"
4165  " --> ch_l3id: %x\n"
4166  " --> ch_addr: %x\n"
4167  " --> bc_addr: %x\n"
4168  " --> bc_l3id: %x\n"
4169  " --> display: %s\n"
4170  " --> activated: %d\n"
4171  " --> state: %s\n"
4172  " --> capability: %s\n"
4173 #ifdef MISDN_1_2
4174  " --> pipeline: %s\n"
4175 #else
4176  " --> echo_cancel: %d\n"
4177 #endif
4178  " --> notone : rx %d tx:%d\n"
4179  " --> bc_hold: %d\n",
4180  ast ? ast->name : "",
4181  help->l3id,
4182  help->addr,
4183  bc->addr,
4184  bc->l3_id,
4185  bc->display,
4186  bc->active,
4187  bc_state2str(bc->bc_state),
4188  bearer2str(bc->capability),
4189 #ifdef MISDN_1_2
4190  bc->pipeline,
4191 #else
4192  bc->ec_enable,
4193 #endif
4194  help->norxtone, help->notxtone,
4195  bc->holded);
4196  }
4197 }
4198 
4199 static char *handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4200 {
4201  struct chan_list *help;
4202 
4203  switch (cmd) {
4204  case CLI_INIT:
4205  e->command = "misdn show channels";
4206  e->usage =
4207  "Usage: misdn show channels\n"
4208  " Show the internal mISDN channel list\n";
4209  return NULL;
4210  case CLI_GENERATE:
4211  return NULL;
4212  }
4213 
4214  if (a->argc != 3) {
4215  return CLI_SHOWUSAGE;
4216  }
4217 
4218  ast_cli(a->fd, "Channel List: %p\n", cl_te);
4219 
4220  /*
4221  * Walking the list and dumping the channel information could
4222  * take awhile. With the list locked for the duration, the
4223  * channel driver cannot process signaling messages. However,
4224  * since this is a CLI command it should not be run very often.
4225  */
4226  ast_mutex_lock(&cl_te_lock);
4227  for (help = cl_te; help; help = help->next) {
4228  struct misdn_bchannel *bc = help->bc;
4229  struct ast_channel *ast = help->ast;
4230  if (!ast) {
4231  if (!bc) {
4232  ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
4233  continue;
4234  }
4235  ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
4236  }
4237 
4238  if (misdn_debug[0] > 2) {
4239  ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
4240  }
4241  if (bc) {
4242  print_bc_info(a->fd, help, bc);
4243  } else {
4244  if (help->hold.state != MISDN_HOLD_IDLE) {
4245  ast_cli(a->fd, "ITS A HELD CALL BC:\n");
4246  ast_cli(a->fd, " --> l3_id: %x\n"
4247  " --> dialed:%s\n"
4248  " --> caller:\"%s\" <%s>\n"
4249  " --> hold_port: %d\n"
4250  " --> hold_channel: %d\n",
4251  help->l3id,
4252  ast->exten,
4253  S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
4254  S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
4255  help->hold.port,
4256  help->hold.channel
4257  );
4258  } else {
4259  ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n",
4260  ast->exten,
4261  S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""));
4262  }
4263  }
4264  }
4265  ast_mutex_unlock(&cl_te_lock);
4266 
4268 
4269  return CLI_SUCCESS;
4270 }
4271 
4272 static char *handle_cli_misdn_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4273 {
4274  struct chan_list *help;
4275 
4276  switch (cmd) {
4277  case CLI_INIT:
4278  e->command = "misdn show channel";
4279  e->usage =
4280  "Usage: misdn show channel <channel>\n"
4281  " Show an internal mISDN channel\n.";
4282  return NULL;
4283  case CLI_GENERATE:
4284  return complete_ch(a);
4285  }
4286 
4287  if (a->argc != 4) {
4288  return CLI_SHOWUSAGE;
4289  }
4290 
4291  ast_mutex_lock(&cl_te_lock);
4292  for (help = cl_te; help; help = help->next) {
4293  struct misdn_bchannel *bc = help->bc;
4294  struct ast_channel *ast = help->ast;
4295 
4296  if (bc && ast) {
4297  if (!strcasecmp(ast->name, a->argv[3])) {
4298  print_bc_info(a->fd, help, bc);
4299  break;
4300  }
4301  }
4302  }
4303  ast_mutex_unlock(&cl_te_lock);
4304 
4305  return CLI_SUCCESS;
4306 }
4307 
4308 static char *handle_cli_misdn_set_tics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4309 {
4310  switch (cmd) {
4311  case CLI_INIT:
4312  e->command = "misdn set tics";
4313  e->usage =
4314  "Usage: misdn set tics <value>\n";
4315  return NULL;
4316  case CLI_GENERATE:
4317  return NULL;
4318  }
4319 
4320  if (a->argc != 4) {
4321  return CLI_SHOWUSAGE;
4322  }
4323 
4324  /* XXX Wow, this does... a whole lot of nothing... XXX */
4325  MAXTICS = atoi(a->argv[3]);
4326 
4327  return CLI_SUCCESS;
4328 }
4329 
4330 static char *handle_cli_misdn_show_stacks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4331 {
4332  int port;
4333 
4334  switch (cmd) {
4335  case CLI_INIT:
4336  e->command = "misdn show stacks";
4337  e->usage =
4338  "Usage: misdn show stacks\n"
4339  " Show internal mISDN stack_list.\n";
4340  return NULL;
4341  case CLI_GENERATE:
4342  return NULL;
4343  }
4344 
4345  if (a->argc != 3) {
4346  return CLI_SHOWUSAGE;
4347  }
4348 
4349  ast_cli(a->fd, "BEGIN STACK_LIST:\n");
4350  for (port = misdn_cfg_get_next_port(0); port > 0;
4351  port = misdn_cfg_get_next_port(port)) {
4352  char buf[128];
4353 
4354  get_show_stack_details(port, buf);
4355  ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
4356  }
4357 
4358  return CLI_SUCCESS;
4359 }
4360 
4361 static char *handle_cli_misdn_show_ports_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4362 {
4363  int port;
4364 
4365  switch (cmd) {
4366  case CLI_INIT:
4367  e->command = "misdn show ports stats";
4368  e->usage =
4369  "Usage: misdn show ports stats\n"
4370  " Show mISDNs channel's call statistics per port.\n";
4371  return NULL;
4372  case CLI_GENERATE:
4373  return NULL;
4374  }
4375 
4376  if (a->argc != 4) {
4377  return CLI_SHOWUSAGE;
4378  }
4379 
4380  ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
4381  for (port = misdn_cfg_get_next_port(0); port > 0;
4382  port = misdn_cfg_get_next_port(port)) {
4383  ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
4384  }
4385  ast_cli(a->fd, "\n");
4386 
4387  return CLI_SUCCESS;
4388 }
4389 
4390 static char *handle_cli_misdn_show_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4391 {
4392  int port;
4393  char buf[128];
4394 
4395  switch (cmd) {
4396  case CLI_INIT:
4397  e->command = "misdn show port";
4398  e->usage =
4399  "Usage: misdn show port <port>\n"
4400  " Show detailed information for given port.\n";
4401  return NULL;
4402  case CLI_GENERATE:
4403  return NULL;
4404  }
4405 
4406  if (a->argc != 4) {
4407  return CLI_SHOWUSAGE;
4408  }
4409 
4410  port = atoi(a->argv[3]);
4411 
4412  ast_cli(a->fd, "BEGIN STACK_LIST:\n");
4413  get_show_stack_details(port, buf);
4414  ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
4415 
4416  return CLI_SUCCESS;
4417 }
4418 
4419 #if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
4420 static const struct FacParm Fac_Msgs[] = {
4421 /* *INDENT-OFF* */
4422  [0].Function = Fac_ERROR,
4423  [0].u.ERROR.invokeId = 8,
4424  [0].u.ERROR.errorValue = FacError_CCBS_AlreadyAccepted,
4425 
4426  [1].Function = Fac_RESULT,
4427  [1].u.RESULT.InvokeID = 9,
4428 
4429  [2].Function = Fac_REJECT,
4430  [2].u.REJECT.Code = FacReject_Gen_BadlyStructuredComponent,
4431 
4432  [3].Function = Fac_REJECT,
4433  [3].u.REJECT.InvokeIDPresent = 1,
4434  [3].u.REJECT.InvokeID = 10,
4435  [3].u.REJECT.Code = FacReject_Inv_InitiatorReleasing,
4436 
4437  [4].Function = Fac_REJECT,
4438  [4].u.REJECT.InvokeIDPresent = 1,
4439  [4].u.REJECT.InvokeID = 11,
4440  [4].u.REJECT.Code = FacReject_Res_MistypedResult,
4441 
4442  [5].Function = Fac_REJECT,
4443  [5].u.REJECT.InvokeIDPresent = 1,
4444  [5].u.REJECT.InvokeID = 12,
4445  [5].u.REJECT.Code = FacReject_Err_ErrorResponseUnexpected,
4446 
4447  [6].Function = Fac_StatusRequest,
4448  [6].u.StatusRequest.InvokeID = 13,
4449  [6].u.StatusRequest.ComponentType = FacComponent_Invoke,
4450  [6].u.StatusRequest.Component.Invoke.Q931ie.Bc.Length = 2,
4451  [6].u.StatusRequest.Component.Invoke.Q931ie.Bc.Contents = "AB",
4452  [6].u.StatusRequest.Component.Invoke.Q931ie.Llc.Length = 3,
4453  [6].u.StatusRequest.Component.Invoke.Q931ie.Llc.Contents = "CDE",
4454  [6].u.StatusRequest.Component.Invoke.Q931ie.Hlc.Length = 4,
4455  [6].u.StatusRequest.Component.Invoke.Q931ie.Hlc.Contents = "FGHI",
4456  [6].u.StatusRequest.Component.Invoke.CompatibilityMode = 1,
4457 
4458  [7].Function = Fac_StatusRequest,
4459  [7].u.StatusRequest.InvokeID = 14,
4460  [7].u.StatusRequest.ComponentType = FacComponent_Result,
4461  [7].u.StatusRequest.Component.Result.Status = 2,
4462 
4463  [8].Function = Fac_CallInfoRetain,
4464  [8].u.CallInfoRetain.InvokeID = 15,
4465  [8].u.CallInfoRetain.CallLinkageID = 115,
4466 
4467  [9].Function = Fac_EraseCallLinkageID,
4468  [9].u.EraseCallLinkageID.InvokeID = 16,
4469  [9].u.EraseCallLinkageID.CallLinkageID = 105,
4470 
4471  [10].Function = Fac_CCBSDeactivate,
4472  [10].u.CCBSDeactivate.InvokeID = 17,
4473  [10].u.CCBSDeactivate.ComponentType = FacComponent_Invoke,
4474  [10].u.CCBSDeactivate.Component.Invoke.CCBSReference = 2,
4475 
4476  [11].Function = Fac_CCBSDeactivate,
4477  [11].u.CCBSDeactivate.InvokeID = 18,
4478  [11].u.CCBSDeactivate.ComponentType = FacComponent_Result,
4479 
4480  [12].Function = Fac_CCBSErase,
4481  [12].u.CCBSErase.InvokeID = 19,
4482  [12].u.CCBSErase.Q931ie.Bc.Length = 2,
4483  [12].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4484  [12].u.CCBSErase.AddressOfB.Party.Type = 0,
4485  [12].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 5,
4486  [12].u.CCBSErase.AddressOfB.Party.Number = "33403",
4487  [12].u.CCBSErase.AddressOfB.Subaddress.Type = 0,
4488  [12].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
4489  [12].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.Information = "3748",
4490  [12].u.CCBSErase.RecallMode = 1,
4491  [12].u.CCBSErase.CCBSReference = 102,
4492  [12].u.CCBSErase.Reason = 3,
4493 
4494  [13].Function = Fac_CCBSErase,
4495  [13].u.CCBSErase.InvokeID = 20,
4496  [13].u.CCBSErase.Q931ie.Bc.Length = 2,
4497  [13].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4498  [13].u.CCBSErase.AddressOfB.Party.Type = 1,
4499  [13].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 11,
4500  [13].u.CCBSErase.AddressOfB.Party.TypeOfNumber = 1,
4501  [13].u.CCBSErase.AddressOfB.Party.Number = "18003020102",
4502  [13].u.CCBSErase.AddressOfB.Subaddress.Type = 0,
4503  [13].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
4504  [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.OddCountPresent = 1,
4505  [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.OddCount = 1,
4506  [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.Information = "3748",
4507  [13].u.CCBSErase.RecallMode = 1,
4508  [13].u.CCBSErase.CCBSReference = 102,
4509  [13].u.CCBSErase.Reason = 3,
4510 
4511  [14].Function = Fac_CCBSErase,
4512  [14].u.CCBSErase.InvokeID = 21,
4513  [14].u.CCBSErase.Q931ie.Bc.Length = 2,
4514  [14].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4515  [14].u.CCBSErase.AddressOfB.Party.Type = 2,
4516  [14].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
4517  [14].u.CCBSErase.AddressOfB.Party.Number = "1803",
4518  [14].u.CCBSErase.AddressOfB.Subaddress.Type = 1,
4519  [14].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
4520  [14].u.CCBSErase.AddressOfB.Subaddress.u.Nsap = "6492",
4521  [14].u.CCBSErase.RecallMode = 1,
4522  [14].u.CCBSErase.CCBSReference = 102,
4523  [14].u.CCBSErase.Reason = 3,
4524 
4525  [15].Function = Fac_CCBSErase,
4526  [15].u.CCBSErase.InvokeID = 22,
4527  [15].u.CCBSErase.Q931ie.Bc.Length = 2,
4528  [15].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4529  [15].u.CCBSErase.AddressOfB.Party.Type = 3,
4530  [15].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
4531  [15].u.CCBSErase.AddressOfB.Party.Number = "1803",
4532  [15].u.CCBSErase.RecallMode = 1,
4533  [15].u.CCBSErase.CCBSReference = 102,
4534  [15].u.CCBSErase.Reason = 3,
4535 
4536  [16].Function = Fac_CCBSErase,
4537  [16].u.CCBSErase.InvokeID = 23,
4538  [16].u.CCBSErase.Q931ie.Bc.Length = 2,
4539  [16].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4540  [16].u.CCBSErase.AddressOfB.Party.Type = 4,
4541  [16].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
4542  [16].u.CCBSErase.AddressOfB.Party.Number = "1803",
4543  [16].u.CCBSErase.RecallMode = 1,
4544  [16].u.CCBSErase.CCBSReference = 102,
4545  [16].u.CCBSErase.Reason = 3,
4546 
4547  [17].Function = Fac_CCBSErase,
4548  [17].u.CCBSErase.InvokeID = 24,
4549  [17].u.CCBSErase.Q931ie.Bc.Length = 2,
4550  [17].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4551  [17].u.CCBSErase.AddressOfB.Party.Type = 5,
4552  [17].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 11,
4553  [17].u.CCBSErase.AddressOfB.Party.TypeOfNumber = 4,
4554  [17].u.CCBSErase.AddressOfB.Party.Number = "18003020102",
4555  [17].u.CCBSErase.RecallMode = 1,
4556  [17].u.CCBSErase.CCBSReference = 102,
4557  [17].u.CCBSErase.Reason = 3,
4558 
4559  [18].Function = Fac_CCBSErase,
4560  [18].u.CCBSErase.InvokeID = 25,
4561  [18].u.CCBSErase.Q931ie.Bc.Length = 2,
4562  [18].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4563  [18].u.CCBSErase.AddressOfB.Party.Type = 8,
4564  [18].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
4565  [18].u.CCBSErase.AddressOfB.Party.Number = "1803",
4566  [18].u.CCBSErase.RecallMode = 1,
4567  [18].u.CCBSErase.CCBSReference = 102,
4568  [18].u.CCBSErase.Reason = 3,
4569 
4570  [19].Function = Fac_CCBSRemoteUserFree,
4571  [19].u.CCBSRemoteUserFree.InvokeID = 26,
4572  [19].u.CCBSRemoteUserFree.Q931ie.Bc.Length = 2,
4573  [19].u.CCBSRemoteUserFree.Q931ie.Bc.Contents = "JK",
4574  [19].u.CCBSRemoteUserFree.AddressOfB.Party.Type = 8,
4575  [19].u.CCBSRemoteUserFree.AddressOfB.Party.LengthOfNumber = 4,
4576  [19].u.CCBSRemoteUserFree.AddressOfB.Party.Number = "1803",
4577  [19].u.CCBSRemoteUserFree.RecallMode = 1,
4578  [19].u.CCBSRemoteUserFree.CCBSReference = 102,
4579 
4580  [20].Function = Fac_CCBSCall,
4581  [20].u.CCBSCall.InvokeID = 27,
4582  [20].u.CCBSCall.CCBSReference = 115,
4583 
4584  [21].Function = Fac_CCBSStatusRequest,
4585  [21].u.CCBSStatusRequest.InvokeID = 28,
4586  [21].u.CCBSStatusRequest.ComponentType = FacComponent_Invoke,
4587  [21].u.CCBSStatusRequest.Component.Invoke.Q931ie.Bc.Length = 2,
4588  [21].u.CCBSStatusRequest.Component.Invoke.Q931ie.Bc.Contents = "JK",
4589  [21].u.CCBSStatusRequest.Component.Invoke.RecallMode = 1,
4590  [21].u.CCBSStatusRequest.Component.Invoke.CCBSReference = 102,
4591 
4592  [22].Function = Fac_CCBSStatusRequest,
4593  [22].u.CCBSStatusRequest.InvokeID = 29,
4594  [22].u.CCBSStatusRequest.ComponentType = FacComponent_Result,
4595  [22].u.CCBSStatusRequest.Component.Result.Free = 1,
4596 
4597  [23].Function = Fac_CCBSBFree,
4598  [23].u.CCBSBFree.InvokeID = 30,
4599  [23].u.CCBSBFree.Q931ie.Bc.Length = 2,
4600  [23].u.CCBSBFree.Q931ie.Bc.Contents = "JK",
4601  [23].u.CCBSBFree.AddressOfB.Party.Type = 8,
4602  [23].u.CCBSBFree.AddressOfB.Party.LengthOfNumber = 4,
4603  [23].u.CCBSBFree.AddressOfB.Party.Number = "1803",
4604  [23].u.CCBSBFree.RecallMode = 1,
4605  [23].u.CCBSBFree.CCBSReference = 14,
4606 
4607  [24].Function = Fac_CCBSStopAlerting,
4608  [24].u.CCBSStopAlerting.InvokeID = 31,
4609  [24].u.CCBSStopAlerting.CCBSReference = 37,
4610 
4611  [25].Function = Fac_CCBSRequest,
4612  [25].u.CCBSRequest.InvokeID = 32,
4613  [25].u.CCBSRequest.ComponentType = FacComponent_Invoke,
4614  [25].u.CCBSRequest.Component.Invoke.CallLinkageID = 57,
4615 
4616  [26].Function = Fac_CCBSRequest,
4617  [26].u.CCBSRequest.InvokeID = 33,
4618  [26].u.CCBSRequest.ComponentType = FacComponent_Result,
4619  [26].u.CCBSRequest.Component.Result.RecallMode = 1,
4620  [26].u.CCBSRequest.Component.Result.CCBSReference = 102,
4621 
4622  [27].Function = Fac_CCBSInterrogate,
4623  [27].u.CCBSInterrogate.InvokeID = 34,
4624  [27].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
4625  [27].u.CCBSInterrogate.Component.Invoke.AParty.Type = 8,
4626  [27].u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber = 4,
4627  [27].u.CCBSInterrogate.Component.Invoke.AParty.Number = "1803",
4628  [27].u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent = 1,
4629  [27].u.CCBSInterrogate.Component.Invoke.CCBSReference = 76,
4630 
4631  [28].Function = Fac_CCBSInterrogate,
4632  [28].u.CCBSInterrogate.InvokeID = 35,
4633  [28].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
4634  [28].u.CCBSInterrogate.Component.Invoke.AParty.Type = 8,
4635  [28].u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber = 4,
4636  [28].u.CCBSInterrogate.Component.Invoke.AParty.Number = "1803",
4637 
4638  [29].Function = Fac_CCBSInterrogate,
4639  [29].u.CCBSInterrogate.InvokeID = 36,
4640  [29].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
4641  [29].u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent = 1,
4642  [29].u.CCBSInterrogate.Component.Invoke.CCBSReference = 76,
4643 
4644  [30].Function = Fac_CCBSInterrogate,
4645  [30].u.CCBSInterrogate.InvokeID = 37,
4646  [30].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
4647 
4648  [31].Function = Fac_CCBSInterrogate,
4649  [31].u.CCBSInterrogate.InvokeID = 38,
4650  [31].u.CCBSInterrogate.ComponentType = FacComponent_Result,
4651  [31].u.CCBSInterrogate.Component.Result.RecallMode = 1,
4652 
4653  [32].Function = Fac_CCBSInterrogate,
4654  [32].u.CCBSInterrogate.InvokeID = 39,
4655  [32].u.CCBSInterrogate.ComponentType = FacComponent_Result,
4656  [32].u.CCBSInterrogate.Component.Result.RecallMode = 1,
4657  [32].u.CCBSInterrogate.Component.Result.NumRecords = 1,
4658  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].CCBSReference = 12,
4659  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Length = 2,
4660  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Contents = "JK",
4661  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Type = 8,
4662  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.LengthOfNumber = 4,
4663  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Number = "1803",
4664  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.Type = 1,
4665  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.Length = 4,
4666  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.u.Nsap = "6492",
4667 
4668  [33].Function = Fac_CCBSInterrogate,
4669  [33].u.CCBSInterrogate.InvokeID = 40,
4670  [33].u.CCBSInterrogate.ComponentType = FacComponent_Result,
4671  [33].u.CCBSInterrogate.Component.Result.RecallMode = 1,
4672  [33].u.CCBSInterrogate.Component.Result.NumRecords = 2,
4673  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].CCBSReference = 12,
4674  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Length = 2,
4675  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Contents = "JK",
4676  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Type = 8,
4677  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.LengthOfNumber = 4,
4678  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Number = "1803",
4679  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].CCBSReference = 102,
4680  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].Q931ie.Bc.Length = 2,
4681  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].Q931ie.Bc.Contents = "LM",
4682  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.Type = 8,
4683  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.LengthOfNumber = 4,
4684  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.Number = "6229",
4685  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.Type = 1,
4686  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.Length = 4,
4687  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.u.Nsap = "8592",
4688  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.Type = 1,
4689  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.Length = 4,
4690  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.u.Nsap = "6492",
4691 
4692  [34].Function = Fac_CCNRRequest,
4693  [34].u.CCNRRequest.InvokeID = 512,
4694  [34].u.CCNRRequest.ComponentType = FacComponent_Invoke,
4695  [34].u.CCNRRequest.Component.Invoke.CallLinkageID = 57,
4696 
4697  [35].Function = Fac_CCNRRequest,
4698  [35].u.CCNRRequest.InvokeID = 150,
4699  [35].u.CCNRRequest.ComponentType = FacComponent_Result,
4700  [35].u.CCNRRequest.Component.Result.RecallMode = 1,
4701  [35].u.CCNRRequest.Component.Result.CCBSReference = 102,
4702 
4703  [36].Function = Fac_CCNRInterrogate,
4704  [36].u.CCNRInterrogate.InvokeID = -129,
4705  [36].u.CCNRInterrogate.ComponentType = FacComponent_Invoke,
4706 
4707  [37].Function = Fac_CCNRInterrogate,
4708  [37].u.CCNRInterrogate.InvokeID = -3,
4709  [37].u.CCNRInterrogate.ComponentType = FacComponent_Result,
4710  [37].u.CCNRInterrogate.Component.Result.RecallMode = 1,
4711 
4712  [38].Function = Fac_CCBS_T_Call,
4713  [38].u.EctExecute.InvokeID = 41,
4714 
4715  [39].Function = Fac_CCBS_T_Suspend,
4716  [39].u.EctExecute.InvokeID = 42,
4717 
4718  [40].Function = Fac_CCBS_T_Resume,
4719  [40].u.EctExecute.InvokeID = 43,
4720 
4721  [41].Function = Fac_CCBS_T_RemoteUserFree,
4722  [41].u.EctExecute.InvokeID = 44,
4723 
4724  [42].Function = Fac_CCBS_T_Available,
4725  [42].u.EctExecute.InvokeID = 45,
4726 
4727  [43].Function = Fac_CCBS_T_Request,
4728  [43].u.CCBS_T_Request.InvokeID = 46,
4729  [43].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4730  [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4731  [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4732  [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4733  [43].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4734  [43].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4735  [43].u.CCBS_T_Request.Component.Invoke.RetentionSupported = 1,
4736  [43].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
4737  [43].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
4738  [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
4739  [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
4740  [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
4741 
4742  [44].Function = Fac_CCBS_T_Request,
4743  [44].u.CCBS_T_Request.InvokeID = 47,
4744  [44].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4745  [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4746  [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4747  [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4748  [44].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4749  [44].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4750  [44].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
4751  [44].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
4752  [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
4753  [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
4754  [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
4755 
4756  [45].Function = Fac_CCBS_T_Request,
4757  [45].u.CCBS_T_Request.InvokeID = 48,
4758  [45].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4759  [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4760  [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4761  [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4762  [45].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4763  [45].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4764  [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
4765  [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
4766  [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
4767 
4768  [46].Function = Fac_CCBS_T_Request,
4769  [46].u.CCBS_T_Request.InvokeID = 49,
4770  [46].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4771  [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4772  [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4773  [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4774  [46].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4775  [46].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4776  [46].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
4777  [46].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
4778 
4779  [47].Function = Fac_CCBS_T_Request,
4780  [47].u.CCBS_T_Request.InvokeID = 50,
4781  [47].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4782  [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4783  [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4784  [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4785  [47].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4786  [47].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4787 
4788  [48].Function = Fac_CCBS_T_Request,
4789  [48].u.CCBS_T_Request.InvokeID = 51,
4790  [48].u.CCBS_T_Request.ComponentType = FacComponent_Result,
4791  [48].u.CCBS_T_Request.Component.Result.RetentionSupported = 1,
4792 
4793  [49].Function = Fac_CCNR_T_Request,
4794  [49].u.CCNR_T_Request.InvokeID = 52,
4795  [49].u.CCNR_T_Request.ComponentType = FacComponent_Invoke,
4796  [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.Type = 8,
4797  [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4798  [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4799  [49].u.CCNR_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4800  [49].u.CCNR_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4801 
4802  [50].Function = Fac_CCNR_T_Request,
4803  [50].u.CCNR_T_Request.InvokeID = 53,
4804  [50].u.CCNR_T_Request.ComponentType = FacComponent_Result,
4805  [50].u.CCNR_T_Request.Component.Result.RetentionSupported = 1,
4806 
4807  [51].Function = Fac_EctExecute,
4808  [51].u.EctExecute.InvokeID = 54,
4809 
4810  [52].Function = Fac_ExplicitEctExecute,
4811  [52].u.ExplicitEctExecute.InvokeID = 55,
4812  [52].u.ExplicitEctExecute.LinkID = 23,
4813 
4814  [53].Function = Fac_RequestSubaddress,
4815  [53].u.RequestSubaddress.InvokeID = 56,
4816 
4817  [54].Function = Fac_SubaddressTransfer,
4818  [54].u.SubaddressTransfer.InvokeID = 57,
4819  [54].u.SubaddressTransfer.Subaddress.Type = 1,
4820  [54].u.SubaddressTransfer.Subaddress.Length = 4,
4821  [54].u.SubaddressTransfer.Subaddress.u.Nsap = "6492",
4822 
4823  [55].Function = Fac_EctLinkIdRequest,
4824  [55].u.EctLinkIdRequest.InvokeID = 58,
4825  [55].u.EctLinkIdRequest.ComponentType = FacComponent_Invoke,
4826 
4827  [56].Function = Fac_EctLinkIdRequest,
4828  [56].u.EctLinkIdRequest.InvokeID = 59,
4829  [56].u.EctLinkIdRequest.ComponentType = FacComponent_Result,
4830  [56].u.EctLinkIdRequest.Component.Result.LinkID = 76,
4831 
4832  [57].Function = Fac_EctInform,
4833  [57].u.EctInform.InvokeID = 60,
4834  [57].u.EctInform.Status = 1,
4835  [57].u.EctInform.RedirectionPresent = 1,
4836  [57].u.EctInform.Redirection.Type = 0,
4837  [57].u.EctInform.Redirection.Unscreened.Type = 8,
4838  [57].u.EctInform.Redirection.Unscreened.LengthOfNumber = 4,
4839  [57].u.EctInform.Redirection.Unscreened.Number = "6229",
4840 
4841  [58].Function = Fac_EctInform,
4842  [58].u.EctInform.InvokeID = 61,
4843  [58].u.EctInform.Status = 1,
4844  [58].u.EctInform.RedirectionPresent = 1,
4845  [58].u.EctInform.Redirection.Type = 1,
4846 
4847  [59].Function = Fac_EctInform,
4848  [59].u.EctInform.InvokeID = 62,
4849  [59].u.EctInform.Status = 1,
4850  [59].u.EctInform.RedirectionPresent = 1,
4851  [59].u.EctInform.Redirection.Type = 2,
4852 
4853  [60].Function = Fac_EctInform,
4854  [60].u.EctInform.InvokeID = 63,
4855  [60].u.EctInform.Status = 1,
4856  [60].u.EctInform.RedirectionPresent = 1,
4857  [60].u.EctInform.Redirection.Type = 3,
4858  [60].u.EctInform.Redirection.Unscreened.Type = 8,
4859  [60].u.EctInform.Redirection.Unscreened.LengthOfNumber = 4,
4860  [60].u.EctInform.Redirection.Unscreened.Number = "3340",
4861 
4862  [61].Function = Fac_EctInform,
4863  [61].u.EctInform.InvokeID = 64,
4864  [61].u.EctInform.Status = 1,
4865  [61].u.EctInform.RedirectionPresent = 0,
4866 
4867  [62].Function = Fac_EctLoopTest,
4868  [62].u.EctLoopTest.InvokeID = 65,
4869  [62].u.EctLoopTest.ComponentType = FacComponent_Invoke,
4870  [62].u.EctLoopTest.Component.Invoke.CallTransferID = 7,
4871 
4872  [63].Function = Fac_EctLoopTest,
4873  [63].u.EctLoopTest.InvokeID = 66,
4874  [63].u.EctLoopTest.ComponentType = FacComponent_Result,
4875  [63].u.EctLoopTest.Component.Result.LoopResult = 2,
4876 
4877  [64].Function = Fac_ActivationDiversion,
4878  [64].u.ActivationDiversion.InvokeID = 67,
4879  [64].u.ActivationDiversion.ComponentType = FacComponent_Invoke,
4880  [64].u.ActivationDiversion.Component.Invoke.Procedure = 2,
4881  [64].u.ActivationDiversion.Component.Invoke.BasicService = 3,
4882  [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 4,
4883  [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber = 4,
4884  [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number = "1803",
4885  [64].u.ActivationDiversion.Component.Invoke.ServedUser.Type = 4,
4886  [64].u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber = 4,
4887  [64].u.ActivationDiversion.Component.Invoke.ServedUser.Number = "5398",
4888 
4889  [65].Function = Fac_ActivationDiversion,
4890  [65].u.ActivationDiversion.InvokeID = 68,
4891  [65].u.ActivationDiversion.ComponentType = FacComponent_Invoke,
4892  [65].u.ActivationDiversion.Component.Invoke.Procedure = 1,
4893  [65].u.ActivationDiversion.Component.Invoke.BasicService = 5,
4894  [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 4,
4895  [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber = 4,
4896  [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number = "1803",
4897 
4898  [66].Function = Fac_ActivationDiversion,
4899  [66].u.ActivationDiversion.InvokeID = 69,
4900  [66].u.ActivationDiversion.ComponentType = FacComponent_Result,
4901 
4902  [67].Function = Fac_DeactivationDiversion,
4903  [67].u.DeactivationDiversion.InvokeID = 70,
4904  [67].u.DeactivationDiversion.ComponentType = FacComponent_Invoke,
4905  [67].u.DeactivationDiversion.Component.Invoke.Procedure = 1,
4906  [67].u.DeactivationDiversion.Component.Invoke.BasicService = 5,
4907 
4908  [68].Function = Fac_DeactivationDiversion,
4909  [68].u.DeactivationDiversion.InvokeID = 71,
4910  [68].u.DeactivationDiversion.ComponentType = FacComponent_Result,
4911 
4912  [69].Function = Fac_ActivationStatusNotificationDiv,
4913  [69].u.ActivationStatusNotificationDiv.InvokeID = 72,
4914  [69].u.ActivationStatusNotificationDiv.Procedure = 1,
4915  [69].u.ActivationStatusNotificationDiv.BasicService = 5,
4916  [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.Type = 4,
4917  [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.LengthOfNumber = 4,
4918  [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.Number = "1803",
4919 
4920  [70].Function = Fac_DeactivationStatusNotificationDiv,
4921  [70].u.DeactivationStatusNotificationDiv.InvokeID = 73,
4922  [70].u.DeactivationStatusNotificationDiv.Procedure = 1,
4923  [70].u.DeactivationStatusNotificationDiv.BasicService = 5,
4924 
4925  [71].Function = Fac_InterrogationDiversion,
4926  [71].u.InterrogationDiversion.InvokeID = 74,
4927  [71].u.InterrogationDiversion.ComponentType = FacComponent_Invoke,
4928  [71].u.InterrogationDiversion.Component.Invoke.Procedure = 1,
4929  [71].u.InterrogationDiversion.Component.Invoke.BasicService = 5,
4930 
4931  [72].Function = Fac_InterrogationDiversion,
4932  [72].u.InterrogationDiversion.InvokeID = 75,
4933  [72].u.InterrogationDiversion.ComponentType = FacComponent_Invoke,
4934  [72].u.InterrogationDiversion.Component.Invoke.Procedure = 1,
4935 
4936  [73].Function = Fac_InterrogationDiversion,
4937  [73].u.InterrogationDiversion.InvokeID = 76,
4938  [73].u.InterrogationDiversion.ComponentType = FacComponent_Result,
4939  [73].u.InterrogationDiversion.Component.Result.NumRecords = 2,
4940  [73].u.InterrogationDiversion.Component.Result.List[0].Procedure = 2,
4941  [73].u.InterrogationDiversion.Component.Result.List[0].BasicService = 5,
4942  [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.Type = 4,
4943  [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.LengthOfNumber = 4,
4944  [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.Number = "1803",
4945  [73].u.InterrogationDiversion.Component.Result.List[1].Procedure = 1,
4946  [73].u.InterrogationDiversion.Component.Result.List[1].BasicService = 3,
4947  [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.Type = 4,
4948  [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.LengthOfNumber = 4,
4949  [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.Number = "1903",
4950  [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.Type = 4,
4951  [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.LengthOfNumber = 4,
4952  [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.Number = "5398",
4953 
4954  [74].Function = Fac_DiversionInformation,
4955  [74].u.DiversionInformation.InvokeID = 77,
4956  [74].u.DiversionInformation.DiversionReason = 3,
4957  [74].u.DiversionInformation.BasicService = 5,
4958  [74].u.DiversionInformation.ServedUserSubaddress.Type = 1,
4959  [74].u.DiversionInformation.ServedUserSubaddress.Length = 4,
4960  [74].u.DiversionInformation.ServedUserSubaddress.u.Nsap = "6492",
4961  [74].u.DiversionInformation.CallingAddressPresent = 1,
4962  [74].u.DiversionInformation.CallingAddress.Type = 0,
4963  [74].u.DiversionInformation.CallingAddress.Address.ScreeningIndicator = 3,
4964  [74].u.DiversionInformation.CallingAddress.Address.Party.Type = 4,
4965  [74].u.DiversionInformation.CallingAddress.Address.Party.LengthOfNumber = 4,
4966  [74].u.DiversionInformation.CallingAddress.Address.Party.Number = "1803",
4967  [74].u.DiversionInformation.OriginalCalledPresent = 1,
4968  [74].u.DiversionInformation.OriginalCalled.Type = 1,
4969  [74].u.DiversionInformation.LastDivertingPresent = 1,
4970  [74].u.DiversionInformation.LastDiverting.Type = 2,
4971  [74].u.DiversionInformation.LastDivertingReasonPresent = 1,
4972  [74].u.DiversionInformation.LastDivertingReason = 3,
4973  [74].u.DiversionInformation.UserInfo.Length = 5,
4974  [74].u.DiversionInformation.UserInfo.Contents = "79828",
4975 
4976  [75].Function = Fac_DiversionInformation,
4977  [75].u.DiversionInformation.InvokeID = 78,
4978  [75].u.DiversionInformation.DiversionReason = 3,
4979  [75].u.DiversionInformation.BasicService = 5,
4980  [75].u.DiversionInformation.CallingAddressPresent = 1,
4981  [75].u.DiversionInformation.CallingAddress.Type = 1,
4982  [75].u.DiversionInformation.OriginalCalledPresent = 1,
4983  [75].u.DiversionInformation.OriginalCalled.Type = 2,
4984  [75].u.DiversionInformation.LastDivertingPresent = 1,
4985  [75].u.DiversionInformation.LastDiverting.Type = 1,
4986 
4987  [76].Function = Fac_DiversionInformation,
4988  [76].u.DiversionInformation.InvokeID = 79,
4989  [76].u.DiversionInformation.DiversionReason = 2,
4990  [76].u.DiversionInformation.BasicService = 3,
4991  [76].u.DiversionInformation.CallingAddressPresent = 1,
4992  [76].u.DiversionInformation.CallingAddress.Type = 2,
4993 
4994  [77].Function = Fac_DiversionInformation,
4995  [77].u.DiversionInformation.InvokeID = 80,
4996  [77].u.DiversionInformation.DiversionReason = 3,
4997  [77].u.DiversionInformation.BasicService = 5,
4998  [77].u.DiversionInformation.CallingAddressPresent = 1,
4999  [77].u.DiversionInformation.CallingAddress.Type = 3,
5000  [77].u.DiversionInformation.CallingAddress.Address.ScreeningIndicator = 2,
5001  [77].u.DiversionInformation.CallingAddress.Address.Party.Type = 4,
5002  [77].u.DiversionInformation.CallingAddress.Address.Party.LengthOfNumber = 4,
5003  [77].u.DiversionInformation.CallingAddress.Address.Party.Number = "1803",
5004 
5005  [78].Function = Fac_DiversionInformation,
5006  [78].u.DiversionInformation.InvokeID = 81,
5007  [78].u.DiversionInformation.DiversionReason = 2,
5008  [78].u.DiversionInformation.BasicService = 4,
5009  [78].u.DiversionInformation.UserInfo.Length = 5,
5010  [78].u.DiversionInformation.UserInfo.Contents = "79828",
5011 
5012  [79].Function = Fac_DiversionInformation,
5013  [79].u.DiversionInformation.InvokeID = 82,
5014  [79].u.DiversionInformation.DiversionReason = 2,
5015  [79].u.DiversionInformation.BasicService = 4,
5016 
5017  [80].Function = Fac_CallDeflection,
5018  [80].u.CallDeflection.InvokeID = 83,
5019  [80].u.CallDeflection.ComponentType = FacComponent_Invoke,
5020  [80].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
5021  [80].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
5022  [80].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
5023  [80].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1,
5024  [80].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 1,
5025 
5026  [81].Function = Fac_CallDeflection,
5027  [81].u.CallDeflection.InvokeID = 84,
5028  [81].u.CallDeflection.ComponentType = FacComponent_Invoke,
5029  [81].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
5030  [81].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
5031  [81].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
5032  [81].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1,
5033  [81].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0,
5034 
5035  [82].Function = Fac_CallDeflection,
5036  [82].u.CallDeflection.InvokeID = 85,
5037  [82].u.CallDeflection.ComponentType = FacComponent_Invoke,
5038  [82].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
5039  [82].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
5040  [82].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
5041 
5042  [83].Function = Fac_CallDeflection,
5043  [83].u.CallDeflection.InvokeID = 86,
5044  [83].u.CallDeflection.ComponentType = FacComponent_Result,
5045 
5046  [84].Function = Fac_CallRerouteing,
5047  [84].u.CallRerouteing.InvokeID = 87,
5048  [84].u.CallRerouteing.ComponentType = FacComponent_Invoke,
5049  [84].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
5050  [84].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
5051  [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
5052  [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
5053  [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
5054  [84].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
5055  [84].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
5056  [84].u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 3,
5057  [84].u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Contents = "RTG",
5058  [84].u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 2,
5059  [84].u.CallRerouteing.Component.Invoke.Q931ie.Llc.Contents = "MY",
5060  [84].u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 5,
5061  [84].u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Contents = "YEHAW",
5062  [84].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1,
5063  [84].u.CallRerouteing.Component.Invoke.SubscriptionOption = 2,
5064  [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Type = 1,
5065  [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 4,
5066  [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.u.Nsap = "6492",
5067 
5068  [85].Function = Fac_CallRerouteing,
5069  [85].u.CallRerouteing.InvokeID = 88,
5070  [85].u.CallRerouteing.ComponentType = FacComponent_Invoke,
5071  [85].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
5072  [85].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
5073  [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
5074  [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
5075  [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
5076  [85].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
5077  [85].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
5078  [85].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1,
5079  [85].u.CallRerouteing.Component.Invoke.SubscriptionOption = 2,
5080 
5081  [86].Function = Fac_CallRerouteing,
5082  [86].u.CallRerouteing.InvokeID = 89,
5083  [86].u.CallRerouteing.ComponentType = FacComponent_Invoke,
5084  [86].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
5085  [86].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
5086  [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
5087  [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
5088  [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
5089  [86].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
5090  [86].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
5091  [86].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 2,
5092 
5093  [87].Function = Fac_CallRerouteing,
5094  [87].u.CallRerouteing.InvokeID = 90,
5095  [87].u.CallRerouteing.ComponentType = FacComponent_Result,
5096 
5097  [88].Function = Fac_InterrogateServedUserNumbers,
5098  [88].u.InterrogateServedUserNumbers.InvokeID = 91,
5099  [88].u.InterrogateServedUserNumbers.ComponentType = FacComponent_Invoke,
5100 
5101  [89].Function = Fac_InterrogateServedUserNumbers,
5102  [89].u.InterrogateServedUserNumbers.InvokeID = 92,
5103  [89].u.InterrogateServedUserNumbers.ComponentType = FacComponent_Result,
5104  [89].u.InterrogateServedUserNumbers.Component.Result.NumRecords = 2,
5105  [89].u.InterrogateServedUserNumbers.Component.Result.List[0].Type = 4,
5106  [89].u.InterrogateServedUserNumbers.Component.Result.List[0].LengthOfNumber = 4,
5107  [89].u.InterrogateServedUserNumbers.Component.Result.List[0].Number = "1803",
5108  [89].u.InterrogateServedUserNumbers.Component.Result.List[1].Type = 4,
5109  [89].u.InterrogateServedUserNumbers.Component.Result.List[1].LengthOfNumber = 4,
5110  [89].u.InterrogateServedUserNumbers.Component.Result.List[1].Number = "5786",
5111 
5112  [90].Function = Fac_DivertingLegInformation1,
5113  [90].u.DivertingLegInformation1.InvokeID = 93,
5114  [90].u.DivertingLegInformation1.DiversionReason = 4,
5115  [90].u.DivertingLegInformation1.SubscriptionOption = 1,
5116  [90].u.DivertingLegInformation1.DivertedToPresent = 1,
5117  [90].u.DivertingLegInformation1.DivertedTo.Type = 2,
5118 
5119  [91].Function = Fac_DivertingLegInformation1,
5120  [91].u.DivertingLegInformation1.InvokeID = 94,
5121  [91].u.DivertingLegInformation1.DiversionReason = 4,
5122  [91].u.DivertingLegInformation1.SubscriptionOption = 1,
5123 
5124  [92].Function = Fac_DivertingLegInformation2,
5125  [92].u.DivertingLegInformation2.InvokeID = 95,
5126  [92].u.DivertingLegInformation2.DiversionCounter = 3,
5127  [92].u.DivertingLegInformation2.DiversionReason = 2,
5128  [92].u.DivertingLegInformation2.DivertingPresent = 1,
5129  [92].u.DivertingLegInformation2.Diverting.Type = 2,
5130  [92].u.DivertingLegInformation2.OriginalCalledPresent = 1,
5131  [92].u.DivertingLegInformation2.OriginalCalled.Type = 1,
5132 
5133  [93].Function = Fac_DivertingLegInformation2,
5134  [93].u.DivertingLegInformation2.InvokeID = 96,
5135  [93].u.DivertingLegInformation2.DiversionCounter = 3,
5136  [93].u.DivertingLegInformation2.DiversionReason = 2,
5137  [93].u.DivertingLegInformation2.OriginalCalledPresent = 1,
5138  [93].u.DivertingLegInformation2.OriginalCalled.Type = 1,
5139 
5140  [94].Function = Fac_DivertingLegInformation2,
5141  [94].u.DivertingLegInformation2.InvokeID = 97,
5142  [94].u.DivertingLegInformation2.DiversionCounter = 1,
5143  [94].u.DivertingLegInformation2.DiversionReason = 2,
5144 
5145  [95].Function = Fac_DivertingLegInformation3,
5146  [95].u.DivertingLegInformation3.InvokeID = 98,
5147  [95].u.DivertingLegInformation3.PresentationAllowedIndicator = 1,
5148 /* *INDENT-ON* */
5149 };
5150 #endif /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
5151 
5152 static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5153 {
5154  const char *channame;
5155  const char *nr;
5156  struct chan_list *tmp;
5157  int port;
5158  const char *served_nr;
5159  struct misdn_bchannel dummy, *bc=&dummy;
5160  unsigned max_len;
5161 
5162  switch (cmd) {
5163  case CLI_INIT:
5164  e->command = "misdn send facility";
5165  e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
5166  "\t type is one of:\n"
5167  "\t - calldeflect\n"
5168 #if defined(AST_MISDN_ENHANCEMENTS)
5169  "\t - callrerouting\n"
5170 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
5171  "\t - CFActivate\n"
5172  "\t - CFDeactivate\n";
5173 
5174  return NULL;
5175  case CLI_GENERATE:
5176  return complete_ch(a);
5177  }
5178 
5179  if (a->argc < 5) {
5180  return CLI_SHOWUSAGE;
5181  }
5182 
5183  if (strstr(a->argv[3], "calldeflect")) {
5184  if (a->argc < 6) {
5185  ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
5186  return 0;
5187  }
5188  channame = a->argv[4];
5189  nr = a->argv[5];
5190 
5191  ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
5192  tmp = get_chan_by_ast_name(channame);
5193  if (!tmp) {
5194  ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
5195  return 0;
5196  }
5197  ao2_lock(tmp);
5198 
5199 #if defined(AST_MISDN_ENHANCEMENTS)
5200  max_len = sizeof(tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
5201  if (max_len < strlen(nr)) {
5202  ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
5203  nr, channame, max_len);
5204  ao2_unlock(tmp);
5205  chan_list_unref(tmp, "Number too long");
5206  return 0;
5207  }
5208  tmp->bc->fac_out.Function = Fac_CallDeflection;
5209  tmp->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
5210  tmp->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
5211  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
5212  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
5213  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
5214  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(nr);
5215  strcpy((char *) tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, nr);
5216  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
5217 
5218 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
5219 
5220  max_len = sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
5221  if (max_len < strlen(nr)) {
5222  ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
5223  nr, channame, max_len);
5224  ao2_unlock(tmp);
5225  chan_list_unref(tmp, "Number too long");
5226  return 0;
5227  }
5228  tmp->bc->fac_out.Function = Fac_CD;
5229  tmp->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
5230  //tmp->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
5231  strcpy((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr);
5232 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
5233 
5234  /* Send message */
5235  print_facility(&tmp->bc->fac_out, tmp->bc);
5236  ao2_unlock(tmp);
5238  chan_list_unref(tmp, "Send facility complete");
5239 #if defined(AST_MISDN_ENHANCEMENTS)
5240  } else if (strstr(a->argv[3], "callrerouteing") || strstr(a->argv[3], "callrerouting")) {
5241  if (a->argc < 6) {
5242  ast_verbose("callrerouting requires 1 arg: ToNumber\n\n");
5243  return 0;
5244  }
5245  channame = a->argv[4];
5246  nr = a->argv[5];
5247 
5248  ast_verbose("Sending Callrerouting (%s) to %s\n", nr, channame);
5249  tmp = get_chan_by_ast_name(channame);
5250  if (!tmp) {
5251  ast_verbose("Sending Call Rerouting with nr %s to %s failed: Channel does not exist.\n", nr, channame);
5252  return 0;
5253  }
5254  ao2_lock(tmp);
5255 
5256  max_len = sizeof(tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
5257  if (max_len < strlen(nr)) {
5258  ast_verbose("Sending Call Rerouting with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
5259  nr, channame, max_len);
5260  ao2_unlock(tmp);
5261  chan_list_unref(tmp, "Number too long");
5262  return 0;
5263  }
5264  tmp->bc->fac_out.Function = Fac_CallRerouteing;
5265  tmp->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
5266  tmp->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
5267 
5268  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
5269  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
5270 
5271  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
5272  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(nr);
5273  strcpy((char *) tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, nr);
5274  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
5275 
5276  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
5277 
5278  /* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
5279  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
5280  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
5281  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
5282  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
5283  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
5284  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
5285  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
5286 
5287  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
5288  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
5289 
5290  /* Send message */
5291  print_facility(&tmp->bc->fac_out, tmp->bc);
5292  ao2_unlock(tmp);
5294  chan_list_unref(tmp, "Send facility complete");
5295 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
5296  } else if (strstr(a->argv[3], "CFActivate")) {
5297  if (a->argc < 7) {
5298  ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
5299  return 0;
5300  }
5301  port = atoi(a->argv[4]);
5302  served_nr = a->argv[5];
5303  nr = a->argv[6];
5304 
5305  misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
5306 
5307  ast_verbose("Sending CFActivate Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
5308 
5309 #if defined(AST_MISDN_ENHANCEMENTS)
5310  bc->fac_out.Function = Fac_ActivationDiversion;
5311  bc->fac_out.u.ActivationDiversion.InvokeID = ++misdn_invoke_id;
5312  bc->fac_out.u.ActivationDiversion.ComponentType = FacComponent_Invoke;
5313  bc->fac_out.u.ActivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
5314  bc->fac_out.u.ActivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
5315  ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number,
5316  served_nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number));
5317  bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
5318  strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number);
5319  bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
5320  ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number,
5321  nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number));
5322  bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber =
5323  strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number);
5324  bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 0;/* unknown */
5325  bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Subaddress.Length = 0;
5326 
5327 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
5328 
5329  bc->fac_out.Function = Fac_CFActivate;
5330  bc->fac_out.u.CFActivate.BasicService = 0; /* All Services */
5331  bc->fac_out.u.CFActivate.Procedure = 0; /* Unconditional */
5332  ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
5333  ast_copy_string((char *) bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
5334 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
5335 
5336  /* Send message */
5337  print_facility(&bc->fac_out, bc);
5339  } else if (strstr(a->argv[3], "CFDeactivate")) {
5340  if (a->argc < 6) {
5341  ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
5342  return 0;
5343  }
5344  port = atoi(a->argv[4]);
5345  served_nr = a->argv[5];
5346 
5347  misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
5348  ast_verbose("Sending CFDeactivate Port:(%d) FromNr. (%s)\n", port, served_nr);
5349 
5350 #if defined(AST_MISDN_ENHANCEMENTS)
5351  bc->fac_out.Function = Fac_DeactivationDiversion;
5352  bc->fac_out.u.DeactivationDiversion.InvokeID = ++misdn_invoke_id;
5353  bc->fac_out.u.DeactivationDiversion.ComponentType = FacComponent_Invoke;
5354  bc->fac_out.u.DeactivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
5355  bc->fac_out.u.DeactivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
5356  ast_copy_string((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number,
5357  served_nr, sizeof(bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number));
5358  bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
5359  strlen((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number);
5360  bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
5361 
5362 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
5363 
5364  bc->fac_out.Function = Fac_CFDeactivate;
5365  bc->fac_out.u.CFDeactivate.BasicService = 0; /* All Services */
5366  bc->fac_out.u.CFDeactivate.Procedure = 0; /* Unconditional */
5367  ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
5368 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
5369 
5370  /* Send message */
5371  print_facility(&bc->fac_out, bc);
5373 #if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
5374  } else if (strstr(a->argv[3], "test")) {
5375  int msg_number;
5376 
5377  if (a->argc < 5) {
5378  ast_verbose("test (<port> [<msg#>]) | (<channel-name> <msg#>)\n\n");
5379  return 0;
5380  }
5381  port = atoi(a->argv[4]);
5382 
5383  channame = a->argv[4];
5384  tmp = get_chan_by_ast_name(channame);
5385  if (tmp) {
5386  /* We are going to send this FACILITY message out on an existing connection */
5387  msg_number = atoi(a->argv[5]);
5388  if (msg_number < ARRAY_LEN(Fac_Msgs)) {
5389  ao2_lock(tmp);
5390  tmp->bc->fac_out = Fac_Msgs[msg_number];
5391 
5392  /* Send message */
5393  print_facility(&tmp->bc->fac_out, tmp->bc);
5394  ao2_unlock(tmp);
5396  } else {
5397  ast_verbose("test <channel-name> <msg#>\n\n");
5398  }
5399  chan_list_unref(tmp, "Facility test done");
5400  } else if (a->argc < 6) {
5401  for (msg_number = 0; msg_number < ARRAY_LEN(Fac_Msgs); ++msg_number) {
5402  misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
5403  bc->fac_out = Fac_Msgs[msg_number];
5404 
5405  /* Send message */
5406  print_facility(&bc->fac_out, bc);
5408  sleep(1);
5409  }
5410  } else {
5411  msg_number = atoi(a->argv[5]);
5412  if (msg_number < ARRAY_LEN(Fac_Msgs)) {
5413  misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
5414  bc->fac_out = Fac_Msgs[msg_number];
5415 
5416  /* Send message */
5417  print_facility(&bc->fac_out, bc);
5419  } else {
5420  ast_verbose("test <port> [<msg#>]\n\n");
5421  }
5422  }
5423  } else if (strstr(a->argv[3], "register")) {
5424  if (a->argc < 5) {
5425  ast_verbose("register <port>\n\n");
5426  return 0;
5427  }
5428  port = atoi(a->argv[4]);
5429 
5430  bc = misdn_lib_get_register_bc(port);
5431  if (!bc) {
5432  ast_verbose("Could not allocate REGISTER bc struct\n\n");
5433  return 0;
5434  }
5435  bc->fac_out = Fac_Msgs[45];
5436 
5437  /* Send message */
5438  print_facility(&bc->fac_out, bc);
5440 #endif /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
5441  }
5442 
5443  return CLI_SUCCESS;
5444 }
5445 
5446 static char *handle_cli_misdn_send_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5447 {
5448  int port;
5449  int channel;
5450 
5451  switch (cmd) {
5452  case CLI_INIT:
5453  e->command = "misdn send restart";
5454  e->usage =
5455  "Usage: misdn send restart [port [channel]]\n"
5456  " Send a restart for every bchannel on the given port.\n";
5457  return NULL;
5458  case CLI_GENERATE:
5459  return NULL;
5460  }
5461 
5462  if (a->argc < 4 || a->argc > 5) {
5463  return CLI_SHOWUSAGE;
5464  }
5465 
5466  port = atoi(a->argv[3]);
5467 
5468  if (a->argc == 5) {
5469  channel = atoi(a->argv[4]);
5470  misdn_lib_send_restart(port, channel);
5471  } else {
5472  misdn_lib_send_restart(port, -1);
5473  }
5474 
5475  return CLI_SUCCESS;
5476 }
5477 
5478 static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5479 {
5480  const char *channame;
5481  const char *msg;
5482  struct chan_list *tmp;
5483  int i, msglen;
5484 
5485  switch (cmd) {
5486  case CLI_INIT:
5487  e->command = "misdn send digit";
5488  e->usage =
5489  "Usage: misdn send digit <channel> \"<msg>\" \n"
5490  " Send <digit> to <channel> as DTMF Tone\n"
5491  " when channel is a mISDN channel\n";
5492  return NULL;
5493  case CLI_GENERATE:
5494  return complete_ch(a);
5495  }
5496 
5497  if (a->argc != 5) {
5498  return CLI_SHOWUSAGE;
5499  }
5500 
5501  channame = a->argv[3];
5502  msg = a->argv[4];
5503  msglen = strlen(msg);
5504 
5505  ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
5506 
5507  tmp = get_chan_by_ast_name(channame);
5508  if (!tmp) {
5509  ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
5510  return CLI_SUCCESS;
5511  }
5512 #if 1
5513  for (i = 0; i < msglen; i++) {
5514  if (!tmp->ast) {
5515  break;
5516  }
5517  ast_cli(a->fd, "Sending: %c\n", msg[i]);
5518  send_digit_to_chan(tmp, msg[i]);
5519  /* res = ast_safe_sleep(tmp->ast, 250); */
5520  usleep(250000);
5521  /* res = ast_waitfor(tmp->ast,100); */
5522  }
5523 #else
5524  if (tmp->ast) {
5525  ast_dtmf_stream(tmp->ast, NULL, msg, 250);
5526  }
5527 #endif
5528  chan_list_unref(tmp, "Digit(s) sent");
5529 
5530  return CLI_SUCCESS;
5531 }
5532 
5533 static char *handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5534 {
5535  const char *channame;
5536  struct chan_list *tmp;
5537 
5538  switch (cmd) {
5539  case CLI_INIT:
5540  e->command = "misdn toggle echocancel";
5541  e->usage =
5542  "Usage: misdn toggle echocancel <channel>\n"
5543  " Toggle EchoCancel on mISDN Channel.\n";
5544  return NULL;
5545  case CLI_GENERATE:
5546  return complete_ch(a);
5547  }
5548 
5549  if (a->argc != 4) {
5550  return CLI_SHOWUSAGE;
5551  }
5552 
5553  channame = a->argv[3];
5554 
5555  ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
5556 
5557  tmp = get_chan_by_ast_name(channame);
5558  if (!tmp) {
5559  ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
5560  return CLI_SUCCESS;
5561  }
5562 
5563  tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
5564 
5565  if (tmp->toggle_ec) {
5566 #ifdef MISDN_1_2
5567  update_pipeline_config(tmp->bc);
5568 #else
5569  update_ec_config(tmp->bc);
5570 #endif
5571  manager_ec_enable(tmp->bc);
5572  } else {
5573  manager_ec_disable(tmp->bc);
5574  }
5575  chan_list_unref(tmp, "Done toggling echo cancel");
5576 
5577  return CLI_SUCCESS;
5578 }
5579 
5580 static char *handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5581 {
5582  const char *channame;
5583  const char *msg;
5584  struct chan_list *tmp;
5585 
5586  switch (cmd) {
5587  case CLI_INIT:
5588  e->command = "misdn send display";
5589  e->usage =
5590  "Usage: misdn send display <channel> \"<msg>\" \n"
5591  " Send <msg> to <channel> as Display Message\n"
5592  " when channel is a mISDN channel\n";
5593  return NULL;
5594  case CLI_GENERATE:
5595  return complete_ch(a);
5596  }
5597 
5598  if (a->argc != 5) {
5599  return CLI_SHOWUSAGE;
5600  }
5601 
5602  channame = a->argv[3];
5603  msg = a->argv[4];
5604 
5605  ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
5606 
5607  tmp = get_chan_by_ast_name(channame);
5608  if (tmp && tmp->bc) {
5609  ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
5611  chan_list_unref(tmp, "Done sending display");
5612  } else {
5613  if (tmp) {
5614  chan_list_unref(tmp, "Display failed");
5615  }
5616  ast_cli(a->fd, "No such channel %s\n", channame);
5617  return CLI_SUCCESS;
5618  }
5619 
5620  return CLI_SUCCESS;
5621 }
5622 
5623 static char *complete_ch(struct ast_cli_args *a)
5624 {
5625  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
5626 }
5627 
5628 static char *complete_debug_port(struct ast_cli_args *a)
5629 {
5630  if (a->n) {
5631  return NULL;
5632  }
5633 
5634  switch (a->pos) {
5635  case 4:
5636  if (a->word[0] == 'p') {
5637  return ast_strdup("port");
5638  } else if (a->word[0] == 'o') {
5639  return ast_strdup("only");
5640  }
5641  break;
5642  case 6:
5643  if (a->word[0] == 'o') {
5644  return ast_strdup("only");
5645  }
5646  break;
5647  }
5648  return NULL;
5649 }
5650 
5651 static char *complete_show_config(struct ast_cli_args *a)
5652 {
5653  char buffer[BUFFERSIZE];
5654  enum misdn_cfg_elements elem;
5655  int wordlen = strlen(a->word);
5656  int which = 0;
5657  int port = 0;
5658 
5659  switch (a->pos) {
5660  case 3:
5661  if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n)) {
5662  return ast_strdup("description");
5663  }
5664  if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n)) {
5665  return ast_strdup("descriptions");
5666  }
5667  if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n)) {
5668  return ast_strdup("0");
5669  }
5670  while ((port = misdn_cfg_get_next_port(port)) != -1) {
5671  snprintf(buffer, sizeof(buffer), "%d", port);
5672  if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
5673  return ast_strdup(buffer);
5674  }
5675  }
5676  break;
5677  case 4:
5678  if (strstr(a->line, "description ")) {
5679  for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
5680  if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST)) {
5681  continue;
5682  }
5683  misdn_cfg_get_name(elem, buffer, sizeof(buffer));
5684  if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
5685  if (++which > a->n) {
5686  return ast_strdup(buffer);
5687  }
5688  }
5689  }
5690  } else if (strstr(a->line, "descriptions ")) {
5691  if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n)) {
5692  return ast_strdup("general");
5693  }
5694  if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n)) {
5695  return ast_strdup("ports");
5696  }
5697  }
5698  break;
5699  }
5700  return NULL;
5701 }
5702 
5703 static struct ast_cli_entry chan_misdn_clis[] = {
5704 /* *INDENT-OFF* */
5705  AST_CLI_DEFINE(handle_cli_misdn_port_block, "Block the given port"),
5706  AST_CLI_DEFINE(handle_cli_misdn_port_down, "Try to deactivate the L1 on the given port"),
5707  AST_CLI_DEFINE(handle_cli_misdn_port_unblock, "Unblock the given port"),
5708  AST_CLI_DEFINE(handle_cli_misdn_port_up, "Try to establish L1 on the given port"),
5709  AST_CLI_DEFINE(handle_cli_misdn_reload, "Reload internal mISDN config, read from the config file"),
5710  AST_CLI_DEFINE(handle_cli_misdn_restart_pid, "Restart the given pid"),
5711  AST_CLI_DEFINE(handle_cli_misdn_restart_port, "Restart the given port"),
5712  AST_CLI_DEFINE(handle_cli_misdn_show_channel, "Show an internal mISDN channel"),
5713  AST_CLI_DEFINE(handle_cli_misdn_show_channels, "Show the internal mISDN channel list"),
5714  AST_CLI_DEFINE(handle_cli_misdn_show_config, "Show internal mISDN config, read from the config file"),
5715  AST_CLI_DEFINE(handle_cli_misdn_show_port, "Show detailed information for given port"),
5716  AST_CLI_DEFINE(handle_cli_misdn_show_ports_stats, "Show mISDNs channel's call statistics per port"),
5717  AST_CLI_DEFINE(handle_cli_misdn_show_stacks, "Show internal mISDN stack_list"),
5718  AST_CLI_DEFINE(handle_cli_misdn_send_facility, "Sends a Facility Message to the mISDN Channel"),
5719  AST_CLI_DEFINE(handle_cli_misdn_send_digit, "Send DTMF digit to mISDN Channel"),
5720  AST_CLI_DEFINE(handle_cli_misdn_send_display, "Send Text to mISDN Channel"),
5721  AST_CLI_DEFINE(handle_cli_misdn_send_restart, "Send a restart for every bchannel on the given port"),
5722  AST_CLI_DEFINE(handle_cli_misdn_set_crypt_debug, "Set CryptDebuglevel of chan_misdn, at the moment, level={1,2}"),
5723  AST_CLI_DEFINE(handle_cli_misdn_set_debug, "Set Debuglevel of chan_misdn"),
5725  AST_CLI_DEFINE(handle_cli_misdn_toggle_echocancel, "Toggle EchoCancel on mISDN Channel"),
5726 /* *INDENT-ON* */
5727 };
5728 
5729 /*! \brief Updates caller ID information from config */
5730 static void update_config(struct chan_list *ch)
5731 {
5732  struct ast_channel *ast;
5733  struct misdn_bchannel *bc;
5734  int port;
5735  int hdlc = 0;
5736  int pres;
5737  int screen;
5738 
5739  if (!ch) {
5740  ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
5741  return;
5742  }
5743 
5744  ast = ch->ast;
5745  bc = ch->bc;
5746  if (! ast || ! bc) {
5747  ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
5748  return;
5749  }
5750 
5751  port = bc->port;
5752 
5753  chan_misdn_log(7, port, "update_config: Getting Config\n");
5754 
5755  misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
5756  if (hdlc) {
5757  switch (bc->capability) {
5760  chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
5761  bc->hdlc = 1;
5762  break;
5763  }
5764  }
5765 
5766 
5767  misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
5768  misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
5769  chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
5770 
5771  if (pres < 0 || screen < 0) {
5772  chan_misdn_log(2, port, " --> pres: %x\n", ast->connected.id.number.presentation);
5773 
5775  chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
5776 
5778  chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
5779  } else {
5780  bc->caller.screening = screen;
5781  bc->caller.presentation = pres;
5782  }
5783 }
5784 
5785 
5786 static void config_jitterbuffer(struct chan_list *ch)
5787 {
5788  struct misdn_bchannel *bc = ch->bc;
5789  int len = ch->jb_len;
5790  int threshold = ch->jb_upper_threshold;
5791 
5792  chan_misdn_log(5, bc->port, "config_jb: Called\n");
5793 
5794  if (!len) {
5795  chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
5796  bc->nojitter = 1;
5797  } else {
5798  if (len <= 100 || len > 8000) {
5799  chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
5800  len = 1000;
5801  }
5802 
5803  if (threshold > len) {
5804  chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
5805  }
5806 
5807  if (ch->jb) {
5808  cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
5809  misdn_jb_destroy(ch->jb);
5810  ch->jb = NULL;
5811  }
5812 
5813  ch->jb = misdn_jb_init(len, threshold);
5814 
5815  if (!ch->jb) {
5816  bc->nojitter = 1;
5817  }
5818  }
5819 }
5820 
5821 
5822 void debug_numtype(int port, int numtype, char *type)
5823 {
5824  switch (numtype) {
5825  case NUMTYPE_UNKNOWN:
5826  chan_misdn_log(2, port, " --> %s: Unknown\n", type);
5827  break;
5828  case NUMTYPE_INTERNATIONAL:
5829  chan_misdn_log(2, port, " --> %s: International\n", type);
5830  break;
5831  case NUMTYPE_NATIONAL:
5832  chan_misdn_log(2, port, " --> %s: National\n", type);
5833  break;
5835  chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
5836  break;
5837  case NUMTYPE_SUBSCRIBER:
5838  chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
5839  break;
5840  case NUMTYPE_ABBREVIATED:
5841  chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
5842  break;
5843  /* Maybe we should cut off the prefix if present ? */
5844  default:
5845  chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
5846  break;
5847  }
5848 }
5849 
5850 
5851 #ifdef MISDN_1_2
5852 static int update_pipeline_config(struct misdn_bchannel *bc)
5853 {
5854  int ec;
5855 
5856  misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
5857 
5858  if (*bc->pipeline) {
5859  return 0;
5860  }
5861 
5862  misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
5863  if (ec == 1) {
5864  ast_copy_string(bc->pipeline, "mg2ec", sizeof(bc->pipeline));
5865  } else if (ec > 1) {
5866  snprintf(bc->pipeline, sizeof(bc->pipeline), "mg2ec(deftaps=%d)", ec);
5867  }
5868 
5869  return 0;
5870 }
5871 #else
5872 static int update_ec_config(struct misdn_bchannel *bc)
5873 {
5874  int ec;
5875  int port = bc->port;
5876 
5877  misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
5878 
5879  if (ec == 1) {
5880  bc->ec_enable = 1;
5881  } else if (ec > 1) {
5882  bc->ec_enable = 1;
5883  bc->ec_deftaps = ec;
5884  }
5885 
5886  return 0;
5887 }
5888 #endif
5889 
5890 
5891 static int read_config(struct chan_list *ch)
5892 {
5893  struct ast_channel *ast;
5894  struct misdn_bchannel *bc;
5895  int port;
5896  int hdlc = 0;
5897  char lang[BUFFERSIZE + 1];
5898  char faxdetect[BUFFERSIZE + 1];
5899  char buf[256];
5900  char buf2[256];
5901  ast_group_t pg;
5902  ast_group_t cg;
5903 
5904  if (!ch) {
5905  ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
5906  return -1;
5907  }
5908 
5909  ast = ch->ast;
5910  bc = ch->bc;
5911  if (! ast || ! bc) {
5912  ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
5913  return -1;
5914  }
5915 
5916  port = bc->port;
5917  chan_misdn_log(1, port, "read_config: Getting Config\n");
5918 
5919  misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
5920  ast_string_field_set(ast, language, lang);
5921 
5923 
5924  misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
5925  misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
5926 
5928 
5929  misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
5930 
5931  misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
5932  if (ch->ast_dsp) {
5933  ch->ignore_dtmf = 1;
5934  }
5935 
5937  misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
5938 
5940 
5942 
5944 
5945  misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
5946 
5947  misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
5948  if (hdlc) {
5949  switch (bc->capability) {
5952  chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
5953  bc->hdlc = 1;
5954  break;
5955  }
5956 
5957  }
5958  /*Initialize new Jitterbuffer*/
5959  misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
5961 
5962  config_jitterbuffer(ch);
5963 
5964  misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
5965 
5966  ast_copy_string(ast->context, ch->context, sizeof(ast->context));
5967 
5968 #ifdef MISDN_1_2
5969  update_pipeline_config(bc);
5970 #else
5971  update_ec_config(bc);
5972 #endif
5973 
5975 
5979 
5980  misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
5981  misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
5982  chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
5983  ast->pickupgroup = pg;
5984  ast->callgroup = cg;
5985 
5986  if (ch->originator == ORG_AST) {
5987  char callerid[BUFFERSIZE + 1];
5988 
5989  /* ORIGINATOR Asterisk (outgoing call) */
5990 
5992 
5993  if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
5994  ch->faxdetect = strstr(faxdetect, "nojump") ? 2 : 1;
5995  }
5996 
5997  misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
5998  if (!ast_strlen_zero(callerid)) {
5999  char *cid_name = NULL;
6000  char *cid_num = NULL;
6001 
6002  ast_callerid_parse(callerid, &cid_name, &cid_num);
6003  if (cid_name) {
6004  ast_copy_string(bc->caller.name, cid_name, sizeof(bc->caller.name));
6005  } else {
6006  bc->caller.name[0] = '\0';
6007  }
6008  if (cid_num) {
6009  ast_copy_string(bc->caller.number, cid_num, sizeof(bc->caller.number));
6010  } else {
6011  bc->caller.number[0] = '\0';
6012  }
6013  chan_misdn_log(1, port, " --> * Setting caller to \"%s\" <%s>\n", bc->caller.name, bc->caller.number);
6014  }
6015 
6018  debug_numtype(port, bc->dialed.number_type, "TON");
6019 
6020  ch->overlap_dial = 0;
6021  } else {
6022  /* ORIGINATOR MISDN (incoming call) */
6023 
6024  if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
6025  ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
6026  }
6027 
6028  /* Add configured prefix to caller.number */
6030 
6031  if (ast_strlen_zero(bc->dialed.number) && !ast_strlen_zero(bc->keypad)) {
6032  ast_copy_string(bc->dialed.number, bc->keypad, sizeof(bc->dialed.number));
6033  }
6034 
6035  /* Add configured prefix to dialed.number */
6037 
6038  ast_copy_string(ast->exten, bc->dialed.number, sizeof(ast->exten));
6039 
6042  } /* ORIG MISDN END */
6043 
6045  if (!ast_strlen_zero(bc->incoming_cid_tag)) {
6046  chan_misdn_log(1, port, " --> * Setting incoming caller id tag to \"%s\"\n", bc->incoming_cid_tag);
6047  }
6048  ch->overlap_dial_task = -1;
6049 
6050  if (ch->faxdetect || ch->ast_dsp) {
6052  if (!ch->dsp) {
6053  ch->dsp = ast_dsp_new();
6054  }
6055  if (ch->dsp) {
6057  }
6058  }
6059 
6060  /* AOCD initialization */
6061  bc->AOCDtype = Fac_None;
6062 
6063  return 0;
6064 }
6065 
6066 /*!
6067  * \internal
6068  * \brief Send a connected line update to the other channel
6069  *
6070  * \param ast Current Asterisk channel
6071  * \param id Party id information to send to the other side
6072  * \param source Why are we sending this update
6073  * \param cid_tag User tag to apply to the party id.
6074  *
6075  * \return Nothing
6076  */
6077 static void misdn_queue_connected_line_update(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
6078 {
6079  struct ast_party_connected_line connected;
6080  struct ast_set_party_connected_line update_connected;
6081 
6082  ast_party_connected_line_init(&connected);
6083  memset(&update_connected, 0, sizeof(update_connected));
6084  update_connected.id.number = 1;
6085  connected.id.number.valid = 1;
6086  connected.id.number.str = (char *) id->number;
6087  connected.id.number.plan = misdn_to_ast_ton(id->number_type)
6091  connected.id.tag = cid_tag;
6092  connected.source = source;
6093  ast_channel_queue_connected_line_update(ast, &connected, &update_connected);
6094 }
6095 
6096 /*!
6097  * \internal
6098  * \brief Update the caller id party on this channel.
6099  *
6100  * \param ast Current Asterisk channel
6101  * \param id Remote party id information to update.
6102  * \param cid_tag User tag to apply to the party id.
6103  *
6104  * \return Nothing
6105  */
6106 static void misdn_update_caller_id(struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag)
6107 {
6108  struct ast_party_caller caller;
6109  struct ast_set_party_caller update_caller;
6110 
6111  memset(&update_caller, 0, sizeof(update_caller));
6112  update_caller.id.number = 1;
6113  update_caller.ani.number = 1;
6114 
6115  ast_channel_lock(ast);
6116  ast_party_caller_set_init(&caller, &ast->caller);
6117 
6118  caller.id.number.valid = 1;
6119  caller.id.number.str = (char *) id->number;
6120  caller.id.number.plan = misdn_to_ast_ton(id->number_type)
6124 
6125  caller.ani.number = caller.id.number;
6126 
6127  caller.id.tag = cid_tag;
6128  caller.ani.tag = cid_tag;
6129 
6130  ast_channel_set_caller_event(ast, &caller, &update_caller);
6131  ast_channel_unlock(ast);
6132 }
6133 
6134 /*!
6135  * \internal
6136  * \brief Update the remote party id information.
6137  *
6138  * \param ast Current Asterisk channel
6139  * \param id Remote party id information to update.
6140  * \param source Why are we sending this update
6141  * \param cid_tag User tag to apply to the party id.
6142  *
6143  * \return Nothing
6144  */
6145 static void misdn_update_remote_party(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
6146 {
6147  misdn_update_caller_id(ast, id, cid_tag);
6148  misdn_queue_connected_line_update(ast, id, source, cid_tag);
6149 }
6150 
6151 /*!
6152  * \internal
6153  * \brief Get the connected line information out of the Asterisk channel.
6154  *
6155  * \param ast Current Asterisk channel
6156  * \param bc Associated B channel
6157  * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
6158  *
6159  * \return Nothing
6160  */
6161 static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
6162 {
6163  int number_type;
6164 
6165  if (originator == ORG_MISDN) {
6166  /* ORIGINATOR MISDN (incoming call) */
6167 
6169  S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
6170  sizeof(bc->connected.name));
6171  if (ast->connected.id.number.valid) {
6173  sizeof(bc->connected.number));
6178  } else {
6179  bc->connected.number[0] = '\0';
6180  bc->connected.presentation = 0;/* Allowed */
6181  bc->connected.screening = 0;/* Unscreened */
6184  }
6185 
6186  misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
6187  if (0 <= number_type) {
6188  /* Force us to send in CONNECT message */
6189  bc->connected.number_type = number_type;
6191  }
6192  debug_numtype(bc->port, bc->connected.number_type, "CTON");
6193  } else {
6194  /* ORIGINATOR Asterisk (outgoing call) */
6195 
6197  S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
6198  sizeof(bc->caller.name));
6199  if (ast->connected.id.number.valid) {
6201  sizeof(bc->caller.number));
6206  } else {
6207  bc->caller.number[0] = '\0';
6208  bc->caller.presentation = 0;/* Allowed */
6209  bc->caller.screening = 0;/* Unscreened */
6212  }
6213 
6214  misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
6215  if (0 <= number_type) {
6216  /* Force us to send in SETUP message */
6217  bc->caller.number_type = number_type;
6219  }
6220  debug_numtype(bc->port, bc->caller.number_type, "LTON");
6221  }
6222 }
6223 
6224 /*!
6225  * \internal
6226  * \brief Notify peer that the connected line has changed.
6227  *
6228  * \param ast Current Asterisk channel
6229  * \param bc Associated B channel
6230  * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
6231  *
6232  * \return Nothing
6233  */
6234 static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
6235 {
6236  struct chan_list *ch;
6237 
6238  misdn_get_connected_line(ast, bc, originator);
6239  if (originator == ORG_MISDN) {
6240  bc->redirecting.to = bc->connected;
6241  } else {
6242  bc->redirecting.to = bc->caller;
6243  }
6244  switch (bc->outgoing_colp) {
6245  case 1:/* restricted */
6246  bc->redirecting.to.presentation = 1;/* restricted */
6247  break;
6248  case 2:/* blocked */
6249  /* Don't tell the remote party that the call was transferred. */
6250  return;
6251  default:
6252  break;
6253  }
6254 
6255  ch = MISDN_ASTERISK_TECH_PVT(ast);
6256  if (ch->state == MISDN_CONNECTED
6257  || originator != ORG_MISDN) {
6258  int is_ptmp;
6259 
6260  is_ptmp = !misdn_lib_is_ptp(bc->port);
6261  if (is_ptmp) {
6262  /*
6263  * We should not send these messages to the network if we are
6264  * the CPE side since phones do not transfer calls within
6265  * themselves. Well... If you consider handing the handset to
6266  * someone else a transfer then how is the network to know?
6267  */
6268  if (!misdn_lib_port_is_nt(bc->port)) {
6269  return;
6270  }
6271  if (ch->state != MISDN_CONNECTED) {
6272  /* Send NOTIFY(Nie(transfer-active), RDNie(redirecting.to data)) */
6273  bc->redirecting.to_changed = 1;
6276 #if defined(AST_MISDN_ENHANCEMENTS)
6277  } else {
6278  /* Send FACILITY(Fie(RequestSubaddress), Nie(transfer-active), RDNie(redirecting.to data)) */
6279  bc->redirecting.to_changed = 1;
6281  bc->fac_out.Function = Fac_RequestSubaddress;
6282  bc->fac_out.u.RequestSubaddress.InvokeID = ++misdn_invoke_id;
6283 
6284  /* Send message */
6285  print_facility(&bc->fac_out, bc);
6287 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6288  }
6289 #if defined(AST_MISDN_ENHANCEMENTS)
6290  } else {
6291  /* Send FACILITY(Fie(EctInform(transfer-active, redirecting.to data))) */
6292  bc->fac_out.Function = Fac_EctInform;
6293  bc->fac_out.u.EctInform.InvokeID = ++misdn_invoke_id;
6294  bc->fac_out.u.EctInform.Status = 1;/* active */
6295  bc->fac_out.u.EctInform.RedirectionPresent = 1;/* Must be present when status is active */
6296  misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.EctInform.Redirection,
6297  &bc->redirecting.to);
6298 
6299  /* Send message */
6300  print_facility(&bc->fac_out, bc);
6302 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6303  }
6304  }
6305 }
6306 
6307 /*!
6308  * \internal
6309  * \brief Copy the redirecting information out of the Asterisk channel
6310  *
6311  * \param bc Associated B channel
6312  * \param ast Current Asterisk channel
6313  *
6314  * \return Nothing
6315  */
6317 {
6320  sizeof(bc->redirecting.from.name));
6321  if (ast->redirecting.from.number.valid) {
6323  sizeof(bc->redirecting.from.number));
6328  } else {
6329  bc->redirecting.from.number[0] = '\0';
6330  bc->redirecting.from.presentation = 0;/* Allowed */
6331  bc->redirecting.from.screening = 0;/* Unscreened */
6334  }
6335 
6337  S_COR(ast->redirecting.to.name.valid, ast->redirecting.to.name.str, ""),
6338  sizeof(bc->redirecting.to.name));
6339  if (ast->redirecting.to.number.valid) {
6341  sizeof(bc->redirecting.to.number));
6346  } else {
6347  bc->redirecting.to.number[0] = '\0';
6348  bc->redirecting.to.presentation = 0;/* Allowed */
6349  bc->redirecting.to.screening = 0;/* Unscreened */
6352  }
6353 
6355  bc->redirecting.count = ast->redirecting.count;
6356 }
6357 
6358 /*!
6359  * \internal
6360  * \brief Copy the redirecting info into the Asterisk channel
6361  *
6362  * \param ast Current Asterisk channel
6363  * \param redirect Associated B channel redirecting info
6364  * \param tag Caller ID tag to set in the redirecting party fields
6365  *
6366  * \return Nothing
6367  */
6368 static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag)
6369 {
6370  struct ast_party_redirecting redirecting;
6371  struct ast_set_party_redirecting update_redirecting;
6372 
6373  ast_party_redirecting_set_init(&redirecting, &ast->redirecting);
6374  memset(&update_redirecting, 0, sizeof(update_redirecting));
6375 
6376  update_redirecting.from.number = 1;
6377  redirecting.from.number.valid = 1;
6378  redirecting.from.number.str = (char *) redirect->from.number;
6379  redirecting.from.number.plan =
6380  misdn_to_ast_ton(redirect->from.number_type)
6381  | misdn_to_ast_plan(redirect->from.number_plan);
6382  redirecting.from.number.presentation =
6384  | misdn_to_ast_screen(redirect->from.screening);
6385  redirecting.from.tag = tag;
6386 
6387  update_redirecting.to.number = 1;
6388  redirecting.to.number.valid = 1;
6389  redirecting.to.number.str = (char *) redirect->to.number;
6390  redirecting.to.number.plan =
6391  misdn_to_ast_ton(redirect->to.number_type)
6392  | misdn_to_ast_plan(redirect->to.number_plan);
6393  redirecting.to.number.presentation =
6394  misdn_to_ast_pres(redirect->to.presentation)
6395  | misdn_to_ast_screen(redirect->to.screening);
6396  redirecting.to.tag = tag;
6397 
6398  redirecting.reason = misdn_to_ast_reason(redirect->reason);
6399  redirecting.count = redirect->count;
6400 
6401  ast_channel_set_redirecting(ast, &redirecting, &update_redirecting);
6402 }
6403 
6404 /*!
6405  * \internal
6406  * \brief Notify peer that the redirecting information has changed.
6407  *
6408  * \param ast Current Asterisk channel
6409  * \param bc Associated B channel
6410  * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
6411  *
6412  * \return Nothing
6413  */
6414 static void misdn_update_redirecting(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
6415 {
6416  int is_ptmp;
6417 
6419  switch (bc->outgoing_colp) {
6420  case 1:/* restricted */
6421  bc->redirecting.to.presentation = 1;/* restricted */
6422  break;
6423  case 2:/* blocked */
6424  /* Don't tell the remote party that the call was redirected. */
6425  return;
6426  default:
6427  break;
6428  }
6429 
6430  if (originator != ORG_MISDN) {
6431  return;
6432  }
6433 
6434  is_ptmp = !misdn_lib_is_ptp(bc->port);
6435  if (is_ptmp) {
6436  /*
6437  * We should not send these messages to the network if we are
6438  * the CPE side since phones do not redirect calls within
6439  * themselves. Well... If you consider someone else picking up
6440  * the handset a redirection then how is the network to know?
6441  */
6442  if (!misdn_lib_port_is_nt(bc->port)) {
6443  return;
6444  }
6445  /* Send NOTIFY(call-is-diverting, redirecting.to data) */
6446  bc->redirecting.to_changed = 1;
6449 #if defined(AST_MISDN_ENHANCEMENTS)
6450  } else {
6451  int match; /* TRUE if the dialed number matches the redirecting to number */
6452 
6453  match = (strcmp(ast->exten, bc->redirecting.to.number) == 0) ? 1 : 0;
6454  if (!bc->div_leg_3_tx_pending
6455  || !match) {
6456  /* Send DivertingLegInformation1 */
6457  bc->fac_out.Function = Fac_DivertingLegInformation1;
6458  bc->fac_out.u.DivertingLegInformation1.InvokeID = ++misdn_invoke_id;
6459  bc->fac_out.u.DivertingLegInformation1.DiversionReason =
6460  misdn_to_diversion_reason(bc->redirecting.reason);
6461  bc->fac_out.u.DivertingLegInformation1.SubscriptionOption = 2;/* notificationWithDivertedToNr */
6462  bc->fac_out.u.DivertingLegInformation1.DivertedToPresent = 1;
6463  misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.DivertingLegInformation1.DivertedTo, &bc->redirecting.to);
6464  print_facility(&bc->fac_out, bc);
6466  }
6467  bc->div_leg_3_tx_pending = 0;
6468 
6469  /* Send DivertingLegInformation3 */
6470  bc->fac_out.Function = Fac_DivertingLegInformation3;
6471  bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
6472  bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
6473  bc->redirecting.to.presentation == 0 ? 1 : 0;
6474  print_facility(&bc->fac_out, bc);
6476 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6477  }
6478 }
6479 
6480 
6481 /*****************************/
6482 /*** AST Indications Start ***/
6483 /*****************************/
6484 
6485 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
6486 {
6487  int port = 0;
6488  int r;
6489  int exceed;
6490  int number_type;
6491  struct chan_list *ch;
6492  struct misdn_bchannel *newbc;
6493  char *dest_cp;
6494  int append_msn = 0;
6495 
6497  AST_APP_ARG(intf); /* The interface token is discarded. */
6498  AST_APP_ARG(ext); /* extension token */
6499  AST_APP_ARG(opts); /* options token */
6500  );
6501 
6502  if (!ast) {
6503  ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
6504  return -1;
6505  }
6506 
6507  if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest) {
6508  ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
6511  return -1;
6512  }
6513 
6514  ch = MISDN_ASTERISK_TECH_PVT(ast);
6515  if (!ch) {
6516  ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast->name);
6519  return -1;
6520  }
6521 
6522  newbc = ch->bc;
6523  if (!newbc) {
6524  ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast->name);
6527  return -1;
6528  }
6529 
6530  port = newbc->port;
6531 
6532 #if defined(AST_MISDN_ENHANCEMENTS)
6533  if ((ch->peer = misdn_cc_caller_get(ast))) {
6534  chan_misdn_log(3, port, " --> Found CC caller data, peer:%s\n",
6535  ch->peer->chan ? "available" : "NULL");
6536  }
6537 
6538  if (ch->record_id != -1) {
6539  struct misdn_cc_record *cc_record;
6540 
6541  /* This is a call completion retry call */
6542  AST_LIST_LOCK(&misdn_cc_records_db);
6543  cc_record = misdn_cc_find_by_id(ch->record_id);
6544  if (!cc_record) {
6545  AST_LIST_UNLOCK(&misdn_cc_records_db);
6546  ast_log(LOG_WARNING, " --> ! misdn_call called on %s, cc_record==NULL\n", ast->name);
6549  return -1;
6550  }
6551 
6552  /* Setup calling parameters to retry the call. */
6553  newbc->dialed = cc_record->redial.dialed;
6554  newbc->caller = cc_record->redial.caller;
6555  memset(&newbc->redirecting, 0, sizeof(newbc->redirecting));
6556  newbc->capability = cc_record->redial.capability;
6557  newbc->hdlc = cc_record->redial.hdlc;
6558  newbc->sending_complete = 1;
6559 
6560  if (cc_record->ptp) {
6561  newbc->fac_out.Function = Fac_CCBS_T_Call;
6562  newbc->fac_out.u.CCBS_T_Call.InvokeID = ++misdn_invoke_id;
6563  } else {
6564  newbc->fac_out.Function = Fac_CCBSCall;
6565  newbc->fac_out.u.CCBSCall.InvokeID = ++misdn_invoke_id;
6566  newbc->fac_out.u.CCBSCall.CCBSReference = cc_record->mode.ptmp.reference_id;
6567  }
6568  AST_LIST_UNLOCK(&misdn_cc_records_db);
6569 
6570  ast_copy_string(ast->exten, newbc->dialed.number, sizeof(ast->exten));
6571 
6572  chan_misdn_log(1, port, "* Call completion to: %s\n", newbc->dialed.number);
6573  chan_misdn_log(2, port, " --> * tech:%s context:%s\n", ast->name, ast->context);
6574  } else
6575 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6576  {
6577  /*
6578  * dest is ---v
6579  * Dial(mISDN/g:group_name[/extension[/options]])
6580  * Dial(mISDN/port[:preselected_channel][/extension[/options]])
6581  *
6582  * The dial extension could be empty if you are using MISDN_KEYPAD
6583  * to control ISDN provider features.
6584  */
6585  dest_cp = ast_strdupa(dest);
6586  AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
6587  if (!args.ext) {
6588  args.ext = "";
6589  }
6590 
6591  chan_misdn_log(1, port, "* CALL: %s\n", dest);
6592  chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast->name, ast->context);
6593 
6594  ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
6595  ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
6596 
6597  if (ast_strlen_zero(newbc->caller.name)
6598  && ast->connected.id.name.valid
6599  && !ast_strlen_zero(ast->connected.id.name.str)) {
6600  ast_copy_string(newbc->caller.name, ast->connected.id.name.str, sizeof(newbc->caller.name));
6601  chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
6602  }
6603  if (ast_strlen_zero(newbc->caller.number)
6604  && ast->connected.id.number.valid
6605  && !ast_strlen_zero(ast->connected.id.number.str)) {
6606  ast_copy_string(newbc->caller.number, ast->connected.id.number.str, sizeof(newbc->caller.number));
6607  chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
6608  }
6609 
6610  misdn_cfg_get(port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
6611  if (append_msn) {
6612  strncat(newbc->incoming_cid_tag, "_", sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
6613  strncat(newbc->incoming_cid_tag, newbc->caller.number, sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
6614  }
6615 
6616  ast->caller.id.tag = ast_strdup(newbc->incoming_cid_tag);
6617 
6618  misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
6619  if (number_type < 0) {
6620  if (ast->connected.id.number.valid) {
6623  } else {
6625  newbc->caller.number_plan = NUMPLAN_ISDN;
6626  }
6627  } else {
6628  /* Force us to send in SETUP message */
6629  newbc->caller.number_type = number_type;
6630  newbc->caller.number_plan = NUMPLAN_ISDN;
6631  }
6632  debug_numtype(port, newbc->caller.number_type, "LTON");
6633 
6634  newbc->capability = ast->transfercapability;
6635  pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
6637  chan_misdn_log(2, port, " --> * Call with flag Digital\n");
6638  }
6639 
6640  /* update caller screening and presentation */
6641  update_config(ch);
6642 
6643  /* fill in some ies from channel dialplan variables */
6644  import_ch(ast, newbc, ch);
6645 
6646  /* Finally The Options Override Everything */
6647  if (!ast_strlen_zero(args.opts)) {
6648  misdn_set_opt_exec(ast, args.opts);
6649  } else {
6650  chan_misdn_log(2, port, "NO OPTS GIVEN\n");
6651  }
6652  if (newbc->set_presentation) {
6653  newbc->caller.presentation = newbc->presentation;
6654  }
6655 
6656  misdn_copy_redirecting_from_ast(newbc, ast);
6657  switch (newbc->outgoing_colp) {
6658  case 1:/* restricted */
6659  case 2:/* blocked */
6660  newbc->redirecting.from.presentation = 1;/* restricted */
6661  break;
6662  default:
6663  break;
6664  }
6665 #if defined(AST_MISDN_ENHANCEMENTS)
6666  if (newbc->redirecting.from.number[0] && misdn_lib_is_ptp(port)) {
6667  if (newbc->redirecting.count < 1) {
6668  newbc->redirecting.count = 1;
6669  }
6670 
6671  /* Create DivertingLegInformation2 facility */
6672  newbc->fac_out.Function = Fac_DivertingLegInformation2;
6673  newbc->fac_out.u.DivertingLegInformation2.InvokeID = ++misdn_invoke_id;
6674  newbc->fac_out.u.DivertingLegInformation2.DivertingPresent = 1;
6675  misdn_PresentedNumberUnscreened_fill(
6676  &newbc->fac_out.u.DivertingLegInformation2.Diverting,
6677  &newbc->redirecting.from);
6678  switch (newbc->outgoing_colp) {
6679  case 2:/* blocked */
6680  /* Block the number going out */
6681  newbc->fac_out.u.DivertingLegInformation2.Diverting.Type = 1;/* presentationRestricted */
6682 
6683  /* Don't tell about any previous diversions or why for that matter. */
6684  newbc->fac_out.u.DivertingLegInformation2.DiversionCounter = 1;
6685  newbc->fac_out.u.DivertingLegInformation2.DiversionReason = 0;/* unknown */
6686  break;
6687  default:
6688  newbc->fac_out.u.DivertingLegInformation2.DiversionCounter =
6689  newbc->redirecting.count;
6690  newbc->fac_out.u.DivertingLegInformation2.DiversionReason =
6691  misdn_to_diversion_reason(newbc->redirecting.reason);
6692  break;
6693  }
6694  newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 0;
6695  if (1 < newbc->fac_out.u.DivertingLegInformation2.DiversionCounter) {
6696  newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 1;
6697  newbc->fac_out.u.DivertingLegInformation2.OriginalCalled.Type = 2;/* numberNotAvailableDueToInterworking */
6698  }
6699 
6700  /*
6701  * Expect a DivertingLegInformation3 to update the COLR of the
6702  * redirecting-to party we are attempting to call now.
6703  */
6704  newbc->div_leg_3_rx_wanted = 1;
6705  }
6706 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6707  }
6708 
6709  exceed = add_out_calls(port);
6710  if (exceed != 0) {
6711  char tmp[16];
6712 
6713  snprintf(tmp, sizeof(tmp), "%d", exceed);
6714  pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
6717  return -1;
6718  }
6719 
6720 #if defined(AST_MISDN_ENHANCEMENTS)
6721  if (newbc->fac_out.Function != Fac_None) {
6722  print_facility(&newbc->fac_out, newbc);
6723  }
6724 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6725  r = misdn_lib_send_event(newbc, EVENT_SETUP);
6726 
6727  /** we should have l3id after sending setup **/
6728  ch->l3id = newbc->l3_id;
6729 
6730  if (r == -ENOCHAN) {
6731  chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
6732  chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
6735  return -1;
6736  }
6737 
6738  chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
6739 
6742 
6743  if (newbc->nt) {
6744  stop_bc_tones(ch);
6745  }
6746 
6747  ch->state = MISDN_CALLING;
6748 
6749  return 0;
6750 }
6751 
6752 
6753 static int misdn_answer(struct ast_channel *ast)
6754 {
6755  struct chan_list *p;
6756  const char *tmp;
6757 
6758  if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
6759  return -1;
6760  }
6761 
6762  chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
6763 
6764  if (!p) {
6765  ast_log(LOG_WARNING, " --> Channel not connected ??\n");
6767  }
6768 
6769  if (!p->bc) {
6770  chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
6771 
6773  }
6774 
6775  ast_channel_lock(ast);
6776  tmp = pbx_builtin_getvar_helper(ast, "CRYPT_KEY");
6777  if (!ast_strlen_zero(tmp)) {
6778  chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
6779  ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
6780  } else {
6781  chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
6782  }
6783 
6784  tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
6785  if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
6786  chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
6787  p->bc->nodsp = 1;
6788  p->bc->hdlc = 0;
6789  p->bc->nojitter = 1;
6790  }
6791  ast_channel_unlock(ast);
6792 
6793  p->state = MISDN_CONNECTED;
6794  stop_indicate(p);
6795 
6796  if (ast_strlen_zero(p->bc->connected.number)) {
6797  chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
6799 
6800  /*
6801  * Use the misdn_set_opt() application to set the presentation
6802  * before we answer or you can use the CONECTEDLINE() function
6803  * to set everything before using the Answer() application.
6804  */
6806  p->bc->connected.screening = 0; /* unscreened */
6809  }
6810 
6811  switch (p->bc->outgoing_colp) {
6812  case 1:/* restricted */
6813  case 2:/* blocked */
6814  p->bc->connected.presentation = 1;/* restricted */
6815  break;
6816  default:
6817  break;
6818  }
6819 
6820 #if defined(AST_MISDN_ENHANCEMENTS)
6821  if (p->bc->div_leg_3_tx_pending) {
6822  p->bc->div_leg_3_tx_pending = 0;
6823 
6824  /* Send DivertingLegInformation3 */
6825  p->bc->fac_out.Function = Fac_DivertingLegInformation3;
6826  p->bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
6827  p->bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
6828  (p->bc->connected.presentation == 0) ? 1 : 0;
6829  print_facility(&p->bc->fac_out, p->bc);
6830  }
6831 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6833  start_bc_tones(p);
6834 
6835  return 0;
6836 }
6837 
6838 static int misdn_digit_begin(struct ast_channel *chan, char digit)
6839 {
6840  /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
6841  return 0;
6842 }
6843 
6844 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
6845 {
6846  struct chan_list *p;
6847  struct misdn_bchannel *bc;
6848  char buf[2] = { digit, 0 };
6849 
6850  if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
6851  return -1;
6852  }
6853 
6854  bc = p->bc;
6855  chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
6856 
6857  if (!bc) {
6858  ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
6859  return -1;
6860  }
6861 
6862  switch (p->state) {
6863  case MISDN_CALLING:
6864  if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
6865  strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
6866  }
6867  break;
6869  ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
6870  if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
6871  strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
6872  }
6873  ast_copy_string(p->ast->exten, bc->dialed.number, sizeof(p->ast->exten));
6875  break;
6876  default:
6877  if (bc->send_dtmf) {
6878  send_digit_to_chan(p, digit);
6879  }
6880  break;
6881  }
6882 
6883  return 0;
6884 }
6885 
6886 
6887 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
6888 {
6889  struct chan_list *p;
6890 
6891  if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
6892  return -1;
6893  }
6894 
6895  chan_misdn_log(1, p->bc ? p->bc->port : 0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
6896 
6897  p->ast = ast;
6898 
6899  return 0;
6900 }
6901 
6902 
6903 
6904 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
6905 {
6906  struct chan_list *p;
6907 
6908  if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
6909  ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
6910  return -1;
6911  }
6912 
6913  if (!p->bc) {
6914  if (p->hold.state == MISDN_HOLD_IDLE) {
6915  chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on %s\n", cond,
6916  ast->name);
6917  ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
6918  } else {
6919  chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on hold %s\n",
6920  cond, ast->name);
6921  }
6922  return -1;
6923  }
6924 
6925  chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] on %s\n", cond, ast->name);
6926 
6927  switch (cond) {
6928  case AST_CONTROL_BUSY:
6929  chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc->pid);
6931 
6933  if (p->state != MISDN_CONNECTED) {
6934  start_bc_tones(p);
6936  }
6937  return -1;
6938  case AST_CONTROL_RING:
6939  chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc->pid);
6940  return -1;
6941  case AST_CONTROL_RINGING:
6942  chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc->pid);
6943  switch (p->state) {
6944  case MISDN_ALERTING:
6945  chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc->pid);
6946  break;
6947  case MISDN_CONNECTED:
6948  chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc->pid);
6949  return -1;
6950  default:
6951  p->state = MISDN_ALERTING;
6952  chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid);
6954 
6955  chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid);
6957 
6958  if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
6959  chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
6960  } else {
6961  return -1;
6962  }
6963  }
6964  break;
6965  case AST_CONTROL_ANSWER:
6966  chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc->pid);
6967  start_bc_tones(p);
6968  break;
6970  chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc->pid);
6971  return -1;
6972  case AST_CONTROL_OFFHOOK:
6973  chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc->pid);
6974  return -1;
6975  case AST_CONTROL_FLASH:
6976  chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc->pid);
6977  break;
6978  case AST_CONTROL_PROGRESS:
6979  chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc->pid);
6981  break;
6983  chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
6985  break;
6987  chan_misdn_log(1, p->bc->port, " --> *\tincomplete pid:%d\n", p->bc->pid);
6988  if (!p->overlap_dial) {
6989  /* Overlapped dialing not enabled - send hangup */
6991  start_bc_tones(p);
6993 
6994  if (p->bc->nt) {
6996  }
6997  }
6998  break;
7000  chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
7001 
7003  start_bc_tones(p);
7005 
7006  if (p->bc->nt) {
7008  }
7009  break;
7010  case -1 :
7011  chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc->pid);
7012 
7013  stop_indicate(p);
7014 
7015  if (p->state == MISDN_CONNECTED) {
7016  start_bc_tones(p);
7017  }
7018  break;
7019  case AST_CONTROL_HOLD:
7020  ast_moh_start(ast, data, p->mohinterpret);
7021  chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc->pid);
7022  break;
7023  case AST_CONTROL_UNHOLD:
7024  ast_moh_stop(ast);
7025  chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc->pid);
7026  break;
7028  chan_misdn_log(1, p->bc->port, "* IND :\tconnected line update pid:%d\n", p->bc->pid);
7030  break;
7032  chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
7033  misdn_update_redirecting(ast, p->bc, p->originator);
7034  break;
7035  default:
7036  chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
7037  return -1;
7038  }
7039 
7040  return 0;
7041 }
7042 
7043 static int misdn_hangup(struct ast_channel *ast)
7044 {
7045  struct chan_list *p;
7046  struct misdn_bchannel *bc;
7047  const char *var;
7048 
7049  if (!ast) {
7050  return -1;
7051  }
7052 
7053  ast_debug(1, "misdn_hangup(%s)\n", ast->name);
7054 
7055  /* Take the ast_channel's tech_pvt reference. */
7056  ast_mutex_lock(&release_lock);
7057  p = MISDN_ASTERISK_TECH_PVT(ast);
7058  if (!p) {
7059  ast_mutex_unlock(&release_lock);
7060  return -1;
7061  }
7062  MISDN_ASTERISK_TECH_PVT(ast) = NULL;
7063 
7064  if (!misdn_chan_is_valid(p)) {
7065  ast_mutex_unlock(&release_lock);
7066  chan_list_unref(p, "Release ast_channel reference. Was not active?");
7067  return 0;
7068  }
7069 
7070  if (p->hold.state == MISDN_HOLD_IDLE) {
7071  bc = p->bc;
7072  } else {
7074  bc = misdn_lib_find_held_bc(p->hold.port, p->l3id);
7075  if (!bc) {
7076  chan_misdn_log(4, p->hold.port,
7077  "misdn_hangup: Could not find held bc for (%s)\n", ast->name);
7078  release_chan_early(p);
7079  ast_mutex_unlock(&release_lock);
7080  chan_list_unref(p, "Release ast_channel reference");
7081  return 0;
7082  }
7083  }
7084 
7085  if (ast->_state == AST_STATE_RESERVED || p->state == MISDN_NOTHING) {
7086  /* between request and call */
7087  ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
7088  release_chan_early(p);
7089  if (bc) {
7090  misdn_lib_release(bc);
7091  }
7092  ast_mutex_unlock(&release_lock);
7093  chan_list_unref(p, "Release ast_channel reference");
7094  return 0;
7095  }
7096  if (!bc) {
7097  ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n",
7098  misdn_get_ch_state(p), p->l3id);
7099  release_chan_early(p);
7100  ast_mutex_unlock(&release_lock);
7101  chan_list_unref(p, "Release ast_channel reference");
7102  return 0;
7103  }
7104 
7105  p->ast = NULL;
7106  p->need_hangup = 0;
7107  p->need_queue_hangup = 0;
7108  p->need_busy = 0;
7109 
7110  if (!bc->nt) {
7111  stop_bc_tones(p);
7112  }
7113 
7115 
7116  /* Channel lock is already held when we are called. */
7117  //ast_channel_lock(ast);
7118  var = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE");
7119  if (!var) {
7120  var = pbx_builtin_getvar_helper(ast, "PRI_CAUSE");
7121  }
7122  if (var) {
7123  int tmpcause;
7124 
7125  tmpcause = atoi(var);
7126  bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
7127  }
7128 
7129  var = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
7130  if (var) {
7131  ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", var);
7132  ast_copy_string(bc->uu, var, sizeof(bc->uu));
7133  bc->uulen = strlen(bc->uu);
7134  }
7135  //ast_channel_unlock(ast);
7136 
7137  chan_misdn_log(1, bc->port,
7138  "* IND : HANGUP\tpid:%d context:%s dialed:%s caller:\"%s\" <%s> State:%s\n",
7139  bc->pid,
7140  ast->context,
7141  ast->exten,
7142  (ast->caller.id.name.valid && ast->caller.id.name.str)
7143  ? ast->caller.id.name.str : "",
7144  (ast->caller.id.number.valid && ast->caller.id.number.str)
7145  ? ast->caller.id.number.str : "",
7146  misdn_get_ch_state(p));
7147  chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
7148  chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
7149  chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
7150 
7151  switch (p->state) {
7152  case MISDN_INCOMING_SETUP:
7153  /*
7154  * This is the only place in misdn_hangup, where we
7155  * can call release_chan, else it might create a lot of trouble.
7156  */
7157  ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
7158  release_chan(p, bc);
7160  ast_mutex_unlock(&release_lock);
7161  chan_list_unref(p, "Release ast_channel reference");
7162  return 0;
7163  case MISDN_DIALING:
7164  if (p->hold.state == MISDN_HOLD_IDLE) {
7165  start_bc_tones(p);
7167  }
7168 
7169  if (bc->need_disconnect) {
7171  }
7172  break;
7174  if (p->hold.state == MISDN_HOLD_IDLE) {
7175  start_bc_tones(p);
7177  }
7178 
7179  if (bc->need_disconnect) {
7181  }
7182  break;
7183 
7184  case MISDN_CALLING:
7185  case MISDN_ALERTING:
7186  case MISDN_PROGRESS:
7187  case MISDN_PROCEEDING:
7188  if (p->originator != ORG_AST && p->hold.state == MISDN_HOLD_IDLE) {
7190  }
7191 
7192  if (bc->need_disconnect) {
7194  }
7195  break;
7196  case MISDN_CONNECTED:
7197  /* Alerting or Disconnect */
7198  if (bc->nt && p->hold.state == MISDN_HOLD_IDLE) {
7199  start_bc_tones(p);
7202  }
7203  if (bc->need_disconnect) {
7205  }
7206  break;
7207  case MISDN_DISCONNECTED:
7208  if (bc->need_release) {
7210  }
7211  break;
7212 
7213  case MISDN_CLEANING:
7214  ast_mutex_unlock(&release_lock);
7215  chan_list_unref(p, "Release ast_channel reference");
7216  return 0;
7217 
7218  case MISDN_BUSY:
7219  break;
7220  default:
7221  if (bc->nt) {
7222  bc->out_cause = -1;
7223  if (bc->need_release) {
7225  }
7226  } else {
7227  if (bc->need_disconnect) {
7229  }
7230  }
7231  break;
7232  }
7233 
7234  p->state = MISDN_CLEANING;
7235  chan_misdn_log(3, bc->port, " --> Channel: %s hungup new state:%s\n", ast->name,
7236  misdn_get_ch_state(p));
7237 
7238  ast_mutex_unlock(&release_lock);
7239  chan_list_unref(p, "Release ast_channel reference");
7240  return 0;
7241 }
7242 
7243 
7244 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
7245 {
7246  struct ast_frame *f;
7247 
7248  if (tmp->dsp) {
7249  f = ast_dsp_process(tmp->ast, tmp->dsp, frame);
7250  } else {
7251  chan_misdn_log(0, tmp->bc->port, "No DSP-Path found\n");
7252  return NULL;
7253  }
7254 
7255  if (!f || (f->frametype != AST_FRAME_DTMF)) {
7256  return f;
7257  }
7258 
7259  ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass.integer);
7260 
7261  if (tmp->faxdetect && (f->subclass.integer == 'f')) {
7262  /* Fax tone -- Handle and return NULL */
7263  if (!tmp->faxhandled) {
7264  struct ast_channel *ast = tmp->ast;
7265  tmp->faxhandled++;
7266  chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
7267  tmp->bc->rxgain = 0;
7268  isdn_lib_update_rxgain(tmp->bc);
7269  tmp->bc->txgain = 0;
7270  isdn_lib_update_txgain(tmp->bc);
7271 #ifdef MISDN_1_2
7272  *tmp->bc->pipeline = 0;
7273 #else
7274  tmp->bc->ec_enable = 0;
7275 #endif
7276  isdn_lib_update_ec(tmp->bc);
7277  isdn_lib_stop_dtmf(tmp->bc);
7278  switch (tmp->faxdetect) {
7279  case 1:
7280  if (strcmp(ast->exten, "fax")) {
7281  char *context;
7282  char context_tmp[BUFFERSIZE];
7283  misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
7284  context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
7285  if (ast_exists_extension(ast, context, "fax", 1,
7286  S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
7287  ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
7288  /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7289  pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
7290  if (ast_async_goto(ast, context, "fax", 1)) {
7291  ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
7292  }
7293  } else {
7294  ast_log(LOG_NOTICE, "Fax detected but no fax extension, context:%s exten:%s\n", context, ast->exten);
7295  }
7296  } else {
7297  ast_debug(1, "Already in a fax extension, not redirecting\n");
7298  }
7299  break;
7300  case 2:
7301  ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
7302  break;
7303  default:
7304  break;
7305  }
7306  } else {
7307  ast_debug(1, "Fax already handled\n");
7308  }
7309  }
7310 
7311  if (tmp->ast_dsp && (f->subclass.integer != 'f')) {
7312  chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass.integer);
7313  }
7314 
7315  return f;
7316 }
7317 
7318 
7319 static struct ast_frame *misdn_read(struct ast_channel *ast)
7320 {
7321  struct chan_list *tmp;
7322  int len, t;
7323  struct pollfd pfd = { .fd = -1, .events = POLLIN };
7324 
7325  if (!ast) {
7326  chan_misdn_log(1, 0, "misdn_read called without ast\n");
7327  return NULL;
7328  }
7329  if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
7330  chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
7331  return NULL;
7332  }
7333 
7334  if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
7335  chan_misdn_log(1, 0, "misdn_read called without bc\n");
7336  return NULL;
7337  }
7338 
7339  pfd.fd = tmp->pipe[0];
7340  t = ast_poll(&pfd, 1, 20);
7341 
7342  if (t < 0) {
7343  chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
7344  return NULL;
7345  }
7346 
7347  if (!t) {
7348  chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
7349  len = 160;
7350  } else if (pfd.revents & POLLIN) {
7351  len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
7352 
7353  if (len <= 0) {
7354  /* we hangup here, since our pipe is closed */
7355  chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
7356  return NULL;
7357  }
7358  } else {
7359  return NULL;
7360  }
7361 
7364  tmp->frame.datalen = len;
7365  tmp->frame.samples = len;
7366  tmp->frame.mallocd = 0;
7367  tmp->frame.offset = 0;
7368  tmp->frame.delivery = ast_tv(0, 0);
7369  tmp->frame.src = NULL;
7370  tmp->frame.data.ptr = tmp->ast_rd_buf;
7371 
7372  if (tmp->faxdetect && !tmp->faxhandled) {
7373  if (tmp->faxdetect_timeout) {
7374  if (ast_tvzero(tmp->faxdetect_tv)) {
7375  tmp->faxdetect_tv = ast_tvnow();
7376  chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
7377  return process_ast_dsp(tmp, &tmp->frame);
7378  } else {
7379  struct timeval tv_now = ast_tvnow();
7380  int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
7381  if (diff <= (tmp->faxdetect_timeout * 1000)) {
7382  chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
7383  return process_ast_dsp(tmp, &tmp->frame);
7384  } else {
7385  chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
7386  tmp->faxdetect = 0;
7387  return &tmp->frame;
7388  }
7389  }
7390  } else {
7391  chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
7392  return process_ast_dsp(tmp, &tmp->frame);
7393  }
7394  } else {
7395  if (tmp->ast_dsp) {
7396  return process_ast_dsp(tmp, &tmp->frame);
7397  } else {
7398  return &tmp->frame;
7399  }
7400  }
7401 }
7402 
7403 
7404 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
7405 {
7406  struct chan_list *ch;
7407 
7408  if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
7409  return -1;
7410  }
7411 
7412  if (ch->hold.state != MISDN_HOLD_IDLE) {
7413  chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
7414  return 0;
7415  }
7416 
7417  if (!ch->bc) {
7418  ast_log(LOG_WARNING, "private but no bc\n");
7419  return -1;
7420  }
7421 
7422  if (ch->notxtone) {
7423  chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
7424  return 0;
7425  }
7426 
7427 
7428  if (!frame->subclass.codec) {
7429  chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
7430  return 0;
7431  }
7432 
7433  if (!(frame->subclass.codec & prefformat)) {
7434  chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", ast_getformatname(frame->subclass.codec));
7435  return 0;
7436  }
7437 
7438 
7439  if (!frame->samples) {
7440  chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
7441 
7442  if (!strcmp(frame->src,"ast_prod")) {
7443  chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
7444 
7445  if (ch->ts) {
7446  chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
7448  }
7449  return 0;
7450  }
7451 
7452  return -1;
7453  }
7454 
7455  if (!ch->bc->addr) {
7456  chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
7457  return 0;
7458  }
7459 
7460 #ifdef MISDN_DEBUG
7461  {
7462  int i;
7463  int max = 5 > frame->samples ? frame->samples : 5;
7464 
7465  ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
7466 
7467  for (i = 0; i < max; i++) {
7468  ast_debug(1, "%2.2x ", ((char *) frame->data.ptr)[i]);
7469  }
7470  }
7471 #endif
7472 
7473  switch (ch->bc->bc_state) {
7474  case BCHAN_ACTIVATED:
7475  case BCHAN_BRIDGED:
7476  break;
7477  default:
7478  if (!ch->dropped_frame_cnt) {
7479  chan_misdn_log(5, ch->bc->port,
7480  "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",
7481  frame->samples, ch->bc->addr, ast->exten,
7482  S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
7483  misdn_get_ch_state(ch), ch->bc->bc_state, ch->bc->l3_id);
7484  }
7485 
7486  if (++ch->dropped_frame_cnt > 100) {
7487  ch->dropped_frame_cnt = 0;
7488  chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x dropped > 100 frames!\n", frame->samples, ch->bc->addr);
7489  }
7490 
7491  return 0;
7492  }
7493 
7494  chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
7495  if (!ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability)) {
7496  /* Buffered Transmit (triggered by read from isdn side)*/
7497  if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
7498  if (ch->bc->active) {
7499  cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
7500  }
7501  }
7502 
7503  } else {
7504  /* transmit without jitterbuffer */
7505  misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
7506  }
7507 
7508  return 0;
7509 }
7510 
7512  struct ast_channel *c1, int flags,
7513  struct ast_frame **fo,
7514  struct ast_channel **rc,
7515  int timeoutms)
7516 {
7517  struct chan_list *ch1, *ch2;
7518  struct ast_channel *carr[2], *who;
7519  int to = -1;
7520  struct ast_frame *f;
7521  int p1_b, p2_b;
7522  int bridging;
7523 
7524  ch1 = get_chan_by_ast(c0);
7525  if (!ch1) {
7526  return -1;
7527  }
7528  ch2 = get_chan_by_ast(c1);
7529  if (!ch2) {
7530  chan_list_unref(ch1, "Failed to find ch2");
7531  return -1;
7532  }
7533 
7534  carr[0] = c0;
7535  carr[1] = c1;
7536 
7537  misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
7538  misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
7539 
7540  if (! p1_b || ! p2_b) {
7541  ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
7542  chan_list_unref(ch1, "Bridge fallback ch1");
7543  chan_list_unref(ch2, "Bridge fallback ch2");
7544  return AST_BRIDGE_FAILED;
7545  }
7546 
7547  misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
7548  if (bridging) {
7549  /* trying to make a mISDN_dsp conference */
7550  chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
7551  misdn_lib_bridge(ch1->bc, ch2->bc);
7552  }
7553 
7554  ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
7555 
7556  chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between \"%s\" <%s> and \"%s\" <%s>\n",
7557  ch1->bc->caller.name,
7558  ch1->bc->caller.number,
7559  ch2->bc->caller.name,
7560  ch2->bc->caller.number);
7561 
7562  if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
7563  ch1->ignore_dtmf = 1;
7564  }
7565 
7566  if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
7567  ch2->ignore_dtmf = 1;
7568  }
7569 
7570  for (;/*ever*/;) {
7571  to = -1;
7572  who = ast_waitfor_n(carr, 2, &to);
7573 
7574  if (!who) {
7575  ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
7576  break;
7577  }
7578  f = ast_read(who);
7579 
7580  if (!f || f->frametype == AST_FRAME_CONTROL) {
7581  /* got hangup .. */
7582 
7583  if (!f) {
7584  chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
7585  } else {
7586  chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass.integer);
7587  }
7588 
7589  *fo = f;
7590  *rc = who;
7591  break;
7592  }
7593 
7594  if (f->frametype == AST_FRAME_DTMF) {
7595  chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass.integer, who->exten);
7596 
7597  *fo = f;
7598  *rc = who;
7599  break;
7600  }
7601 
7602 #if 0
7603  if (f->frametype == AST_FRAME_VOICE) {
7604  chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
7605 
7606  continue;
7607  }
7608 #endif
7609 
7610  ast_write((who == c0) ? c1 : c0, f);
7611  }
7612 
7613  chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
7614 
7615  misdn_lib_split_bridge(ch1->bc, ch2->bc);
7616 
7617  chan_list_unref(ch1, "Bridge complete ch1");
7618  chan_list_unref(ch2, "Bridge complete ch2");
7619  return AST_BRIDGE_COMPLETE;
7620 }
7621 
7622 /** AST INDICATIONS END **/
7623 
7624 static int dialtone_indicate(struct chan_list *cl)
7625 {
7626  struct ast_channel *ast = cl->ast;
7627  int nd = 0;
7628 
7629  if (!ast) {
7630  chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
7631  return -1;
7632  }
7633 
7634  misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
7635 
7636  if (nd) {
7637  chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
7638  return 0;
7639  }
7640 
7641  chan_misdn_log(3, cl->bc->port, " --> Dial\n");
7642 
7643  cl->ts = ast_get_indication_tone(ast->zone, "dial");
7644 
7645  if (cl->ts) {
7646  cl->notxtone = 0;
7647  cl->norxtone = 0;
7648  /* This prods us in misdn_write */
7649  ast_playtones_start(ast, 0, cl->ts->data, 0);
7650  }
7651 
7652  return 0;
7653 }
7654 
7655 static void hanguptone_indicate(struct chan_list *cl)
7656 {
7658 }
7659 
7660 static int stop_indicate(struct chan_list *cl)
7661 {
7662  struct ast_channel *ast = cl->ast;
7663 
7664  if (!ast) {
7665  chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
7666  return -1;
7667  }
7668 
7669  chan_misdn_log(3, cl->bc->port, " --> None\n");
7671  ast_playtones_stop(ast);
7672 
7673  if (cl->ts) {
7674  cl->ts = ast_tone_zone_sound_unref(cl->ts);
7675  }
7676 
7677  return 0;
7678 }
7679 
7680 
7681 static int start_bc_tones(struct chan_list* cl)
7682 {
7684  cl->notxtone = 0;
7685  cl->norxtone = 0;
7686  return 0;
7687 }
7688 
7689 static int stop_bc_tones(struct chan_list *cl)
7690 {
7691  if (!cl) {
7692  return -1;
7693  }
7694 
7695  cl->notxtone = 1;
7696  cl->norxtone = 1;
7697 
7698  return 0;
7699 }
7700 
7701 /*!
7702  * \internal
7703  * \brief Destroy the chan_list object.
7704  *
7705  * \param obj chan_list object to destroy.
7706  *
7707  * \return Nothing
7708  */
7709 static void chan_list_destructor(void *obj)
7710 {
7711  struct chan_list *ch = obj;
7712 
7713 #if defined(AST_MISDN_ENHANCEMENTS)
7714  if (ch->peer) {
7715  ao2_ref(ch->peer, -1);
7716  ch->peer = NULL;
7717  }
7718 #endif /* AST_MISDN_ENHANCEMENTS */
7719 
7720  if (ch->dsp) {
7721  ast_dsp_free(ch->dsp);
7722  ch->dsp = NULL;
7723  }
7724 
7725  /* releasing jitterbuffer */
7726  if (ch->jb) {
7727  misdn_jb_destroy(ch->jb);
7728  ch->jb = NULL;
7729  }
7730 
7731  if (ch->overlap_dial) {
7732  if (ch->overlap_dial_task != -1) {
7734  ch->overlap_dial_task = -1;
7735  }
7737  }
7738 
7739  if (-1 < ch->pipe[0]) {
7740  close(ch->pipe[0]);
7741  }
7742  if (-1 < ch->pipe[1]) {
7743  close(ch->pipe[1]);
7744  }
7745 }
7746 
7747 /*! Returns a reference to the new chan_list. */
7748 static struct chan_list *chan_list_init(int orig)
7749 {
7750  struct chan_list *cl;
7751 
7752  cl = ao2_alloc(sizeof(*cl), chan_list_destructor);
7753  if (!cl) {
7754  chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
7755  return NULL;
7756  }
7757 
7758  cl->originator = orig;
7759  cl->need_queue_hangup = 1;
7760  cl->need_hangup = 1;
7761  cl->need_busy = 1;
7762  cl->overlap_dial_task = -1;
7763 #if defined(AST_MISDN_ENHANCEMENTS)
7764  cl->record_id = -1;
7765 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
7766  cl->pipe[0] = -1;
7767  cl->pipe[1] = -1;
7768 
7769  return cl;
7770 }
7771 
7772 static struct ast_channel *misdn_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
7773 {
7774  struct ast_channel *ast;
7775  char group[BUFFERSIZE + 1] = "";
7776  char dial_str[128];
7777  char *dest_cp;
7778  char *p = NULL;
7779  int channel = 0;
7780  int port = 0;
7781  struct misdn_bchannel *newbc = NULL;
7782  int dec = 0;
7783 #if defined(AST_MISDN_ENHANCEMENTS)
7784  int cc_retry_call = 0; /* TRUE if this is a call completion retry call */
7785  long record_id = -1;
7786  struct misdn_cc_record *cc_record;
7787  const char *err_msg;
7788 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
7789  struct chan_list *cl;
7790 
7792  AST_APP_ARG(intf); /* interface token */
7793  AST_APP_ARG(ext); /* extension token */
7794  AST_APP_ARG(opts); /* options token */
7795  );
7796 
7797  snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
7798 
7799  /*
7800  * data is ---v
7801  * Dial(mISDN/g:group_name[/extension[/options]])
7802  * Dial(mISDN/port[:preselected_channel][/extension[/options]])
7803  * Dial(mISDN/cc/cc-record-id)
7804  *
7805  * The dial extension could be empty if you are using MISDN_KEYPAD
7806  * to control ISDN provider features.
7807  */
7808  dest_cp = ast_strdupa(data);
7809  AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
7810  if (!args.ext) {
7811  args.ext = "";
7812  }
7813 
7814  if (!ast_strlen_zero(args.intf)) {
7815  if (args.intf[0] == 'g' && args.intf[1] == ':') {
7816  /* We make a group call lets checkout which ports are in my group */
7817  args.intf += 2;
7818  ast_copy_string(group, args.intf, sizeof(group));
7819  chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
7820 #if defined(AST_MISDN_ENHANCEMENTS)
7821  } else if (strcmp(args.intf, "cc") == 0) {
7822  cc_retry_call = 1;
7823 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
7824  } else if ((p = strchr(args.intf, ':'))) {
7825  /* we have a preselected channel */
7826  *p++ = 0;
7827  channel = atoi(p);
7828  port = atoi(args.intf);
7829  chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
7830  } else {
7831  port = atoi(args.intf);
7832  }
7833  } else {
7834  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
7835  return NULL;
7836  }
7837 
7838 #if defined(AST_MISDN_ENHANCEMENTS)
7839  if (cc_retry_call) {
7840  if (ast_strlen_zero(args.ext)) {
7841  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT cc-record-id, check extensions.conf\n", dial_str);
7842  return NULL;
7843  }
7844  if (!isdigit(*args.ext)) {
7845  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) cc-record-id must be a number.\n", dial_str);
7846  return NULL;
7847  }
7848  record_id = atol(args.ext);
7849 
7850  AST_LIST_LOCK(&misdn_cc_records_db);
7851  cc_record = misdn_cc_find_by_id(record_id);
7852  if (!cc_record) {
7853  AST_LIST_UNLOCK(&misdn_cc_records_db);
7854  err_msg = misdn_cc_record_not_found;
7855  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
7856  return NULL;
7857  }
7858  if (!cc_record->activated) {
7859  AST_LIST_UNLOCK(&misdn_cc_records_db);
7860  err_msg = "Call completion has not been activated";
7861  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
7862  return NULL;
7863  }
7864  port = cc_record->port;
7865  AST_LIST_UNLOCK(&misdn_cc_records_db);
7866  }
7867 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
7868 
7870  chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
7871  dec = 1;
7872  }
7873 
7874  if (!ast_strlen_zero(group)) {
7875  char cfg_group[BUFFERSIZE + 1];
7876  struct robin_list *rr = NULL;
7877 
7878  /* Group dial */
7879 
7881  chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
7882  rr = get_robin_position(group);
7883  }
7884 
7885  if (rr) {
7886  int port_start;
7887  int bchan_start;
7888  int port_up;
7889  int check;
7890  int maxbchans;
7891  int wraped = 0;
7892 
7893  if (!rr->port) {
7895  }
7896 
7897  if (!rr->channel) {
7898  rr->channel = 1;
7899  }
7900 
7901  bchan_start = rr->channel;
7902  port_start = rr->port;
7903  do {
7904  misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
7905  if (strcasecmp(cfg_group, group)) {
7906  wraped = 1;
7908  rr->channel = 1;
7909  continue;
7910  }
7911 
7912  misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
7913  port_up = misdn_lib_port_up(rr->port, check);
7914 
7915  if (!port_up) {
7916  chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
7918  rr->channel = 1;
7919  } else if (port_up < 0) {
7920  ast_log(LOG_WARNING, "This port (%d) is blocked\n", rr->port);
7922  rr->channel = 1;
7923  } else {
7924  chan_misdn_log(4, rr->port, "portup\n");
7925  maxbchans = misdn_lib_get_maxchans(rr->port);
7926 
7927  for (;rr->channel <= maxbchans;rr->channel++) {
7928  /* ive come full circle and can stop now */
7929  if (wraped && (rr->port == port_start) && (rr->channel == bchan_start)) {
7930  break;
7931  }
7932 
7933  chan_misdn_log(4, rr->port, "Checking channel %d\n", rr->channel);
7934 
7935  if ((newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0))) {
7936  chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
7937  rr->channel++;
7938  break;
7939  }
7940  }
7941  if (wraped && (rr->port == port_start) && (rr->channel <= bchan_start)) {
7942  break;
7943  } else if (!newbc || (rr->channel == maxbchans)) {
7945  rr->channel = 1;
7946  }
7947 
7948  }
7949  wraped = 1;
7950  } while (!newbc && (rr->port > 0));
7951  } else {
7952  for (port = misdn_cfg_get_next_port(0); port > 0;
7953  port = misdn_cfg_get_next_port(port)) {
7954  misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
7955 
7956  chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
7957  if (!strcasecmp(cfg_group, group)) {
7958  int port_up;
7959  int check;
7960 
7961  misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
7962  port_up = misdn_lib_port_up(port, check);
7963 
7964  chan_misdn_log(4, port, "portup:%d\n", port_up);
7965 
7966  if (port_up > 0) {
7967  newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
7968  if (newbc) {
7969  break;
7970  }
7971  }
7972  }
7973  }
7974  }
7975 
7976  /* Group dial failed ?*/
7977  if (!newbc) {
7979  "Could not Dial out on group '%s'.\n"
7980  "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
7981  "\tOr there was no free channel on none of the ports\n\n",
7982  group);
7983  return NULL;
7984  }
7985  } else {
7986  /* 'Normal' Port dial * Port dial */
7987  if (channel) {
7988  chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
7989  }
7990  newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
7991  if (!newbc) {
7992  ast_log(LOG_WARNING, "Could not create channel on port:%d for Dial(%s)\n", port, dial_str);
7993  return NULL;
7994  }
7995  }
7996 
7997  /* create ast_channel and link all the objects together */
7998  cl = chan_list_init(ORG_AST);
7999  if (!cl) {
8000  misdn_lib_release(newbc);
8001  ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
8002  return NULL;
8003  }
8004  cl->bc = newbc;
8005 
8006  ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, format, requestor ? requestor->linkedid : NULL, port, channel);
8007  if (!ast) {
8008  chan_list_unref(cl, "Failed to create a new channel");
8009  misdn_lib_release(newbc);
8010  ast_log(LOG_ERROR, "Could not create Asterisk channel for Dial(%s)\n", dial_str);
8011  return NULL;
8012  }
8013 
8014 #if defined(AST_MISDN_ENHANCEMENTS)
8015  cl->record_id = record_id;
8016 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
8017 
8018  /* register chan in local list */
8019  cl_queue_chan(cl);
8020 
8021  /* fill in the config into the objects */
8022  read_config(cl);
8023 
8024  /* important */
8025  cl->need_hangup = 0;
8026 
8027  chan_list_unref(cl, "Successful misdn_request()");
8028  return ast;
8029 }
8030 
8031 
8032 static int misdn_send_text(struct ast_channel *chan, const char *text)
8033 {
8034  struct chan_list *tmp = MISDN_ASTERISK_TECH_PVT(chan);
8035 
8036  if (tmp && tmp->bc) {
8037  ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
8039  } else {
8040  ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
8041  return -1;
8042  }
8043 
8044  return 0;
8045 }
8046 
8047 static struct ast_channel_tech misdn_tech = {
8048  .type = misdn_type,
8049  .description = "Channel driver for mISDN Support (Bri/Pri)",
8050  .capabilities = AST_FORMAT_ALAW ,
8051  .requester = misdn_request,
8052  .send_digit_begin = misdn_digit_begin,
8053  .send_digit_end = misdn_digit_end,
8054  .call = misdn_call,
8055  .bridge = misdn_bridge,
8056  .hangup = misdn_hangup,
8057  .answer = misdn_answer,
8058  .read = misdn_read,
8059  .write = misdn_write,
8060  .indicate = misdn_indication,
8061  .fixup = misdn_fixup,
8062  .send_text = misdn_send_text,
8063  .properties = 0,
8064 };
8065 
8067  .type = misdn_type,
8068  .description = "Channel driver for mISDN Support (Bri/Pri)",
8069  .capabilities = AST_FORMAT_ALAW ,
8070  .requester = misdn_request,
8071  .send_digit_begin = misdn_digit_begin,
8072  .send_digit_end = misdn_digit_end,
8073  .call = misdn_call,
8074  .hangup = misdn_hangup,
8075  .answer = misdn_answer,
8076  .read = misdn_read,
8077  .write = misdn_write,
8078  .indicate = misdn_indication,
8079  .fixup = misdn_fixup,
8080  .send_text = misdn_send_text,
8081  .properties = 0,
8082 };
8083 
8084 
8085 static int glob_channel = 0;
8086 
8087 static void update_name(struct ast_channel *tmp, int port, int c)
8088 {
8089  int chan_offset = 0;
8090  int tmp_port = misdn_cfg_get_next_port(0);
8091  char newname[255];
8092 
8093  for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
8094  if (tmp_port == port) {
8095  break;
8096  }
8097  chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
8098  }
8099  if (c < 0) {
8100  c = 0;
8101  }
8102 
8103  snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
8104  if (strncmp(tmp->name, newname, strlen(newname))) {
8105  snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
8106  ast_change_name(tmp, newname);
8107  chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
8108  }
8109 }
8110 
8111 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, const char *linkedid, int port, int c)
8112 {
8113  struct ast_channel *tmp;
8114  char *cid_name = NULL;
8115  char *cid_num = NULL;
8116  int chan_offset = 0;
8117  int tmp_port = misdn_cfg_get_next_port(0);
8118  int bridging;
8119 
8120  for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
8121  if (tmp_port == port) {
8122  break;
8123  }
8124  chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
8125  }
8126  if (c < 0) {
8127  c = 0;
8128  }
8129 
8130  if (callerid) {
8131  ast_callerid_parse(callerid, &cid_name, &cid_num);
8132  }
8133 
8134  tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", linkedid, 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
8135  if (tmp) {
8136  chan_misdn_log(2, port, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
8137 
8138  tmp->nativeformats = prefformat;
8139 
8140  tmp->readformat = format;
8141  tmp->rawreadformat = format;
8142  tmp->writeformat = format;
8143  tmp->rawwriteformat = format;
8144 
8145  /* Link the channel and private together */
8146  chan_list_ref(chlist, "Give a reference to ast_channel");
8147  MISDN_ASTERISK_TECH_PVT(tmp) = chlist;
8148  chlist->ast = tmp;
8149 
8150  misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
8151  tmp->tech = bridging ? &misdn_tech : &misdn_tech_wo_bridge;
8152 
8153  tmp->writeformat = format;
8154  tmp->readformat = format;
8155  tmp->priority = 1;
8156 
8157  if (exten) {
8158  ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
8159  } else {
8160  chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
8161  }
8162 
8163  if (!ast_strlen_zero(cid_num)) {
8164  /* Don't use ast_set_callerid() here because it will
8165  * generate a needless NewCallerID event */
8166  tmp->caller.ani.number.valid = 1;
8167  tmp->caller.ani.number.str = ast_strdup(cid_num);
8168  }
8169 
8170  if (pipe(chlist->pipe) < 0) {
8171  ast_log(LOG_ERROR, "Pipe failed\n");
8172  }
8173  ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
8174 
8175  tmp->rings = (state == AST_STATE_RING) ? 1 : 0;
8176 
8178  } else {
8179  chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
8180  }
8181 
8182  return tmp;
8183 }
8184 
8185 /*! Returns a reference to the found chan_list. */
8186 static struct chan_list *find_chan_by_bc(struct misdn_bchannel *bc)
8187 {
8188  struct chan_list *help;
8189 
8190  ast_mutex_lock(&cl_te_lock);
8191  for (help = cl_te; help; help = help->next) {
8192  if (help->bc == bc) {
8193  chan_list_ref(help, "Found chan_list by bc");
8194  ast_mutex_unlock(&cl_te_lock);
8195  return help;
8196  }
8197  }
8198  ast_mutex_unlock(&cl_te_lock);
8199 
8200  chan_misdn_log(6, bc->port,
8201  "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
8202  bc->dialed.number,
8203  bc->caller.name,
8204  bc->caller.number);
8205 
8206  return NULL;
8207 }
8208 
8209 /*! Returns a reference to the found chan_list. */
8210 static struct chan_list *find_hold_call(struct misdn_bchannel *bc)
8211 {
8212  struct chan_list *help;
8213 
8214  if (bc->pri) {
8215  return NULL;
8216  }
8217 
8218  chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d dialed:%s caller:\"%s\" <%s>\n",
8219  bc->channel,
8220  bc->dialed.number,
8221  bc->caller.name,
8222  bc->caller.number);
8223  ast_mutex_lock(&cl_te_lock);
8224  for (help = cl_te; help; help = help->next) {
8225  chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
8226  if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
8227  chan_list_ref(help, "Found chan_list hold call");
8228  ast_mutex_unlock(&cl_te_lock);
8229  return help;
8230  }
8231  }
8232  ast_mutex_unlock(&cl_te_lock);
8233  chan_misdn_log(6, bc->port,
8234  "$$$ find_hold_call: No channel found for dialed:%s caller:\"%s\" <%s>\n",
8235  bc->dialed.number,
8236  bc->caller.name,
8237  bc->caller.number);
8238 
8239  return NULL;
8240 }
8241 
8242 
8243 /*! Returns a reference to the found chan_list. */
8244 static struct chan_list *find_hold_call_l3(unsigned long l3_id)
8245 {
8246  struct chan_list *help;
8247 
8248  ast_mutex_lock(&cl_te_lock);
8249  for (help = cl_te; help; help = help->next) {
8250  if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
8251  chan_list_ref(help, "Found chan_list hold call l3");
8252  ast_mutex_unlock(&cl_te_lock);
8253  return help;
8254  }
8255  }
8256  ast_mutex_unlock(&cl_te_lock);
8257 
8258  return NULL;
8259 }
8260 
8261 #define TRANSFER_ON_HELD_CALL_HANGUP 1
8262 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
8263 /*!
8264  * \internal
8265  * \brief Find a suitable active call to go with a held call so we could try a transfer.
8266  *
8267  * \param bc B channel record.
8268  *
8269  * \return Found call record or NULL.
8270  *
8271  * \note Returns a reference to the found chan_list.
8272  *
8273  * \note There could be a possibility where we find the wrong active call to transfer.
8274  * This concern is mitigated by the fact that there could be at most one other call
8275  * on a PTMP BRI link to another device. Maybe the l3_id could help in locating an
8276  * active call on the same TEI?
8277  */
8279 {
8280  struct chan_list *list;
8281 
8282  ast_mutex_lock(&cl_te_lock);
8283  for (list = cl_te; list; list = list->next) {
8284  if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
8285  && list->ast) {
8286  switch (list->state) {
8287  case MISDN_PROCEEDING:
8288  case MISDN_PROGRESS:
8289  case MISDN_ALERTING:
8290  case MISDN_CONNECTED:
8291  chan_list_ref(list, "Found chan_list hold active call");
8292  ast_mutex_unlock(&cl_te_lock);
8293  return list;
8294  default:
8295  break;
8296  }
8297  }
8298  }
8299  ast_mutex_unlock(&cl_te_lock);
8300  return NULL;
8301 }
8302 #endif /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
8303 
8304 static void cl_queue_chan(struct chan_list *chan)
8305 {
8306  chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
8307 
8308  chan_list_ref(chan, "Adding chan_list to list");
8309  ast_mutex_lock(&cl_te_lock);
8310  chan->next = NULL;
8311  if (!cl_te) {
8312  /* List is empty, make head of list. */
8313  cl_te = chan;
8314  } else {
8315  struct chan_list *help;
8316 
8317  /* Put at end of list. */
8318  for (help = cl_te; help->next; help = help->next) {
8319  }
8320  help->next = chan;
8321  }
8322  ast_mutex_unlock(&cl_te_lock);
8323 }
8324 
8325 static int cl_dequeue_chan(struct chan_list *chan)
8326 {
8327  int found_it;
8328  struct chan_list *help;
8329 
8330  ast_mutex_lock(&cl_te_lock);
8331  if (!cl_te) {
8332  /* List is empty. */
8333  ast_mutex_unlock(&cl_te_lock);
8334  return 0;
8335  }
8336 
8337  if (cl_te == chan) {
8338  /* What we want is the head of the list. */
8339  cl_te = cl_te->next;
8340  ast_mutex_unlock(&cl_te_lock);
8341  chan_list_unref(chan, "Removed chan_list from list head");
8342  return 1;
8343  }
8344 
8345  found_it = 0;
8346  for (help = cl_te; help->next; help = help->next) {
8347  if (help->next == chan) {
8348  /* Found it in the list. */
8349  help->next = help->next->next;
8350  found_it = 1;
8351  break;
8352  }
8353  }
8354 
8355  ast_mutex_unlock(&cl_te_lock);
8356  if (found_it) {
8357  chan_list_unref(chan, "Removed chan_list from list");
8358  }
8359  return found_it;
8360 }
8361 
8362 /** Channel Queue End **/
8363 
8364 
8365 static int pbx_start_chan(struct chan_list *ch)
8366 {
8367  int ret = ast_pbx_start(ch->ast);
8368 
8369  ch->need_hangup = (ret >= 0) ? 0 : 1;
8370 
8371  return ret;
8372 }
8373 
8374 static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
8375 {
8376  int port = bc->port;
8377 
8378  if (!ch) {
8379  cb_log(1, port, "Cannot hangup chan, no ch\n");
8380  return;
8381  }
8382 
8383  cb_log(5, port, "hangup_chan called\n");
8384 
8385  if (ch->need_hangup) {
8386  cb_log(2, port, " --> hangup\n");
8387  ch->need_hangup = 0;
8388  ch->need_queue_hangup = 0;
8389  if (ch->ast && send_cause2ast(ch->ast, bc, ch)) {
8390  ast_hangup(ch->ast);
8391  }
8392  return;
8393  }
8394 
8395  if (!ch->need_queue_hangup) {
8396  cb_log(2, port, " --> No need to queue hangup\n");
8397  return;
8398  }
8399 
8400  ch->need_queue_hangup = 0;
8401  if (ch->ast) {
8402  if (send_cause2ast(ch->ast, bc, ch)) {
8404  cb_log(2, port, " --> queue_hangup\n");
8405  }
8406  } else {
8407  cb_log(1, port, "Cannot hangup chan, no ast\n");
8408  }
8409 }
8410 
8411 /*!
8412  * \internal
8413  * \brief ISDN asked us to release channel, pendant to misdn_hangup.
8414  *
8415  * \param ch Call channel record to release.
8416  * \param bc Current B channel record associated with ch.
8417  *
8418  * \return Nothing
8419  *
8420  * \note The only valid thing to do with ch after calling is to chan_list_unref(ch, "").
8421  */
8422 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
8423 {
8424  struct ast_channel *ast;
8425 
8426  chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
8427 
8428  ast_mutex_lock(&release_lock);
8429  for (;;) {
8430  ast = ch->ast;
8431  if (!ast || !ast_channel_trylock(ast)) {
8432  break;
8433  }
8434  DEADLOCK_AVOIDANCE(&release_lock);
8435  }
8436  if (!cl_dequeue_chan(ch)) {
8437  /* Someone already released it. */
8438  if (ast) {
8439  ast_channel_unlock(ast);
8440  }
8441  ast_mutex_unlock(&release_lock);
8442  return;
8443  }
8444  ch->state = MISDN_CLEANING;
8445  ch->ast = NULL;
8446  if (ast) {
8447  struct chan_list *ast_ch;
8448 
8449  ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
8450  MISDN_ASTERISK_TECH_PVT(ast) = NULL;
8451  chan_misdn_log(1, bc->port,
8452  "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n",
8453  bc->pid,
8454  ast->context,
8455  ast->exten,
8456  S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
8457  S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""));
8458 
8459  if (ast->_state != AST_STATE_RESERVED) {
8460  chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
8462  }
8463  ast_channel_unlock(ast);
8464  if (ast_ch) {
8465  chan_list_unref(ast_ch, "Release ast_channel reference.");
8466  }
8467  }
8468 
8469  if (ch->originator == ORG_AST) {
8470  --misdn_out_calls[bc->port];
8471  } else {
8472  --misdn_in_calls[bc->port];
8473  }
8474 
8475  ast_mutex_unlock(&release_lock);
8476 }
8477 
8478 /*!
8479  * \internal
8480  * \brief Do everything in release_chan() that makes sense without a bc.
8481  *
8482  * \param ch Call channel record to release.
8483  *
8484  * \return Nothing
8485  *
8486  * \note The only valid thing to do with ch after calling is to chan_list_unref(ch, "").
8487  */
8488 static void release_chan_early(struct chan_list *ch)
8489 {
8490  struct ast_channel *ast;
8491 
8492  ast_mutex_lock(&release_lock);
8493  for (;;) {
8494  ast = ch->ast;
8495  if (!ast || !ast_channel_trylock(ast)) {
8496  break;
8497  }
8498  DEADLOCK_AVOIDANCE(&release_lock);
8499  }
8500  if (!cl_dequeue_chan(ch)) {
8501  /* Someone already released it. */
8502  if (ast) {
8503  ast_channel_unlock(ast);
8504  }
8505  ast_mutex_unlock(&release_lock);
8506  return;
8507  }
8508  ch->state = MISDN_CLEANING;
8509  ch->ast = NULL;
8510  if (ast) {
8511  struct chan_list *ast_ch;
8512 
8513  ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
8514  MISDN_ASTERISK_TECH_PVT(ast) = NULL;
8515 
8516  if (ast->_state != AST_STATE_RESERVED) {
8518  }
8519  ast_channel_unlock(ast);
8520  if (ast_ch) {
8521  chan_list_unref(ast_ch, "Release ast_channel reference.");
8522  }
8523  }
8524 
8525  if (ch->hold.state != MISDN_HOLD_IDLE) {
8526  if (ch->originator == ORG_AST) {
8527  --misdn_out_calls[ch->hold.port];
8528  } else {
8529  --misdn_in_calls[ch->hold.port];
8530  }
8531  }
8532 
8533  ast_mutex_unlock(&release_lock);
8534 }
8535 
8536 /*!
8537  * \internal
8538  * \brief Attempt to transfer the active channel party to the held channel party.
8539  *
8540  * \param active_ch Channel currently connected.
8541  * \param held_ch Channel currently on hold.
8542  *
8543  * \retval 0 on success.
8544  * \retval -1 on error.
8545  */
8546 static int misdn_attempt_transfer(struct chan_list *active_ch, struct chan_list *held_ch)
8547 {
8548  int retval;
8549  struct ast_channel *target;
8550  struct ast_channel *transferee;
8551  struct ast_party_connected_line target_colp;
8552  struct ast_party_connected_line transferee_colp;
8553 
8554  switch (active_ch->state) {
8555  case MISDN_PROCEEDING:
8556  case MISDN_PROGRESS:
8557  case MISDN_ALERTING:
8558  case MISDN_CONNECTED:
8559  break;
8560  default:
8561  return -1;
8562  }
8563 
8564  ast_channel_lock(held_ch->ast);
8565  while (ast_channel_trylock(active_ch->ast)) {
8566  CHANNEL_DEADLOCK_AVOIDANCE(held_ch->ast);
8567  }
8568 
8569  transferee = ast_bridged_channel(held_ch->ast);
8570  if (!transferee) {
8571  /*
8572  * Could not transfer. Held channel is not bridged anymore.
8573  * Held party probably got tired of waiting and hung up.
8574  */
8575  ast_channel_unlock(held_ch->ast);
8576  ast_channel_unlock(active_ch->ast);
8577  return -1;
8578  }
8579 
8580  target = active_ch->ast;
8581  chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
8582  held_ch->ast->name, target->name);
8583 
8584  ast_party_connected_line_init(&target_colp);
8585  ast_party_connected_line_copy(&target_colp, &target->connected);
8586  ast_party_connected_line_init(&transferee_colp);
8587  ast_party_connected_line_copy(&transferee_colp, &held_ch->ast->connected);
8588  held_ch->hold.state = MISDN_HOLD_TRANSFER;
8589 
8590  /*
8591  * Before starting a masquerade, all channel and pvt locks must
8592  * be unlocked. Any recursive channel locks held before
8593  * ast_channel_transfer_masquerade() invalidates deadlock
8594  * avoidance. Since we are unlocking both the pvt and its owner
8595  * channel it is possible for "target" and "transferee" to be
8596  * destroyed by their pbx threads. To prevent this we must give
8597  * "target" and "transferee" a reference before any unlocking
8598  * takes place.
8599  */
8600  ao2_ref(target, +1);
8601  ao2_ref(transferee, +1);
8602  ast_channel_unlock(held_ch->ast);
8603  ast_channel_unlock(active_ch->ast);
8604 
8605  /* Setup transfer masquerade. */
8606  retval = ast_channel_transfer_masquerade(target, &target_colp, 0,
8607  transferee, &transferee_colp, 1);
8608 
8609  ast_party_connected_line_free(&target_colp);
8610  ast_party_connected_line_free(&transferee_colp);
8611  ao2_ref(target, -1);
8612  ao2_ref(transferee, -1);
8613  return retval;
8614 }
8615 
8616 
8617 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
8618 {
8619  char *predial;
8620  struct ast_frame fr;
8621 
8622  predial = ast_strdupa(ast->exten);
8623 
8624  ch->state = MISDN_DIALING;
8625 
8626  if (!ch->noautorespond_on_setup) {
8627  if (bc->nt) {
8629  } else {
8630  if (misdn_lib_is_ptp(bc->port)) {
8632  } else {
8634  }
8635  }
8636  } else {
8638  }
8639 
8640  chan_misdn_log(1, bc->port,
8641  "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
8642  ast->context,
8643  ast->exten,
8644  (ast->caller.id.name.valid && ast->caller.id.name.str)
8645  ? ast->caller.id.name.str : "",
8646  (ast->caller.id.number.valid && ast->caller.id.number.str)
8647  ? ast->caller.id.number.str : "");
8648 
8649  strcpy(ast->exten, "s");
8650 
8651  if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->caller.number) || pbx_start_chan(ch) < 0) {
8652  ast = NULL;
8654  hangup_chan(ch, bc);
8655  hanguptone_indicate(ch);
8656 
8658  }
8659 
8660 
8661  while (!ast_strlen_zero(predial)) {
8663  fr.subclass.integer = *predial;
8664  fr.src = NULL;
8665  fr.data.ptr = NULL;
8666  fr.datalen = 0;
8667  fr.samples = 0;
8668  fr.mallocd = 0;
8669  fr.offset = 0;
8670  fr.delivery = ast_tv(0,0);
8671 
8672  if (ch->ast && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
8673  ast_queue_frame(ch->ast, &fr);
8674  }
8675  predial++;
8676  }
8677 }
8678 
8679 /*!
8680  * \retval -1 if can hangup after calling.
8681  * \retval 0 if cannot hangup after calling.
8682  */
8683 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
8684 {
8685  int can_hangup;
8686 
8687  if (!ast) {
8688  chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
8689  return 0;
8690  }
8691  if (!bc) {
8692  chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
8693  return 0;
8694  }
8695  if (!ch) {
8696  chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
8697  return 0;
8698  }
8699 
8700  ast->hangupcause = bc->cause;
8701 
8702  can_hangup = -1;
8703  switch (bc->cause) {
8704  case AST_CAUSE_UNALLOCATED:
8707  case 4: /* Send special information tone */
8710  /* Congestion Cases */
8711  /*
8712  * Not Queueing the Congestion anymore, since we want to hear
8713  * the inband message
8714  *
8715  chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
8716  ch->state = MISDN_BUSY;
8717 
8718  ast_queue_control(ast, AST_CONTROL_CONGESTION);
8719  */
8720  break;
8721 
8723  case AST_CAUSE_USER_BUSY:
8724  ch->state = MISDN_BUSY;
8725 
8726  if (!ch->need_busy) {
8727  chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
8728  break;
8729  }
8730  ch->need_busy = 0;
8731 
8732  chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
8734 
8735  /* The BUSY is likely to cause a hangup or the user needs to hear it. */
8736  can_hangup = 0;
8737  break;
8738  }
8739  return can_hangup;
8740 }
8741 
8742 
8743 /*! \brief Import parameters from the dialplan environment variables */
8744 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
8745 {
8746  const char *tmp;
8747 
8748  ast_channel_lock(chan);
8749  tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
8750  if (tmp && (atoi(tmp) == 1)) {
8751  bc->sending_complete = 1;
8752  }
8753 
8754  tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
8755  if (tmp) {
8756  ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
8757  ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
8758  bc->uulen = strlen(bc->uu);
8759  }
8760 
8761  tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
8762  if (tmp) {
8763  ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
8764  }
8765  ast_channel_unlock(chan);
8766 }
8767 
8768 /*! \brief Export parameters to the dialplan environment variables */
8769 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
8770 {
8771  char tmp[32];
8772 
8773  /*
8774  * The only use for MISDN_PID is if there is a problem and you
8775  * have to use the "misdn restart pid" CLI command. Otherwise,
8776  * the pid is not used by anyone. The internal use of MISDN_PID
8777  * has been deleted.
8778  */
8779  chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
8780  snprintf(tmp, sizeof(tmp), "%d", bc->pid);
8781  pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
8782 
8783  if (bc->sending_complete) {
8784  snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
8785  pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
8786  }
8787 
8788  if (bc->urate) {
8789  snprintf(tmp, sizeof(tmp), "%d", bc->urate);
8790  pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
8791  }
8792 
8793  if (bc->uulen) {
8794  pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
8795  }
8796 
8797  if (!ast_strlen_zero(bc->keypad)) {
8798  pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
8799  }
8800 }
8801 
8802 int add_in_calls(int port)
8803 {
8804  int max_in_calls;
8805 
8806  misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
8807  misdn_in_calls[port]++;
8808 
8809  if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
8810  ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
8811  return misdn_in_calls[port] - max_in_calls;
8812  }
8813 
8814  return 0;
8815 }
8816 
8817 int add_out_calls(int port)
8818 {
8819  int max_out_calls;
8820 
8821  misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
8822 
8823  if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
8824  ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
8825  return (misdn_out_calls[port] + 1) - max_out_calls;
8826  }
8827 
8828  misdn_out_calls[port]++;
8829 
8830  return 0;
8831 }
8832 
8833 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
8834 {
8835  if (pbx_start_chan(ch) < 0) {
8836  hangup_chan(ch, bc);
8837  chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
8838  if (bc->nt) {
8839  hanguptone_indicate(ch);
8841  } else {
8843  }
8844  }
8845 }
8846 
8847 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
8848 {
8849  ch->state = MISDN_WAITING4DIGS;
8851  if (bc->nt && !bc->dialed.number[0]) {
8852  dialtone_indicate(ch);
8853  }
8854 }
8855 
8856 #if defined(AST_MISDN_ENHANCEMENTS)
8857 /*!
8858  * \internal
8859  * \brief Handle the FACILITY CCBSStatusRequest message.
8860  *
8861  * \param port Logical port number.
8862  * \param facility Facility ie contents.
8863  *
8864  * \return Nothing
8865  */
8866 static void misdn_cc_handle_ccbs_status_request(int port, const struct FacParm *facility)
8867 {
8868  struct misdn_cc_record *cc_record;
8869  struct misdn_bchannel dummy;
8870 
8871  switch (facility->u.CCBSStatusRequest.ComponentType) {
8872  case FacComponent_Invoke:
8873  /* Build message */
8874  misdn_make_dummy(&dummy, port, 0, misdn_lib_port_is_nt(port), 0);
8875  dummy.fac_out.Function = Fac_CCBSStatusRequest;
8876  dummy.fac_out.u.CCBSStatusRequest.InvokeID = facility->u.CCBSStatusRequest.InvokeID;
8877  dummy.fac_out.u.CCBSStatusRequest.ComponentType = FacComponent_Result;
8878 
8879  /* Answer User-A free question */
8880  AST_LIST_LOCK(&misdn_cc_records_db);
8881  cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSStatusRequest.Component.Invoke.CCBSReference);
8882  if (cc_record) {
8883  dummy.fac_out.u.CCBSStatusRequest.Component.Result.Free = cc_record->party_a_free;
8884  } else {
8885  /* No record so say User-A is free */
8886  dummy.fac_out.u.CCBSStatusRequest.Component.Result.Free = 1;
8887  }
8888  AST_LIST_UNLOCK(&misdn_cc_records_db);
8889 
8890  /* Send message */
8891  print_facility(&dummy.fac_out, &dummy);
8893  break;
8894 
8895  default:
8896  chan_misdn_log(0, port, " --> not yet handled: facility type:0x%04X\n", facility->Function);
8897  break;
8898  }
8899 }
8900 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
8901 
8902 #if defined(AST_MISDN_ENHANCEMENTS)
8903 /*!
8904  * \internal
8905  * \brief Start a PBX to notify that User-B is available.
8906  *
8907  * \param record_id Call completion record ID
8908  * \param notify Dialplan location to start processing.
8909  *
8910  * \return Nothing
8911  */
8912 static void misdn_cc_pbx_notify(long record_id, const struct misdn_cc_notify *notify)
8913 {
8914  struct ast_channel *chan;
8915  char id_str[32];
8916 
8917  static unsigned short sequence = 0;
8918 
8919  /* Create a channel to notify with */
8920  snprintf(id_str, sizeof(id_str), "%ld", record_id);
8921  chan = ast_channel_alloc(0, AST_STATE_DOWN, id_str, NULL, NULL,
8922  notify->exten, notify->context, NULL, 0,
8923  "mISDN-CC/%ld-%X", record_id, (unsigned) ++sequence);
8924  if (!chan) {
8925  ast_log(LOG_ERROR, "Unable to allocate channel!\n");
8926  return;
8927  }
8928  chan->priority = notify->priority;
8929  ast_free(chan->dialed.number.str);
8930  chan->dialed.number.str = ast_strdup(notify->exten);
8931 
8932  if (ast_pbx_start(chan)) {
8933  ast_log(LOG_WARNING, "Unable to start pbx channel %s!\n", chan->name);
8934  ast_channel_release(chan);
8935  } else {
8936  ast_verb(1, "Started pbx for call completion notify channel %s\n", chan->name);
8937  }
8938 }
8939 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
8940 
8941 #if defined(AST_MISDN_ENHANCEMENTS)
8942 /*!
8943  * \internal
8944  * \brief Handle the FACILITY CCBS_T_RemoteUserFree message.
8945  *
8946  * \param bc B channel control structure message came in on
8947  *
8948  * \return Nothing
8949  */
8950 static void misdn_cc_handle_T_remote_user_free(struct misdn_bchannel *bc)
8951 {
8952  struct misdn_cc_record *cc_record;
8953  struct misdn_cc_notify notify;
8954  long record_id;
8955 
8956  AST_LIST_LOCK(&misdn_cc_records_db);
8957  cc_record = misdn_cc_find_by_bc(bc);
8958  if (cc_record) {
8959  if (cc_record->party_a_free) {
8960  notify = cc_record->remote_user_free;
8961  } else {
8962  /* Send CCBS_T_Suspend message */
8963  bc->fac_out.Function = Fac_CCBS_T_Suspend;
8964  bc->fac_out.u.CCBS_T_Suspend.InvokeID = ++misdn_invoke_id;
8965  print_facility(&bc->fac_out, bc);
8967 
8968  notify = cc_record->b_free;
8969  }
8970  record_id = cc_record->record_id;
8971  AST_LIST_UNLOCK(&misdn_cc_records_db);
8972  if (notify.context[0]) {
8973  /* Party A is free or B-Free notify has been setup. */
8974  misdn_cc_pbx_notify(record_id, &notify);
8975  }
8976  } else {
8977  AST_LIST_UNLOCK(&misdn_cc_records_db);
8978  }
8979 }
8980 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
8981 
8982 #if defined(AST_MISDN_ENHANCEMENTS)
8983 /*!
8984  * \internal
8985  * \brief Handle the FACILITY CCBSRemoteUserFree message.
8986  *
8987  * \param port Logical port number.
8988  * \param facility Facility ie contents.
8989  *
8990  * \return Nothing
8991  */
8992 static void misdn_cc_handle_remote_user_free(int port, const struct FacParm *facility)
8993 {
8994  struct misdn_cc_record *cc_record;
8995  struct misdn_cc_notify notify;
8996  long record_id;
8997 
8998  AST_LIST_LOCK(&misdn_cc_records_db);
8999  cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSRemoteUserFree.CCBSReference);
9000  if (cc_record) {
9001  notify = cc_record->remote_user_free;
9002  record_id = cc_record->record_id;
9003  AST_LIST_UNLOCK(&misdn_cc_records_db);
9004  misdn_cc_pbx_notify(record_id, &notify);
9005  } else {
9006  AST_LIST_UNLOCK(&misdn_cc_records_db);
9007  }
9008 }
9009 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9010 
9011 #if defined(AST_MISDN_ENHANCEMENTS)
9012 /*!
9013  * \internal
9014  * \brief Handle the FACILITY CCBSBFree message.
9015  *
9016  * \param port Logical port number.
9017  * \param facility Facility ie contents.
9018  *
9019  * \return Nothing
9020  */
9021 static void misdn_cc_handle_b_free(int port, const struct FacParm *facility)
9022 {
9023  struct misdn_cc_record *cc_record;
9024  struct misdn_cc_notify notify;
9025  long record_id;
9026 
9027  AST_LIST_LOCK(&misdn_cc_records_db);
9028  cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSBFree.CCBSReference);
9029  if (cc_record && cc_record->b_free.context[0]) {
9030  /* B-Free notify has been setup. */
9031  notify = cc_record->b_free;
9032  record_id = cc_record->record_id;
9033  AST_LIST_UNLOCK(&misdn_cc_records_db);
9034  misdn_cc_pbx_notify(record_id, &notify);
9035  } else {
9036  AST_LIST_UNLOCK(&misdn_cc_records_db);
9037  }
9038 }
9039 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9040 
9041 /*!
9042  * \internal
9043  * \brief Handle the incoming facility ie contents
9044  *
9045  * \param event Message type facility ie came in on
9046  * \param bc B channel control structure message came in on
9047  * \param ch Associated channel call record
9048  *
9049  * \return Nothing
9050  */
9051 static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel *bc, struct chan_list *ch)
9052 {
9053 #if defined(AST_MISDN_ENHANCEMENTS)
9054  const char *diagnostic_msg;
9055  struct misdn_cc_record *cc_record;
9056  char buf[32];
9057  struct misdn_party_id party_id;
9058  long new_record_id;
9059 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9060 
9061  print_facility(&bc->fac_in, bc);
9062  switch (bc->fac_in.Function) {
9063 #if defined(AST_MISDN_ENHANCEMENTS)
9064  case Fac_ActivationDiversion:
9065  switch (bc->fac_in.u.ActivationDiversion.ComponentType) {
9066  case FacComponent_Result:
9067  /* Positive ACK to activation */
9068  /* We don't handle this yet */
9069  break;
9070  default:
9071  chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
9072  bc->fac_in.Function);
9073  break;
9074  }
9075  break;
9076  case Fac_DeactivationDiversion:
9077  switch (bc->fac_in.u.DeactivationDiversion.ComponentType) {
9078  case FacComponent_Result:
9079  /* Positive ACK to deactivation */
9080  /* We don't handle this yet */
9081  break;
9082  default:
9083  chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
9084  bc->fac_in.Function);
9085  break;
9086  }
9087  break;
9088  case Fac_ActivationStatusNotificationDiv:
9089  /* Sent to other MSN numbers on the line when a user activates call forwarding. */
9090  /* Sent in the first call control message of an outgoing call from the served user. */
9091  /* We do not have anything to do for this message. */
9092  break;
9093  case Fac_DeactivationStatusNotificationDiv:
9094  /* Sent to other MSN numbers on the line when a user deactivates call forwarding. */
9095  /* We do not have anything to do for this message. */
9096  break;
9097 #if 0 /* We don't handle this yet */
9098  case Fac_InterrogationDiversion:
9099  /* We don't handle this yet */
9100  break;
9101  case Fac_InterrogateServedUserNumbers:
9102  /* We don't handle this yet */
9103  break;
9104 #endif /* We don't handle this yet */
9105  case Fac_DiversionInformation:
9106  /* Sent to the served user when a call is forwarded. */
9107  /* We do not have anything to do for this message. */
9108  break;
9109  case Fac_CallDeflection:
9110  if (ch && ch->ast) {
9111  switch (bc->fac_in.u.CallDeflection.ComponentType) {
9112  case FacComponent_Invoke:
9114  sizeof(bc->redirecting.from.number));
9115  bc->redirecting.from.name[0] = 0;
9118  bc->redirecting.from.screening = 0;/* Unscreened */
9119  if (bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
9121  bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser
9122  ? 0 /* Allowed */ : 1 /* Restricted */;
9123  } else {
9124  bc->redirecting.from.presentation = 0;/* Allowed */
9125  }
9126 
9127  /* Add configured prefix to the call deflection number */
9128  memset(&party_id, 0, sizeof(party_id));
9129  misdn_PartyNumber_extract(&party_id,
9130  &bc->fac_in.u.CallDeflection.Component.Invoke.Deflection.Party);
9132  party_id.number, sizeof(party_id.number));
9133  //party_id.presentation = 0;/* Allowed */
9134  //party_id.screening = 0;/* Unscreened */
9135  bc->redirecting.to = party_id;
9136 
9137  ++bc->redirecting.count;
9139 
9141  ast_string_field_set(ch->ast, call_forward, bc->redirecting.to.number);
9142 
9143  /* Send back positive ACK */
9144 #if 1
9145  /*
9146  * Since there are no return result arguments it must be a
9147  * generic result message. ETSI 300-196
9148  */
9149  bc->fac_out.Function = Fac_RESULT;
9150  bc->fac_out.u.RESULT.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
9151 #else
9152  bc->fac_out.Function = Fac_CallDeflection;
9153  bc->fac_out.u.CallDeflection.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
9154  bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Result;
9155 #endif
9156  print_facility(&bc->fac_out, bc);
9158 
9159  /* This line is BUSY to further attempts by this dialing attempt. */
9161  break;
9162 
9163  case FacComponent_Result:
9164  /* Positive ACK to call deflection */
9165  /*
9166  * Sent in DISCONNECT or FACILITY message depending upon network option.
9167  * It is in the FACILITY message if the call is still offered to the user
9168  * while trying to alert the deflected to party.
9169  */
9170  /* Ignore the ACK */
9171  break;
9172 
9173  default:
9174  break;
9175  }
9176  }
9177  break;
9178 #if 0 /* We don't handle this yet */
9179  case Fac_CallRerouteing:
9180  /* Private-Public ISDN interworking message */
9181  /* We don't handle this yet */
9182  break;
9183 #endif /* We don't handle this yet */
9184  case Fac_DivertingLegInformation1:
9185  /* Private-Public ISDN interworking message */
9186  bc->div_leg_3_rx_wanted = 0;
9187  if (ch && ch->ast) {
9188  bc->redirecting.reason =
9189  diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation1.DiversionReason);
9190  if (bc->fac_in.u.DivertingLegInformation1.DivertedToPresent) {
9191  misdn_PresentedNumberUnscreened_extract(&bc->redirecting.to,
9192  &bc->fac_in.u.DivertingLegInformation1.DivertedTo);
9193 
9194  /* Add configured prefix to redirecting.to.number */
9196  bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
9197  } else {
9198  bc->redirecting.to.number[0] = '\0';
9201  bc->redirecting.to.presentation = 1;/* restricted */
9202  bc->redirecting.to.screening = 0;/* unscreened */
9203  }
9205  bc->div_leg_3_rx_wanted = 1;
9206  }
9207  break;
9208  case Fac_DivertingLegInformation2:
9209  /* Private-Public ISDN interworking message */
9210  switch (event) {
9211  case EVENT_SETUP:
9212  /* Comes in on a SETUP with redirecting.from information */
9213  bc->div_leg_3_tx_pending = 1;
9214  if (ch && ch->ast) {
9215  /*
9216  * Setup the redirecting.to informtion so we can identify
9217  * if the user wants to manually supply the COLR for this
9218  * redirected to number if further redirects could happen.
9219  *
9220  * All the user needs to do is set the REDIRECTING(to-pres)
9221  * to the COLR and REDIRECTING(to-num) = ${EXTEN} to be safe
9222  * after determining that the incoming call was redirected by
9223  * checking if there is a REDIRECTING(from-num).
9224  */
9226  sizeof(bc->redirecting.to.number));
9229  bc->redirecting.to.presentation = 1;/* restricted */
9230  bc->redirecting.to.screening = 0;/* unscreened */
9231 
9232  bc->redirecting.reason =
9233  diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation2.DiversionReason);
9234  bc->redirecting.count = bc->fac_in.u.DivertingLegInformation2.DiversionCounter;
9235  if (bc->fac_in.u.DivertingLegInformation2.DivertingPresent) {
9236  /* This information is redundant if there was a redirecting ie in the SETUP. */
9237  misdn_PresentedNumberUnscreened_extract(&bc->redirecting.from,
9238  &bc->fac_in.u.DivertingLegInformation2.Diverting);
9239 
9240  /* Add configured prefix to redirecting.from.number */
9242  bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
9243  }
9244 #if 0
9245  if (bc->fac_in.u.DivertingLegInformation2.OriginalCalledPresent) {
9246  /* We have no place to put the OriginalCalled number */
9247  }
9248 #endif
9250  }
9251  break;
9252  default:
9253  chan_misdn_log(0, bc->port," --> Expected in a SETUP message: facility type:0x%04X\n",
9254  bc->fac_in.Function);
9255  break;
9256  }
9257  break;
9258  case Fac_DivertingLegInformation3:
9259  /* Private-Public ISDN interworking message */
9260  if (bc->div_leg_3_rx_wanted) {
9261  bc->div_leg_3_rx_wanted = 0;
9262 
9263  if (ch && ch->ast) {
9265  bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator
9269  }
9270  }
9271  break;
9272 
9273 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
9274 
9275  case Fac_CD:
9276  if (ch && ch->ast) {
9278  sizeof(bc->redirecting.from.number));
9279  bc->redirecting.from.name[0] = 0;
9282  bc->redirecting.from.screening = 0;/* Unscreened */
9284  bc->fac_in.u.CDeflection.PresentationAllowed
9285  ? 0 /* Allowed */ : 1 /* Restricted */;
9286 
9288  (char *) bc->fac_in.u.CDeflection.DeflectedToNumber,
9289  sizeof(bc->redirecting.to.number));
9290  bc->redirecting.to.name[0] = 0;
9293  bc->redirecting.to.presentation = 0;/* Allowed */
9294  bc->redirecting.to.screening = 0;/* Unscreened */
9295 
9296  ++bc->redirecting.count;
9298 
9300  ast_string_field_set(ch->ast, call_forward, bc->redirecting.to.number);
9301 
9303 
9304  /* This line is BUSY to further attempts by this dialing attempt. */
9306  }
9307  break;
9308 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
9309  case Fac_AOCDCurrency:
9310  if (ch && ch->ast) {
9311  bc->AOCDtype = Fac_AOCDCurrency;
9312  memcpy(&bc->AOCD.currency, &bc->fac_in.u.AOCDcur, sizeof(bc->AOCD.currency));
9313  bc->AOCD_need_export = 1;
9314  export_aoc_vars(ch->originator, ch->ast, bc);
9315  }
9316  break;
9317  case Fac_AOCDChargingUnit:
9318  if (ch && ch->ast) {
9319  bc->AOCDtype = Fac_AOCDChargingUnit;
9320  memcpy(&bc->AOCD.chargingUnit, &bc->fac_in.u.AOCDchu, sizeof(bc->AOCD.chargingUnit));
9321  bc->AOCD_need_export = 1;
9322  export_aoc_vars(ch->originator, ch->ast, bc);
9323  }
9324  break;
9325 #if defined(AST_MISDN_ENHANCEMENTS)
9326  case Fac_ERROR:
9327  diagnostic_msg = misdn_to_str_error_code(bc->fac_in.u.ERROR.errorValue);
9328  chan_misdn_log(1, bc->port, " --> Facility error code: %s\n", diagnostic_msg);
9329  switch (event) {
9330  case EVENT_DISCONNECT:
9331  case EVENT_RELEASE:
9333  /* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
9334  if (ch && ch->peer) {
9335  misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
9336  }
9337  break;
9338  default:
9339  break;
9340  }
9341  AST_LIST_LOCK(&misdn_cc_records_db);
9342  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.ERROR.invokeId);
9343  if (cc_record) {
9344  cc_record->outstanding_message = 0;
9345  cc_record->error_code = bc->fac_in.u.ERROR.errorValue;
9346  }
9347  AST_LIST_UNLOCK(&misdn_cc_records_db);
9348  break;
9349  case Fac_REJECT:
9350  diagnostic_msg = misdn_to_str_reject_code(bc->fac_in.u.REJECT.Code);
9351  chan_misdn_log(1, bc->port, " --> Facility reject code: %s\n", diagnostic_msg);
9352  switch (event) {
9353  case EVENT_DISCONNECT:
9354  case EVENT_RELEASE:
9356  /* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
9357  if (ch && ch->peer) {
9358  misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
9359  }
9360  break;
9361  default:
9362  break;
9363  }
9364  if (bc->fac_in.u.REJECT.InvokeIDPresent) {
9365  AST_LIST_LOCK(&misdn_cc_records_db);
9366  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.REJECT.InvokeID);
9367  if (cc_record) {
9368  cc_record->outstanding_message = 0;
9369  cc_record->reject_code = bc->fac_in.u.REJECT.Code;
9370  }
9371  AST_LIST_UNLOCK(&misdn_cc_records_db);
9372  }
9373  break;
9374  case Fac_RESULT:
9375  AST_LIST_LOCK(&misdn_cc_records_db);
9376  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.RESULT.InvokeID);
9377  if (cc_record) {
9378  cc_record->outstanding_message = 0;
9379  }
9380  AST_LIST_UNLOCK(&misdn_cc_records_db);
9381  break;
9382 #if 0 /* We don't handle this yet */
9383  case Fac_EctExecute:
9384  /* We don't handle this yet */
9385  break;
9386  case Fac_ExplicitEctExecute:
9387  /* We don't handle this yet */
9388  break;
9389  case Fac_EctLinkIdRequest:
9390  /* We don't handle this yet */
9391  break;
9392 #endif /* We don't handle this yet */
9393  case Fac_SubaddressTransfer:
9394  /* We do not have anything to do for this message since we do not handle subaddreses. */
9395  break;
9396  case Fac_RequestSubaddress:
9397  /*
9398  * We do not have anything to do for this message since we do not handle subaddreses.
9399  * However, we do care about some other ie's that should be present.
9400  */
9401  if (bc->redirecting.to_changed) {
9402  /* Add configured prefix to redirecting.to.number */
9404  bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
9405  }
9406  switch (bc->notify_description_code) {
9408  /* Notify ie was not present. */
9409  bc->redirecting.to_changed = 0;
9410  break;
9412  /*
9413  * It would be preferable to update the connected line information
9414  * only when the message callStatus is active. However, the
9415  * optional redirection number may not be present in the active
9416  * message if an alerting message were received earlier.
9417  *
9418  * The consequences if we wind up sending two updates is benign.
9419  * The other end will think that it got transferred twice.
9420  */
9421  if (!bc->redirecting.to_changed) {
9422  break;
9423  }
9424  bc->redirecting.to_changed = 0;
9425  if (!ch || !ch->ast) {
9426  break;
9427  }
9430  bc->incoming_cid_tag);
9431  break;
9433  if (!bc->redirecting.to_changed) {
9434  break;
9435  }
9436  bc->redirecting.to_changed = 0;
9437  if (!ch || !ch->ast) {
9438  break;
9439  }
9442  break;
9443  default:
9444  bc->redirecting.to_changed = 0;
9445  chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
9447  break;
9448  }
9450  break;
9451  case Fac_EctInform:
9452  /* Private-Public ISDN interworking message */
9453  if (ch && ch->ast && bc->fac_in.u.EctInform.RedirectionPresent) {
9454  /* Add configured prefix to the redirection number */
9455  memset(&party_id, 0, sizeof(party_id));
9456  misdn_PresentedNumberUnscreened_extract(&party_id,
9457  &bc->fac_in.u.EctInform.Redirection);
9459  party_id.number, sizeof(party_id.number));
9460 
9461  /*
9462  * It would be preferable to update the connected line information
9463  * only when the message callStatus is active. However, the
9464  * optional redirection number may not be present in the active
9465  * message if an alerting message were received earlier.
9466  *
9467  * The consequences if we wind up sending two updates is benign.
9468  * The other end will think that it got transferred twice.
9469  */
9470  misdn_update_remote_party(ch->ast, &party_id,
9471  (bc->fac_in.u.EctInform.Status == 0 /* alerting */)
9474  bc->incoming_cid_tag);
9475  }
9476  break;
9477 #if 0 /* We don't handle this yet */
9478  case Fac_EctLoopTest:
9479  /* The use of this message is unclear on how it works to detect loops. */
9480  /* We don't handle this yet */
9481  break;
9482 #endif /* We don't handle this yet */
9483  case Fac_CallInfoRetain:
9484  switch (event) {
9485  case EVENT_ALERTING:
9486  case EVENT_DISCONNECT:
9487  /* CCBS/CCNR is available */
9488  if (ch && ch->peer) {
9489  AST_LIST_LOCK(&misdn_cc_records_db);
9490  if (ch->record_id == -1) {
9491  cc_record = misdn_cc_new();
9492  } else {
9493  /*
9494  * We are doing a call-completion attempt
9495  * or the switch is sending us extra call-completion
9496  * availability indications (erroneously?).
9497  *
9498  * Assume that the network request retention option
9499  * is not on and that the current call-completion
9500  * request is disabled.
9501  */
9502  cc_record = misdn_cc_find_by_id(ch->record_id);
9503  if (cc_record) {
9504  if (cc_record->ptp && cc_record->mode.ptp.bc) {
9505  /*
9506  * What? We are getting mixed messages from the
9507  * switch. We are currently setup for
9508  * point-to-point. Now we are switching to
9509  * point-to-multipoint.
9510  *
9511  * Close the call-completion signaling link
9512  */
9513  cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
9514  cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
9515  misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
9516  }
9517 
9518  /*
9519  * Resetup the existing record for a possible new
9520  * call-completion request.
9521  */
9522  new_record_id = misdn_cc_record_id_new();
9523  if (new_record_id < 0) {
9524  /* Looks like we must keep the old id anyway. */
9525  } else {
9526  cc_record->record_id = new_record_id;
9527  ch->record_id = new_record_id;
9528  }
9529  cc_record->ptp = 0;
9530  cc_record->port = bc->port;
9531  memset(&cc_record->mode, 0, sizeof(cc_record->mode));
9532  cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
9533  cc_record->invoke_id = ++misdn_invoke_id;
9534  cc_record->activated = 0;
9535  cc_record->outstanding_message = 0;
9536  cc_record->activation_requested = 0;
9537  cc_record->error_code = FacError_None;
9538  cc_record->reject_code = FacReject_None;
9539  memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
9540  memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
9541  cc_record->time_created = time(NULL);
9542 
9543  cc_record = NULL;
9544  } else {
9545  /*
9546  * Where did the record go? We will have to recapture
9547  * the call setup information. Unfortunately, some
9548  * setup information may have been changed.
9549  */
9550  ch->record_id = -1;
9551  cc_record = misdn_cc_new();
9552  }
9553  }
9554  if (cc_record) {
9555  ch->record_id = cc_record->record_id;
9556  cc_record->ptp = 0;
9557  cc_record->port = bc->port;
9558  cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
9559 
9560  /* Record call information for possible call-completion attempt. */
9561  cc_record->redial.caller = bc->caller;
9562  cc_record->redial.dialed = bc->dialed;
9563  cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
9564  cc_record->redial.capability = bc->capability;
9565  cc_record->redial.hdlc = bc->hdlc;
9566  }
9567  AST_LIST_UNLOCK(&misdn_cc_records_db);
9568 
9569  /* Set MISDN_CC_RECORD_ID in original channel */
9570  if (ch->record_id != -1) {
9571  snprintf(buf, sizeof(buf), "%ld", ch->record_id);
9572  } else {
9573  buf[0] = 0;
9574  }
9575  misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
9576  }
9577  break;
9578  default:
9579  chan_misdn_log(0, bc->port,
9580  " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
9581  bc->fac_in.Function);
9582  break;
9583  }
9584  break;
9585  case Fac_CCBS_T_Call:
9586  case Fac_CCBSCall:
9587  switch (event) {
9588  case EVENT_SETUP:
9589  /*
9590  * This is a call completion retry call.
9591  * If we had anything to do we would do it here.
9592  */
9593  break;
9594  default:
9595  chan_misdn_log(0, bc->port, " --> Expected in a SETUP message: facility type:0x%04X\n",
9596  bc->fac_in.Function);
9597  break;
9598  }
9599  break;
9600  case Fac_CCBSDeactivate:
9601  switch (bc->fac_in.u.CCBSDeactivate.ComponentType) {
9602  case FacComponent_Result:
9603  AST_LIST_LOCK(&misdn_cc_records_db);
9604  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSDeactivate.InvokeID);
9605  if (cc_record) {
9606  cc_record->outstanding_message = 0;
9607  }
9608  AST_LIST_UNLOCK(&misdn_cc_records_db);
9609  break;
9610 
9611  default:
9612  chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
9613  bc->fac_in.Function);
9614  break;
9615  }
9616  break;
9617  case Fac_CCBSErase:
9618  AST_LIST_LOCK(&misdn_cc_records_db);
9619  cc_record = misdn_cc_find_by_reference(bc->port, bc->fac_in.u.CCBSErase.CCBSReference);
9620  if (cc_record) {
9621  misdn_cc_delete(cc_record);
9622  }
9623  AST_LIST_UNLOCK(&misdn_cc_records_db);
9624  break;
9625  case Fac_CCBSRemoteUserFree:
9626  misdn_cc_handle_remote_user_free(bc->port, &bc->fac_in);
9627  break;
9628  case Fac_CCBSBFree:
9629  misdn_cc_handle_b_free(bc->port, &bc->fac_in);
9630  break;
9631  case Fac_CCBSStatusRequest:
9632  misdn_cc_handle_ccbs_status_request(bc->port, &bc->fac_in);
9633  break;
9634  case Fac_EraseCallLinkageID:
9635  AST_LIST_LOCK(&misdn_cc_records_db);
9636  cc_record = misdn_cc_find_by_linkage(bc->port,
9637  bc->fac_in.u.EraseCallLinkageID.CallLinkageID);
9638  if (cc_record && !cc_record->activation_requested) {
9639  /*
9640  * The T-RETENTION timer expired before we requested
9641  * call completion activation. Call completion is no
9642  * longer available.
9643  */
9644  misdn_cc_delete(cc_record);
9645  }
9646  AST_LIST_UNLOCK(&misdn_cc_records_db);
9647  break;
9648  case Fac_CCBSStopAlerting:
9649  /* We do not have anything to do for this message. */
9650  break;
9651  case Fac_CCBSRequest:
9652  case Fac_CCNRRequest:
9653  switch (bc->fac_in.u.CCBSRequest.ComponentType) {
9654  case FacComponent_Result:
9655  AST_LIST_LOCK(&misdn_cc_records_db);
9656  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSRequest.InvokeID);
9657  if (cc_record && !cc_record->ptp) {
9658  cc_record->outstanding_message = 0;
9659  cc_record->activated = 1;
9660  cc_record->mode.ptmp.recall_mode = bc->fac_in.u.CCBSRequest.Component.Result.RecallMode;
9661  cc_record->mode.ptmp.reference_id = bc->fac_in.u.CCBSRequest.Component.Result.CCBSReference;
9662  }
9663  AST_LIST_UNLOCK(&misdn_cc_records_db);
9664  break;
9665 
9666  default:
9667  chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
9668  bc->fac_in.Function);
9669  break;
9670  }
9671  break;
9672 #if 0 /* We don't handle this yet */
9673  case Fac_CCBSInterrogate:
9674  case Fac_CCNRInterrogate:
9675  /* We don't handle this yet */
9676  break;
9677  case Fac_StatusRequest:
9678  /* We don't handle this yet */
9679  break;
9680 #endif /* We don't handle this yet */
9681 #if 0 /* We don't handle this yet */
9682  case Fac_CCBS_T_Suspend:
9683  case Fac_CCBS_T_Resume:
9684  /* We don't handle this yet */
9685  break;
9686 #endif /* We don't handle this yet */
9687  case Fac_CCBS_T_RemoteUserFree:
9688  misdn_cc_handle_T_remote_user_free(bc);
9689  break;
9690  case Fac_CCBS_T_Available:
9691  switch (event) {
9692  case EVENT_ALERTING:
9693  case EVENT_DISCONNECT:
9694  /* CCBS-T/CCNR-T is available */
9695  if (ch && ch->peer) {
9696  int set_id = 1;
9697 
9698  AST_LIST_LOCK(&misdn_cc_records_db);
9699  if (ch->record_id == -1) {
9700  cc_record = misdn_cc_new();
9701  } else {
9702  /*
9703  * We are doing a call-completion attempt
9704  * or the switch is sending us extra call-completion
9705  * availability indications (erroneously?).
9706  */
9707  cc_record = misdn_cc_find_by_id(ch->record_id);
9708  if (cc_record) {
9709  if (cc_record->ptp && cc_record->mode.ptp.retention_enabled) {
9710  /*
9711  * Call-completion is still activated.
9712  * The user does not have to request it again.
9713  */
9714  chan_misdn_log(1, bc->port, " --> Call-completion request retention option is enabled\n");
9715 
9716  set_id = 0;
9717  } else {
9718  if (cc_record->ptp && cc_record->mode.ptp.bc) {
9719  /*
9720  * The network request retention option
9721  * is not on and the current call-completion
9722  * request is to be disabled.
9723  *
9724  * We should get here only if EVENT_DISCONNECT
9725  *
9726  * Close the call-completion signaling link
9727  */
9728  cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
9729  cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
9730  misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
9731  }
9732 
9733  /*
9734  * Resetup the existing record for a possible new
9735  * call-completion request.
9736  */
9737  new_record_id = misdn_cc_record_id_new();
9738  if (new_record_id < 0) {
9739  /* Looks like we must keep the old id anyway. */
9740  } else {
9741  cc_record->record_id = new_record_id;
9742  ch->record_id = new_record_id;
9743  }
9744  cc_record->ptp = 1;
9745  cc_record->port = bc->port;
9746  memset(&cc_record->mode, 0, sizeof(cc_record->mode));
9747  cc_record->invoke_id = ++misdn_invoke_id;
9748  cc_record->activated = 0;
9749  cc_record->outstanding_message = 0;
9750  cc_record->activation_requested = 0;
9751  cc_record->error_code = FacError_None;
9752  cc_record->reject_code = FacReject_None;
9753  memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
9754  memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
9755  cc_record->time_created = time(NULL);
9756  }
9757  cc_record = NULL;
9758  } else {
9759  /*
9760  * Where did the record go? We will have to recapture
9761  * the call setup information. Unfortunately, some
9762  * setup information may have been changed.
9763  */
9764  ch->record_id = -1;
9765  cc_record = misdn_cc_new();
9766  }
9767  }
9768  if (cc_record) {
9769  ch->record_id = cc_record->record_id;
9770  cc_record->ptp = 1;
9771  cc_record->port = bc->port;
9772 
9773  /* Record call information for possible call-completion attempt. */
9774  cc_record->redial.caller = bc->caller;
9775  cc_record->redial.dialed = bc->dialed;
9776  cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
9777  cc_record->redial.capability = bc->capability;
9778  cc_record->redial.hdlc = bc->hdlc;
9779  }
9780  AST_LIST_UNLOCK(&misdn_cc_records_db);
9781 
9782  /* Set MISDN_CC_RECORD_ID in original channel */
9783  if (ch->record_id != -1 && set_id) {
9784  snprintf(buf, sizeof(buf), "%ld", ch->record_id);
9785  } else {
9786  buf[0] = 0;
9787  }
9788  misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
9789  }
9790  break;
9791  default:
9792  chan_misdn_log(0, bc->port,
9793  " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
9794  bc->fac_in.Function);
9795  break;
9796  }
9797  break;
9798  case Fac_CCBS_T_Request:
9799  case Fac_CCNR_T_Request:
9800  switch (bc->fac_in.u.CCBS_T_Request.ComponentType) {
9801  case FacComponent_Result:
9802  AST_LIST_LOCK(&misdn_cc_records_db);
9803  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBS_T_Request.InvokeID);
9804  if (cc_record && cc_record->ptp) {
9805  cc_record->outstanding_message = 0;
9806  cc_record->activated = 1;
9807  cc_record->mode.ptp.retention_enabled =
9808  cc_record->mode.ptp.requested_retention
9809  ? bc->fac_in.u.CCBS_T_Request.Component.Result.RetentionSupported
9810  ? 1 : 0
9811  : 0;
9812  }
9813  AST_LIST_UNLOCK(&misdn_cc_records_db);
9814  break;
9815 
9816  case FacComponent_Invoke:
9817  /* We cannot be User-B in ptp mode. */
9818  default:
9819  chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
9820  bc->fac_in.Function);
9821  break;
9822  }
9823  break;
9824 
9825 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9826  case Fac_None:
9827  break;
9828  default:
9829  chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
9830  bc->fac_in.Function);
9831  break;
9832  }
9833 }
9834 
9835 /*!
9836  * \internal
9837  * \brief Determine if the given dialed party matches our MSN.
9838  * \since 1.8
9839  *
9840  * \param port ISDN port
9841  * \param dialed Dialed party information of incoming call.
9842  *
9843  * \retval non-zero if MSN is valid.
9844  * \retval 0 if MSN invalid.
9845  */
9846 static int misdn_is_msn_valid(int port, const struct misdn_party_dialing *dialed)
9847 {
9848  char number[sizeof(dialed->number)];
9849 
9850  ast_copy_string(number, dialed->number, sizeof(number));
9851  misdn_add_number_prefix(port, dialed->number_type, number, sizeof(number));
9852  return misdn_cfg_is_msn_valid(port, number);
9853 }
9854 
9855 /************************************************************/
9856 /* Receive Events from isdn_lib here */
9857 /************************************************************/
9858 static enum event_response_e
9859 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
9860 {
9861 #if defined(AST_MISDN_ENHANCEMENTS)
9862  struct misdn_cc_record *cc_record;
9863 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9864  struct chan_list *held_ch;
9865  struct chan_list *ch = find_chan_by_bc(bc);
9866 
9867  if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
9868  int debuglevel = 1;
9869 
9870  /* Debug Only Non-Bchan */
9871  if (event == EVENT_CLEANUP && !user_data) {
9872  debuglevel = 5;
9873  }
9874 
9875  chan_misdn_log(debuglevel, bc->port,
9876  "I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
9877  manager_isdn_get_info(event),
9878  bc->caller.name,
9879  bc->caller.number,
9880  bc->dialed.number,
9881  bc->pid,
9882  ch ? misdn_get_ch_state(ch) : "none");
9883  if (debuglevel == 1) {
9884  misdn_lib_log_ies(bc);
9885  chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
9886  }
9887  }
9888 
9889  if (!ch) {
9890  switch(event) {
9891  case EVENT_SETUP:
9892  case EVENT_DISCONNECT:
9893  case EVENT_RELEASE:
9895  case EVENT_PORT_ALARM:
9896  case EVENT_RETRIEVE:
9897  case EVENT_NEW_BC:
9898  case EVENT_FACILITY:
9899  case EVENT_REGISTER:
9900  break;
9901  case EVENT_CLEANUP:
9902  case EVENT_TONE_GENERATE:
9903  case EVENT_BCHAN_DATA:
9904  return -1;
9905  default:
9906  chan_misdn_log(1, bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n", bc->l3_id, bc, manager_isdn_get_info(event), bc->port, bc->channel);
9907  return -1;
9908  }
9909  } else {
9910  switch (event) {
9911  case EVENT_TONE_GENERATE:
9912  break;
9913  case EVENT_DISCONNECT:
9914  case EVENT_RELEASE:
9916  case EVENT_CLEANUP:
9917  case EVENT_TIMEOUT:
9918  if (!ch->ast) {
9919  chan_misdn_log(3, bc->port, "ast_hangup already called, so we have no ast ptr anymore in event(%s)\n", manager_isdn_get_info(event));
9920  }
9921  break;
9922  default:
9923  if (!ch->ast || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
9924  if (event != EVENT_BCHAN_DATA) {
9925  ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
9926  }
9927  chan_list_unref(ch, "No Ast or Ast private pointer");
9928  return -1;
9929  }
9930  break;
9931  }
9932  }
9933 
9934 
9935  switch (event) {
9936  case EVENT_PORT_ALARM:
9937  {
9938  int boa = 0;
9939  misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
9940  if (boa) {
9941  cb_log(1, bc->port, " --> blocking\n");
9943  }
9944  }
9945  break;
9946  case EVENT_BCHAN_ACTIVATED:
9947  break;
9948 
9949  case EVENT_NEW_CHANNEL:
9950  update_name(ch->ast,bc->port,bc->channel);
9951  break;
9952 
9953  case EVENT_NEW_L3ID:
9954  ch->l3id=bc->l3_id;
9955  ch->addr=bc->addr;
9956  break;
9957 
9958  case EVENT_NEW_BC:
9959  if (!ch) {
9960  ch = find_hold_call(bc);
9961  }
9962 
9963  if (!ch) {
9964  ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
9965  break;
9966  }
9967 
9968  if (bc) {
9969  ch->bc = (struct misdn_bchannel *) user_data;
9970  }
9971  break;
9972 
9973  case EVENT_DTMF_TONE:
9974  {
9975  /* sending INFOS as DTMF-Frames :) */
9976  struct ast_frame fr;
9977 
9978  memset(&fr, 0, sizeof(fr));
9980  fr.subclass.integer = bc->dtmf ;
9981  fr.src = NULL;
9982  fr.data.ptr = NULL;
9983  fr.datalen = 0;
9984  fr.samples = 0;
9985  fr.mallocd = 0;
9986  fr.offset = 0;
9987  fr.delivery = ast_tv(0,0);
9988 
9989  if (!ch->ignore_dtmf) {
9990  chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
9991  ast_queue_frame(ch->ast, &fr);
9992  } else {
9993  chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
9994  }
9995  break;
9996  }
9997  case EVENT_STATUS:
9998  break;
9999 
10000  case EVENT_INFORMATION:
10001  if (ch->state != MISDN_CONNECTED) {
10002  stop_indicate(ch);
10003  }
10004 
10005  if (!ch->ast) {
10006  break;
10007  }
10008 
10009  if (ch->state == MISDN_WAITING4DIGS) {
10010  /* Ok, incomplete Setup, waiting till extension exists */
10011  if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
10012  chan_misdn_log(1, bc->port, " --> using keypad as info\n");
10013  ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
10014  }
10015 
10016  strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10017  ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
10018 
10019  /* Check for Pickup Request first */
10020  if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
10021  if (ast_pickup_call(ch->ast)) {
10022  hangup_chan(ch, bc);
10023  } else {
10025  hangup_chan(ch, bc);
10026  ch->ast = NULL;
10027  break;
10028  }
10029  }
10030 
10031  if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10032  if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10034  "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10035  bc->dialed.number, ch->context, bc->port);
10036  pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10037  strcpy(ch->ast->exten, "i");
10038  ch->state = MISDN_DIALING;
10039  start_pbx(ch, bc, ch->ast);
10040  break;
10041  }
10042 
10044  "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10045  "\tMaybe you want to add an 'i' extension to catch this case.\n",
10046  bc->dialed.number, ch->context, bc->port);
10047 
10048  if (bc->nt) {
10049  hanguptone_indicate(ch);
10050  }
10051  ch->state = MISDN_EXTCANTMATCH;
10053 
10055  break;
10056  }
10057 
10058  if (ch->overlap_dial) {
10060  ch->overlap_tv = ast_tvnow();
10062  if (ch->overlap_dial_task == -1) {
10063  ch->overlap_dial_task =
10065  }
10066  break;
10067  }
10068 
10069  if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10070  ch->state = MISDN_DIALING;
10071  start_pbx(ch, bc, ch->ast);
10072  }
10073  } else {
10074  /* sending INFOS as DTMF-Frames :) */
10075  struct ast_frame fr;
10076  int digits;
10077 
10078  memset(&fr, 0, sizeof(fr));
10080  fr.subclass.integer = bc->info_dad[0] ;
10081  fr.src = NULL;
10082  fr.data.ptr = NULL;
10083  fr.datalen = 0;
10084  fr.samples = 0;
10085  fr.mallocd = 0;
10086  fr.offset = 0;
10087  fr.delivery = ast_tv(0,0);
10088 
10089  misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
10090  if (ch->state != MISDN_CONNECTED) {
10091  if (digits) {
10092  strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10093  ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
10094  ast_cdr_update(ch->ast);
10095  }
10096 
10097  ast_queue_frame(ch->ast, &fr);
10098  }
10099  }
10100  break;
10101  case EVENT_SETUP:
10102  {
10103  struct ast_channel *chan;
10104  int exceed;
10105  int ai;
10106  int im;
10107  int append_msn = 0;
10108 
10109  if (ch) {
10110  switch (ch->state) {
10111  case MISDN_NOTHING:
10112  chan_list_unref(ch, "Ignore found ch. Is it for an outgoing call?");
10113  ch = NULL;
10114  break;
10115  default:
10116  chan_list_unref(ch, "Already have a call.");
10117  chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
10118  return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /* Ignore MSNs which are not in our List */
10119  }
10120  }
10121 
10122  if (!bc->nt && !misdn_is_msn_valid(bc->port, &bc->dialed)) {
10123  chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
10124  return RESPONSE_IGNORE_SETUP; /* Ignore MSNs which are not in our List */
10125  }
10126 
10127  if (bc->cw) {
10128  int cause;
10129  chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
10130  misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
10131  bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
10132  return RESPONSE_RELEASE_SETUP;
10133  }
10134 
10135  print_bearer(bc);
10136 
10137  ch = chan_list_init(ORG_MISDN);
10138  if (!ch) {
10139  chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
10140  return RESPONSE_RELEASE_SETUP;
10141  }
10142 
10143  ch->bc = bc;
10144  ch->l3id = bc->l3_id;
10145  ch->addr = bc->addr;
10146 
10147  chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, AST_FORMAT_ALAW, NULL, bc->port, bc->channel);
10148  if (!chan) {
10149  chan_list_unref(ch, "Failed to create a new channel");
10150  ast_log(LOG_ERROR, "cb_events: misdn_new failed!\n");
10151  return RESPONSE_RELEASE_SETUP;
10152  }
10153 
10154  if ((exceed = add_in_calls(bc->port))) {
10155  char tmp[16];
10156  snprintf(tmp, sizeof(tmp), "%d", exceed);
10157  pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
10158  }
10159 
10160  read_config(ch);
10161 
10162  export_ch(chan, bc, ch);
10163 
10164  ch->ast->rings = 1;
10166 
10167  /* Update asterisk channel caller information */
10168  chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
10169  chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
10172 
10173  chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
10174  chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
10177 
10178  ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
10179 
10180  misdn_cfg_get(bc->port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
10181  if (append_msn) {
10182  strncat(bc->incoming_cid_tag, "_", sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10183  strncat(bc->incoming_cid_tag, bc->dialed.number, sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10184  }
10185 
10186  ast_channel_lock(chan);
10187  chan->caller.id.tag = ast_strdup(bc->incoming_cid_tag);
10188  ast_channel_unlock(chan);
10189 
10190  if (!ast_strlen_zero(bc->redirecting.from.number)) {
10191  /* Add configured prefix to redirecting.from.number */
10193 
10194  /* Update asterisk channel redirecting information */
10196  }
10197 
10198  pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
10199  chan->transfercapability = bc->capability;
10200 
10201  switch (bc->capability) {
10203  pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
10204  break;
10205  default:
10206  pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
10207  break;
10208  }
10209 
10210  if (!strstr(ch->allowed_bearers, "all")) {
10211  int i;
10212 
10213  for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
10214  if (allowed_bearers_array[i].cap == bc->capability) {
10215  if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
10216  /* The bearer capability is allowed */
10217  if (allowed_bearers_array[i].deprecated) {
10218  chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
10219  allowed_bearers_array[i].name);
10220  }
10221  break;
10222  }
10223  }
10224  }
10225  if (i == ARRAY_LEN(allowed_bearers_array)) {
10226  /* We did not find the bearer capability */
10227  chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
10228  bearer2str(bc->capability), bc->capability);
10229 
10230  ch->state = MISDN_EXTCANTMATCH;
10231  chan_list_unref(ch, "BC not allowed, releasing call");
10233  return RESPONSE_RELEASE_SETUP;
10234  }
10235  }
10236 
10237  /** queue new chan **/
10238  cl_queue_chan(ch);
10239 
10240  if (bc->fac_in.Function != Fac_None) {
10241  misdn_facility_ie_handler(event, bc, ch);
10242  }
10243 
10244  /* Check for Pickup Request first */
10245  if (!strcmp(chan->exten, ast_pickup_ext())) {
10246  if (!ch->noautorespond_on_setup) {
10247  /* Sending SETUP_ACK */
10249  } else {
10251  }
10252  if (ast_pickup_call(chan)) {
10253  hangup_chan(ch, bc);
10254  } else {
10256  hangup_chan(ch, bc);
10257  ch->ast = NULL;
10258  break;
10259  }
10260  }
10261 
10262  /*
10263  * added support for s extension hope it will help those poor cretains
10264  * which haven't overlap dial.
10265  */
10266  misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
10267  if (ai) {
10268  do_immediate_setup(bc, ch, chan);
10269  break;
10270  }
10271 
10272  /* check if we should jump into s when we have no dialed.number */
10273  misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
10274  if (im && ast_strlen_zero(bc->dialed.number)) {
10275  do_immediate_setup(bc, ch, chan);
10276  break;
10277  }
10278 
10279  chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
10280  if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10281  if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10283  "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10284  bc->dialed.number, ch->context, bc->port);
10285  pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10286  strcpy(ch->ast->exten, "i");
10288  ch->state = MISDN_DIALING;
10289  start_pbx(ch, bc, chan);
10290  break;
10291  }
10292 
10294  "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10295  "\tMaybe you want to add an 'i' extension to catch this case.\n",
10296  bc->dialed.number, ch->context, bc->port);
10297  if (bc->nt) {
10298  hanguptone_indicate(ch);
10299  }
10300 
10301  ch->state = MISDN_EXTCANTMATCH;
10303 
10305  break;
10306  }
10307 
10308  /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
10309  * jump into the dialplan, when the dialed extension does not exist, the 's' extension
10310  * will be used by Asterisk automatically. */
10311  if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
10312  if (!ch->noautorespond_on_setup) {
10313  ch->state=MISDN_DIALING;
10315  } else {
10317  }
10318  start_pbx(ch, bc, chan);
10319  break;
10320  }
10321 
10322 
10323  /*
10324  * When we are NT and overlapdial is set and if
10325  * the number is empty, we wait for the ISDN timeout
10326  * instead of our own timer.
10327  */
10328  if (ch->overlap_dial && bc->nt && !bc->dialed.number[0]) {
10329  wait_for_digits(ch, bc, chan);
10330  break;
10331  }
10332 
10333  /*
10334  * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
10335  * Infos with a Interdigit Timeout.
10336  * */
10337  if (ch->overlap_dial) {
10339  ch->overlap_tv = ast_tvnow();
10341 
10342  wait_for_digits(ch, bc, chan);
10343  if (ch->overlap_dial_task == -1) {
10344  ch->overlap_dial_task =
10346  }
10347  break;
10348  }
10349 
10350  /* If the extension does not exist and we're not TE_PTMP we wait for more digits
10351  * without interdigit timeout.
10352  * */
10353  if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10354  wait_for_digits(ch, bc, chan);
10355  break;
10356  }
10357 
10358  /*
10359  * If the extension exists let's just jump into it.
10360  * */
10361  if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10363  ch->state = MISDN_DIALING;
10364  start_pbx(ch, bc, chan);
10365  break;
10366  }
10367  break;
10368  }
10369 #if defined(AST_MISDN_ENHANCEMENTS)
10370  case EVENT_REGISTER:
10371  if (bc->fac_in.Function != Fac_None) {
10372  misdn_facility_ie_handler(event, bc, ch);
10373  }
10374  /*
10375  * Shut down this connection immediately.
10376  * The current design of chan_misdn data structures
10377  * does not allow the proper handling of inbound call records
10378  * without an assigned B channel. Therefore, we cannot
10379  * be the CCBS User-B party in a point-to-point setup.
10380  */
10381  bc->fac_out.Function = Fac_None;
10384  break;
10385 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
10388 
10389  if (bc->channel) {
10390  update_name(ch->ast,bc->port,bc->channel);
10391  }
10392 
10393  if (bc->fac_in.Function != Fac_None) {
10394  misdn_facility_ie_handler(event, bc, ch);
10395  }
10396 
10397  if (!ast_strlen_zero(bc->infos_pending)) {
10398  /* TX Pending Infos */
10399  strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10400 
10401  if (!ch->ast) {
10402  break;
10403  }
10404  ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
10405  ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
10406  ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
10407 
10409  }
10410  break;
10411  case EVENT_PROCEEDING:
10412  if (misdn_cap_is_speech(bc->capability) &&
10413  misdn_inband_avail(bc)) {
10414  start_bc_tones(ch);
10415  }
10416 
10417  ch->state = MISDN_PROCEEDING;
10418 
10419  if (bc->fac_in.Function != Fac_None) {
10420  misdn_facility_ie_handler(event, bc, ch);
10421  }
10422 
10423  if (!ch->ast) {
10424  break;
10425  }
10426 
10428  break;
10429  case EVENT_PROGRESS:
10430  if (bc->channel) {
10431  update_name(ch->ast, bc->port, bc->channel);
10432  }
10433 
10434  if (bc->fac_in.Function != Fac_None) {
10435  misdn_facility_ie_handler(event, bc, ch);
10436  }
10437 
10438  if (!bc->nt) {
10439  if (misdn_cap_is_speech(bc->capability) &&
10440  misdn_inband_avail(bc)) {
10441  start_bc_tones(ch);
10442  }
10443 
10444  ch->state = MISDN_PROGRESS;
10445 
10446  if (!ch->ast) {
10447  break;
10448  }
10450  }
10451  break;
10452  case EVENT_ALERTING:
10453  ch->state = MISDN_ALERTING;
10454 
10455  if (!ch->ast) {
10456  break;
10457  }
10458 
10459  if (bc->fac_in.Function != Fac_None) {
10460  misdn_facility_ie_handler(event, bc, ch);
10461  }
10462 
10465 
10466  cb_log(7, bc->port, " --> Set State Ringing\n");
10467 
10469  cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
10470  start_bc_tones(ch);
10471  } else {
10472  cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
10473  if (ch->far_alerting) {
10474  cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
10475  start_bc_tones(ch);
10476  /*tone_indicate(ch, TONE_FAR_ALERTING);*/
10477  }
10478  }
10479  break;
10480  case EVENT_CONNECT:
10481  if (bc->fac_in.Function != Fac_None) {
10482  misdn_facility_ie_handler(event, bc, ch);
10483  }
10484 #if defined(AST_MISDN_ENHANCEMENTS)
10485  if (bc->div_leg_3_rx_wanted) {
10486  bc->div_leg_3_rx_wanted = 0;
10487 
10488  if (ch->ast) {
10492  }
10493  }
10494 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
10495 
10496  /* we answer when we've got our very new L3 ID from the NT stack */
10498 
10499  if (!ch->ast) {
10500  break;
10501  }
10502 
10503  stop_indicate(ch);
10504 
10505 #if defined(AST_MISDN_ENHANCEMENTS)
10506  if (ch->record_id != -1) {
10507  /*
10508  * We will delete the associated call completion
10509  * record since we now have a completed call.
10510  * We will not wait/depend on the network to tell
10511  * us to delete it.
10512  */
10513  AST_LIST_LOCK(&misdn_cc_records_db);
10514  cc_record = misdn_cc_find_by_id(ch->record_id);
10515  if (cc_record) {
10516  if (cc_record->ptp && cc_record->mode.ptp.bc) {
10517  /* Close the call-completion signaling link */
10518  cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
10519  cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10520  misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
10521  }
10522  misdn_cc_delete(cc_record);
10523  }
10524  AST_LIST_UNLOCK(&misdn_cc_records_db);
10525  ch->record_id = -1;
10526  if (ch->peer) {
10527  misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, "");
10528 
10529  ao2_ref(ch->peer, -1);
10530  ch->peer = NULL;
10531  }
10532  }
10533 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
10534 
10535  if (!ast_strlen_zero(bc->connected.number)) {
10536  /* Add configured prefix to connected.number */
10538 
10539  /* Update the connected line information on the other channel */
10541  }
10542 
10543  ch->l3id = bc->l3_id;
10544  ch->addr = bc->addr;
10545 
10546  start_bc_tones(ch);
10547 
10548  ch->state = MISDN_CONNECTED;
10549 
10551  break;
10553  ch->l3id = bc->l3_id;
10554  ch->addr = bc->addr;
10555 
10556  start_bc_tones(ch);
10557 
10558  ch->state = MISDN_CONNECTED;
10559  break;
10560  case EVENT_DISCONNECT:
10561  /* we might not have an ch->ast ptr here anymore */
10562  if (ch) {
10563  if (bc->fac_in.Function != Fac_None) {
10564  misdn_facility_ie_handler(event, bc, ch);
10565  }
10566 
10567  chan_misdn_log(3, bc->port, " --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
10568  if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
10569  /* If there's inband information available (e.g. a
10570  recorded message saying what was wrong with the
10571  dialled number, or perhaps even giving an
10572  alternative number, then play it instead of
10573  immediately releasing the call */
10574  chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
10575 
10576  ch->state = MISDN_DISCONNECTED;
10577  start_bc_tones(ch);
10578 
10579  if (ch->ast) {
10580  ch->ast->hangupcause = bc->cause;
10581  if (bc->cause == AST_CAUSE_USER_BUSY) {
10583  }
10584  }
10585  ch->need_busy = 0;
10586  break;
10587  }
10588 
10589  bc->need_disconnect = 0;
10590  stop_bc_tones(ch);
10591 
10592  /* Check for held channel, to implement transfer */
10593  held_ch = find_hold_call(bc);
10594  if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
10595  hangup_chan(ch, bc);
10596  }
10597  } else {
10598  held_ch = find_hold_call_l3(bc->l3_id);
10599  if (held_ch) {
10600  if (bc->fac_in.Function != Fac_None) {
10601  misdn_facility_ie_handler(event, bc, held_ch);
10602  }
10603 
10604  if (held_ch->hold.state == MISDN_HOLD_ACTIVE) {
10605  bc->need_disconnect = 0;
10606 
10607 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
10608  /*
10609  * Some phones disconnect the held call and the active call at the
10610  * same time to do the transfer. Unfortunately, either call could
10611  * be disconnected first.
10612  */
10613  ch = find_hold_active_call(bc);
10614  if (!ch || misdn_attempt_transfer(ch, held_ch)) {
10615  held_ch->hold.state = MISDN_HOLD_DISCONNECT;
10616  hangup_chan(held_ch, bc);
10617  }
10618 #else
10619  hangup_chan(held_ch, bc);
10620 #endif /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
10621  }
10622  }
10623  }
10624  if (held_ch) {
10625  chan_list_unref(held_ch, "Done with held call");
10626  }
10627  bc->out_cause = -1;
10628  if (bc->need_release) {
10630  }
10631  break;
10632  case EVENT_RELEASE:
10633  if (!ch) {
10634  ch = find_hold_call_l3(bc->l3_id);
10635  if (!ch) {
10636  chan_misdn_log(1, bc->port,
10637  " --> no Ch, so we've already released. (%s)\n",
10638  manager_isdn_get_info(event));
10639  return -1;
10640  }
10641  }
10642  if (bc->fac_in.Function != Fac_None) {
10643  misdn_facility_ie_handler(event, bc, ch);
10644  }
10645 
10646  bc->need_disconnect = 0;
10647  bc->need_release = 0;
10648 
10649  hangup_chan(ch, bc);
10650  release_chan(ch, bc);
10651  break;
10653  if (!ch) {
10654  ch = find_hold_call_l3(bc->l3_id);
10655  }
10656 
10657  bc->need_disconnect = 0;
10658  bc->need_release = 0;
10659  bc->need_release_complete = 0;
10660 
10661  if (ch) {
10662  if (bc->fac_in.Function != Fac_None) {
10663  misdn_facility_ie_handler(event, bc, ch);
10664  }
10665 
10666  stop_bc_tones(ch);
10667  hangup_chan(ch, bc);
10668  release_chan(ch, bc);
10669  } else {
10670 #if defined(AST_MISDN_ENHANCEMENTS)
10671  /*
10672  * A call-completion signaling link established with
10673  * REGISTER does not have a struct chan_list record
10674  * associated with it.
10675  */
10676  AST_LIST_LOCK(&misdn_cc_records_db);
10677  cc_record = misdn_cc_find_by_bc(bc);
10678  if (cc_record) {
10679  /* The call-completion signaling link is closed. */
10680  misdn_cc_delete(cc_record);
10681  }
10682  AST_LIST_UNLOCK(&misdn_cc_records_db);
10683 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
10684 
10685  chan_misdn_log(1, bc->port,
10686  " --> no Ch, so we've already released. (%s)\n",
10687  manager_isdn_get_info(event));
10688  }
10689  break;
10690  case EVENT_BCHAN_ERROR:
10691  case EVENT_CLEANUP:
10692  stop_bc_tones(ch);
10693 
10694  switch (ch->state) {
10695  case MISDN_CALLING:
10697  break;
10698  default:
10699  break;
10700  }
10701 
10702  hangup_chan(ch, bc);
10703  release_chan(ch, bc);
10704  break;
10705  case EVENT_TONE_GENERATE:
10706  {
10707  int tone_len = bc->tone_cnt;
10708  struct ast_channel *ast = ch->ast;
10709  void *tmp;
10710  int res;
10711  int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
10712 
10713  chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
10714 
10715  if (!ast) {
10716  break;
10717  }
10718 
10719  if (!ast->generator) {
10720  break;
10721  }
10722 
10723  tmp = ast->generatordata;
10724  ast->generatordata = NULL;
10725  generate = ast->generator->generate;
10726 
10727  if (tone_len < 0 || tone_len > 512) {
10728  ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
10729  tone_len = 128;
10730  }
10731 
10732  res = generate(ast, tmp, tone_len, tone_len);
10733  ast->generatordata = tmp;
10734 
10735  if (res) {
10736  ast_log(LOG_WARNING, "Auto-deactivating generator\n");
10738  } else {
10739  bc->tone_cnt = 0;
10740  }
10741  break;
10742  }
10743  case EVENT_BCHAN_DATA:
10744  if (ch->bc->AOCD_need_export) {
10745  export_aoc_vars(ch->originator, ch->ast, ch->bc);
10746  }
10747  if (!misdn_cap_is_speech(ch->bc->capability)) {
10748  struct ast_frame frame;
10749 
10750  /* In Data Modes we queue frames */
10751  memset(&frame, 0, sizeof(frame));
10752  frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
10753  frame.subclass.codec = AST_FORMAT_ALAW;
10754  frame.datalen = bc->bframe_len;
10755  frame.samples = bc->bframe_len;
10756  frame.mallocd = 0;
10757  frame.offset = 0;
10758  frame.delivery = ast_tv(0, 0);
10759  frame.src = NULL;
10760  frame.data.ptr = bc->bframe;
10761 
10762  if (ch->ast) {
10763  ast_queue_frame(ch->ast, &frame);
10764  }
10765  } else {
10766  struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
10767  int t;
10768 
10769  t = ast_poll(&pfd, 1, 0);
10770 
10771  if (t < 0) {
10772  chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
10773  break;
10774  }
10775  if (!t) {
10776  chan_misdn_log(9, bc->port, "poll() timed out\n");
10777  break;
10778  }
10779 
10780  if (pfd.revents & POLLOUT) {
10781  chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
10782  if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
10783  chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
10784 
10785  stop_bc_tones(ch);
10786  hangup_chan(ch, bc);
10787  release_chan(ch, bc);
10788  }
10789  } else {
10790  chan_misdn_log(1, bc->port, "Write Pipe full!\n");
10791  }
10792  }
10793  break;
10794  case EVENT_TIMEOUT:
10795  if (ch && bc) {
10796  chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
10797  }
10798 
10799  switch (ch->state) {
10800  case MISDN_DIALING:
10801  case MISDN_PROGRESS:
10802  if (bc->nt && !ch->nttimeout) {
10803  break;
10804  }
10805  /* fall-through */
10806  case MISDN_CALLING:
10807  case MISDN_ALERTING:
10808  case MISDN_PROCEEDING:
10810  if (bc->nt) {
10812  hanguptone_indicate(ch);
10813  }
10814 
10817  break;
10818  case MISDN_WAITING4DIGS:
10819  if (bc->nt) {
10822  hanguptone_indicate(ch);
10824  } else {
10827  }
10828  break;
10829  case MISDN_CLEANING:
10830  chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
10831  break;
10832  default:
10834  break;
10835  }
10836  break;
10837 
10838  /****************************/
10839  /** Supplementary Services **/
10840  /****************************/
10841  case EVENT_RETRIEVE:
10842  if (!ch) {
10843  chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
10844  ch = find_hold_call_l3(bc->l3_id);
10845  if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
10846  ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
10848  break;
10849  }
10850  }
10851 
10852  /* remember the channel again */
10853  ch->bc = bc;
10854 
10855  ch->hold.state = MISDN_HOLD_IDLE;
10856  ch->hold.port = 0;
10857  ch->hold.channel = 0;
10858 
10860 
10862  chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
10864  }
10865  break;
10866  case EVENT_HOLD:
10867  {
10868  int hold_allowed;
10869  struct ast_channel *bridged;
10870 
10871  misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
10872  if (!hold_allowed) {
10873  chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
10875  break;
10876  }
10877 
10878  bridged = ast_bridged_channel(ch->ast);
10879  if (bridged) {
10880  chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
10881  ch->l3id = bc->l3_id;
10882 
10883  /* forget the channel now */
10884  ch->bc = NULL;
10886  ch->hold.port = bc->port;
10887  ch->hold.channel = bc->channel;
10888 
10890 
10892  } else {
10894  chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
10895  }
10896  break;
10897  }
10898  case EVENT_NOTIFY:
10899  if (bc->redirecting.to_changed) {
10900  /* Add configured prefix to redirecting.to.number */
10902  bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
10903  }
10904  switch (bc->notify_description_code) {
10906  /* Ignore for now. */
10907  bc->redirecting.to_changed = 0;
10908  break;
10910  if (!bc->redirecting.to_changed) {
10911  break;
10912  }
10913  bc->redirecting.to_changed = 0;
10914  if (!ch || !ch->ast) {
10915  break;
10916  }
10917  switch (ch->state) {
10918  case MISDN_ALERTING:
10919  /* Call is deflecting after we have seen an ALERTING message */
10921  break;
10922  default:
10923  /* Call is deflecting for call forwarding unconditional or busy reason. */
10925  break;
10926  }
10929  break;
10931  /*
10932  * It would be preferable to update the connected line information
10933  * only when the message callStatus is active. However, the
10934  * optional redirection number may not be present in the active
10935  * message if an alerting message were received earlier.
10936  *
10937  * The consequences if we wind up sending two updates is benign.
10938  * The other end will think that it got transferred twice.
10939  */
10940  if (!bc->redirecting.to_changed) {
10941  break;
10942  }
10943  bc->redirecting.to_changed = 0;
10944  if (!ch || !ch->ast) {
10945  break;
10946  }
10949  bc->incoming_cid_tag);
10950  break;
10952  if (!bc->redirecting.to_changed) {
10953  break;
10954  }
10955  bc->redirecting.to_changed = 0;
10956  if (!ch || !ch->ast) {
10957  break;
10958  }
10961  break;
10962  default:
10963  bc->redirecting.to_changed = 0;
10964  chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
10966  break;
10967  }
10969  break;
10970  case EVENT_FACILITY:
10971  if (bc->fac_in.Function == Fac_None) {
10972  /* This is a FACILITY message so we MUST have a facility ie */
10973  chan_misdn_log(0, bc->port," --> Missing facility ie or unknown facility ie contents.\n");
10974  } else {
10975  misdn_facility_ie_handler(event, bc, ch);
10976  }
10977 
10978  /* In case it came in on a FACILITY message and we did not handle it. */
10979  bc->redirecting.to_changed = 0;
10981  break;
10982  case EVENT_RESTART:
10983  if (!bc->dummy) {
10984  stop_bc_tones(ch);
10985  release_chan(ch, bc);
10986  }
10987  break;
10988  default:
10989  chan_misdn_log(1, 0, "Got Unknown Event\n");
10990  break;
10991  }
10992 
10993  if (ch) {
10994  chan_list_unref(ch, "cb_event complete OK");
10995  }
10996  return RESPONSE_OK;
10997 }
10998 
10999 /** TE STUFF END **/
11000 
11001 #if defined(AST_MISDN_ENHANCEMENTS)
11002 /*!
11003  * \internal
11004  * \brief Get call completion record information.
11005  *
11006  * \param chan Asterisk channel to operate upon. (Not used)
11007  * \param function_name Name of the function that called us.
11008  * \param function_args Argument string passed to function (Could be NULL)
11009  * \param buf Buffer to put returned string.
11010  * \param size Size of the supplied buffer including the null terminator.
11011  *
11012  * \retval 0 on success.
11013  * \retval -1 on error.
11014  */
11015 static int misdn_cc_read(struct ast_channel *chan, const char *function_name,
11016  char *function_args, char *buf, size_t size)
11017 {
11018  char *parse;
11019  struct misdn_cc_record *cc_record;
11020 
11022  AST_APP_ARG(cc_id); /* Call completion record ID value. */
11023  AST_APP_ARG(get_name); /* Name of what to get */
11024  AST_APP_ARG(other); /* Any extraneous garbage arguments */
11025  );
11026 
11027  /* Ensure that the buffer is empty */
11028  *buf = 0;
11029 
11030  if (ast_strlen_zero(function_args)) {
11031  ast_log(LOG_ERROR, "Function '%s' requires arguments.\n", function_name);
11032  return -1;
11033  }
11034 
11035  parse = ast_strdupa(function_args);
11036  AST_STANDARD_APP_ARGS(args, parse);
11037 
11038  if (!args.argc || ast_strlen_zero(args.cc_id)) {
11039  ast_log(LOG_ERROR, "Function '%s' missing call completion record ID.\n",
11040  function_name);
11041  return -1;
11042  }
11043  if (!isdigit(*args.cc_id)) {
11044  ast_log(LOG_ERROR, "Function '%s' call completion record ID must be numeric.\n",
11045  function_name);
11046  return -1;
11047  }
11048 
11049  if (ast_strlen_zero(args.get_name)) {
11050  ast_log(LOG_ERROR, "Function '%s' missing what-to-get parameter.\n",
11051  function_name);
11052  return -1;
11053  }
11054 
11055  AST_LIST_LOCK(&misdn_cc_records_db);
11056  cc_record = misdn_cc_find_by_id(atoi(args.cc_id));
11057  if (cc_record) {
11058  if (!strcasecmp("a-all", args.get_name)) {
11059  snprintf(buf, size, "\"%s\" <%s>", cc_record->redial.caller.name,
11060  cc_record->redial.caller.number);
11061  } else if (!strcasecmp("a-name", args.get_name)) {
11062  ast_copy_string(buf, cc_record->redial.caller.name, size);
11063  } else if (!strncasecmp("a-num", args.get_name, 5)) {
11064  ast_copy_string(buf, cc_record->redial.caller.number, size);
11065  } else if (!strcasecmp("a-ton", args.get_name)) {
11066  snprintf(buf, size, "%d",
11067  misdn_to_ast_plan(cc_record->redial.caller.number_plan)
11068  | misdn_to_ast_ton(cc_record->redial.caller.number_type));
11069  } else if (!strncasecmp("a-pres", args.get_name, 6)) {
11071  misdn_to_ast_pres(cc_record->redial.caller.presentation)
11072  | misdn_to_ast_screen(cc_record->redial.caller.screening)), size);
11073  } else if (!strcasecmp("a-busy", args.get_name)) {
11074  ast_copy_string(buf, cc_record->party_a_free ? "no" : "yes", size);
11075  } else if (!strncasecmp("b-num", args.get_name, 5)) {
11076  ast_copy_string(buf, cc_record->redial.dialed.number, size);
11077  } else if (!strcasecmp("b-ton", args.get_name)) {
11078  snprintf(buf, size, "%d",
11079  misdn_to_ast_plan(cc_record->redial.dialed.number_plan)
11080  | misdn_to_ast_ton(cc_record->redial.dialed.number_type));
11081  } else if (!strcasecmp("port", args.get_name)) {
11082  snprintf(buf, size, "%d", cc_record->port);
11083  } else if (!strcasecmp("available-notify-priority", args.get_name)) {
11084  snprintf(buf, size, "%d", cc_record->remote_user_free.priority);
11085  } else if (!strcasecmp("available-notify-exten", args.get_name)) {
11086  ast_copy_string(buf, cc_record->remote_user_free.exten, size);
11087  } else if (!strcasecmp("available-notify-context", args.get_name)) {
11088  ast_copy_string(buf, cc_record->remote_user_free.context, size);
11089  } else if (!strcasecmp("busy-notify-priority", args.get_name)) {
11090  snprintf(buf, size, "%d", cc_record->b_free.priority);
11091  } else if (!strcasecmp("busy-notify-exten", args.get_name)) {
11092  ast_copy_string(buf, cc_record->b_free.exten, size);
11093  } else if (!strcasecmp("busy-notify-context", args.get_name)) {
11094  ast_copy_string(buf, cc_record->b_free.context, size);
11095  } else {
11096  AST_LIST_UNLOCK(&misdn_cc_records_db);
11097  ast_log(LOG_ERROR, "Function '%s': Unknown what-to-get '%s'.\n", function_name, args.get_name);
11098  return -1;
11099  }
11100  }
11101  AST_LIST_UNLOCK(&misdn_cc_records_db);
11102 
11103  return 0;
11104 }
11105 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11106 
11107 #if defined(AST_MISDN_ENHANCEMENTS)
11108 static struct ast_custom_function misdn_cc_function = {
11109  .name = "mISDN_CC",
11110  .synopsis = "Get call completion record information.",
11111  .syntax = "mISDN_CC(${MISDN_CC_RECORD_ID},<what-to-get>)",
11112  .desc =
11113  "mISDN_CC(${MISDN_CC_RECORD_ID},<what-to-get>)\n"
11114  "The following can be retrieved:\n"
11115  "\"a-num\", \"a-name\", \"a-all\", \"a-ton\", \"a-pres\", \"a-busy\",\n"
11116  "\"b-num\", \"b-ton\", \"port\",\n"
11117  " User-A is available for call completion:\n"
11118  " \"available-notify-priority\",\n"
11119  " \"available-notify-exten\",\n"
11120  " \"available-notify-context\",\n"
11121  " User-A is busy:\n"
11122  " \"busy-notify-priority\",\n"
11123  " \"busy-notify-exten\",\n"
11124  " \"busy-notify-context\"\n",
11125  .read = misdn_cc_read,
11126 };
11127 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11128 
11129 /******************************************
11130  *
11131  * Asterisk Channel Endpoint END
11132  *
11133  *
11134  *******************************************/
11135 
11136 
11137 
11138 static int unload_module(void)
11139 {
11140  /* First, take us out of the channel loop */
11141  ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
11142 
11144 
11145  if (!g_config_initialized) {
11146  return 0;
11147  }
11148 
11149  ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11150 
11151  /* ast_unregister_application("misdn_crypt"); */
11152  ast_unregister_application("misdn_set_opt");
11153  ast_unregister_application("misdn_facility");
11154  ast_unregister_application("misdn_check_l2l1");
11155 #if defined(AST_MISDN_ENHANCEMENTS)
11156  ast_unregister_application(misdn_command_name);
11157  ast_custom_function_unregister(&misdn_cc_function);
11158 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11159 
11160  ast_channel_unregister(&misdn_tech);
11161 
11162  free_robin_list();
11165 
11166  ast_free(misdn_out_calls);
11167  ast_free(misdn_in_calls);
11168  ast_free(misdn_debug_only);
11169  ast_free(misdn_ports);
11170  ast_free(misdn_debug);
11171 
11172 #if defined(AST_MISDN_ENHANCEMENTS)
11173  misdn_cc_destroy();
11174 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11175 
11176  return 0;
11177 }
11178 
11179 static int load_module(void)
11180 {
11181  int i, port;
11182  int ntflags = 0, ntkc = 0;
11183  char ports[256] = "";
11184  char tempbuf[BUFFERSIZE + 1];
11185  char ntfile[BUFFERSIZE + 1];
11186  struct misdn_lib_iface iface = {
11187  .cb_event = cb_events,
11188  .cb_log = chan_misdn_log,
11189  .cb_jb_empty = chan_misdn_jb_empty,
11190  };
11191 
11192  max_ports = misdn_lib_maxports_get();
11193 
11194  if (max_ports <= 0) {
11195  ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
11196  return AST_MODULE_LOAD_DECLINE;
11197  }
11198 
11199  if (misdn_cfg_init(max_ports, 0)) {
11200  ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
11201  return AST_MODULE_LOAD_DECLINE;
11202  }
11203  g_config_initialized = 1;
11204 
11205 #if defined(AST_MISDN_ENHANCEMENTS)
11206  misdn_cc_init();
11207 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11208 
11209  misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
11210  if (!misdn_debug) {
11211  ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
11212  return AST_MODULE_LOAD_DECLINE;
11213  }
11214  misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
11215  if (!misdn_ports) {
11216  ast_free(misdn_debug);
11217  ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
11218  return AST_MODULE_LOAD_DECLINE;
11219  }
11220  misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
11221  for (i = 1; i <= max_ports; i++) {
11222  misdn_debug[i] = misdn_debug[0];
11223  misdn_ports[i] = i;
11224  }
11225  *misdn_ports = 0;
11226  misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
11227  if (!misdn_debug_only) {
11228  ast_free(misdn_ports);
11229  ast_free(misdn_debug);
11230  ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
11231  return AST_MODULE_LOAD_DECLINE;
11232  }
11233 
11234  misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
11235  if (!ast_strlen_zero(tempbuf)) {
11236  tracing = 1;
11237  }
11238 
11239  misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11240  if (!misdn_in_calls) {
11241  ast_free(misdn_debug_only);
11242  ast_free(misdn_ports);
11243  ast_free(misdn_debug);
11244  ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
11245  return AST_MODULE_LOAD_DECLINE;
11246  }
11247  misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11248  if (!misdn_out_calls) {
11249  ast_free(misdn_in_calls);
11250  ast_free(misdn_debug_only);
11251  ast_free(misdn_ports);
11252  ast_free(misdn_debug);
11253  ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
11254  return AST_MODULE_LOAD_DECLINE;
11255  }
11256 
11257  for (i = 1; i <= max_ports; i++) {
11258  misdn_in_calls[i] = 0;
11259  misdn_out_calls[i] = 0;
11260  }
11261 
11262  ast_mutex_init(&cl_te_lock);
11263  ast_mutex_init(&release_lock);
11264 
11267 
11268  if (!ast_strlen_zero(ports)) {
11269  chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
11270  }
11271  if (misdn_lib_init(ports, &iface, NULL)) {
11272  chan_misdn_log(0, 0, "No te ports initialized\n");
11273  }
11274 
11275  misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
11276  misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
11277  misdn_cfg_get(0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
11278 
11279  misdn_lib_nt_keepcalls(ntkc);
11280  misdn_lib_nt_debug_init(ntflags, ntfile);
11281 
11282  if (ast_channel_register(&misdn_tech)) {
11283  ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
11284  unload_module();
11285  return AST_MODULE_LOAD_DECLINE;
11286  }
11287 
11288  ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11289 
11290  ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
11291  "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
11292  "Sets mISDN opts. and optargs\n"
11293  "\n"
11294  "The available options are:\n"
11295  " a - Have Asterisk detect DTMF tones on called channel\n"
11296  " c - Make crypted outgoing call, optarg is keyindex\n"
11297  " d - Send display text to called phone, text is the optarg\n"
11298  " e - Perform echo cancellation on this channel,\n"
11299  " takes taps as optarg (32,64,128,256)\n"
11300  " e! - Disable echo cancellation on this channel\n"
11301  " f - Enable fax detection\n"
11302  " h - Make digital outgoing call\n"
11303  " h1 - Make HDLC mode digital outgoing call\n"
11304  " i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
11305  " they will be transported inband.\n"
11306  " jb - Set jitter buffer length, optarg is length\n"
11307  " jt - Set jitter buffer upper threshold, optarg is threshold\n"
11308  " jn - Disable jitter buffer\n"
11309  " n - Disable mISDN DSP on channel.\n"
11310  " Disables: echo cancel, DTMF detection, and volume control.\n"
11311  " p - Caller ID presentation,\n"
11312  " optarg is either 'allowed' or 'restricted'\n"
11313  " s - Send Non-inband DTMF as inband\n"
11314  " vr - Rx gain control, optarg is gain\n"
11315  " vt - Tx gain control, optarg is gain\n"
11316  );
11317 
11318 
11319  ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
11320  "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
11321  "Sends the Facility Message FACILITY_TYPE with \n"
11322  "the given Arguments to the current ISDN Channel\n"
11323  "Supported Facilities are:\n"
11324  "\n"
11325  "type=calldeflect args=Nr where to deflect\n"
11326 #if defined(AST_MISDN_ENHANCEMENTS)
11327  "type=callrerouting args=Nr where to deflect\n"
11328 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11329  );
11330 
11331 
11332  ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
11333  "misdn_check_l2l1(<port>||g:<groupname>,timeout)\n"
11334  "Checks if the L2 and L1 are up on either the given <port> or\n"
11335  "on the ports in the group with <groupname>\n"
11336  "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
11337  "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
11338  "\n"
11339  "This application, ensures the L1/L2 state of the Ports in a group\n"
11340  "it is intended to make the pmp_l1_check option redundant and to\n"
11341  "fix a buggy switch config from your provider\n"
11342  "\n"
11343  "a sample dialplan would look like:\n\n"
11344  "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
11345  "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
11346  );
11347 
11348 #if defined(AST_MISDN_ENHANCEMENTS)
11349  ast_register_application(misdn_command_name, misdn_command_exec, misdn_command_name,
11350  "misdn_command(<command>[,<options>])\n"
11351  "The following commands are defined:\n"
11352  "cc-initialize\n"
11353  " Setup mISDN support for call completion\n"
11354  " Must call before doing any Dial() involving call completion.\n"
11355  "ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11356  " Request Call Completion No Reply activation\n"
11357  "ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11358  " Request Call Completion Busy Subscriber activation\n"
11359  "cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11360  " Set the dialplan location to notify when User-B is available but User-A is busy.\n"
11361  " Setting this dialplan location is optional.\n"
11362  "cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>\n"
11363  " Set the busy status of call completion User-A\n"
11364  "cc-deactivate,${MISDN_CC_RECORD_ID}\n"
11365  " Deactivate the identified call completion request\n"
11366  "\n"
11367  "MISDN_CC_RECORD_ID is set when Dial() returns and call completion is possible\n"
11368  "MISDN_CC_STATUS is set to ACTIVATED or ERROR after the call completion\n"
11369  "activation request.\n"
11370  "MISDN_ERROR_MSG is set to a descriptive message on error.\n"
11371  );
11372 
11373  ast_custom_function_register(&misdn_cc_function);
11374 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11375 
11376  misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
11377 
11378  /* start the l1 watchers */
11379 
11380  for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
11381  int l1timeout;
11382  misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
11383  if (l1timeout) {
11384  chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
11385  misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
11386  }
11387  }
11388 
11389  chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
11390 
11391  return 0;
11392 }
11393 
11394 
11395 
11396 static int reload(void)
11397 {
11398  reload_config();
11399 
11400  return 0;
11401 }
11402 
11403 /*** SOME APPS ;)***/
11404 
11405 #if defined(AST_MISDN_ENHANCEMENTS)
11406 /*!
11407 * \brief misdn_command arguments container.
11408 */
11409 AST_DEFINE_APP_ARGS_TYPE(misdn_command_args,
11410  AST_APP_ARG(name); /* Subcommand name */
11411  AST_APP_ARG(arg)[10 + 1]; /* Subcommand arguments */
11412 );
11413 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11414 
11415 #if defined(AST_MISDN_ENHANCEMENTS)
11416 static void misdn_cc_caller_destroy(void *obj)
11417 {
11418  /* oh snap! */
11419 }
11420 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11421 
11422 #if defined(AST_MISDN_ENHANCEMENTS)
11423 static struct misdn_cc_caller *misdn_cc_caller_alloc(struct ast_channel *chan)
11424 {
11425  struct misdn_cc_caller *cc_caller;
11426 
11427  if (!(cc_caller = ao2_alloc(sizeof(*cc_caller), misdn_cc_caller_destroy))) {
11428  return NULL;
11429  }
11430 
11431  cc_caller->chan = chan;
11432 
11433  return cc_caller;
11434 }
11435 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11436 
11437 #if defined(AST_MISDN_ENHANCEMENTS)
11438 /*!
11439  * \internal
11440  * \brief misdn_command(cc-initialize) subcommand handler
11441  *
11442  * \param chan Asterisk channel to operate upon.
11443  * \param subcommand Arguments for the subcommand
11444  *
11445  * \retval 0 on success.
11446  * \retval -1 on error.
11447  */
11448 static int misdn_command_cc_initialize(struct ast_channel *chan, struct misdn_command_args *subcommand)
11449 {
11450  struct misdn_cc_caller *cc_caller;
11451  struct ast_datastore *datastore;
11452 
11453  if (!(cc_caller = misdn_cc_caller_alloc(chan))) {
11454  return -1;
11455  }
11456 
11457  if (!(datastore = ast_datastore_alloc(&misdn_cc_ds_info, NULL))) {
11458  ao2_ref(cc_caller, -1);
11459  return -1;
11460  }
11461 
11462  ast_channel_lock(chan);
11463 
11464  /* Inherit reference */
11465  datastore->data = cc_caller;
11466  cc_caller = NULL;
11467 
11469 
11470  ast_channel_datastore_add(chan, datastore);
11471 
11472  ast_channel_unlock(chan);
11473 
11474  return 0;
11475 }
11476 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11477 
11478 #if defined(AST_MISDN_ENHANCEMENTS)
11479 /*!
11480  * \internal
11481  * \brief misdn_command(cc-deactivate) subcommand handler
11482  *
11483  * \details
11484  * misdn_command(cc-deactivate,${MISDN_CC_RECORD_ID})
11485  * Deactivate a call completion service instance.
11486  *
11487  * \param chan Asterisk channel to operate upon.
11488  * \param subcommand Arguments for the subcommand
11489  *
11490  * \retval 0 on success.
11491  * \retval -1 on error.
11492  */
11493 static int misdn_command_cc_deactivate(struct ast_channel *chan, struct misdn_command_args *subcommand)
11494 {
11495  long record_id;
11496  const char *error_str;
11497  struct misdn_cc_record *cc_record;
11498  struct misdn_bchannel *bc;
11499  struct misdn_bchannel dummy;
11500 
11501  static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID})\n";
11502 
11503  if (ast_strlen_zero(subcommand->arg[0]) || !isdigit(*subcommand->arg[0])) {
11504  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11505  return -1;
11506  }
11507  record_id = atol(subcommand->arg[0]);
11508 
11509  AST_LIST_LOCK(&misdn_cc_records_db);
11510  cc_record = misdn_cc_find_by_id(record_id);
11511  if (cc_record && 0 <= cc_record->port) {
11512  if (cc_record->ptp) {
11513  if (cc_record->mode.ptp.bc) {
11514  /* Close the call-completion signaling link */
11515  bc = cc_record->mode.ptp.bc;
11516  bc->fac_out.Function = Fac_None;
11519  }
11520  misdn_cc_delete(cc_record);
11521  } else if (cc_record->activated) {
11522  cc_record->error_code = FacError_None;
11523  cc_record->reject_code = FacReject_None;
11524  cc_record->invoke_id = ++misdn_invoke_id;
11525  cc_record->outstanding_message = 1;
11526 
11527  /* Build message */
11528  misdn_make_dummy(&dummy, cc_record->port, 0, misdn_lib_port_is_nt(cc_record->port), 0);
11529  dummy.fac_out.Function = Fac_CCBSDeactivate;
11530  dummy.fac_out.u.CCBSDeactivate.InvokeID = cc_record->invoke_id;
11531  dummy.fac_out.u.CCBSDeactivate.ComponentType = FacComponent_Invoke;
11532  dummy.fac_out.u.CCBSDeactivate.Component.Invoke.CCBSReference = cc_record->mode.ptmp.reference_id;
11533 
11534  /* Send message */
11535  print_facility(&dummy.fac_out, &dummy);
11537  }
11538  }
11539  AST_LIST_UNLOCK(&misdn_cc_records_db);
11540 
11541  /* Wait for the response to the call completion deactivation request. */
11542  misdn_cc_response_wait(chan, MISDN_CC_REQUEST_WAIT_MAX, record_id);
11543 
11544  AST_LIST_LOCK(&misdn_cc_records_db);
11545  cc_record = misdn_cc_find_by_id(record_id);
11546  if (cc_record) {
11547  if (cc_record->port < 0) {
11548  /* The network did not tell us that call completion was available. */
11549  error_str = NULL;
11550  } else if (cc_record->outstanding_message) {
11551  cc_record->outstanding_message = 0;
11552  error_str = misdn_no_response_from_network;
11553  } else if (cc_record->reject_code != FacReject_None) {
11554  error_str = misdn_to_str_reject_code(cc_record->reject_code);
11555  } else if (cc_record->error_code != FacError_None) {
11556  error_str = misdn_to_str_error_code(cc_record->error_code);
11557  } else {
11558  error_str = NULL;
11559  }
11560 
11561  misdn_cc_delete(cc_record);
11562  } else {
11563  error_str = NULL;
11564  }
11565  AST_LIST_UNLOCK(&misdn_cc_records_db);
11566  if (error_str) {
11567  ast_verb(1, "%s(%s) diagnostic '%s' on channel %s\n",
11568  misdn_command_name, subcommand->name, error_str, chan->name);
11569  pbx_builtin_setvar_helper(chan, MISDN_ERROR_MSG, error_str);
11570  }
11571 
11572  return 0;
11573 }
11574 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11575 
11576 #if defined(AST_MISDN_ENHANCEMENTS)
11577 /*!
11578  * \internal
11579  * \brief misdn_command(cc-a-busy) subcommand handler
11580  *
11581  * \details
11582  * misdn_command(cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>)
11583  * Set the status of User-A for a call completion service instance.
11584  *
11585  * \param chan Asterisk channel to operate upon.
11586  * \param subcommand Arguments for the subcommand
11587  *
11588  * \retval 0 on success.
11589  * \retval -1 on error.
11590  */
11591 static int misdn_command_cc_a_busy(struct ast_channel *chan, struct misdn_command_args *subcommand)
11592 {
11593  long record_id;
11594  int party_a_free;
11595  struct misdn_cc_record *cc_record;
11596  struct misdn_bchannel *bc;
11597 
11598  static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<yes/no>)\n";
11599 
11600  if (ast_strlen_zero(subcommand->arg[0]) || !isdigit(*subcommand->arg[0])) {
11601  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11602  return -1;
11603  }
11604  record_id = atol(subcommand->arg[0]);
11605 
11606  if (ast_true(subcommand->arg[1])) {
11607  party_a_free = 0;
11608  } else if (ast_false(subcommand->arg[1])) {
11609  party_a_free = 1;
11610  } else {
11611  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11612  return -1;
11613  }
11614 
11615  AST_LIST_LOCK(&misdn_cc_records_db);
11616  cc_record = misdn_cc_find_by_id(record_id);
11617  if (cc_record && cc_record->party_a_free != party_a_free) {
11618  /* User-A's status has changed */
11619  cc_record->party_a_free = party_a_free;
11620 
11621  if (cc_record->ptp && cc_record->mode.ptp.bc) {
11622  cc_record->error_code = FacError_None;
11623  cc_record->reject_code = FacReject_None;
11624 
11625  /* Build message */
11626  bc = cc_record->mode.ptp.bc;
11627  if (cc_record->party_a_free) {
11628  bc->fac_out.Function = Fac_CCBS_T_Resume;
11629  bc->fac_out.u.CCBS_T_Resume.InvokeID = ++misdn_invoke_id;
11630  } else {
11631  bc->fac_out.Function = Fac_CCBS_T_Suspend;
11632  bc->fac_out.u.CCBS_T_Suspend.InvokeID = ++misdn_invoke_id;
11633  }
11634 
11635  /* Send message */
11636  print_facility(&bc->fac_out, bc);
11638  }
11639  }
11640  AST_LIST_UNLOCK(&misdn_cc_records_db);
11641 
11642  return 0;
11643 }
11644 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11645 
11646 #if defined(AST_MISDN_ENHANCEMENTS)
11647 /*!
11648  * \internal
11649  * \brief misdn_command(cc-b-free) subcommand handler
11650  *
11651  * \details
11652  * misdn_command(cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
11653  * Set the dialplan location to notify when User-B is free and User-A is busy.
11654  *
11655  * \param chan Asterisk channel to operate upon.
11656  * \param subcommand Arguments for the subcommand
11657  *
11658  * \retval 0 on success.
11659  * \retval -1 on error.
11660  */
11661 static int misdn_command_cc_b_free(struct ast_channel *chan, struct misdn_command_args *subcommand)
11662 {
11663  unsigned index;
11664  long record_id;
11665  int priority;
11666  char *context;
11667  char *exten;
11668  struct misdn_cc_record *cc_record;
11669 
11670  static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)\n";
11671 
11672  /* Check that all arguments are present */
11673  for (index = 0; index < 4; ++index) {
11674  if (ast_strlen_zero(subcommand->arg[index])) {
11675  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11676  return -1;
11677  }
11678  }
11679 
11680  /* These must be numeric */
11681  if (!isdigit(*subcommand->arg[0]) || !isdigit(*subcommand->arg[3])) {
11682  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11683  return -1;
11684  }
11685 
11686  record_id = atol(subcommand->arg[0]);
11687  context = subcommand->arg[1];
11688  exten = subcommand->arg[2];
11689  priority = atoi(subcommand->arg[3]);
11690 
11691  AST_LIST_LOCK(&misdn_cc_records_db);
11692  cc_record = misdn_cc_find_by_id(record_id);
11693  if (cc_record) {
11694  /* Save User-B free information */
11695  ast_copy_string(cc_record->b_free.context, context, sizeof(cc_record->b_free.context));
11696  ast_copy_string(cc_record->b_free.exten, exten, sizeof(cc_record->b_free.exten));
11697  cc_record->b_free.priority = priority;
11698  }
11699  AST_LIST_UNLOCK(&misdn_cc_records_db);
11700 
11701  return 0;
11702 }
11703 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11704 
11705 #if defined(AST_MISDN_ENHANCEMENTS)
11706 struct misdn_cc_request {
11707  enum FacFunction ptmp;
11708  enum FacFunction ptp;
11709 };
11710 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11711 
11712 #if defined(AST_MISDN_ENHANCEMENTS)
11713 /*!
11714  * \internal
11715  * \brief misdn_command(ccbs-request/ccnr-request) subcommand handler helper
11716  *
11717  * \details
11718  * misdn_command(ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
11719  * misdn_command(ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
11720  * Set the dialplan location to notify when User-B is free and User-A is free.
11721  *
11722  * \param chan Asterisk channel to operate upon.
11723  * \param subcommand Arguments for the subcommand
11724  * \param request Which call-completion request message to generate.
11725  *
11726  * \retval 0 on success.
11727  * \retval -1 on error.
11728  */
11729 static int misdn_command_cc_request(struct ast_channel *chan, struct misdn_command_args *subcommand, const struct misdn_cc_request *request)
11730 {
11731  unsigned index;
11732  int request_retention;
11733  long record_id;
11734  int priority;
11735  char *context;
11736  char *exten;
11737  const char *error_str;
11738  struct misdn_cc_record *cc_record;
11739  struct misdn_bchannel *bc;
11740  struct misdn_bchannel dummy;
11741  struct misdn_party_id id;
11742 
11743  static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)\n";
11744 
11745  /* Check that all arguments are present */
11746  for (index = 0; index < 4; ++index) {
11747  if (ast_strlen_zero(subcommand->arg[index])) {
11748  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11749  return -1;
11750  }
11751  }
11752 
11753  /* These must be numeric */
11754  if (!isdigit(*subcommand->arg[0]) || !isdigit(*subcommand->arg[3])) {
11755  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11756  return -1;
11757  }
11758 
11759  record_id = atol(subcommand->arg[0]);
11760  context = subcommand->arg[1];
11761  exten = subcommand->arg[2];
11762  priority = atoi(subcommand->arg[3]);
11763 
11764  AST_LIST_LOCK(&misdn_cc_records_db);
11765  cc_record = misdn_cc_find_by_id(record_id);
11766  if (cc_record) {
11767  /* Save User-B free information */
11768  ast_copy_string(cc_record->remote_user_free.context, context,
11769  sizeof(cc_record->remote_user_free.context));
11770  ast_copy_string(cc_record->remote_user_free.exten, exten,
11771  sizeof(cc_record->remote_user_free.exten));
11772  cc_record->remote_user_free.priority = priority;
11773 
11774  if (0 <= cc_record->port) {
11775  if (cc_record->ptp) {
11776  if (!cc_record->mode.ptp.bc) {
11777  bc = misdn_lib_get_register_bc(cc_record->port);
11778  if (bc) {
11779  cc_record->mode.ptp.bc = bc;
11780  cc_record->error_code = FacError_None;
11781  cc_record->reject_code = FacReject_None;
11782  cc_record->invoke_id = ++misdn_invoke_id;
11783  cc_record->outstanding_message = 1;
11784  cc_record->activation_requested = 1;
11785 
11787  &request_retention, sizeof(request_retention));
11788  cc_record->mode.ptp.requested_retention = request_retention ? 1 : 0;
11789 
11790  /* Build message */
11791  bc->fac_out.Function = request->ptp;
11792  bc->fac_out.u.CCBS_T_Request.InvokeID = cc_record->invoke_id;
11793  bc->fac_out.u.CCBS_T_Request.ComponentType = FacComponent_Invoke;
11794  bc->fac_out.u.CCBS_T_Request.Component.Invoke.Q931ie =
11795  cc_record->redial.setup_bc_hlc_llc;
11796  memset(&id, 0, sizeof(id));
11797  id.number_plan = cc_record->redial.dialed.number_plan;
11798  id.number_type = cc_record->redial.dialed.number_type;
11799  ast_copy_string(id.number, cc_record->redial.dialed.number,
11800  sizeof(id.number));
11801  misdn_Address_fill(
11802  &bc->fac_out.u.CCBS_T_Request.Component.Invoke.Destination,
11803  &id);
11804  misdn_Address_fill(
11805  &bc->fac_out.u.CCBS_T_Request.Component.Invoke.Originating,
11806  &cc_record->redial.caller);
11807  bc->fac_out.u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1;
11808  bc->fac_out.u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator =
11809  (cc_record->redial.caller.presentation != 0) ? 0 : 1;
11810  bc->fac_out.u.CCBS_T_Request.Component.Invoke.RetentionSupported =
11811  request_retention ? 1 : 0;
11812 
11813  /* Send message */
11814  print_facility(&bc->fac_out, bc);
11816  }
11817  }
11818  } else {
11819  cc_record->error_code = FacError_None;
11820  cc_record->reject_code = FacReject_None;
11821  cc_record->invoke_id = ++misdn_invoke_id;
11822  cc_record->outstanding_message = 1;
11823  cc_record->activation_requested = 1;
11824 
11825  /* Build message */
11826  misdn_make_dummy(&dummy, cc_record->port, 0,
11827  misdn_lib_port_is_nt(cc_record->port), 0);
11828  dummy.fac_out.Function = request->ptmp;
11829  dummy.fac_out.u.CCBSRequest.InvokeID = cc_record->invoke_id;
11830  dummy.fac_out.u.CCBSRequest.ComponentType = FacComponent_Invoke;
11831  dummy.fac_out.u.CCBSRequest.Component.Invoke.CallLinkageID =
11832  cc_record->mode.ptmp.linkage_id;
11833 
11834  /* Send message */
11835  print_facility(&dummy.fac_out, &dummy);
11837  }
11838  }
11839  }
11840  AST_LIST_UNLOCK(&misdn_cc_records_db);
11841 
11842  /* Wait for the response to the call completion request. */
11843  misdn_cc_response_wait(chan, MISDN_CC_REQUEST_WAIT_MAX, record_id);
11844 
11845  AST_LIST_LOCK(&misdn_cc_records_db);
11846  cc_record = misdn_cc_find_by_id(record_id);
11847  if (cc_record) {
11848  if (!cc_record->activated) {
11849  if (cc_record->port < 0) {
11850  /* The network did not tell us that call completion was available. */
11851  error_str = "No port number";
11852  } else if (cc_record->outstanding_message) {
11853  cc_record->outstanding_message = 0;
11854  error_str = misdn_no_response_from_network;
11855  } else if (cc_record->reject_code != FacReject_None) {
11856  error_str = misdn_to_str_reject_code(cc_record->reject_code);
11857  } else if (cc_record->error_code != FacError_None) {
11858  error_str = misdn_to_str_error_code(cc_record->error_code);
11859  } else if (cc_record->ptp) {
11860  if (cc_record->mode.ptp.bc) {
11861  error_str = "Call-completion already requested";
11862  } else {
11863  error_str = "Could not allocate call-completion signaling link";
11864  }
11865  } else {
11866  /* Should never happen. */
11867  error_str = "Unexpected error";
11868  }
11869 
11870  /* No need to keep the call completion record. */
11871  if (cc_record->ptp && cc_record->mode.ptp.bc) {
11872  /* Close the call-completion signaling link */
11873  bc = cc_record->mode.ptp.bc;
11874  bc->fac_out.Function = Fac_None;
11877  }
11878  misdn_cc_delete(cc_record);
11879  } else {
11880  error_str = NULL;
11881  }
11882  } else {
11883  error_str = misdn_cc_record_not_found;
11884  }
11885  AST_LIST_UNLOCK(&misdn_cc_records_db);
11886  if (error_str) {
11887  ast_verb(1, "%s(%s) diagnostic '%s' on channel %s\n",
11888  misdn_command_name, subcommand->name, error_str, chan->name);
11889  pbx_builtin_setvar_helper(chan, MISDN_ERROR_MSG, error_str);
11890  pbx_builtin_setvar_helper(chan, MISDN_CC_STATUS, "ERROR");
11891  } else {
11892  pbx_builtin_setvar_helper(chan, MISDN_CC_STATUS, "ACTIVATED");
11893  }
11894 
11895  return 0;
11896 }
11897 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11898 
11899 #if defined(AST_MISDN_ENHANCEMENTS)
11900 /*!
11901  * \internal
11902  * \brief misdn_command(ccbs-request) subcommand handler
11903  *
11904  * \details
11905  * misdn_command(ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
11906  * Set the dialplan location to notify when User-B is free and User-A is free.
11907  *
11908  * \param chan Asterisk channel to operate upon.
11909  * \param subcommand Arguments for the subcommand
11910  *
11911  * \retval 0 on success.
11912  * \retval -1 on error.
11913  */
11914 static int misdn_command_ccbs_request(struct ast_channel *chan, struct misdn_command_args *subcommand)
11915 {
11916  static const struct misdn_cc_request request = {
11917  .ptmp = Fac_CCBSRequest,
11918  .ptp = Fac_CCBS_T_Request
11919  };
11920 
11921  return misdn_command_cc_request(chan, subcommand, &request);
11922 }
11923 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11924 
11925 #if defined(AST_MISDN_ENHANCEMENTS)
11926 /*!
11927  * \internal
11928  * \brief misdn_command(ccnr-request) subcommand handler
11929  *
11930  * \details
11931  * misdn_command(ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
11932  * Set the dialplan location to notify when User-B is free and User-A is free.
11933  *
11934  * \param chan Asterisk channel to operate upon.
11935  * \param subcommand Arguments for the subcommand
11936  *
11937  * \retval 0 on success.
11938  * \retval -1 on error.
11939  */
11940 static int misdn_command_ccnr_request(struct ast_channel *chan, struct misdn_command_args *subcommand)
11941 {
11942  static const struct misdn_cc_request request = {
11943  .ptmp = Fac_CCNRRequest,
11944  .ptp = Fac_CCNR_T_Request
11945  };
11946 
11947  return misdn_command_cc_request(chan, subcommand, &request);
11948 }
11949 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11950 
11951 #if defined(AST_MISDN_ENHANCEMENTS)
11952 struct misdn_command_table {
11953  /*! \brief subcommand name */
11954  const char *name;
11955 
11956  /*! \brief subcommand handler */
11957  int (*func)(struct ast_channel *chan, struct misdn_command_args *subcommand);
11958 
11959  /*! \brief TRUE if the subcommand can only be executed on mISDN channels */
11960  int misdn_only;
11961 };
11962 static const struct misdn_command_table misdn_commands[] = {
11963 /* *INDENT-OFF* */
11964  /* subcommand-name subcommand-handler mISDN only */
11965  { "cc-initialize", misdn_command_cc_initialize, 0 },
11966  { "cc-deactivate", misdn_command_cc_deactivate, 0 },
11967  { "cc-a-busy", misdn_command_cc_a_busy, 0 },
11968  { "cc-b-free", misdn_command_cc_b_free, 0 },
11969  { "ccbs-request", misdn_command_ccbs_request, 0 },
11970  { "ccnr-request", misdn_command_ccnr_request, 0 },
11971 /* *INDENT-ON* */
11972 };
11973 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11974 
11975 #if defined(AST_MISDN_ENHANCEMENTS)
11976 /*!
11977  * \internal
11978  * \brief misdn_command() dialplan application.
11979  *
11980  * \param chan Asterisk channel to operate upon.
11981  * \param data Application options string.
11982  *
11983  * \retval 0 on success.
11984  * \retval -1 on error.
11985  */
11986 static int misdn_command_exec(struct ast_channel *chan, const char *data)
11987 {
11988  char *parse;
11989  unsigned index;
11990  struct misdn_command_args subcommand;
11991 
11992  if (ast_strlen_zero((char *) data)) {
11993  ast_log(LOG_ERROR, "%s requires arguments\n", misdn_command_name);
11994  return -1;
11995  }
11996 
11997  ast_log(LOG_DEBUG, "%s(%s)\n", misdn_command_name, (char *) data);
11998 
11999  parse = ast_strdupa(data);
12000  AST_STANDARD_APP_ARGS(subcommand, parse);
12001  if (!subcommand.argc || ast_strlen_zero(subcommand.name)) {
12002  ast_log(LOG_ERROR, "%s requires a subcommand\n", misdn_command_name);
12003  return -1;
12004  }
12005 
12006  for (index = 0; index < ARRAY_LEN(misdn_commands); ++index) {
12007  if (strcasecmp(misdn_commands[index].name, subcommand.name) == 0) {
12008  strcpy(subcommand.name, misdn_commands[index].name);
12009  if (misdn_commands[index].misdn_only
12010  && strcasecmp(chan->tech->type, misdn_type) != 0) {
12012  "%s(%s) only makes sense with %s channels!\n",
12013  misdn_command_name, subcommand.name, misdn_type);
12014  return -1;
12015  }
12016  return misdn_commands[index].func(chan, &subcommand);
12017  }
12018  }
12019 
12020  ast_log(LOG_WARNING, "%s(%s) subcommand is unknown\n", misdn_command_name,
12021  subcommand.name);
12022  return -1;
12023 }
12024 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
12025 
12026 static int misdn_facility_exec(struct ast_channel *chan, const char *data)
12027 {
12028  struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12029  char *parse;
12030  unsigned max_len;
12031 
12033  AST_APP_ARG(facility_type);
12034  AST_APP_ARG(arg)[99];
12035  );
12036 
12037  chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
12038 
12039  if (strcasecmp(chan->tech->type, misdn_type)) {
12040  ast_log(LOG_WARNING, "misdn_facility only makes sense with %s channels!\n", misdn_type);
12041  return -1;
12042  }
12043 
12044  if (ast_strlen_zero((char *) data)) {
12045  ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12046  return -1;
12047  }
12048 
12049  parse = ast_strdupa(data);
12050  AST_STANDARD_APP_ARGS(args, parse);
12051 
12052  if (ast_strlen_zero(args.facility_type)) {
12053  ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12054  return -1;
12055  }
12056 
12057  if (!strcasecmp(args.facility_type, "calldeflect")) {
12058  if (ast_strlen_zero(args.arg[0])) {
12059  ast_log(LOG_WARNING, "Facility: Call Deflection requires an argument: Number\n");
12060  }
12061 
12062 #if defined(AST_MISDN_ENHANCEMENTS)
12063  max_len = sizeof(ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
12064  if (max_len < strlen(args.arg[0])) {
12066  "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12067  max_len);
12068  return 0;
12069  }
12070  ch->bc->fac_out.Function = Fac_CallDeflection;
12071  ch->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
12072  ch->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
12073  ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
12074  ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
12075  ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
12076  ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(args.arg[0]);
12077  strcpy((char *) ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, args.arg[0]);
12078  ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
12079 
12080 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
12081 
12082  max_len = sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
12083  if (max_len < strlen(args.arg[0])) {
12085  "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12086  max_len);
12087  return 0;
12088  }
12089  ch->bc->fac_out.Function = Fac_CD;
12090  ch->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
12091  //ch->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
12092  strcpy((char *) ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0]);
12093 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
12094 
12095  /* Send message */
12096  print_facility(&ch->bc->fac_out, ch->bc);
12098 #if defined(AST_MISDN_ENHANCEMENTS)
12099  } else if (!strcasecmp(args.facility_type, "callrerouteing")
12100  || !strcasecmp(args.facility_type, "callrerouting")) {
12101  if (ast_strlen_zero(args.arg[0])) {
12102  ast_log(LOG_WARNING, "Facility: Call rerouting requires an argument: Number\n");
12103  }
12104 
12105  max_len = sizeof(ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
12106  if (max_len < strlen(args.arg[0])) {
12108  "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12109  max_len);
12110  return 0;
12111  }
12112  ch->bc->fac_out.Function = Fac_CallRerouteing;
12113  ch->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
12114  ch->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
12115 
12116  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
12117  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
12118 
12119  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
12120  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(args.arg[0]);
12121  strcpy((char *) ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, args.arg[0]);
12122  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
12123 
12124  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
12125 
12126  /* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
12127  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
12128  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
12129  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
12130  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
12131  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
12132  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
12133  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
12134 
12135  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
12136  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
12137 
12138  /* Send message */
12139  print_facility(&ch->bc->fac_out, ch->bc);
12141 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
12142  } else {
12143  chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", args.facility_type);
12144  }
12145 
12146  return 0;
12147 }
12148 
12149 static int misdn_check_l2l1(struct ast_channel *chan, const char *data)
12150 {
12151  char *parse;
12152  char group[BUFFERSIZE + 1];
12153  char *port_str;
12154  int port = 0;
12155  int timeout;
12156  int dowait = 0;
12157  int port_up;
12158 
12160  AST_APP_ARG(grouppar);
12161  AST_APP_ARG(timeout);
12162  );
12163 
12164  if (ast_strlen_zero((char *) data)) {
12165  ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
12166  return -1;
12167  }
12168 
12169  parse = ast_strdupa(data);
12170  AST_STANDARD_APP_ARGS(args, parse);
12171 
12172  if (args.argc != 2) {
12173  ast_log(LOG_WARNING, "Wrong argument count\n");
12174  return 0;
12175  }
12176 
12177  /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
12178  timeout = atoi(args.timeout);
12179  port_str = args.grouppar;
12180 
12181  if (port_str[0] == 'g' && port_str[1] == ':') {
12182  /* We make a group call lets checkout which ports are in my group */
12183  port_str += 2;
12184  ast_copy_string(group, port_str, sizeof(group));
12185  chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
12186 
12187  for (port = misdn_cfg_get_next_port(port);
12188  port > 0;
12189  port = misdn_cfg_get_next_port(port)) {
12190  char cfg_group[BUFFERSIZE + 1];
12191 
12192  chan_misdn_log(2, 0, "trying port %d\n", port);
12193 
12194  misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
12195 
12196  if (!strcasecmp(cfg_group, group)) {
12197  port_up = misdn_lib_port_up(port, 1);
12198  if (!port_up) {
12199  chan_misdn_log(2, 0, " --> port '%d'\n", port);
12200  misdn_lib_get_port_up(port);
12201  dowait = 1;
12202  }
12203  }
12204  }
12205  } else {
12206  port = atoi(port_str);
12207  chan_misdn_log(2, 0, "Checking Port: %d\n", port);
12208  port_up = misdn_lib_port_up(port, 1);
12209  if (!port_up) {
12210  misdn_lib_get_port_up(port);
12211  dowait = 1;
12212  }
12213  }
12214 
12215  if (dowait) {
12216  chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
12217  ast_safe_sleep(chan, timeout * 1000);
12218  }
12219 
12220  return 0;
12221 }
12222 
12223 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data)
12224 {
12225  struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12226  char *tok;
12227  char *tokb;
12228  char *parse;
12229  int keyidx = 0;
12230  int rxgain = 0;
12231  int txgain = 0;
12232  int change_jitter = 0;
12233 
12234  if (strcasecmp(chan->tech->type, misdn_type)) {
12235  ast_log(LOG_WARNING, "misdn_set_opt makes sense only with %s channels!\n", misdn_type);
12236  return -1;
12237  }
12238 
12239  if (ast_strlen_zero((char *) data)) {
12240  ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
12241  return -1;
12242  }
12243 
12244  parse = ast_strdupa(data);
12245  for (tok = strtok_r(parse, ":", &tokb);
12246  tok;
12247  tok = strtok_r(NULL, ":", &tokb)) {
12248  int neglect = 0;
12249 
12250  if (tok[0] == '!') {
12251  neglect = 1;
12252  tok++;
12253  }
12254 
12255  switch(tok[0]) {
12256  case 'd' :
12257  ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
12258  chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
12259  break;
12260  case 'n':
12261  chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
12262  ch->bc->nodsp = 1;
12263  break;
12264  case 'j':
12265  chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
12266  tok++;
12267  change_jitter = 1;
12268 
12269  switch (tok[0]) {
12270  case 'b':
12271  ch->jb_len = atoi(++tok);
12272  chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
12273  break;
12274  case 't' :
12275  ch->jb_upper_threshold = atoi(++tok);
12276  chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
12277  break;
12278  case 'n':
12279  ch->bc->nojitter = 1;
12280  chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
12281  break;
12282  default:
12283  ch->jb_len = 4000;
12284  ch->jb_upper_threshold = 0;
12285  chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
12286  chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
12287  break;
12288  }
12289  break;
12290  case 'v':
12291  tok++;
12292 
12293  switch (tok[0]) {
12294  case 'r' :
12295  rxgain = atoi(++tok);
12296  if (rxgain < -8) {
12297  rxgain = -8;
12298  }
12299  if (rxgain > 8) {
12300  rxgain = 8;
12301  }
12302  ch->bc->rxgain = rxgain;
12303  chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
12304  break;
12305  case 't':
12306  txgain = atoi(++tok);
12307  if (txgain < -8) {
12308  txgain = -8;
12309  }
12310  if (txgain > 8) {
12311  txgain = 8;
12312  }
12313  ch->bc->txgain = txgain;
12314  chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
12315  break;
12316  }
12317  break;
12318  case 'c':
12319  keyidx = atoi(++tok);
12320  {
12321  char keys[4096];
12322  char *key = NULL;
12323  char *tmp = keys;
12324  int i;
12325 
12326  misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
12327 
12328  for (i = 0; i < keyidx; i++) {
12329  key = strsep(&tmp, ",");
12330  }
12331 
12332  if (key) {
12333  ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
12334  }
12335 
12336  chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
12337  break;
12338  }
12339  case 'e':
12340  chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
12341 
12342  if (neglect) {
12343  chan_misdn_log(1, ch->bc->port, " --> disabled\n");
12344 #ifdef MISDN_1_2
12345  *ch->bc->pipeline = 0;
12346 #else
12347  ch->bc->ec_enable = 0;
12348 #endif
12349  } else {
12350 #ifdef MISDN_1_2
12351  update_pipeline_config(ch->bc);
12352 #else
12353  ch->bc->ec_enable = 1;
12354  ch->bc->orig = ch->originator;
12355  tok++;
12356  if (*tok) {
12357  ch->bc->ec_deftaps = atoi(tok);
12358  }
12359 #endif
12360  }
12361  break;
12362  case 'h':
12363  chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
12364 
12365  if (strlen(tok) > 1 && tok[1] == '1') {
12366  chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
12367  if (!ch->bc->hdlc) {
12368  ch->bc->hdlc = 1;
12369  }
12370  }
12372  break;
12373  case 's':
12374  chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
12375  ch->bc->send_dtmf = 1;
12376  break;
12377  case 'f':
12378  chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
12379  ch->faxdetect = 1;
12381  break;
12382  case 'a':
12383  chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
12384  ch->ast_dsp = 1;
12385  break;
12386  case 'p':
12387  chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
12388  /* CRICH: callingpres!!! */
12389  if (strstr(tok, "allowed")) {
12390  ch->bc->presentation = 0;
12391  ch->bc->set_presentation = 1;
12392  } else if (strstr(tok, "restricted")) {
12393  ch->bc->presentation = 1;
12394  ch->bc->set_presentation = 1;
12395  } else if (strstr(tok, "not_screened")) {
12396  chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
12397  ch->bc->presentation = 1;
12398  ch->bc->set_presentation = 1;
12399  }
12400  break;
12401  case 'i' :
12402  chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
12403  ch->ignore_dtmf = 1;
12404  break;
12405  default:
12406  break;
12407  }
12408  }
12409 
12410  if (change_jitter) {
12411  config_jitterbuffer(ch);
12412  }
12413 
12414  if (ch->faxdetect || ch->ast_dsp) {
12415  if (!ch->dsp) {
12416  ch->dsp = ast_dsp_new();
12417  }
12418  if (ch->dsp) {
12420  }
12421  }
12422 
12423  if (ch->ast_dsp) {
12424  chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
12425  ch->bc->nodsp = 1;
12426  }
12427 
12428  return 0;
12429 }
12430 
12431 
12432 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len)
12433 {
12434  struct chan_list *ch;
12435  int res;
12436 
12437  ch = find_chan_by_bc(bc);
12438  if (!ch) {
12439  return 0;
12440  }
12441 
12442  if (ch->jb) {
12443  res = misdn_jb_empty(ch->jb, buf, len);
12444  } else {
12445  res = 0;
12446  }
12447  chan_list_unref(ch, "Done emptying jb");
12448 
12449  return res;
12450 }
12451 
12452 
12453 
12454 /*******************************************************/
12455 /***************** JITTERBUFFER ************************/
12456 /*******************************************************/
12457 
12458 
12459 /* allocates the jb-structure and initialize the elements*/
12461 {
12462  struct misdn_jb *jb;
12463 
12464  jb = ast_calloc(1, sizeof(*jb));
12465  if (!jb) {
12466  chan_misdn_log(-1, 0, "No free Mem for jb\n");
12467  return NULL;
12468  }
12469  jb->size = size;
12471  //jb->wp = 0;
12472  //jb->rp = 0;
12473  //jb->state_full = 0;
12474  //jb->state_empty = 0;
12475  //jb->bytes_wrote = 0;
12476  jb->samples = ast_calloc(size, sizeof(*jb->samples));
12477  if (!jb->samples) {
12478  ast_free(jb);
12479  chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
12480  return NULL;
12481  }
12482 
12483  jb->ok = ast_calloc(size, sizeof(*jb->ok));
12484  if (!jb->ok) {
12485  ast_free(jb->samples);
12486  ast_free(jb);
12487  chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
12488  return NULL;
12489  }
12490 
12491  ast_mutex_init(&jb->mutexjb);
12492 
12493  return jb;
12494 }
12495 
12496 /* frees the data and destroys the given jitterbuffer struct */
12497 void misdn_jb_destroy(struct misdn_jb *jb)
12498 {
12499  ast_mutex_destroy(&jb->mutexjb);
12500 
12501  ast_free(jb->ok);
12502  ast_free(jb->samples);
12503  ast_free(jb);
12504 }
12505 
12506 /* fills the jitterbuffer with len data returns < 0 if there was an
12507  error (buffer overflow). */
12508 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
12509 {
12510  int i;
12511  int j;
12512  int rp;
12513  int wp;
12514 
12515  if (!jb || ! data) {
12516  return 0;
12517  }
12518 
12519  ast_mutex_lock(&jb->mutexjb);
12520 
12521  wp = jb->wp;
12522  rp = jb->rp;
12523 
12524  for (i = 0; i < len; i++) {
12525  jb->samples[wp] = data[i];
12526  jb->ok[wp] = 1;
12527  wp = (wp != jb->size - 1) ? wp + 1 : 0;
12528 
12529  if (wp == jb->rp) {
12530  jb->state_full = 1;
12531  }
12532  }
12533 
12534  if (wp >= rp) {
12535  jb->state_buffer = wp - rp;
12536  } else {
12537  jb->state_buffer = jb->size - rp + wp;
12538  }
12539  chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12540 
12541  if (jb->state_full) {
12542  jb->wp = wp;
12543 
12544  rp = wp;
12545  for (j = 0; j < jb->upper_threshold; j++) {
12546  rp = (rp != 0) ? rp - 1 : jb->size - 1;
12547  }
12548  jb->rp = rp;
12549  jb->state_full = 0;
12550  jb->state_empty = 1;
12551 
12552  ast_mutex_unlock(&jb->mutexjb);
12553 
12554  return -1;
12555  }
12556 
12557  if (!jb->state_empty) {
12558  jb->bytes_wrote += len;
12559  if (jb->bytes_wrote >= jb->upper_threshold) {
12560  jb->state_empty = 1;
12561  jb->bytes_wrote = 0;
12562  }
12563  }
12564  jb->wp = wp;
12565 
12566  ast_mutex_unlock(&jb->mutexjb);
12567 
12568  return 0;
12569 }
12570 
12571 /* gets len bytes out of the jitterbuffer if available, else only the
12572 available data is returned and the return value indicates the number
12573 of data. */
12574 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
12575 {
12576  int i;
12577  int wp;
12578  int rp;
12579  int read = 0;
12580 
12581  ast_mutex_lock(&jb->mutexjb);
12582 
12583  rp = jb->rp;
12584  wp = jb->wp;
12585 
12586  if (jb->state_empty) {
12587  for (i = 0; i < len; i++) {
12588  if (wp == rp) {
12589  jb->rp = rp;
12590  jb->state_empty = 0;
12591 
12592  ast_mutex_unlock(&jb->mutexjb);
12593 
12594  return read;
12595  } else {
12596  if (jb->ok[rp] == 1) {
12597  data[i] = jb->samples[rp];
12598  jb->ok[rp] = 0;
12599  rp = (rp != jb->size - 1) ? rp + 1 : 0;
12600  read += 1;
12601  }
12602  }
12603  }
12604 
12605  if (wp >= rp) {
12606  jb->state_buffer = wp - rp;
12607  } else {
12608  jb->state_buffer = jb->size - rp + wp;
12609  }
12610  chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12611 
12612  jb->rp = rp;
12613  } else {
12614  chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
12615  }
12616 
12617  ast_mutex_unlock(&jb->mutexjb);
12618 
12619  return read;
12620 }
12621 
12622 /*******************************************************/
12623 /*************** JITTERBUFFER END *********************/
12624 /*******************************************************/
12625 
12626 static void chan_misdn_log(int level, int port, char *tmpl, ...)
12627 {
12628  va_list ap;
12629  char buf[1024];
12630  char port_buf[8];
12631 
12632  if (!(0 <= port && port <= max_ports)) {
12633  ast_log(LOG_WARNING, "chan_misdn_log called with out-of-range port number! (%d)\n", port);
12634  port = 0;
12635  level = -1;
12636  } else if (!(level == -1
12637  || (misdn_debug_only[port]
12638  ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12639  : level <= misdn_debug[port])
12640  || (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)))) {
12641  /*
12642  * We are not going to print anything so lets not
12643  * go to all the work of generating a string.
12644  */
12645  return;
12646  }
12647 
12648  snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
12649  va_start(ap, tmpl);
12650  vsnprintf(buf, sizeof(buf), tmpl, ap);
12651  va_end(ap);
12652 
12653  if (level == -1) {
12654  ast_log(LOG_WARNING, "%s", buf);
12655  } else if (misdn_debug_only[port]
12656  ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12657  : level <= misdn_debug[port]) {
12658  ast_verbose("%s%s", port_buf, buf);
12659  }
12660 
12661  if (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)) {
12662  char ctimebuf[30];
12663  time_t tm;
12664  char *tmp;
12665  char *p;
12666  FILE *fp;
12667 
12668  fp = fopen(global_tracefile, "a+");
12669  if (!fp) {
12670  ast_verbose("Error opening Tracefile: [ %s ] %s\n", global_tracefile, strerror(errno));
12671  return;
12672  }
12673 
12674  tm = time(NULL);
12675  tmp = ctime_r(&tm, ctimebuf);
12676  p = strchr(tmp, '\n');
12677  if (p) {
12678  *p = ':';
12679  }
12680  fputs(tmp, fp);
12681  fputs(" ", fp);
12682  fputs(port_buf, fp);
12683  fputs(" ", fp);
12684  fputs(buf, fp);
12685 
12686  fclose(fp);
12687  }
12688 }
12689 
12690 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Channel driver for mISDN Support (BRI/PRI)",
12691  .load = load_module,
12692  .unload = unload_module,
12693  .reload = reload,
12694  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
12695 );
static int misdn_send_text(struct ast_channel *chan, const char *text)
Definition: chan_misdn.c:8032
int ast_dsp
TRUE if we will use the Asterisk DSP to detect DTMF/Fax.
Definition: chan_misdn.c:456
int misdn_lib_maxports_get(void)
Definition: isdn_lib.c:4094
const char * type
Definition: datastore.h:32
int need_busy
TRUE if we could send an AST_CONTROL_BUSY if needed.
Definition: chan_misdn.c:374
static void chan_misdn_log(int level, int port, char *tmpl,...)
Definition: chan_misdn.c:12626
ast_mutex_t mutexjb
Definition: chan_misdn.c:112
static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
Definition: chan_misdn.c:6485
#define AST_CAUSE_PROTOCOL_ERROR
Definition: causes.h:144
int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_data)
Definition: isdn_lib.c:4143
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
Definition: channel.c:3534
unsigned long long ast_group_t
Definition: channel.h:175
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
char keypad[MISDN_MAX_KEYPAD_LEN]
Q.931 Keypad Facility IE contents.
Definition: isdn_lib.h:647
enum sip_cc_notify_state state
Definition: chan_sip.c:842
void misdn_cfg_destroy(void)
Tone Indication Support.
static int ast_to_misdn_pres(int presentation)
Definition: chan_misdn.c:2117
static int misdn_digit_begin(struct ast_channel *chan, char digit)
Definition: chan_misdn.c:6838
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2308
int display_setup
Put a display ie in the SETUP message.
Definition: isdn_lib.h:585
AST_CONNECTED_LINE_UPDATE_SOURCE
Connected line update source code.
Definition: callerid.h:439
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7051
#define ast_channel_lock(chan)
Definition: channel.h:2466
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Definition: dsp.c:1392
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
static enum ast_bridge_result misdn_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
Definition: chan_misdn.c:7511
Main Channel structure associated with a channel.
Definition: channel.h:742
static int stop_indicate(struct chan_list *cl)
Definition: chan_misdn.c:7660
#define AST_DEFINE_APP_ARGS_TYPE(type, arglist)
Define a structure type to hold an application&#39;s arguments.
Definition: app.h:588
static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
Definition: chan_misdn.c:740
Music on hold handling.
int jb_len
Jitterbuffer length.
Definition: chan_misdn.c:462
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
static struct chan_list * find_hold_call(struct misdn_bchannel *bc)
Definition: chan_misdn.c:8210
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
const char * ast_named_caller_presentation(int data)
Convert caller ID pres value to text code.
Definition: callerid.c:1183
int faxdetect
Fax detection option. (0:no 1:yes 2:yes+nojump)
Definition: chan_misdn.c:433
void debug_numtype(int port, int numtype, char *type)
Definition: chan_misdn.c:5822
struct FacParm fac_out
Outbound FACILITY message function type and contents.
Definition: isdn_lib.h:512
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void hanguptone_indicate(struct chan_list *cl)
Definition: chan_misdn.c:7655
static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
Definition: chan_misdn.c:8847
const char *const type
Definition: channel.h:508
#define AST_CAUSE_INCOMPATIBLE_DESTINATION
Definition: causes.h:134
static const char * misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
Definition: chan_misdn.c:1804
struct chan_list * next
Next channel call record in the list.
Definition: chan_misdn.c:580
Asterisk main include file. File version handling, generic pbx functions.
int rings
Definition: channel.h:840
char number[MISDN_MAX_NUMBER_LEN]
Phone number (Address)
Definition: isdn_lib.h:298
void misdn_lib_nt_debug_init(int flags, char *file)
Definition: isdn_lib.c:4124
int misdn_cfg_init(int this_max_ports, int reload)
static char * handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4199
static struct ast_channel * misdn_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
Definition: chan_misdn.c:7772
char ast_rd_buf[4096]
Read buffer for inbound audio from pipe[0].
Definition: chan_misdn.c:421
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int offset
Definition: frame.h:156
char * str
Subscriber phone number (Malloced)
Definition: channel.h:336
void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update)
Set the caller id information in the Asterisk channel and generate an AMI event if the caller id name...
Definition: channel.c:7091
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
Definition: channel.c:1601
static void update_config(struct chan_list *ch)
Updates caller ID information from config.
Definition: chan_misdn.c:5730
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_tone_zone * zone
Definition: channel.h:767
struct ast_set_party_id ani
Definition: channel.h:391
char * strsep(char **str, const char *delims)
int misdn_lib_pid_restart(int pid)
Definition: isdn_lib.c:3932
int misdn_cfg_is_msn_valid(int port, char *msn)
Definition: misdn_config.c:694
static char * handle_cli_misdn_port_down(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3909
int priority
Definition: channel.h:841
struct ast_dsp * dsp
Allocated DSP controller.
Definition: chan_misdn.c:482
static int read_config(struct chan_list *ch)
Definition: chan_misdn.c:5891
static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
Definition: chan_misdn.c:1972
String manipulation functions.
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:245
int need_hangup
TRUE if a channel can be hung up by calling asterisk directly when done.
Definition: chan_misdn.c:369
int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Schedule callback(data) to happen when ms into the future.
Definition: sched.c:406
int nodsp
TRUE if we will not use jollys dsp.
Definition: isdn_lib.h:474
#define ast_strdup(a)
Definition: astmm.h:109
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
format_t writeformat
Definition: channel.h:854
int need_queue_hangup
TRUE if a hangup needs to be queued.
Definition: chan_misdn.c:364
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition: causes.h:121
int addr
From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid() ...
Definition: chan_misdn.c:519
static void misdn_update_redirecting(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
Definition: chan_misdn.c:6414
int txgain
Tx gain setting (range -8 to 8)
Definition: isdn_lib.h:708
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
int ec_enable
TRUE if the echo cancellor is enabled.
Definition: isdn_lib.h:688
enum FacFunction AOCDtype
Definition: isdn_lib.h:515
Support for translation of data formats. translate.c.
#define MAX_MUSICCLASS
Definition: channel.h:139
int tone_cnt
Number of tone samples to generate.
Definition: isdn_lib.h:544
Time-related functions and macros.
int ignore_dtmf
TRUE if DTMF digits are to be passed inband only.
Definition: chan_misdn.c:410
int presentation
User set presentation restriction code 0=Allowed, 1=Restricted, 2=Unavailable.
Definition: isdn_lib.h:600
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
static struct sched_context * misdn_tasks
the main schedule context for stuff like l1 watcher, overlap dial, ...
Definition: chan_misdn.c:642
char * ok
Definition: chan_misdn.c:106
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:938
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:449
int uulen
User-User information string length in uu[].
Definition: isdn_lib.h:666
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1650
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
void * ptr
Definition: frame.h:160
char uu[256]
User-User information string.
Definition: isdn_lib.h:663
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:97
static int misdn_attempt_transfer(struct chan_list *active_ch, struct chan_list *held_ch)
Definition: chan_misdn.c:8546
int dummy
TRUE if this is a dummy BC record.
Definition: isdn_lib.h:361
int pipe[2]
Pipe file descriptor handles array. Read from pipe[0], write to pipe[1].
Definition: chan_misdn.c:416
static char * handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5533
void misdn_dump_chanlist(void)
Definition: isdn_lib.c:483
Convenient Signal Processing routines.
#define COLOR_YELLOW
Definition: term.h:54
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
static void misdn_update_caller_id(struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag)
Definition: chan_misdn.c:6106
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1921
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:120
static int misdn_to_ast_pres(int presentation)
Definition: chan_misdn.c:2089
static void cl_queue_chan(struct chan_list *chan)
Definition: chan_misdn.c:8304
enum misdn_cfg_elements misdn_cfg_get_elem(const char *name)
Definition: misdn_config.c:616
static void release_chan_early(struct chan_list *ch)
Definition: chan_misdn.c:8488
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:485
static int pbx_start_chan(struct chan_list *ch)
Definition: chan_misdn.c:8365
int bframe_len
B channel speech sample data buffer size.
Definition: isdn_lib.h:435
descriptor for a cli entry.
Definition: cli.h:165
void manager_ec_enable(struct misdn_bchannel *bc)
Definition: isdn_lib.c:4628
const int argc
Definition: cli.h:154
static int cl_dequeue_chan(struct chan_list *chan)
Definition: chan_misdn.c:8325
#define LOG_WARNING
Definition: logger.h:144
struct misdn_jb * jb
Allocated jitterbuffer controller.
Definition: chan_misdn.c:475
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char * manager_isdn_get_info(enum event_e event)
Definition: isdn_lib.c:4324
char incoming_cid_tag[MISDN_MAX_NAME_LEN]
Incoming Caller ID string tag for special purpose.
Definition: isdn_lib.h:348
static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
Definition: chan_misdn.c:6234
static int misdn_hangup(struct ast_channel *ast)
Definition: chan_misdn.c:7043
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
void misdn_jb_destroy(struct misdn_jb *jb)
frees the data and destroys the given jitterbuffer struct
Definition: chan_misdn.c:12497
int faxdetect_timeout
Number of seconds to detect a Fax machine when detection enabled.
Definition: chan_misdn.c:440
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
struct ast_dsp * ast_dsp_new(void)
Definition: dsp.c:1607
int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
fills the jitterbuffer with len data returns &lt; 0 if there was an error (buffer overrun).
Definition: chan_misdn.c:12508
int cw
TRUE if call waiting.
Definition: isdn_lib.h:426
Connected-Line/Calling/Redirecting ID info struct.
Definition: isdn_lib.h:273
void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel)
Definition: isdn_lib.c:77
#define AST_FRAME_DTMF
Definition: frame.h:128
misdn_cfg_elements
struct robin_list * next
Definition: chan_misdn.c:595
int hdlc
TRUE if call made in digital HDLC mode.
Definition: isdn_lib.h:635
void misdn_lib_tone_generator_start(struct misdn_bchannel *bc)
Definition: isdn_lib.c:2271
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
mISDN_REDIRECTING_REASON
Q.931 encoded redirecting reason.
Definition: isdn_lib.h:197
static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
Definition: chan_misdn.c:8422
struct ast_generator * generator
Definition: channel.h:747
int add_out_calls(int port)
Definition: chan_misdn.c:8817
#define var
Definition: ast_expr2f.c:606
int size
Definition: chan_misdn.c:104
struct ast_frame frame
Inbound audio frame returned by misdn_read().
Definition: chan_misdn.c:426
format_t rawwriteformat
Definition: channel.h:856
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
static int misdn_tasks_add(int timeout, ast_sched_cb callback, const void *data)
Definition: chan_misdn.c:3573
int norxtone
Definition: chan_misdn.c:387
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct hold_info hold
HELD channel call information.
Definition: chan_misdn.c:507
int jb_upper_threshold
Jitterbuffer upper threshold.
Definition: chan_misdn.c:468
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
Definition: channel.h:814
B channel control structure.
Definition: isdn_lib.h:324
#define AST_PRES_USER_NUMBER_FAILED_SCREEN
Definition: callerid.h:320
int outgoing_colp
Select what to do with outgoing COLP information.
Definition: isdn_lib.h:594
Definition: cli.h:146
int presentation
Number presentation restriction code 0=Allowed, 1=Restricted, 2=Unavailable.
Definition: isdn_lib.h:277
enum misdn_chan_state state
Definition: chan_misdn.c:4048
int state_buffer
Definition: chan_misdn.c:110
static struct robin_list * robin
Definition: chan_misdn.c:598
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
Structure for a data store type.
Definition: datastore.h:31
static void config_jitterbuffer(struct chan_list *ch)
Definition: chan_misdn.c:5786
static const char * misdn_get_ch_state(struct chan_list *p)
Definition: chan_misdn.c:4071
Configuration File Parser.
char * str
Subscriber name (Malloced)
Definition: channel.h:214
static char * handle_cli_misdn_set_tics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4308
static struct chan_list * find_hold_active_call(struct misdn_bchannel *bc)
Definition: chan_misdn.c:8278
int misdn_cfg_is_group_method(char *group, enum misdn_cfg_method meth)
Definition: misdn_config.c:726
static struct chan_list * get_chan_by_ast_name(const char *name)
Definition: chan_misdn.c:758
char crypt_key[255]
Blowfish encryption key string (secret)
Definition: isdn_lib.h:529
static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag)
Definition: chan_misdn.c:6368
char txt[255]
Definition: chan_misdn.c:4049
#define MISDN_ASTERISK_TECH_PVT(ast)
Definition: chan_misdn.c:655
static struct ast_threadstorage buf2
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
static char * handle_cli_misdn_restart_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3843
static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
Definition: chan_misdn.c:8833
int capability
SETUP message bearer capability field code value.
Definition: isdn_lib.h:609
#define ast_mutex_lock(a)
Definition: lock.h:155
void misdn_cfg_reload(void)
void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc)
Definition: isdn_lib.c:2276
#define ao2_unlock(a)
Definition: astobj2.h:497
unsigned short transfercapability
Definition: channel.h:863
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:907
int misdn_cfg_get_next_port(int port)
Definition: misdn_config.c:892
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
char * text
Definition: app_queue.c:1091
format_t nativeformats
Definition: channel.h:852
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
static int * misdn_debug_only
Definition: chan_misdn.c:669
Structure for a data store object.
Definition: datastore.h:54
void misdn_lib_destroy(void)
Definition: isdn_lib.c:4285
static const char * misdn_to_str_pres(int presentation)
Definition: chan_misdn.c:2056
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2353
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
const char * str
Definition: app_jack.c:144
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
format_t codec
Definition: frame.h:137
struct misdn_bchannel * misdn_lib_find_held_bc(int port, int l3_id)
Find a held call&#39;s B channel record.
Definition: isdn_lib.c:4580
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:411
int AOCD_need_export
TRUE if AOCDtype and AOCD data are ready to export to Asterisk.
Definition: isdn_lib.h:521
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: features.c:7380
char context[AST_MAX_CONTEXT]
Incoming call dialplan context identifier.
Definition: chan_misdn.c:525
I/O Management (derived from Cheops-NG)
mISDN_NUMBER_PLAN
Definition: isdn_lib.h:92
char mohinterpret[MAX_MUSICCLASS]
The configured music-on-hold class to use for this call.
Definition: chan_misdn.c:531
#define COLOR_BRWHITE
Definition: term.h:62
static struct chan_list * cl_te
Global channel call record list head.
Definition: chan_misdn.c:678
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:119
Common implementation-independent jitterbuffer stuff.
int value
Definition: syslog.c:39
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
static char * handle_cli_misdn_restart_pid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3865
const ast_string_field linkedid
Definition: channel.h:787
#define LOG_DEBUG
Definition: logger.h:122
static int misdn_chan_is_valid(struct chan_list *ch)
Definition: chan_misdn.c:723
void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
Import parameters from the dialplan environment variables.
Definition: chan_misdn.c:8744
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition: causes.h:115
struct ast_channel * ast
Associated Asterisk channel structure.
Definition: chan_misdn.c:487
const char * ext
Definition: http.c:112
static const char * misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
Definition: chan_misdn.c:1930
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len)
Definition: chan_misdn.c:12432
format_t rawreadformat
Definition: channel.h:855
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
#define AST_PRES_NETWORK_NUMBER
Definition: callerid.h:321
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:157
int misdn_lib_get_maxchans(int port)
Definition: isdn_lib.c:137
void isdn_lib_update_rxgain(struct misdn_bchannel *bc)
Definition: isdn_lib.c:4440
ast_group_t pickupgroup
Definition: channel.h:819
struct misdn_party_id to
Where the call is being redirected toward (Sent to the calling party)
Definition: isdn_lib.h:310
#define ast_verb(level,...)
Definition: logger.h:243
static void chan_list_destructor(void *obj)
Definition: chan_misdn.c:7709
misdn_hold_state
Definition: chan_misdn.c:319
Indicate what information in ast_party_caller should be set.
Definition: channel.h:387
int notxtone
TRUE if we are not to generate tones (Playtones)
Definition: chan_misdn.c:392
static char * handle_cli_misdn_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4113
const char * line
Definition: cli.h:156
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
ast_group_t callgroup
Definition: channel.h:818
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:5415
static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
Definition: chan_misdn.c:8617
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
void isdn_lib_update_txgain(struct misdn_bchannel *bc)
Definition: isdn_lib.c:4445
int misdn_cap_is_speech(int cap)
Definition: isdn_lib.c:436
static int misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data)
Definition: chan_misdn.c:3578
void isdn_lib_update_ec(struct misdn_bchannel *bc)
Definition: isdn_lib.c:4450
static int misdn_is_msn_valid(int port, const struct misdn_party_dialing *dialed)
Definition: chan_misdn.c:9846
static pthread_t misdn_tasks_thread
Definition: chan_misdn.c:643
void get_show_stack_details(int port, char *buf)
Definition: isdn_lib.c:168
struct timeval overlap_tv
Overlap timer start time. Timer restarted for every digit received.
Definition: chan_misdn.c:575
String fields in structures.
char * ast_print_group(char *buf, int buflen, ast_group_t group)
print call- and pickup groups into buffer
Definition: channel.c:8236
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1581
#define AST_PRES_RESTRICTED
Definition: callerid.h:325
threshold
Definition: dsp.h:62
static int stop_bc_tones(struct chan_list *cl)
Definition: chan_misdn.c:7689
struct ast_set_party_id from
Definition: channel.h:467
static void misdn_tasks_destroy(void)
Definition: chan_misdn.c:3543
static void misdn_tasks_init(void)
Definition: chan_misdn.c:3523
static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
Definition: chan_misdn.c:6887
Number structure.
Definition: app_followme.c:109
#define BUFFERSIZE
static void print_facility(const struct FacParm *fac, const struct misdn_bchannel *bc)
Definition: chan_misdn.c:2734
static int misdn_l1_task(const void *vdata)
Definition: chan_misdn.c:3588
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static char * handle_cli_misdn_port_unblock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3821
void ast_change_name(struct ast_channel *chan, const char *newname)
Change channel name.
Definition: channel.c:6229
static char * handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5580
static ast_mutex_t release_lock
Definition: chan_misdn.c:295
int misdn_inband_avail(struct misdn_bchannel *bc)
Definition: isdn_lib.c:444
void misdn_lib_split_bridge(struct misdn_bchannel *bc1, struct misdn_bchannel *bc2)
Definition: isdn_lib.c:4751
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct ast_frame * process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
Definition: chan_misdn.c:7244
int set_presentation
TRUE if the user set the presentation restriction code.
Definition: isdn_lib.h:603
char number[MISDN_MAX_NUMBER_LEN]
Dialed/Called Phone Number (Address)
Definition: isdn_lib.h:266
#define AST_CAUSE_NO_ROUTE_TRANSIT_NET
Definition: causes.h:98
void manager_ec_disable(struct misdn_bchannel *bc)
Definition: isdn_lib.c:4677
static void show_config_description(int fd, enum misdn_cfg_elements elem)
Definition: chan_misdn.c:3931
void misdn_cfg_get_name(enum misdn_cfg_elements elem, void *buf, int bufsize)
Definition: misdn_config.c:637
char * samples
Definition: chan_misdn.c:106
event_response_e
Definition: isdn_lib.h:110
char display[84]
Display message that can be displayed by the user phone.
Definition: isdn_lib.h:642
static int misdn_answer(struct ast_channel *ast)
Definition: chan_misdn.c:6753
struct ast_jb_conf * misdn_get_global_jbconf()
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
Definition: channel.c:9098
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:377
static char * complete_ch(struct ast_cli_args *a)
Definition: chan_misdn.c:5623
int pri
TRUE if ISDN-PRI (ISDN-BRI otherwise)
Definition: isdn_lib.h:367
General Asterisk PBX channel definitions.
void misdn_cfg_get_desc(enum misdn_cfg_elements elem, void *buf, int bufsize, void *buf_default, int bufsize_default)
Definition: misdn_config.c:663
#define AST_PRES_USER_NUMBER_UNSCREENED
Definition: callerid.h:318
static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
Definition: chan_misdn.c:1846
struct ast_party_dialed::@155 number
Dialed/Called number.
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
const char * src
Definition: frame.h:158
int misdn_lib_port_block(int port)
Definition: isdn_lib.c:91
static struct ast_frame * misdn_read(struct ast_channel *ast)
Definition: chan_misdn.c:7319
static int load_module(void)
Definition: chan_misdn.c:11179
int need_release_complete
TRUE if RELEASE_COMPLETE needs to be sent to clear a call.
Definition: isdn_lib.h:392
const int fd
Definition: cli.h:153
#define AST_FORMAT_ALAW
Definition: frame.h:248
Definition: dsp.c:390
static char * handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3689
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const int n
Definition: cli.h:159
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
static struct ast_cli_entry chan_misdn_clis[]
Definition: chan_misdn.c:5703
static void misdn_tasks_remove(int task_id)
Definition: chan_misdn.c:3583
Data structure associated with a custom dialplan function.
Definition: pbx.h:95
#define ast_register_application(app, execute, synopsis, description)
Register an application.
Definition: module.h:421
void misdn_lib_release(struct misdn_bchannel *bc)
Definition: isdn_lib.c:1759
Asterisk internal frame definitions.
int overlap_dial_task
Overlap dialing timeout Task ID. -1 if not running.
Definition: chan_misdn.c:565
static struct state_struct state_array[]
Definition: chan_misdn.c:4052
ast_cond_t cond
Definition: app_meetme.c:963
#define AST_MAX_EXTENSION
Definition: channel.h:135
int datalen
Definition: frame.h:148
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
Scheduler Routines (derived from cheops)
Caller Party information.
Definition: channel.h:368
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
int dropped_frame_cnt
Number of outgoing audio frames dropped since last debug gripe message.
Definition: chan_misdn.c:536
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static const char * misdn_to_str_screen(int screening)
Definition: chan_misdn.c:2145
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
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
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
#define ao2_lock(a)
Definition: astobj2.h:488
static char * handle_cli_misdn_show_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4390
void misdn_lib_log_ies(struct misdn_bchannel *bc)
Definition: isdn_lib.c:3431
int holded
TRUE if this channel is on hold.
Definition: isdn_lib.h:556
static struct ast_tone_zone_sound * ast_tone_zone_sound_unref(struct ast_tone_zone_sound *ts)
Release a reference to an ast_tone_zone_sound.
Definition: indications.h:226
#define AST_BRIDGE_DTMF_CHANNEL_1
Report DTMF on channel 1.
Definition: channel.h:1934
struct ast_set_party_id id
Definition: channel.h:389
int display_connected
Put a display ie in the CONNECT message.
Definition: isdn_lib.h:573
#define MISDN_MAX_NUMBER_LEN
Definition: isdn_lib.h:246
void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Set the redirecting id information in the Asterisk channel.
Definition: channel.c:9111
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
int nojitter
TRUE if we will not use the jitter buffer system.
Definition: isdn_lib.h:477
char infos_pending[MISDN_MAX_NUMBER_LEN]
Collected digits to go into info_dad[] while waiting for a SETUP_ACKNOWLEDGE to come in...
Definition: isdn_lib.h:653
struct misdn_party_id caller
Originating/Caller ID information struct.
Definition: isdn_lib.h:343
struct timeval faxdetect_tv
Starting time of fax detection with timeout when nonzero.
Definition: chan_misdn.c:445
static struct chan_list * find_chan_by_bc(struct misdn_bchannel *bc)
Definition: chan_misdn.c:8186
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
char name[MISDN_MAX_NAME_LEN]
Subscriber Name.
Definition: isdn_lib.h:295
int rxgain
Rx gain setting (range -8 to 8)
Definition: isdn_lib.h:714
static int max_ports
Definition: chan_misdn.c:670
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
static struct ast_channel_tech misdn_tech_wo_bridge
Definition: chan_misdn.c:8066
struct FacAOCDCurrency currency
Definition: isdn_lib.h:517
char * bc_state2str(enum bchannel_state state)
Definition: isdn_lib.c:617
enum misdn_chan_state state
State of the channel.
Definition: chan_misdn.c:358
AST_REDIRECTING_REASON
redirecting reason codes.
Definition: callerid.h:390
int far_alerting
TRUE if we must do the ringback tones.
Definition: chan_misdn.c:542
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
static char global_tracefile[BUFFERSIZE+1]
Definition: chan_misdn.c:99
Core PBX routines and definitions.
Interface to mISDN.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
int ast_cdr_update(struct ast_channel *chan)
Update CDR on a channel.
Definition: cdr.c:1083
int misdn_lib_port_unblock(int port)
Definition: isdn_lib.c:104
void misdn_lib_nt_keepcalls(int kc)
Definition: isdn_lib.c:4112
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition: causes.h:114
static char * complete_show_config(struct ast_cli_args *a)
Definition: chan_misdn.c:5651
int port
Logical port the channel call record is HELD on because the B channel is no longer associated...
Definition: chan_misdn.c:334
int misdn_lib_is_ptp(int port)
Definition: isdn_lib.c:128
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:290
static void print_bc_info(int fd, struct chan_list *help, struct misdn_bchannel *bc)
Definition: chan_misdn.c:4136
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Definition: term.c:184
struct misdn_party_id connected
Connected-Party/Connected-Line ID information struct.
Definition: isdn_lib.h:353
const char *const * argv
Definition: cli.h:155
void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
Export parameters to the dialplan environment variables.
Definition: chan_misdn.c:8769
struct robin_list * prev
Definition: chan_misdn.c:596
char allowed_bearers[BUFFERSIZE+1]
The &quot;allowed_bearers&quot; string read in from /etc/asterisk/misdn.conf.
Definition: chan_misdn.c:353
struct ast_party_dialed dialed
Dialed/Called information.
Definition: channel.h:797
Dialed/Called information struct.
Definition: isdn_lib.h:258
int pid
B channel process ID (1-5000)
Definition: isdn_lib.h:402
int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len)
Definition: isdn_lib.c:4382
int originator
Who originally created this channel. ORG_AST or ORG_MISDN.
Definition: chan_misdn.c:379
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 int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
Definition: chan_misdn.c:8683
static const char desc[]
Definition: cdr_radius.c:85
int dec
TRUE if allocate higher B channels first.
Definition: isdn_lib.h:395
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int misdn_cfg_get_next_port_spin(int port)
Definition: misdn_config.c:909
enum mISDN_NUMBER_TYPE number_type
Type-of-number in ISDN terms for the dialed/called number.
Definition: isdn_lib.h:260
static const char * bearer2str(int cap)
Definition: chan_misdn.c:2345
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
static void free_robin_list(void)
Definition: chan_misdn.c:601
static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
Definition: chan_misdn.c:7404
static void sighandler(int sig)
Definition: chan_misdn.c:3493
#define LOG_ERROR
Definition: logger.h:155
int ast_channel_transfer_masquerade(struct ast_channel *target_chan, const struct ast_party_connected_line *target_id, int target_held, struct ast_channel *transferee_chan, const struct ast_party_connected_line *transferee_id, int transferee_held)
Setup a masquerade to transfer a call.
Definition: channel.c:6184
static int misdn_check_l2l1(struct ast_channel *chan, const char *data)
Definition: chan_misdn.c:12149
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void sched_context_destroy(struct sched_context *c)
destroys a schedule context Destroys (free&#39;s) the given sched_context structure
Definition: sched.c:267
static char * handle_cli_misdn_port_block(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3799
void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
Initialize the given caller structure using the given guide for a set update operation.
Definition: channel.c:2288
static char * handle_cli_misdn_set_crypt_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3776
int64_t format_t
Definition: frame_defs.h:32
static struct @350 args
#define CLI_SHOWUSAGE
Definition: cli.h:44
static int tracing
Definition: chan_misdn.c:663
static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
Definition: chan_misdn.c:3396
unsigned char number
Definition: channel.h:315
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:243
int misdn_lib_send_restart(int port, int channel)
Definition: isdn_lib.c:3943
#define AST_PRES_NUMBER_TYPE
Definition: callerid.h:317
static int ast_to_misdn_screen(int screening)
Definition: chan_misdn.c:2214
static struct chan_list * find_hold_call_l3(unsigned long l3_id)
Definition: chan_misdn.c:8244
static int * misdn_debug
Definition: chan_misdn.c:668
static void misdn_update_remote_party(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
Definition: chan_misdn.c:6145
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int send_dtmf
TRUE if we should produce DTMF tones ourselves.
Definition: isdn_lib.h:457
enum ast_channel_state _state
Definition: channel.h:839
Description of a tone.
Definition: indications.h:36
struct ast_tone_zone_sound * ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication)
Locate a tone zone sound.
Definition: indications.c:473
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_misdn.c:6844
Connected Line/Party information.
Definition: channel.h:401
const ast_string_field name
Definition: channel.h:787
struct misdn_party_redirecting redirecting
Redirecting information struct (Where a call diversion or transfer was invoked)
Definition: isdn_lib.h:358
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int incoming_early_audio
TRUE if you want to send Tone Indications to an incoming ISDN channel on a TE Port.
Definition: chan_misdn.c:404
static int misdn_overlap_dial_task(const void *data)
Definition: chan_misdn.c:3597
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
int port
Logical Layer 1 port associated with this B channel.
Definition: isdn_lib.h:370
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
static int glob_channel
Definition: chan_misdn.c:8085
char * group
Definition: chan_misdn.c:592
int add_in_calls(int port)
Definition: chan_misdn.c:8802
int urate
Q.931 Bearer Capability IE Layer 1 User Rate field.
Definition: isdn_lib.h:629
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
Definition: channel.h:447
#define LOG_NOTICE
Definition: logger.h:133
struct misdn_party_dialing dialed
Dialed/Called information struct.
Definition: isdn_lib.h:337
static void misdn_tasks_wakeup(void)
Definition: chan_misdn.c:3555
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static char * handle_cli_misdn_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3956
static const char misdn_type[]
Definition: chan_misdn.c:661
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
static int dialtone_indicate(struct chan_list *cl)
Definition: chan_misdn.c:7624
ast_mutex_t overlap_tv_lock
overlap_tv access lock.
Definition: chan_misdn.c:570
static struct ast_channel_tech misdn_tech
Definition: chan_misdn.c:8047
#define ORG_MISDN
Definition: chan_misdn.c:317
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
static int unload_module(void)
Definition: chan_misdn.c:11138
static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast)
Definition: chan_misdn.c:6316
static char * handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5152
int misdn_lib_get_port_up(int port)
Definition: isdn_lib.c:1781
#define ast_channel_unlock(chan)
Definition: channel.h:2467
int errno
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1642
static const char name[]
#define AST_MAX_CONTEXT
Definition: channel.h:136
int source
Information about the source of an update.
Definition: channel.h:424
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
static struct allowed_bearers allowed_bearers_array[]
Definition: chan_misdn.c:2334
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
int addr
B Channel mISDN driver layer ID from mISDN_get_layerid()
Definition: isdn_lib.h:429
void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone)
Definition: isdn_lib.c:4596
static int * misdn_ports
Definition: chan_misdn.c:645
void misdn_cfg_update_ptp(void)
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
Definition: lock.h:480
int active
Seems to have been intended for something to do with the jitter buffer.
Definition: isdn_lib.h:537
#define AST_CAUSE_NUMBER_CHANGED
Definition: causes.h:111
static struct ast_format f[]
Definition: format_g726.c:181
static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
Definition: chan_misdn.c:2286
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
struct misdn_bchannel * misdn_lib_get_free_bc(int port, int channel, int inout, int dec)
Definition: isdn_lib.c:3205
const char * word
Definition: cli.h:157
static int _misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data, int variable)
Definition: chan_misdn.c:3560
static format_t capability
Definition: chan_mgcp.c:228
static void reload_config(void)
Definition: chan_misdn.c:4092
static void * misdn_tasks_thread_func(void *data)
Definition: chan_misdn.c:3497
#define pthread_create
Definition: lock.h:573
Channel call record structure.
Definition: chan_misdn.c:349
static char * handle_cli_misdn_send_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5446
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:156
static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
Definition: chan_misdn.c:1888
int misdn_lib_port_up(int port, int check)
Definition: isdn_lib.c:1821
int misdn_lib_port_is_nt(int port)
Definition: isdn_lib.c:65
unsigned int inheritance
Definition: datastore.h:58
static int update_ec_config(struct misdn_bchannel *bc)
Definition: chan_misdn.c:5872
static int * misdn_out_calls
Definition: chan_misdn.c:673
static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
Definition: chan_misdn.c:3353
unsigned int l3id
From associated B channel: Layer 3 process ID.
Definition: chan_misdn.c:513
int to_changed
TRUE if the redirecting.to information has changed.
Definition: isdn_lib.h:319
static const char type[]
Definition: chan_nbs.c:57
#define chan_list_ref(obj, debug)
Definition: chan_misdn.c:343
enum misdn_hold_state state
Call HOLD state.
Definition: chan_misdn.c:329
static struct chan_list * chan_list_init(int orig)
Definition: chan_misdn.c:7748
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2631
int channel
Original B channel number the HELD call was using.
Definition: chan_misdn.c:340
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:158
int MAXTICS
Definition: chan_misdn.c:584
enum event_response_e(* cb_event)(enum event_e event, struct misdn_bchannel *bc, void *user_data)
Definition: isdn_lib.h:729
struct timeval delivery
Definition: frame.h:162
int channel
Assigned B channel number B1, B2... 0 if not assigned.
Definition: isdn_lib.h:411
Indicate what information in ast_party_connected_line should be set.
Definition: channel.h:431
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:616
int mallocd
Definition: frame.h:152
static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
Definition: chan_misdn.c:8374
int ast_sched_runq(struct sched_context *con)
Runs the queue.
Definition: sched.c:600
const char * usage
Definition: cli.h:171
int(* generate)(struct ast_channel *chan, void *data, int len, int samples)
Definition: channel.h:186
static int g_config_initialized
Definition: chan_misdn.c:101
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
void misdn_cfg_get_ports_string(char *ports)
Generate a comma separated list of all active ports.
Definition: misdn_config.c:761
#define AST_PRES_RESTRICTION
Definition: callerid.h:323
static void print_bearer(struct misdn_bchannel *bc)
Definition: chan_misdn.c:3327
#define AST_PRES_USER_NUMBER_PASSED_SCREEN
Definition: callerid.h:319
static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
Definition: chan_misdn.c:3430
int out_cause
Q.931 Cause for disconnection code (sent)
Definition: isdn_lib.h:677
#define CLI_SUCCESS
Definition: cli.h:43
char * tag
User-set &quot;tag&quot;.
Definition: channel.h:304
struct ast_set_party_id id
Definition: channel.h:433
void ast_deactivate_generator(struct ast_channel *chan)
Definition: channel.c:3107
void * data
Definition: datastore.h:56
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:2316
struct ast_set_party_id to
Definition: channel.h:469
enum mISDN_REDIRECTING_REASON reason
Reason a call is being redirected (Q.931 field value)
Definition: isdn_lib.h:313
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:99
void misdn_lib_isdn_l1watcher(int port)
Definition: isdn_lib.c:3049
void misdn_cfg_get_config_string(int port, enum misdn_cfg_elements elem, char *buf, int bufsize)
Definition: misdn_config.c:787
int need_release
TRUE if RELEASE needs to be sent to clear a call.
Definition: isdn_lib.h:389
struct ast_tone_zone_sound * ts
Tone zone sound used for dialtone generation.
Definition: chan_misdn.c:554
struct sched_context * sched_context_create(void)
New schedule context.
Definition: sched.c:246
int need_more_infos
TRUE if we send SETUP_ACKNOWLEDGE on incoming calls anyway (instead of PROCEEDING).
Definition: isdn_lib.h:465
int dtmf
Last decoded DTMF digit from mISDN driver.
Definition: isdn_lib.h:452
enum bchannel_state bc_state
Current B Channel state.
Definition: isdn_lib.h:547
Indicate what information in ast_party_redirecting should be set.
Definition: channel.h:465
static int reload(void)
Definition: chan_misdn.c:11396
int count
Number of times the call was redirected.
Definition: channel.h:455
Standard Command Line Interface.
format_t readformat
Definition: channel.h:853
misdn_chan_state
Definition: chan_misdn.c:297
static int start_bc_tones(struct chan_list *cl)
Definition: chan_misdn.c:7681
#define ast_calloc(a, b)
Definition: astmm.h:82
struct ast_party_id to
Call is redirecting to a new party (Sent to the caller)
Definition: channel.h:452
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int faxhandled
TRUE if a fax has been detected.
Definition: chan_misdn.c:450
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:179
int need_disconnect
TRUE if DISCONNECT needs to be sent to clear a call.
Definition: isdn_lib.h:386
int misdn_lib_port_is_pri(int port)
Definition: isdn_lib.c:53
void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize)
Definition: misdn_config.c:562
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is &quot;false&quot;...
Definition: utils.c:1550
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
const int pos
Definition: cli.h:158
#define AST_CAUSE_USER_BUSY
Definition: causes.h:106
int misdn_lib_get_port_down(int port)
Definition: isdn_lib.c:1805
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place Determine the number of s...
Definition: sched.c:334
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
enum mISDN_NOTIFY_CODE notify_description_code
Notification indicator ie description code.
Definition: isdn_lib.h:606
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:8731
#define AST_PRES_ALLOWED
Definition: callerid.h:324
char * ast_transfercapability2str(int transfercapability) attribute_const
Gives the string form of a given transfer capability.
Definition: channel.c:1041
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static char * complete_debug_port(struct ast_cli_args *a)
Definition: chan_misdn.c:5628
mISDN_NUMBER_TYPE
Definition: isdn_lib.h:101
static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
Definition: chan_misdn.c:6161
void isdn_lib_stop_dtmf(struct misdn_bchannel *bc)
Definition: isdn_lib.c:4462
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: cli.c:1547
Data structure associated with a single frame of data.
Definition: frame.h:142
int progress_indicator
Progress Indicator IE progress description field. Used to determine if there is an inband audio messa...
Definition: isdn_lib.h:492
int hangupcause
Definition: channel.h:849
Internal Asterisk hangup causes.
void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide)
Initialize the given redirecting id structure using the given guide for a set update operation...
Definition: channel.c:2380
int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event)
Definition: isdn_lib.c:3523
int upper_threshold
Definition: chan_misdn.c:105
#define ORG_AST
Definition: chan_misdn.c:315
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:319
int ec_deftaps
Number of taps in the echo cancellor when enabled.
Definition: isdn_lib.h:693
int(* ast_sched_cb)(const void *data)
callback for a cheops scheduler A cheops scheduler callback takes a pointer with callback data and ...
Definition: sched.h:160
int misdn_lib_port_restart(int port)
Definition: isdn_lib.c:3982
static int * ptp
Definition: misdn_config.c:432
const char * name
Definition: pbx.h:96
Handy terminal functions for vt* terms.
const char * data
Description of a tone.
Definition: indications.h:53
#define LOG_VERBOSE
Definition: logger.h:166
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
enum ast_frame_type frametype
Definition: frame.h:144
char * bframe
B channel speech sample data buffer.
Definition: isdn_lib.h:432
static int * misdn_in_calls
Definition: chan_misdn.c:672
void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Queue a redirecting update frame on a channel.
Definition: channel.c:9605
int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int(*cond)(void *), void *data)
Wait for a specified amount of time, looking for hangups and a condition argument.
Definition: channel.c:1845
#define AST_PRES_UNAVAILABLE
Definition: callerid.h:326
#define ast_mutex_init(pmutex)
Definition: lock.h:152
int state_full
Definition: chan_misdn.c:109
#define ast_channel_trylock(chan)
Definition: channel.h:2468
static void send_digit_to_chan(struct chan_list *cl, char digit)
Definition: chan_misdn.c:3650
int cause
Q.931 Cause for disconnection code (received)
Definition: isdn_lib.h:671
static int misdn_facility_exec(struct ast_channel *chan, const char *data)
Definition: chan_misdn.c:12026
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
char info_dad[MISDN_MAX_NUMBER_LEN]
Current overlap dialing digits to/from INFORMATION messages.
Definition: isdn_lib.h:650
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
void misdn_lib_bridge(struct misdn_bchannel *bc1, struct misdn_bchannel *bc2)
Definition: isdn_lib.c:4728
int te_choose_channel
TRUE if the TE side should choose the B channel to use.
Definition: isdn_lib.h:444
Interface to mISDN - Config.
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send DTMF to a channel.
Definition: app.c:501
#define ast_mutex_destroy(a)
Definition: lock.h:154
static struct robin_list * get_robin_position(char *group)
Definition: chan_misdn.c:613
static int prefformat
Only alaw and mulaw is allowed for now.
Definition: chan_misdn.c:666
static char * handle_cli_misdn_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4272
static char * handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5478
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
Definition: app.h:619
int reason
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:458
static void update_name(struct ast_channel *tmp, int port, int c)
Definition: chan_misdn.c:8087
Redirecting information struct.
Definition: isdn_lib.h:305
struct misdn_bchannel * bc
Associated B channel structure.
Definition: chan_misdn.c:492
int screening
Number screening code 0=Unscreened, 1=Passed Screen, 2=Failed Screen, 3=Network Number.
Definition: isdn_lib.h:282
#define chan_list_unref(obj, debug)
Definition: chan_misdn.c:344
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:110
int misdn_cfg_is_port_valid(int port)
Definition: misdn_config.c:719
#define ast_malloc(a)
Definition: astmm.h:91
Asterisk module definitions.
int bytes_wrote
Definition: chan_misdn.c:111
union misdn_bchannel::@126 AOCD
static struct keys keys
static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
Definition: chan_misdn.c:2246
struct misdn_jb * misdn_jb_init(int size, int upper_threshold)
allocates the jb-structure and initialize the elements
Definition: chan_misdn.c:12460
static int misdn_to_ast_screen(int screening)
Definition: chan_misdn.c:2182
int law
Companding ALaw/uLaw encoding (INFO_CODEC_ALAW / INFO_CODEC_ULAW)
Definition: isdn_lib.h:612
int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
gets len bytes out of the jitterbuffer if available, else only the available data is returned and the...
Definition: chan_misdn.c:12574
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
struct ast_channel_tech * tech
Definition: channel.h:743
static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2069
int orig
Who originated the call (ORG_AST, ORG_MISDN)
Definition: isdn_lib.h:702
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
struct FacParm fac_in
Inbound FACILITY message function type and contents.
Definition: isdn_lib.h:507
static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
Definition: chan_misdn.c:6904
static char * handle_cli_misdn_show_stacks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4330
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
static struct ast_channel * misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, const char *linkedid, int port, int c)
Definition: chan_misdn.c:8111
void * generatordata
Definition: channel.h:746
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
int overlap_dial
Enables overlap dialing for the set amount of seconds. (0 = Disabled)
Definition: chan_misdn.c:560
enum mISDN_NUMBER_PLAN number_plan
Type-of-number numbering plan.
Definition: isdn_lib.h:288
static ast_mutex_t cl_te_lock
Definition: chan_misdn.c:679
static int misdn_set_opt_exec(struct ast_channel *chan, const char *data)
Definition: chan_misdn.c:12223
struct FacAOCDChargingUnit chargingUnit
Definition: isdn_lib.h:518
#define AST_BRIDGE_DTMF_CHANNEL_0
Report DTMF on channel 0.
Definition: channel.h:1932
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
const char * ast_pickup_ext(void)
Determine system call pickup extension.
Definition: features.c:849
Structure for mutex and tracking information.
Definition: lock.h:121
int count
Number of times the call has been redirected.
Definition: isdn_lib.h:316
int noautorespond_on_setup
TRUE of we are not to respond immediately to a SETUP message. Check the dialplan first.
Definition: chan_misdn.c:385
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
static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel *bc, struct chan_list *ch)
Definition: chan_misdn.c:9051
static char * handle_cli_misdn_show_ports_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4361
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
static void misdn_queue_connected_line_update(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
Definition: chan_misdn.c:6077
int samples
Definition: frame.h:150
static char * handle_cli_misdn_port_up(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3887
static enum event_response_e cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
Definition: chan_misdn.c:9859
event_e
Definition: isdn_lib.h:119
#define ast_mutex_unlock(a)
Definition: lock.h:156
void(* cb_log)(int level, int port, char *tmpl,...)
Definition: isdn_lib.c:32
ast_bridge_result
Definition: channel.h:168
int early_bconnect
TRUE if the call progress indicators can indicate an inband audio message for the user to listen to...
Definition: isdn_lib.h:449
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1009
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
int state_empty
Definition: chan_misdn.c:108
static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
Definition: chan_misdn.c:2014
int nttimeout
TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
Definition: chan_misdn.c:548
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
int toggle_ec
TRUE if echo canceller is enabled. Value is toggled.
Definition: chan_misdn.c:397