Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
26  *
27  * MISDN http://www.misdn.org/
28  *
29  * \ingroup channel_drivers
30  */
31 
32 /*! \li \ref chan_misdn.c uses the configuration file \ref misdn.conf
33  * \addtogroup configuration_file
34  */
35 
36 /*! \page misdn.conf misdn.conf
37  * \verbinclude misdn.conf.sample
38  */
39 
40 /*!
41  * \note
42  * To use the CCBS/CCNR supplementary service feature and other
43  * supplementary services using FACILITY messages requires a
44  * modified version of mISDN.
45  *
46  * \note
47  * The latest modified mISDN v1.1.x based version is available at:
48  * http://svn.digium.com/svn/thirdparty/mISDN/trunk
49  * http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
50  *
51  * \note
52  * Taged versions of the modified mISDN code are available under:
53  * http://svn.digium.com/svn/thirdparty/mISDN/tags
54  * http://svn.digium.com/svn/thirdparty/mISDNuser/tags
55  */
56 
57 /* Define to enable cli commands to generate canned CCBS messages. */
58 // #define CCBS_TEST_MESSAGES 1
59 
60 /*
61  * XXX The mISDN channel driver needs its native bridge code
62  * converted to the new bridge technology scheme. The
63  * chan_dahdi native bridge code can be used as an example. It
64  * is unlikely that this will ever get done. Support for this
65  * channel driver is dwindling because the supported version of
66  * mISDN does not support newer kernels.
67  *
68  * Without native bridge support, the following config file
69  * parameters have no effect: bridging.
70  *
71  * The existing native bridge code is marked with the
72  * mISDN_NATIVE_BRIDGING conditional.
73  */
74 
75 /*** MODULEINFO
76  <depend>isdnnet</depend>
77  <depend>misdn</depend>
78  <depend>suppserv</depend>
79  <support_level>deprecated</support_level>
80  <replacement>chan_dahdi</replacement>
81  ***/
82 
83 #include "asterisk.h"
84 
85 #include <pthread.h>
86 #include <sys/socket.h>
87 #include <sys/time.h>
88 #include <arpa/inet.h>
89 #include <fcntl.h>
90 #include <sys/ioctl.h>
91 #include <signal.h>
92 #include <sys/file.h>
93 #include <semaphore.h>
94 #include <ctype.h>
95 #include <time.h>
96 
97 #include "asterisk/channel.h"
98 #include "asterisk/config.h"
99 #include "asterisk/module.h"
100 #include "asterisk/pbx.h"
101 #include "asterisk/io.h"
102 #include "asterisk/frame.h"
103 #include "asterisk/translate.h"
104 #include "asterisk/cli.h"
105 #include "asterisk/musiconhold.h"
106 #include "asterisk/dsp.h"
107 #include "asterisk/file.h"
108 #include "asterisk/callerid.h"
109 #include "asterisk/indications.h"
110 #include "asterisk/app.h"
111 #include "asterisk/features.h"
112 #include "asterisk/term.h"
113 #include "asterisk/sched.h"
114 #include "asterisk/stringfields.h"
115 #include "asterisk/abstract_jb.h"
116 #include "asterisk/causes.h"
117 #include "asterisk/format.h"
118 #include "asterisk/format_cap.h"
120 #include "asterisk/bridge.h"
121 #include "asterisk/pickup.h"
122 #include "asterisk/format_cache.h"
123 
124 #include "chan_misdn_config.h"
125 #include "isdn_lib.h"
126 
127 static char global_tracefile[BUFFERSIZE + 1];
128 
129 static int g_config_initialized = 0;
130 
131 struct misdn_jb{
132  int size;
134  char *samples, *ok;
135  int wp,rp;
141 };
142 
143 /*! \brief allocates the jb-structure and initialize the elements */
144 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
145 
146 /*! \brief frees the data and destroys the given jitterbuffer struct */
147 void misdn_jb_destroy(struct misdn_jb *jb);
148 
149 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
150 error (buffer overrun). */
151 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
152 
153 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
154 available data is returned and the return value indicates the number
155 of data. */
156 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
157 
158 static char *complete_ch(struct ast_cli_args *a);
159 static char *complete_debug_port(struct ast_cli_args *a);
160 static char *complete_show_config(struct ast_cli_args *a);
161 
162 /* BEGIN: chan_misdn.h */
163 
164 #if defined(AST_MISDN_ENHANCEMENTS)
165 /*
166  * This timeout duration is to clean up any call completion records that
167  * are forgotten about by the switch.
168  */
169 #define MISDN_CC_RECORD_AGE_MAX (6UL * 60 * 60) /* seconds */
170 
171 #define MISDN_CC_REQUEST_WAIT_MAX 5 /* seconds */
172 
173 /*!
174  * \brief Caller that initialized call completion services
175  *
176  * \details
177  * This data is the payload for a datastore that is put on the channel that
178  * initializes call completion services. This datastore is set to be inherited
179  * by the outbound mISDN channel. When one of these channels hangs up, the
180  * channel pointer will be set to NULL. That way, we can ensure that we do not
181  * touch this channel after it gets destroyed.
182  */
183 struct misdn_cc_caller {
184  /*! \brief The channel that initialized call completion services */
185  struct ast_channel *chan;
186 };
187 
188 struct misdn_cc_notify {
189  /*! \brief Dialplan: Notify extension priority */
190  int priority;
191 
192  /*! \brief Dialplan: Notify extension context */
193  char context[AST_MAX_CONTEXT];
194 
195  /*! \brief Dialplan: Notify extension number (User-A) */
196  char exten[AST_MAX_EXTENSION];
197 };
198 
199 /*! \brief mISDN call completion record */
200 struct misdn_cc_record {
201  /*! \brief Call completion record linked list */
202  AST_LIST_ENTRY(misdn_cc_record) list;
203 
204  /*! \brief Time the record was created. */
205  time_t time_created;
206 
207  /*! \brief MISDN_CC_RECORD_ID value */
208  long record_id;
209 
210  /*!
211  * \brief Logical Layer 1 port associated with this
212  * call completion record
213  */
214  int port;
215 
216  /*! \brief TRUE if point-to-point mode (CCBS-T/CCNR-T mode) */
217  int ptp;
218 
219  /*! \brief Mode specific parameters */
220  union {
221  /*! \brief point-to-point specific parameters. */
222  struct {
223  /*!
224  * \brief Call-completion signaling link.
225  * NULL if signaling link not established.
226  */
227  struct misdn_bchannel *bc;
228 
229  /*!
230  * \brief TRUE if we requested the request retention option
231  * to be enabled.
232  */
233  int requested_retention;
234 
235  /*!
236  * \brief TRUE if the request retention option is enabled.
237  */
238  int retention_enabled;
239  } ptp;
240 
241  /*! \brief point-to-multi-point specific parameters. */
242  struct {
243  /*! \brief CallLinkageID (valid when port determined) */
244  int linkage_id;
245 
246  /*! \breif CCBSReference (valid when activated is TRUE) */
247  int reference_id;
248 
249  /*! \brief globalRecall(0), specificRecall(1) */
250  int recall_mode;
251  } ptmp;
252  } mode;
253 
254  /*! \brief TRUE if call completion activated */
255  int activated;
256 
257  /*! \brief Outstanding message ID (valid when outstanding_message) */
258  int invoke_id;
259 
260  /*! \brief TRUE if waiting for a response from a message (invoke_id is valid) */
261  int outstanding_message;
262 
263  /*! \brief TRUE if activation has been requested */
264  int activation_requested;
265 
266  /*!
267  * \brief TRUE if User-A is free
268  * \note PTMP - Used to answer CCBSStatusRequest.
269  * PTP - Determines how to respond to CCBS_T_RemoteUserFree.
270  */
271  int party_a_free;
272 
273  /*! \brief Error code received from last outstanding message. */
274  enum FacErrorCode error_code;
275 
276  /*! \brief Reject code received from last outstanding message. */
277  enum FacRejectCode reject_code;
278 
279  /*!
280  * \brief Saved struct misdn_bchannel call information when
281  * attempted to call User-B
282  */
283  struct {
284  /*! \brief User-A caller id information */
285  struct misdn_party_id caller;
286 
287  /*! \brief User-B number information */
288  struct misdn_party_dialing dialed;
289 
290  /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */
291  struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
292 
293  /*! \brief SETUP message bearer capability field code value */
294  int capability;
295 
296  /*! \brief TRUE if call made in digital HDLC mode */
297  int hdlc;
298  } redial;
299 
300  /*! \brief Dialplan location to indicate User-B free and User-A is free */
301  struct misdn_cc_notify remote_user_free;
302 
303  /*! \brief Dialplan location to indicate User-B free and User-A is busy */
304  struct misdn_cc_notify b_free;
305 };
306 
307 /*! \brief mISDN call completion record database */
308 static AST_LIST_HEAD_STATIC(misdn_cc_records_db, misdn_cc_record);
309 /*! \brief Next call completion record ID to use */
310 static __u16 misdn_cc_record_id;
311 /*! \brief Next invoke ID to use */
312 static __s16 misdn_invoke_id;
313 
314 static const char misdn_no_response_from_network[] = "No response from network";
315 static const char misdn_cc_record_not_found[] = "Call completion record not found";
316 
317 /* mISDN channel variable names */
318 #define MISDN_CC_RECORD_ID "MISDN_CC_RECORD_ID"
319 #define MISDN_CC_STATUS "MISDN_CC_STATUS"
320 #define MISDN_ERROR_MSG "MISDN_ERROR_MSG"
321 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
322 
324 
326  MISDN_NOTHING = 0, /*!< at beginning */
327  MISDN_WAITING4DIGS, /*!< when waiting for info */
328  MISDN_EXTCANTMATCH, /*!< when asterisk couldn't match our ext */
329  MISDN_INCOMING_SETUP, /*!< for incoming setup */
330  MISDN_DIALING, /*!< when pbx_start */
331  MISDN_PROGRESS, /*!< we have progress */
332  MISDN_PROCEEDING, /*!< we have progress */
333  MISDN_CALLING, /*!< when misdn_call is called */
334  MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
335  MISDN_ALERTING, /*!< when Alerting */
336  MISDN_BUSY, /*!< when BUSY */
337  MISDN_CONNECTED, /*!< when connected */
338  MISDN_DISCONNECTED, /*!< when connected */
339  MISDN_CLEANING, /*!< when hangup from * but we were connected before */
340 };
341 
342 /*! Asterisk created the channel (outgoing call) */
343 #define ORG_AST 1
344 /*! mISDN created the channel (incoming call) */
345 #define ORG_MISDN 2
346 
348  MISDN_HOLD_IDLE, /*!< HOLD not active */
349  MISDN_HOLD_ACTIVE, /*!< Call is held */
350  MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
351  MISDN_HOLD_DISCONNECT, /*!< Held call is being disconnected */
352 };
353 struct hold_info {
354  /*!
355  * \brief Call HOLD state.
356  */
358  /*!
359  * \brief Logical port the channel call record is HELD on
360  * because the B channel is no longer associated.
361  */
362  int port;
363 
364  /*!
365  * \brief Original B channel number the HELD call was using.
366  * \note Used only for debug display messages.
367  */
368  int channel;
369 };
370 
371 #define chan_list_ref(obj, debug) ao2_t_ref((obj), +1, (debug))
372 #define chan_list_unref(obj, debug) ao2_t_ref((obj), -1, (debug))
373 
374 /*!
375  * \brief Channel call record structure
376  */
377 struct chan_list {
378  /*!
379  * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
380  */
382 
383  /*!
384  * \brief State of the channel
385  */
387 
388  /*!
389  * \brief TRUE if a hangup needs to be queued
390  * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
391  */
393 
394  /*!
395  * \brief TRUE if a channel can be hung up by calling asterisk directly when done.
396  */
398 
399  /*!
400  * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
401  */
403 
404  /*!
405  * \brief Who originally created this channel. ORG_AST or ORG_MISDN
406  */
408 
409  /*!
410  * \brief TRUE of we are not to respond immediately to a SETUP message. Check the dialplan first.
411  * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
412  */
414 
415  int norxtone; /*!< Boolean assigned values but the value is not used. */
416 
417  /*!
418  * \brief TRUE if we are not to generate tones (Playtones)
419  */
420  int notxtone;
421 
422  /*!
423  * \brief TRUE if echo canceller is enabled. Value is toggled.
424  */
426 
427  /*!
428  * \brief TRUE if you want to send Tone Indications to an incoming
429  * ISDN channel on a TE Port.
430  * \note The "incoming_early_audio" boolean read in from /etc/asterisk/misdn.conf
431  */
433 
434  /*!
435  * \brief TRUE if DTMF digits are to be passed inband only.
436  * \note It is settable by the misdn_set_opt() application.
437  */
439 
440  /*!
441  * \brief Pipe file descriptor handles array.
442  * Read from pipe[0], write to pipe[1]
443  */
444  int pipe[2];
445 
446  /*!
447  * \brief Read buffer for inbound audio from pipe[0]
448  */
449  char ast_rd_buf[4096];
450 
451  /*!
452  * \brief Inbound audio frame returned by misdn_read().
453  */
454  struct ast_frame frame;
455 
456  /*!
457  * \brief Fax detection option. (0:no 1:yes 2:yes+nojump)
458  * \note The "faxdetect" option string read in from /etc/asterisk/misdn.conf
459  * \note It is settable by the misdn_set_opt() application.
460  */
462 
463  /*!
464  * \brief Number of seconds to detect a Fax machine when detection enabled.
465  * \note 0 disables the timeout.
466  * \note The "faxdetect_timeout" value read in from /etc/asterisk/misdn.conf
467  */
469 
470  /*!
471  * \brief Starting time of fax detection with timeout when nonzero.
472  */
473  struct timeval faxdetect_tv;
474 
475  /*!
476  * \brief TRUE if a fax has been detected.
477  */
479 
480  /*!
481  * \brief TRUE if we will use the Asterisk DSP to detect DTMF/Fax
482  * \note The "astdtmf" boolean read in from /etc/asterisk/misdn.conf
483  */
484  int ast_dsp;
485 
486  /*!
487  * \brief Jitterbuffer length
488  * \note The "jitterbuffer" value read in from /etc/asterisk/misdn.conf
489  */
490  int jb_len;
491 
492  /*!
493  * \brief Jitterbuffer upper threshold
494  * \note The "jitterbuffer_upper_threshold" value read in from /etc/asterisk/misdn.conf
495  */
497 
498  /*!
499  * \brief Allocated jitterbuffer controller
500  * \note misdn_jb_init() creates the jitterbuffer.
501  * \note Must use misdn_jb_destroy() to clean up.
502  */
503  struct misdn_jb *jb;
504 
505  /*!
506  * \brief Allocated DSP controller
507  * \note ast_dsp_new() creates the DSP controller.
508  * \note Must use ast_dsp_free() to clean up.
509  */
510  struct ast_dsp *dsp;
511 
512  /*!
513  * \brief Associated Asterisk channel structure.
514  */
515  struct ast_channel * ast;
516 
517  /*!
518  * \brief Associated B channel structure.
519  */
521 
522 #if defined(AST_MISDN_ENHANCEMENTS)
523  /*!
524  * \brief Peer channel for which call completion was initialized.
525  */
526  struct misdn_cc_caller *peer;
527 
528  /*! \brief Associated call completion record ID (-1 if not associated) */
529  long record_id;
530 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
531 
532  /*!
533  * \brief HELD channel call information
534  */
535  struct hold_info hold;
536 
537  /*!
538  * \brief From associated B channel: Layer 3 process ID
539  * \note Used to find the HELD channel call record when retrieving a call.
540  */
541  unsigned int l3id;
542 
543  /*!
544  * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
545  * \note Used only for debug display messages.
546  */
547  int addr;
548 
549  /*!
550  * \brief Incoming call dialplan context identifier.
551  * \note The "context" string read in from /etc/asterisk/misdn.conf
552  */
554 
555  /*!
556  * \brief The configured music-on-hold class to use for this call.
557  * \note The "musicclass" string read in from /etc/asterisk/misdn.conf
558  */
560 
561  /*!
562  * \brief Number of outgoing audio frames dropped since last debug gripe message.
563  */
565 
566  /*!
567  * \brief TRUE if we must do the ringback tones.
568  * \note The "far_alerting" boolean read in from /etc/asterisk/misdn.conf
569  */
571 
572  /*!
573  * \brief TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
574  * \note The "nttimeout" boolean read in from /etc/asterisk/misdn.conf
575  */
577 
578  /*!
579  * \brief Tone zone sound used for dialtone generation.
580  * \note Used as a boolean. Non-NULL to prod generation if enabled.
581  */
583 
584  /*!
585  * \brief Enables overlap dialing for the set amount of seconds. (0 = Disabled)
586  * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
587  */
589 
590  /*!
591  * \brief Overlap dialing timeout Task ID. -1 if not running.
592  */
594 
595  /*!
596  * \brief overlap_tv access lock.
597  */
599 
600  /*!
601  * \brief Overlap timer start time. Timer restarted for every digit received.
602  */
603  struct timeval overlap_tv;
604 
605  /*!
606  * \brief Next channel call record in the list.
607  */
608  struct chan_list *next;
609 };
610 
611 
612 int MAXTICS = 8;
613 
614 
615 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
616 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
617 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
618 
619 struct robin_list {
620  char *group;
621  int port;
622  int channel;
623  struct robin_list *next;
624  struct robin_list *prev;
625 };
626 static struct robin_list *robin = NULL;
627 
628 
629 static void free_robin_list(void)
630 {
631  struct robin_list *r;
632  struct robin_list *next;
633 
634  for (r = robin, robin = NULL; r; r = next) {
635  next = r->next;
636  ast_free(r->group);
637  ast_free(r);
638  }
639 }
640 
641 static struct robin_list *get_robin_position(char *group)
642 {
643  struct robin_list *new;
644  struct robin_list *iter = robin;
645  for (; iter; iter = iter->next) {
646  if (!strcasecmp(iter->group, group)) {
647  return iter;
648  }
649  }
650  new = ast_calloc(1, sizeof(*new));
651  if (!new) {
652  return NULL;
653  }
654  new->group = ast_strdup(group);
655  if (!new->group) {
656  ast_free(new);
657  return NULL;
658  }
659  new->channel = 1;
660  if (robin) {
661  new->next = robin;
662  robin->prev = new;
663  }
664  robin = new;
665  return robin;
666 }
667 
668 
669 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
671 static pthread_t misdn_tasks_thread;
672 
673 static int *misdn_ports;
674 
675 static void chan_misdn_log(int level, int port, char *tmpl, ...)
676  __attribute__((format(printf, 3, 4)));
677 
678 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int port, int c);
679 static void send_digit_to_chan(struct chan_list *cl, char digit);
680 
681 static int pbx_start_chan(struct chan_list *ch);
682 
683 #define MISDN_ASTERISK_TECH_PVT(ast) ast_channel_tech_pvt(ast)
684 #define MISDN_ASTERISK_TECH_PVT_SET(ast, value) ast_channel_tech_pvt_set(ast, value)
685 
686 #include "asterisk/strings.h"
687 
688 /* #define MISDN_DEBUG 1 */
689 
690 static const char misdn_type[] = "mISDN";
691 
692 static int tracing = 0;
693 
694 static int *misdn_debug;
695 static int *misdn_debug_only;
696 static int max_ports;
697 
698 static int *misdn_in_calls;
699 static int *misdn_out_calls;
700 
701 /*!
702  * \brief Global channel call record list head.
703  */
704 static struct chan_list *cl_te=NULL;
706 
707 static enum event_response_e
708 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
709 
710 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
711 
712 static void cl_queue_chan(struct chan_list *chan);
713 
714 static int dialtone_indicate(struct chan_list *cl);
715 static void hanguptone_indicate(struct chan_list *cl);
716 static int stop_indicate(struct chan_list *cl);
717 
718 static int start_bc_tones(struct chan_list *cl);
719 static int stop_bc_tones(struct chan_list *cl);
720 static void release_chan_early(struct chan_list *ch);
721 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc);
722 
723 #if defined(AST_MISDN_ENHANCEMENTS)
724 static const char misdn_command_name[] = "misdn_command";
725 static int misdn_command_exec(struct ast_channel *chan, const char *data);
726 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
727 static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
728 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
729 static int misdn_facility_exec(struct ast_channel *chan, const char *data);
730 
731 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
732 
733 void debug_numtype(int port, int numtype, char *type);
734 
735 int add_out_calls(int port);
736 int add_in_calls(int port);
737 
738 
739 #ifdef MISDN_1_2
740 static int update_pipeline_config(struct misdn_bchannel *bc);
741 #else
742 static int update_ec_config(struct misdn_bchannel *bc);
743 #endif
744 
745 
746 
747 /*************** Helpers *****************/
748 
749 static int misdn_chan_is_valid(struct chan_list *ch)
750 {
751  struct chan_list *list;
752 
753  ast_mutex_lock(&cl_te_lock);
754  for (list = cl_te; list; list = list->next) {
755  if (list == ch) {
756  ast_mutex_unlock(&cl_te_lock);
757  return 1;
758  }
759  }
760  ast_mutex_unlock(&cl_te_lock);
761 
762  return 0;
763 }
764 
765 #if defined(mISDN_NATIVE_BRIDGING)
766 /*! Returns a reference to the found chan_list. */
767 static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
768 {
769  struct chan_list *tmp;
770 
771  ast_mutex_lock(&cl_te_lock);
772  for (tmp = cl_te; tmp; tmp = tmp->next) {
773  if (tmp->ast == ast) {
774  chan_list_ref(tmp, "Found chan_list by ast");
775  ast_mutex_unlock(&cl_te_lock);
776  return tmp;
777  }
778  }
779  ast_mutex_unlock(&cl_te_lock);
780 
781  return NULL;
782 }
783 #endif /* defined(mISDN_NATIVE_BRIDGING) */
784 
785 /*! Returns a reference to the found chan_list. */
786 static struct chan_list *get_chan_by_ast_name(const char *name)
787 {
788  struct chan_list *tmp;
789 
790  ast_mutex_lock(&cl_te_lock);
791  for (tmp = cl_te; tmp; tmp = tmp->next) {
792  if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
793  chan_list_ref(tmp, "Found chan_list by ast name");
794  ast_mutex_unlock(&cl_te_lock);
795  return tmp;
796  }
797  }
798  ast_mutex_unlock(&cl_te_lock);
799 
800  return NULL;
801 }
802 
803 #if defined(AST_MISDN_ENHANCEMENTS)
804 /*!
805  * \internal
806  * \brief Destroy the misdn_cc_ds_info datastore payload
807  *
808  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
809  *
810  * \details
811  * Since the payload is a reference to an astobj2 object, we just decrement its
812  * reference count. Before doing so, we NULL out the channel pointer inside of
813  * the misdn_cc_caller instance. This function will be called in one of two
814  * cases. In both cases, we no longer need the channel pointer:
815  *
816  * - The original channel that initialized call completion services, the same
817  * channel that is stored here, has been destroyed early. This could happen
818  * if it transferred the mISDN channel, for example.
819  *
820  * - The mISDN channel that had this datastore inherited on to it is now being
821  * destroyed. If this is the case, then the call completion events have
822  * already occurred and the appropriate channel variables have already been
823  * set on the original channel that requested call completion services.
824  *
825  * \return Nothing
826  */
827 static void misdn_cc_ds_destroy(void *data)
828 {
829  struct misdn_cc_caller *cc_caller = data;
830 
831  ao2_lock(cc_caller);
832  cc_caller->chan = NULL;
833  ao2_unlock(cc_caller);
834 
835  ao2_ref(cc_caller, -1);
836 }
837 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
838 
839 #if defined(AST_MISDN_ENHANCEMENTS)
840 /*!
841  * \internal
842  * \brief Duplicate the misdn_cc_ds_info datastore payload
843  *
844  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
845  *
846  * \details
847  * All we need to do is bump the reference count and return the same instance.
848  *
849  * \return A reference to an instance of a misdn_cc_caller
850  */
851 static void *misdn_cc_ds_duplicate(void *data)
852 {
853  struct misdn_cc_caller *cc_caller = data;
854 
855  ao2_ref(cc_caller, +1);
856 
857  return cc_caller;
858 }
859 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
860 
861 #if defined(AST_MISDN_ENHANCEMENTS)
862 static const struct ast_datastore_info misdn_cc_ds_info = {
863  .type = "misdn_cc",
864  .destroy = misdn_cc_ds_destroy,
865  .duplicate = misdn_cc_ds_duplicate,
866 };
867 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
868 
869 #if defined(AST_MISDN_ENHANCEMENTS)
870 /*!
871  * \internal
872  * \brief Set a channel var on the peer channel for call completion services
873  *
874  * \param[in] peer The peer that initialized call completion services
875  * \param[in] var The variable name to set
876  * \param[in] value The variable value to set
877  *
878  * This function may be called from outside of the channel thread. It handles
879  * the fact that the peer channel may be hung up and destroyed at any time.
880  *
881  * \return nothing
882  */
883 static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
884  const char *value)
885 {
886  ao2_lock(peer);
887 
888  /*! \todo XXX This nastiness can go away once ast_channel is ref counted! */
889  while (peer->chan && ast_channel_trylock(peer->chan)) {
890  ao2_unlock(peer);
891  sched_yield();
892  ao2_lock(peer);
893  }
894 
895  if (peer->chan) {
896  pbx_builtin_setvar_helper(peer->chan, var, value);
897  ast_channel_unlock(peer->chan);
898  }
899 
900  ao2_unlock(peer);
901 }
902 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
903 
904 #if defined(AST_MISDN_ENHANCEMENTS)
905 /*!
906  * \internal
907  * \brief Get a reference to the CC caller if it exists
908  */
909 static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
910 {
911  struct ast_datastore *datastore;
912  struct misdn_cc_caller *cc_caller;
913 
914  ast_channel_lock(chan);
915 
916  if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
917  ast_channel_unlock(chan);
918  return NULL;
919  }
920 
921  ao2_ref(datastore->data, +1);
922  cc_caller = datastore->data;
923 
924  ast_channel_unlock(chan);
925 
926  return cc_caller;
927 }
928 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
929 
930 #if defined(AST_MISDN_ENHANCEMENTS)
931 /*!
932  * \internal
933  * \brief Find the call completion record given the record id.
934  *
935  * \param record_id
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_id(long record_id)
943 {
944  struct misdn_cc_record *current;
945 
946  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
947  if (current->record_id == record_id) {
948  /* Found the record */
949  break;
950  }
951  }
952 
953  return current;
954 }
955 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
956 
957 #if defined(AST_MISDN_ENHANCEMENTS)
958 /*!
959  * \internal
960  * \brief Find the call completion record given the port and call linkage id.
961  *
962  * \param port Logical port number
963  * \param linkage_id Call linkage ID number from switch.
964  *
965  * \retval pointer to found call completion record
966  * \retval NULL if not found
967  *
968  * \note Assumes the misdn_cc_records_db lock is already obtained.
969  */
970 static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
971 {
972  struct misdn_cc_record *current;
973 
974  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
975  if (current->port == port
976  && !current->ptp
977  && current->mode.ptmp.linkage_id == linkage_id) {
978  /* Found the record */
979  break;
980  }
981  }
982 
983  return current;
984 }
985 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
986 
987 #if defined(AST_MISDN_ENHANCEMENTS)
988 /*!
989  * \internal
990  * \brief Find the call completion record given the port and outstanding invocation id.
991  *
992  * \param port Logical port number
993  * \param invoke_id Outstanding message invocation ID number.
994  *
995  * \retval pointer to found call completion record
996  * \retval NULL if not found
997  *
998  * \note Assumes the misdn_cc_records_db lock is already obtained.
999  */
1000 static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
1001 {
1002  struct misdn_cc_record *current;
1003 
1004  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1005  if (current->outstanding_message
1006  && current->invoke_id == invoke_id
1007  && current->port == port) {
1008  /* Found the record */
1009  break;
1010  }
1011  }
1012 
1013  return current;
1014 }
1015 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1016 
1017 #if defined(AST_MISDN_ENHANCEMENTS)
1018 /*!
1019  * \internal
1020  * \brief Find the call completion record given the port and CCBS reference id.
1021  *
1022  * \param port Logical port number
1023  * \param reference_id CCBS reference ID number from switch.
1024  *
1025  * \retval pointer to found call completion record
1026  * \retval NULL if not found
1027  *
1028  * \note Assumes the misdn_cc_records_db lock is already obtained.
1029  */
1030 static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
1031 {
1032  struct misdn_cc_record *current;
1033 
1034  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1035  if (current->activated
1036  && current->port == port
1037  && !current->ptp
1038  && current->mode.ptmp.reference_id == reference_id) {
1039  /* Found the record */
1040  break;
1041  }
1042  }
1043 
1044  return current;
1045 }
1046 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1047 
1048 #if defined(AST_MISDN_ENHANCEMENTS)
1049 /*!
1050  * \internal
1051  * \brief Find the call completion record given the B channel pointer
1052  *
1053  * \param bc B channel control structure pointer.
1054  *
1055  * \retval pointer to found call completion record
1056  * \retval NULL if not found
1057  *
1058  * \note Assumes the misdn_cc_records_db lock is already obtained.
1059  */
1060 static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
1061 {
1062  struct misdn_cc_record *current;
1063 
1064  if (bc) {
1065  AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1066  if (current->ptp
1067  && current->mode.ptp.bc == bc) {
1068  /* Found the record */
1069  break;
1070  }
1071  }
1072  } else {
1073  current = NULL;
1074  }
1075 
1076  return current;
1077 }
1078 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1079 
1080 #if defined(AST_MISDN_ENHANCEMENTS)
1081 /*!
1082  * \internal
1083  * \brief Delete the given call completion record
1084  *
1085  * \param doomed Call completion record to destroy
1086  *
1087  * \return Nothing
1088  *
1089  * \note Assumes the misdn_cc_records_db lock is already obtained.
1090  */
1091 static void misdn_cc_delete(struct misdn_cc_record *doomed)
1092 {
1093  struct misdn_cc_record *current;
1094 
1095  AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1096  if (current == doomed) {
1098  ast_free(current);
1099  return;
1100  }
1101  }
1103 
1104  /* The doomed node is not in the call completion database */
1105 }
1106 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1107 
1108 #if defined(AST_MISDN_ENHANCEMENTS)
1109 /*!
1110  * \internal
1111  * \brief Delete all old call completion records
1112  *
1113  * \return Nothing
1114  *
1115  * \note Assumes the misdn_cc_records_db lock is already obtained.
1116  */
1117 static void misdn_cc_remove_old(void)
1118 {
1119  struct misdn_cc_record *current;
1120  time_t now;
1121 
1122  now = time(NULL);
1123  AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1124  if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
1125  if (current->ptp && current->mode.ptp.bc) {
1126  /* Close the old call-completion signaling link */
1127  current->mode.ptp.bc->fac_out.Function = Fac_None;
1128  current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
1129  misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
1130  }
1131 
1132  /* Remove the old call completion record */
1134  ast_free(current);
1135  }
1136  }
1138 }
1139 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1140 
1141 #if defined(AST_MISDN_ENHANCEMENTS)
1142 /*!
1143  * \internal
1144  * \brief Allocate the next record id.
1145  *
1146  * \retval New record id on success.
1147  * \retval -1 on error.
1148  *
1149  * \note Assumes the misdn_cc_records_db lock is already obtained.
1150  */
1151 static long misdn_cc_record_id_new(void)
1152 {
1153  long record_id;
1154  long first_id;
1155 
1156  record_id = ++misdn_cc_record_id;
1157  first_id = record_id;
1158  while (misdn_cc_find_by_id(record_id)) {
1159  record_id = ++misdn_cc_record_id;
1160  if (record_id == first_id) {
1161  /*
1162  * We have a resource leak.
1163  * We should never need to allocate 64k records.
1164  */
1165  chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
1166  record_id = -1;
1167  break;
1168  }
1169  }
1170 
1171  return record_id;
1172 }
1173 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1174 
1175 #if defined(AST_MISDN_ENHANCEMENTS)
1176 /*!
1177  * \internal
1178  * \brief Create a new call completion record
1179  *
1180  * \retval pointer to new call completion record
1181  * \retval NULL if failed
1182  *
1183  * \note Assumes the misdn_cc_records_db lock is already obtained.
1184  */
1185 static struct misdn_cc_record *misdn_cc_new(void)
1186 {
1187  struct misdn_cc_record *cc_record;
1188  long record_id;
1189 
1190  misdn_cc_remove_old();
1191 
1192  cc_record = ast_calloc(1, sizeof(*cc_record));
1193  if (cc_record) {
1194  record_id = misdn_cc_record_id_new();
1195  if (record_id < 0) {
1196  ast_free(cc_record);
1197  return NULL;
1198  }
1199 
1200  /* Initialize the new record */
1201  cc_record->record_id = record_id;
1202  cc_record->port = -1;/* Invalid port so it will never be found this way */
1203  cc_record->invoke_id = ++misdn_invoke_id;
1204  cc_record->party_a_free = 1;/* Default User-A as free */
1205  cc_record->error_code = FacError_None;
1206  cc_record->reject_code = FacReject_None;
1207  cc_record->time_created = time(NULL);
1208 
1209  /* Insert the new record into the database */
1210  AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
1211  }
1212  return cc_record;
1213 }
1214 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1215 
1216 #if defined(AST_MISDN_ENHANCEMENTS)
1217 /*!
1218  * \internal
1219  * \brief Destroy the call completion record database
1220  *
1221  * \return Nothing
1222  */
1223 static void misdn_cc_destroy(void)
1224 {
1225  struct misdn_cc_record *current;
1226 
1227  while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
1228  /* Do a misdn_cc_delete(current) inline */
1229  ast_free(current);
1230  }
1231 }
1232 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1233 
1234 #if defined(AST_MISDN_ENHANCEMENTS)
1235 /*!
1236  * \internal
1237  * \brief Initialize the call completion record database
1238  *
1239  * \return Nothing
1240  */
1241 static void misdn_cc_init(void)
1242 {
1243  misdn_cc_record_id = 0;
1244 }
1245 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1246 
1247 #if defined(AST_MISDN_ENHANCEMENTS)
1248 /*!
1249  * \internal
1250  * \brief Check the status of an outstanding invocation request.
1251  *
1252  * \param data Points to an integer containing the call completion record id.
1253  *
1254  * \retval 0 if got a response.
1255  * \retval -1 if no response yet.
1256  */
1257 static int misdn_cc_response_check(void *data)
1258 {
1259  int not_responded;
1260  struct misdn_cc_record *cc_record;
1261 
1262  AST_LIST_LOCK(&misdn_cc_records_db);
1263  cc_record = misdn_cc_find_by_id(*(long *) data);
1264  if (cc_record) {
1265  if (cc_record->outstanding_message) {
1266  not_responded = -1;
1267  } else {
1268  not_responded = 0;
1269  }
1270  } else {
1271  /* No record so there is no response to check. */
1272  not_responded = 0;
1273  }
1274  AST_LIST_UNLOCK(&misdn_cc_records_db);
1275 
1276  return not_responded;
1277 }
1278 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1279 
1280 #if defined(AST_MISDN_ENHANCEMENTS)
1281 /*!
1282  * \internal
1283  * \brief Wait for a response from the switch for an outstanding
1284  * invocation request.
1285  *
1286  * \param chan Asterisk channel to operate upon.
1287  * \param wait_seconds Number of seconds to wait
1288  * \param record_id Call completion record ID.
1289  *
1290  * \return Nothing
1291  */
1292 static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
1293 {
1294  unsigned count;
1295 
1296  for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
1297  /* Sleep in 500 ms increments */
1298  if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
1299  /* We got hung up or our response came in. */
1300  break;
1301  }
1302  }
1303 }
1304 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1305 
1306 #if defined(AST_MISDN_ENHANCEMENTS)
1307 /*!
1308  * \internal
1309  * \brief Convert the mISDN reject code to a string
1310  *
1311  * \param code mISDN reject code.
1312  *
1313  * \return The mISDN reject code as a string
1314  */
1315 static const char *misdn_to_str_reject_code(enum FacRejectCode code)
1316 {
1317  static const struct {
1318  enum FacRejectCode code;
1319  char *name;
1320  } arr[] = {
1321 /* *INDENT-OFF* */
1322  { FacReject_None, "No reject occurred" },
1323  { FacReject_Unknown, "Unknown reject code" },
1324 
1325  { FacReject_Gen_UnrecognizedComponent, "General: Unrecognized Component" },
1326  { FacReject_Gen_MistypedComponent, "General: Mistyped Component" },
1327  { FacReject_Gen_BadlyStructuredComponent, "General: Badly Structured Component" },
1328 
1329  { FacReject_Inv_DuplicateInvocation, "Invoke: Duplicate Invocation" },
1330  { FacReject_Inv_UnrecognizedOperation, "Invoke: Unrecognized Operation" },
1331  { FacReject_Inv_MistypedArgument, "Invoke: Mistyped Argument" },
1332  { FacReject_Inv_ResourceLimitation, "Invoke: Resource Limitation" },
1333  { FacReject_Inv_InitiatorReleasing, "Invoke: Initiator Releasing" },
1334  { FacReject_Inv_UnrecognizedLinkedID, "Invoke: Unrecognized Linked ID" },
1335  { FacReject_Inv_LinkedResponseUnexpected, "Invoke: Linked Response Unexpected" },
1336  { FacReject_Inv_UnexpectedChildOperation, "Invoke: Unexpected Child Operation" },
1337 
1338  { FacReject_Res_UnrecognizedInvocation, "Result: Unrecognized Invocation" },
1339  { FacReject_Res_ResultResponseUnexpected, "Result: Result Response Unexpected" },
1340  { FacReject_Res_MistypedResult, "Result: Mistyped Result" },
1341 
1342  { FacReject_Err_UnrecognizedInvocation, "Error: Unrecognized Invocation" },
1343  { FacReject_Err_ErrorResponseUnexpected, "Error: Error Response Unexpected" },
1344  { FacReject_Err_UnrecognizedError, "Error: Unrecognized Error" },
1345  { FacReject_Err_UnexpectedError, "Error: Unexpected Error" },
1346  { FacReject_Err_MistypedParameter, "Error: Mistyped Parameter" },
1347 /* *INDENT-ON* */
1348  };
1349 
1350  unsigned index;
1351 
1352  for (index = 0; index < ARRAY_LEN(arr); ++index) {
1353  if (arr[index].code == code) {
1354  return arr[index].name;
1355  }
1356  }
1357 
1358  return "unknown";
1359 }
1360 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1361 
1362 #if defined(AST_MISDN_ENHANCEMENTS)
1363 /*!
1364  * \internal
1365  * \brief Convert the mISDN error code to a string
1366  *
1367  * \param code mISDN error code.
1368  *
1369  * \return The mISDN error code as a string
1370  */
1371 static const char *misdn_to_str_error_code(enum FacErrorCode code)
1372 {
1373  static const struct {
1374  enum FacErrorCode code;
1375  char *name;
1376  } arr[] = {
1377 /* *INDENT-OFF* */
1378  { FacError_None, "No error occurred" },
1379  { FacError_Unknown, "Unknown OID error code" },
1380 
1381  { FacError_Gen_NotSubscribed, "General: Not Subscribed" },
1382  { FacError_Gen_NotAvailable, "General: Not Available" },
1383  { FacError_Gen_NotImplemented, "General: Not Implemented" },
1384  { FacError_Gen_InvalidServedUserNr, "General: Invalid Served User Number" },
1385  { FacError_Gen_InvalidCallState, "General: Invalid Call State" },
1386  { FacError_Gen_BasicServiceNotProvided, "General: Basic Service Not Provided" },
1387  { FacError_Gen_NotIncomingCall, "General: Not Incoming Call" },
1388  { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
1389  { FacError_Gen_ResourceUnavailable, "General: Resource Unavailable" },
1390 
1391  { FacError_Div_InvalidDivertedToNr, "Diversion: Invalid Diverted To Number" },
1392  { FacError_Div_SpecialServiceNr, "Diversion: Special Service Number" },
1393  { FacError_Div_DiversionToServedUserNr, "Diversion: Diversion To Served User Number" },
1394  { FacError_Div_IncomingCallAccepted, "Diversion: Incoming Call Accepted" },
1395  { FacError_Div_NumberOfDiversionsExceeded, "Diversion: Number Of Diversions Exceeded" },
1396  { FacError_Div_NotActivated, "Diversion: Not Activated" },
1397  { FacError_Div_RequestAlreadyAccepted, "Diversion: Request Already Accepted" },
1398 
1399  { FacError_AOC_NoChargingInfoAvailable, "AOC: No Charging Info Available" },
1400 
1401  { FacError_CCBS_InvalidCallLinkageID, "CCBS: Invalid Call Linkage ID" },
1402  { FacError_CCBS_InvalidCCBSReference, "CCBS: Invalid CCBS Reference" },
1403  { FacError_CCBS_LongTermDenial, "CCBS: Long Term Denial" },
1404  { FacError_CCBS_ShortTermDenial, "CCBS: Short Term Denial" },
1405  { FacError_CCBS_IsAlreadyActivated, "CCBS: Is Already Activated" },
1406  { FacError_CCBS_AlreadyAccepted, "CCBS: Already Accepted" },
1407  { FacError_CCBS_OutgoingCCBSQueueFull, "CCBS: Outgoing CCBS Queue Full" },
1408  { FacError_CCBS_CallFailureReasonNotBusy, "CCBS: Call Failure Reason Not Busy" },
1409  { FacError_CCBS_NotReadyForCall, "CCBS: Not Ready For Call" },
1410 
1411  { FacError_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
1412  { FacError_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
1413 
1414  { FacError_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
1415 /* *INDENT-ON* */
1416  };
1417 
1418  unsigned index;
1419 
1420  for (index = 0; index < ARRAY_LEN(arr); ++index) {
1421  if (arr[index].code == code) {
1422  return arr[index].name;
1423  }
1424  }
1425 
1426  return "unknown";
1427 }
1428 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1429 
1430 #if defined(AST_MISDN_ENHANCEMENTS)
1431 /*!
1432  * \internal
1433  * \brief Convert mISDN redirecting reason to diversion reason.
1434  *
1435  * \param reason mISDN redirecting reason code.
1436  *
1437  * \return Supported diversion reason code.
1438  */
1439 static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
1440 {
1441  unsigned diversion_reason;
1442 
1443  switch (reason) {
1445  diversion_reason = 1;/* cfu */
1446  break;
1448  diversion_reason = 2;/* cfb */
1449  break;
1451  diversion_reason = 3;/* cfnr */
1452  break;
1453  default:
1454  diversion_reason = 0;/* unknown */
1455  break;
1456  }
1457 
1458  return diversion_reason;
1459 }
1460 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1461 
1462 #if defined(AST_MISDN_ENHANCEMENTS)
1463 /*!
1464  * \internal
1465  * \brief Convert diversion reason to mISDN redirecting reason
1466  *
1467  * \param diversion_reason Diversion reason to convert
1468  *
1469  * \return Supported redirecting reason code.
1470  */
1471 static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
1472 {
1473  enum mISDN_REDIRECTING_REASON reason;
1474 
1475  switch (diversion_reason) {
1476  case 1:/* cfu */
1478  break;
1479  case 2:/* cfb */
1481  break;
1482  case 3:/* cfnr */
1484  break;
1485  default:
1487  break;
1488  }
1489 
1490  return reason;
1491 }
1492 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1493 
1494 #if defined(AST_MISDN_ENHANCEMENTS)
1495 /*!
1496  * \internal
1497  * \brief Convert the mISDN presentation to PresentedNumberUnscreened type
1498  *
1499  * \param presentation mISDN presentation to convert
1500  * \param number_present TRUE if the number is present
1501  *
1502  * \return PresentedNumberUnscreened type
1503  */
1504 static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
1505 {
1506  unsigned type;
1507 
1508  switch (presentation) {
1509  case 0:/* allowed */
1510  if (number_present) {
1511  type = 0;/* presentationAllowedNumber */
1512  } else {
1513  type = 2;/* numberNotAvailableDueToInterworking */
1514  }
1515  break;
1516  case 1:/* restricted */
1517  if (number_present) {
1518  type = 3;/* presentationRestrictedNumber */
1519  } else {
1520  type = 1;/* presentationRestricted */
1521  }
1522  break;
1523  default:
1524  type = 2;/* numberNotAvailableDueToInterworking */
1525  break;
1526  }
1527 
1528  return type;
1529 }
1530 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1531 
1532 #if defined(AST_MISDN_ENHANCEMENTS)
1533 /*!
1534  * \internal
1535  * \brief Convert the PresentedNumberUnscreened type to mISDN presentation
1536  *
1537  * \param type PresentedNumberUnscreened type
1538  *
1539  * \return mISDN presentation
1540  */
1541 static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
1542 {
1543  int presentation;
1544 
1545  switch (type) {
1546  default:
1547  case 0:/* presentationAllowedNumber */
1548  presentation = 0;/* allowed */
1549  break;
1550 
1551  case 1:/* presentationRestricted */
1552  case 3:/* presentationRestrictedNumber */
1553  presentation = 1;/* restricted */
1554  break;
1555 
1556  case 2:/* numberNotAvailableDueToInterworking */
1557  presentation = 2;/* unavailable */
1558  break;
1559  }
1560 
1561  return presentation;
1562 }
1563 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1564 
1565 #if defined(AST_MISDN_ENHANCEMENTS)
1566 /*!
1567  * \internal
1568  * \brief Convert the mISDN numbering plan to PartyNumber numbering plan
1569  *
1570  * \param number_plan mISDN numbering plan
1571  *
1572  * \return PartyNumber numbering plan
1573  */
1574 static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
1575 {
1576  unsigned party_plan;
1577 
1578  switch (number_plan) {
1579  default:
1580  case NUMPLAN_UNKNOWN:
1581  party_plan = 0;/* unknown */
1582  break;
1583 
1584  case NUMPLAN_ISDN:
1585  party_plan = 1;/* public */
1586  break;
1587 
1588  case NUMPLAN_DATA:
1589  party_plan = 3;/* data */
1590  break;
1591 
1592  case NUMPLAN_TELEX:
1593  party_plan = 4;/* telex */
1594  break;
1595 
1596  case NUMPLAN_NATIONAL:
1597  party_plan = 8;/* nationalStandard */
1598  break;
1599 
1600  case NUMPLAN_PRIVATE:
1601  party_plan = 5;/* private */
1602  break;
1603  }
1604 
1605  return party_plan;
1606 }
1607 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1608 
1609 #if defined(AST_MISDN_ENHANCEMENTS)
1610 /*!
1611  * \internal
1612  * \brief Convert PartyNumber numbering plan to mISDN numbering plan
1613  *
1614  * \param party_plan PartyNumber numbering plan
1615  *
1616  * \return mISDN numbering plan
1617  */
1618 static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
1619 {
1620  enum mISDN_NUMBER_PLAN number_plan;
1621 
1622  switch (party_plan) {
1623  default:
1624  case 0:/* unknown */
1625  number_plan = NUMPLAN_UNKNOWN;
1626  break;
1627  case 1:/* public */
1628  number_plan = NUMPLAN_ISDN;
1629  break;
1630  case 3:/* data */
1631  number_plan = NUMPLAN_DATA;
1632  break;
1633  case 4:/* telex */
1634  number_plan = NUMPLAN_TELEX;
1635  break;
1636  case 8:/* nationalStandard */
1637  number_plan = NUMPLAN_NATIONAL;
1638  break;
1639  case 5:/* private */
1640  number_plan = NUMPLAN_PRIVATE;
1641  break;
1642  }
1643 
1644  return number_plan;
1645 }
1646 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1647 
1648 #if defined(AST_MISDN_ENHANCEMENTS)
1649 /*!
1650  * \internal
1651  * \brief Convert mISDN type-of-number to PartyNumber public type-of-number
1652  *
1653  * \param ton mISDN type-of-number
1654  *
1655  * \return PartyNumber public type-of-number
1656  */
1657 static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
1658 {
1659  unsigned party_ton;
1660 
1661  switch (ton) {
1662  default:
1663  case NUMTYPE_UNKNOWN:
1664  party_ton = 0;/* unknown */
1665  break;
1666 
1667  case NUMTYPE_INTERNATIONAL:
1668  party_ton = 1;/* internationalNumber */
1669  break;
1670 
1671  case NUMTYPE_NATIONAL:
1672  party_ton = 2;/* nationalNumber */
1673  break;
1674 
1676  party_ton = 3;/* networkSpecificNumber */
1677  break;
1678 
1679  case NUMTYPE_SUBSCRIBER:
1680  party_ton = 4;/* subscriberNumber */
1681  break;
1682 
1683  case NUMTYPE_ABBREVIATED:
1684  party_ton = 6;/* abbreviatedNumber */
1685  break;
1686  }
1687 
1688  return party_ton;
1689 }
1690 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1691 
1692 #if defined(AST_MISDN_ENHANCEMENTS)
1693 /*!
1694  * \internal
1695  * \brief Convert the PartyNumber public type-of-number to mISDN type-of-number
1696  *
1697  * \param party_ton PartyNumber public type-of-number
1698  *
1699  * \return mISDN type-of-number
1700  */
1701 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
1702 {
1703  enum mISDN_NUMBER_TYPE ton;
1704 
1705  switch (party_ton) {
1706  default:
1707  case 0:/* unknown */
1708  ton = NUMTYPE_UNKNOWN;
1709  break;
1710 
1711  case 1:/* internationalNumber */
1712  ton = NUMTYPE_INTERNATIONAL;
1713  break;
1714 
1715  case 2:/* nationalNumber */
1716  ton = NUMTYPE_NATIONAL;
1717  break;
1718 
1719  case 3:/* networkSpecificNumber */
1721  break;
1722 
1723  case 4:/* subscriberNumber */
1724  ton = NUMTYPE_SUBSCRIBER;
1725  break;
1726 
1727  case 6:/* abbreviatedNumber */
1728  ton = NUMTYPE_ABBREVIATED;
1729  break;
1730  }
1731 
1732  return ton;
1733 }
1734 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1735 
1736 #if defined(AST_MISDN_ENHANCEMENTS)
1737 /*!
1738  * \internal
1739  * \brief Convert mISDN type-of-number to PartyNumber private type-of-number
1740  *
1741  * \param ton mISDN type-of-number
1742  *
1743  * \return PartyNumber private type-of-number
1744  */
1745 static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
1746 {
1747  unsigned party_ton;
1748 
1749  switch (ton) {
1750  default:
1751  case NUMTYPE_UNKNOWN:
1752  party_ton = 0;/* unknown */
1753  break;
1754 
1755  case NUMTYPE_INTERNATIONAL:
1756  party_ton = 1;/* level2RegionalNumber */
1757  break;
1758 
1759  case NUMTYPE_NATIONAL:
1760  party_ton = 2;/* level1RegionalNumber */
1761  break;
1762 
1764  party_ton = 3;/* pTNSpecificNumber */
1765  break;
1766 
1767  case NUMTYPE_SUBSCRIBER:
1768  party_ton = 4;/* localNumber */
1769  break;
1770 
1771  case NUMTYPE_ABBREVIATED:
1772  party_ton = 6;/* abbreviatedNumber */
1773  break;
1774  }
1775 
1776  return party_ton;
1777 }
1778 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1779 
1780 #if defined(AST_MISDN_ENHANCEMENTS)
1781 /*!
1782  * \internal
1783  * \brief Convert the PartyNumber private type-of-number to mISDN type-of-number
1784  *
1785  * \param party_ton PartyNumber private type-of-number
1786  *
1787  * \return mISDN type-of-number
1788  */
1789 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
1790 {
1791  enum mISDN_NUMBER_TYPE ton;
1792 
1793  switch (party_ton) {
1794  default:
1795  case 0:/* unknown */
1796  ton = NUMTYPE_UNKNOWN;
1797  break;
1798 
1799  case 1:/* level2RegionalNumber */
1800  ton = NUMTYPE_INTERNATIONAL;
1801  break;
1802 
1803  case 2:/* level1RegionalNumber */
1804  ton = NUMTYPE_NATIONAL;
1805  break;
1806 
1807  case 3:/* pTNSpecificNumber */
1809  break;
1810 
1811  case 4:/* localNumber */
1812  ton = NUMTYPE_SUBSCRIBER;
1813  break;
1814 
1815  case 6:/* abbreviatedNumber */
1816  ton = NUMTYPE_ABBREVIATED;
1817  break;
1818  }
1819 
1820  return ton;
1821 }
1822 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1823 
1824 /*!
1825  * \internal
1826  * \brief Convert the mISDN type of number code to a string
1827  *
1828  * \param number_type mISDN type of number code.
1829  *
1830  * \return The mISDN type of number code as a string
1831  */
1832 static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
1833 {
1834  const char *str;
1835 
1836  switch (number_type) {
1837  default:
1838  case NUMTYPE_UNKNOWN:
1839  str = "Unknown";
1840  break;
1841 
1842  case NUMTYPE_INTERNATIONAL:
1843  str = "International";
1844  break;
1845 
1846  case NUMTYPE_NATIONAL:
1847  str = "National";
1848  break;
1849 
1851  str = "Network Specific";
1852  break;
1853 
1854  case NUMTYPE_SUBSCRIBER:
1855  str = "Subscriber";
1856  break;
1857 
1858  case NUMTYPE_ABBREVIATED:
1859  str = "Abbreviated";
1860  break;
1861  }
1862 
1863  return str;
1864 }
1865 
1866 /*!
1867  * \internal
1868  * \brief Convert the mISDN type of number code to Asterisk type of number code
1869  *
1870  * \param number_type mISDN type of number code.
1871  *
1872  * \return Asterisk type of number code
1873  */
1874 static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
1875 {
1876  int ast_number_type;
1877 
1878  switch (number_type) {
1879  default:
1880  case NUMTYPE_UNKNOWN:
1881  ast_number_type = NUMTYPE_UNKNOWN << 4;
1882  break;
1883 
1884  case NUMTYPE_INTERNATIONAL:
1885  ast_number_type = NUMTYPE_INTERNATIONAL << 4;
1886  break;
1887 
1888  case NUMTYPE_NATIONAL:
1889  ast_number_type = NUMTYPE_NATIONAL << 4;
1890  break;
1891 
1893  ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
1894  break;
1895 
1896  case NUMTYPE_SUBSCRIBER:
1897  ast_number_type = NUMTYPE_SUBSCRIBER << 4;
1898  break;
1899 
1900  case NUMTYPE_ABBREVIATED:
1901  ast_number_type = NUMTYPE_ABBREVIATED << 4;
1902  break;
1903  }
1904 
1905  return ast_number_type;
1906 }
1907 
1908 /*!
1909  * \internal
1910  * \brief Convert the Asterisk type of number code to mISDN type of number code
1911  *
1912  * \param ast_number_type Asterisk type of number code.
1913  *
1914  * \return mISDN type of number code
1915  */
1916 static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
1917 {
1918  enum mISDN_NUMBER_TYPE number_type;
1919 
1920  switch ((ast_number_type >> 4) & 0x07) {
1921  default:
1922  case NUMTYPE_UNKNOWN:
1923  number_type = NUMTYPE_UNKNOWN;
1924  break;
1925 
1926  case NUMTYPE_INTERNATIONAL:
1927  number_type = NUMTYPE_INTERNATIONAL;
1928  break;
1929 
1930  case NUMTYPE_NATIONAL:
1931  number_type = NUMTYPE_NATIONAL;
1932  break;
1933 
1935  number_type = NUMTYPE_NETWORK_SPECIFIC;
1936  break;
1937 
1938  case NUMTYPE_SUBSCRIBER:
1939  number_type = NUMTYPE_SUBSCRIBER;
1940  break;
1941 
1942  case NUMTYPE_ABBREVIATED:
1943  number_type = NUMTYPE_ABBREVIATED;
1944  break;
1945  }
1946 
1947  return number_type;
1948 }
1949 
1950 /*!
1951  * \internal
1952  * \brief Convert the mISDN numbering plan code to a string
1953  *
1954  * \param number_plan mISDN numbering plan code.
1955  *
1956  * \return The mISDN numbering plan code as a string
1957  */
1958 static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
1959 {
1960  const char *str;
1961 
1962  switch (number_plan) {
1963  default:
1964  case NUMPLAN_UNKNOWN:
1965  str = "Unknown";
1966  break;
1967 
1968  case NUMPLAN_ISDN:
1969  str = "ISDN";
1970  break;
1971 
1972  case NUMPLAN_DATA:
1973  str = "Data";
1974  break;
1975 
1976  case NUMPLAN_TELEX:
1977  str = "Telex";
1978  break;
1979 
1980  case NUMPLAN_NATIONAL:
1981  str = "National";
1982  break;
1983 
1984  case NUMPLAN_PRIVATE:
1985  str = "Private";
1986  break;
1987  }
1988 
1989  return str;
1990 }
1991 
1992 /*!
1993  * \internal
1994  * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
1995  *
1996  * \param number_plan mISDN numbering plan code.
1997  *
1998  * \return Asterisk numbering plan code
1999  */
2000 static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
2001 {
2002  int ast_number_plan;
2003 
2004  switch (number_plan) {
2005  default:
2006  case NUMPLAN_UNKNOWN:
2007  ast_number_plan = NUMPLAN_UNKNOWN;
2008  break;
2009 
2010  case NUMPLAN_ISDN:
2011  ast_number_plan = NUMPLAN_ISDN;
2012  break;
2013 
2014  case NUMPLAN_DATA:
2015  ast_number_plan = NUMPLAN_DATA;
2016  break;
2017 
2018  case NUMPLAN_TELEX:
2019  ast_number_plan = NUMPLAN_TELEX;
2020  break;
2021 
2022  case NUMPLAN_NATIONAL:
2023  ast_number_plan = NUMPLAN_NATIONAL;
2024  break;
2025 
2026  case NUMPLAN_PRIVATE:
2027  ast_number_plan = NUMPLAN_PRIVATE;
2028  break;
2029  }
2030 
2031  return ast_number_plan;
2032 }
2033 
2034 /*!
2035  * \internal
2036  * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
2037  *
2038  * \param ast_number_plan Asterisk numbering plan code.
2039  *
2040  * \return mISDN numbering plan code
2041  */
2042 static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
2043 {
2044  enum mISDN_NUMBER_PLAN number_plan;
2045 
2046  switch (ast_number_plan & 0x0F) {
2047  default:
2048  case NUMPLAN_UNKNOWN:
2049  number_plan = NUMPLAN_UNKNOWN;
2050  break;
2051 
2052  case NUMPLAN_ISDN:
2053  number_plan = NUMPLAN_ISDN;
2054  break;
2055 
2056  case NUMPLAN_DATA:
2057  number_plan = NUMPLAN_DATA;
2058  break;
2059 
2060  case NUMPLAN_TELEX:
2061  number_plan = NUMPLAN_TELEX;
2062  break;
2063 
2064  case NUMPLAN_NATIONAL:
2065  number_plan = NUMPLAN_NATIONAL;
2066  break;
2067 
2068  case NUMPLAN_PRIVATE:
2069  number_plan = NUMPLAN_PRIVATE;
2070  break;
2071  }
2072 
2073  return number_plan;
2074 }
2075 
2076 /*!
2077  * \internal
2078  * \brief Convert the mISDN presentation code to a string
2079  *
2080  * \param presentation mISDN number presentation restriction code.
2081  *
2082  * \return The mISDN presentation code as a string
2083  */
2084 static const char *misdn_to_str_pres(int presentation)
2085 {
2086  const char *str;
2087 
2088  switch (presentation) {
2089  case 0:
2090  str = "Allowed";
2091  break;
2092 
2093  case 1:
2094  str = "Restricted";
2095  break;
2096 
2097  case 2:
2098  str = "Unavailable";
2099  break;
2100 
2101  default:
2102  str = "Unknown";
2103  break;
2104  }
2105 
2106  return str;
2107 }
2108 
2109 /*!
2110  * \internal
2111  * \brief Convert the mISDN presentation code to Asterisk presentation code
2112  *
2113  * \param presentation mISDN number presentation restriction code.
2114  *
2115  * \return Asterisk presentation code
2116  */
2117 static int misdn_to_ast_pres(int presentation)
2118 {
2119  switch (presentation) {
2120  default:
2121  case 0:
2122  presentation = AST_PRES_ALLOWED;
2123  break;
2124 
2125  case 1:
2126  presentation = AST_PRES_RESTRICTED;
2127  break;
2128 
2129  case 2:
2130  presentation = AST_PRES_UNAVAILABLE;
2131  break;
2132  }
2133 
2134  return presentation;
2135 }
2136 
2137 /*!
2138  * \internal
2139  * \brief Convert the Asterisk presentation code to mISDN presentation code
2140  *
2141  * \param presentation Asterisk number presentation restriction code.
2142  *
2143  * \return mISDN presentation code
2144  */
2145 static int ast_to_misdn_pres(int presentation)
2146 {
2147  switch (presentation & AST_PRES_RESTRICTION) {
2148  default:
2149  case AST_PRES_ALLOWED:
2150  presentation = 0;
2151  break;
2152 
2153  case AST_PRES_RESTRICTED:
2154  presentation = 1;
2155  break;
2156 
2157  case AST_PRES_UNAVAILABLE:
2158  presentation = 2;
2159  break;
2160  }
2161 
2162  return presentation;
2163 }
2164 
2165 /*!
2166  * \internal
2167  * \brief Convert the mISDN screening code to a string
2168  *
2169  * \param screening mISDN number screening code.
2170  *
2171  * \return The mISDN screening code as a string
2172  */
2173 static const char *misdn_to_str_screen(int screening)
2174 {
2175  const char *str;
2176 
2177  switch (screening) {
2178  case 0:
2179  str = "Unscreened";
2180  break;
2181 
2182  case 1:
2183  str = "Passed Screen";
2184  break;
2185 
2186  case 2:
2187  str = "Failed Screen";
2188  break;
2189 
2190  case 3:
2191  str = "Network Number";
2192  break;
2193 
2194  default:
2195  str = "Unknown";
2196  break;
2197  }
2198 
2199  return str;
2200 }
2201 
2202 /*!
2203  * \internal
2204  * \brief Convert the mISDN screening code to Asterisk screening code
2205  *
2206  * \param screening mISDN number screening code.
2207  *
2208  * \return Asterisk screening code
2209  */
2210 static int misdn_to_ast_screen(int screening)
2211 {
2212  switch (screening) {
2213  default:
2214  case 0:
2215  screening = AST_PRES_USER_NUMBER_UNSCREENED;
2216  break;
2217 
2218  case 1:
2220  break;
2221 
2222  case 2:
2224  break;
2225 
2226  case 3:
2227  screening = AST_PRES_NETWORK_NUMBER;
2228  break;
2229  }
2230 
2231  return screening;
2232 }
2233 
2234 /*!
2235  * \internal
2236  * \brief Convert the Asterisk screening code to mISDN screening code
2237  *
2238  * \param screening Asterisk number screening code.
2239  *
2240  * \return mISDN screening code
2241  */
2242 static int ast_to_misdn_screen(int screening)
2243 {
2244  switch (screening & AST_PRES_NUMBER_TYPE) {
2245  default:
2247  screening = 0;
2248  break;
2249 
2251  screening = 1;
2252  break;
2253 
2255  screening = 2;
2256  break;
2257 
2259  screening = 3;
2260  break;
2261  }
2262 
2263  return screening;
2264 }
2265 
2266 /*!
2267  * \internal
2268  * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
2269  *
2270  * \param ast Asterisk redirecting reason code.
2271  *
2272  * \return mISDN reason code
2273  */
2275 {
2276  unsigned index;
2277 
2278  static const struct misdn_reasons {
2279  enum AST_REDIRECTING_REASON ast;
2280  enum mISDN_REDIRECTING_REASON q931;
2281  } misdn_reason_table[] = {
2282  /* *INDENT-OFF* */
2286  { AST_REDIRECTING_REASON_UNAVAILABLE, mISDN_REDIRECTING_REASON_NO_REPLY },
2288  { AST_REDIRECTING_REASON_TIME_OF_DAY, mISDN_REDIRECTING_REASON_UNKNOWN },
2289  { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
2291  { AST_REDIRECTING_REASON_FOLLOW_ME, mISDN_REDIRECTING_REASON_UNKNOWN },
2293  { AST_REDIRECTING_REASON_AWAY, mISDN_REDIRECTING_REASON_UNKNOWN },
2295  /* *INDENT-ON* */
2296  };
2297 
2298  for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
2299  if (misdn_reason_table[index].ast == ast) {
2300  return misdn_reason_table[index].q931;
2301  }
2302  }
2304 }
2305 
2306 /*!
2307  * \internal
2308  * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
2309  *
2310  * \param q931 mISDN redirecting reason code.
2311  *
2312  * \return Asterisk redirecting reason code
2313  */
2315 {
2316  enum AST_REDIRECTING_REASON ast;
2317 
2318  switch (q931) {
2319  default:
2322  break;
2323 
2326  break;
2327 
2330  break;
2331 
2334  break;
2335 
2338  break;
2339 
2342  break;
2343 
2346  break;
2347  }
2348 
2349  return ast;
2350 }
2351 
2352 
2353 
2355  char *name; /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
2356  char *display; /*!< Bearer capability displayable name */
2357  int cap; /*!< SETUP message bearer capability field code value */
2358  int deprecated; /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
2359 };
2360 
2361 /* *INDENT-OFF* */
2362 static const struct allowed_bearers allowed_bearers_array[] = {
2363  /* Name, Displayable Name Bearer Capability, Deprecated */
2364  { "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
2365  { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
2366  { "digital_unrestricted", "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
2367  { "digital_restricted", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 0 },
2368  { "digital_restriced", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 1 }, /* Allow misspelling for backwards compatibility */
2369  { "video", "Video", INFO_CAPABILITY_VIDEO, 0 }
2370 };
2371 /* *INDENT-ON* */
2372 
2373 static const char *bearer2str(int cap)
2374 {
2375  unsigned index;
2376 
2377  for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
2378  if (allowed_bearers_array[index].cap == cap) {
2379  return allowed_bearers_array[index].display;
2380  }
2381  }
2382 
2383  return "Unknown Bearer";
2384 }
2385 
2386 #if defined(AST_MISDN_ENHANCEMENTS)
2387 /*!
2388  * \internal
2389  * \brief Fill in facility PartyNumber information
2390  *
2391  * \param party PartyNumber structure to fill in.
2392  * \param id Information to put in PartyNumber structure.
2393  *
2394  * \return Nothing
2395  */
2396 static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
2397 {
2398  ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
2399  party->LengthOfNumber = strlen((char *) party->Number);
2400  party->Type = misdn_to_PartyNumber_plan(id->number_plan);
2401  switch (party->Type) {
2402  case 1:/* public */
2403  party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
2404  break;
2405  case 5:/* private */
2406  party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
2407  break;
2408  default:
2409  party->TypeOfNumber = 0;/* Don't care */
2410  break;
2411  }
2412 }
2413 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2414 
2415 #if defined(AST_MISDN_ENHANCEMENTS)
2416 /*!
2417  * \internal
2418  * \brief Extract the information from PartyNumber
2419  *
2420  * \param id Where to put extracted PartyNumber information
2421  * \param party PartyNumber information to extract
2422  *
2423  * \return Nothing
2424  */
2425 static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
2426 {
2427  if (party->LengthOfNumber) {
2428  ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
2429  id->number_plan = PartyNumber_to_misdn_plan(party->Type);
2430  switch (party->Type) {
2431  case 1:/* public */
2432  id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
2433  break;
2434  case 5:/* private */
2435  id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
2436  break;
2437  default:
2438  id->number_type = NUMTYPE_UNKNOWN;
2439  break;
2440  }
2441  } else {
2442  /* Number not present */
2443  id->number_type = NUMTYPE_UNKNOWN;
2444  id->number_plan = NUMPLAN_ISDN;
2445  id->number[0] = 0;
2446  }
2447 }
2448 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2449 
2450 #if defined(AST_MISDN_ENHANCEMENTS)
2451 /*!
2452  * \internal
2453  * \brief Fill in facility Address information
2454  *
2455  * \param Address Address structure to fill in.
2456  * \param id Information to put in Address structure.
2457  *
2458  * \return Nothing
2459  */
2460 static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
2461 {
2462  misdn_PartyNumber_fill(&Address->Party, id);
2463 
2464  /* Subaddresses are not supported yet */
2465  Address->Subaddress.Length = 0;
2466 }
2467 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2468 
2469 #if defined(AST_MISDN_ENHANCEMENTS)
2470 /*!
2471  * \internal
2472  * \brief Fill in facility PresentedNumberUnscreened information
2473  *
2474  * \param presented PresentedNumberUnscreened structure to fill in.
2475  * \param id Information to put in PresentedNumberUnscreened structure.
2476  *
2477  * \return Nothing
2478  */
2479 static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
2480 {
2481  presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
2482  misdn_PartyNumber_fill(&presented->Unscreened, id);
2483 }
2484 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2485 
2486 #if defined(AST_MISDN_ENHANCEMENTS)
2487 /*!
2488  * \internal
2489  * \brief Extract the information from PartyNumber
2490  *
2491  * \param id Where to put extracted PresentedNumberUnscreened information
2492  * \param presented PresentedNumberUnscreened information to extract
2493  *
2494  * \return Nothing
2495  */
2496 static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
2497 {
2498  id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
2499  id->screening = 0;/* unscreened */
2500  switch (presented->Type) {
2501  case 0:/* presentationAllowedNumber */
2502  case 3:/* presentationRestrictedNumber */
2503  misdn_PartyNumber_extract(id, &presented->Unscreened);
2504  break;
2505  case 1:/* presentationRestricted */
2506  case 2:/* numberNotAvailableDueToInterworking */
2507  default:
2508  /* Number not present (And uninitialized so do not even look at it!) */
2509  id->number_type = NUMTYPE_UNKNOWN;
2510  id->number_plan = NUMPLAN_ISDN;
2511  id->number[0] = 0;
2512  break;
2513  }
2514 }
2515 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2516 
2517 #if defined(AST_MISDN_ENHANCEMENTS)
2518 static const char Level_Spacing[] = " ";/* Work for up to 10 levels */
2519 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2520 
2521 #if defined(AST_MISDN_ENHANCEMENTS)
2522 static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2523 {
2524  if (Party->LengthOfNumber) {
2525  const char *Spacing;
2526 
2527  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2528  chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
2529  Spacing, Party->Type);
2530  switch (Party->Type) {
2531  case 0: /* Unknown PartyNumber */
2532  chan_misdn_log(1, bc->port, " -->%s Unknown: %s\n",
2533  Spacing, Party->Number);
2534  break;
2535  case 1: /* Public PartyNumber */
2536  chan_misdn_log(1, bc->port, " -->%s Public TON:%d %s\n",
2537  Spacing, Party->TypeOfNumber, Party->Number);
2538  break;
2539  case 2: /* NSAP encoded PartyNumber */
2540  chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
2541  Spacing, Party->Number);
2542  break;
2543  case 3: /* Data PartyNumber (Not used) */
2544  chan_misdn_log(1, bc->port, " -->%s Data: %s\n",
2545  Spacing, Party->Number);
2546  break;
2547  case 4: /* Telex PartyNumber (Not used) */
2548  chan_misdn_log(1, bc->port, " -->%s Telex: %s\n",
2549  Spacing, Party->Number);
2550  break;
2551  case 5: /* Private PartyNumber */
2552  chan_misdn_log(1, bc->port, " -->%s Private TON:%d %s\n",
2553  Spacing, Party->TypeOfNumber, Party->Number);
2554  break;
2555  case 8: /* National Standard PartyNumber (Not used) */
2556  chan_misdn_log(1, bc->port, " -->%s National: %s\n",
2557  Spacing, Party->Number);
2558  break;
2559  default:
2560  break;
2561  }
2562  }
2563 }
2564 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2565 
2566 #if defined(AST_MISDN_ENHANCEMENTS)
2567 static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
2568 {
2569  if (Subaddress->Length) {
2570  const char *Spacing;
2571 
2572  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2573  chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
2574  Spacing, Subaddress->Type);
2575  switch (Subaddress->Type) {
2576  case 0: /* UserSpecified */
2577  if (Subaddress->u.UserSpecified.OddCountPresent) {
2578  chan_misdn_log(1, bc->port, " -->%s User BCD OddCount:%d NumOctets:%d\n",
2579  Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
2580  } else {
2581  chan_misdn_log(1, bc->port, " -->%s User: %s\n",
2582  Spacing, Subaddress->u.UserSpecified.Information);
2583  }
2584  break;
2585  case 1: /* NSAP */
2586  chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
2587  Spacing, Subaddress->u.Nsap);
2588  break;
2589  default:
2590  break;
2591  }
2592  }
2593 }
2594 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2595 
2596 #if defined(AST_MISDN_ENHANCEMENTS)
2597 static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
2598 {
2599  print_facility_PartyNumber(Level, &Address->Party, bc);
2600  print_facility_Subaddress(Level, &Address->Subaddress, bc);
2601 }
2602 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2603 
2604 #if defined(AST_MISDN_ENHANCEMENTS)
2605 static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, 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 Unscreened Type:%d\n", Spacing, Presented->Type);
2611  switch (Presented->Type) {
2612  case 0: /* presentationAllowedNumber */
2613  chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
2614  print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2615  break;
2616  case 1: /* presentationRestricted */
2617  chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
2618  break;
2619  case 2: /* numberNotAvailableDueToInterworking */
2620  chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
2621  break;
2622  case 3: /* presentationRestrictedNumber */
2623  chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
2624  print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2625  break;
2626  default:
2627  break;
2628  }
2629 }
2630 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2631 
2632 #if defined(AST_MISDN_ENHANCEMENTS)
2633 static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
2634 {
2635  const char *Spacing;
2636 
2637  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2638  chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
2639  print_facility_PartyNumber(Level, &Address->Party, bc);
2640  print_facility_Subaddress(Level, &Address->Subaddress, bc);
2641 }
2642 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2643 
2644 #if defined(AST_MISDN_ENHANCEMENTS)
2645 static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, 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 Screened Type:%d\n", Spacing, Presented->Type);
2651  switch (Presented->Type) {
2652  case 0: /* presentationAllowedAddress */
2653  chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
2654  print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2655  break;
2656  case 1: /* presentationRestricted */
2657  chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
2658  break;
2659  case 2: /* numberNotAvailableDueToInterworking */
2660  chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
2661  break;
2662  case 3: /* presentationRestrictedAddress */
2663  chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
2664  print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2665  break;
2666  default:
2667  break;
2668  }
2669 }
2670 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2671 
2672 #if defined(AST_MISDN_ENHANCEMENTS)
2673 static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
2674 {
2675  const char *Spacing;
2676 
2677  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2678  chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2679  if (Q931ie->Bc.Length) {
2680  chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2681  }
2682  if (Q931ie->Hlc.Length) {
2683  chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2684  }
2685  if (Q931ie->Llc.Length) {
2686  chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2687  }
2688 }
2689 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2690 
2691 #if defined(AST_MISDN_ENHANCEMENTS)
2692 static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
2693 {
2694  const char *Spacing;
2695 
2696  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2697  chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2698  if (Q931ie->Bc.Length) {
2699  chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2700  }
2701  if (Q931ie->Hlc.Length) {
2702  chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2703  }
2704  if (Q931ie->Llc.Length) {
2705  chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2706  }
2707  if (Q931ie->UserInfo.Length) {
2708  chan_misdn_log(1, bc->port, " -->%s UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
2709  }
2710 }
2711 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2712 
2713 #if defined(AST_MISDN_ENHANCEMENTS)
2714 static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
2715 {
2716  const char *Spacing;
2717 
2718  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2719  chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
2720  Spacing, CallInfo->CCBSReference);
2721  chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
2722  print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
2723  print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
2724  if (CallInfo->SubaddressOfA.Length) {
2725  chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
2726  print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
2727  }
2728 }
2729 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2730 
2731 #if defined(AST_MISDN_ENHANCEMENTS)
2732 static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2733 {
2734  const char *Spacing;
2735 
2736  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2737  if (Party->LengthOfNumber) {
2738  print_facility_PartyNumber(Level, Party, bc);
2739  } else {
2740  chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
2741  }
2742 }
2743 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2744 
2745 #if defined(AST_MISDN_ENHANCEMENTS)
2746 static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
2747 {
2748  const char *Spacing;
2749 
2750  Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2751  chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
2752  Spacing,
2753  ForwardingRecord->Procedure,
2754  ForwardingRecord->BasicService);
2755  chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
2756  print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
2757  chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
2758  print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
2759 }
2760 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2761 
2762 static void print_facility(const struct FacParm *fac, const struct misdn_bchannel *bc)
2763 {
2764 #if defined(AST_MISDN_ENHANCEMENTS)
2765  unsigned Index;
2766 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2767 
2768  switch (fac->Function) {
2769 #if defined(AST_MISDN_ENHANCEMENTS)
2770  case Fac_ActivationDiversion:
2771  chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
2772  fac->u.ActivationDiversion.InvokeID);
2773  switch (fac->u.ActivationDiversion.ComponentType) {
2774  case FacComponent_Invoke:
2775  chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2776  fac->u.ActivationDiversion.Component.Invoke.Procedure,
2777  fac->u.ActivationDiversion.Component.Invoke.BasicService);
2778  chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
2779  print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
2780  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2781  print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
2782  break;
2783  case FacComponent_Result:
2784  chan_misdn_log(1, bc->port, " --> Result\n");
2785  break;
2786  default:
2787  break;
2788  }
2789  break;
2790  case Fac_DeactivationDiversion:
2791  chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
2792  fac->u.DeactivationDiversion.InvokeID);
2793  switch (fac->u.DeactivationDiversion.ComponentType) {
2794  case FacComponent_Invoke:
2795  chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2796  fac->u.DeactivationDiversion.Component.Invoke.Procedure,
2797  fac->u.DeactivationDiversion.Component.Invoke.BasicService);
2798  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2799  print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
2800  break;
2801  case FacComponent_Result:
2802  chan_misdn_log(1, bc->port, " --> Result\n");
2803  break;
2804  default:
2805  break;
2806  }
2807  break;
2808  case Fac_ActivationStatusNotificationDiv:
2809  chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2810  fac->u.ActivationStatusNotificationDiv.InvokeID,
2811  fac->u.ActivationStatusNotificationDiv.Procedure,
2812  fac->u.ActivationStatusNotificationDiv.BasicService);
2813  chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
2814  print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
2815  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2816  print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
2817  break;
2818  case Fac_DeactivationStatusNotificationDiv:
2819  chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2820  fac->u.DeactivationStatusNotificationDiv.InvokeID,
2821  fac->u.DeactivationStatusNotificationDiv.Procedure,
2822  fac->u.DeactivationStatusNotificationDiv.BasicService);
2823  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2824  print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
2825  break;
2826  case Fac_InterrogationDiversion:
2827  chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
2828  fac->u.InterrogationDiversion.InvokeID);
2829  switch (fac->u.InterrogationDiversion.ComponentType) {
2830  case FacComponent_Invoke:
2831  chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2832  fac->u.InterrogationDiversion.Component.Invoke.Procedure,
2833  fac->u.InterrogationDiversion.Component.Invoke.BasicService);
2834  chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2835  print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
2836  break;
2837  case FacComponent_Result:
2838  chan_misdn_log(1, bc->port, " --> Result:\n");
2839  if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
2840  for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
2841  chan_misdn_log(1, bc->port, " --> IntResult[%d]:\n", Index);
2842  print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
2843  }
2844  }
2845  break;
2846  default:
2847  break;
2848  }
2849  break;
2850  case Fac_DiversionInformation:
2851  chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
2852  fac->u.DiversionInformation.InvokeID,
2853  fac->u.DiversionInformation.DiversionReason,
2854  fac->u.DiversionInformation.BasicService);
2855  if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
2856  chan_misdn_log(1, bc->port, " --> ServedUserSubaddress:\n");
2857  print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
2858  }
2859  if (fac->u.DiversionInformation.CallingAddressPresent) {
2860  chan_misdn_log(1, bc->port, " --> CallingAddress:\n");
2861  print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
2862  }
2863  if (fac->u.DiversionInformation.OriginalCalledPresent) {
2864  chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
2865  print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
2866  }
2867  if (fac->u.DiversionInformation.LastDivertingPresent) {
2868  chan_misdn_log(1, bc->port, " --> LastDivertingNr:\n");
2869  print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
2870  }
2871  if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
2872  chan_misdn_log(1, bc->port, " --> LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
2873  }
2874  if (fac->u.DiversionInformation.UserInfo.Length) {
2875  chan_misdn_log(1, bc->port, " --> UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
2876  }
2877  break;
2878  case Fac_CallDeflection:
2879  chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
2880  fac->u.CallDeflection.InvokeID);
2881  switch (fac->u.CallDeflection.ComponentType) {
2882  case FacComponent_Invoke:
2883  chan_misdn_log(1, bc->port, " --> Invoke:\n");
2884  if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
2885  chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
2886  fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
2887  }
2888  chan_misdn_log(1, bc->port, " --> DeflectionAddress:\n");
2889  print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
2890  break;
2891  case FacComponent_Result:
2892  chan_misdn_log(1, bc->port, " --> Result\n");
2893  break;
2894  default:
2895  break;
2896  }
2897  break;
2898  case Fac_CallRerouteing:
2899  chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
2900  fac->u.CallRerouteing.InvokeID);
2901  switch (fac->u.CallRerouteing.ComponentType) {
2902  case FacComponent_Invoke:
2903  chan_misdn_log(1, bc->port, " --> Invoke: Reason:%d Counter:%d\n",
2904  fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
2905  fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
2906  chan_misdn_log(1, bc->port, " --> CalledAddress:\n");
2907  print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
2908  print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
2909  chan_misdn_log(1, bc->port, " --> LastReroutingNr:\n");
2910  print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
2911  chan_misdn_log(1, bc->port, " --> SubscriptionOption:%d\n",
2912  fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
2913  if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
2914  chan_misdn_log(1, bc->port, " --> CallingParty:\n");
2915  print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
2916  }
2917  break;
2918  case FacComponent_Result:
2919  chan_misdn_log(1, bc->port, " --> Result\n");
2920  break;
2921  default:
2922  break;
2923  }
2924  break;
2925  case Fac_InterrogateServedUserNumbers:
2926  chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
2927  fac->u.InterrogateServedUserNumbers.InvokeID);
2928  switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
2929  case FacComponent_Invoke:
2930  chan_misdn_log(1, bc->port, " --> Invoke\n");
2931  break;
2932  case FacComponent_Result:
2933  chan_misdn_log(1, bc->port, " --> Result:\n");
2934  if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
2935  for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
2936  chan_misdn_log(1, bc->port, " --> ServedUserNr[%d]:\n", Index);
2937  print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
2938  }
2939  }
2940  break;
2941  default:
2942  break;
2943  }
2944  break;
2945  case Fac_DivertingLegInformation1:
2946  chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
2947  fac->u.DivertingLegInformation1.InvokeID,
2948  fac->u.DivertingLegInformation1.DiversionReason,
2949  fac->u.DivertingLegInformation1.SubscriptionOption);
2950  if (fac->u.DivertingLegInformation1.DivertedToPresent) {
2951  chan_misdn_log(1, bc->port, " --> DivertedToNr:\n");
2952  print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
2953  }
2954  break;
2955  case Fac_DivertingLegInformation2:
2956  chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
2957  fac->u.DivertingLegInformation2.InvokeID,
2958  fac->u.DivertingLegInformation2.DiversionReason,
2959  fac->u.DivertingLegInformation2.DiversionCounter);
2960  if (fac->u.DivertingLegInformation2.DivertingPresent) {
2961  chan_misdn_log(1, bc->port, " --> DivertingNr:\n");
2962  print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
2963  }
2964  if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
2965  chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
2966  print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
2967  }
2968  break;
2969  case Fac_DivertingLegInformation3:
2970  chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
2971  fac->u.DivertingLegInformation3.InvokeID,
2972  fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
2973  break;
2974 
2975 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
2976 
2977  case Fac_CD:
2978  chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
2979  fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
2980  break;
2981 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
2982  case Fac_AOCDCurrency:
2983  if (fac->u.AOCDcur.chargeNotAvailable) {
2984  chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
2985  } else if (fac->u.AOCDcur.freeOfCharge) {
2986  chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
2987  } else if (fac->u.AOCDchu.billingId >= 0) {
2988  chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
2989  fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2990  (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
2991  } else {
2992  chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
2993  fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2994  (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
2995  }
2996  break;
2997  case Fac_AOCDChargingUnit:
2998  if (fac->u.AOCDchu.chargeNotAvailable) {
2999  chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
3000  } else if (fac->u.AOCDchu.freeOfCharge) {
3001  chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
3002  } else if (fac->u.AOCDchu.billingId >= 0) {
3003  chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
3004  fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
3005  } else {
3006  chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
3007  fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
3008  }
3009  break;
3010 #if defined(AST_MISDN_ENHANCEMENTS)
3011  case Fac_ERROR:
3012  chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
3013  fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
3014  break;
3015  case Fac_RESULT:
3016  chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
3017  fac->u.RESULT.InvokeID);
3018  break;
3019  case Fac_REJECT:
3020  if (fac->u.REJECT.InvokeIDPresent) {
3021  chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
3022  fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
3023  } else {
3024  chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
3025  fac->u.REJECT.Code);
3026  }
3027  break;
3028  case Fac_EctExecute:
3029  chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
3030  fac->u.EctExecute.InvokeID);
3031  break;
3032  case Fac_ExplicitEctExecute:
3033  chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
3034  fac->u.ExplicitEctExecute.InvokeID,
3035  fac->u.ExplicitEctExecute.LinkID);
3036  break;
3037  case Fac_RequestSubaddress:
3038  chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
3039  fac->u.RequestSubaddress.InvokeID);
3040  break;
3041  case Fac_SubaddressTransfer:
3042  chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
3043  fac->u.SubaddressTransfer.InvokeID);
3044  print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
3045  break;
3046  case Fac_EctLinkIdRequest:
3047  chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
3048  fac->u.EctLinkIdRequest.InvokeID);
3049  switch (fac->u.EctLinkIdRequest.ComponentType) {
3050  case FacComponent_Invoke:
3051  chan_misdn_log(1, bc->port, " --> Invoke\n");
3052  break;
3053  case FacComponent_Result:
3054  chan_misdn_log(1, bc->port, " --> Result: LinkID:%d\n",
3055  fac->u.EctLinkIdRequest.Component.Result.LinkID);
3056  break;
3057  default:
3058  break;
3059  }
3060  break;
3061  case Fac_EctInform:
3062  chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
3063  fac->u.EctInform.InvokeID,
3064  fac->u.EctInform.Status);
3065  if (fac->u.EctInform.RedirectionPresent) {
3066  chan_misdn_log(1, bc->port, " --> Redirection Number\n");
3067  print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
3068  }
3069  break;
3070  case Fac_EctLoopTest:
3071  chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
3072  fac->u.EctLoopTest.InvokeID);
3073  switch (fac->u.EctLoopTest.ComponentType) {
3074  case FacComponent_Invoke:
3075  chan_misdn_log(1, bc->port, " --> Invoke: CallTransferID:%d\n",
3076  fac->u.EctLoopTest.Component.Invoke.CallTransferID);
3077  break;
3078  case FacComponent_Result:
3079  chan_misdn_log(1, bc->port, " --> Result: LoopResult:%d\n",
3080  fac->u.EctLoopTest.Component.Result.LoopResult);
3081  break;
3082  default:
3083  break;
3084  }
3085  break;
3086  case Fac_StatusRequest:
3087  chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
3088  fac->u.StatusRequest.InvokeID);
3089  switch (fac->u.StatusRequest.ComponentType) {
3090  case FacComponent_Invoke:
3091  chan_misdn_log(1, bc->port, " --> Invoke: Compatibility:%d\n",
3092  fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
3093  break;
3094  case FacComponent_Result:
3095  chan_misdn_log(1, bc->port, " --> Result: Status:%d\n",
3096  fac->u.StatusRequest.Component.Result.Status);
3097  break;
3098  default:
3099  break;
3100  }
3101  break;
3102  case Fac_CallInfoRetain:
3103  chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
3104  fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
3105  break;
3106  case Fac_CCBSDeactivate:
3107  chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
3108  fac->u.CCBSDeactivate.InvokeID);
3109  switch (fac->u.CCBSDeactivate.ComponentType) {
3110  case FacComponent_Invoke:
3111  chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d\n",
3112  fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
3113  break;
3114  case FacComponent_Result:
3115  chan_misdn_log(1, bc->port, " --> Result\n");
3116  break;
3117  default:
3118  break;
3119  }
3120  break;
3121  case Fac_CCBSErase:
3122  chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
3123  fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
3124  fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
3125  chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3126  print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
3127  print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
3128  break;
3129  case Fac_CCBSRemoteUserFree:
3130  chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3131  fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
3132  fac->u.CCBSRemoteUserFree.RecallMode);
3133  chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3134  print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
3135  print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
3136  break;
3137  case Fac_CCBSCall:
3138  chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
3139  fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
3140  break;
3141  case Fac_CCBSStatusRequest:
3142  chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
3143  fac->u.CCBSStatusRequest.InvokeID);
3144  switch (fac->u.CCBSStatusRequest.ComponentType) {
3145  case FacComponent_Invoke:
3146  chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d RecallMode:%d\n",
3147  fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
3148  fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
3149  print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
3150  break;
3151  case FacComponent_Result:
3152  chan_misdn_log(1, bc->port, " --> Result: Free:%d\n",
3153  fac->u.CCBSStatusRequest.Component.Result.Free);
3154  break;
3155  default:
3156  break;
3157  }
3158  break;
3159  case Fac_CCBSBFree:
3160  chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3161  fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
3162  fac->u.CCBSBFree.RecallMode);
3163  chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3164  print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
3165  print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
3166  break;
3167  case Fac_EraseCallLinkageID:
3168  chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
3169  fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
3170  break;
3171  case Fac_CCBSStopAlerting:
3172  chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
3173  fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
3174  break;
3175  case Fac_CCBSRequest:
3176  chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
3177  fac->u.CCBSRequest.InvokeID);
3178  switch (fac->u.CCBSRequest.ComponentType) {
3179  case FacComponent_Invoke:
3180  chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
3181  fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
3182  break;
3183  case FacComponent_Result:
3184  chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
3185  fac->u.CCBSRequest.Component.Result.CCBSReference,
3186  fac->u.CCBSRequest.Component.Result.RecallMode);
3187  break;
3188  default:
3189  break;
3190  }
3191  break;
3192  case Fac_CCBSInterrogate:
3193  chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
3194  fac->u.CCBSInterrogate.InvokeID);
3195  switch (fac->u.CCBSInterrogate.ComponentType) {
3196  case FacComponent_Invoke:
3197  chan_misdn_log(1, bc->port, " --> Invoke\n");
3198  if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
3199  chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
3200  fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
3201  }
3202  if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3203  chan_misdn_log(1, bc->port, " --> AParty\n");
3204  print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
3205  }
3206  break;
3207  case FacComponent_Result:
3208  chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
3209  fac->u.CCBSInterrogate.Component.Result.RecallMode);
3210  if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
3211  for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
3212  chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
3213  print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
3214  }
3215  }
3216  break;
3217  default:
3218  break;
3219  }
3220  break;
3221  case Fac_CCNRRequest:
3222  chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
3223  fac->u.CCNRRequest.InvokeID);
3224  switch (fac->u.CCNRRequest.ComponentType) {
3225  case FacComponent_Invoke:
3226  chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
3227  fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
3228  break;
3229  case FacComponent_Result:
3230  chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
3231  fac->u.CCNRRequest.Component.Result.CCBSReference,
3232  fac->u.CCNRRequest.Component.Result.RecallMode);
3233  break;
3234  default:
3235  break;
3236  }
3237  break;
3238  case Fac_CCNRInterrogate:
3239  chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
3240  fac->u.CCNRInterrogate.InvokeID);
3241  switch (fac->u.CCNRInterrogate.ComponentType) {
3242  case FacComponent_Invoke:
3243  chan_misdn_log(1, bc->port, " --> Invoke\n");
3244  if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
3245  chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
3246  fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
3247  }
3248  if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3249  chan_misdn_log(1, bc->port, " --> AParty\n");
3250  print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
3251  }
3252  break;
3253  case FacComponent_Result:
3254  chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
3255  fac->u.CCNRInterrogate.Component.Result.RecallMode);
3256  if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
3257  for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
3258  chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
3259  print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
3260  }
3261  }
3262  break;
3263  default:
3264  break;
3265  }
3266  break;
3267  case Fac_CCBS_T_Call:
3268  chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
3269  fac->u.CCBS_T_Call.InvokeID);
3270  break;
3271  case Fac_CCBS_T_Suspend:
3272  chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
3273  fac->u.CCBS_T_Suspend.InvokeID);
3274  break;
3275  case Fac_CCBS_T_Resume:
3276  chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
3277  fac->u.CCBS_T_Resume.InvokeID);
3278  break;
3279  case Fac_CCBS_T_RemoteUserFree:
3280  chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
3281  fac->u.CCBS_T_RemoteUserFree.InvokeID);
3282  break;
3283  case Fac_CCBS_T_Available:
3284  chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
3285  fac->u.CCBS_T_Available.InvokeID);
3286  break;
3287  case Fac_CCBS_T_Request:
3288  chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
3289  fac->u.CCBS_T_Request.InvokeID);
3290  switch (fac->u.CCBS_T_Request.ComponentType) {
3291  case FacComponent_Invoke:
3292  chan_misdn_log(1, bc->port, " --> Invoke\n");
3293  chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
3294  print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
3295  print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
3296  if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
3297  chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
3298  }
3299  if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
3300  chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
3301  fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);
3302  }
3303  if (fac->u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
3304  chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
3305  print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Originating, bc);
3306  }
3307  break;
3308  case FacComponent_Result:
3309  chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
3310  fac->u.CCBS_T_Request.Component.Result.RetentionSupported);
3311  break;
3312  default:
3313  break;
3314  }
3315  break;
3316  case Fac_CCNR_T_Request:
3317  chan_misdn_log(1, bc->port, " --> CCNR_T_Request: InvokeID:%d\n",
3318  fac->u.CCNR_T_Request.InvokeID);
3319  switch (fac->u.CCNR_T_Request.ComponentType) {
3320  case FacComponent_Invoke:
3321  chan_misdn_log(1, bc->port, " --> Invoke\n");
3322  chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
3323  print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Destination, bc);
3324  print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCNR_T_Request.Component.Invoke.Q931ie, bc);
3325  if (fac->u.CCNR_T_Request.Component.Invoke.RetentionSupported) {
3326  chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
3327  }
3328  if (fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
3329  chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
3330  fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicator);
3331  }
3332  if (fac->u.CCNR_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
3333  chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
3334  print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Originating, bc);
3335  }
3336  break;
3337  case FacComponent_Result:
3338  chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
3339  fac->u.CCNR_T_Request.Component.Result.RetentionSupported);
3340  break;
3341  default:
3342  break;
3343  }
3344  break;
3345 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
3346  case Fac_None:
3347  /* No facility so print nothing */
3348  break;
3349  default:
3350  chan_misdn_log(1, bc->port, " --> unknown facility\n");
3351  break;
3352  }
3353 }
3354 
3355 static void print_bearer(struct misdn_bchannel *bc)
3356 {
3357  chan_misdn_log(2, bc->port, " --> Bearer: %s\n", bearer2str(bc->capability));
3358 
3359  switch(bc->law) {
3360  case INFO_CODEC_ALAW:
3361  chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
3362  break;
3363  case INFO_CODEC_ULAW:
3364  chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
3365  break;
3366  }
3367 }
3368 
3369 /*!
3370  * \internal
3371  * \brief Prefix a string to another string in place.
3372  *
3373  * \param str_prefix String to prefix to the main string.
3374  * \param str_main String to get the prefix added to it.
3375  * \param size Buffer size of the main string (Includes null terminator).
3376  *
3377  * \note The str_main buffer size must be greater than one.
3378  *
3379  * \return Nothing
3380  */
3381 static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
3382 {
3383  size_t len_over;
3384  size_t len_total;
3385  size_t len_main;
3386  size_t len_prefix;
3387 
3388  len_prefix = strlen(str_prefix);
3389  if (!len_prefix) {
3390  /* There is no prefix to prepend. */
3391  return;
3392  }
3393  len_main = strlen(str_main);
3394  len_total = len_prefix + len_main;
3395  if (size <= len_total) {
3396  /* We need to truncate since the buffer is too small. */
3397  len_over = len_total + 1 - size;
3398  if (len_over <= len_main) {
3399  len_main -= len_over;
3400  } else {
3401  len_over -= len_main;
3402  len_main = 0;
3403  len_prefix -= len_over;
3404  }
3405  }
3406  if (len_main) {
3407  memmove(str_main + len_prefix, str_main, len_main);
3408  }
3409  memcpy(str_main, str_prefix, len_prefix);
3410  str_main[len_prefix + len_main] = '\0';
3411 }
3412 
3413 /*!
3414  * \internal
3415  * \brief Add a configured prefix to the given number.
3416  *
3417  * \param port Logical port number
3418  * \param number_type Type-of-number passed in.
3419  * \param number Given number string to add prefix
3420  * \param size Buffer size number string occupies.
3421  *
3422  * \return Nothing
3423  */
3424 static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
3425 {
3426  enum misdn_cfg_elements type_prefix;
3427  char num_prefix[MISDN_MAX_NUMBER_LEN];
3428 
3429  /* Get prefix string. */
3430  switch (number_type) {
3431  case NUMTYPE_UNKNOWN:
3432  type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
3433  break;
3434  case NUMTYPE_INTERNATIONAL:
3435  type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
3436  break;
3437  case NUMTYPE_NATIONAL:
3438  type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
3439  break;
3442  break;
3443  case NUMTYPE_SUBSCRIBER:
3444  type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
3445  break;
3446  case NUMTYPE_ABBREVIATED:
3447  type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
3448  break;
3449  default:
3450  /* Type-of-number does not have a prefix that can be added. */
3451  return;
3452  }
3453  misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
3454 
3455  misdn_prefix_string(num_prefix, number, size);
3456 }
3457 
3458 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
3459 {
3460  RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
3461  char buf[128];
3462 
3463  if (!bc->AOCD_need_export || !ast) {
3464  return;
3465  }
3466 
3467  if (originator == ORG_AST) {
3468  chan = ast_channel_bridge_peer(ast);
3469  if (!chan) {
3470  return;
3471  }
3472  } else {
3473  chan = ast_channel_ref(ast);
3474  }
3475 
3476  switch (bc->AOCDtype) {
3477  case Fac_AOCDCurrency:
3478  pbx_builtin_setvar_helper(chan, "AOCD_Type", "currency");
3479  if (bc->AOCD.currency.chargeNotAvailable) {
3480  pbx_builtin_setvar_helper(chan, "AOCD_ChargeAvailable", "no");
3481  } else {
3482  pbx_builtin_setvar_helper(chan, "AOCD_ChargeAvailable", "yes");
3483  if (bc->AOCD.currency.freeOfCharge) {
3484  pbx_builtin_setvar_helper(chan, "AOCD_FreeOfCharge", "yes");
3485  } else {
3486  pbx_builtin_setvar_helper(chan, "AOCD_FreeOfCharge", "no");
3487  if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
3488  pbx_builtin_setvar_helper(chan, "AOCD_Amount", buf);
3489  if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf)) {
3490  pbx_builtin_setvar_helper(chan, "AOCD_BillingId", buf);
3491  }
3492  }
3493  }
3494  }
3495  break;
3496  case Fac_AOCDChargingUnit:
3497  pbx_builtin_setvar_helper(chan, "AOCD_Type", "charging_unit");
3498  if (bc->AOCD.chargingUnit.chargeNotAvailable) {
3499  pbx_builtin_setvar_helper(chan, "AOCD_ChargeAvailable", "no");
3500  } else {
3501  pbx_builtin_setvar_helper(chan, "AOCD_ChargeAvailable", "yes");
3502  if (bc->AOCD.chargingUnit.freeOfCharge) {
3503  pbx_builtin_setvar_helper(chan, "AOCD_FreeOfCharge", "yes");
3504  } else {
3505  pbx_builtin_setvar_helper(chan, "AOCD_FreeOfCharge", "no");
3506  if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
3507  pbx_builtin_setvar_helper(chan, "AOCD_RecordedUnits", buf);
3508  if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf)) {
3509  pbx_builtin_setvar_helper(chan, "AOCD_BillingId", buf);
3510  }
3511  }
3512  }
3513  }
3514  break;
3515  default:
3516  break;
3517  }
3518 
3519  bc->AOCD_need_export = 0;
3520 }
3521 
3522 /*************** Helpers END *************/
3523 
3524 static void sighandler(int sig)
3525 {
3526 }
3527 
3528 static void *misdn_tasks_thread_func(void *data)
3529 {
3530  int wait;
3531  struct sigaction sa;
3532 
3533  sa.sa_handler = sighandler;
3534  sa.sa_flags = SA_NODEFER;
3535  sigemptyset(&sa.sa_mask);
3536  sigaddset(&sa.sa_mask, SIGUSR1);
3537  sigaction(SIGUSR1, &sa, NULL);
3538 
3539  sem_post((sem_t *)data);
3540 
3541  while (1) {
3542  wait = ast_sched_wait(misdn_tasks);
3543  if (wait < 0) {
3544  wait = 8000;
3545  }
3546  if (poll(NULL, 0, wait) < 0) {
3547  chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
3548  }
3549  ast_sched_runq(misdn_tasks);
3550  }
3551  return NULL;
3552 }
3553 
3554 static void misdn_tasks_init(void)
3555 {
3556  sem_t blocker;
3557  int i = 5;
3558 
3559  if (sem_init(&blocker, 0, 0)) {
3560  perror("chan_misdn: Failed to initialize semaphore!");
3561  exit(1);
3562  }
3563 
3564  chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
3565 
3566  misdn_tasks = ast_sched_context_create();
3568 
3569  while (sem_wait(&blocker) && --i) {
3570  }
3571  sem_destroy(&blocker);
3572 }
3573 
3574 static void misdn_tasks_destroy(void)
3575 {
3576  if (misdn_tasks) {
3577  chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
3578  if (pthread_cancel(misdn_tasks_thread) == 0) {
3579  cb_log(4, 0, "Joining misdn_tasks thread\n");
3580  pthread_join(misdn_tasks_thread, NULL);
3581  }
3582  ast_sched_context_destroy(misdn_tasks);
3583  }
3584 }
3585 
3586 static inline void misdn_tasks_wakeup(void)
3587 {
3588  pthread_kill(misdn_tasks_thread, SIGUSR1);
3589 }
3590 
3591 static inline int _misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data, int variable)
3592 {
3593  int task_id;
3594 
3595  if (!misdn_tasks) {
3596  misdn_tasks_init();
3597  }
3598  task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
3600 
3601  return task_id;
3602 }
3603 
3604 static int misdn_tasks_add(int timeout, ast_sched_cb callback, const void *data)
3605 {
3606  return _misdn_tasks_add_variable(timeout, callback, data, 0);
3607 }
3608 
3609 static int misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data)
3610 {
3611  return _misdn_tasks_add_variable(timeout, callback, data, 1);
3612 }
3613 
3614 static void misdn_tasks_remove(int task_id)
3615 {
3616  AST_SCHED_DEL(misdn_tasks, task_id);
3617 }
3618 
3619 static int misdn_l1_task(const void *vdata)
3620 {
3621  const int *data = vdata;
3622 
3623  misdn_lib_isdn_l1watcher(*data);
3624  chan_misdn_log(5, *data, "L1watcher timeout\n");
3625  return 1;
3626 }
3627 
3628 static int misdn_overlap_dial_task(const void *data)
3629 {
3630  struct timeval tv_end, tv_now;
3631  int diff;
3632  struct chan_list *ch = (struct chan_list *) data;
3633  char *dad;
3634 
3635  chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
3636 
3637  if (ch->state != MISDN_WAITING4DIGS) {
3638  ch->overlap_dial_task = -1;
3639  return 0;
3640  }
3641 
3643  tv_end = ch->overlap_tv;
3645 
3646  tv_end.tv_sec += ch->overlap_dial;
3647  tv_now = ast_tvnow();
3648 
3649  diff = ast_tvdiff_ms(tv_end, tv_now);
3650  if (100 < diff) {
3651  return diff;
3652  }
3653 
3654  /* if we are 100ms near the timeout, we are satisfied.. */
3655  stop_indicate(ch);
3656 
3657  if (ast_strlen_zero(ch->bc->dialed.number)) {
3658  dad = "s";
3659  ast_channel_exten_set(ch->ast, dad);
3660  } else {
3661  dad = ch->bc->dialed.number;
3662  }
3663 
3664  if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
3665  ch->state = MISDN_DIALING;
3666  if (pbx_start_chan(ch) < 0) {
3667  chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
3668  goto misdn_overlap_dial_task_disconnect;
3669  }
3670  } else {
3671 misdn_overlap_dial_task_disconnect:
3672  hanguptone_indicate(ch);
3674  ch->state = MISDN_CLEANING;
3676  }
3677  ch->overlap_dial_task = -1;
3678  return 0;
3679 }
3680 
3681 static void send_digit_to_chan(struct chan_list *cl, char digit)
3682 {
3683  static const char * const dtmf_tones[] = {
3684 /* *INDENT-OFF* */
3685  "!941+1336/100,!0/100", /* 0 */
3686  "!697+1209/100,!0/100", /* 1 */
3687  "!697+1336/100,!0/100", /* 2 */
3688  "!697+1477/100,!0/100", /* 3 */
3689  "!770+1209/100,!0/100", /* 4 */
3690  "!770+1336/100,!0/100", /* 5 */
3691  "!770+1477/100,!0/100", /* 6 */
3692  "!852+1209/100,!0/100", /* 7 */
3693  "!852+1336/100,!0/100", /* 8 */
3694  "!852+1477/100,!0/100", /* 9 */
3695  "!697+1633/100,!0/100", /* A */
3696  "!770+1633/100,!0/100", /* B */
3697  "!852+1633/100,!0/100", /* C */
3698  "!941+1633/100,!0/100", /* D */
3699  "!941+1209/100,!0/100", /* * */
3700  "!941+1477/100,!0/100", /* # */
3701 /* *INDENT-ON* */
3702  };
3703  struct ast_channel *chan = cl->ast;
3704 
3705  if (digit >= '0' && digit <='9') {
3706  ast_playtones_start(chan, 0, dtmf_tones[digit - '0'], 0);
3707  } else if (digit >= 'A' && digit <= 'D') {
3708  ast_playtones_start(chan, 0, dtmf_tones[digit - 'A' + 10], 0);
3709  } else if (digit == '*') {
3710  ast_playtones_start(chan, 0, dtmf_tones[14], 0);
3711  } else if (digit == '#') {
3712  ast_playtones_start(chan, 0, dtmf_tones[15], 0);
3713  } else {
3714  /* not handled */
3715  ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, ast_channel_name(chan));
3716  }
3717 }
3718 
3719 /*** CLI HANDLING ***/
3720 static char *handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3721 {
3722  int level;
3723 
3724  switch (cmd) {
3725  case CLI_INIT:
3726  e->command = "misdn set debug [on|off]";
3727  e->usage =
3728  "Usage: misdn set debug {on|off|<level>} [only] | [port <port> [only]]\n"
3729  " Set the debug level of the mISDN channel.\n";
3730  return NULL;
3731  case CLI_GENERATE:
3732  return complete_debug_port(a);
3733  }
3734 
3735  if (a->argc < 4 || a->argc > 7) {
3736  return CLI_SHOWUSAGE;
3737  }
3738 
3739  if (!strcasecmp(a->argv[3], "on")) {
3740  level = 1;
3741  } else if (!strcasecmp(a->argv[3], "off")) {
3742  level = 0;
3743  } else if (isdigit(a->argv[3][0])) {
3744  level = atoi(a->argv[3]);
3745  } else {
3746  return CLI_SHOWUSAGE;
3747  }
3748 
3749  switch (a->argc) {
3750  case 4:
3751  case 5:
3752  {
3753  int i;
3754  int only = 0;
3755  if (a->argc == 5) {
3756  if (strncasecmp(a->argv[4], "only", strlen(a->argv[4]))) {
3757  return CLI_SHOWUSAGE;
3758  } else {
3759  only = 1;
3760  }
3761  }
3762 
3763  for (i = 0; i <= max_ports; i++) {
3764  misdn_debug[i] = level;
3765  misdn_debug_only[i] = only;
3766  }
3767  ast_cli(a->fd, "changing debug level for all ports to %d%s\n", misdn_debug[0], only ? " (only)" : "");
3768  }
3769  break;
3770  case 6:
3771  case 7:
3772  {
3773  int port;
3774  if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
3775  return CLI_SHOWUSAGE;
3776  port = atoi(a->argv[5]);
3777  if (port <= 0 || port > max_ports) {
3778  switch (max_ports) {
3779  case 0:
3780  ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
3781  break;
3782  case 1:
3783  ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
3784  break;
3785  default:
3786  ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
3787  }
3788  return 0;
3789  }
3790  if (a->argc == 7) {
3791  if (strncasecmp(a->argv[6], "only", strlen(a->argv[6]))) {
3792  return CLI_SHOWUSAGE;
3793  } else {
3794  misdn_debug_only[port] = 1;
3795  }
3796  } else {
3797  misdn_debug_only[port] = 0;
3798  }
3799  misdn_debug[port] = level;
3800  ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port] ? " (only)" : "", port);
3801  }
3802  }
3803 
3804  return CLI_SUCCESS;
3805 }
3806 
3807 static char *handle_cli_misdn_set_crypt_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3808 {
3809  switch (cmd) {
3810  case CLI_INIT:
3811  e->command = "misdn set crypt debug";
3812  e->usage =
3813  "Usage: misdn set crypt debug <level>\n"
3814  " Set the crypt debug level of the mISDN channel. Level\n"
3815  " must be 1 or 2.\n";
3816  return NULL;
3817  case CLI_GENERATE:
3818  return NULL;
3819  }
3820 
3821  if (a->argc != 5) {
3822  return CLI_SHOWUSAGE;
3823  }
3824 
3825  /* XXX Is this supposed to not do anything? XXX */
3826 
3827  return CLI_SUCCESS;
3828 }
3829 
3830 static char *handle_cli_misdn_port_block(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3831 {
3832  switch (cmd) {
3833  case CLI_INIT:
3834  e->command = "misdn port block";
3835  e->usage =
3836  "Usage: misdn port block <port>\n"
3837  " Block the specified port by <port>.\n";
3838  return NULL;
3839  case CLI_GENERATE:
3840  return NULL;
3841  }
3842 
3843  if (a->argc != 4) {
3844  return CLI_SHOWUSAGE;
3845  }
3846 
3847  misdn_lib_port_block(atoi(a->argv[3]));
3848 
3849  return CLI_SUCCESS;
3850 }
3851 
3852 static char *handle_cli_misdn_port_unblock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3853 {
3854  switch (cmd) {
3855  case CLI_INIT:
3856  e->command = "misdn port unblock";
3857  e->usage =
3858  "Usage: misdn port unblock <port>\n"
3859  " Unblock the port specified by <port>.\n";
3860  return NULL;
3861  case CLI_GENERATE:
3862  return NULL;
3863  }
3864 
3865  if (a->argc != 4) {
3866  return CLI_SHOWUSAGE;
3867  }
3868 
3869  misdn_lib_port_unblock(atoi(a->argv[3]));
3870 
3871  return CLI_SUCCESS;
3872 }
3873 
3874 static char *handle_cli_misdn_restart_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3875 {
3876  switch (cmd) {
3877  case CLI_INIT:
3878  e->command = "misdn restart port";
3879  e->usage =
3880  "Usage: misdn restart port <port>\n"
3881  " Restart the given port.\n";
3882  return NULL;
3883  case CLI_GENERATE:
3884  return NULL;
3885  }
3886 
3887  if (a->argc != 4) {
3888  return CLI_SHOWUSAGE;
3889  }
3890 
3891  misdn_lib_port_restart(atoi(a->argv[3]));
3892 
3893  return CLI_SUCCESS;
3894 }
3895 
3896 static char *handle_cli_misdn_restart_pid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3897 {
3898  switch (cmd) {
3899  case CLI_INIT:
3900  e->command = "misdn restart pid";
3901  e->usage =
3902  "Usage: misdn restart pid <pid>\n"
3903  " Restart the given pid\n";
3904  return NULL;
3905  case CLI_GENERATE:
3906  return NULL;
3907  }
3908 
3909  if (a->argc != 4) {
3910  return CLI_SHOWUSAGE;
3911  }
3912 
3913  misdn_lib_pid_restart(atoi(a->argv[3]));
3914 
3915  return CLI_SUCCESS;
3916 }
3917 
3918 static char *handle_cli_misdn_port_up(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3919 {
3920  switch (cmd) {
3921  case CLI_INIT:
3922  e->command = "misdn port up";
3923  e->usage =
3924  "Usage: misdn port up <port>\n"
3925  " Try to establish L1 on the given port.\n";
3926  return NULL;
3927  case CLI_GENERATE:
3928  return NULL;
3929  }
3930 
3931  if (a->argc != 4) {
3932  return CLI_SHOWUSAGE;
3933  }
3934 
3935  misdn_lib_get_port_up(atoi(a->argv[3]));
3936 
3937  return CLI_SUCCESS;
3938 }
3939 
3940 static char *handle_cli_misdn_port_down(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3941 {
3942  switch (cmd) {
3943  case CLI_INIT:
3944  e->command = "misdn port down";
3945  e->usage =
3946  "Usage: misdn port down <port>\n"
3947  " Try to deactivate the L1 on the given port.\n";
3948  return NULL;
3949  case CLI_GENERATE:
3950  return NULL;
3951  }
3952 
3953  if (a->argc != 4) {
3954  return CLI_SHOWUSAGE;
3955  }
3956 
3957  misdn_lib_get_port_down(atoi(a->argv[3]));
3958 
3959  return CLI_SUCCESS;
3960 }
3961 
3962 static inline void show_config_description(int fd, enum misdn_cfg_elements elem)
3963 {
3964  char section[BUFFERSIZE];
3965  char name[BUFFERSIZE];
3966  char desc[BUFFERSIZE];
3967  char def[BUFFERSIZE];
3968  char tmp[BUFFERSIZE];
3969 
3970  misdn_cfg_get_name(elem, tmp, sizeof(tmp));
3971  term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
3972  misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
3973 
3974  if (elem < MISDN_CFG_LAST) {
3975  term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
3976  } else {
3977  term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
3978  }
3979 
3980  if (*def) {
3981  ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc);
3982  } else {
3983  ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
3984  }
3985 }
3986 
3987 static char *handle_cli_misdn_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3988 {
3989  char buffer[BUFFERSIZE];
3990  enum misdn_cfg_elements elem;
3991  int linebreak;
3992  int onlyport = -1;
3993  int ok = 0;
3994 
3995  switch (cmd) {
3996  case CLI_INIT:
3997  e->command = "misdn show config";
3998  e->usage =
3999  "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
4000  " Use 0 for <port> to only print the general config.\n";
4001  return NULL;
4002  case CLI_GENERATE:
4003  return complete_show_config(a);
4004  }
4005 
4006  if (a->argc >= 4) {
4007  if (!strcmp(a->argv[3], "description")) {
4008  if (a->argc == 5) {
4009  enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
4010  if (elem == MISDN_CFG_FIRST) {
4011  ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
4012  } else {
4013  show_config_description(a->fd, elem);
4014  }
4015  return CLI_SUCCESS;
4016  }
4017  return CLI_SHOWUSAGE;
4018  } else if (!strcmp(a->argv[3], "descriptions")) {
4019  if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
4020  for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
4021  show_config_description(a->fd, elem);
4022  ast_cli(a->fd, "\n");
4023  }
4024  ok = 1;
4025  }
4026  if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
4027  for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
4028  show_config_description(a->fd, elem);
4029  ast_cli(a->fd, "\n");
4030  }
4031  ok = 1;
4032  }
4033  return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
4034  } else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
4035  ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
4036  return CLI_SHOWUSAGE;
4037  }
4038  }
4039 
4040  if (a->argc == 3 || onlyport == 0) {
4041  ast_cli(a->fd, "mISDN General-Config:\n");
4042  for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
4043  misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
4044  ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
4045  }
4046  ast_cli(a->fd, "\n");
4047  }
4048 
4049  if (onlyport < 0) {
4050  int port = misdn_cfg_get_next_port(0);
4051 
4052  for (; port > 0; port = misdn_cfg_get_next_port(port)) {
4053  ast_cli(a->fd, "\n[PORT %d]\n", port);
4054  for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
4055  misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
4056  ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
4057  }
4058  ast_cli(a->fd, "\n");
4059  }
4060  }
4061 
4062  if (onlyport > 0) {
4063  if (misdn_cfg_is_port_valid(onlyport)) {
4064  ast_cli(a->fd, "[PORT %d]\n", onlyport);
4065  for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
4066  misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
4067  ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
4068  }
4069  ast_cli(a->fd, "\n");
4070  } else {
4071  ast_cli(a->fd, "Port %d is not active!\n", onlyport);
4072  }
4073  }
4074 
4075  return CLI_SUCCESS;
4076 }
4077 
4080  char txt[255];
4081 };
4082 
4083 static const struct state_struct state_array[] = {
4084 /* *INDENT-OFF* */
4085  { MISDN_NOTHING, "NOTHING" }, /* at beginning */
4086  { MISDN_WAITING4DIGS, "WAITING4DIGS" }, /* when waiting for infos */
4087  { MISDN_EXTCANTMATCH, "EXTCANTMATCH" }, /* when asterisk couldn't match our ext */
4088  { MISDN_INCOMING_SETUP, "INCOMING SETUP" }, /* when pbx_start */
4089  { MISDN_DIALING, "DIALING" }, /* when pbx_start */
4090  { MISDN_PROGRESS, "PROGRESS" }, /* when pbx_start */
4091  { MISDN_PROCEEDING, "PROCEEDING" }, /* when pbx_start */
4092  { MISDN_CALLING, "CALLING" }, /* when misdn_call is called */
4093  { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" }, /* when misdn_call is called */
4094  { MISDN_ALERTING, "ALERTING" }, /* when Alerting */
4095  { MISDN_BUSY, "BUSY" }, /* when BUSY */
4096  { MISDN_CONNECTED, "CONNECTED" }, /* when connected */
4097  { MISDN_DISCONNECTED, "DISCONNECTED" }, /* when connected */
4098  { MISDN_CLEANING, "CLEANING" }, /* when hangup from * but we were connected before */
4099 /* *INDENT-ON* */
4100 };
4101 
4102 static const char *misdn_get_ch_state(struct chan_list *p)
4103 {
4104  int i;
4105  static char state[8];
4106 
4107  if (!p) {
4108  return NULL;
4109  }
4110 
4111  for (i = 0; i < ARRAY_LEN(state_array); i++) {
4112  if (state_array[i].state == p->state) {
4113  return state_array[i].txt;
4114  }
4115  }
4116 
4117  snprintf(state, sizeof(state), "%d", p->state) ;
4118 
4119  return state;
4120 }
4121 
4122 
4123 static void reload_config(void)
4124 {
4125  int i, cfg_debug;
4126 
4127  if (!g_config_initialized) {
4128  ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
4129  return ;
4130  }
4131 
4132  free_robin_list();
4133  misdn_cfg_reload();
4136  misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
4137 
4138  for (i = 0; i <= max_ports; i++) {
4139  misdn_debug[i] = cfg_debug;
4140  misdn_debug_only[i] = 0;
4141  }
4142 }
4143 
4144 static char *handle_cli_misdn_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4145 {
4146  switch (cmd) {
4147  case CLI_INIT:
4148  e->command = "misdn reload";
4149  e->usage =
4150  "Usage: misdn reload\n"
4151  " Reload internal mISDN config, read from the config\n"
4152  " file.\n";
4153  return NULL;
4154  case CLI_GENERATE:
4155  return NULL;
4156  }
4157 
4158  if (a->argc != 2) {
4159  return CLI_SHOWUSAGE;
4160  }
4161 
4162  ast_cli(a->fd, "Reloading mISDN configuration\n");
4163  reload_config();
4164  return CLI_SUCCESS;
4165 }
4166 
4167 static void print_bc_info(int fd, struct chan_list *help, struct misdn_bchannel *bc)
4168 {
4169  struct ast_channel *ast = help->ast;
4170 
4171  ast_cli(fd,
4172  "* Pid:%d Port:%d Ch:%d Mode:%s Orig:%s dialed:%s\n"
4173  " --> caller:\"%s\" <%s>\n"
4174  " --> redirecting-from:\"%s\" <%s>\n"
4175  " --> redirecting-to:\"%s\" <%s>\n"
4176  " --> context:%s state:%s\n",
4177  bc->pid,
4178  bc->port,
4179  bc->channel,
4180  bc->nt ? "NT" : "TE",
4181  help->originator == ORG_AST ? "*" : "I",
4182  ast ? ast_channel_exten(ast) : "",
4183  (ast && ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
4184  ? ast_channel_caller(ast)->id.name.str : "",
4185  (ast && ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
4186  ? ast_channel_caller(ast)->id.number.str : "",
4187  bc->redirecting.from.name,
4188  bc->redirecting.from.number,
4189  bc->redirecting.to.name,
4190  bc->redirecting.to.number,
4191  ast ? ast_channel_context(ast) : "",
4192  misdn_get_ch_state(help));
4193  if (misdn_debug[bc->port] > 0) {
4194  ast_cli(fd,
4195  " --> astname: %s\n"
4196  " --> ch_l3id: %x\n"
4197  " --> ch_addr: %x\n"
4198  " --> bc_addr: %x\n"
4199  " --> bc_l3id: %x\n"
4200  " --> display: %s\n"
4201  " --> activated: %d\n"
4202  " --> state: %s\n"
4203  " --> capability: %s\n"
4204 #ifdef MISDN_1_2
4205  " --> pipeline: %s\n"
4206 #else
4207  " --> echo_cancel: %d\n"
4208 #endif
4209  " --> notone : rx %d tx:%d\n"
4210  " --> bc_hold: %d\n",
4211  ast ? ast_channel_name(ast) : "",
4212  help->l3id,
4213  help->addr,
4214  bc->addr,
4215  bc->l3_id,
4216  bc->display,
4217  bc->active,
4218  bc_state2str(bc->bc_state),
4219  bearer2str(bc->capability),
4220 #ifdef MISDN_1_2
4221  bc->pipeline,
4222 #else
4223  bc->ec_enable,
4224 #endif
4225  help->norxtone, help->notxtone,
4226  bc->holded);
4227  }
4228 }
4229 
4230 static char *handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4231 {
4232  struct chan_list *help;
4233 
4234  switch (cmd) {
4235  case CLI_INIT:
4236  e->command = "misdn show channels";
4237  e->usage =
4238  "Usage: misdn show channels\n"
4239  " Show the internal mISDN channel list\n";
4240  return NULL;
4241  case CLI_GENERATE:
4242  return NULL;
4243  }
4244 
4245  if (a->argc != 3) {
4246  return CLI_SHOWUSAGE;
4247  }
4248 
4249  ast_cli(a->fd, "Channel List: %p\n", cl_te);
4250 
4251  /*
4252  * Walking the list and dumping the channel information could
4253  * take awhile. With the list locked for the duration, the
4254  * channel driver cannot process signaling messages. However,
4255  * since this is a CLI command it should not be run very often.
4256  */
4257  ast_mutex_lock(&cl_te_lock);
4258  for (help = cl_te; help; help = help->next) {
4259  struct misdn_bchannel *bc = help->bc;
4260  struct ast_channel *ast = help->ast;
4261  if (!ast) {
4262  if (!bc) {
4263  ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
4264  continue;
4265  }
4266  ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
4267  }
4268 
4269  if (misdn_debug[0] > 2) {
4270  ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
4271  }
4272  if (bc) {
4273  print_bc_info(a->fd, help, bc);
4274  } else {
4275  if (help->hold.state != MISDN_HOLD_IDLE) {
4276  ast_cli(a->fd, "ITS A HELD CALL BC:\n");
4277  ast_cli(a->fd, " --> l3_id: %x\n"
4278  " --> dialed:%s\n"
4279  " --> caller:\"%s\" <%s>\n"
4280  " --> hold_port: %d\n"
4281  " --> hold_channel: %d\n",
4282  help->l3id,
4283  ast_channel_exten(ast),
4284  S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, ""),
4285  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""),
4286  help->hold.port,
4287  help->hold.channel
4288  );
4289  } else {
4290  ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n",
4291  ast_channel_exten(ast),
4292  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""));
4293  }
4294  }
4295  }
4296  ast_mutex_unlock(&cl_te_lock);
4297 
4299 
4300  return CLI_SUCCESS;
4301 }
4302 
4303 static char *handle_cli_misdn_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4304 {
4305  struct chan_list *help;
4306 
4307  switch (cmd) {
4308  case CLI_INIT:
4309  e->command = "misdn show channel";
4310  e->usage =
4311  "Usage: misdn show channel <channel>\n"
4312  " Show an internal mISDN channel\n.";
4313  return NULL;
4314  case CLI_GENERATE:
4315  return complete_ch(a);
4316  }
4317 
4318  if (a->argc != 4) {
4319  return CLI_SHOWUSAGE;
4320  }
4321 
4322  ast_mutex_lock(&cl_te_lock);
4323  for (help = cl_te; help; help = help->next) {
4324  struct misdn_bchannel *bc = help->bc;
4325  struct ast_channel *ast = help->ast;
4326 
4327  if (bc && ast) {
4328  if (!strcasecmp(ast_channel_name(ast), a->argv[3])) {
4329  print_bc_info(a->fd, help, bc);
4330  break;
4331  }
4332  }
4333  }
4334  ast_mutex_unlock(&cl_te_lock);
4335 
4336  return CLI_SUCCESS;
4337 }
4338 
4339 static char *handle_cli_misdn_set_tics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4340 {
4341  switch (cmd) {
4342  case CLI_INIT:
4343  e->command = "misdn set tics";
4344  e->usage =
4345  "Usage: misdn set tics <value>\n";
4346  return NULL;
4347  case CLI_GENERATE:
4348  return NULL;
4349  }
4350 
4351  if (a->argc != 4) {
4352  return CLI_SHOWUSAGE;
4353  }
4354 
4355  /* XXX Wow, this does... a whole lot of nothing... XXX */
4356  MAXTICS = atoi(a->argv[3]);
4357 
4358  return CLI_SUCCESS;
4359 }
4360 
4361 static char *handle_cli_misdn_show_stacks(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 stacks";
4368  e->usage =
4369  "Usage: misdn show stacks\n"
4370  " Show internal mISDN stack_list.\n";
4371  return NULL;
4372  case CLI_GENERATE:
4373  return NULL;
4374  }
4375 
4376  if (a->argc != 3) {
4377  return CLI_SHOWUSAGE;
4378  }
4379 
4380  ast_cli(a->fd, "BEGIN STACK_LIST:\n");
4381  for (port = misdn_cfg_get_next_port(0); port > 0;
4382  port = misdn_cfg_get_next_port(port)) {
4383  char buf[128];
4384 
4385  get_show_stack_details(port, buf);
4386  ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
4387  }
4388 
4389  return CLI_SUCCESS;
4390 }
4391 
4392 static char *handle_cli_misdn_show_ports_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4393 {
4394  int port;
4395 
4396  switch (cmd) {
4397  case CLI_INIT:
4398  e->command = "misdn show ports stats";
4399  e->usage =
4400  "Usage: misdn show ports stats\n"
4401  " Show mISDNs channel's call statistics per port.\n";
4402  return NULL;
4403  case CLI_GENERATE:
4404  return NULL;
4405  }
4406 
4407  if (a->argc != 4) {
4408  return CLI_SHOWUSAGE;
4409  }
4410 
4411  ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
4412  for (port = misdn_cfg_get_next_port(0); port > 0;
4413  port = misdn_cfg_get_next_port(port)) {
4414  ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
4415  }
4416  ast_cli(a->fd, "\n");
4417 
4418  return CLI_SUCCESS;
4419 }
4420 
4421 static char *handle_cli_misdn_show_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4422 {
4423  int port;
4424  char buf[128];
4425 
4426  switch (cmd) {
4427  case CLI_INIT:
4428  e->command = "misdn show port";
4429  e->usage =
4430  "Usage: misdn show port <port>\n"
4431  " Show detailed information for given port.\n";
4432  return NULL;
4433  case CLI_GENERATE:
4434  return NULL;
4435  }
4436 
4437  if (a->argc != 4) {
4438  return CLI_SHOWUSAGE;
4439  }
4440 
4441  port = atoi(a->argv[3]);
4442 
4443  ast_cli(a->fd, "BEGIN STACK_LIST:\n");
4444  get_show_stack_details(port, buf);
4445  ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
4446 
4447  return CLI_SUCCESS;
4448 }
4449 
4450 #if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
4451 static const struct FacParm Fac_Msgs[] = {
4452 /* *INDENT-OFF* */
4453  [0].Function = Fac_ERROR,
4454  [0].u.ERROR.invokeId = 8,
4455  [0].u.ERROR.errorValue = FacError_CCBS_AlreadyAccepted,
4456 
4457  [1].Function = Fac_RESULT,
4458  [1].u.RESULT.InvokeID = 9,
4459 
4460  [2].Function = Fac_REJECT,
4461  [2].u.REJECT.Code = FacReject_Gen_BadlyStructuredComponent,
4462 
4463  [3].Function = Fac_REJECT,
4464  [3].u.REJECT.InvokeIDPresent = 1,
4465  [3].u.REJECT.InvokeID = 10,
4466  [3].u.REJECT.Code = FacReject_Inv_InitiatorReleasing,
4467 
4468  [4].Function = Fac_REJECT,
4469  [4].u.REJECT.InvokeIDPresent = 1,
4470  [4].u.REJECT.InvokeID = 11,
4471  [4].u.REJECT.Code = FacReject_Res_MistypedResult,
4472 
4473  [5].Function = Fac_REJECT,
4474  [5].u.REJECT.InvokeIDPresent = 1,
4475  [5].u.REJECT.InvokeID = 12,
4476  [5].u.REJECT.Code = FacReject_Err_ErrorResponseUnexpected,
4477 
4478  [6].Function = Fac_StatusRequest,
4479  [6].u.StatusRequest.InvokeID = 13,
4480  [6].u.StatusRequest.ComponentType = FacComponent_Invoke,
4481  [6].u.StatusRequest.Component.Invoke.Q931ie.Bc.Length = 2,
4482  [6].u.StatusRequest.Component.Invoke.Q931ie.Bc.Contents = "AB",
4483  [6].u.StatusRequest.Component.Invoke.Q931ie.Llc.Length = 3,
4484  [6].u.StatusRequest.Component.Invoke.Q931ie.Llc.Contents = "CDE",
4485  [6].u.StatusRequest.Component.Invoke.Q931ie.Hlc.Length = 4,
4486  [6].u.StatusRequest.Component.Invoke.Q931ie.Hlc.Contents = "FGHI",
4487  [6].u.StatusRequest.Component.Invoke.CompatibilityMode = 1,
4488 
4489  [7].Function = Fac_StatusRequest,
4490  [7].u.StatusRequest.InvokeID = 14,
4491  [7].u.StatusRequest.ComponentType = FacComponent_Result,
4492  [7].u.StatusRequest.Component.Result.Status = 2,
4493 
4494  [8].Function = Fac_CallInfoRetain,
4495  [8].u.CallInfoRetain.InvokeID = 15,
4496  [8].u.CallInfoRetain.CallLinkageID = 115,
4497 
4498  [9].Function = Fac_EraseCallLinkageID,
4499  [9].u.EraseCallLinkageID.InvokeID = 16,
4500  [9].u.EraseCallLinkageID.CallLinkageID = 105,
4501 
4502  [10].Function = Fac_CCBSDeactivate,
4503  [10].u.CCBSDeactivate.InvokeID = 17,
4504  [10].u.CCBSDeactivate.ComponentType = FacComponent_Invoke,
4505  [10].u.CCBSDeactivate.Component.Invoke.CCBSReference = 2,
4506 
4507  [11].Function = Fac_CCBSDeactivate,
4508  [11].u.CCBSDeactivate.InvokeID = 18,
4509  [11].u.CCBSDeactivate.ComponentType = FacComponent_Result,
4510 
4511  [12].Function = Fac_CCBSErase,
4512  [12].u.CCBSErase.InvokeID = 19,
4513  [12].u.CCBSErase.Q931ie.Bc.Length = 2,
4514  [12].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4515  [12].u.CCBSErase.AddressOfB.Party.Type = 0,
4516  [12].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 5,
4517  [12].u.CCBSErase.AddressOfB.Party.Number = "33403",
4518  [12].u.CCBSErase.AddressOfB.Subaddress.Type = 0,
4519  [12].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
4520  [12].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.Information = "3748",
4521  [12].u.CCBSErase.RecallMode = 1,
4522  [12].u.CCBSErase.CCBSReference = 102,
4523  [12].u.CCBSErase.Reason = 3,
4524 
4525  [13].Function = Fac_CCBSErase,
4526  [13].u.CCBSErase.InvokeID = 20,
4527  [13].u.CCBSErase.Q931ie.Bc.Length = 2,
4528  [13].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4529  [13].u.CCBSErase.AddressOfB.Party.Type = 1,
4530  [13].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 11,
4531  [13].u.CCBSErase.AddressOfB.Party.TypeOfNumber = 1,
4532  [13].u.CCBSErase.AddressOfB.Party.Number = "18003020102",
4533  [13].u.CCBSErase.AddressOfB.Subaddress.Type = 0,
4534  [13].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
4535  [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.OddCountPresent = 1,
4536  [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.OddCount = 1,
4537  [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.Information = "3748",
4538  [13].u.CCBSErase.RecallMode = 1,
4539  [13].u.CCBSErase.CCBSReference = 102,
4540  [13].u.CCBSErase.Reason = 3,
4541 
4542  [14].Function = Fac_CCBSErase,
4543  [14].u.CCBSErase.InvokeID = 21,
4544  [14].u.CCBSErase.Q931ie.Bc.Length = 2,
4545  [14].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4546  [14].u.CCBSErase.AddressOfB.Party.Type = 2,
4547  [14].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
4548  [14].u.CCBSErase.AddressOfB.Party.Number = "1803",
4549  [14].u.CCBSErase.AddressOfB.Subaddress.Type = 1,
4550  [14].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
4551  [14].u.CCBSErase.AddressOfB.Subaddress.u.Nsap = "6492",
4552  [14].u.CCBSErase.RecallMode = 1,
4553  [14].u.CCBSErase.CCBSReference = 102,
4554  [14].u.CCBSErase.Reason = 3,
4555 
4556  [15].Function = Fac_CCBSErase,
4557  [15].u.CCBSErase.InvokeID = 22,
4558  [15].u.CCBSErase.Q931ie.Bc.Length = 2,
4559  [15].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4560  [15].u.CCBSErase.AddressOfB.Party.Type = 3,
4561  [15].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
4562  [15].u.CCBSErase.AddressOfB.Party.Number = "1803",
4563  [15].u.CCBSErase.RecallMode = 1,
4564  [15].u.CCBSErase.CCBSReference = 102,
4565  [15].u.CCBSErase.Reason = 3,
4566 
4567  [16].Function = Fac_CCBSErase,
4568  [16].u.CCBSErase.InvokeID = 23,
4569  [16].u.CCBSErase.Q931ie.Bc.Length = 2,
4570  [16].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4571  [16].u.CCBSErase.AddressOfB.Party.Type = 4,
4572  [16].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
4573  [16].u.CCBSErase.AddressOfB.Party.Number = "1803",
4574  [16].u.CCBSErase.RecallMode = 1,
4575  [16].u.CCBSErase.CCBSReference = 102,
4576  [16].u.CCBSErase.Reason = 3,
4577 
4578  [17].Function = Fac_CCBSErase,
4579  [17].u.CCBSErase.InvokeID = 24,
4580  [17].u.CCBSErase.Q931ie.Bc.Length = 2,
4581  [17].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4582  [17].u.CCBSErase.AddressOfB.Party.Type = 5,
4583  [17].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 11,
4584  [17].u.CCBSErase.AddressOfB.Party.TypeOfNumber = 4,
4585  [17].u.CCBSErase.AddressOfB.Party.Number = "18003020102",
4586  [17].u.CCBSErase.RecallMode = 1,
4587  [17].u.CCBSErase.CCBSReference = 102,
4588  [17].u.CCBSErase.Reason = 3,
4589 
4590  [18].Function = Fac_CCBSErase,
4591  [18].u.CCBSErase.InvokeID = 25,
4592  [18].u.CCBSErase.Q931ie.Bc.Length = 2,
4593  [18].u.CCBSErase.Q931ie.Bc.Contents = "JK",
4594  [18].u.CCBSErase.AddressOfB.Party.Type = 8,
4595  [18].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
4596  [18].u.CCBSErase.AddressOfB.Party.Number = "1803",
4597  [18].u.CCBSErase.RecallMode = 1,
4598  [18].u.CCBSErase.CCBSReference = 102,
4599  [18].u.CCBSErase.Reason = 3,
4600 
4601  [19].Function = Fac_CCBSRemoteUserFree,
4602  [19].u.CCBSRemoteUserFree.InvokeID = 26,
4603  [19].u.CCBSRemoteUserFree.Q931ie.Bc.Length = 2,
4604  [19].u.CCBSRemoteUserFree.Q931ie.Bc.Contents = "JK",
4605  [19].u.CCBSRemoteUserFree.AddressOfB.Party.Type = 8,
4606  [19].u.CCBSRemoteUserFree.AddressOfB.Party.LengthOfNumber = 4,
4607  [19].u.CCBSRemoteUserFree.AddressOfB.Party.Number = "1803",
4608  [19].u.CCBSRemoteUserFree.RecallMode = 1,
4609  [19].u.CCBSRemoteUserFree.CCBSReference = 102,
4610 
4611  [20].Function = Fac_CCBSCall,
4612  [20].u.CCBSCall.InvokeID = 27,
4613  [20].u.CCBSCall.CCBSReference = 115,
4614 
4615  [21].Function = Fac_CCBSStatusRequest,
4616  [21].u.CCBSStatusRequest.InvokeID = 28,
4617  [21].u.CCBSStatusRequest.ComponentType = FacComponent_Invoke,
4618  [21].u.CCBSStatusRequest.Component.Invoke.Q931ie.Bc.Length = 2,
4619  [21].u.CCBSStatusRequest.Component.Invoke.Q931ie.Bc.Contents = "JK",
4620  [21].u.CCBSStatusRequest.Component.Invoke.RecallMode = 1,
4621  [21].u.CCBSStatusRequest.Component.Invoke.CCBSReference = 102,
4622 
4623  [22].Function = Fac_CCBSStatusRequest,
4624  [22].u.CCBSStatusRequest.InvokeID = 29,
4625  [22].u.CCBSStatusRequest.ComponentType = FacComponent_Result,
4626  [22].u.CCBSStatusRequest.Component.Result.Free = 1,
4627 
4628  [23].Function = Fac_CCBSBFree,
4629  [23].u.CCBSBFree.InvokeID = 30,
4630  [23].u.CCBSBFree.Q931ie.Bc.Length = 2,
4631  [23].u.CCBSBFree.Q931ie.Bc.Contents = "JK",
4632  [23].u.CCBSBFree.AddressOfB.Party.Type = 8,
4633  [23].u.CCBSBFree.AddressOfB.Party.LengthOfNumber = 4,
4634  [23].u.CCBSBFree.AddressOfB.Party.Number = "1803",
4635  [23].u.CCBSBFree.RecallMode = 1,
4636  [23].u.CCBSBFree.CCBSReference = 14,
4637 
4638  [24].Function = Fac_CCBSStopAlerting,
4639  [24].u.CCBSStopAlerting.InvokeID = 31,
4640  [24].u.CCBSStopAlerting.CCBSReference = 37,
4641 
4642  [25].Function = Fac_CCBSRequest,
4643  [25].u.CCBSRequest.InvokeID = 32,
4644  [25].u.CCBSRequest.ComponentType = FacComponent_Invoke,
4645  [25].u.CCBSRequest.Component.Invoke.CallLinkageID = 57,
4646 
4647  [26].Function = Fac_CCBSRequest,
4648  [26].u.CCBSRequest.InvokeID = 33,
4649  [26].u.CCBSRequest.ComponentType = FacComponent_Result,
4650  [26].u.CCBSRequest.Component.Result.RecallMode = 1,
4651  [26].u.CCBSRequest.Component.Result.CCBSReference = 102,
4652 
4653  [27].Function = Fac_CCBSInterrogate,
4654  [27].u.CCBSInterrogate.InvokeID = 34,
4655  [27].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
4656  [27].u.CCBSInterrogate.Component.Invoke.AParty.Type = 8,
4657  [27].u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber = 4,
4658  [27].u.CCBSInterrogate.Component.Invoke.AParty.Number = "1803",
4659  [27].u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent = 1,
4660  [27].u.CCBSInterrogate.Component.Invoke.CCBSReference = 76,
4661 
4662  [28].Function = Fac_CCBSInterrogate,
4663  [28].u.CCBSInterrogate.InvokeID = 35,
4664  [28].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
4665  [28].u.CCBSInterrogate.Component.Invoke.AParty.Type = 8,
4666  [28].u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber = 4,
4667  [28].u.CCBSInterrogate.Component.Invoke.AParty.Number = "1803",
4668 
4669  [29].Function = Fac_CCBSInterrogate,
4670  [29].u.CCBSInterrogate.InvokeID = 36,
4671  [29].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
4672  [29].u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent = 1,
4673  [29].u.CCBSInterrogate.Component.Invoke.CCBSReference = 76,
4674 
4675  [30].Function = Fac_CCBSInterrogate,
4676  [30].u.CCBSInterrogate.InvokeID = 37,
4677  [30].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
4678 
4679  [31].Function = Fac_CCBSInterrogate,
4680  [31].u.CCBSInterrogate.InvokeID = 38,
4681  [31].u.CCBSInterrogate.ComponentType = FacComponent_Result,
4682  [31].u.CCBSInterrogate.Component.Result.RecallMode = 1,
4683 
4684  [32].Function = Fac_CCBSInterrogate,
4685  [32].u.CCBSInterrogate.InvokeID = 39,
4686  [32].u.CCBSInterrogate.ComponentType = FacComponent_Result,
4687  [32].u.CCBSInterrogate.Component.Result.RecallMode = 1,
4688  [32].u.CCBSInterrogate.Component.Result.NumRecords = 1,
4689  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].CCBSReference = 12,
4690  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Length = 2,
4691  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Contents = "JK",
4692  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Type = 8,
4693  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.LengthOfNumber = 4,
4694  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Number = "1803",
4695  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.Type = 1,
4696  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.Length = 4,
4697  [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.u.Nsap = "6492",
4698 
4699  [33].Function = Fac_CCBSInterrogate,
4700  [33].u.CCBSInterrogate.InvokeID = 40,
4701  [33].u.CCBSInterrogate.ComponentType = FacComponent_Result,
4702  [33].u.CCBSInterrogate.Component.Result.RecallMode = 1,
4703  [33].u.CCBSInterrogate.Component.Result.NumRecords = 2,
4704  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].CCBSReference = 12,
4705  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Length = 2,
4706  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Contents = "JK",
4707  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Type = 8,
4708  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.LengthOfNumber = 4,
4709  [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Number = "1803",
4710  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].CCBSReference = 102,
4711  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].Q931ie.Bc.Length = 2,
4712  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].Q931ie.Bc.Contents = "LM",
4713  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.Type = 8,
4714  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.LengthOfNumber = 4,
4715  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.Number = "6229",
4716  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.Type = 1,
4717  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.Length = 4,
4718  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.u.Nsap = "8592",
4719  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.Type = 1,
4720  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.Length = 4,
4721  [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.u.Nsap = "6492",
4722 
4723  [34].Function = Fac_CCNRRequest,
4724  [34].u.CCNRRequest.InvokeID = 512,
4725  [34].u.CCNRRequest.ComponentType = FacComponent_Invoke,
4726  [34].u.CCNRRequest.Component.Invoke.CallLinkageID = 57,
4727 
4728  [35].Function = Fac_CCNRRequest,
4729  [35].u.CCNRRequest.InvokeID = 150,
4730  [35].u.CCNRRequest.ComponentType = FacComponent_Result,
4731  [35].u.CCNRRequest.Component.Result.RecallMode = 1,
4732  [35].u.CCNRRequest.Component.Result.CCBSReference = 102,
4733 
4734  [36].Function = Fac_CCNRInterrogate,
4735  [36].u.CCNRInterrogate.InvokeID = -129,
4736  [36].u.CCNRInterrogate.ComponentType = FacComponent_Invoke,
4737 
4738  [37].Function = Fac_CCNRInterrogate,
4739  [37].u.CCNRInterrogate.InvokeID = -3,
4740  [37].u.CCNRInterrogate.ComponentType = FacComponent_Result,
4741  [37].u.CCNRInterrogate.Component.Result.RecallMode = 1,
4742 
4743  [38].Function = Fac_CCBS_T_Call,
4744  [38].u.EctExecute.InvokeID = 41,
4745 
4746  [39].Function = Fac_CCBS_T_Suspend,
4747  [39].u.EctExecute.InvokeID = 42,
4748 
4749  [40].Function = Fac_CCBS_T_Resume,
4750  [40].u.EctExecute.InvokeID = 43,
4751 
4752  [41].Function = Fac_CCBS_T_RemoteUserFree,
4753  [41].u.EctExecute.InvokeID = 44,
4754 
4755  [42].Function = Fac_CCBS_T_Available,
4756  [42].u.EctExecute.InvokeID = 45,
4757 
4758  [43].Function = Fac_CCBS_T_Request,
4759  [43].u.CCBS_T_Request.InvokeID = 46,
4760  [43].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4761  [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4762  [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4763  [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4764  [43].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4765  [43].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4766  [43].u.CCBS_T_Request.Component.Invoke.RetentionSupported = 1,
4767  [43].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
4768  [43].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
4769  [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
4770  [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
4771  [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
4772 
4773  [44].Function = Fac_CCBS_T_Request,
4774  [44].u.CCBS_T_Request.InvokeID = 47,
4775  [44].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4776  [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4777  [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4778  [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4779  [44].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4780  [44].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4781  [44].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
4782  [44].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
4783  [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
4784  [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
4785  [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
4786 
4787  [45].Function = Fac_CCBS_T_Request,
4788  [45].u.CCBS_T_Request.InvokeID = 48,
4789  [45].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4790  [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4791  [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4792  [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4793  [45].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4794  [45].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4795  [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
4796  [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
4797  [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
4798 
4799  [46].Function = Fac_CCBS_T_Request,
4800  [46].u.CCBS_T_Request.InvokeID = 49,
4801  [46].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4802  [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4803  [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4804  [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4805  [46].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4806  [46].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4807  [46].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
4808  [46].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
4809 
4810  [47].Function = Fac_CCBS_T_Request,
4811  [47].u.CCBS_T_Request.InvokeID = 50,
4812  [47].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
4813  [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
4814  [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4815  [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4816  [47].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4817  [47].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4818 
4819  [48].Function = Fac_CCBS_T_Request,
4820  [48].u.CCBS_T_Request.InvokeID = 51,
4821  [48].u.CCBS_T_Request.ComponentType = FacComponent_Result,
4822  [48].u.CCBS_T_Request.Component.Result.RetentionSupported = 1,
4823 
4824  [49].Function = Fac_CCNR_T_Request,
4825  [49].u.CCNR_T_Request.InvokeID = 52,
4826  [49].u.CCNR_T_Request.ComponentType = FacComponent_Invoke,
4827  [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.Type = 8,
4828  [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
4829  [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.Number = "6229",
4830  [49].u.CCNR_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
4831  [49].u.CCNR_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
4832 
4833  [50].Function = Fac_CCNR_T_Request,
4834  [50].u.CCNR_T_Request.InvokeID = 53,
4835  [50].u.CCNR_T_Request.ComponentType = FacComponent_Result,
4836  [50].u.CCNR_T_Request.Component.Result.RetentionSupported = 1,
4837 
4838  [51].Function = Fac_EctExecute,
4839  [51].u.EctExecute.InvokeID = 54,
4840 
4841  [52].Function = Fac_ExplicitEctExecute,
4842  [52].u.ExplicitEctExecute.InvokeID = 55,
4843  [52].u.ExplicitEctExecute.LinkID = 23,
4844 
4845  [53].Function = Fac_RequestSubaddress,
4846  [53].u.RequestSubaddress.InvokeID = 56,
4847 
4848  [54].Function = Fac_SubaddressTransfer,
4849  [54].u.SubaddressTransfer.InvokeID = 57,
4850  [54].u.SubaddressTransfer.Subaddress.Type = 1,
4851  [54].u.SubaddressTransfer.Subaddress.Length = 4,
4852  [54].u.SubaddressTransfer.Subaddress.u.Nsap = "6492",
4853 
4854  [55].Function = Fac_EctLinkIdRequest,
4855  [55].u.EctLinkIdRequest.InvokeID = 58,
4856  [55].u.EctLinkIdRequest.ComponentType = FacComponent_Invoke,
4857 
4858  [56].Function = Fac_EctLinkIdRequest,
4859  [56].u.EctLinkIdRequest.InvokeID = 59,
4860  [56].u.EctLinkIdRequest.ComponentType = FacComponent_Result,
4861  [56].u.EctLinkIdRequest.Component.Result.LinkID = 76,
4862 
4863  [57].Function = Fac_EctInform,
4864  [57].u.EctInform.InvokeID = 60,
4865  [57].u.EctInform.Status = 1,
4866  [57].u.EctInform.RedirectionPresent = 1,
4867  [57].u.EctInform.Redirection.Type = 0,
4868  [57].u.EctInform.Redirection.Unscreened.Type = 8,
4869  [57].u.EctInform.Redirection.Unscreened.LengthOfNumber = 4,
4870  [57].u.EctInform.Redirection.Unscreened.Number = "6229",
4871 
4872  [58].Function = Fac_EctInform,
4873  [58].u.EctInform.InvokeID = 61,
4874  [58].u.EctInform.Status = 1,
4875  [58].u.EctInform.RedirectionPresent = 1,
4876  [58].u.EctInform.Redirection.Type = 1,
4877 
4878  [59].Function = Fac_EctInform,
4879  [59].u.EctInform.InvokeID = 62,
4880  [59].u.EctInform.Status = 1,
4881  [59].u.EctInform.RedirectionPresent = 1,
4882  [59].u.EctInform.Redirection.Type = 2,
4883 
4884  [60].Function = Fac_EctInform,
4885  [60].u.EctInform.InvokeID = 63,
4886  [60].u.EctInform.Status = 1,
4887  [60].u.EctInform.RedirectionPresent = 1,
4888  [60].u.EctInform.Redirection.Type = 3,
4889  [60].u.EctInform.Redirection.Unscreened.Type = 8,
4890  [60].u.EctInform.Redirection.Unscreened.LengthOfNumber = 4,
4891  [60].u.EctInform.Redirection.Unscreened.Number = "3340",
4892 
4893  [61].Function = Fac_EctInform,
4894  [61].u.EctInform.InvokeID = 64,
4895  [61].u.EctInform.Status = 1,
4896  [61].u.EctInform.RedirectionPresent = 0,
4897 
4898  [62].Function = Fac_EctLoopTest,
4899  [62].u.EctLoopTest.InvokeID = 65,
4900  [62].u.EctLoopTest.ComponentType = FacComponent_Invoke,
4901  [62].u.EctLoopTest.Component.Invoke.CallTransferID = 7,
4902 
4903  [63].Function = Fac_EctLoopTest,
4904  [63].u.EctLoopTest.InvokeID = 66,
4905  [63].u.EctLoopTest.ComponentType = FacComponent_Result,
4906  [63].u.EctLoopTest.Component.Result.LoopResult = 2,
4907 
4908  [64].Function = Fac_ActivationDiversion,
4909  [64].u.ActivationDiversion.InvokeID = 67,
4910  [64].u.ActivationDiversion.ComponentType = FacComponent_Invoke,
4911  [64].u.ActivationDiversion.Component.Invoke.Procedure = 2,
4912  [64].u.ActivationDiversion.Component.Invoke.BasicService = 3,
4913  [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 4,
4914  [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber = 4,
4915  [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number = "1803",
4916  [64].u.ActivationDiversion.Component.Invoke.ServedUser.Type = 4,
4917  [64].u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber = 4,
4918  [64].u.ActivationDiversion.Component.Invoke.ServedUser.Number = "5398",
4919 
4920  [65].Function = Fac_ActivationDiversion,
4921  [65].u.ActivationDiversion.InvokeID = 68,
4922  [65].u.ActivationDiversion.ComponentType = FacComponent_Invoke,
4923  [65].u.ActivationDiversion.Component.Invoke.Procedure = 1,
4924  [65].u.ActivationDiversion.Component.Invoke.BasicService = 5,
4925  [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 4,
4926  [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber = 4,
4927  [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number = "1803",
4928 
4929  [66].Function = Fac_ActivationDiversion,
4930  [66].u.ActivationDiversion.InvokeID = 69,
4931  [66].u.ActivationDiversion.ComponentType = FacComponent_Result,
4932 
4933  [67].Function = Fac_DeactivationDiversion,
4934  [67].u.DeactivationDiversion.InvokeID = 70,
4935  [67].u.DeactivationDiversion.ComponentType = FacComponent_Invoke,
4936  [67].u.DeactivationDiversion.Component.Invoke.Procedure = 1,
4937  [67].u.DeactivationDiversion.Component.Invoke.BasicService = 5,
4938 
4939  [68].Function = Fac_DeactivationDiversion,
4940  [68].u.DeactivationDiversion.InvokeID = 71,
4941  [68].u.DeactivationDiversion.ComponentType = FacComponent_Result,
4942 
4943  [69].Function = Fac_ActivationStatusNotificationDiv,
4944  [69].u.ActivationStatusNotificationDiv.InvokeID = 72,
4945  [69].u.ActivationStatusNotificationDiv.Procedure = 1,
4946  [69].u.ActivationStatusNotificationDiv.BasicService = 5,
4947  [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.Type = 4,
4948  [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.LengthOfNumber = 4,
4949  [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.Number = "1803",
4950 
4951  [70].Function = Fac_DeactivationStatusNotificationDiv,
4952  [70].u.DeactivationStatusNotificationDiv.InvokeID = 73,
4953  [70].u.DeactivationStatusNotificationDiv.Procedure = 1,
4954  [70].u.DeactivationStatusNotificationDiv.BasicService = 5,
4955 
4956  [71].Function = Fac_InterrogationDiversion,
4957  [71].u.InterrogationDiversion.InvokeID = 74,
4958  [71].u.InterrogationDiversion.ComponentType = FacComponent_Invoke,
4959  [71].u.InterrogationDiversion.Component.Invoke.Procedure = 1,
4960  [71].u.InterrogationDiversion.Component.Invoke.BasicService = 5,
4961 
4962  [72].Function = Fac_InterrogationDiversion,
4963  [72].u.InterrogationDiversion.InvokeID = 75,
4964  [72].u.InterrogationDiversion.ComponentType = FacComponent_Invoke,
4965  [72].u.InterrogationDiversion.Component.Invoke.Procedure = 1,
4966 
4967  [73].Function = Fac_InterrogationDiversion,
4968  [73].u.InterrogationDiversion.InvokeID = 76,
4969  [73].u.InterrogationDiversion.ComponentType = FacComponent_Result,
4970  [73].u.InterrogationDiversion.Component.Result.NumRecords = 2,
4971  [73].u.InterrogationDiversion.Component.Result.List[0].Procedure = 2,
4972  [73].u.InterrogationDiversion.Component.Result.List[0].BasicService = 5,
4973  [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.Type = 4,
4974  [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.LengthOfNumber = 4,
4975  [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.Number = "1803",
4976  [73].u.InterrogationDiversion.Component.Result.List[1].Procedure = 1,
4977  [73].u.InterrogationDiversion.Component.Result.List[1].BasicService = 3,
4978  [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.Type = 4,
4979  [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.LengthOfNumber = 4,
4980  [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.Number = "1903",
4981  [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.Type = 4,
4982  [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.LengthOfNumber = 4,
4983  [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.Number = "5398",
4984 
4985  [74].Function = Fac_DiversionInformation,
4986  [74].u.DiversionInformation.InvokeID = 77,
4987  [74].u.DiversionInformation.DiversionReason = 3,
4988  [74].u.DiversionInformation.BasicService = 5,
4989  [74].u.DiversionInformation.ServedUserSubaddress.Type = 1,
4990  [74].u.DiversionInformation.ServedUserSubaddress.Length = 4,
4991  [74].u.DiversionInformation.ServedUserSubaddress.u.Nsap = "6492",
4992  [74].u.DiversionInformation.CallingAddressPresent = 1,
4993  [74].u.DiversionInformation.CallingAddress.Type = 0,
4994  [74].u.DiversionInformation.CallingAddress.Address.ScreeningIndicator = 3,
4995  [74].u.DiversionInformation.CallingAddress.Address.Party.Type = 4,
4996  [74].u.DiversionInformation.CallingAddress.Address.Party.LengthOfNumber = 4,
4997  [74].u.DiversionInformation.CallingAddress.Address.Party.Number = "1803",
4998  [74].u.DiversionInformation.OriginalCalledPresent = 1,
4999  [74].u.DiversionInformation.OriginalCalled.Type = 1,
5000  [74].u.DiversionInformation.LastDivertingPresent = 1,
5001  [74].u.DiversionInformation.LastDiverting.Type = 2,
5002  [74].u.DiversionInformation.LastDivertingReasonPresent = 1,
5003  [74].u.DiversionInformation.LastDivertingReason = 3,
5004  [74].u.DiversionInformation.UserInfo.Length = 5,
5005  [74].u.DiversionInformation.UserInfo.Contents = "79828",
5006 
5007  [75].Function = Fac_DiversionInformation,
5008  [75].u.DiversionInformation.InvokeID = 78,
5009  [75].u.DiversionInformation.DiversionReason = 3,
5010  [75].u.DiversionInformation.BasicService = 5,
5011  [75].u.DiversionInformation.CallingAddressPresent = 1,
5012  [75].u.DiversionInformation.CallingAddress.Type = 1,
5013  [75].u.DiversionInformation.OriginalCalledPresent = 1,
5014  [75].u.DiversionInformation.OriginalCalled.Type = 2,
5015  [75].u.DiversionInformation.LastDivertingPresent = 1,
5016  [75].u.DiversionInformation.LastDiverting.Type = 1,
5017 
5018  [76].Function = Fac_DiversionInformation,
5019  [76].u.DiversionInformation.InvokeID = 79,
5020  [76].u.DiversionInformation.DiversionReason = 2,
5021  [76].u.DiversionInformation.BasicService = 3,
5022  [76].u.DiversionInformation.CallingAddressPresent = 1,
5023  [76].u.DiversionInformation.CallingAddress.Type = 2,
5024 
5025  [77].Function = Fac_DiversionInformation,
5026  [77].u.DiversionInformation.InvokeID = 80,
5027  [77].u.DiversionInformation.DiversionReason = 3,
5028  [77].u.DiversionInformation.BasicService = 5,
5029  [77].u.DiversionInformation.CallingAddressPresent = 1,
5030  [77].u.DiversionInformation.CallingAddress.Type = 3,
5031  [77].u.DiversionInformation.CallingAddress.Address.ScreeningIndicator = 2,
5032  [77].u.DiversionInformation.CallingAddress.Address.Party.Type = 4,
5033  [77].u.DiversionInformation.CallingAddress.Address.Party.LengthOfNumber = 4,
5034  [77].u.DiversionInformation.CallingAddress.Address.Party.Number = "1803",
5035 
5036  [78].Function = Fac_DiversionInformation,
5037  [78].u.DiversionInformation.InvokeID = 81,
5038  [78].u.DiversionInformation.DiversionReason = 2,
5039  [78].u.DiversionInformation.BasicService = 4,
5040  [78].u.DiversionInformation.UserInfo.Length = 5,
5041  [78].u.DiversionInformation.UserInfo.Contents = "79828",
5042 
5043  [79].Function = Fac_DiversionInformation,
5044  [79].u.DiversionInformation.InvokeID = 82,
5045  [79].u.DiversionInformation.DiversionReason = 2,
5046  [79].u.DiversionInformation.BasicService = 4,
5047 
5048  [80].Function = Fac_CallDeflection,
5049  [80].u.CallDeflection.InvokeID = 83,
5050  [80].u.CallDeflection.ComponentType = FacComponent_Invoke,
5051  [80].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
5052  [80].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
5053  [80].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
5054  [80].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1,
5055  [80].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 1,
5056 
5057  [81].Function = Fac_CallDeflection,
5058  [81].u.CallDeflection.InvokeID = 84,
5059  [81].u.CallDeflection.ComponentType = FacComponent_Invoke,
5060  [81].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
5061  [81].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
5062  [81].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
5063  [81].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1,
5064  [81].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0,
5065 
5066  [82].Function = Fac_CallDeflection,
5067  [82].u.CallDeflection.InvokeID = 85,
5068  [82].u.CallDeflection.ComponentType = FacComponent_Invoke,
5069  [82].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
5070  [82].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
5071  [82].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
5072 
5073  [83].Function = Fac_CallDeflection,
5074  [83].u.CallDeflection.InvokeID = 86,
5075  [83].u.CallDeflection.ComponentType = FacComponent_Result,
5076 
5077  [84].Function = Fac_CallRerouteing,
5078  [84].u.CallRerouteing.InvokeID = 87,
5079  [84].u.CallRerouteing.ComponentType = FacComponent_Invoke,
5080  [84].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
5081  [84].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
5082  [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
5083  [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
5084  [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
5085  [84].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
5086  [84].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
5087  [84].u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 3,
5088  [84].u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Contents = "RTG",
5089  [84].u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 2,
5090  [84].u.CallRerouteing.Component.Invoke.Q931ie.Llc.Contents = "MY",
5091  [84].u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 5,
5092  [84].u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Contents = "YEHAW",
5093  [84].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1,
5094  [84].u.CallRerouteing.Component.Invoke.SubscriptionOption = 2,
5095  [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Type = 1,
5096  [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 4,
5097  [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.u.Nsap = "6492",
5098 
5099  [85].Function = Fac_CallRerouteing,
5100  [85].u.CallRerouteing.InvokeID = 88,
5101  [85].u.CallRerouteing.ComponentType = FacComponent_Invoke,
5102  [85].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
5103  [85].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
5104  [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
5105  [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
5106  [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
5107  [85].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
5108  [85].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
5109  [85].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1,
5110  [85].u.CallRerouteing.Component.Invoke.SubscriptionOption = 2,
5111 
5112  [86].Function = Fac_CallRerouteing,
5113  [86].u.CallRerouteing.InvokeID = 89,
5114  [86].u.CallRerouteing.ComponentType = FacComponent_Invoke,
5115  [86].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
5116  [86].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
5117  [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
5118  [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
5119  [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
5120  [86].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
5121  [86].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
5122  [86].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 2,
5123 
5124  [87].Function = Fac_CallRerouteing,
5125  [87].u.CallRerouteing.InvokeID = 90,
5126  [87].u.CallRerouteing.ComponentType = FacComponent_Result,
5127 
5128  [88].Function = Fac_InterrogateServedUserNumbers,
5129  [88].u.InterrogateServedUserNumbers.InvokeID = 91,
5130  [88].u.InterrogateServedUserNumbers.ComponentType = FacComponent_Invoke,
5131 
5132  [89].Function = Fac_InterrogateServedUserNumbers,
5133  [89].u.InterrogateServedUserNumbers.InvokeID = 92,
5134  [89].u.InterrogateServedUserNumbers.ComponentType = FacComponent_Result,
5135  [89].u.InterrogateServedUserNumbers.Component.Result.NumRecords = 2,
5136  [89].u.InterrogateServedUserNumbers.Component.Result.List[0].Type = 4,
5137  [89].u.InterrogateServedUserNumbers.Component.Result.List[0].LengthOfNumber = 4,
5138  [89].u.InterrogateServedUserNumbers.Component.Result.List[0].Number = "1803",
5139  [89].u.InterrogateServedUserNumbers.Component.Result.List[1].Type = 4,
5140  [89].u.InterrogateServedUserNumbers.Component.Result.List[1].LengthOfNumber = 4,
5141  [89].u.InterrogateServedUserNumbers.Component.Result.List[1].Number = "5786",
5142 
5143  [90].Function = Fac_DivertingLegInformation1,
5144  [90].u.DivertingLegInformation1.InvokeID = 93,
5145  [90].u.DivertingLegInformation1.DiversionReason = 4,
5146  [90].u.DivertingLegInformation1.SubscriptionOption = 1,
5147  [90].u.DivertingLegInformation1.DivertedToPresent = 1,
5148  [90].u.DivertingLegInformation1.DivertedTo.Type = 2,
5149 
5150  [91].Function = Fac_DivertingLegInformation1,
5151  [91].u.DivertingLegInformation1.InvokeID = 94,
5152  [91].u.DivertingLegInformation1.DiversionReason = 4,
5153  [91].u.DivertingLegInformation1.SubscriptionOption = 1,
5154 
5155  [92].Function = Fac_DivertingLegInformation2,
5156  [92].u.DivertingLegInformation2.InvokeID = 95,
5157  [92].u.DivertingLegInformation2.DiversionCounter = 3,
5158  [92].u.DivertingLegInformation2.DiversionReason = 2,
5159  [92].u.DivertingLegInformation2.DivertingPresent = 1,
5160  [92].u.DivertingLegInformation2.Diverting.Type = 2,
5161  [92].u.DivertingLegInformation2.OriginalCalledPresent = 1,
5162  [92].u.DivertingLegInformation2.OriginalCalled.Type = 1,
5163 
5164  [93].Function = Fac_DivertingLegInformation2,
5165  [93].u.DivertingLegInformation2.InvokeID = 96,
5166  [93].u.DivertingLegInformation2.DiversionCounter = 3,
5167  [93].u.DivertingLegInformation2.DiversionReason = 2,
5168  [93].u.DivertingLegInformation2.OriginalCalledPresent = 1,
5169  [93].u.DivertingLegInformation2.OriginalCalled.Type = 1,
5170 
5171  [94].Function = Fac_DivertingLegInformation2,
5172  [94].u.DivertingLegInformation2.InvokeID = 97,
5173  [94].u.DivertingLegInformation2.DiversionCounter = 1,
5174  [94].u.DivertingLegInformation2.DiversionReason = 2,
5175 
5176  [95].Function = Fac_DivertingLegInformation3,
5177  [95].u.DivertingLegInformation3.InvokeID = 98,
5178  [95].u.DivertingLegInformation3.PresentationAllowedIndicator = 1,
5179 /* *INDENT-ON* */
5180 };
5181 #endif /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
5182 
5183 static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5184 {
5185  const char *channame;
5186  const char *nr;
5187  struct chan_list *tmp;
5188  int port;
5189  const char *served_nr;
5190  struct misdn_bchannel dummy, *bc=&dummy;
5191  unsigned max_len;
5192 
5193  switch (cmd) {
5194  case CLI_INIT:
5195  e->command = "misdn send facility";
5196  e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
5197  "\t type is one of:\n"
5198  "\t - calldeflect\n"
5199 #if defined(AST_MISDN_ENHANCEMENTS)
5200  "\t - callrerouting\n"
5201 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
5202  "\t - CFActivate\n"
5203  "\t - CFDeactivate\n";
5204 
5205  return NULL;
5206  case CLI_GENERATE:
5207  return complete_ch(a);
5208  }
5209 
5210  if (a->argc < 5) {
5211  return CLI_SHOWUSAGE;
5212  }
5213 
5214  if (strstr(a->argv[3], "calldeflect")) {
5215  if (a->argc < 6) {
5216  ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
5217  return 0;
5218  }
5219  channame = a->argv[4];
5220  nr = a->argv[5];
5221 
5222  ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
5223  tmp = get_chan_by_ast_name(channame);
5224  if (!tmp) {
5225  ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
5226  return 0;
5227  }
5228  ao2_lock(tmp);
5229 
5230 #if defined(AST_MISDN_ENHANCEMENTS)
5231  max_len = sizeof(tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
5232  if (max_len < strlen(nr)) {
5233  ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
5234  nr, channame, max_len);
5235  ao2_unlock(tmp);
5236  chan_list_unref(tmp, "Number too long");
5237  return 0;
5238  }
5239  tmp->bc->fac_out.Function = Fac_CallDeflection;
5240  tmp->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
5241  tmp->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
5242  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
5243  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
5244  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
5245  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(nr);
5246  strcpy((char *) tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, nr);
5247  tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
5248 
5249 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
5250 
5251  max_len = sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
5252  if (max_len < strlen(nr)) {
5253  ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
5254  nr, channame, max_len);
5255  ao2_unlock(tmp);
5256  chan_list_unref(tmp, "Number too long");
5257  return 0;
5258  }
5259  tmp->bc->fac_out.Function = Fac_CD;
5260  tmp->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
5261  //tmp->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
5262  strcpy((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr);
5263 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
5264 
5265  /* Send message */
5266  print_facility(&tmp->bc->fac_out, tmp->bc);
5267  ao2_unlock(tmp);
5269  chan_list_unref(tmp, "Send facility complete");
5270 #if defined(AST_MISDN_ENHANCEMENTS)
5271  } else if (strstr(a->argv[3], "callrerouteing") || strstr(a->argv[3], "callrerouting")) {
5272  if (a->argc < 6) {
5273  ast_verbose("callrerouting requires 1 arg: ToNumber\n\n");
5274  return 0;
5275  }
5276  channame = a->argv[4];
5277  nr = a->argv[5];
5278 
5279  ast_verbose("Sending Callrerouting (%s) to %s\n", nr, channame);
5280  tmp = get_chan_by_ast_name(channame);
5281  if (!tmp) {
5282  ast_verbose("Sending Call Rerouting with nr %s to %s failed: Channel does not exist.\n", nr, channame);
5283  return 0;
5284  }
5285  ao2_lock(tmp);
5286 
5287  max_len = sizeof(tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
5288  if (max_len < strlen(nr)) {
5289  ast_verbose("Sending Call Rerouting with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
5290  nr, channame, max_len);
5291  ao2_unlock(tmp);
5292  chan_list_unref(tmp, "Number too long");
5293  return 0;
5294  }
5295  tmp->bc->fac_out.Function = Fac_CallRerouteing;
5296  tmp->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
5297  tmp->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
5298 
5299  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
5300  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
5301 
5302  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
5303  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(nr);
5304  strcpy((char *) tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, nr);
5305  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
5306 
5307  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
5308 
5309  /* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
5310  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
5311  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
5312  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
5313  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
5314  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
5315  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
5316  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
5317 
5318  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
5319  tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
5320 
5321  /* Send message */
5322  print_facility(&tmp->bc->fac_out, tmp->bc);
5323  ao2_unlock(tmp);
5325  chan_list_unref(tmp, "Send facility complete");
5326 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
5327  } else if (strstr(a->argv[3], "CFActivate")) {
5328  if (a->argc < 7) {
5329  ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
5330  return 0;
5331  }
5332  port = atoi(a->argv[4]);
5333  served_nr = a->argv[5];
5334  nr = a->argv[6];
5335 
5336  misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
5337 
5338  ast_verbose("Sending CFActivate Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
5339 
5340 #if defined(AST_MISDN_ENHANCEMENTS)
5341  bc->fac_out.Function = Fac_ActivationDiversion;
5342  bc->fac_out.u.ActivationDiversion.InvokeID = ++misdn_invoke_id;
5343  bc->fac_out.u.ActivationDiversion.ComponentType = FacComponent_Invoke;
5344  bc->fac_out.u.ActivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
5345  bc->fac_out.u.ActivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
5346  ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number,
5347  served_nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number));
5348  bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
5349  strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number);
5350  bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
5351  ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number,
5352  nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number));
5353  bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber =
5354  strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number);
5355  bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 0;/* unknown */
5356  bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Subaddress.Length = 0;
5357 
5358 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
5359 
5360  bc->fac_out.Function = Fac_CFActivate;
5361  bc->fac_out.u.CFActivate.BasicService = 0; /* All Services */
5362  bc->fac_out.u.CFActivate.Procedure = 0; /* Unconditional */
5363  ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
5364  ast_copy_string((char *) bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
5365 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
5366 
5367  /* Send message */
5368  print_facility(&bc->fac_out, bc);
5370  } else if (strstr(a->argv[3], "CFDeactivate")) {
5371  if (a->argc < 6) {
5372  ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
5373  return 0;
5374  }
5375  port = atoi(a->argv[4]);
5376  served_nr = a->argv[5];
5377 
5378  misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
5379  ast_verbose("Sending CFDeactivate Port:(%d) FromNr. (%s)\n", port, served_nr);
5380 
5381 #if defined(AST_MISDN_ENHANCEMENTS)
5382  bc->fac_out.Function = Fac_DeactivationDiversion;
5383  bc->fac_out.u.DeactivationDiversion.InvokeID = ++misdn_invoke_id;
5384  bc->fac_out.u.DeactivationDiversion.ComponentType = FacComponent_Invoke;
5385  bc->fac_out.u.DeactivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
5386  bc->fac_out.u.DeactivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
5387  ast_copy_string((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number,
5388  served_nr, sizeof(bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number));
5389  bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
5390  strlen((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number);
5391  bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
5392 
5393 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
5394 
5395  bc->fac_out.Function = Fac_CFDeactivate;
5396  bc->fac_out.u.CFDeactivate.BasicService = 0; /* All Services */
5397  bc->fac_out.u.CFDeactivate.Procedure = 0; /* Unconditional */
5398  ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
5399 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
5400 
5401  /* Send message */
5402  print_facility(&bc->fac_out, bc);
5404 #if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
5405  } else if (strstr(a->argv[3], "test")) {
5406  int msg_number;
5407 
5408  if (a->argc < 5) {
5409  ast_verbose("test (<port> [<msg#>]) | (<channel-name> <msg#>)\n\n");
5410  return 0;
5411  }
5412  port = atoi(a->argv[4]);
5413 
5414  channame = a->argv[4];
5415  tmp = get_chan_by_ast_name(channame);
5416  if (tmp) {
5417  /* We are going to send this FACILITY message out on an existing connection */
5418  msg_number = atoi(a->argv[5]);
5419  if (msg_number < ARRAY_LEN(Fac_Msgs)) {
5420  ao2_lock(tmp);
5421  tmp->bc->fac_out = Fac_Msgs[msg_number];
5422 
5423  /* Send message */
5424  print_facility(&tmp->bc->fac_out, tmp->bc);
5425  ao2_unlock(tmp);
5427  } else {
5428  ast_verbose("test <channel-name> <msg#>\n\n");
5429  }
5430  chan_list_unref(tmp, "Facility test done");
5431  } else if (a->argc < 6) {
5432  for (msg_number = 0; msg_number < ARRAY_LEN(Fac_Msgs); ++msg_number) {
5433  misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
5434  bc->fac_out = Fac_Msgs[msg_number];
5435 
5436  /* Send message */
5437  print_facility(&bc->fac_out, bc);
5439  sleep(1);
5440  }
5441  } else {
5442  msg_number = atoi(a->argv[5]);
5443  if (msg_number < ARRAY_LEN(Fac_Msgs)) {
5444  misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
5445  bc->fac_out = Fac_Msgs[msg_number];
5446 
5447  /* Send message */
5448  print_facility(&bc->fac_out, bc);
5450  } else {
5451  ast_verbose("test <port> [<msg#>]\n\n");
5452  }
5453  }
5454  } else if (strstr(a->argv[3], "register")) {
5455  if (a->argc < 5) {
5456  ast_verbose("register <port>\n\n");
5457  return 0;
5458  }
5459  port = atoi(a->argv[4]);
5460 
5461  bc = misdn_lib_get_register_bc(port);
5462  if (!bc) {
5463  ast_verbose("Could not allocate REGISTER bc struct\n\n");
5464  return 0;
5465  }
5466  bc->fac_out = Fac_Msgs[45];
5467 
5468  /* Send message */
5469  print_facility(&bc->fac_out, bc);
5471 #endif /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
5472  }
5473 
5474  return CLI_SUCCESS;
5475 }
5476 
5477 static char *handle_cli_misdn_send_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5478 {
5479  int port;
5480  int channel;
5481 
5482  switch (cmd) {
5483  case CLI_INIT:
5484  e->command = "misdn send restart";
5485  e->usage =
5486  "Usage: misdn send restart [port [channel]]\n"
5487  " Send a restart for every bchannel on the given port.\n";
5488  return NULL;
5489  case CLI_GENERATE:
5490  return NULL;
5491  }
5492 
5493  if (a->argc < 4 || a->argc > 5) {
5494  return CLI_SHOWUSAGE;
5495  }
5496 
5497  port = atoi(a->argv[3]);
5498 
5499  if (a->argc == 5) {
5500  channel = atoi(a->argv[4]);
5501  misdn_lib_send_restart(port, channel);
5502  } else {
5503  misdn_lib_send_restart(port, -1);
5504  }
5505 
5506  return CLI_SUCCESS;
5507 }
5508 
5509 static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5510 {
5511  const char *channame;
5512  const char *msg;
5513  struct chan_list *tmp;
5514  int i, msglen;
5515 
5516  switch (cmd) {
5517  case CLI_INIT:
5518  e->command = "misdn send digit";
5519  e->usage =
5520  "Usage: misdn send digit <channel> \"<msg>\" \n"
5521  " Send <digit> to <channel> as DTMF Tone\n"
5522  " when channel is a mISDN channel\n";
5523  return NULL;
5524  case CLI_GENERATE:
5525  return complete_ch(a);
5526  }
5527 
5528  if (a->argc != 5) {
5529  return CLI_SHOWUSAGE;
5530  }
5531 
5532  channame = a->argv[3];
5533  msg = a->argv[4];
5534  msglen = strlen(msg);
5535 
5536  ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
5537 
5538  tmp = get_chan_by_ast_name(channame);
5539  if (!tmp) {
5540  ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
5541  return CLI_SUCCESS;
5542  }
5543 #if 1
5544  for (i = 0; i < msglen; i++) {
5545  if (!tmp->ast) {
5546  break;
5547  }
5548  ast_cli(a->fd, "Sending: %c\n", msg[i]);
5549  send_digit_to_chan(tmp, msg[i]);
5550  /* res = ast_safe_sleep(tmp->ast, 250); */
5551  usleep(250000);
5552  /* res = ast_waitfor(tmp->ast,100); */
5553  }
5554 #else
5555  if (tmp->ast) {
5556  ast_dtmf_stream(tmp->ast, NULL, msg, 250);
5557  }
5558 #endif
5559  chan_list_unref(tmp, "Digit(s) sent");
5560 
5561  return CLI_SUCCESS;
5562 }
5563 
5564 static char *handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5565 {
5566  const char *channame;
5567  struct chan_list *tmp;
5568 
5569  switch (cmd) {
5570  case CLI_INIT:
5571  e->command = "misdn toggle echocancel";
5572  e->usage =
5573  "Usage: misdn toggle echocancel <channel>\n"
5574  " Toggle EchoCancel on mISDN Channel.\n";
5575  return NULL;
5576  case CLI_GENERATE:
5577  return complete_ch(a);
5578  }
5579 
5580  if (a->argc != 4) {
5581  return CLI_SHOWUSAGE;
5582  }
5583 
5584  channame = a->argv[3];
5585 
5586  ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
5587 
5588  tmp = get_chan_by_ast_name(channame);
5589  if (!tmp) {
5590  ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
5591  return CLI_SUCCESS;
5592  }
5593 
5594  tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
5595 
5596  if (tmp->toggle_ec) {
5597 #ifdef MISDN_1_2
5598  update_pipeline_config(tmp->bc);
5599 #else
5600  update_ec_config(tmp->bc);
5601 #endif
5602  manager_ec_enable(tmp->bc);
5603  } else {
5604  manager_ec_disable(tmp->bc);
5605  }
5606  chan_list_unref(tmp, "Done toggling echo cancel");
5607 
5608  return CLI_SUCCESS;
5609 }
5610 
5611 static char *handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5612 {
5613  const char *channame;
5614  const char *msg;
5615  struct chan_list *tmp;
5616 
5617  switch (cmd) {
5618  case CLI_INIT:
5619  e->command = "misdn send display";
5620  e->usage =
5621  "Usage: misdn send display <channel> \"<msg>\" \n"
5622  " Send <msg> to <channel> as Display Message\n"
5623  " when channel is a mISDN channel\n";
5624  return NULL;
5625  case CLI_GENERATE:
5626  return complete_ch(a);
5627  }
5628 
5629  if (a->argc != 5) {
5630  return CLI_SHOWUSAGE;
5631  }
5632 
5633  channame = a->argv[3];
5634  msg = a->argv[4];
5635 
5636  ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
5637 
5638  tmp = get_chan_by_ast_name(channame);
5639  if (tmp && tmp->bc) {
5640  ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
5642  chan_list_unref(tmp, "Done sending display");
5643  } else {
5644  if (tmp) {
5645  chan_list_unref(tmp, "Display failed");
5646  }
5647  ast_cli(a->fd, "No such channel %s\n", channame);
5648  return CLI_SUCCESS;
5649  }
5650 
5651  return CLI_SUCCESS;
5652 }
5653 
5654 static char *complete_ch(struct ast_cli_args *a)
5655 {
5656  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
5657 }
5658 
5659 static char *complete_debug_port(struct ast_cli_args *a)
5660 {
5661  if (a->n) {
5662  return NULL;
5663  }
5664 
5665  switch (a->pos) {
5666  case 4:
5667  if (a->word[0] == 'p') {
5668  return ast_strdup("port");
5669  } else if (a->word[0] == 'o') {
5670  return ast_strdup("only");
5671  }
5672  break;
5673  case 6:
5674  if (a->word[0] == 'o') {
5675  return ast_strdup("only");
5676  }
5677  break;
5678  }
5679  return NULL;
5680 }
5681 
5682 static char *complete_show_config(struct ast_cli_args *a)
5683 {
5684  char buffer[BUFFERSIZE];
5685  enum misdn_cfg_elements elem;
5686  int wordlen = strlen(a->word);
5687  int which = 0;
5688  int port = 0;
5689 
5690  switch (a->pos) {
5691  case 3:
5692  if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n)) {
5693  return ast_strdup("description");
5694  }
5695  if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n)) {
5696  return ast_strdup("descriptions");
5697  }
5698  if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n)) {
5699  return ast_strdup("0");
5700  }
5701  while ((port = misdn_cfg_get_next_port(port)) != -1) {
5702  snprintf(buffer, sizeof(buffer), "%d", port);
5703  if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
5704  return ast_strdup(buffer);
5705  }
5706  }
5707  break;
5708  case 4:
5709  if (strstr(a->line, "description ")) {
5710  for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
5711  if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST)) {
5712  continue;
5713  }
5714  misdn_cfg_get_name(elem, buffer, sizeof(buffer));
5715  if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
5716  if (++which > a->n) {
5717  return ast_strdup(buffer);
5718  }
5719  }
5720  }
5721  } else if (strstr(a->line, "descriptions ")) {
5722  if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n)) {
5723  return ast_strdup("general");
5724  }
5725  if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n)) {
5726  return ast_strdup("ports");
5727  }
5728  }
5729  break;
5730  }
5731  return NULL;
5732 }
5733 
5734 static struct ast_cli_entry chan_misdn_clis[] = {
5735 /* *INDENT-OFF* */
5736  AST_CLI_DEFINE(handle_cli_misdn_port_block, "Block the given port"),
5737  AST_CLI_DEFINE(handle_cli_misdn_port_down, "Try to deactivate the L1 on the given port"),
5738  AST_CLI_DEFINE(handle_cli_misdn_port_unblock, "Unblock the given port"),
5739  AST_CLI_DEFINE(handle_cli_misdn_port_up, "Try to establish L1 on the given port"),
5740  AST_CLI_DEFINE(handle_cli_misdn_reload, "Reload internal mISDN config, read from the config file"),
5741  AST_CLI_DEFINE(handle_cli_misdn_restart_pid, "Restart the given pid"),
5742  AST_CLI_DEFINE(handle_cli_misdn_restart_port, "Restart the given port"),
5743  AST_CLI_DEFINE(handle_cli_misdn_show_channel, "Show an internal mISDN channel"),
5744  AST_CLI_DEFINE(handle_cli_misdn_show_channels, "Show the internal mISDN channel list"),
5745  AST_CLI_DEFINE(handle_cli_misdn_show_config, "Show internal mISDN config, read from the config file"),
5746  AST_CLI_DEFINE(handle_cli_misdn_show_port, "Show detailed information for given port"),
5747  AST_CLI_DEFINE(handle_cli_misdn_show_ports_stats, "Show mISDNs channel's call statistics per port"),
5748  AST_CLI_DEFINE(handle_cli_misdn_show_stacks, "Show internal mISDN stack_list"),
5749  AST_CLI_DEFINE(handle_cli_misdn_send_facility, "Sends a Facility Message to the mISDN Channel"),
5750  AST_CLI_DEFINE(handle_cli_misdn_send_digit, "Send DTMF digit to mISDN Channel"),
5751  AST_CLI_DEFINE(handle_cli_misdn_send_display, "Send Text to mISDN Channel"),
5752  AST_CLI_DEFINE(handle_cli_misdn_send_restart, "Send a restart for every bchannel on the given port"),
5753  AST_CLI_DEFINE(handle_cli_misdn_set_crypt_debug, "Set CryptDebuglevel of chan_misdn, at the moment, level={1,2}"),
5754  AST_CLI_DEFINE(handle_cli_misdn_set_debug, "Set Debuglevel of chan_misdn"),
5756  AST_CLI_DEFINE(handle_cli_misdn_toggle_echocancel, "Toggle EchoCancel on mISDN Channel"),
5757 /* *INDENT-ON* */
5758 };
5759 
5760 /*! \brief Updates caller ID information from config */
5761 static void update_config(struct chan_list *ch)
5762 {
5763  struct ast_channel *ast;
5764  struct misdn_bchannel *bc;
5765  int port;
5766  int hdlc = 0;
5767  int pres;
5768  int screen;
5769 
5770  if (!ch) {
5771  ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
5772  return;
5773  }
5774 
5775  ast = ch->ast;
5776  bc = ch->bc;
5777  if (! ast || ! bc) {
5778  ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
5779  return;
5780  }
5781 
5782  port = bc->port;
5783 
5784  chan_misdn_log(7, port, "update_config: Getting Config\n");
5785 
5786  misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
5787  if (hdlc) {
5788  switch (bc->capability) {
5791  chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
5792  bc->hdlc = 1;
5793  break;
5794  }
5795  }
5796 
5797 
5798  misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
5799  misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
5800  chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
5801 
5802  if (pres < 0 || screen < 0) {
5803  chan_misdn_log(2, port, " --> pres: %x\n", ast_channel_connected(ast)->id.number.presentation);
5804 
5805  bc->caller.presentation = ast_to_misdn_pres(ast_channel_connected(ast)->id.number.presentation);
5806  chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
5807 
5808  bc->caller.screening = ast_to_misdn_screen(ast_channel_connected(ast)->id.number.presentation);
5809  chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
5810  } else {
5811  bc->caller.screening = screen;
5812  bc->caller.presentation = pres;
5813  }
5814 }
5815 
5816 
5817 static void config_jitterbuffer(struct chan_list *ch)
5818 {
5819  struct misdn_bchannel *bc = ch->bc;
5820  int len = ch->jb_len;
5821  int threshold = ch->jb_upper_threshold;
5822 
5823  chan_misdn_log(5, bc->port, "config_jb: Called\n");
5824 
5825  if (!len) {
5826  chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
5827  bc->nojitter = 1;
5828  } else {
5829  if (len <= 100 || len > 8000) {
5830  chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
5831  len = 1000;
5832  }
5833 
5834  if (threshold > len) {
5835  chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
5836  }
5837 
5838  if (ch->jb) {
5839  cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
5840  misdn_jb_destroy(ch->jb);
5841  ch->jb = NULL;
5842  }
5843 
5844  ch->jb = misdn_jb_init(len, threshold);
5845 
5846  if (!ch->jb) {
5847  bc->nojitter = 1;
5848  }
5849  }
5850 }
5851 
5852 
5853 void debug_numtype(int port, int numtype, char *type)
5854 {
5855  switch (numtype) {
5856  case NUMTYPE_UNKNOWN:
5857  chan_misdn_log(2, port, " --> %s: Unknown\n", type);
5858  break;
5859  case NUMTYPE_INTERNATIONAL:
5860  chan_misdn_log(2, port, " --> %s: International\n", type);
5861  break;
5862  case NUMTYPE_NATIONAL:
5863  chan_misdn_log(2, port, " --> %s: National\n", type);
5864  break;
5866  chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
5867  break;
5868  case NUMTYPE_SUBSCRIBER:
5869  chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
5870  break;
5871  case NUMTYPE_ABBREVIATED:
5872  chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
5873  break;
5874  /* Maybe we should cut off the prefix if present ? */
5875  default:
5876  chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
5877  break;
5878  }
5879 }
5880 
5881 
5882 #ifdef MISDN_1_2
5883 static int update_pipeline_config(struct misdn_bchannel *bc)
5884 {
5885  int ec;
5886 
5887  misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
5888 
5889  if (*bc->pipeline) {
5890  return 0;
5891  }
5892 
5893  misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
5894  if (ec == 1) {
5895  ast_copy_string(bc->pipeline, "mg2ec", sizeof(bc->pipeline));
5896  } else if (ec > 1) {
5897  snprintf(bc->pipeline, sizeof(bc->pipeline), "mg2ec(deftaps=%d)", ec);
5898  }
5899 
5900  return 0;
5901 }
5902 #else
5903 static int update_ec_config(struct misdn_bchannel *bc)
5904 {
5905  int ec;
5906  int port = bc->port;
5907 
5908  misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
5909 
5910  if (ec == 1) {
5911  bc->ec_enable = 1;
5912  } else if (ec > 1) {
5913  bc->ec_enable = 1;
5914  bc->ec_deftaps = ec;
5915  }
5916 
5917  return 0;
5918 }
5919 #endif
5920 
5921 
5922 static int read_config(struct chan_list *ch)
5923 {
5924  struct ast_channel *ast;
5925  struct misdn_bchannel *bc;
5926  int port;
5927  int hdlc = 0;
5928  char lang[BUFFERSIZE + 1];
5929  char faxdetect[BUFFERSIZE + 1];
5930  char buf[256];
5931  char buf2[256];
5932  ast_group_t pg;
5933  ast_group_t cg;
5934  struct ast_namedgroups *npg;
5935  struct ast_namedgroups *ncg;
5936  struct ast_str *tmp_str;
5937 
5938  if (!ch) {
5939  ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
5940  return -1;
5941  }
5942 
5943  ast = ch->ast;
5944  bc = ch->bc;
5945  if (! ast || ! bc) {
5946  ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
5947  return -1;
5948  }
5949 
5950  port = bc->port;
5951  chan_misdn_log(1, port, "read_config: Getting Config\n");
5952 
5953  misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
5954  ast_channel_lock(ast);
5955  ast_channel_language_set(ast, lang);
5956  ast_channel_unlock(ast);
5957 
5959 
5960  misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
5961  misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
5962 
5964 
5965  misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
5966 
5967  misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
5968  if (ch->ast_dsp) {
5969  ch->ignore_dtmf = 1;
5970  }
5971 
5973  misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
5974 
5976 
5978 
5980 
5981  misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
5982 
5983  misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
5984  if (hdlc) {
5985  switch (bc->capability) {
5988  chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
5989  bc->hdlc = 1;
5990  break;
5991  }
5992 
5993  }
5994  /*Initialize new Jitterbuffer*/
5995  misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
5997 
5998  config_jitterbuffer(ch);
5999 
6000  misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
6001 
6002  ast_channel_lock(ast);
6003  ast_channel_context_set(ast, ch->context);
6004  ast_channel_unlock(ast);
6005 
6006 #ifdef MISDN_1_2
6007  update_pipeline_config(bc);
6008 #else
6009  update_ec_config(bc);
6010 #endif
6011 
6013 
6017 
6018  misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
6019  misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
6020  chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
6021  ast_channel_lock(ast);
6022  ast_channel_pickupgroup_set(ast, pg);
6023  ast_channel_callgroup_set(ast, cg);
6024  ast_channel_unlock(ast);
6025 
6026  misdn_cfg_get(port, MISDN_CFG_NAMEDPICKUPGROUP, &npg, sizeof(npg));
6027  misdn_cfg_get(port, MISDN_CFG_NAMEDCALLGROUP, &ncg, sizeof(ncg));
6028 
6029  tmp_str = ast_str_create(1024);
6030  if (tmp_str) {
6031  chan_misdn_log(5, port, " --> * NamedCallGrp:%s\n", ast_print_namedgroups(&tmp_str, ncg));
6032  ast_str_reset(tmp_str);
6033  chan_misdn_log(5, port, " --> * NamedPickupGrp:%s\n", ast_print_namedgroups(&tmp_str, npg));
6034  ast_free(tmp_str);
6035  }
6036 
6037  ast_channel_lock(ast);
6040  ast_channel_unlock(ast);
6041 
6042  if (ch->originator == ORG_AST) {
6043  char callerid[BUFFERSIZE + 1];
6044 
6045  /* ORIGINATOR Asterisk (outgoing call) */
6046 
6048 
6049  if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
6050  ch->faxdetect = strstr(faxdetect, "nojump") ? 2 : 1;
6051  }
6052 
6053  misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
6054  if (!ast_strlen_zero(callerid)) {
6055  char *cid_name = NULL;
6056  char *cid_num = NULL;
6057 
6058  ast_callerid_parse(callerid, &cid_name, &cid_num);
6059  if (cid_name) {
6060  ast_copy_string(bc->caller.name, cid_name, sizeof(bc->caller.name));
6061  } else {
6062  bc->caller.name[0] = '\0';
6063  }
6064  if (cid_num) {
6065  ast_copy_string(bc->caller.number, cid_num, sizeof(bc->caller.number));
6066  } else {
6067  bc->caller.number[0] = '\0';
6068  }
6069  chan_misdn_log(1, port, " --> * Setting caller to \"%s\" <%s>\n", bc->caller.name, bc->caller.number);
6070  }
6071 
6074  debug_numtype(port, bc->dialed.number_type, "TON");
6075 
6076  ch->overlap_dial = 0;
6077  } else {
6078  /* ORIGINATOR MISDN (incoming call) */
6079 
6080  if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
6081  ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
6082  }
6083 
6084  /* Add configured prefix to caller.number */
6086 
6087  if (ast_strlen_zero(bc->dialed.number) && !ast_strlen_zero(bc->keypad)) {
6088  ast_copy_string(bc->dialed.number, bc->keypad, sizeof(bc->dialed.number));
6089  }
6090 
6091  /* Add configured prefix to dialed.number */
6093 
6094  ast_channel_lock(ast);
6096  ast_channel_unlock(ast);
6097 
6100  } /* ORIG MISDN END */
6101 
6103  if (!ast_strlen_zero(bc->incoming_cid_tag)) {
6104  chan_misdn_log(1, port, " --> * Setting incoming caller id tag to \"%s\"\n", bc->incoming_cid_tag);
6105  }
6106  ch->overlap_dial_task = -1;
6107 
6108  if (ch->faxdetect || ch->ast_dsp) {
6110  if (!ch->dsp) {
6111  ch->dsp = ast_dsp_new();
6112  }
6113  if (ch->dsp) {
6115  }
6116  }
6117 
6118  /* AOCD initialization */
6119  bc->AOCDtype = Fac_None;
6120 
6121  return 0;
6122 }
6123 
6124 /*!
6125  * \internal
6126  * \brief Send a connected line update to the other channel
6127  *
6128  * \param ast Current Asterisk channel
6129  * \param id Party id information to send to the other side
6130  * \param source Why are we sending this update
6131  * \param cid_tag User tag to apply to the party id.
6132  *
6133  * \return Nothing
6134  */
6135 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)
6136 {
6137  struct ast_party_connected_line connected;
6138  struct ast_set_party_connected_line update_connected;
6139 
6140  ast_party_connected_line_init(&connected);
6141  memset(&update_connected, 0, sizeof(update_connected));
6142  update_connected.id.number = 1;
6143  connected.id.number.valid = 1;
6144  connected.id.number.str = (char *) id->number;
6145  connected.id.number.plan = misdn_to_ast_ton(id->number_type)
6149 
6150  /*
6151  * Make sure that any earlier private connected id
6152  * representation at the remote end is invalidated
6153  */
6154  ast_set_party_id_all(&update_connected.priv);
6155 
6156  connected.id.tag = cid_tag;
6157  connected.source = source;
6158  ast_channel_queue_connected_line_update(ast, &connected, &update_connected);
6159 }
6160 
6161 /*!
6162  * \internal
6163  * \brief Update the caller id party on this channel.
6164  *
6165  * \param ast Current Asterisk channel
6166  * \param id Remote party id information to update.
6167  * \param cid_tag User tag to apply to the party id.
6168  *
6169  * \return Nothing
6170  */
6171 static void misdn_update_caller_id(struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag)
6172 {
6173  struct ast_party_caller caller;
6174  struct ast_set_party_caller update_caller;
6175 
6176  memset(&update_caller, 0, sizeof(update_caller));
6177  update_caller.id.number = 1;
6178  update_caller.ani.number = 1;
6179 
6180  ast_channel_lock(ast);
6182 
6183  caller.id.number.valid = 1;
6184  caller.id.number.str = (char *) id->number;
6185  caller.id.number.plan = misdn_to_ast_ton(id->number_type)
6189 
6190  caller.ani.number = caller.id.number;
6191 
6192  caller.id.tag = cid_tag;
6193  caller.ani.tag = cid_tag;
6194 
6195  ast_channel_set_caller_event(ast, &caller, &update_caller);
6196  ast_channel_unlock(ast);
6197 }
6198 
6199 /*!
6200  * \internal
6201  * \brief Update the remote party id information.
6202  *
6203  * \param ast Current Asterisk channel
6204  * \param id Remote party id information to update.
6205  * \param source Why are we sending this update
6206  * \param cid_tag User tag to apply to the party id.
6207  *
6208  * \return Nothing
6209  */
6210 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)
6211 {
6212  misdn_update_caller_id(ast, id, cid_tag);
6213  misdn_queue_connected_line_update(ast, id, source, cid_tag);
6214 }
6215 
6216 /*!
6217  * \internal
6218  * \brief Get the connected line information out of the Asterisk channel.
6219  *
6220  * \param ast Current Asterisk channel
6221  * \param bc Associated B channel
6222  * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
6223  *
6224  * \return Nothing
6225  */
6226 static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
6227 {
6228  int number_type;
6229  struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
6230 
6231  if (originator == ORG_MISDN) {
6232  /* ORIGINATOR MISDN (incoming call) */
6233 
6235  S_COR(connected_id.name.valid, connected_id.name.str, ""),
6236  sizeof(bc->connected.name));
6237  if (connected_id.number.valid) {
6238  ast_copy_string(bc->connected.number, S_OR(connected_id.number.str, ""),
6239  sizeof(bc->connected.number));
6242  bc->connected.number_type = ast_to_misdn_ton(connected_id.number.plan);
6243  bc->connected.number_plan = ast_to_misdn_plan(connected_id.number.plan);
6244  } else {
6245  bc->connected.number[0] = '\0';
6246  bc->connected.presentation = 0;/* Allowed */
6247  bc->connected.screening = 0;/* Unscreened */
6250  }
6251 
6252  misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
6253  if (0 <= number_type) {
6254  /* Force us to send in CONNECT message */
6255  bc->connected.number_type = number_type;
6257  }
6258  debug_numtype(bc->port, bc->connected.number_type, "CTON");
6259  } else {
6260  /* ORIGINATOR Asterisk (outgoing call) */
6261 
6263  S_COR(connected_id.name.valid, connected_id.name.str, ""),
6264  sizeof(bc->caller.name));
6265  if (connected_id.number.valid) {
6266  ast_copy_string(bc->caller.number, S_OR(connected_id.number.str, ""),
6267  sizeof(bc->caller.number));
6270  bc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan);
6271  bc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan);
6272  } else {
6273  bc->caller.number[0] = '\0';
6274  bc->caller.presentation = 0;/* Allowed */
6275  bc->caller.screening = 0;/* Unscreened */
6278  }
6279 
6280  misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
6281  if (0 <= number_type) {
6282  /* Force us to send in SETUP message */
6283  bc->caller.number_type = number_type;
6285  }
6286  debug_numtype(bc->port, bc->caller.number_type, "LTON");
6287  }
6288 }
6289 
6290 /*!
6291  * \internal
6292  * \brief Notify peer that the connected line has changed.
6293  *
6294  * \param ast Current Asterisk channel
6295  * \param bc Associated B channel
6296  * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
6297  *
6298  * \return Nothing
6299  */
6300 static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
6301 {
6302  struct chan_list *ch;
6303 
6304  misdn_get_connected_line(ast, bc, originator);
6305  if (originator == ORG_MISDN) {
6306  bc->redirecting.to = bc->connected;
6307  } else {
6308  bc->redirecting.to = bc->caller;
6309  }
6310  switch (bc->outgoing_colp) {
6311  case 1:/* restricted */
6312  bc->redirecting.to.presentation = 1;/* restricted */
6313  break;
6314  case 2:/* blocked */
6315  /* Don't tell the remote party that the call was transferred. */
6316  return;
6317  default:
6318  break;
6319  }
6320 
6321  ch = MISDN_ASTERISK_TECH_PVT(ast);
6322  if (ch->state == MISDN_CONNECTED
6323  || originator != ORG_MISDN) {
6324  int is_ptmp;
6325 
6326  is_ptmp = !misdn_lib_is_ptp(bc->port);
6327  if (is_ptmp) {
6328  /*
6329  * We should not send these messages to the network if we are
6330  * the CPE side since phones do not transfer calls within
6331  * themselves. Well... If you consider handing the handset to
6332  * someone else a transfer then how is the network to know?
6333  */
6334  if (!misdn_lib_port_is_nt(bc->port)) {
6335  return;
6336  }
6337  if (ch->state != MISDN_CONNECTED) {
6338  /* Send NOTIFY(Nie(transfer-active), RDNie(redirecting.to data)) */
6339  bc->redirecting.to_changed = 1;
6342 #if defined(AST_MISDN_ENHANCEMENTS)
6343  } else {
6344  /* Send FACILITY(Fie(RequestSubaddress), Nie(transfer-active), RDNie(redirecting.to data)) */
6345  bc->redirecting.to_changed = 1;
6347  bc->fac_out.Function = Fac_RequestSubaddress;
6348  bc->fac_out.u.RequestSubaddress.InvokeID = ++misdn_invoke_id;
6349 
6350  /* Send message */
6351  print_facility(&bc->fac_out, bc);
6353 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6354  }
6355 #if defined(AST_MISDN_ENHANCEMENTS)
6356  } else {
6357  /* Send FACILITY(Fie(EctInform(transfer-active, redirecting.to data))) */
6358  bc->fac_out.Function = Fac_EctInform;
6359  bc->fac_out.u.EctInform.InvokeID = ++misdn_invoke_id;
6360  bc->fac_out.u.EctInform.Status = 1;/* active */
6361  bc->fac_out.u.EctInform.RedirectionPresent = 1;/* Must be present when status is active */
6362  misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.EctInform.Redirection,
6363  &bc->redirecting.to);
6364 
6365  /* Send message */
6366  print_facility(&bc->fac_out, bc);
6368 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6369  }
6370  }
6371 }
6372 
6373 /*!
6374  * \internal
6375  * \brief Copy the redirecting information out of the Asterisk channel
6376  *
6377  * \param bc Associated B channel
6378  * \param ast Current Asterisk channel
6379  *
6380  * \return Nothing
6381  */
6382 static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast)
6383 {
6386 
6388  S_COR(from_id.name.valid, from_id.name.str, ""),
6389  sizeof(bc->redirecting.from.name));
6390  if (from_id.number.valid) {
6391  ast_copy_string(bc->redirecting.from.number, S_OR(from_id.number.str, ""),
6392  sizeof(bc->redirecting.from.number));
6397  } else {
6398  bc->redirecting.from.number[0] = '\0';
6399  bc->redirecting.from.presentation = 0;/* Allowed */
6400  bc->redirecting.from.screening = 0;/* Unscreened */
6403  }
6404 
6406  S_COR(to_id.name.valid, to_id.name.str, ""),
6407  sizeof(bc->redirecting.to.name));
6408  if (to_id.number.valid) {
6410  sizeof(bc->redirecting.to.number));
6415  } else {
6416  bc->redirecting.to.number[0] = '\0';
6417  bc->redirecting.to.presentation = 0;/* Allowed */
6418  bc->redirecting.to.screening = 0;/* Unscreened */
6421  }
6422 
6425 }
6426 
6427 /*!
6428  * \internal
6429  * \brief Copy the redirecting info into the Asterisk channel
6430  *
6431  * \param ast Current Asterisk channel
6432  * \param redirect Associated B channel redirecting info
6433  * \param tag Caller ID tag to set in the redirecting party fields
6434  *
6435  * \return Nothing
6436  */
6437 static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag)
6438 {
6439  struct ast_party_redirecting redirecting;
6440  struct ast_set_party_redirecting update_redirecting;
6441 
6443  memset(&update_redirecting, 0, sizeof(update_redirecting));
6444 
6445  update_redirecting.from.number = 1;
6446  redirecting.from.number.valid = 1;
6447  redirecting.from.number.str = (char *) redirect->from.number;
6448  redirecting.from.number.plan =
6449  misdn_to_ast_ton(redirect->from.number_type)
6450  | misdn_to_ast_plan(redirect->from.number_plan);
6451  redirecting.from.number.presentation =
6453  | misdn_to_ast_screen(redirect->from.screening);
6454  redirecting.from.tag = tag;
6455 
6456  update_redirecting.to.number = 1;
6457  redirecting.to.number.valid = 1;
6458  redirecting.to.number.str = (char *) redirect->to.number;
6459  redirecting.to.number.plan =
6460  misdn_to_ast_ton(redirect->to.number_type)
6461  | misdn_to_ast_plan(redirect->to.number_plan);
6462  redirecting.to.number.presentation =
6463  misdn_to_ast_pres(redirect->to.presentation)
6464  | misdn_to_ast_screen(redirect->to.screening);
6465  redirecting.to.tag = tag;
6466 
6467  redirecting.reason.code = misdn_to_ast_reason(redirect->reason);
6468  redirecting.count = redirect->count;
6469 
6470  ast_channel_set_redirecting(ast, &redirecting, &update_redirecting);
6471 }
6472 
6473 /*!
6474  * \internal
6475  * \brief Notify peer that the redirecting information has changed.
6476  *
6477  * \param ast Current Asterisk channel
6478  * \param bc Associated B channel
6479  * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
6480  *
6481  * \return Nothing
6482  */
6483 static void misdn_update_redirecting(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
6484 {
6485  int is_ptmp;
6486 
6488  switch (bc->outgoing_colp) {
6489  case 1:/* restricted */
6490  bc->redirecting.to.presentation = 1;/* restricted */
6491  break;
6492  case 2:/* blocked */
6493  /* Don't tell the remote party that the call was redirected. */
6494  return;
6495  default:
6496  break;
6497  }
6498 
6499  if (originator != ORG_MISDN) {
6500  return;
6501  }
6502 
6503  is_ptmp = !misdn_lib_is_ptp(bc->port);
6504  if (is_ptmp) {
6505  /*
6506  * We should not send these messages to the network if we are
6507  * the CPE side since phones do not redirect calls within
6508  * themselves. Well... If you consider someone else picking up
6509  * the handset a redirection then how is the network to know?
6510  */
6511  if (!misdn_lib_port_is_nt(bc->port)) {
6512  return;
6513  }
6514  /* Send NOTIFY(call-is-diverting, redirecting.to data) */
6515  bc->redirecting.to_changed = 1;
6518 #if defined(AST_MISDN_ENHANCEMENTS)
6519  } else {
6520  int match; /* TRUE if the dialed number matches the redirecting to number */
6521 
6522  match = (strcmp(ast_channel_exten(ast), bc->redirecting.to.number) == 0) ? 1 : 0;
6523  if (!bc->div_leg_3_tx_pending
6524  || !match) {
6525  /* Send DivertingLegInformation1 */
6526  bc->fac_out.Function = Fac_DivertingLegInformation1;
6527  bc->fac_out.u.DivertingLegInformation1.InvokeID = ++misdn_invoke_id;
6528  bc->fac_out.u.DivertingLegInformation1.DiversionReason =
6529  misdn_to_diversion_reason(bc->redirecting.reason);
6530  bc->fac_out.u.DivertingLegInformation1.SubscriptionOption = 2;/* notificationWithDivertedToNr */
6531  bc->fac_out.u.DivertingLegInformation1.DivertedToPresent = 1;
6532  misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.DivertingLegInformation1.DivertedTo, &bc->redirecting.to);
6533  print_facility(&bc->fac_out, bc);
6535  }
6536  bc->div_leg_3_tx_pending = 0;
6537 
6538  /* Send DivertingLegInformation3 */
6539  bc->fac_out.Function = Fac_DivertingLegInformation3;
6540  bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
6541  bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
6542  bc->redirecting.to.presentation == 0 ? 1 : 0;
6543  print_facility(&bc->fac_out, bc);
6545 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6546  }
6547 }
6548 
6549 
6550 /*****************************/
6551 /*** AST Indications Start ***/
6552 /*****************************/
6553 
6554 static int misdn_call(struct ast_channel *ast, const char *dest, int timeout)
6555 {
6556  int port = 0;
6557  int r;
6558  int exceed;
6559  int number_type;
6560  struct chan_list *ch;
6561  struct misdn_bchannel *newbc;
6562  char *dest_cp;
6563  int append_msn = 0;
6564 
6566  AST_APP_ARG(intf); /* The interface token is discarded. */
6567  AST_APP_ARG(ext); /* extension token */
6568  AST_APP_ARG(opts); /* options token */
6569  );
6570 
6571  if (!ast) {
6572  ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
6573  return -1;
6574  }
6575 
6576  if (((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) || !dest) {
6577  ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast_channel_name(ast));
6580  return -1;
6581  }
6582 
6583  ch = MISDN_ASTERISK_TECH_PVT(ast);
6584  if (!ch) {
6585  ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast_channel_name(ast));
6588  return -1;
6589  }
6590 
6591  newbc = ch->bc;
6592  if (!newbc) {
6593  ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast_channel_name(ast));
6596  return -1;
6597  }
6598 
6599  port = newbc->port;
6600 
6601 #if defined(AST_MISDN_ENHANCEMENTS)
6602  if ((ch->peer = misdn_cc_caller_get(ast))) {
6603  chan_misdn_log(3, port, " --> Found CC caller data, peer:%s\n",
6604  ch->peer->chan ? "available" : "NULL");
6605  }
6606 
6607  if (ch->record_id != -1) {
6608  struct misdn_cc_record *cc_record;
6609 
6610  /* This is a call completion retry call */
6611  AST_LIST_LOCK(&misdn_cc_records_db);
6612  cc_record = misdn_cc_find_by_id(ch->record_id);
6613  if (!cc_record) {
6614  AST_LIST_UNLOCK(&misdn_cc_records_db);
6615  ast_log(LOG_WARNING, " --> ! misdn_call called on %s, cc_record==NULL\n", ast_channel_name(ast));
6618  return -1;
6619  }
6620 
6621  /* Setup calling parameters to retry the call. */
6622  newbc->dialed = cc_record->redial.dialed;
6623  newbc->caller = cc_record->redial.caller;
6624  memset(&newbc->redirecting, 0, sizeof(newbc->redirecting));
6625  newbc->capability = cc_record->redial.capability;
6626  newbc->hdlc = cc_record->redial.hdlc;
6627  newbc->sending_complete = 1;
6628 
6629  if (cc_record->ptp) {
6630  newbc->fac_out.Function = Fac_CCBS_T_Call;
6631  newbc->fac_out.u.CCBS_T_Call.InvokeID = ++misdn_invoke_id;
6632  } else {
6633  newbc->fac_out.Function = Fac_CCBSCall;
6634  newbc->fac_out.u.CCBSCall.InvokeID = ++misdn_invoke_id;
6635  newbc->fac_out.u.CCBSCall.CCBSReference = cc_record->mode.ptmp.reference_id;
6636  }
6637  AST_LIST_UNLOCK(&misdn_cc_records_db);
6638 
6639  ast_channel_exten_set(ast, newbc->dialed.number);
6640 
6641  chan_misdn_log(1, port, "* Call completion to: %s\n", newbc->dialed.number);
6642  chan_misdn_log(2, port, " --> * tech:%s context:%s\n", ast_channel_name(ast), ast_channel_context(ast));
6643  } else
6644 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6645  {
6646  struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
6647 
6648  /*
6649  * dest is ---v
6650  * Dial(mISDN/g:group_name[/extension[/options]])
6651  * Dial(mISDN/port[:preselected_channel][/extension[/options]])
6652  *
6653  * The dial extension could be empty if you are using MISDN_KEYPAD
6654  * to control ISDN provider features.
6655  */
6656  dest_cp = ast_strdupa(dest);
6657  AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
6658  if (!args.ext) {
6659  args.ext = "";
6660  }
6661 
6662  chan_misdn_log(1, port, "* CALL: %s\n", dest);
6663  chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast_channel_name(ast), ast_channel_context(ast));
6664 
6665  ast_channel_exten_set(ast, args.ext);
6666  ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
6667 
6668  if (ast_strlen_zero(newbc->caller.name)
6669  && connected_id.name.valid
6670  && !ast_strlen_zero(connected_id.name.str)) {
6671  ast_copy_string(newbc->caller.name, connected_id.name.str, sizeof(newbc->caller.name));
6672  chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
6673  }
6674  if (ast_strlen_zero(newbc->caller.number)
6675  && connected_id.number.valid
6676  && !ast_strlen_zero(connected_id.number.str)) {
6677  ast_copy_string(newbc->caller.number, connected_id.number.str, sizeof(newbc->caller.number));
6678  chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
6679  }
6680 
6681  misdn_cfg_get(port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
6682  if (append_msn) {
6683  strncat(newbc->incoming_cid_tag, "_", sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
6684  strncat(newbc->incoming_cid_tag, newbc->caller.number, sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
6685  }
6686 
6688 
6689  misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
6690  if (number_type < 0) {
6691  if (connected_id.number.valid) {
6692  newbc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan);
6693  newbc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan);
6694  } else {
6696  newbc->caller.number_plan = NUMPLAN_ISDN;
6697  }
6698  } else {
6699  /* Force us to send in SETUP message */
6700  newbc->caller.number_type = number_type;
6701  newbc->caller.number_plan = NUMPLAN_ISDN;
6702  }
6703  debug_numtype(port, newbc->caller.number_type, "LTON");
6704 
6706  pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
6708  chan_misdn_log(2, port, " --> * Call with flag Digital\n");
6709  }
6710 
6711  /* update caller screening and presentation */
6712  update_config(ch);
6713 
6714  /* fill in some ies from channel dialplan variables */
6715  import_ch(ast, newbc, ch);
6716 
6717  /* Finally The Options Override Everything */
6718  if (!ast_strlen_zero(args.opts)) {
6719  misdn_set_opt_exec(ast, args.opts);
6720  } else {
6721  chan_misdn_log(2, port, "NO OPTS GIVEN\n");
6722  }
6723  if (newbc->set_presentation) {
6724  newbc->caller.presentation = newbc->presentation;
6725  }
6726 
6727  misdn_copy_redirecting_from_ast(newbc, ast);
6728  switch (newbc->outgoing_colp) {
6729  case 1:/* restricted */
6730  case 2:/* blocked */
6731  newbc->redirecting.from.presentation = 1;/* restricted */
6732  break;
6733  default:
6734  break;
6735  }
6736 #if defined(AST_MISDN_ENHANCEMENTS)
6737  if (newbc->redirecting.from.number[0] && misdn_lib_is_ptp(port)) {
6738  if (newbc->redirecting.count < 1) {
6739  newbc->redirecting.count = 1;
6740  }
6741 
6742  /* Create DivertingLegInformation2 facility */
6743  newbc->fac_out.Function = Fac_DivertingLegInformation2;
6744  newbc->fac_out.u.DivertingLegInformation2.InvokeID = ++misdn_invoke_id;
6745  newbc->fac_out.u.DivertingLegInformation2.DivertingPresent = 1;
6746  misdn_PresentedNumberUnscreened_fill(
6747  &newbc->fac_out.u.DivertingLegInformation2.Diverting,
6748  &newbc->redirecting.from);
6749  switch (newbc->outgoing_colp) {
6750  case 2:/* blocked */
6751  /* Block the number going out */
6752  newbc->fac_out.u.DivertingLegInformation2.Diverting.Type = 1;/* presentationRestricted */
6753 
6754  /* Don't tell about any previous diversions or why for that matter. */
6755  newbc->fac_out.u.DivertingLegInformation2.DiversionCounter = 1;
6756  newbc->fac_out.u.DivertingLegInformation2.DiversionReason = 0;/* unknown */
6757  break;
6758  default:
6759  newbc->fac_out.u.DivertingLegInformation2.DiversionCounter =
6760  newbc->redirecting.count;
6761  newbc->fac_out.u.DivertingLegInformation2.DiversionReason =
6762  misdn_to_diversion_reason(newbc->redirecting.reason);
6763  break;
6764  }
6765  newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 0;
6766  if (1 < newbc->fac_out.u.DivertingLegInformation2.DiversionCounter) {
6767  newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 1;
6768  newbc->fac_out.u.DivertingLegInformation2.OriginalCalled.Type = 2;/* numberNotAvailableDueToInterworking */
6769  }
6770 
6771  /*
6772  * Expect a DivertingLegInformation3 to update the COLR of the
6773  * redirecting-to party we are attempting to call now.
6774  */
6775  newbc->div_leg_3_rx_wanted = 1;
6776  }
6777 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6778  }
6779 
6780  exceed = add_out_calls(port);
6781  if (exceed != 0) {
6782  char tmp[16];
6783 
6784  snprintf(tmp, sizeof(tmp), "%d", exceed);
6785  pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
6788  return -1;
6789  }
6790 
6791 #if defined(AST_MISDN_ENHANCEMENTS)
6792  if (newbc->fac_out.Function != Fac_None) {
6793  print_facility(&newbc->fac_out, newbc);
6794  }
6795 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6796  r = misdn_lib_send_event(newbc, EVENT_SETUP);
6797 
6798  /** we should have l3id after sending setup **/
6799  ch->l3id = newbc->l3_id;
6800 
6801  if (r == -ENOCHAN) {
6802  chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
6803  chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
6806  return -1;
6807  }
6808 
6809  chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
6810 
6813 
6814  if (newbc->nt) {
6815  stop_bc_tones(ch);
6816  }
6817 
6818  ch->state = MISDN_CALLING;
6819 
6820  return 0;
6821 }
6822 
6823 
6824 static int misdn_answer(struct ast_channel *ast)
6825 {
6826  struct chan_list *p;
6827  const char *tmp;
6828 
6829  if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
6830  return -1;
6831  }
6832 
6833  chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
6834 
6835  if (!p) {
6836  ast_log(LOG_WARNING, " --> Channel not connected ??\n");
6838  }
6839 
6840  if (!p->bc) {
6841  chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
6842 
6844  }
6845 
6846  ast_channel_lock(ast);
6847  tmp = pbx_builtin_getvar_helper(ast, "CRYPT_KEY");
6848  if (!ast_strlen_zero(tmp)) {
6849  chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
6850  ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
6851  } else {
6852  chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
6853  }
6854 
6855  tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
6856  if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
6857  chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
6858  p->bc->nodsp = 1;
6859  p->bc->hdlc = 0;
6860  p->bc->nojitter = 1;
6861  }
6862  ast_channel_unlock(ast);
6863 
6864  p->state = MISDN_CONNECTED;
6865  stop_indicate(p);
6866 
6867  if (ast_strlen_zero(p->bc->connected.number)) {
6868  chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
6870 
6871  /*
6872  * Use the misdn_set_opt() application to set the presentation
6873  * before we answer or you can use the CONECTEDLINE() function
6874  * to set everything before using the Answer() application.
6875  */
6877  p->bc->connected.screening = 0; /* unscreened */
6880  }
6881 
6882  switch (p->bc->outgoing_colp) {
6883  case 1:/* restricted */
6884  case 2:/* blocked */
6885  p->bc->connected.presentation = 1;/* restricted */
6886  break;
6887  default:
6888  break;
6889  }
6890 
6891 #if defined(AST_MISDN_ENHANCEMENTS)
6892  if (p->bc->div_leg_3_tx_pending) {
6893  p->bc->div_leg_3_tx_pending = 0;
6894 
6895  /* Send DivertingLegInformation3 */
6896  p->bc->fac_out.Function = Fac_DivertingLegInformation3;
6897  p->bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
6898  p->bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
6899  (p->bc->connected.presentation == 0) ? 1 : 0;
6900  print_facility(&p->bc->fac_out, p->bc);
6901  }
6902 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
6904  start_bc_tones(p);
6905 
6906  return 0;
6907 }
6908 
6909 static int misdn_digit_begin(struct ast_channel *chan, char digit)
6910 {
6911  /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
6912  return 0;
6913 }
6914 
6915 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
6916 {
6917  struct chan_list *p;
6918  struct misdn_bchannel *bc;
6919  char buf[2] = { digit, 0 };
6920 
6921  if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
6922  return -1;
6923  }
6924 
6925  bc = p->bc;
6926  chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
6927 
6928  if (!bc) {
6929  ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
6930  return -1;
6931  }
6932 
6933  switch (p->state) {
6934  case MISDN_CALLING:
6935  if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
6936  strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
6937  }
6938  break;
6940  ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
6941  if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
6942  strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
6943  }
6946  break;
6947  default:
6948  if (bc->send_dtmf) {
6949  send_digit_to_chan(p, digit);
6950  }
6951  break;
6952  }
6953 
6954  return 0;
6955 }
6956 
6957 
6958 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
6959 {
6960  struct chan_list *p;
6961 
6962  if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
6963  return -1;
6964  }
6965 
6966  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);
6967 
6968  p->ast = ast;
6969 
6970  return 0;
6971 }
6972 
6973 
6974 
6975 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
6976 {
6977  struct chan_list *p;
6978 
6979  if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
6980  ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
6981  return -1;
6982  }
6983 
6984  if (!p->bc) {
6985  if (p->hold.state == MISDN_HOLD_IDLE) {
6986  chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on %s\n", cond,
6987  ast_channel_name(ast));
6988  ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
6989  } else {
6990  chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on hold %s\n",
6991  cond, ast_channel_name(ast));
6992  }
6993  return -1;
6994  }
6995 
6996  chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] on %s\n", cond, ast_channel_name(ast));
6997 
6998  switch (cond) {
6999  case AST_CONTROL_BUSY:
7000  chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc->pid);
7002 
7004  if (p->state != MISDN_CONNECTED) {
7005  start_bc_tones(p);
7007  }
7008  return -1;
7009  case AST_CONTROL_RING:
7010  chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc->pid);
7011  return -1;
7012  case AST_CONTROL_RINGING:
7013  chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc->pid);
7014  switch (p->state) {
7015  case MISDN_ALERTING:
7016  chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc->pid);
7017  break;
7018  case MISDN_CONNECTED:
7019  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);
7020  return -1;
7021  default:
7022  p->state = MISDN_ALERTING;
7023  chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid);
7025 
7026  chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid);
7028 
7029  if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
7030  chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
7031  } else {
7032  return -1;
7033  }
7034  }
7035  break;
7036  case AST_CONTROL_ANSWER:
7037  chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc->pid);
7038  start_bc_tones(p);
7039  break;
7041  chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc->pid);
7042  return -1;
7043  case AST_CONTROL_OFFHOOK:
7044  chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc->pid);
7045  return -1;
7046  case AST_CONTROL_FLASH:
7047  chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc->pid);
7048  break;
7049  case AST_CONTROL_PROGRESS:
7050  chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc->pid);
7052  break;
7054  chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
7056  break;
7058  chan_misdn_log(1, p->bc->port, " --> *\tincomplete pid:%d\n", p->bc->pid);
7059  if (!p->overlap_dial) {
7060  /* Overlapped dialing not enabled - send hangup */
7062  start_bc_tones(p);
7064 
7065  if (p->bc->nt) {
7067  }
7068  }
7069  break;
7071  chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
7072 
7074  start_bc_tones(p);
7076 
7077  if (p->bc->nt) {
7079  }
7080  break;
7081  case -1 :
7082  chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc->pid);
7083 
7084  stop_indicate(p);
7085 
7086  if (p->state == MISDN_CONNECTED) {
7087  start_bc_tones(p);
7088  }
7089  break;
7090  case AST_CONTROL_HOLD:
7091  ast_moh_start(ast, data, p->mohinterpret);
7092  chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc->pid);
7093  break;
7094  case AST_CONTROL_UNHOLD:
7095  ast_moh_stop(ast);
7096  chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc->pid);
7097  break;
7099  chan_misdn_log(1, p->bc->port, "* IND :\tconnected line update pid:%d\n", p->bc->pid);
7101  break;
7103  chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
7104  misdn_update_redirecting(ast, p->bc, p->originator);
7105  break;
7106  default:
7107  chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
7108  /* fallthrough */
7111  return -1;
7112  }
7113 
7114  return 0;
7115 }
7116 
7117 static int misdn_hangup(struct ast_channel *ast)
7118 {
7119  struct chan_list *p;
7120  struct misdn_bchannel *bc;
7121  const char *var;
7122 
7123  if (!ast) {
7124  return -1;
7125  }
7126 
7127  ast_debug(1, "misdn_hangup(%s)\n", ast_channel_name(ast));
7128 
7129  /* Take the ast_channel's tech_pvt reference. */
7130  ast_mutex_lock(&release_lock);
7131  p = MISDN_ASTERISK_TECH_PVT(ast);
7132  if (!p) {
7133  ast_mutex_unlock(&release_lock);
7134  return -1;
7135  }
7137 
7138  if (!misdn_chan_is_valid(p)) {
7139  ast_mutex_unlock(&release_lock);
7140  chan_list_unref(p, "Release ast_channel reference. Was not active?");
7141  return 0;
7142  }
7143 
7144  if (p->hold.state == MISDN_HOLD_IDLE) {
7145  bc = p->bc;
7146  } else {
7148  bc = misdn_lib_find_held_bc(p->hold.port, p->l3id);
7149  if (!bc) {
7150  chan_misdn_log(4, p->hold.port,
7151  "misdn_hangup: Could not find held bc for (%s)\n", ast_channel_name(ast));
7152  release_chan_early(p);
7153  ast_mutex_unlock(&release_lock);
7154  chan_list_unref(p, "Release ast_channel reference");
7155  return 0;
7156  }
7157  }
7158 
7160  /* between request and call */
7161  ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
7162  release_chan_early(p);
7163  if (bc) {
7164  misdn_lib_release(bc);
7165  }
7166  ast_mutex_unlock(&release_lock);
7167  chan_list_unref(p, "Release ast_channel reference");
7168  return 0;
7169  }
7170  if (!bc) {
7171  ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n",
7172  misdn_get_ch_state(p), p->l3id);
7173  release_chan_early(p);
7174  ast_mutex_unlock(&release_lock);
7175  chan_list_unref(p, "Release ast_channel reference");
7176  return 0;
7177  }
7178 
7179  p->ast = NULL;
7180  p->need_hangup = 0;
7181  p->need_queue_hangup = 0;
7182  p->need_busy = 0;
7183 
7184  if (!bc->nt) {
7185  stop_bc_tones(p);
7186  }
7187 
7189 
7190  /* Channel lock is already held when we are called. */
7191  //ast_channel_lock(ast);
7192  var = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE");
7193  if (!var) {
7194  var = pbx_builtin_getvar_helper(ast, "PRI_CAUSE");
7195  }
7196  if (var) {
7197  int tmpcause;
7198 
7199  tmpcause = atoi(var);
7200  bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
7201  }
7202 
7203  var = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
7204  if (var) {
7205  ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", var);
7206  ast_copy_string(bc->uu, var, sizeof(bc->uu));
7207  bc->uulen = strlen(bc->uu);
7208  }
7209  //ast_channel_unlock(ast);
7210 
7211  chan_misdn_log(1, bc->port,
7212  "* IND : HANGUP\tpid:%d context:%s dialed:%s caller:\"%s\" <%s> State:%s\n",
7213  bc->pid,
7214  ast_channel_context(ast),
7215  ast_channel_exten(ast),
7216  (ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
7217  ? ast_channel_caller(ast)->id.name.str : "",
7218  (ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
7219  ? ast_channel_caller(ast)->id.number.str : "",
7220  misdn_get_ch_state(p));
7221  chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
7222  chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
7223  chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
7224 
7225  switch (p->state) {
7226  case MISDN_INCOMING_SETUP:
7227  /*
7228  * This is the only place in misdn_hangup, where we
7229  * can call release_chan, else it might create a lot of trouble.
7230  */
7231  ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
7232  release_chan(p, bc);
7234  ast_mutex_unlock(&release_lock);
7235  chan_list_unref(p, "Release ast_channel reference");
7236  return 0;
7237  case MISDN_DIALING:
7238  if (p->hold.state == MISDN_HOLD_IDLE) {
7239  start_bc_tones(p);
7241  }
7242 
7243  if (bc->need_disconnect) {
7245  }
7246  break;
7248  if (p->hold.state == MISDN_HOLD_IDLE) {
7249  start_bc_tones(p);
7251  }
7252 
7253  if (bc->need_disconnect) {
7255  }
7256  break;
7257 
7258  case MISDN_CALLING:
7259  case MISDN_ALERTING:
7260  case MISDN_PROGRESS:
7261  case MISDN_PROCEEDING:
7262  if (p->originator != ORG_AST && p->hold.state == MISDN_HOLD_IDLE) {
7264  }
7265 
7266  if (bc->need_disconnect) {
7268  }
7269  break;
7270  case MISDN_CONNECTED:
7271  /* Alerting or Disconnect */
7272  if (bc->nt && p->hold.state == MISDN_HOLD_IDLE) {
7273  start_bc_tones(p);
7276  }
7277  if (bc->need_disconnect) {
7279  }
7280  break;
7281  case MISDN_DISCONNECTED:
7282  if (bc->need_release) {
7284  }
7285  break;
7286 
7287  case MISDN_CLEANING:
7288  ast_mutex_unlock(&release_lock);
7289  chan_list_unref(p, "Release ast_channel reference");
7290  return 0;
7291 
7292  case MISDN_BUSY:
7293  break;
7294  default:
7295  if (bc->nt) {
7296  bc->out_cause = -1;
7297  if (bc->need_release) {
7299  }
7300  } else {
7301  if (bc->need_disconnect) {
7303  }
7304  }
7305  break;
7306  }
7307 
7308  p->state = MISDN_CLEANING;
7309  chan_misdn_log(3, bc->port, " --> Channel: %s hungup new state:%s\n", ast_channel_name(ast),
7310  misdn_get_ch_state(p));
7311 
7312  ast_mutex_unlock(&release_lock);
7313  chan_list_unref(p, "Release ast_channel reference");
7314  return 0;
7315 }
7316 
7317 
7318 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
7319 {
7320  struct ast_frame *f;
7321 
7322  if (tmp->dsp) {
7323  f = ast_dsp_process(tmp->ast, tmp->dsp, frame);
7324  } else {
7325  chan_misdn_log(0, tmp->bc->port, "No DSP-Path found\n");
7326  return NULL;
7327  }
7328 
7329  if (!f || (f->frametype != AST_FRAME_DTMF)) {
7330  return f;
7331  }
7332 
7333  ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass.integer);
7334 
7335  if (tmp->faxdetect && (f->subclass.integer == 'f')) {
7336  /* Fax tone -- Handle and return NULL */
7337  if (!tmp->faxhandled) {
7338  struct ast_channel *ast = tmp->ast;
7339  tmp->faxhandled++;
7340  chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast_channel_name(ast));
7341  tmp->bc->rxgain = 0;
7342  isdn_lib_update_rxgain(tmp->bc);
7343  tmp->bc->txgain = 0;
7344  isdn_lib_update_txgain(tmp->bc);
7345 #ifdef MISDN_1_2
7346  *tmp->bc->pipeline = 0;
7347 #else
7348  tmp->bc->ec_enable = 0;
7349 #endif
7350  isdn_lib_update_ec(tmp->bc);
7351  isdn_lib_stop_dtmf(tmp->bc);
7352  switch (tmp->faxdetect) {
7353  case 1:
7354  if (strcmp(ast_channel_exten(ast), "fax")) {
7355  const char *context;
7356  char context_tmp[BUFFERSIZE];
7357  misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
7358  context = S_OR(context_tmp, S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast)));
7359  if (ast_exists_extension(ast, context, "fax", 1,
7360  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
7361  ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast_channel_name(ast), context);
7362  /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7363  pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast_channel_exten(ast));
7364  if (ast_async_goto(ast, context, "fax", 1)) {
7365  ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), context);
7366  }
7367  } else {
7368  ast_log(LOG_NOTICE, "Fax detected but no fax extension, context:%s exten:%s\n", context, ast_channel_exten(ast));
7369  }
7370  } else {
7371  ast_debug(1, "Already in a fax extension, not redirecting\n");
7372  }
7373  break;
7374  case 2:
7375  ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast_channel_name(ast));
7376  break;
7377  default:
7378  break;
7379  }
7380  } else {
7381  ast_debug(1, "Fax already handled\n");
7382  }
7383  }
7384 
7385  if (tmp->ast_dsp && (f->subclass.integer != 'f')) {
7386  chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass.integer);
7387  }
7388 
7389  return f;
7390 }
7391 
7392 
7393 static struct ast_frame *misdn_read(struct ast_channel *ast)
7394 {
7395  struct chan_list *tmp;
7396  int len, t;
7397  struct pollfd pfd = { .fd = -1, .events = POLLIN };
7398 
7399  if (!ast) {
7400  chan_misdn_log(1, 0, "misdn_read called without ast\n");
7401  return NULL;
7402  }
7403  if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
7404  chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
7405  return NULL;
7406  }
7407 
7408  if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
7409  chan_misdn_log(1, 0, "misdn_read called without bc\n");
7410  return NULL;
7411  }
7412 
7413  pfd.fd = tmp->pipe[0];
7414  t = ast_poll(&pfd, 1, 20);
7415 
7416  if (t < 0) {
7417  chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
7418  return NULL;
7419  }
7420 
7421  if (!t) {
7422  chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
7423  len = 160;
7424  } else if (pfd.revents & POLLIN) {
7425  len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
7426 
7427  if (len <= 0) {
7428  /* we hangup here, since our pipe is closed */
7429  chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
7430  return NULL;
7431  }
7432  } else {
7433  return NULL;
7434  }
7435 
7438  tmp->frame.datalen = len;
7439  tmp->frame.samples = len;
7440  tmp->frame.mallocd = 0;
7441  tmp->frame.offset = 0;
7442  tmp->frame.delivery = ast_tv(0, 0);
7443  tmp->frame.src = NULL;
7444  tmp->frame.data.ptr = tmp->ast_rd_buf;
7445 
7446  if (tmp->faxdetect && !tmp->faxhandled) {
7447  if (tmp->faxdetect_timeout) {
7448  if (ast_tvzero(tmp->faxdetect_tv)) {
7449  tmp->faxdetect_tv = ast_tvnow();
7450  chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
7451  return process_ast_dsp(tmp, &tmp->frame);
7452  } else {
7453  struct timeval tv_now = ast_tvnow();
7454  int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
7455  if (diff <= (tmp->faxdetect_timeout * 1000)) {
7456  chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
7457  return process_ast_dsp(tmp, &tmp->frame);
7458  } else {
7459  chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
7460  tmp->faxdetect = 0;
7461  return &tmp->frame;
7462  }
7463  }
7464  } else {
7465  chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
7466  return process_ast_dsp(tmp, &tmp->frame);
7467  }
7468  } else {
7469  if (tmp->ast_dsp) {
7470  return process_ast_dsp(tmp, &tmp->frame);
7471  } else {
7472  return &tmp->frame;
7473  }
7474  }
7475 }
7476 
7477 
7478 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
7479 {
7480  struct chan_list *ch;
7481 
7482  if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
7483  return -1;
7484  }
7485 
7486  if (ch->hold.state != MISDN_HOLD_IDLE) {
7487  chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
7488  return 0;
7489  }
7490 
7491  if (!ch->bc) {
7492  ast_log(LOG_WARNING, "private but no bc\n");
7493  return -1;
7494  }
7495 
7496  if (ch->notxtone) {
7497  chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
7498  return 0;
7499  }
7500 
7501 
7502  if (!frame->subclass.format) {
7503  chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
7504  return 0;
7505  }
7506 
7508  chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n",
7510  return 0;
7511  }
7512 
7513 
7514  if (!frame->samples) {
7515  chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
7516 
7517  if (!strcmp(frame->src,"ast_prod")) {
7518  chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
7519 
7520  if (ch->ts) {
7521  chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
7523  }
7524  return 0;
7525  }
7526 
7527  return -1;
7528  }
7529 
7530  if (!ch->bc->addr) {
7531  chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
7532  return 0;
7533  }
7534 
7535 #ifdef MISDN_DEBUG
7536  {
7537  int i;
7538  int max = 5 > frame->samples ? frame->samples : 5;
7539 
7540  ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
7541 
7542  for (i = 0; i < max; i++) {
7543  ast_debug(1, "%02hhx ", ((unsigned char *) frame->data.ptr)[i]);
7544  }
7545  }
7546 #endif
7547 
7548  switch (ch->bc->bc_state) {
7549  case BCHAN_ACTIVATED:
7550  case BCHAN_BRIDGED:
7551  break;
7552  default:
7553  if (!ch->dropped_frame_cnt) {
7554  chan_misdn_log(5, ch->bc->port,
7555  "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",
7556  frame->samples, ch->bc->addr, ast_channel_exten(ast),
7557  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""),
7558  misdn_get_ch_state(ch), ch->bc->bc_state, ch->bc->l3_id);
7559  }
7560 
7561  if (++ch->dropped_frame_cnt > 100) {
7562  ch->dropped_frame_cnt = 0;
7563  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);
7564  }
7565 
7566  return 0;
7567  }
7568 
7569  chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
7570  if (!ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability)) {
7571  /* Buffered Transmit (triggered by read from isdn side)*/
7572  if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
7573  if (ch->bc->active) {
7574  cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
7575  }
7576  }
7577 
7578  } else {
7579  /* transmit without jitterbuffer */
7580  misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
7581  }
7582 
7583  return 0;
7584 }
7585 
7586 #if defined(mISDN_NATIVE_BRIDGING)
7587 static enum ast_bridge_result misdn_bridge(struct ast_channel *c0,
7588  struct ast_channel *c1, int flags,
7589  struct ast_frame **fo,
7590  struct ast_channel **rc,
7591  int timeoutms)
7592 {
7593  struct chan_list *ch1, *ch2;
7594  struct ast_channel *carr[2], *who;
7595  int to = -1;
7596  struct ast_frame *f;
7597  int p1_b, p2_b;
7598  int bridging;
7599 
7600  misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
7601  if (!bridging) {
7602  /* Native mISDN bridging globally disabled. */
7603  return AST_BRIDGE_FAILED_NOWARN;
7604  }
7605 
7606  ch1 = get_chan_by_ast(c0);
7607  if (!ch1) {
7608  return AST_BRIDGE_FAILED;
7609  }
7610  ch2 = get_chan_by_ast(c1);
7611  if (!ch2) {
7612  chan_list_unref(ch1, "Failed to find ch2");
7613  return AST_BRIDGE_FAILED;
7614  }
7615 
7616  carr[0] = c0;
7617  carr[1] = c1;
7618 
7619  misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
7620  misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
7621  if (!p1_b || !p2_b) {
7622  ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
7623  chan_list_unref(ch1, "Bridge fallback ch1");
7624  chan_list_unref(ch2, "Bridge fallback ch2");
7625  return AST_BRIDGE_FAILED_NOWARN;
7626  }
7627 
7628  /* make a mISDN_dsp conference */
7629  chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
7630  misdn_lib_bridge(ch1->bc, ch2->bc);
7631 
7632  ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
7633 
7634  chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between \"%s\" <%s> and \"%s\" <%s>\n",
7635  ch1->bc->caller.name,
7636  ch1->bc->caller.number,
7637  ch2->bc->caller.name,
7638  ch2->bc->caller.number);
7639 
7640  if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
7641  ch1->ignore_dtmf = 1;
7642  }
7643 
7644  if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
7645  ch2->ignore_dtmf = 1;
7646  }
7647 
7648  for (;/*ever*/;) {
7649  to = -1;
7650  who = ast_waitfor_n(carr, 2, &to);
7651 
7652  if (!who) {
7653  ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
7654  break;
7655  }
7656  f = ast_read(who);
7657 
7659  /* got hangup .. */
7660 
7661  if (!f) {
7662  chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
7663  } else {
7664  chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass.integer);
7665  }
7666 
7667  *fo = f;
7668  *rc = who;
7669  break;
7670  }
7671 
7672  if (f->frametype == AST_FRAME_DTMF) {
7673  chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass.integer, ast_channel_exten(who));
7674 
7675  *fo = f;
7676  *rc = who;
7677  break;
7678  }
7679 
7680 #if 0
7681  if (f->frametype == AST_FRAME_VOICE) {
7682  chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
7683 
7684  continue;
7685  }
7686 #endif
7687 
7689  ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr, f->datalen);
7690  } else {
7691  ast_write((who == c0) ? c1 : c0, f);
7692  }
7693  }
7694 
7695  chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
7696 
7697  misdn_lib_split_bridge(ch1->bc, ch2->bc);
7698 
7699  chan_list_unref(ch1, "Bridge complete ch1");
7700  chan_list_unref(ch2, "Bridge complete ch2");
7701  return AST_BRIDGE_COMPLETE;
7702 }
7703 #endif /* defined(mISDN_NATIVE_BRIDGING) */
7704 
7705 /** AST INDICATIONS END **/
7706 
7707 static int dialtone_indicate(struct chan_list *cl)
7708 {
7709  struct ast_channel *ast = cl->ast;
7710  int nd = 0;
7711 
7712  if (!ast) {
7713  chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
7714  return -1;
7715  }
7716 
7717  misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
7718 
7719  if (nd) {
7720  chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
7721  return 0;
7722  }
7723 
7724  chan_misdn_log(3, cl->bc->port, " --> Dial\n");
7725 
7726  cl->ts = ast_get_indication_tone(ast_channel_zone(ast), "dial");
7727 
7728  if (cl->ts) {
7729  cl->notxtone = 0;
7730  cl->norxtone = 0;
7731  /* This prods us in misdn_write */
7732  ast_playtones_start(ast, 0, cl->ts->data, 0);
7733  }
7734 
7735  return 0;
7736 }
7737 
7738 static void hanguptone_indicate(struct chan_list *cl)
7739 {
7741 }
7742 
7743 static int stop_indicate(struct chan_list *cl)
7744 {
7745  struct ast_channel *ast = cl->ast;
7746 
7747  if (!ast) {
7748  chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
7749  return -1;
7750  }
7751 
7752  chan_misdn_log(3, cl->bc->port, " --> None\n");
7754  ast_playtones_stop(ast);
7755 
7756  if (cl->ts) {
7757  cl->ts = ast_tone_zone_sound_unref(cl->ts);
7758  }
7759 
7760  return 0;
7761 }
7762 
7763 
7764 static int start_bc_tones(struct chan_list* cl)
7765 {
7767  cl->notxtone = 0;
7768  cl->norxtone = 0;
7769  return 0;
7770 }
7771 
7772 static int stop_bc_tones(struct chan_list *cl)
7773 {
7774  if (!cl) {
7775  return -1;
7776  }
7777 
7778  cl->notxtone = 1;
7779  cl->norxtone = 1;
7780 
7781  return 0;
7782 }
7783 
7784 /*!
7785  * \internal
7786  * \brief Destroy the chan_list object.
7787  *
7788  * \param obj chan_list object to destroy.
7789  *
7790  * \return Nothing
7791  */
7792 static void chan_list_destructor(void *obj)
7793 {
7794  struct chan_list *ch = obj;
7795 
7796 #if defined(AST_MISDN_ENHANCEMENTS)
7797  if (ch->peer) {
7798  ao2_ref(ch->peer, -1);
7799  ch->peer = NULL;
7800  }
7801 #endif /* AST_MISDN_ENHANCEMENTS */
7802 
7803  if (ch->dsp) {
7804  ast_dsp_free(ch->dsp);
7805  ch->dsp = NULL;
7806  }
7807 
7808  /* releasing jitterbuffer */
7809  if (ch->jb) {
7810  misdn_jb_destroy(ch->jb);
7811  ch->jb = NULL;
7812  }
7813 
7814  if (ch->overlap_dial) {
7815  if (ch->overlap_dial_task != -1) {
7817  ch->overlap_dial_task = -1;
7818  }
7820  }
7821 
7822  if (-1 < ch->pipe[0]) {
7823  close(ch->pipe[0]);
7824  }
7825  if (-1 < ch->pipe[1]) {
7826  close(ch->pipe[1]);
7827  }
7828 }
7829 
7830 /*! Returns a reference to the new chan_list. */
7831 static struct chan_list *chan_list_init(int orig)
7832 {
7833  struct chan_list *cl;
7834 
7835  cl = ao2_alloc(sizeof(*cl), chan_list_destructor);
7836  if (!cl) {
7837  chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
7838  return NULL;
7839  }
7840 
7841  cl->originator = orig;
7842  cl->need_queue_hangup = 1;
7843  cl->need_hangup = 1;
7844  cl->need_busy = 1;
7845  cl->overlap_dial_task = -1;
7846 #if defined(AST_MISDN_ENHANCEMENTS)
7847  cl->record_id = -1;
7848 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
7849  cl->pipe[0] = -1;
7850  cl->pipe[1] = -1;
7851 
7852  return cl;
7853 }
7854 
7855 static struct ast_channel *misdn_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
7856 {
7857  struct ast_channel *ast;
7858  char group[BUFFERSIZE + 1] = "";
7859  char dial_str[128];
7860  char *dest_cp;
7861  char *p = NULL;
7862  int channel = 0;
7863  int port = 0;
7864  struct misdn_bchannel *newbc = NULL;
7865  int dec = 0;
7866 #if defined(AST_MISDN_ENHANCEMENTS)
7867  int cc_retry_call = 0; /* TRUE if this is a call completion retry call */
7868  long record_id = -1;
7869  struct misdn_cc_record *cc_record;
7870  const char *err_msg;
7871 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
7872  struct chan_list *cl;
7873 
7875  AST_APP_ARG(intf); /* interface token */
7876  AST_APP_ARG(ext); /* extension token */
7877  AST_APP_ARG(opts); /* options token */
7878  );
7879 
7880  snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, data);
7881 
7882  /*
7883  * data is ---v
7884  * Dial(mISDN/g:group_name[/extension[/options]])
7885  * Dial(mISDN/port[:preselected_channel][/extension[/options]])
7886  * Dial(mISDN/cc/cc-record-id)
7887  *
7888  * The dial extension could be empty if you are using MISDN_KEYPAD
7889  * to control ISDN provider features.
7890  */
7891  dest_cp = ast_strdupa(data);
7892  AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
7893  if (!args.ext) {
7894  args.ext = "";
7895  }
7896 
7897  if (!ast_strlen_zero(args.intf)) {
7898  if (args.intf[0] == 'g' && args.intf[1] == ':') {
7899  /* We make a group call lets checkout which ports are in my group */
7900  args.intf += 2;
7901  ast_copy_string(group, args.intf, sizeof(group));
7902  chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
7903 #if defined(AST_MISDN_ENHANCEMENTS)
7904  } else if (strcmp(args.intf, "cc") == 0) {
7905  cc_retry_call = 1;
7906 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
7907  } else if ((p = strchr(args.intf, ':'))) {
7908  /* we have a preselected channel */
7909  *p++ = 0;
7910  channel = atoi(p);
7911  port = atoi(args.intf);
7912  chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
7913  } else {
7914  port = atoi(args.intf);
7915  }
7916  } else {
7917  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
7918  return NULL;
7919  }
7920 
7921 #if defined(AST_MISDN_ENHANCEMENTS)
7922  if (cc_retry_call) {
7923  if (ast_strlen_zero(args.ext)) {
7924  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT cc-record-id, check extensions.conf\n", dial_str);
7925  return NULL;
7926  }
7927  if (!isdigit(*args.ext)) {
7928  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) cc-record-id must be a number.\n", dial_str);
7929  return NULL;
7930  }
7931  record_id = atol(args.ext);
7932 
7933  AST_LIST_LOCK(&misdn_cc_records_db);
7934  cc_record = misdn_cc_find_by_id(record_id);
7935  if (!cc_record) {
7936  AST_LIST_UNLOCK(&misdn_cc_records_db);
7937  err_msg = misdn_cc_record_not_found;
7938  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
7939  return NULL;
7940  }
7941  if (!cc_record->activated) {
7942  AST_LIST_UNLOCK(&misdn_cc_records_db);
7943  err_msg = "Call completion has not been activated";
7944  ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
7945  return NULL;
7946  }
7947  port = cc_record->port;
7948  AST_LIST_UNLOCK(&misdn_cc_records_db);
7949  }
7950 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
7951 
7953  chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
7954  dec = 1;
7955  }
7956 
7957  if (!ast_strlen_zero(group)) {
7958  char cfg_group[BUFFERSIZE + 1];
7959  struct robin_list *rr = NULL;
7960 
7961  /* Group dial */
7962 
7964  chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
7965  rr = get_robin_position(group);
7966  }
7967 
7968  if (rr) {
7969  int port_start;
7970  int bchan_start;
7971  int port_up;
7972  int check;
7973  int maxbchans;
7974  int wraped = 0;
7975 
7976  if (!rr->port) {
7978  }
7979 
7980  if (!rr->channel) {
7981  rr->channel = 1;
7982  }
7983 
7984  bchan_start = rr->channel;
7985  port_start = rr->port;
7986  do {
7987  misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
7988  if (strcasecmp(cfg_group, group)) {
7989  wraped = 1;
7991  rr->channel = 1;
7992  continue;
7993  }
7994 
7995  misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
7996  port_up = misdn_lib_port_up(rr->port, check);
7997 
7998  if (!port_up) {
7999  chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
8001  rr->channel = 1;
8002  } else if (port_up < 0) {
8003  ast_log(LOG_WARNING, "This port (%d) is blocked\n", rr->port);
8005  rr->channel = 1;
8006  } else {
8007  chan_misdn_log(4, rr->port, "portup\n");
8008  maxbchans = misdn_lib_get_maxchans(rr->port);
8009 
8010  for (;rr->channel <= maxbchans;rr->channel++) {
8011  /* ive come full circle and can stop now */
8012  if (wraped && (rr->port == port_start) && (rr->channel == bchan_start)) {
8013  break;
8014  }
8015 
8016  chan_misdn_log(4, rr->port, "Checking channel %d\n", rr->channel);
8017 
8018  if ((newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0))) {
8019  chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
8020  rr->channel++;
8021  break;
8022  }
8023  }
8024  if (wraped && (rr->port == port_start) && (rr->channel <= bchan_start)) {
8025  break;
8026  } else if (!newbc || (rr->channel == maxbchans)) {
8028  rr->channel = 1;
8029  }
8030 
8031  }
8032  wraped = 1;
8033  } while (!newbc && (rr->port > 0));
8034  } else {
8035  for (port = misdn_cfg_get_next_port(0); port > 0;
8036  port = misdn_cfg_get_next_port(port)) {
8037  misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
8038 
8039  chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
8040  if (!strcasecmp(cfg_group, group)) {
8041  int port_up;
8042  int check;
8043 
8044  misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
8045  port_up = misdn_lib_port_up(port, check);
8046 
8047  chan_misdn_log(4, port, "portup:%d\n", port_up);
8048 
8049  if (port_up > 0) {
8050  newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
8051  if (newbc) {
8052  break;
8053  }
8054  }
8055  }
8056  }
8057  }
8058 
8059  /* Group dial failed ?*/
8060  if (!newbc) {
8062  "Could not Dial out on group '%s'.\n"
8063  "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
8064  "\tOr there was no free channel on none of the ports\n\n",
8065  group);
8066  return NULL;
8067  }
8068  } else {
8069  /* 'Normal' Port dial * Port dial */
8070  if (channel) {
8071  chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
8072  }
8073  newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
8074  if (!newbc) {
8075  ast_log(LOG_WARNING, "Could not create channel on port:%d for Dial(%s)\n", port, dial_str);
8076  return NULL;
8077  }
8078  }
8079 
8080  /* create ast_channel and link all the objects together */
8081  cl = chan_list_init(ORG_AST);
8082  if (!cl) {
8083  misdn_lib_release(newbc);
8084  ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
8085  return NULL;
8086  }
8087  cl->bc = newbc;
8088 
8089  ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, cap, assignedids, requestor, port, channel);
8090  if (!ast) {
8091  chan_list_unref(cl, "Failed to create a new channel");
8092  misdn_lib_release(newbc);
8093  ast_log(LOG_ERROR, "Could not create Asterisk channel for Dial(%s)\n", dial_str);
8094  return NULL;
8095  }
8096 
8097 #if defined(AST_MISDN_ENHANCEMENTS)
8098  cl->record_id = record_id;
8099 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
8100 
8101  /* register chan in local list */
8102  cl_queue_chan(cl);
8103 
8104  /* fill in the config into the objects */
8105  read_config(cl);
8106 
8107  /* important */
8108  cl->need_hangup = 0;
8109 
8110  chan_list_unref(cl, "Successful misdn_request()");
8111  return ast;
8112 }
8113 
8114 
8115 static int misdn_send_text(struct ast_channel *chan, const char *text)
8116 {
8117  struct chan_list *tmp = MISDN_ASTERISK_TECH_PVT(chan);
8118 
8119  if (tmp && tmp->bc) {
8120  ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
8122  } else {
8123  ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
8124  return -1;
8125  }
8126 
8127  return 0;
8128 }
8129 
8130 static struct ast_channel_tech misdn_tech = {
8131  .type = misdn_type,
8132  .description = "Channel driver for mISDN Support (Bri/Pri)",
8133  .requester = misdn_request,
8134  .send_digit_begin = misdn_digit_begin,
8135  .send_digit_end = misdn_digit_end,
8136  .call = misdn_call,
8137  .hangup = misdn_hangup,
8138  .answer = misdn_answer,
8139  .read = misdn_read,
8140  .write = misdn_write,
8141  .indicate = misdn_indication,
8142  .fixup = misdn_fixup,
8143  .send_text = misdn_send_text,
8144  .properties = 0,
8145 };
8146 
8147 
8148 static int glob_channel = 0;
8149 
8150 static void update_name(struct ast_channel *tmp, int port, int c)
8151 {
8152  int chan_offset = 0;
8153  int tmp_port = misdn_cfg_get_next_port(0);
8154  char newname[255];
8155 
8156  for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
8157  if (tmp_port == port) {
8158  break;
8159  }
8160  chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
8161  }
8162  if (c < 0) {
8163  c = 0;
8164  }
8165 
8166  snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
8167  if (strncmp(ast_channel_name(tmp), newname, strlen(newname))) {
8168  snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
8169  ast_change_name(tmp, newname);
8170  chan_misdn_log(3, port, " --> updating channel name to [%s]\n", ast_channel_name(tmp));
8171  }
8172 }
8173 
8174 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int port, int c)
8175 {
8176  struct ast_format_cap *native;
8177  struct ast_channel *tmp;
8178  char *cid_name = NULL;
8179  char *cid_num = NULL;
8180  int chan_offset = 0;
8181  int tmp_port = misdn_cfg_get_next_port(0);
8182  struct ast_format *tmpfmt;
8183 
8185  if (!native) {
8186  return NULL;
8187  }
8188 
8189  for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
8190  if (tmp_port == port) {
8191  break;
8192  }
8193  chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
8194  }
8195  if (c < 0) {
8196  c = 0;
8197  }
8198 
8199  if (callerid) {
8200  ast_callerid_parse(callerid, &cid_name, &cid_num);
8201  }
8202 
8203  tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", assignedids, requestor, 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
8204  if (tmp) {
8205  chan_misdn_log(2, port, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
8206 
8207  tmpfmt = ast_format_cap_get_format(cap, 0);
8209  ast_channel_nativeformats_set(tmp, native);
8210  ast_channel_set_writeformat(tmp, tmpfmt);
8211  ast_channel_set_rawwriteformat(tmp, tmpfmt);
8212  ast_channel_set_readformat(tmp, tmpfmt);
8213  ast_channel_set_rawreadformat(tmp, tmpfmt);
8214 
8215  ao2_ref(tmpfmt, -1);
8216 
8217  /* Link the channel and private together */
8218  chan_list_ref(chlist, "Give a reference to ast_channel");
8219  MISDN_ASTERISK_TECH_PVT_SET(tmp, chlist);
8220  chlist->ast = tmp;
8221 
8222  ast_channel_tech_set(tmp, &misdn_tech);
8223 
8224  ast_channel_priority_set(tmp, 1);
8225 
8226  if (exten) {
8227  ast_channel_exten_set(tmp, exten);
8228  } else {
8229  chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
8230  }
8231 
8232  if (!ast_strlen_zero(cid_num)) {
8233  /* Don't use ast_set_callerid() here because it will
8234  * generate a needless NewCallerID event */
8235  ast_channel_caller(tmp)->ani.number.valid = 1;
8236  ast_channel_caller(tmp)->ani.number.str = ast_strdup(cid_num);
8237  }
8238 
8239  if (pipe(chlist->pipe) < 0) {
8240  ast_log(LOG_ERROR, "Pipe failed\n");
8241  }
8242  ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
8243 
8244  ast_channel_rings_set(tmp, (state == AST_STATE_RING) ? 1 : 0);
8245 
8247 
8248  ast_channel_unlock(tmp);
8249  } else {
8250  chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
8251  }
8252 
8253  ao2_ref(native, -1);
8254 
8255  return tmp;
8256 }
8257 
8258 /*! Returns a reference to the found chan_list. */
8259 static struct chan_list *find_chan_by_bc(struct misdn_bchannel *bc)
8260 {
8261  struct chan_list *help;
8262 
8263  ast_mutex_lock(&cl_te_lock);
8264  for (help = cl_te; help; help = help->next) {
8265  if (help->bc == bc) {
8266  chan_list_ref(help, "Found chan_list by bc");
8267  ast_mutex_unlock(&cl_te_lock);
8268  return help;
8269  }
8270  }
8271  ast_mutex_unlock(&cl_te_lock);
8272 
8273  chan_misdn_log(6, bc->port,
8274  "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
8275  bc->dialed.number,
8276  bc->caller.name,
8277  bc->caller.number);
8278 
8279  return NULL;
8280 }
8281 
8282 /*! Returns a reference to the found chan_list. */
8283 static struct chan_list *find_hold_call(struct misdn_bchannel *bc)
8284 {
8285  struct chan_list *help;
8286 
8287  if (bc->pri) {
8288  return NULL;
8289  }
8290 
8291  chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d dialed:%s caller:\"%s\" <%s>\n",
8292  bc->channel,
8293  bc->dialed.number,
8294  bc->caller.name,
8295  bc->caller.number);
8296  ast_mutex_lock(&cl_te_lock);
8297  for (help = cl_te; help; help = help->next) {
8298  chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
8299  if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
8300  chan_list_ref(help, "Found chan_list hold call");
8301  ast_mutex_unlock(&cl_te_lock);
8302  return help;
8303  }
8304  }
8305  ast_mutex_unlock(&cl_te_lock);
8306  chan_misdn_log(6, bc->port,
8307  "$$$ find_hold_call: No channel found for dialed:%s caller:\"%s\" <%s>\n",
8308  bc->dialed.number,
8309  bc->caller.name,
8310  bc->caller.number);
8311 
8312  return NULL;
8313 }
8314 
8315 
8316 /*! Returns a reference to the found chan_list. */
8317 static struct chan_list *find_hold_call_l3(unsigned long l3_id)
8318 {
8319  struct chan_list *help;
8320 
8321  ast_mutex_lock(&cl_te_lock);
8322  for (help = cl_te; help; help = help->next) {
8323  if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
8324  chan_list_ref(help, "Found chan_list hold call l3");
8325  ast_mutex_unlock(&cl_te_lock);
8326  return help;
8327  }
8328  }
8329  ast_mutex_unlock(&cl_te_lock);
8330 
8331  return NULL;
8332 }
8333 
8334 #define TRANSFER_ON_HELD_CALL_HANGUP 1
8335 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
8336 /*!
8337  * \internal
8338  * \brief Find a suitable active call to go with a held call so we could try a transfer.
8339  *
8340  * \param bc B channel record.
8341  *
8342  * \return Found call record or NULL.
8343  *
8344  * \note Returns a reference to the found chan_list.
8345  *
8346  * \note There could be a possibility where we find the wrong active call to transfer.
8347  * This concern is mitigated by the fact that there could be at most one other call
8348  * on a PTMP BRI link to another device. Maybe the l3_id could help in locating an
8349  * active call on the same TEI?
8350  */
8352 {
8353  struct chan_list *list;
8354 
8355  ast_mutex_lock(&cl_te_lock);
8356  for (list = cl_te; list; list = list->next) {
8357  if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
8358  && list->ast) {
8359  switch (list->state) {
8360  case MISDN_PROCEEDING:
8361  case MISDN_PROGRESS:
8362  case MISDN_ALERTING:
8363  case MISDN_CONNECTED:
8364  chan_list_ref(list, "Found chan_list hold active call");
8365  ast_mutex_unlock(&cl_te_lock);
8366  return list;
8367  default:
8368  break;
8369  }
8370  }
8371  }
8372  ast_mutex_unlock(&cl_te_lock);
8373  return NULL;
8374 }
8375 #endif /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
8376 
8377 static void cl_queue_chan(struct chan_list *chan)
8378 {
8379  chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
8380 
8381  chan_list_ref(chan, "Adding chan_list to list");
8382  ast_mutex_lock(&cl_te_lock);
8383  chan->next = NULL;
8384  if (!cl_te) {
8385  /* List is empty, make head of list. */
8386  cl_te = chan;
8387  } else {
8388  struct chan_list *help;
8389 
8390  /* Put at end of list. */
8391  for (help = cl_te; help->next; help = help->next) {
8392  }
8393  help->next = chan;
8394  }
8395  ast_mutex_unlock(&cl_te_lock);
8396 }
8397 
8398 static int cl_dequeue_chan(struct chan_list *chan)
8399 {
8400  int found_it;
8401  struct chan_list *help;
8402 
8403  ast_mutex_lock(&cl_te_lock);
8404  if (!cl_te) {
8405  /* List is empty. */
8406  ast_mutex_unlock(&cl_te_lock);
8407  return 0;
8408  }
8409 
8410  if (cl_te == chan) {
8411  /* What we want is the head of the list. */
8412  cl_te = cl_te->next;
8413  ast_mutex_unlock(&cl_te_lock);
8414  chan_list_unref(chan, "Removed chan_list from list head");
8415  return 1;
8416  }
8417 
8418  found_it = 0;
8419  for (help = cl_te; help->next; help = help->next) {
8420  if (help->next == chan) {
8421  /* Found it in the list. */
8422  help->next = help->next->next;
8423  found_it = 1;
8424  break;
8425  }
8426  }
8427 
8428  ast_mutex_unlock(&cl_te_lock);
8429  if (found_it) {
8430  chan_list_unref(chan, "Removed chan_list from list");
8431  }
8432  return found_it;
8433 }
8434 
8435 /** Channel Queue End **/
8436 
8437 
8438 static int pbx_start_chan(struct chan_list *ch)
8439 {
8440  int ret = ast_pbx_start(ch->ast);
8441 
8442  ch->need_hangup = (ret >= 0) ? 0 : 1;
8443 
8444  return ret;
8445 }
8446 
8447 static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
8448 {
8449  int port = bc->port;
8450 
8451  if (!ch) {
8452  cb_log(1, port, "Cannot hangup chan, no ch\n");
8453  return;
8454  }
8455 
8456  cb_log(5, port, "hangup_chan called\n");
8457 
8458  if (ch->need_hangup) {
8459  cb_log(2, port, " --> hangup\n");
8460  ch->need_hangup = 0;
8461  ch->need_queue_hangup = 0;
8462  if (ch->ast && send_cause2ast(ch->ast, bc, ch)) {
8463  ast_hangup(ch->ast);
8464  }
8465  return;
8466  }
8467 
8468  if (!ch->need_queue_hangup) {
8469  cb_log(2, port, " --> No need to queue hangup\n");
8470  return;
8471  }
8472 
8473  ch->need_queue_hangup = 0;
8474  if (ch->ast) {
8475  if (send_cause2ast(ch->ast, bc, ch)) {
8477  cb_log(2, port, " --> queue_hangup\n");
8478  }
8479  } else {
8480  cb_log(1, port, "Cannot hangup chan, no ast\n");
8481  }
8482 }
8483 
8484 /*!
8485  * \internal
8486  * \brief ISDN asked us to release channel, pendant to misdn_hangup.
8487  *
8488  * \param ch Call channel record to release.
8489  * \param bc Current B channel record associated with ch.
8490  *
8491  * \return Nothing
8492  *
8493  * \note The only valid thing to do with ch after calling is to chan_list_unref(ch, "").
8494  */
8495 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
8496 {
8497  struct ast_channel *ast;
8498 
8499  chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
8500 
8501  ast_mutex_lock(&release_lock);
8502  for (;;) {
8503  ast = ch->ast;
8504  if (!ast || !ast_channel_trylock(ast)) {
8505  break;
8506  }
8507  DEADLOCK_AVOIDANCE(&release_lock);
8508  }
8509  if (!cl_dequeue_chan(ch)) {
8510  /* Someone already released it. */
8511  if (ast) {
8512  ast_channel_unlock(ast);
8513  }
8514  ast_mutex_unlock(&release_lock);
8515  return;
8516  }
8517  ch->state = MISDN_CLEANING;
8518  ch->ast = NULL;
8519  if (ast) {
8520  struct chan_list *ast_ch;
8521 
8522  ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
8524  chan_misdn_log(1, bc->port,
8525  "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n",
8526  bc->pid,
8527  ast_channel_context(ast),
8528  ast_channel_exten(ast),
8529  S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, ""),
8530  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""));
8531 
8532  if (ast_channel_state(ast) != AST_STATE_RESERVED) {
8533  chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
8535  }
8536  ast_channel_unlock(ast);
8537  if (ast_ch) {
8538  chan_list_unref(ast_ch, "Release ast_channel reference.");
8539  }
8540  }
8541 
8542  if (ch->originator == ORG_AST) {
8543  --misdn_out_calls[bc->port];
8544  } else {
8545  --misdn_in_calls[bc->port];
8546  }
8547 
8548  ast_mutex_unlock(&release_lock);
8549 }
8550 
8551 /*!
8552  * \internal
8553  * \brief Do everything in release_chan() that makes sense without a bc.
8554  *
8555  * \param ch Call channel record to release.
8556  *
8557  * \return Nothing
8558  *
8559  * \note The only valid thing to do with ch after calling is to chan_list_unref(ch, "").
8560  */
8561 static void release_chan_early(struct chan_list *ch)
8562 {
8563  struct ast_channel *ast;
8564 
8565  ast_mutex_lock(&release_lock);
8566  for (;;) {
8567  ast = ch->ast;
8568  if (!ast || !ast_channel_trylock(ast)) {
8569  break;
8570  }
8571  DEADLOCK_AVOIDANCE(&release_lock);
8572  }
8573  if (!cl_dequeue_chan(ch)) {
8574  /* Someone already released it. */
8575  if (ast) {
8576  ast_channel_unlock(ast);
8577  }
8578  ast_mutex_unlock(&release_lock);
8579  return;
8580  }
8581  ch->state = MISDN_CLEANING;
8582  ch->ast = NULL;
8583  if (ast) {
8584  struct chan_list *ast_ch;
8585 
8586  ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
8588 
8589  if (ast_channel_state(ast) != AST_STATE_RESERVED) {
8591  }
8592  ast_channel_unlock(ast);
8593  if (ast_ch) {
8594  chan_list_unref(ast_ch, "Release ast_channel reference.");
8595  }
8596  }
8597 
8598  if (ch->hold.state != MISDN_HOLD_IDLE) {
8599  if (ch->originator == ORG_AST) {
8600  --misdn_out_calls[ch->hold.port];
8601  } else {
8602  --misdn_in_calls[ch->hold.port];
8603  }
8604  }
8605 
8606  ast_mutex_unlock(&release_lock);
8607 }
8608 
8609 /*!
8610  * \internal
8611  * \brief Attempt to transfer the active channel party to the held channel party.
8612  *
8613  * \param active_ch Channel currently connected.
8614  * \param held_ch Channel currently on hold.
8615  *
8616  * \retval 0 on success.
8617  * \retval -1 on error.
8618  */
8619 static int misdn_attempt_transfer(struct chan_list *active_ch, struct chan_list *held_ch)
8620 {
8621  int retval;
8622  enum ast_transfer_result xfer_res;
8623  struct ast_channel *to_target;
8624  struct ast_channel *to_transferee;
8625 
8626  switch (active_ch->state) {
8627  case MISDN_PROCEEDING:
8628  case MISDN_PROGRESS:
8629  case MISDN_ALERTING:
8630  case MISDN_CONNECTED:
8631  break;
8632  default:
8633  return -1;
8634  }
8635 
8636  ast_channel_lock_both(held_ch->ast, active_ch->ast);
8637  to_target = active_ch->ast;
8638  to_transferee = held_ch->ast;
8639  chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
8640  ast_channel_name(to_transferee), ast_channel_name(to_target));
8641  held_ch->hold.state = MISDN_HOLD_TRANSFER;
8642  ast_channel_ref(to_target);
8643  ast_channel_ref(to_transferee);
8644  ast_channel_unlock(to_target);
8645  ast_channel_unlock(to_transferee);
8646 
8647  retval = 0;
8648  xfer_res = ast_bridge_transfer_attended(to_transferee, to_target);
8649  if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
8650  retval = -1;
8651  }
8652 
8653  ast_channel_unref(to_target);
8654  ast_channel_unref(to_transferee);
8655  return retval;
8656 }
8657 
8658 
8659 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
8660 {
8661  char *predial;
8662  struct ast_frame fr;
8663 
8664  predial = ast_strdupa(ast_channel_exten(ast));
8665 
8666  ch->state = MISDN_DIALING;
8667 
8668  if (!ch->noautorespond_on_setup) {
8669  if (bc->nt) {
8671  } else {
8672  if (misdn_lib_is_ptp(bc->port)) {
8674  } else {
8676  }
8677  }
8678  } else {
8680  }
8681 
8682  chan_misdn_log(1, bc->port,
8683  "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
8684  ast_channel_context(ast),
8685  ast_channel_exten(ast),
8686  (ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
8687  ? ast_channel_caller(ast)->id.name.str : "",
8688  (ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
8689  ? ast_channel_caller(ast)->id.number.str : "");
8690 
8691  ast_channel_exten_set(ast, "s");
8692 
8693  if (!ast_canmatch_extension(ast, ast_channel_context(ast), ast_channel_exten(ast), 1, bc->caller.number) || pbx_start_chan(ch) < 0) {
8694  ast = NULL;
8696  hangup_chan(ch, bc);
8697  hanguptone_indicate(ch);
8698 
8700  }
8701 
8702 
8703  while (!ast_strlen_zero(predial)) {
8705  fr.subclass.integer = *predial;
8706  fr.src = NULL;
8707  fr.data.ptr = NULL;
8708  fr.datalen = 0;
8709  fr.samples = 0;
8710  fr.mallocd = 0;
8711  fr.offset = 0;
8712  fr.delivery = ast_tv(0,0);
8713 
8714  if (ch->ast && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
8715  ast_queue_frame(ch->ast, &fr);
8716  }
8717  predial++;
8718  }
8719 }
8720 
8721 /*!
8722  * \retval -1 if can hangup after calling.
8723  * \retval 0 if cannot hangup after calling.
8724  */
8725 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
8726 {
8727  int can_hangup;
8728 
8729  if (!ast) {
8730  chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
8731  return 0;
8732  }
8733  if (!bc) {
8734  chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
8735  return 0;
8736  }
8737  if (!ch) {
8738  chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
8739  return 0;
8740  }
8741 
8743 
8744  can_hangup = -1;
8745  switch (bc->cause) {
8746  case AST_CAUSE_UNALLOCATED:
8749  case 4: /* Send special information tone */
8752  /* Congestion Cases */
8753  /*
8754  * Not Queueing the Congestion anymore, since we want to hear
8755  * the inband message
8756  *
8757  chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
8758  ch->state = MISDN_BUSY;
8759 
8760  ast_queue_control(ast, AST_CONTROL_CONGESTION);
8761  */
8762  break;
8763 
8765  case AST_CAUSE_USER_BUSY:
8766  ch->state = MISDN_BUSY;
8767 
8768  if (!ch->need_busy) {
8769  chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
8770  break;
8771  }
8772  ch->need_busy = 0;
8773 
8774  chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
8776 
8777  /* The BUSY is likely to cause a hangup or the user needs to hear it. */
8778  can_hangup = 0;
8779  break;
8780  }
8781  return can_hangup;
8782 }
8783 
8784 
8785 /*! \brief Import parameters from the dialplan environment variables */
8786 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
8787 {
8788  const char *tmp;
8789 
8790  ast_channel_lock(chan);
8791  tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
8792  if (tmp && (atoi(tmp) == 1)) {
8793  bc->sending_complete = 1;
8794  }
8795 
8796  tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
8797  if (tmp) {
8798  ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
8799  ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
8800  bc->uulen = strlen(bc->uu);
8801  }
8802 
8803  tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
8804  if (tmp) {
8805  ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
8806  }
8807  ast_channel_unlock(chan);
8808 }
8809 
8810 /*! \brief Export parameters to the dialplan environment variables */
8811 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
8812 {
8813  char tmp[32];
8814 
8815  /*
8816  * The only use for MISDN_PID is if there is a problem and you
8817  * have to use the "misdn restart pid" CLI command. Otherwise,
8818  * the pid is not used by anyone. The internal use of MISDN_PID
8819  * has been deleted.
8820  */
8821  chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
8822  snprintf(tmp, sizeof(tmp), "%d", bc->pid);
8823  pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
8824 
8825  if (bc->sending_complete) {
8826  snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
8827  pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
8828  }
8829 
8830  if (bc->urate) {
8831  snprintf(tmp, sizeof(tmp), "%d", bc->urate);
8832  pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
8833  }
8834 
8835  if (bc->uulen) {
8836  pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
8837  }
8838 
8839  if (!ast_strlen_zero(bc->keypad)) {
8840  pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
8841  }
8842 }
8843 
8844 int add_in_calls(int port)
8845 {
8846  int max_in_calls;
8847 
8848  misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
8849  misdn_in_calls[port]++;
8850 
8851  if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
8852  ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
8853  return misdn_in_calls[port] - max_in_calls;
8854  }
8855 
8856  return 0;
8857 }
8858 
8859 int add_out_calls(int port)
8860 {
8861  int max_out_calls;
8862 
8863  misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
8864 
8865  if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
8866  ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
8867  return (misdn_out_calls[port] + 1) - max_out_calls;
8868  }
8869 
8870  misdn_out_calls[port]++;
8871 
8872  return 0;
8873 }
8874 
8875 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
8876 {
8877  if (pbx_start_chan(ch) < 0) {
8878  hangup_chan(ch, bc);
8879  chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
8880  if (bc->nt) {
8881  hanguptone_indicate(ch);
8883  } else {
8885  }
8886  }
8887 }
8888 
8889 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
8890 {
8891  ch->state = MISDN_WAITING4DIGS;
8893  if (bc->nt && !bc->dialed.number[0]) {
8894  dialtone_indicate(ch);
8895  }
8896 }
8897 
8898 #if defined(AST_MISDN_ENHANCEMENTS)
8899 /*!
8900  * \internal
8901  * \brief Handle the FACILITY CCBSStatusRequest message.
8902  *
8903  * \param port Logical port number.
8904  * \param facility Facility ie contents.
8905  *
8906  * \return Nothing
8907  */
8908 static void misdn_cc_handle_ccbs_status_request(int port, const struct FacParm *facility)
8909 {
8910  struct misdn_cc_record *cc_record;
8911  struct misdn_bchannel dummy;
8912 
8913  switch (facility->u.CCBSStatusRequest.ComponentType) {
8914  case FacComponent_Invoke:
8915  /* Build message */
8916  misdn_make_dummy(&dummy, port, 0, misdn_lib_port_is_nt(port), 0);
8917  dummy.fac_out.Function = Fac_CCBSStatusRequest;
8918  dummy.fac_out.u.CCBSStatusRequest.InvokeID = facility->u.CCBSStatusRequest.InvokeID;
8919  dummy.fac_out.u.CCBSStatusRequest.ComponentType = FacComponent_Result;
8920 
8921  /* Answer User-A free question */
8922  AST_LIST_LOCK(&misdn_cc_records_db);
8923  cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSStatusRequest.Component.Invoke.CCBSReference);
8924  if (cc_record) {
8925  dummy.fac_out.u.CCBSStatusRequest.Component.Result.Free = cc_record->party_a_free;
8926  } else {
8927  /* No record so say User-A is free */
8928  dummy.fac_out.u.CCBSStatusRequest.Component.Result.Free = 1;
8929  }
8930  AST_LIST_UNLOCK(&misdn_cc_records_db);
8931 
8932  /* Send message */
8933  print_facility(&dummy.fac_out, &dummy);
8935  break;
8936 
8937  default:
8938  chan_misdn_log(0, port, " --> not yet handled: facility type:0x%04X\n", facility->Function);
8939  break;
8940  }
8941 }
8942 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
8943 
8944 #if defined(AST_MISDN_ENHANCEMENTS)
8945 /*!
8946  * \internal
8947  * \brief Start a PBX to notify that User-B is available.
8948  *
8949  * \param record_id Call completion record ID
8950  * \param notify Dialplan location to start processing.
8951  *
8952  * \return Nothing
8953  */
8954 static void misdn_cc_pbx_notify(long record_id, const struct misdn_cc_notify *notify)
8955 {
8956  struct ast_channel *chan;
8957  char id_str[32];
8958 
8959  static unsigned short sequence = 0;
8960 
8961  /* Create a channel to notify with */
8962  snprintf(id_str, sizeof(id_str), "%ld", record_id);
8963  chan = ast_channel_alloc(0, AST_STATE_DOWN, id_str, NULL, NULL,
8964  notify->exten, notify->context, NULL, 0,
8965  "mISDN-CC/%ld-%X", record_id, (unsigned) ++sequence);
8966  if (!chan) {
8967  ast_log(LOG_ERROR, "Unable to allocate channel!\n");
8968  return;
8969  }
8970  ast_channel_priority_set(chan, notify->priority);
8971  ast_free(ast_channel_dialed(chan)->number.str);
8972  ast_channel_dialed(chan)->number.str = ast_strdup(notify->exten);
8973 
8974  ast_channel_unlock(chan);
8975 
8976  if (ast_pbx_start(chan)) {
8977  ast_log(LOG_WARNING, "Unable to start pbx channel %s!\n", ast_channel_name(chan));
8978  ast_channel_release(chan);
8979  } else {
8980  ast_verb(1, "Started pbx for call completion notify channel %s\n", ast_channel_name(chan));
8981  }
8982 }
8983 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
8984 
8985 #if defined(AST_MISDN_ENHANCEMENTS)
8986 /*!
8987  * \internal
8988  * \brief Handle the FACILITY CCBS_T_RemoteUserFree message.
8989  *
8990  * \param bc B channel control structure message came in on
8991  *
8992  * \return Nothing
8993  */
8994 static void misdn_cc_handle_T_remote_user_free(struct misdn_bchannel *bc)
8995 {
8996  struct misdn_cc_record *cc_record;
8997  struct misdn_cc_notify notify;
8998  long record_id;
8999 
9000  AST_LIST_LOCK(&misdn_cc_records_db);
9001  cc_record = misdn_cc_find_by_bc(bc);
9002  if (cc_record) {
9003  if (cc_record->party_a_free) {
9004  notify = cc_record->remote_user_free;
9005  } else {
9006  /* Send CCBS_T_Suspend message */
9007  bc->fac_out.Function = Fac_CCBS_T_Suspend;
9008  bc->fac_out.u.CCBS_T_Suspend.InvokeID = ++misdn_invoke_id;
9009  print_facility(&bc->fac_out, bc);
9011 
9012  notify = cc_record->b_free;
9013  }
9014  record_id = cc_record->record_id;
9015  AST_LIST_UNLOCK(&misdn_cc_records_db);
9016  if (notify.context[0]) {
9017  /* Party A is free or B-Free notify has been setup. */
9018  misdn_cc_pbx_notify(record_id, &notify);
9019  }
9020  } else {
9021  AST_LIST_UNLOCK(&misdn_cc_records_db);
9022  }
9023 }
9024 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9025 
9026 #if defined(AST_MISDN_ENHANCEMENTS)
9027 /*!
9028  * \internal
9029  * \brief Handle the FACILITY CCBSRemoteUserFree message.
9030  *
9031  * \param port Logical port number.
9032  * \param facility Facility ie contents.
9033  *
9034  * \return Nothing
9035  */
9036 static void misdn_cc_handle_remote_user_free(int port, const struct FacParm *facility)
9037 {
9038  struct misdn_cc_record *cc_record;
9039  struct misdn_cc_notify notify;
9040  long record_id;
9041 
9042  AST_LIST_LOCK(&misdn_cc_records_db);
9043  cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSRemoteUserFree.CCBSReference);
9044  if (cc_record) {
9045  notify = cc_record->remote_user_free;
9046  record_id = cc_record->record_id;
9047  AST_LIST_UNLOCK(&misdn_cc_records_db);
9048  misdn_cc_pbx_notify(record_id, &notify);
9049  } else {
9050  AST_LIST_UNLOCK(&misdn_cc_records_db);
9051  }
9052 }
9053 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9054 
9055 #if defined(AST_MISDN_ENHANCEMENTS)
9056 /*!
9057  * \internal
9058  * \brief Handle the FACILITY CCBSBFree message.
9059  *
9060  * \param port Logical port number.
9061  * \param facility Facility ie contents.
9062  *
9063  * \return Nothing
9064  */
9065 static void misdn_cc_handle_b_free(int port, const struct FacParm *facility)
9066 {
9067  struct misdn_cc_record *cc_record;
9068  struct misdn_cc_notify notify;
9069  long record_id;
9070 
9071  AST_LIST_LOCK(&misdn_cc_records_db);
9072  cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSBFree.CCBSReference);
9073  if (cc_record && cc_record->b_free.context[0]) {
9074  /* B-Free notify has been setup. */
9075  notify = cc_record->b_free;
9076  record_id = cc_record->record_id;
9077  AST_LIST_UNLOCK(&misdn_cc_records_db);
9078  misdn_cc_pbx_notify(record_id, &notify);
9079  } else {
9080  AST_LIST_UNLOCK(&misdn_cc_records_db);
9081  }
9082 }
9083 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9084 
9085 /*!
9086  * \internal
9087  * \brief Handle the incoming facility ie contents
9088  *
9089  * \param event Message type facility ie came in on
9090  * \param bc B channel control structure message came in on
9091  * \param ch Associated channel call record
9092  *
9093  * \return Nothing
9094  */
9095 static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel *bc, struct chan_list *ch)
9096 {
9097 #if defined(AST_MISDN_ENHANCEMENTS)
9098  const char *diagnostic_msg;
9099  struct misdn_cc_record *cc_record;
9100  char buf[32];
9101  struct misdn_party_id party_id;
9102  long new_record_id;
9103 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9104 
9105  print_facility(&bc->fac_in, bc);
9106  switch (bc->fac_in.Function) {
9107 #if defined(AST_MISDN_ENHANCEMENTS)
9108  case Fac_ActivationDiversion:
9109  switch (bc->fac_in.u.ActivationDiversion.ComponentType) {
9110  case FacComponent_Result:
9111  /* Positive ACK to activation */
9112  /* We don't handle this yet */
9113  break;
9114  default:
9115  chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
9116  bc->fac_in.Function);
9117  break;
9118  }
9119  break;
9120  case Fac_DeactivationDiversion:
9121  switch (bc->fac_in.u.DeactivationDiversion.ComponentType) {
9122  case FacComponent_Result:
9123  /* Positive ACK to deactivation */
9124  /* We don't handle this yet */
9125  break;
9126  default:
9127  chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
9128  bc->fac_in.Function);
9129  break;
9130  }
9131  break;
9132  case Fac_ActivationStatusNotificationDiv:
9133  /* Sent to other MSN numbers on the line when a user activates call forwarding. */
9134  /* Sent in the first call control message of an outgoing call from the served user. */
9135  /* We do not have anything to do for this message. */
9136  break;
9137  case Fac_DeactivationStatusNotificationDiv:
9138  /* Sent to other MSN numbers on the line when a user deactivates call forwarding. */
9139  /* We do not have anything to do for this message. */
9140  break;
9141 #if 0 /* We don't handle this yet */
9142  case Fac_InterrogationDiversion:
9143  /* We don't handle this yet */
9144  break;
9145  case Fac_InterrogateServedUserNumbers:
9146  /* We don't handle this yet */
9147  break;
9148 #endif /* We don't handle this yet */
9149  case Fac_DiversionInformation:
9150  /* Sent to the served user when a call is forwarded. */
9151  /* We do not have anything to do for this message. */
9152  break;
9153  case Fac_CallDeflection:
9154  if (ch && ch->ast) {
9155  switch (bc->fac_in.u.CallDeflection.ComponentType) {
9156  case FacComponent_Invoke:
9158  sizeof(bc->redirecting.from.number));
9159  bc->redirecting.from.name[0] = 0;
9162  bc->redirecting.from.screening = 0;/* Unscreened */
9163  if (bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
9165  bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser
9166  ? 0 /* Allowed */ : 1 /* Restricted */;
9167  } else {
9168  bc->redirecting.from.presentation = 0;/* Allowed */
9169  }
9170 
9171  /* Add configured prefix to the call deflection number */
9172  memset(&party_id, 0, sizeof(party_id));
9173  misdn_PartyNumber_extract(&party_id,
9174  &bc->fac_in.u.CallDeflection.Component.Invoke.Deflection.Party);
9176  party_id.number, sizeof(party_id.number));
9177  //party_id.presentation = 0;/* Allowed */
9178  //party_id.screening = 0;/* Unscreened */
9179  bc->redirecting.to = party_id;
9180 
9181  ++bc->redirecting.count;
9183 
9185  ast_channel_call_forward_set(ch->ast, bc->redirecting.to.number);
9186 
9187  /* Send back positive ACK */
9188 #if 1
9189  /*
9190  * Since there are no return result arguments it must be a
9191  * generic result message. ETSI 300-196
9192  */
9193  bc->fac_out.Function = Fac_RESULT;
9194  bc->fac_out.u.RESULT.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
9195 #else
9196  bc->fac_out.Function = Fac_CallDeflection;
9197  bc->fac_out.u.CallDeflection.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
9198  bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Result;
9199 #endif
9200  print_facility(&bc->fac_out, bc);
9202 
9203  /* This line is BUSY to further attempts by this dialing attempt. */
9205  break;
9206 
9207  case FacComponent_Result:
9208  /* Positive ACK to call deflection */
9209  /*
9210  * Sent in DISCONNECT or FACILITY message depending upon network option.
9211  * It is in the FACILITY message if the call is still offered to the user
9212  * while trying to alert the deflected to party.
9213  */
9214  /* Ignore the ACK */
9215  break;
9216 
9217  default:
9218  break;
9219  }
9220  }
9221  break;
9222 #if 0 /* We don't handle this yet */
9223  case Fac_CallRerouteing:
9224  /* Private-Public ISDN interworking message */
9225  /* We don't handle this yet */
9226  break;
9227 #endif /* We don't handle this yet */
9228  case Fac_DivertingLegInformation1:
9229  /* Private-Public ISDN interworking message */
9230  bc->div_leg_3_rx_wanted = 0;
9231  if (ch && ch->ast) {
9232  bc->redirecting.reason =
9233  diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation1.DiversionReason);
9234  if (bc->fac_in.u.DivertingLegInformation1.DivertedToPresent) {
9235  misdn_PresentedNumberUnscreened_extract(&bc->redirecting.to,
9236  &bc->fac_in.u.DivertingLegInformation1.DivertedTo);
9237 
9238  /* Add configured prefix to redirecting.to.number */
9240  bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
9241  } else {
9242  bc->redirecting.to.number[0] = '\0';
9245  bc->redirecting.to.presentation = 1;/* restricted */
9246  bc->redirecting.to.screening = 0;/* unscreened */
9247  }
9249  bc->div_leg_3_rx_wanted = 1;
9250  }
9251  break;
9252  case Fac_DivertingLegInformation2:
9253  /* Private-Public ISDN interworking message */
9254  switch (event) {
9255  case EVENT_SETUP:
9256  /* Comes in on a SETUP with redirecting.from information */
9257  bc->div_leg_3_tx_pending = 1;
9258  if (ch && ch->ast) {
9259  /*
9260  * Setup the redirecting.to informtion so we can identify
9261  * if the user wants to manually supply the COLR for this
9262  * redirected to number if further redirects could happen.
9263  *
9264  * All the user needs to do is set the REDIRECTING(to-pres)
9265  * to the COLR and REDIRECTING(to-num) = ${EXTEN} to be safe
9266  * after determining that the incoming call was redirected by
9267  * checking if there is a REDIRECTING(from-num).
9268  */
9270  sizeof(bc->redirecting.to.number));
9273  bc->redirecting.to.presentation = 1;/* restricted */
9274  bc->redirecting.to.screening = 0;/* unscreened */
9275 
9276  bc->redirecting.reason =
9277  diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation2.DiversionReason);
9278  bc->redirecting.count = bc->fac_in.u.DivertingLegInformation2.DiversionCounter;
9279  if (bc->fac_in.u.DivertingLegInformation2.DivertingPresent) {
9280  /* This information is redundant if there was a redirecting ie in the SETUP. */
9281  misdn_PresentedNumberUnscreened_extract(&bc->redirecting.from,
9282  &bc->fac_in.u.DivertingLegInformation2.Diverting);
9283 
9284  /* Add configured prefix to redirecting.from.number */
9286  bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
9287  }
9288 #if 0
9289  if (bc->fac_in.u.DivertingLegInformation2.OriginalCalledPresent) {
9290  /* We have no place to put the OriginalCalled number */
9291  }
9292 #endif
9294  }
9295  break;
9296  default:
9297  chan_misdn_log(0, bc->port," --> Expected in a SETUP message: facility type:0x%04X\n",
9298  bc->fac_in.Function);
9299  break;
9300  }
9301  break;
9302  case Fac_DivertingLegInformation3:
9303  /* Private-Public ISDN interworking message */
9304  if (bc->div_leg_3_rx_wanted) {
9305  bc->div_leg_3_rx_wanted = 0;
9306 
9307  if (ch && ch->ast) {
9308  struct ast_party_redirecting redirecting;
9309 
9311  bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator
9314  ast_party_redirecting_init(&redirecting);
9316 
9317  /*
9318  * Reset any earlier private redirecting id representations and
9319  * make sure that it is invalidated at the remote end.
9320  */
9321  ast_party_id_reset(&redirecting.priv_orig);
9322  ast_party_id_reset(&redirecting.priv_from);
9323  ast_party_id_reset(&redirecting.priv_to);
9324 
9325  ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
9326  ast_party_redirecting_free(&redirecting);
9327  }
9328  }
9329  break;
9330 
9331 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
9332 
9333  case Fac_CD:
9334  if (ch && ch->ast) {
9336  sizeof(bc->redirecting.from.number));
9337  bc->redirecting.from.name[0] = 0;
9340  bc->redirecting.from.screening = 0;/* Unscreened */
9342  bc->fac_in.u.CDeflection.PresentationAllowed
9343  ? 0 /* Allowed */ : 1 /* Restricted */;
9344 
9346  (char *) bc->fac_in.u.CDeflection.DeflectedToNumber,
9347  sizeof(bc->redirecting.to.number));
9348  bc->redirecting.to.name[0] = 0;
9351  bc->redirecting.to.presentation = 0;/* Allowed */
9352  bc->redirecting.to.screening = 0;/* Unscreened */
9353 
9354  ++bc->redirecting.count;
9356 
9358  ast_channel_call_forward_set(ch->ast, bc->redirecting.to.number);
9359 
9361 
9362  /* This line is BUSY to further attempts by this dialing attempt. */
9364  }
9365  break;
9366 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
9367  case Fac_AOCDCurrency:
9368  if (ch && ch->ast) {
9369  bc->AOCDtype = Fac_AOCDCurrency;
9370  memcpy(&bc->AOCD.currency, &bc->fac_in.u.AOCDcur, sizeof(bc->AOCD.currency));
9371  bc->AOCD_need_export = 1;
9372  export_aoc_vars(ch->originator, ch->ast, bc);
9373  }
9374  break;
9375  case Fac_AOCDChargingUnit:
9376  if (ch && ch->ast) {
9377  bc->AOCDtype = Fac_AOCDChargingUnit;
9378  memcpy(&bc->AOCD.chargingUnit, &bc->fac_in.u.AOCDchu, sizeof(bc->AOCD.chargingUnit));
9379  bc->AOCD_need_export = 1;
9380  export_aoc_vars(ch->originator, ch->ast, bc);
9381  }
9382  break;
9383 #if defined(AST_MISDN_ENHANCEMENTS)
9384  case Fac_ERROR:
9385  diagnostic_msg = misdn_to_str_error_code(bc->fac_in.u.ERROR.errorValue);
9386  chan_misdn_log(1, bc->port, " --> Facility error code: %s\n", diagnostic_msg);
9387  switch (event) {
9388  case EVENT_DISCONNECT:
9389  case EVENT_RELEASE:
9391  /* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
9392  if (ch && ch->peer) {
9393  misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
9394  }
9395  break;
9396  default:
9397  break;
9398  }
9399  AST_LIST_LOCK(&misdn_cc_records_db);
9400  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.ERROR.invokeId);
9401  if (cc_record) {
9402  cc_record->outstanding_message = 0;
9403  cc_record->error_code = bc->fac_in.u.ERROR.errorValue;
9404  }
9405  AST_LIST_UNLOCK(&misdn_cc_records_db);
9406  break;
9407  case Fac_REJECT:
9408  diagnostic_msg = misdn_to_str_reject_code(bc->fac_in.u.REJECT.Code);
9409  chan_misdn_log(1, bc->port, " --> Facility reject code: %s\n", diagnostic_msg);
9410  switch (event) {
9411  case EVENT_DISCONNECT:
9412  case EVENT_RELEASE:
9414  /* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
9415  if (ch && ch->peer) {
9416  misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
9417  }
9418  break;
9419  default:
9420  break;
9421  }
9422  if (bc->fac_in.u.REJECT.InvokeIDPresent) {
9423  AST_LIST_LOCK(&misdn_cc_records_db);
9424  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.REJECT.InvokeID);
9425  if (cc_record) {
9426  cc_record->outstanding_message = 0;
9427  cc_record->reject_code = bc->fac_in.u.REJECT.Code;
9428  }
9429  AST_LIST_UNLOCK(&misdn_cc_records_db);
9430  }
9431  break;
9432  case Fac_RESULT:
9433  AST_LIST_LOCK(&misdn_cc_records_db);
9434  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.RESULT.InvokeID);
9435  if (cc_record) {
9436  cc_record->outstanding_message = 0;
9437  }
9438  AST_LIST_UNLOCK(&misdn_cc_records_db);
9439  break;
9440 #if 0 /* We don't handle this yet */
9441  case Fac_EctExecute:
9442  /* We don't handle this yet */
9443  break;
9444  case Fac_ExplicitEctExecute:
9445  /* We don't handle this yet */
9446  break;
9447  case Fac_EctLinkIdRequest:
9448  /* We don't handle this yet */
9449  break;
9450 #endif /* We don't handle this yet */
9451  case Fac_SubaddressTransfer:
9452  /* We do not have anything to do for this message since we do not handle subaddresses. */
9453  break;
9454  case Fac_RequestSubaddress:
9455  /*
9456  * We do not have anything to do for this message since we do not handle subaddresses.
9457  * However, we do care about some other ie's that should be present.
9458  */
9459  if (bc->redirecting.to_changed) {
9460  /* Add configured prefix to redirecting.to.number */
9462  bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
9463  }
9464  switch (bc->notify_description_code) {
9466  /* Notify ie was not present. */
9467  bc->redirecting.to_changed = 0;
9468  break;
9470  /*
9471  * It would be preferable to update the connected line information
9472  * only when the message callStatus is active. However, the
9473  * optional redirection number may not be present in the active
9474  * message if an alerting message were received earlier.
9475  *
9476  * The consequences if we wind up sending two updates is benign.
9477  * The other end will think that it got transferred twice.
9478  */
9479  if (!bc->redirecting.to_changed) {
9480  break;
9481  }
9482  bc->redirecting.to_changed = 0;
9483  if (!ch || !ch->ast) {
9484  break;
9485  }
9488  bc->incoming_cid_tag);
9489  break;
9491  if (!bc->redirecting.to_changed) {
9492  break;
9493  }
9494  bc->redirecting.to_changed = 0;
9495  if (!ch || !ch->ast) {
9496  break;
9497  }
9500  break;
9501  default:
9502  bc->redirecting.to_changed = 0;
9503  chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
9505  break;
9506  }
9508  break;
9509  case Fac_EctInform:
9510  /* Private-Public ISDN interworking message */
9511  if (ch && ch->ast && bc->fac_in.u.EctInform.RedirectionPresent) {
9512  /* Add configured prefix to the redirection number */
9513  memset(&party_id, 0, sizeof(party_id));
9514  misdn_PresentedNumberUnscreened_extract(&party_id,
9515  &bc->fac_in.u.EctInform.Redirection);
9517  party_id.number, sizeof(party_id.number));
9518 
9519  /*
9520  * It would be preferable to update the connected line information
9521  * only when the message callStatus is active. However, the
9522  * optional redirection number may not be present in the active
9523  * message if an alerting message were received earlier.
9524  *
9525  * The consequences if we wind up sending two updates is benign.
9526  * The other end will think that it got transferred twice.
9527  */
9528  misdn_update_remote_party(ch->ast, &party_id,
9529  (bc->fac_in.u.EctInform.Status == 0 /* alerting */)
9532  bc->incoming_cid_tag);
9533  }
9534  break;
9535 #if 0 /* We don't handle this yet */
9536  case Fac_EctLoopTest:
9537  /* The use of this message is unclear on how it works to detect loops. */
9538  /* We don't handle this yet */
9539  break;
9540 #endif /* We don't handle this yet */
9541  case Fac_CallInfoRetain:
9542  switch (event) {
9543  case EVENT_ALERTING:
9544  case EVENT_DISCONNECT:
9545  /* CCBS/CCNR is available */
9546  if (ch && ch->peer) {
9547  AST_LIST_LOCK(&misdn_cc_records_db);
9548  if (ch->record_id == -1) {
9549  cc_record = misdn_cc_new();
9550  } else {
9551  /*
9552  * We are doing a call-completion attempt
9553  * or the switch is sending us extra call-completion
9554  * availability indications (erroneously?).
9555  *
9556  * Assume that the network request retention option
9557  * is not on and that the current call-completion
9558  * request is disabled.
9559  */
9560  cc_record = misdn_cc_find_by_id(ch->record_id);
9561  if (cc_record) {
9562  if (cc_record->ptp && cc_record->mode.ptp.bc) {
9563  /*
9564  * What? We are getting mixed messages from the
9565  * switch. We are currently setup for
9566  * point-to-point. Now we are switching to
9567  * point-to-multipoint.
9568  *
9569  * Close the call-completion signaling link
9570  */
9571  cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
9572  cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
9573  misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
9574  }
9575 
9576  /*
9577  * Resetup the existing record for a possible new
9578  * call-completion request.
9579  */
9580  new_record_id = misdn_cc_record_id_new();
9581  if (new_record_id < 0) {
9582  /* Looks like we must keep the old id anyway. */
9583  } else {
9584  cc_record->record_id = new_record_id;
9585  ch->record_id = new_record_id;
9586  }
9587  cc_record->ptp = 0;
9588  cc_record->port = bc->port;
9589  memset(&cc_record->mode, 0, sizeof(cc_record->mode));
9590  cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
9591  cc_record->invoke_id = ++misdn_invoke_id;
9592  cc_record->activated = 0;
9593  cc_record->outstanding_message = 0;
9594  cc_record->activation_requested = 0;
9595  cc_record->error_code = FacError_None;
9596  cc_record->reject_code = FacReject_None;
9597  memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
9598  memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
9599  cc_record->time_created = time(NULL);
9600 
9601  cc_record = NULL;
9602  } else {
9603  /*
9604  * Where did the record go? We will have to recapture
9605  * the call setup information. Unfortunately, some
9606  * setup information may have been changed.
9607  */
9608  ch->record_id = -1;
9609  cc_record = misdn_cc_new();
9610  }
9611  }
9612  if (cc_record) {
9613  ch->record_id = cc_record->record_id;
9614  cc_record->ptp = 0;
9615  cc_record->port = bc->port;
9616  cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
9617 
9618  /* Record call information for possible call-completion attempt. */
9619  cc_record->redial.caller = bc->caller;
9620  cc_record->redial.dialed = bc->dialed;
9621  cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
9622  cc_record->redial.capability = bc->capability;
9623  cc_record->redial.hdlc = bc->hdlc;
9624  }
9625  AST_LIST_UNLOCK(&misdn_cc_records_db);
9626 
9627  /* Set MISDN_CC_RECORD_ID in original channel */
9628  if (ch->record_id != -1) {
9629  snprintf(buf, sizeof(buf), "%ld", ch->record_id);
9630  } else {
9631  buf[0] = 0;
9632  }
9633  misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
9634  }
9635  break;
9636  default:
9637  chan_misdn_log(0, bc->port,
9638  " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
9639  bc->fac_in.Function);
9640  break;
9641  }
9642  break;
9643  case Fac_CCBS_T_Call:
9644  case Fac_CCBSCall:
9645  switch (event) {
9646  case EVENT_SETUP:
9647  /*
9648  * This is a call completion retry call.
9649  * If we had anything to do we would do it here.
9650  */
9651  break;
9652  default:
9653  chan_misdn_log(0, bc->port, " --> Expected in a SETUP message: facility type:0x%04X\n",
9654  bc->fac_in.Function);
9655  break;
9656  }
9657  break;
9658  case Fac_CCBSDeactivate:
9659  switch (bc->fac_in.u.CCBSDeactivate.ComponentType) {
9660  case FacComponent_Result:
9661  AST_LIST_LOCK(&misdn_cc_records_db);
9662  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSDeactivate.InvokeID);
9663  if (cc_record) {
9664  cc_record->outstanding_message = 0;
9665  }
9666  AST_LIST_UNLOCK(&misdn_cc_records_db);
9667  break;
9668 
9669  default:
9670  chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
9671  bc->fac_in.Function);
9672  break;
9673  }
9674  break;
9675  case Fac_CCBSErase:
9676  AST_LIST_LOCK(&misdn_cc_records_db);
9677  cc_record = misdn_cc_find_by_reference(bc->port, bc->fac_in.u.CCBSErase.CCBSReference);
9678  if (cc_record) {
9679  misdn_cc_delete(cc_record);
9680  }
9681  AST_LIST_UNLOCK(&misdn_cc_records_db);
9682  break;
9683  case Fac_CCBSRemoteUserFree:
9684  misdn_cc_handle_remote_user_free(bc->port, &bc->fac_in);
9685  break;
9686  case Fac_CCBSBFree:
9687  misdn_cc_handle_b_free(bc->port, &bc->fac_in);
9688  break;
9689  case Fac_CCBSStatusRequest:
9690  misdn_cc_handle_ccbs_status_request(bc->port, &bc->fac_in);
9691  break;
9692  case Fac_EraseCallLinkageID:
9693  AST_LIST_LOCK(&misdn_cc_records_db);
9694  cc_record = misdn_cc_find_by_linkage(bc->port,
9695  bc->fac_in.u.EraseCallLinkageID.CallLinkageID);
9696  if (cc_record && !cc_record->activation_requested) {
9697  /*
9698  * The T-RETENTION timer expired before we requested
9699  * call completion activation. Call completion is no
9700  * longer available.
9701  */
9702  misdn_cc_delete(cc_record);
9703  }
9704  AST_LIST_UNLOCK(&misdn_cc_records_db);
9705  break;
9706  case Fac_CCBSStopAlerting:
9707  /* We do not have anything to do for this message. */
9708  break;
9709  case Fac_CCBSRequest:
9710  case Fac_CCNRRequest:
9711  switch (bc->fac_in.u.CCBSRequest.ComponentType) {
9712  case FacComponent_Result:
9713  AST_LIST_LOCK(&misdn_cc_records_db);
9714  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSRequest.InvokeID);
9715  if (cc_record && !cc_record->ptp) {
9716  cc_record->outstanding_message = 0;
9717  cc_record->activated = 1;
9718  cc_record->mode.ptmp.recall_mode = bc->fac_in.u.CCBSRequest.Component.Result.RecallMode;
9719  cc_record->mode.ptmp.reference_id = bc->fac_in.u.CCBSRequest.Component.Result.CCBSReference;
9720  }
9721  AST_LIST_UNLOCK(&misdn_cc_records_db);
9722  break;
9723 
9724  default:
9725  chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
9726  bc->fac_in.Function);
9727  break;
9728  }
9729  break;
9730 #if 0 /* We don't handle this yet */
9731  case Fac_CCBSInterrogate:
9732  case Fac_CCNRInterrogate:
9733  /* We don't handle this yet */
9734  break;
9735  case Fac_StatusRequest:
9736  /* We don't handle this yet */
9737  break;
9738 #endif /* We don't handle this yet */
9739 #if 0 /* We don't handle this yet */
9740  case Fac_CCBS_T_Suspend:
9741  case Fac_CCBS_T_Resume:
9742  /* We don't handle this yet */
9743  break;
9744 #endif /* We don't handle this yet */
9745  case Fac_CCBS_T_RemoteUserFree:
9746  misdn_cc_handle_T_remote_user_free(bc);
9747  break;
9748  case Fac_CCBS_T_Available:
9749  switch (event) {
9750  case EVENT_ALERTING:
9751  case EVENT_DISCONNECT:
9752  /* CCBS-T/CCNR-T is available */
9753  if (ch && ch->peer) {
9754  int set_id = 1;
9755 
9756  AST_LIST_LOCK(&misdn_cc_records_db);
9757  if (ch->record_id == -1) {
9758  cc_record = misdn_cc_new();
9759  } else {
9760  /*
9761  * We are doing a call-completion attempt
9762  * or the switch is sending us extra call-completion
9763  * availability indications (erroneously?).
9764  */
9765  cc_record = misdn_cc_find_by_id(ch->record_id);
9766  if (cc_record) {
9767  if (cc_record->ptp && cc_record->mode.ptp.retention_enabled) {
9768  /*
9769  * Call-completion is still activated.
9770  * The user does not have to request it again.
9771  */
9772  chan_misdn_log(1, bc->port, " --> Call-completion request retention option is enabled\n");
9773 
9774  set_id = 0;
9775  } else {
9776  if (cc_record->ptp && cc_record->mode.ptp.bc) {
9777  /*
9778  * The network request retention option
9779  * is not on and the current call-completion
9780  * request is to be disabled.
9781  *
9782  * We should get here only if EVENT_DISCONNECT
9783  *
9784  * Close the call-completion signaling link
9785  */
9786  cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
9787  cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
9788  misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
9789  }
9790 
9791  /*
9792  * Resetup the existing record for a possible new
9793  * call-completion request.
9794  */
9795  new_record_id = misdn_cc_record_id_new();
9796  if (new_record_id < 0) {
9797  /* Looks like we must keep the old id anyway. */
9798  } else {
9799  cc_record->record_id = new_record_id;
9800  ch->record_id = new_record_id;
9801  }
9802  cc_record->ptp = 1;
9803  cc_record->port = bc->port;
9804  memset(&cc_record->mode, 0, sizeof(cc_record->mode));
9805  cc_record->invoke_id = ++misdn_invoke_id;
9806  cc_record->activated = 0;
9807  cc_record->outstanding_message = 0;
9808  cc_record->activation_requested = 0;
9809  cc_record->error_code = FacError_None;
9810  cc_record->reject_code = FacReject_None;
9811  memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
9812  memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
9813  cc_record->time_created = time(NULL);
9814  }
9815  cc_record = NULL;
9816  } else {
9817  /*
9818  * Where did the record go? We will have to recapture
9819  * the call setup information. Unfortunately, some
9820  * setup information may have been changed.
9821  */
9822  ch->record_id = -1;
9823  cc_record = misdn_cc_new();
9824  }
9825  }
9826  if (cc_record) {
9827  ch->record_id = cc_record->record_id;
9828  cc_record->ptp = 1;
9829  cc_record->port = bc->port;
9830 
9831  /* Record call information for possible call-completion attempt. */
9832  cc_record->redial.caller = bc->caller;
9833  cc_record->redial.dialed = bc->dialed;
9834  cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
9835  cc_record->redial.capability = bc->capability;
9836  cc_record->redial.hdlc = bc->hdlc;
9837  }
9838  AST_LIST_UNLOCK(&misdn_cc_records_db);
9839 
9840  /* Set MISDN_CC_RECORD_ID in original channel */
9841  if (ch->record_id != -1 && set_id) {
9842  snprintf(buf, sizeof(buf), "%ld", ch->record_id);
9843  } else {
9844  buf[0] = 0;
9845  }
9846  misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
9847  }
9848  break;
9849  default:
9850  chan_misdn_log(0, bc->port,
9851  " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
9852  bc->fac_in.Function);
9853  break;
9854  }
9855  break;
9856  case Fac_CCBS_T_Request:
9857  case Fac_CCNR_T_Request:
9858  switch (bc->fac_in.u.CCBS_T_Request.ComponentType) {
9859  case FacComponent_Result:
9860  AST_LIST_LOCK(&misdn_cc_records_db);
9861  cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBS_T_Request.InvokeID);
9862  if (cc_record && cc_record->ptp) {
9863  cc_record->outstanding_message = 0;
9864  cc_record->activated = 1;
9865  cc_record->mode.ptp.retention_enabled =
9866  cc_record->mode.ptp.requested_retention
9867  ? bc->fac_in.u.CCBS_T_Request.Component.Result.RetentionSupported
9868  ? 1 : 0
9869  : 0;
9870  }
9871  AST_LIST_UNLOCK(&misdn_cc_records_db);
9872  break;
9873 
9874  case FacComponent_Invoke:
9875  /* We cannot be User-B in ptp mode. */
9876  default:
9877  chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
9878  bc->fac_in.Function);
9879  break;
9880  }
9881  break;
9882 
9883 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9884  case Fac_None:
9885  break;
9886  default:
9887  chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
9888  bc->fac_in.Function);
9889  break;
9890  }
9891 }
9892 
9893 /*!
9894  * \internal
9895  * \brief Determine if the given dialed party matches our MSN.
9896  * \since 1.8
9897  *
9898  * \param port ISDN port
9899  * \param dialed Dialed party information of incoming call.
9900  *
9901  * \retval non-zero if MSN is valid.
9902  * \retval 0 if MSN invalid.
9903  */
9904 static int misdn_is_msn_valid(int port, const struct misdn_party_dialing *dialed)
9905 {
9906  char number[sizeof(dialed->number)];
9907 
9908  ast_copy_string(number, dialed->number, sizeof(number));
9909  misdn_add_number_prefix(port, dialed->number_type, number, sizeof(number));
9910  return misdn_cfg_is_msn_valid(port, number);
9911 }
9912 
9913 /************************************************************/
9914 /* Receive Events from isdn_lib here */
9915 /************************************************************/
9916 static enum event_response_e
9917 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
9918 {
9919 #if defined(AST_MISDN_ENHANCEMENTS)
9920  struct misdn_cc_record *cc_record;
9921 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
9922  struct chan_list *held_ch;
9923  struct chan_list *ch = find_chan_by_bc(bc);
9924 
9925  if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
9926  int debuglevel = 1;
9927 
9928  /* Debug Only Non-Bchan */
9929  if (event == EVENT_CLEANUP && !user_data) {
9930  debuglevel = 5;
9931  }
9932 
9933  chan_misdn_log(debuglevel, bc->port,
9934  "I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
9935  manager_isdn_get_info(event),
9936  bc->caller.name,
9937  bc->caller.number,
9938  bc->dialed.number,
9939  bc->pid,
9940  ch ? misdn_get_ch_state(ch) : "none");
9941  if (debuglevel == 1) {
9942  misdn_lib_log_ies(bc);
9943  chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
9944  }
9945  }
9946 
9947  if (!ch) {
9948  switch(event) {
9949  case EVENT_SETUP:
9950  case EVENT_DISCONNECT:
9951  case EVENT_RELEASE:
9953  case EVENT_PORT_ALARM:
9954  case EVENT_RETRIEVE:
9955  case EVENT_NEW_BC:
9956  case EVENT_FACILITY:
9957  case EVENT_REGISTER:
9958  break;
9959  case EVENT_CLEANUP:
9960  case EVENT_TONE_GENERATE:
9961  case EVENT_BCHAN_DATA:
9962  return -1;
9963  default:
9964  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);
9965  return -1;
9966  }
9967  } else {
9968  switch (event) {
9969  case EVENT_TONE_GENERATE:
9970  break;
9971  case EVENT_DISCONNECT:
9972  case EVENT_RELEASE:
9974  case EVENT_CLEANUP:
9975  case EVENT_TIMEOUT:
9976  if (!ch->ast) {
9977  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));
9978  }
9979  break;
9980  default:
9981  if (!ch->ast || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
9982  if (event != EVENT_BCHAN_DATA) {
9983  ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
9984  }
9985  chan_list_unref(ch, "No Ast or Ast private pointer");
9986  return -1;
9987  }
9988  break;
9989  }
9990  }
9991 
9992 
9993  switch (event) {
9994  case EVENT_PORT_ALARM:
9995  {
9996  int boa = 0;
9997  misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
9998  if (boa) {
9999  cb_log(1, bc->port, " --> blocking\n");
10001  }
10002  }
10003  break;
10004  case EVENT_BCHAN_ACTIVATED:
10005  break;
10006 
10007  case EVENT_NEW_CHANNEL:
10008  update_name(ch->ast,bc->port,bc->channel);
10009  break;
10010 
10011  case EVENT_NEW_L3ID:
10012  ch->l3id=bc->l3_id;
10013  ch->addr=bc->addr;
10014  break;
10015 
10016  case EVENT_NEW_BC:
10017  if (!ch) {
10018  ch = find_hold_call(bc);
10019  }
10020 
10021  if (!ch) {
10022  ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
10023  break;
10024  }
10025 
10026  if (bc) {
10027  ch->bc = (struct misdn_bchannel *) user_data;
10028  }
10029  break;
10030 
10031  case EVENT_DTMF_TONE:
10032  {
10033  /* sending INFOS as DTMF-Frames :) */
10034  struct ast_frame fr;
10035 
10036  memset(&fr, 0, sizeof(fr));
10038  fr.subclass.integer = bc->dtmf ;
10039  fr.src = NULL;
10040  fr.data.ptr = NULL;
10041  fr.datalen = 0;
10042  fr.samples = 0;
10043  fr.mallocd = 0;
10044  fr.offset = 0;
10045  fr.delivery = ast_tv(0,0);
10046 
10047  if (!ch->ignore_dtmf) {
10048  chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
10049  ast_queue_frame(ch->ast, &fr);
10050  } else {
10051  chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
10052  }
10053  break;
10054  }
10055  case EVENT_STATUS:
10056  break;
10057 
10058  case EVENT_INFORMATION:
10059  if (ch->state != MISDN_CONNECTED) {
10060  stop_indicate(ch);
10061  }
10062 
10063  if (!ch->ast) {
10064  break;
10065  }
10066 
10067  if (ch->state == MISDN_WAITING4DIGS) {
10068  RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
10069  const char *pickupexten;
10070 
10071  /* Ok, incomplete Setup, waiting till extension exists */
10072  if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
10073  chan_misdn_log(1, bc->port, " --> using keypad as info\n");
10074  ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
10075  }
10076 
10077  strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10079 
10080  ast_channel_lock(ch->ast);
10081  pickup_cfg = ast_get_chan_features_pickup_config(ch->ast);
10082  if (!pickup_cfg) {
10083  ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
10084  pickupexten = "";
10085  } else {
10086  pickupexten = ast_strdupa(pickup_cfg->pickupexten);
10087  }
10088  ast_channel_unlock(ch->ast);
10089 
10090  /* Check for Pickup Request first */
10091  if (!strcmp(ast_channel_exten(ch->ast), pickupexten)) {
10092  if (ast_pickup_call(ch->ast)) {
10093  hangup_chan(ch, bc);
10094  } else {
10096  hangup_chan(ch, bc);
10097  ch->ast = NULL;
10098  break;
10099  }
10100  }
10101 
10102  if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10103  if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10105  "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10106  bc->dialed.number, ch->context, bc->port);
10107  pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10108  ast_channel_exten_set(ch->ast, "i");
10109  ch->state = MISDN_DIALING;
10110  start_pbx(ch, bc, ch->ast);
10111  break;
10112  }
10113 
10115  "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10116  "\tMaybe you want to add an 'i' extension to catch this case.\n",
10117  bc->dialed.number, ch->context, bc->port);
10118 
10119  if (bc->nt) {
10120  hanguptone_indicate(ch);
10121  }
10122  ch->state = MISDN_EXTCANTMATCH;
10124 
10126  break;
10127  }
10128 
10129  if (ch->overlap_dial) {
10131  ch->overlap_tv = ast_tvnow();
10133  if (ch->overlap_dial_task == -1) {
10134  ch->overlap_dial_task =
10136  }
10137  break;
10138  }
10139 
10140  if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10141  ch->state = MISDN_DIALING;
10142  start_pbx(ch, bc, ch->ast);
10143  }
10144  } else {
10145  /* sending INFOS as DTMF-Frames :) */
10146  struct ast_frame fr;
10147  int digits;
10148 
10149  memset(&fr, 0, sizeof(fr));
10151  fr.subclass.integer = bc->info_dad[0] ;
10152  fr.src = NULL;
10153  fr.data.ptr = NULL;
10154  fr.datalen = 0;
10155  fr.samples = 0;
10156  fr.mallocd = 0;
10157  fr.offset = 0;
10158  fr.delivery = ast_tv(0,0);
10159 
10160  misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
10161  if (ch->state != MISDN_CONNECTED) {
10162  if (digits) {
10163  strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10165  }
10166 
10167  ast_queue_frame(ch->ast, &fr);
10168  }
10169  }
10170  break;
10171  case EVENT_SETUP:
10172  {
10173  struct ast_channel *chan;
10174  int exceed;
10175  int ai;
10176  int im;
10177  int append_msn = 0;
10178  RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
10179  const char *pickupexten;
10180 
10181  if (ch) {
10182  switch (ch->state) {
10183  case MISDN_NOTHING:
10184  chan_list_unref(ch, "Ignore found ch. Is it for an outgoing call?");
10185  ch = NULL;
10186  break;
10187  default:
10188  chan_list_unref(ch, "Already have a call.");
10189  chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
10190  return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /* Ignore MSNs which are not in our List */
10191  }
10192  }
10193 
10194  if (!bc->nt && !misdn_is_msn_valid(bc->port, &bc->dialed)) {
10195  chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
10196  return RESPONSE_IGNORE_SETUP; /* Ignore MSNs which are not in our List */
10197  }
10198 
10199  if (bc->cw) {
10200  int cause;
10201  chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
10202  misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
10203  bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
10204  return RESPONSE_RELEASE_SETUP;
10205  }
10206 
10207  print_bearer(bc);
10208 
10209  ch = chan_list_init(ORG_MISDN);
10210  if (!ch) {
10211  chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
10212  return RESPONSE_RELEASE_SETUP;
10213  }
10214 
10215  ch->bc = bc;
10216  ch->l3id = bc->l3_id;
10217  ch->addr = bc->addr;
10218 
10219  {
10221  if (!(cap)) {
10222  return RESPONSE_ERR;
10223  }
10225  chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, cap, NULL, NULL, bc->port, bc->channel);
10226  ao2_ref(cap, -1);
10227  }
10228  if (!chan) {
10229  chan_list_unref(ch, "Failed to create a new channel");
10230  ast_log(LOG_ERROR, "cb_events: misdn_new failed!\n");
10231  return RESPONSE_RELEASE_SETUP;
10232  }
10233 
10234  ast_channel_lock(chan);
10235  pickup_cfg = ast_get_chan_features_pickup_config(chan);
10236  if (!pickup_cfg) {
10237  ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
10238  pickupexten = "";
10239  } else {
10240  pickupexten = ast_strdupa(pickup_cfg->pickupexten);
10241  }
10242  ast_channel_unlock(chan);
10243 
10244  if ((exceed = add_in_calls(bc->port))) {
10245  char tmp[16];
10246  snprintf(tmp, sizeof(tmp), "%d", exceed);
10247  pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
10248  }
10249 
10250  read_config(ch);
10251 
10252  export_ch(chan, bc, ch);
10253 
10254  ast_channel_lock(ch->ast);
10255  ast_channel_rings_set(ch->ast, 1);
10257  ast_channel_unlock(ch->ast);
10258 
10259  /* Update asterisk channel caller information */
10260  chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
10261  chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
10264 
10265  chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
10266  chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
10269 
10270  ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
10271 
10272  misdn_cfg_get(bc->port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
10273  if (append_msn) {
10274  strncat(bc->incoming_cid_tag, "_", sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10275  strncat(bc->incoming_cid_tag, bc->dialed.number, sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10276  }
10277 
10278  ast_channel_lock(chan);
10280  ast_channel_unlock(chan);
10281 
10282  if (!ast_strlen_zero(bc->redirecting.from.number)) {
10283  /* Add configured prefix to redirecting.from.number */
10285 
10286  /* Update asterisk channel redirecting information */
10288  }
10289 
10290  pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
10292 
10293  switch (bc->capability) {
10295  pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
10296  break;
10297  default:
10298  pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
10299  break;
10300  }
10301 
10302  if (!strstr(ch->allowed_bearers, "all")) {
10303  int i;
10304 
10305  for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
10306  if (allowed_bearers_array[i].cap == bc->capability) {
10307  if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
10308  /* The bearer capability is allowed */
10309  if (allowed_bearers_array[i].deprecated) {
10310  chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
10311  allowed_bearers_array[i].name);
10312  }
10313  break;
10314  }
10315  }
10316  }
10317  if (i == ARRAY_LEN(allowed_bearers_array)) {
10318  /* We did not find the bearer capability */
10319  chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
10320  bearer2str(bc->capability), bc->capability);
10321 
10322  ch->state = MISDN_EXTCANTMATCH;
10323  chan_list_unref(ch, "BC not allowed, releasing call");
10325  return RESPONSE_RELEASE_SETUP;
10326  }
10327  }
10328 
10329  /** queue new chan **/
10330  cl_queue_chan(ch);
10331 
10332  if (bc->fac_in.Function != Fac_None) {
10333  misdn_facility_ie_handler(event, bc, ch);
10334  }
10335 
10336  /* Check for Pickup Request first */
10337  if (!strcmp(ast_channel_exten(chan), pickupexten)) {
10338  if (!ch->noautorespond_on_setup) {
10339  /* Sending SETUP_ACK */
10341  } else {
10343  }
10344  if (ast_pickup_call(chan)) {
10345  hangup_chan(ch, bc);
10346  } else {
10348  hangup_chan(ch, bc);
10349  ch->ast = NULL;
10350  break;
10351  }
10352  }
10353 
10354  /*
10355  * added support for s extension hope it will help those poor cretains
10356  * which haven't overlap dial.
10357  */
10358  misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
10359  if (ai) {
10360  do_immediate_setup(bc, ch, chan);
10361  break;
10362  }
10363 
10364  /* check if we should jump into s when we have no dialed.number */
10365  misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
10366  if (im && ast_strlen_zero(bc->dialed.number)) {
10367  do_immediate_setup(bc, ch, chan);
10368  break;
10369  }
10370 
10371  chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
10372  if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10373  if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10375  "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10376  bc->dialed.number, ch->context, bc->port);
10377  pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10378  ast_channel_exten_set(ch->ast, "i");
10380  ch->state = MISDN_DIALING;
10381  start_pbx(ch, bc, chan);
10382  break;
10383  }
10384 
10386  "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10387  "\tMaybe you want to add an 'i' extension to catch this case.\n",
10388  bc->dialed.number, ch->context, bc->port);
10389  if (bc->nt) {
10390  hanguptone_indicate(ch);
10391  }
10392 
10393  ch->state = MISDN_EXTCANTMATCH;
10395 
10397  break;
10398  }
10399 
10400  /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
10401  * jump into the dialplan, when the dialed extension does not exist, the 's' extension
10402  * will be used by Asterisk automatically. */
10403  if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
10404  if (!ch->noautorespond_on_setup) {
10405  ch->state=MISDN_DIALING;
10407  } else {
10409  }
10410  start_pbx(ch, bc, chan);
10411  break;
10412  }
10413 
10414 
10415  /*
10416  * When we are NT and overlapdial is set and if
10417  * the number is empty, we wait for the ISDN timeout
10418  * instead of our own timer.
10419  */
10420  if (ch->overlap_dial && bc->nt && !bc->dialed.number[0]) {
10421  wait_for_digits(ch, bc, chan);
10422  break;
10423  }
10424 
10425  /*
10426  * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
10427  * Infos with a Interdigit Timeout.
10428  * */
10429  if (ch->overlap_dial) {
10431  ch->overlap_tv = ast_tvnow();
10433 
10434  wait_for_digits(ch, bc, chan);
10435  if (ch->overlap_dial_task == -1) {
10436  ch->overlap_dial_task =
10438  }
10439  break;
10440  }
10441 
10442  /* If the extension does not exist and we're not TE_PTMP we wait for more digits
10443  * without interdigit timeout.
10444  * */
10445  if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10446  wait_for_digits(ch, bc, chan);
10447  break;
10448  }
10449 
10450  /*
10451  * If the extension exists let's just jump into it.
10452  * */
10453  if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10455  ch->state = MISDN_DIALING;
10456  start_pbx(ch, bc, chan);
10457  break;
10458  }
10459  break;
10460  }
10461 #if defined(AST_MISDN_ENHANCEMENTS)
10462  case EVENT_REGISTER:
10463  if (bc->fac_in.Function != Fac_None) {
10464  misdn_facility_ie_handler(event, bc, ch);
10465  }
10466  /*
10467  * Shut down this connection immediately.
10468  * The current design of chan_misdn data structures
10469  * does not allow the proper handling of inbound call records
10470  * without an assigned B channel. Therefore, we cannot
10471  * be the CCBS User-B party in a point-to-point setup.
10472  */
10473  bc->fac_out.Function = Fac_None;
10476  break;
10477 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
10480 
10481  if (bc->channel) {
10482  update_name(ch->ast,bc->port,bc->channel);
10483  }
10484 
10485  if (bc->fac_in.Function != Fac_None) {
10486  misdn_facility_ie_handler(event, bc, ch);
10487  }
10488 
10489  if (!ast_strlen_zero(bc->infos_pending)) {
10490  /* TX Pending Infos */
10491  strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10492 
10493  if (!ch->ast) {
10494  break;
10495  }
10497  ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
10498  ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
10499 
10501  }
10502  break;
10503  case EVENT_PROCEEDING:
10504  if (misdn_cap_is_speech(bc->capability) &&
10505  misdn_inband_avail(bc)) {
10506  start_bc_tones(ch);
10507  }
10508 
10509  ch->state = MISDN_PROCEEDING;
10510 
10511  if (bc->fac_in.Function != Fac_None) {
10512  misdn_facility_ie_handler(event, bc, ch);
10513  }
10514 
10515  if (!ch->ast) {
10516  break;
10517  }
10518 
10520  break;
10521  case EVENT_PROGRESS:
10522  if (bc->channel) {
10523  update_name(ch->ast, bc->port, bc->channel);
10524  }
10525 
10526  if (bc->fac_in.Function != Fac_None) {
10527  misdn_facility_ie_handler(event, bc, ch);
10528  }
10529 
10530  if (!bc->nt) {
10531  if (misdn_cap_is_speech(bc->capability) &&
10532  misdn_inband_avail(bc)) {
10533  start_bc_tones(ch);
10534  }
10535 
10536  ch->state = MISDN_PROGRESS;
10537 
10538  if (!ch->ast) {
10539  break;
10540  }
10542  }
10543  break;
10544  case EVENT_ALERTING:
10545  ch->state = MISDN_ALERTING;
10546 
10547  if (!ch->ast) {
10548  break;
10549  }
10550 
10551  if (bc->fac_in.Function != Fac_None) {
10552  misdn_facility_ie_handler(event, bc, ch);
10553  }
10554 
10556  ast_channel_lock(ch->ast);
10558  ast_channel_unlock(ch->ast);
10559 
10560  cb_log(7, bc->port, " --> Set State Ringing\n");
10561 
10563  cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
10564  start_bc_tones(ch);
10565  } else {
10566  cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
10567  if (ch->far_alerting) {
10568  cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
10569  start_bc_tones(ch);
10570  /*tone_indicate(ch, TONE_FAR_ALERTING);*/
10571  }
10572  }
10573  break;
10574  case EVENT_CONNECT:
10575  if (bc->fac_in.Function != Fac_None) {
10576  misdn_facility_ie_handler(event, bc, ch);
10577  }
10578 #if defined(AST_MISDN_ENHANCEMENTS)
10579  if (bc->div_leg_3_rx_wanted) {
10580  bc->div_leg_3_rx_wanted = 0;
10581 
10582  if (ch->ast) {
10583  struct ast_party_redirecting redirecting;
10584 
10587  ast_party_redirecting_init(&redirecting);
10589 
10590  /*
10591  * Reset any earlier private redirecting id representations and
10592  * make sure that it is invalidated at the remote end.
10593  */
10594  ast_party_id_reset(&redirecting.priv_orig);
10595  ast_party_id_reset(&redirecting.priv_from);
10596  ast_party_id_reset(&redirecting.priv_to);
10597 
10598  ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
10599  ast_party_redirecting_free(&redirecting);
10600  }
10601  }
10602 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
10603 
10604  /* we answer when we've got our very new L3 ID from the NT stack */
10606 
10607  if (!ch->ast) {
10608  break;
10609  }
10610 
10611  stop_indicate(ch);
10612 
10613 #if defined(AST_MISDN_ENHANCEMENTS)
10614  if (ch->record_id != -1) {
10615  /*
10616  * We will delete the associated call completion
10617  * record since we now have a completed call.
10618  * We will not wait/depend on the network to tell
10619  * us to delete it.
10620  */
10621  AST_LIST_LOCK(&misdn_cc_records_db);
10622  cc_record = misdn_cc_find_by_id(ch->record_id);
10623  if (cc_record) {
10624  if (cc_record->ptp && cc_record->mode.ptp.bc) {
10625  /* Close the call-completion signaling link */
10626  cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
10627  cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10628  misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
10629  }
10630  misdn_cc_delete(cc_record);
10631  }
10632  AST_LIST_UNLOCK(&misdn_cc_records_db);
10633  ch->record_id = -1;
10634  if (ch->peer) {
10635  misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, "");
10636 
10637  ao2_ref(ch->peer, -1);
10638  ch->peer = NULL;
10639  }
10640  }
10641 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
10642 
10643  if (!ast_strlen_zero(bc->connected.number)) {
10644  /* Add configured prefix to connected.number */
10646 
10647  /* Update the connected line information on the other channel */
10649  }
10650 
10651  ch->l3id = bc->l3_id;
10652  ch->addr = bc->addr;
10653 
10654  start_bc_tones(ch);
10655 
10656  ch->state = MISDN_CONNECTED;
10657 
10659  break;
10661  ch->l3id = bc->l3_id;
10662  ch->addr = bc->addr;
10663 
10664  start_bc_tones(ch);
10665 
10666  ch->state = MISDN_CONNECTED;
10667  break;
10668  case EVENT_DISCONNECT:
10669  /* we might not have an ch->ast ptr here anymore */
10670  if (ch) {
10671  if (bc->fac_in.Function != Fac_None) {
10672  misdn_facility_ie_handler(event, bc, ch);
10673  }
10674 
10675  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);
10676  if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
10677  /* If there's inband information available (e.g. a
10678  recorded message saying what was wrong with the
10679  dialled number, or perhaps even giving an
10680  alternative number, then play it instead of
10681  immediately releasing the call */
10682  chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
10683 
10684  ch->state = MISDN_DISCONNECTED;
10685  start_bc_tones(ch);
10686 
10687  if (ch->ast) {
10689  if (bc->cause == AST_CAUSE_USER_BUSY) {
10691  }
10692  }
10693  ch->need_busy = 0;
10694  break;
10695  }
10696 
10697  bc->need_disconnect = 0;
10698  stop_bc_tones(ch);
10699 
10700  /* Check for held channel, to implement transfer */
10701  held_ch = find_hold_call(bc);
10702  if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
10703  hangup_chan(ch, bc);
10704  }
10705  } else {
10706  held_ch = find_hold_call_l3(bc->l3_id);
10707  if (held_ch) {
10708  if (bc->fac_in.Function != Fac_None) {
10709  misdn_facility_ie_handler(event, bc, held_ch);
10710  }
10711 
10712  if (held_ch->hold.state == MISDN_HOLD_ACTIVE) {
10713  bc->need_disconnect = 0;
10714 
10715 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
10716  /*
10717  * Some phones disconnect the held call and the active call at the
10718  * same time to do the transfer. Unfortunately, either call could
10719  * be disconnected first.
10720  */
10721  ch = find_hold_active_call(bc);
10722  if (!ch || misdn_attempt_transfer(ch, held_ch)) {
10723  held_ch->hold.state = MISDN_HOLD_DISCONNECT;
10724  hangup_chan(held_ch, bc);
10725  }
10726 #else
10727  hangup_chan(held_ch, bc);
10728 #endif /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
10729  }
10730  }
10731  }
10732  if (held_ch) {
10733  chan_list_unref(held_ch, "Done with held call");
10734  }
10735  bc->out_cause = -1;
10736  if (bc->need_release) {
10738  }
10739  break;
10740  case EVENT_RELEASE:
10741  if (!ch) {
10742  ch = find_hold_call_l3(bc->l3_id);
10743  if (!ch) {
10744  chan_misdn_log(1, bc->port,
10745  " --> no Ch, so we've already released. (%s)\n",
10746  manager_isdn_get_info(event));
10747  return -1;
10748  }
10749  }
10750  if (bc->fac_in.Function != Fac_None) {
10751  misdn_facility_ie_handler(event, bc, ch);
10752  }
10753 
10754  bc->need_disconnect = 0;
10755  bc->need_release = 0;
10756 
10757  hangup_chan(ch, bc);
10758  release_chan(ch, bc);
10759  break;
10761  if (!ch) {
10762  ch = find_hold_call_l3(bc->l3_id);
10763  }
10764 
10765  bc->need_disconnect = 0;
10766  bc->need_release = 0;
10767  bc->need_release_complete = 0;
10768 
10769  if (ch) {
10770  if (bc->fac_in.Function != Fac_None) {
10771  misdn_facility_ie_handler(event, bc, ch);
10772  }
10773 
10774  stop_bc_tones(ch);
10775  hangup_chan(ch, bc);
10776  release_chan(ch, bc);
10777  } else {
10778 #if defined(AST_MISDN_ENHANCEMENTS)
10779  /*
10780  * A call-completion signaling link established with
10781  * REGISTER does not have a struct chan_list record
10782  * associated with it.
10783  */
10784  AST_LIST_LOCK(&misdn_cc_records_db);
10785  cc_record = misdn_cc_find_by_bc(bc);
10786  if (cc_record) {
10787  /* The call-completion signaling link is closed. */
10788  misdn_cc_delete(cc_record);
10789  }
10790  AST_LIST_UNLOCK(&misdn_cc_records_db);
10791 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
10792 
10793  chan_misdn_log(1, bc->port,
10794  " --> no Ch, so we've already released. (%s)\n",
10795  manager_isdn_get_info(event));
10796  }
10797  break;
10798  case EVENT_BCHAN_ERROR:
10799  case EVENT_CLEANUP:
10800  stop_bc_tones(ch);
10801 
10802  switch (ch->state) {
10803  case MISDN_CALLING:
10805  break;
10806  default:
10807  break;
10808  }
10809 
10810  hangup_chan(ch, bc);
10811  release_chan(ch, bc);
10812  break;
10813  case EVENT_TONE_GENERATE:
10814  {
10815  int tone_len = bc->tone_cnt;
10816  struct ast_channel *ast = ch->ast;
10817  void *tmp;
10818  int res;
10819  int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
10820 
10821  chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
10822 
10823  if (!ast) {
10824  break;
10825  }
10826 
10827  if (!ast_channel_generator(ast)) {
10828  break;
10829  }
10830 
10831  tmp = ast_channel_generatordata(ast);
10833  generate = ast_channel_generator(ast)->generate;
10834 
10835  if (tone_len < 0 || tone_len > 512) {
10836  ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
10837  tone_len = 128;
10838  }
10839 
10840  res = generate(ast, tmp, tone_len, tone_len);
10842 
10843  if (res) {
10844  ast_log(LOG_WARNING, "Auto-deactivating generator\n");
10846  } else {
10847  bc->tone_cnt = 0;
10848  }
10849  break;
10850  }
10851  case EVENT_BCHAN_DATA:
10852  if (ch->bc->AOCD_need_export) {
10853  export_aoc_vars(ch->originator, ch->ast, ch->bc);
10854  }
10855  if (!misdn_cap_is_speech(ch->bc->capability)) {
10856  struct ast_frame frame;
10857 
10858  /* In Data Modes we queue frames */
10859  memset(&frame, 0, sizeof(frame));
10860  frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
10862  frame.datalen = bc->bframe_len;
10863  frame.samples = bc->bframe_len;
10864  frame.mallocd = 0;
10865  frame.offset = 0;
10866  frame.delivery = ast_tv(0, 0);
10867  frame.src = NULL;
10868  frame.data.ptr = bc->bframe;
10869 
10870  if (ch->ast) {
10871  ast_queue_frame(ch->ast, &frame);
10872  }
10873  } else {
10874  struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
10875  int t;
10876 
10877  t = ast_poll(&pfd, 1, 0);
10878 
10879  if (t < 0) {
10880  chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
10881  break;
10882  }
10883  if (!t) {
10884  chan_misdn_log(9, bc->port, "poll() timed out\n");
10885  break;
10886  }
10887 
10888  if (pfd.revents & POLLOUT) {
10889  chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
10890  if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
10891  chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
10892 
10893  stop_bc_tones(ch);
10894  hangup_chan(ch, bc);
10895  release_chan(ch, bc);
10896  }
10897  } else {
10898  chan_misdn_log(1, bc->port, "Write Pipe full!\n");
10899  }
10900  }
10901  break;
10902  case EVENT_TIMEOUT:
10903  if (ch && bc) {
10904  chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
10905  }
10906 
10907  switch (ch->state) {
10908  case MISDN_DIALING:
10909  case MISDN_PROGRESS:
10910  if (bc->nt && !ch->nttimeout) {
10911  break;
10912  }
10913  /* fall-through */
10914  case MISDN_CALLING:
10915  case MISDN_ALERTING:
10916  case MISDN_PROCEEDING:
10918  if (bc->nt) {
10920  hanguptone_indicate(ch);
10921  }
10922 
10925  break;
10926  case MISDN_WAITING4DIGS:
10927  if (bc->nt) {
10930  hanguptone_indicate(ch);
10932  } else {
10935  }
10936  break;
10937  case MISDN_CLEANING:
10938  chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
10939  break;
10940  default:
10942  break;
10943  }
10944  break;
10945 
10946  /****************************/
10947  /** Supplementary Services **/
10948  /****************************/
10949  case EVENT_RETRIEVE:
10950  if (!ch) {
10951  chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
10952  ch = find_hold_call_l3(bc->l3_id);
10953  if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
10954  ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
10956  break;
10957  }
10958  }
10959 
10960  /* remember the channel again */
10961  ch->bc = bc;
10962 
10963  ch->hold.state = MISDN_HOLD_IDLE;
10964  ch->hold.port = 0;
10965  ch->hold.channel = 0;
10966 
10967  ast_queue_unhold(ch->ast);
10968 
10970  chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
10972  }
10973  break;
10974  case EVENT_HOLD:
10975  {
10976  int hold_allowed;
10977  RAII_VAR(struct ast_channel *, bridged, NULL, ast_channel_cleanup);
10978 
10979  misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
10980  if (!hold_allowed) {
10981  chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
10983  break;
10984  }
10985 
10986  bridged = ast_channel_bridge_peer(ch->ast);
10987  if (bridged) {
10988  chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", ast_channel_tech(bridged)->type);
10989  ch->l3id = bc->l3_id;
10990 
10991  /* forget the channel now */
10992  ch->bc = NULL;
10994  ch->hold.port = bc->port;
10995  ch->hold.channel = bc->channel;
10996 
10997  ast_queue_hold(ch->ast, NULL);
10998 
11000  } else {
11002  chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
11003  }
11004  break;
11005  }
11006  case EVENT_NOTIFY:
11007  if (bc->redirecting.to_changed) {
11008  /* Add configured prefix to redirecting.to.number */
11010  bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
11011  }
11012  switch (bc->notify_description_code) {
11014  /* Ignore for now. */
11015  bc->redirecting.to_changed = 0;
11016  break;
11018  {
11019  struct ast_party_redirecting redirecting;
11020 
11021  if (!bc->redirecting.to_changed) {
11022  break;
11023  }
11024  bc->redirecting.to_changed = 0;
11025  if (!ch || !ch->ast) {
11026  break;
11027  }
11028  switch (ch->state) {
11029  case MISDN_ALERTING:
11030  /* Call is deflecting after we have seen an ALERTING message */
11032  break;
11033  default:
11034  /* Call is deflecting for call forwarding unconditional or busy reason. */
11036  break;
11037  }
11039  ast_party_redirecting_init(&redirecting);
11041 
11042  /*
11043  * Reset any earlier private redirecting id representations and
11044  * make sure that it is invalidated at the remote end.
11045  */
11046  ast_party_id_reset(&redirecting.priv_orig);
11047  ast_party_id_reset(&redirecting.priv_from);
11048  ast_party_id_reset(&redirecting.priv_to);
11049 
11050  ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
11051  ast_party_redirecting_free(&redirecting);
11052  break;
11053  }
11055  /*
11056  * It would be preferable to update the connected line information
11057  * only when the message callStatus is active. However, the
11058  * optional redirection number may not be present in the active
11059  * message if an alerting message were received earlier.
11060  *
11061  * The consequences if we wind up sending two updates is benign.
11062  * The other end will think that it got transferred twice.
11063  */
11064  if (!bc->redirecting.to_changed) {
11065  break;
11066  }
11067  bc->redirecting.to_changed = 0;
11068  if (!ch || !ch->ast) {
11069  break;
11070  }
11073  bc->incoming_cid_tag);
11074  break;
11076  if (!bc->redirecting.to_changed) {
11077  break;
11078  }
11079  bc->redirecting.to_changed = 0;
11080  if (!ch || !ch->ast) {
11081  break;
11082  }
11085  break;
11086  default:
11087  bc->redirecting.to_changed = 0;
11088  chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
11090  break;
11091  }
11093  break;
11094  case EVENT_FACILITY:
11095  if (bc->fac_in.Function == Fac_None) {
11096  /* This is a FACILITY message so we MUST have a facility ie */
11097  chan_misdn_log(0, bc->port," --> Missing facility ie or unknown facility ie contents.\n");
11098  } else {
11099  misdn_facility_ie_handler(event, bc, ch);
11100  }
11101 
11102  /* In case it came in on a FACILITY message and we did not handle it. */
11103  bc->redirecting.to_changed = 0;
11105  break;
11106  case EVENT_RESTART:
11107  if (!bc->dummy) {
11108  stop_bc_tones(ch);
11109  release_chan(ch, bc);
11110  }
11111  break;
11112  default:
11113  chan_misdn_log(1, 0, "Got Unknown Event\n");
11114  break;
11115  }
11116 
11117  if (ch) {
11118  chan_list_unref(ch, "cb_event complete OK");
11119  }
11120  return RESPONSE_OK;
11121 }
11122 
11123 /** TE STUFF END **/
11124 
11125 #if defined(AST_MISDN_ENHANCEMENTS)
11126 /*!
11127  * \internal
11128  * \brief Get call completion record information.
11129  *
11130  * \param chan Asterisk channel to operate upon. (Not used)
11131  * \param function_name Name of the function that called us.
11132  * \param function_args Argument string passed to function (Could be NULL)
11133  * \param buf Buffer to put returned string.
11134  * \param size Size of the supplied buffer including the null terminator.
11135  *
11136  * \retval 0 on success.
11137  * \retval -1 on error.
11138  */
11139 static int misdn_cc_read(struct ast_channel *chan, const char *function_name,
11140  char *function_args, char *buf, size_t size)
11141 {
11142  char *parse;
11143  struct misdn_cc_record *cc_record;
11144 
11146  AST_APP_ARG(cc_id); /* Call completion record ID value. */
11147  AST_APP_ARG(get_name); /* Name of what to get */
11148  AST_APP_ARG(other); /* Any extraneous garbage arguments */
11149  );
11150 
11151  /* Ensure that the buffer is empty */
11152  *buf = 0;
11153 
11154  if (ast_strlen_zero(function_args)) {
11155  ast_log(LOG_ERROR, "Function '%s' requires arguments.\n", function_name);
11156  return -1;
11157  }
11158 
11159  parse = ast_strdupa(function_args);
11160  AST_STANDARD_APP_ARGS(args, parse);
11161 
11162  if (!args.argc || ast_strlen_zero(args.cc_id)) {
11163  ast_log(LOG_ERROR, "Function '%s' missing call completion record ID.\n",
11164  function_name);
11165  return -1;
11166  }
11167  if (!isdigit(*args.cc_id)) {
11168  ast_log(LOG_ERROR, "Function '%s' call completion record ID must be numeric.\n",
11169  function_name);
11170  return -1;
11171  }
11172 
11173  if (ast_strlen_zero(args.get_name)) {
11174  ast_log(LOG_ERROR, "Function '%s' missing what-to-get parameter.\n",
11175  function_name);
11176  return -1;
11177  }
11178 
11179  AST_LIST_LOCK(&misdn_cc_records_db);
11180  cc_record = misdn_cc_find_by_id(atoi(args.cc_id));
11181  if (cc_record) {
11182  if (!strcasecmp("a-all", args.get_name)) {
11183  snprintf(buf, size, "\"%s\" <%s>", cc_record->redial.caller.name,
11184  cc_record->redial.caller.number);
11185  } else if (!strcasecmp("a-name", args.get_name)) {
11186  ast_copy_string(buf, cc_record->redial.caller.name, size);
11187  } else if (!strncasecmp("a-num", args.get_name, 5)) {
11188  ast_copy_string(buf, cc_record->redial.caller.number, size);
11189  } else if (!strcasecmp("a-ton", args.get_name)) {
11190  snprintf(buf, size, "%d",
11191  misdn_to_ast_plan(cc_record->redial.caller.number_plan)
11192  | misdn_to_ast_ton(cc_record->redial.caller.number_type));
11193  } else if (!strncasecmp("a-pres", args.get_name, 6)) {
11195  misdn_to_ast_pres(cc_record->redial.caller.presentation)
11196  | misdn_to_ast_screen(cc_record->redial.caller.screening)), size);
11197  } else if (!strcasecmp("a-busy", args.get_name)) {
11198  ast_copy_string(buf, cc_record->party_a_free ? "no" : "yes", size);
11199  } else if (!strncasecmp("b-num", args.get_name, 5)) {
11200  ast_copy_string(buf, cc_record->redial.dialed.number, size);
11201  } else if (!strcasecmp("b-ton", args.get_name)) {
11202  snprintf(buf, size, "%d",
11203  misdn_to_ast_plan(cc_record->redial.dialed.number_plan)
11204  | misdn_to_ast_ton(cc_record->redial.dialed.number_type));
11205  } else if (!strcasecmp("port", args.get_name)) {
11206  snprintf(buf, size, "%d", cc_record->port);
11207  } else if (!strcasecmp("available-notify-priority", args.get_name)) {
11208  snprintf(buf, size, "%d", cc_record->remote_user_free.priority);
11209  } else if (!strcasecmp("available-notify-exten", args.get_name)) {
11210  ast_copy_string(buf, cc_record->remote_user_free.exten, size);
11211  } else if (!strcasecmp("available-notify-context", args.get_name)) {
11212  ast_copy_string(buf, cc_record->remote_user_free.context, size);
11213  } else if (!strcasecmp("busy-notify-priority", args.get_name)) {
11214  snprintf(buf, size, "%d", cc_record->b_free.priority);
11215  } else if (!strcasecmp("busy-notify-exten", args.get_name)) {
11216  ast_copy_string(buf, cc_record->b_free.exten, size);
11217  } else if (!strcasecmp("busy-notify-context", args.get_name)) {
11218  ast_copy_string(buf, cc_record->b_free.context, size);
11219  } else {
11220  AST_LIST_UNLOCK(&misdn_cc_records_db);
11221  ast_log(LOG_ERROR, "Function '%s': Unknown what-to-get '%s'.\n", function_name, args.get_name);
11222  return -1;
11223  }
11224  }
11225  AST_LIST_UNLOCK(&misdn_cc_records_db);
11226 
11227  return 0;
11228 }
11229 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11230 
11231 #if defined(AST_MISDN_ENHANCEMENTS)
11232 static struct ast_custom_function misdn_cc_function = {
11233  .name = "mISDN_CC",
11234  .synopsis = "Get call completion record information.",
11235  .syntax = "mISDN_CC(${MISDN_CC_RECORD_ID},<what-to-get>)",
11236  .desc =
11237  "mISDN_CC(${MISDN_CC_RECORD_ID},<what-to-get>)\n"
11238  "The following can be retrieved:\n"
11239  "\"a-num\", \"a-name\", \"a-all\", \"a-ton\", \"a-pres\", \"a-busy\",\n"
11240  "\"b-num\", \"b-ton\", \"port\",\n"
11241  " User-A is available for call completion:\n"
11242  " \"available-notify-priority\",\n"
11243  " \"available-notify-exten\",\n"
11244  " \"available-notify-context\",\n"
11245  " User-A is busy:\n"
11246  " \"busy-notify-priority\",\n"
11247  " \"busy-notify-exten\",\n"
11248  " \"busy-notify-context\"\n",
11249  .read = misdn_cc_read,
11250 };
11251 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11252 
11253 /******************************************
11254  *
11255  * Asterisk Channel Endpoint END
11256  *
11257  *
11258  *******************************************/
11259 
11260 
11261 
11262 static int unload_module(void)
11263 {
11264  /* First, take us out of the channel loop */
11265  ast_verb(0, "-- Unregistering mISDN Channel Driver --\n");
11266 
11268 
11269  if (!g_config_initialized) {
11270  return 0;
11271  }
11272 
11273  ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11274 
11275  /* ast_unregister_application("misdn_crypt"); */
11276  ast_unregister_application("misdn_set_opt");
11277  ast_unregister_application("misdn_facility");
11278  ast_unregister_application("misdn_check_l2l1");
11279 #if defined(AST_MISDN_ENHANCEMENTS)
11280  ast_unregister_application(misdn_command_name);
11281  ast_custom_function_unregister(&misdn_cc_function);
11282 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11283 
11284  ast_channel_unregister(&misdn_tech);
11285 
11286  free_robin_list();
11289 
11290  ast_free(misdn_out_calls);
11291  ast_free(misdn_in_calls);
11292  ast_free(misdn_debug_only);
11294  ast_free(misdn_debug);
11295 
11296 #if defined(AST_MISDN_ENHANCEMENTS)
11297  misdn_cc_destroy();
11298 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11299  ao2_cleanup(misdn_tech.capabilities);
11300  misdn_tech.capabilities = NULL;
11301 
11302  return 0;
11303 }
11304 
11305 /*!
11306  * \brief Load the module
11307  *
11308  * Module loading including tests for configuration or dependencies.
11309  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
11310  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
11311  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
11312  * configuration file or other non-critical problem return
11313  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
11314  */
11315 static int load_module(void)
11316 {
11317  int i, port;
11318  int ntflags = 0, ntkc = 0;
11319  char ports[256] = "";
11320  char tempbuf[BUFFERSIZE + 1];
11321  char ntfile[BUFFERSIZE + 1];
11322  struct misdn_lib_iface iface = {
11323  .cb_event = cb_events,
11324  .cb_log = chan_misdn_log,
11325  .cb_jb_empty = chan_misdn_jb_empty,
11326  };
11327 
11328 
11330  return AST_MODULE_LOAD_DECLINE;
11331  }
11333 
11334  max_ports = misdn_lib_maxports_get();
11335 
11336  if (max_ports <= 0) {
11337  ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
11338  return AST_MODULE_LOAD_DECLINE;
11339  }
11340 
11341  if (misdn_cfg_init(max_ports, 0)) {
11342  ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
11343  return AST_MODULE_LOAD_DECLINE;
11344  }
11346 
11347 #if defined(AST_MISDN_ENHANCEMENTS)
11348  misdn_cc_init();
11349 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11350 
11351  misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
11352  if (!misdn_debug) {
11353  ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
11354  return AST_MODULE_LOAD_DECLINE;
11355  }
11356  misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
11357  if (!misdn_ports) {
11358  ast_free(misdn_debug);
11359  ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
11360  return AST_MODULE_LOAD_DECLINE;
11361  }
11362  misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
11363  for (i = 1; i <= max_ports; i++) {
11364  misdn_debug[i] = misdn_debug[0];
11365  misdn_ports[i] = i;
11366  }
11367  *misdn_ports = 0;
11368  misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
11369  if (!misdn_debug_only) {
11371  ast_free(misdn_debug);
11372  ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
11373  return AST_MODULE_LOAD_DECLINE;
11374  }
11375 
11376  misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
11377  if (!ast_strlen_zero(tempbuf)) {
11378  tracing = 1;
11379  }
11380 
11381  misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11382  if (!misdn_in_calls) {
11383  ast_free(misdn_debug_only);
11385  ast_free(misdn_debug);
11386  ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
11387  return AST_MODULE_LOAD_DECLINE;
11388  }
11389  misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11390  if (!misdn_out_calls) {
11391  ast_free(misdn_in_calls);
11392  ast_free(misdn_debug_only);
11394  ast_free(misdn_debug);
11395  ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
11396  return AST_MODULE_LOAD_DECLINE;
11397  }
11398 
11399  for (i = 1; i <= max_ports; i++) {
11400  misdn_in_calls[i] = 0;
11401  misdn_out_calls[i] = 0;
11402  }
11403 
11404  ast_mutex_init(&cl_te_lock);
11405  ast_mutex_init(&release_lock);
11406 
11409 
11410  if (!ast_strlen_zero(ports)) {
11411  chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
11412  }
11413  if (misdn_lib_init(ports, &iface, NULL)) {
11414  chan_misdn_log(0, 0, "No te ports initialized\n");
11415  }
11416 
11417  misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
11418  misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
11419  misdn_cfg_get(0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
11420 
11421  misdn_lib_nt_keepcalls(ntkc);
11422  misdn_lib_nt_debug_init(ntflags, ntfile);
11423 
11424  if (ast_channel_register(&misdn_tech)) {
11425  ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
11426  unload_module();
11427  return AST_MODULE_LOAD_DECLINE;
11428  }
11429 
11430  ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11431 
11432  ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
11433  "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
11434  "Sets mISDN opts. and optargs\n"
11435  "\n"
11436  "The available options are:\n"
11437  " a - Have Asterisk detect DTMF tones on called channel\n"
11438  " c - Make crypted outgoing call, optarg is keyindex\n"
11439  " d - Send display text to called phone, text is the optarg\n"
11440  " e - Perform echo cancellation on this channel,\n"
11441  " takes taps as optarg (32,64,128,256)\n"
11442  " e! - Disable echo cancellation on this channel\n"
11443  " f - Enable fax detection\n"
11444  " h - Make digital outgoing call\n"
11445  " h1 - Make HDLC mode digital outgoing call\n"
11446  " i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
11447  " they will be transported inband.\n"
11448  " jb - Set jitter buffer length, optarg is length\n"
11449  " jt - Set jitter buffer upper threshold, optarg is threshold\n"
11450  " jn - Disable jitter buffer\n"
11451  " n - Disable mISDN DSP on channel.\n"
11452  " Disables: echo cancel, DTMF detection, and volume control.\n"
11453  " p - Caller ID presentation,\n"
11454  " optarg is either 'allowed' or 'restricted'\n"
11455  " s - Send Non-inband DTMF as inband\n"
11456  " vr - Rx gain control, optarg is gain\n"
11457  " vt - Tx gain control, optarg is gain\n"
11458  );
11459 
11460 
11461  ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
11462  "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
11463  "Sends the Facility Message FACILITY_TYPE with \n"
11464  "the given Arguments to the current ISDN Channel\n"
11465  "Supported Facilities are:\n"
11466  "\n"
11467  "type=calldeflect args=Nr where to deflect\n"
11468 #if defined(AST_MISDN_ENHANCEMENTS)
11469  "type=callrerouting args=Nr where to deflect\n"
11470 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11471  );
11472 
11473 
11474  ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
11475  "misdn_check_l2l1(<port>||g:<groupname>,timeout)\n"
11476  "Checks if the L2 and L1 are up on either the given <port> or\n"
11477  "on the ports in the group with <groupname>\n"
11478  "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
11479  "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
11480  "\n"
11481  "This application, ensures the L1/L2 state of the Ports in a group\n"
11482  "it is intended to make the pmp_l1_check option redundant and to\n"
11483  "fix a buggy switch config from your provider\n"
11484  "\n"
11485  "a sample dialplan would look like:\n\n"
11486  "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
11487  "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
11488  );
11489 
11490 #if defined(AST_MISDN_ENHANCEMENTS)
11491  ast_register_application(misdn_command_name, misdn_command_exec, misdn_command_name,
11492  "misdn_command(<command>[,<options>])\n"
11493  "The following commands are defined:\n"
11494  "cc-initialize\n"
11495  " Setup mISDN support for call completion\n"
11496  " Must call before doing any Dial() involving call completion.\n"
11497  "ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11498  " Request Call Completion No Reply activation\n"
11499  "ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11500  " Request Call Completion Busy Subscriber activation\n"
11501  "cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11502  " Set the dialplan location to notify when User-B is available but User-A is busy.\n"
11503  " Setting this dialplan location is optional.\n"
11504  "cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>\n"
11505  " Set the busy status of call completion User-A\n"
11506  "cc-deactivate,${MISDN_CC_RECORD_ID}\n"
11507  " Deactivate the identified call completion request\n"
11508  "\n"
11509  "MISDN_CC_RECORD_ID is set when Dial() returns and call completion is possible\n"
11510  "MISDN_CC_STATUS is set to ACTIVATED or ERROR after the call completion\n"
11511  "activation request.\n"
11512  "MISDN_ERROR_MSG is set to a descriptive message on error.\n"
11513  );
11514 
11515  ast_custom_function_register(&misdn_cc_function);
11516 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11517 
11519 
11520  /* start the l1 watchers */
11521 
11522  for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
11523  int l1timeout;
11524  misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
11525  if (l1timeout) {
11526  chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
11527  misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
11528  }
11529  }
11530 
11531  chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
11532 
11533  return 0;
11534 }
11535 
11536 
11537 
11538 static int reload(void)
11539 {
11540  reload_config();
11541 
11542  return 0;
11543 }
11544 
11545 /*** SOME APPS ;)***/
11546 
11547 #if defined(AST_MISDN_ENHANCEMENTS)
11548 /*!
11549 * \brief misdn_command arguments container.
11550 */
11551 AST_DEFINE_APP_ARGS_TYPE(misdn_command_args,
11552  AST_APP_ARG(name); /* Subcommand name */
11553  AST_APP_ARG(arg)[10 + 1]; /* Subcommand arguments */
11554 );
11555 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11556 
11557 #if defined(AST_MISDN_ENHANCEMENTS)
11558 static void misdn_cc_caller_destroy(void *obj)
11559 {
11560  /* oh snap! */
11561 }
11562 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11563 
11564 #if defined(AST_MISDN_ENHANCEMENTS)
11565 static struct misdn_cc_caller *misdn_cc_caller_alloc(struct ast_channel *chan)
11566 {
11567  struct misdn_cc_caller *cc_caller;
11568 
11569  if (!(cc_caller = ao2_alloc(sizeof(*cc_caller), misdn_cc_caller_destroy))) {
11570  return NULL;
11571  }
11572 
11573  cc_caller->chan = chan;
11574 
11575  return cc_caller;
11576 }
11577 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11578 
11579 #if defined(AST_MISDN_ENHANCEMENTS)
11580 /*!
11581  * \internal
11582  * \brief misdn_command(cc-initialize) subcommand handler
11583  *
11584  * \param chan Asterisk channel to operate upon.
11585  * \param subcommand Arguments for the subcommand
11586  *
11587  * \retval 0 on success.
11588  * \retval -1 on error.
11589  */
11590 static int misdn_command_cc_initialize(struct ast_channel *chan, struct misdn_command_args *subcommand)
11591 {
11592  struct misdn_cc_caller *cc_caller;
11593  struct ast_datastore *datastore;
11594 
11595  if (!(cc_caller = misdn_cc_caller_alloc(chan))) {
11596  return -1;
11597  }
11598 
11599  if (!(datastore = ast_datastore_alloc(&misdn_cc_ds_info, NULL))) {
11600  ao2_ref(cc_caller, -1);
11601  return -1;
11602  }
11603 
11604  ast_channel_lock(chan);
11605 
11606  /* Inherit reference */
11607  datastore->data = cc_caller;
11608  cc_caller = NULL;
11609 
11611 
11612  ast_channel_datastore_add(chan, datastore);
11613 
11614  ast_channel_unlock(chan);
11615 
11616  return 0;
11617 }
11618 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11619 
11620 #if defined(AST_MISDN_ENHANCEMENTS)
11621 /*!
11622  * \internal
11623  * \brief misdn_command(cc-deactivate) subcommand handler
11624  *
11625  * \details
11626  * misdn_command(cc-deactivate,${MISDN_CC_RECORD_ID})
11627  * Deactivate a call completion service instance.
11628  *
11629  * \param chan Asterisk channel to operate upon.
11630  * \param subcommand Arguments for the subcommand
11631  *
11632  * \retval 0 on success.
11633  * \retval -1 on error.
11634  */
11635 static int misdn_command_cc_deactivate(struct ast_channel *chan, struct misdn_command_args *subcommand)
11636 {
11637  long record_id;
11638  const char *error_str;
11639  struct misdn_cc_record *cc_record;
11640  struct misdn_bchannel *bc;
11641  struct misdn_bchannel dummy;
11642 
11643  static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID})\n";
11644 
11645  if (ast_strlen_zero(subcommand->arg[0]) || !isdigit(*subcommand->arg[0])) {
11646  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11647  return -1;
11648  }
11649  record_id = atol(subcommand->arg[0]);
11650 
11651  AST_LIST_LOCK(&misdn_cc_records_db);
11652  cc_record = misdn_cc_find_by_id(record_id);
11653  if (cc_record && 0 <= cc_record->port) {
11654  if (cc_record->ptp) {
11655  if (cc_record->mode.ptp.bc) {
11656  /* Close the call-completion signaling link */
11657  bc = cc_record->mode.ptp.bc;
11658  bc->fac_out.Function = Fac_None;
11661  }
11662  misdn_cc_delete(cc_record);
11663  } else if (cc_record->activated) {
11664  cc_record->error_code = FacError_None;
11665  cc_record->reject_code = FacReject_None;
11666  cc_record->invoke_id = ++misdn_invoke_id;
11667  cc_record->outstanding_message = 1;
11668 
11669  /* Build message */
11670  misdn_make_dummy(&dummy, cc_record->port, 0, misdn_lib_port_is_nt(cc_record->port), 0);
11671  dummy.fac_out.Function = Fac_CCBSDeactivate;
11672  dummy.fac_out.u.CCBSDeactivate.InvokeID = cc_record->invoke_id;
11673  dummy.fac_out.u.CCBSDeactivate.ComponentType = FacComponent_Invoke;
11674  dummy.fac_out.u.CCBSDeactivate.Component.Invoke.CCBSReference = cc_record->mode.ptmp.reference_id;
11675 
11676  /* Send message */
11677  print_facility(&dummy.fac_out, &dummy);
11679  }
11680  }
11681  AST_LIST_UNLOCK(&misdn_cc_records_db);
11682 
11683  /* Wait for the response to the call completion deactivation request. */
11684  misdn_cc_response_wait(chan, MISDN_CC_REQUEST_WAIT_MAX, record_id);
11685 
11686  AST_LIST_LOCK(&misdn_cc_records_db);
11687  cc_record = misdn_cc_find_by_id(record_id);
11688  if (cc_record) {
11689  if (cc_record->port < 0) {
11690  /* The network did not tell us that call completion was available. */
11691  error_str = NULL;
11692  } else if (cc_record->outstanding_message) {
11693  cc_record->outstanding_message = 0;
11694  error_str = misdn_no_response_from_network;
11695  } else if (cc_record->reject_code != FacReject_None) {
11696  error_str = misdn_to_str_reject_code(cc_record->reject_code);
11697  } else if (cc_record->error_code != FacError_None) {
11698  error_str = misdn_to_str_error_code(cc_record->error_code);
11699  } else {
11700  error_str = NULL;
11701  }
11702 
11703  misdn_cc_delete(cc_record);
11704  } else {
11705  error_str = NULL;
11706  }
11707  AST_LIST_UNLOCK(&misdn_cc_records_db);
11708  if (error_str) {
11709  ast_verb(1, "%s(%s) diagnostic '%s' on channel %s\n",
11710  misdn_command_name, subcommand->name, error_str, ast_channel_name(chan));
11711  pbx_builtin_setvar_helper(chan, MISDN_ERROR_MSG, error_str);
11712  }
11713 
11714  return 0;
11715 }
11716 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11717 
11718 #if defined(AST_MISDN_ENHANCEMENTS)
11719 /*!
11720  * \internal
11721  * \brief misdn_command(cc-a-busy) subcommand handler
11722  *
11723  * \details
11724  * misdn_command(cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>)
11725  * Set the status of User-A for a call completion service instance.
11726  *
11727  * \param chan Asterisk channel to operate upon.
11728  * \param subcommand Arguments for the subcommand
11729  *
11730  * \retval 0 on success.
11731  * \retval -1 on error.
11732  */
11733 static int misdn_command_cc_a_busy(struct ast_channel *chan, struct misdn_command_args *subcommand)
11734 {
11735  long record_id;
11736  int party_a_free;
11737  struct misdn_cc_record *cc_record;
11738  struct misdn_bchannel *bc;
11739 
11740  static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<yes/no>)\n";
11741 
11742  if (ast_strlen_zero(subcommand->arg[0]) || !isdigit(*subcommand->arg[0])) {
11743  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11744  return -1;
11745  }
11746  record_id = atol(subcommand->arg[0]);
11747 
11748  if (ast_true(subcommand->arg[1])) {
11749  party_a_free = 0;
11750  } else if (ast_false(subcommand->arg[1])) {
11751  party_a_free = 1;
11752  } else {
11753  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11754  return -1;
11755  }
11756 
11757  AST_LIST_LOCK(&misdn_cc_records_db);
11758  cc_record = misdn_cc_find_by_id(record_id);
11759  if (cc_record && cc_record->party_a_free != party_a_free) {
11760  /* User-A's status has changed */
11761  cc_record->party_a_free = party_a_free;
11762 
11763  if (cc_record->ptp && cc_record->mode.ptp.bc) {
11764  cc_record->error_code = FacError_None;
11765  cc_record->reject_code = FacReject_None;
11766 
11767  /* Build message */
11768  bc = cc_record->mode.ptp.bc;
11769  if (cc_record->party_a_free) {
11770  bc->fac_out.Function = Fac_CCBS_T_Resume;
11771  bc->fac_out.u.CCBS_T_Resume.InvokeID = ++misdn_invoke_id;
11772  } else {
11773  bc->fac_out.Function = Fac_CCBS_T_Suspend;
11774  bc->fac_out.u.CCBS_T_Suspend.InvokeID = ++misdn_invoke_id;
11775  }
11776 
11777  /* Send message */
11778  print_facility(&bc->fac_out, bc);
11780  }
11781  }
11782  AST_LIST_UNLOCK(&misdn_cc_records_db);
11783 
11784  return 0;
11785 }
11786 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11787 
11788 #if defined(AST_MISDN_ENHANCEMENTS)
11789 /*!
11790  * \internal
11791  * \brief misdn_command(cc-b-free) subcommand handler
11792  *
11793  * \details
11794  * misdn_command(cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
11795  * Set the dialplan location to notify when User-B is free and User-A is busy.
11796  *
11797  * \param chan Asterisk channel to operate upon.
11798  * \param subcommand Arguments for the subcommand
11799  *
11800  * \retval 0 on success.
11801  * \retval -1 on error.
11802  */
11803 static int misdn_command_cc_b_free(struct ast_channel *chan, struct misdn_command_args *subcommand)
11804 {
11805  unsigned index;
11806  long record_id;
11807  int priority;
11808  char *context;
11809  char *exten;
11810  struct misdn_cc_record *cc_record;
11811 
11812  static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)\n";
11813 
11814  /* Check that all arguments are present */
11815  for (index = 0; index < 4; ++index) {
11816  if (ast_strlen_zero(subcommand->arg[index])) {
11817  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11818  return -1;
11819  }
11820  }
11821 
11822  /* These must be numeric */
11823  if (!isdigit(*subcommand->arg[0]) || !isdigit(*subcommand->arg[3])) {
11824  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11825  return -1;
11826  }
11827 
11828  record_id = atol(subcommand->arg[0]);
11829  context = subcommand->arg[1];
11830  exten = subcommand->arg[2];
11831  priority = atoi(subcommand->arg[3]);
11832 
11833  AST_LIST_LOCK(&misdn_cc_records_db);
11834  cc_record = misdn_cc_find_by_id(record_id);
11835  if (cc_record) {
11836  /* Save User-B free information */
11837  ast_copy_string(cc_record->b_free.context, context, sizeof(cc_record->b_free.context));
11838  ast_copy_string(cc_record->b_free.exten, exten, sizeof(cc_record->b_free.exten));
11839  cc_record->b_free.priority = priority;
11840  }
11841  AST_LIST_UNLOCK(&misdn_cc_records_db);
11842 
11843  return 0;
11844 }
11845 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11846 
11847 #if defined(AST_MISDN_ENHANCEMENTS)
11848 struct misdn_cc_request {
11849  enum FacFunction ptmp;
11850  enum FacFunction ptp;
11851 };
11852 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
11853 
11854 #if defined(AST_MISDN_ENHANCEMENTS)
11855 /*!
11856  * \internal
11857  * \brief misdn_command(ccbs-request/ccnr-request) subcommand handler helper
11858  *
11859  * \details
11860  * misdn_command(ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
11861  * misdn_command(ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
11862  * Set the dialplan location to notify when User-B is free and User-A is free.
11863  *
11864  * \param chan Asterisk channel to operate upon.
11865  * \param subcommand Arguments for the subcommand
11866  * \param request Which call-completion request message to generate.
11867  *
11868  * \retval 0 on success.
11869  * \retval -1 on error.
11870  */
11871 static int misdn_command_cc_request(struct ast_channel *chan, struct misdn_command_args *subcommand, const struct misdn_cc_request *request)
11872 {
11873  unsigned index;
11874  int request_retention;
11875  long record_id;
11876  int priority;
11877  char *context;
11878  char *exten;
11879  const char *error_str;
11880  struct misdn_cc_record *cc_record;
11881  struct misdn_bchannel *bc;
11882  struct misdn_bchannel dummy;
11883  struct misdn_party_id id;
11884 
11885  static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)\n";
11886 
11887  /* Check that all arguments are present */
11888  for (index = 0; index < 4; ++index) {
11889  if (ast_strlen_zero(subcommand->arg[index])) {
11890  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11891  return -1;
11892  }
11893  }
11894 
11895  /* These must be numeric */
11896  if (!isdigit(*subcommand->arg[0]) || !isdigit(*subcommand->arg[3])) {
11897  ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11898  return -1;
11899  }
11900 
11901  record_id = atol(subcommand->arg[0]);
11902  context = subcommand->arg[1];
11903  exten = subcommand->arg[2];
11904  priority = atoi(subcommand->arg[3]);
11905 
11906  AST_LIST_LOCK(&misdn_cc_records_db);
11907  cc_record = misdn_cc_find_by_id(record_id);
11908  if (cc_record) {
11909  /* Save User-B free information */
11910  ast_copy_string(cc_record->remote_user_free.context, context,
11911  sizeof(cc_record->remote_user_free.context));
11912  ast_copy_string(cc_record->remote_user_free.exten, exten,
11913  sizeof(cc_record->remote_user_free.exten));
11914  cc_record->remote_user_free.priority = priority;
11915 
11916  if (0 <= cc_record->port) {
11917  if (cc_record->ptp) {
11918  if (!cc_record->mode.ptp.bc) {
11919  bc = misdn_lib_get_register_bc(cc_record->port);
11920  if (bc) {
11921  cc_record->mode.ptp.bc = bc;
11922  cc_record->error_code = FacError_None;
11923  cc_record->reject_code = FacReject_None;
11924  cc_record->invoke_id = ++misdn_invoke_id;
11925  cc_record->outstanding_message = 1;
11926  cc_record->activation_requested = 1;
11927 
11929  &request_retention, sizeof(request_retention));
11930  cc_record->mode.ptp.requested_retention = request_retention ? 1 : 0;
11931 
11932  /* Build message */
11933  bc->fac_out.Function = request->ptp;
11934  bc->fac_out.u.CCBS_T_Request.InvokeID = cc_record->invoke_id;
11935  bc->fac_out.u.CCBS_T_Request.ComponentType = FacComponent_Invoke;
11936  bc->fac_out.u.CCBS_T_Request.Component.Invoke.Q931ie =
11937  cc_record->redial.setup_bc_hlc_llc;
11938  memset(&id, 0, sizeof(id));
11939  id.number_plan = cc_record->redial.dialed.number_plan;
11940  id.number_type = cc_record->redial.dialed.number_type;
11941  ast_copy_string(id.number, cc_record->redial.dialed.number,
11942  sizeof(id.number));
11943  misdn_Address_fill(
11944  &bc->fac_out.u.CCBS_T_Request.Component.Invoke.Destination,
11945  &id);
11946  misdn_Address_fill(
11947  &bc->fac_out.u.CCBS_T_Request.Component.Invoke.Originating,
11948  &cc_record->redial.caller);
11949  bc->fac_out.u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1;
11950  bc->fac_out.u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator =
11951  (cc_record->redial.caller.presentation != 0) ? 0 : 1;
11952  bc->fac_out.u.CCBS_T_Request.Component.Invoke.RetentionSupported =
11953  request_retention ? 1 : 0;
11954 
11955  /* Send message */
11956  print_facility(&bc->fac_out, bc);
11958  }
11959  }
11960  } else {
11961  cc_record->error_code = FacError_None;
11962  cc_record->reject_code = FacReject_None;
11963  cc_record->invoke_id = ++misdn_invoke_id;
11964  cc_record->outstanding_message = 1;
11965  cc_record->activation_requested = 1;
11966 
11967  /* Build message */
11968  misdn_make_dummy(&dummy, cc_record->port, 0,
11969  misdn_lib_port_is_nt(cc_record->port), 0);
11970  dummy.fac_out.Function = request->ptmp;
11971  dummy.fac_out.u.CCBSRequest.InvokeID = cc_record->invoke_id;
11972  dummy.fac_out.u.CCBSRequest.ComponentType = FacComponent_Invoke;
11973  dummy.fac_out.u.CCBSRequest.Component.Invoke.CallLinkageID =
11974  cc_record->mode.ptmp.linkage_id;
11975 
11976  /* Send message */
11977  print_facility(&dummy.fac_out, &dummy);
11979  }
11980  }
11981  }
11982  AST_LIST_UNLOCK(&misdn_cc_records_db);
11983 
11984  /* Wait for the response to the call completion request. */
11985  misdn_cc_response_wait(chan, MISDN_CC_REQUEST_WAIT_MAX, record_id);
11986 
11987  AST_LIST_LOCK(&misdn_cc_records_db);
11988  cc_record = misdn_cc_find_by_id(record_id);
11989  if (cc_record) {
11990  if (!cc_record->activated) {
11991  if (cc_record->port < 0) {
11992  /* The network did not tell us that call completion was available. */
11993  error_str = "No port number";
11994  } else if (cc_record->outstanding_message) {
11995  cc_record->outstanding_message = 0;
11996  error_str = misdn_no_response_from_network;
11997  } else if (cc_record->reject_code != FacReject_None) {
11998  error_str = misdn_to_str_reject_code(cc_record->reject_code);
11999  } else if (cc_record->error_code != FacError_None) {
12000  error_str = misdn_to_str_error_code(cc_record->error_code);
12001  } else if (cc_record->ptp) {
12002  if (cc_record->mode.ptp.bc) {
12003  error_str = "Call-completion already requested";
12004  } else {
12005  error_str = "Could not allocate call-completion signaling link";
12006  }
12007  } else {
12008  /* Should never happen. */
12009  error_str = "Unexpected error";
12010  }
12011 
12012  /* No need to keep the call completion record. */
12013  if (cc_record->ptp && cc_record->mode.ptp.bc) {
12014  /* Close the call-completion signaling link */
12015  bc = cc_record->mode.ptp.bc;
12016  bc->fac_out.Function = Fac_None;
12019  }
12020  misdn_cc_delete(cc_record);
12021  } else {
12022  error_str = NULL;
12023  }
12024  } else {
12025  error_str = misdn_cc_record_not_found;
12026  }
12027  AST_LIST_UNLOCK(&misdn_cc_records_db);
12028  if (error_str) {
12029  ast_verb(1, "%s(%s) diagnostic '%s' on channel %s\n",
12030  misdn_command_name, subcommand->name, error_str, ast_channel_name(chan));
12031  pbx_builtin_setvar_helper(chan, MISDN_ERROR_MSG, error_str);
12032  pbx_builtin_setvar_helper(chan, MISDN_CC_STATUS, "ERROR");
12033  } else {
12034  pbx_builtin_setvar_helper(chan, MISDN_CC_STATUS, "ACTIVATED");
12035  }
12036 
12037  return 0;
12038 }
12039 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
12040 
12041 #if defined(AST_MISDN_ENHANCEMENTS)
12042 /*!
12043  * \internal
12044  * \brief misdn_command(ccbs-request) subcommand handler
12045  *
12046  * \details
12047  * misdn_command(ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
12048  * Set the dialplan location to notify when User-B is free and User-A is free.
12049  *
12050  * \param chan Asterisk channel to operate upon.
12051  * \param subcommand Arguments for the subcommand
12052  *
12053  * \retval 0 on success.
12054  * \retval -1 on error.
12055  */
12056 static int misdn_command_ccbs_request(struct ast_channel *chan, struct misdn_command_args *subcommand)
12057 {
12058  static const struct misdn_cc_request request = {
12059  .ptmp = Fac_CCBSRequest,
12060  .ptp = Fac_CCBS_T_Request
12061  };
12062 
12063  return misdn_command_cc_request(chan, subcommand, &request);
12064 }
12065 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
12066 
12067 #if defined(AST_MISDN_ENHANCEMENTS)
12068 /*!
12069  * \internal
12070  * \brief misdn_command(ccnr-request) subcommand handler
12071  *
12072  * \details
12073  * misdn_command(ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
12074  * Set the dialplan location to notify when User-B is free and User-A is free.
12075  *
12076  * \param chan Asterisk channel to operate upon.
12077  * \param subcommand Arguments for the subcommand
12078  *
12079  * \retval 0 on success.
12080  * \retval -1 on error.
12081  */
12082 static int misdn_command_ccnr_request(struct ast_channel *chan, struct misdn_command_args *subcommand)
12083 {
12084  static const struct misdn_cc_request request = {
12085  .ptmp = Fac_CCNRRequest,
12086  .ptp = Fac_CCNR_T_Request
12087  };
12088 
12089  return misdn_command_cc_request(chan, subcommand, &request);
12090 }
12091 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
12092 
12093 #if defined(AST_MISDN_ENHANCEMENTS)
12094 struct misdn_command_table {
12095  /*! \brief subcommand name */
12096  const char *name;
12097 
12098  /*! \brief subcommand handler */
12099  int (*func)(struct ast_channel *chan, struct misdn_command_args *subcommand);
12100 
12101  /*! \brief TRUE if the subcommand can only be executed on mISDN channels */
12102  int misdn_only;
12103 };
12104 static const struct misdn_command_table misdn_commands[] = {
12105 /* *INDENT-OFF* */
12106  /* subcommand-name subcommand-handler mISDN only */
12107  { "cc-initialize", misdn_command_cc_initialize, 0 },
12108  { "cc-deactivate", misdn_command_cc_deactivate, 0 },
12109  { "cc-a-busy", misdn_command_cc_a_busy, 0 },
12110  { "cc-b-free", misdn_command_cc_b_free, 0 },
12111  { "ccbs-request", misdn_command_ccbs_request, 0 },
12112  { "ccnr-request", misdn_command_ccnr_request, 0 },
12113 /* *INDENT-ON* */
12114 };
12115 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
12116 
12117 #if defined(AST_MISDN_ENHANCEMENTS)
12118 /*!
12119  * \internal
12120  * \brief misdn_command() dialplan application.
12121  *
12122  * \param chan Asterisk channel to operate upon.
12123  * \param data Application options string.
12124  *
12125  * \retval 0 on success.
12126  * \retval -1 on error.
12127  */
12128 static int misdn_command_exec(struct ast_channel *chan, const char *data)
12129 {
12130  char *parse;
12131  unsigned index;
12132  struct misdn_command_args subcommand;
12133 
12134  if (ast_strlen_zero((char *) data)) {
12135  ast_log(LOG_ERROR, "%s requires arguments\n", misdn_command_name);
12136  return -1;
12137  }
12138 
12139  ast_debug(1, "%s(%s)\n", misdn_command_name, (char *) data);
12140 
12141  parse = ast_strdupa(data);
12142  AST_STANDARD_APP_ARGS(subcommand, parse);
12143  if (!subcommand.argc || ast_strlen_zero(subcommand.name)) {
12144  ast_log(LOG_ERROR, "%s requires a subcommand\n", misdn_command_name);
12145  return -1;
12146  }
12147 
12148  for (index = 0; index < ARRAY_LEN(misdn_commands); ++index) {
12149  if (strcasecmp(misdn_commands[index].name, subcommand.name) == 0) {
12150  strcpy(subcommand.name, misdn_commands[index].name);
12151  if (misdn_commands[index].misdn_only
12152  && strcasecmp(ast_channel_tech(chan)->type, misdn_type) != 0) {
12154  "%s(%s) only makes sense with %s channels!\n",
12155  misdn_command_name, subcommand.name, misdn_type);
12156  return -1;
12157  }
12158  return misdn_commands[index].func(chan, &subcommand);
12159  }
12160  }
12161 
12162  ast_log(LOG_WARNING, "%s(%s) subcommand is unknown\n", misdn_command_name,
12163  subcommand.name);
12164  return -1;
12165 }
12166 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
12167 
12168 static int misdn_facility_exec(struct ast_channel *chan, const char *data)
12169 {
12170  struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12171  char *parse;
12172  unsigned max_len;
12173 
12175  AST_APP_ARG(facility_type);
12176  AST_APP_ARG(arg)[99];
12177  );
12178 
12179  chan_misdn_log(0, 0, "TYPE: %s\n", ast_channel_tech(chan)->type);
12180 
12181  if (strcasecmp(ast_channel_tech(chan)->type, misdn_type)) {
12182  ast_log(LOG_WARNING, "misdn_facility only makes sense with %s channels!\n", misdn_type);
12183  return -1;
12184  }
12185 
12186  if (ast_strlen_zero((char *) data)) {
12187  ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12188  return -1;
12189  }
12190 
12191  parse = ast_strdupa(data);
12192  AST_STANDARD_APP_ARGS(args, parse);
12193 
12194  if (ast_strlen_zero(args.facility_type)) {
12195  ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12196  return -1;
12197  }
12198 
12199  if (!strcasecmp(args.facility_type, "calldeflect")) {
12200  if (ast_strlen_zero(args.arg[0])) {
12201  ast_log(LOG_WARNING, "Facility: Call Deflection requires an argument: Number\n");
12202  }
12203 
12204 #if defined(AST_MISDN_ENHANCEMENTS)
12205  max_len = sizeof(ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
12206  if (max_len < strlen(args.arg[0])) {
12208  "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12209  max_len);
12210  return 0;
12211  }
12212  ch->bc->fac_out.Function = Fac_CallDeflection;
12213  ch->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
12214  ch->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
12215  ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
12216  ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
12217  ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
12218  ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(args.arg[0]);
12219  strcpy((char *) ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, args.arg[0]);
12220  ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
12221 
12222 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
12223 
12224  max_len = sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
12225  if (max_len < strlen(args.arg[0])) {
12227  "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12228  max_len);
12229  return 0;
12230  }
12231  ch->bc->fac_out.Function = Fac_CD;
12232  ch->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
12233  //ch->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
12234  strcpy((char *) ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0]);
12235 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
12236 
12237  /* Send message */
12238  print_facility(&ch->bc->fac_out, ch->bc);
12240 #if defined(AST_MISDN_ENHANCEMENTS)
12241  } else if (!strcasecmp(args.facility_type, "callrerouteing")
12242  || !strcasecmp(args.facility_type, "callrerouting")) {
12243  if (ast_strlen_zero(args.arg[0])) {
12244  ast_log(LOG_WARNING, "Facility: Call rerouting requires an argument: Number\n");
12245  }
12246 
12247  max_len = sizeof(ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
12248  if (max_len < strlen(args.arg[0])) {
12250  "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12251  max_len);
12252  return 0;
12253  }
12254  ch->bc->fac_out.Function = Fac_CallRerouteing;
12255  ch->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
12256  ch->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
12257 
12258  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
12259  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
12260 
12261  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
12262  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(args.arg[0]);
12263  strcpy((char *) ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, args.arg[0]);
12264  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
12265 
12266  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
12267 
12268  /* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
12269  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
12270  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
12271  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
12272  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
12273  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
12274  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
12275  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
12276 
12277  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
12278  ch->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
12279 
12280  /* Send message */
12281  print_facility(&ch->bc->fac_out, ch->bc);
12283 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
12284  } else {
12285  chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", args.facility_type);
12286  }
12287 
12288  return 0;
12289 }
12290 
12291 static int misdn_check_l2l1(struct ast_channel *chan, const char *data)
12292 {
12293  char *parse;
12294  char group[BUFFERSIZE + 1];
12295  char *port_str;
12296  int port = 0;
12297  int timeout;
12298  int dowait = 0;
12299  int port_up;
12300 
12302  AST_APP_ARG(grouppar);
12303  AST_APP_ARG(timeout);
12304  );
12305 
12306  if (ast_strlen_zero((char *) data)) {
12307  ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
12308  return -1;
12309  }
12310 
12311  parse = ast_strdupa(data);
12312  AST_STANDARD_APP_ARGS(args, parse);
12313 
12314  if (args.argc != 2) {
12315  ast_log(LOG_WARNING, "Wrong argument count\n");
12316  return 0;
12317  }
12318 
12319  /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
12320  timeout = atoi(args.timeout);
12321  port_str = args.grouppar;
12322 
12323  if (port_str[0] == 'g' && port_str[1] == ':') {
12324  /* We make a group call lets checkout which ports are in my group */
12325  port_str += 2;
12326  ast_copy_string(group, port_str, sizeof(group));
12327  chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
12328 
12329  for (port = misdn_cfg_get_next_port(port);
12330  port > 0;
12331  port = misdn_cfg_get_next_port(port)) {
12332  char cfg_group[BUFFERSIZE + 1];
12333 
12334  chan_misdn_log(2, 0, "trying port %d\n", port);
12335 
12336  misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
12337 
12338  if (!strcasecmp(cfg_group, group)) {
12339  port_up = misdn_lib_port_up(port, 1);
12340  if (!port_up) {
12341  chan_misdn_log(2, 0, " --> port '%d'\n", port);
12342  misdn_lib_get_port_up(port);
12343  dowait = 1;
12344  }
12345  }
12346  }
12347  } else {
12348  port = atoi(port_str);
12349  chan_misdn_log(2, 0, "Checking Port: %d\n", port);
12350  port_up = misdn_lib_port_up(port, 1);
12351  if (!port_up) {
12352  misdn_lib_get_port_up(port);
12353  dowait = 1;
12354  }
12355  }
12356 
12357  if (dowait) {
12358  chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
12359  ast_safe_sleep(chan, timeout * 1000);
12360  }
12361 
12362  return 0;
12363 }
12364 
12365 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data)
12366 {
12367  struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12368  char *tok;
12369  char *tokb;
12370  char *parse;
12371  int keyidx = 0;
12372  int rxgain = 0;
12373  int txgain = 0;
12374  int change_jitter = 0;
12375 
12376  if (strcasecmp(ast_channel_tech(chan)->type, misdn_type)) {
12377  ast_log(LOG_WARNING, "misdn_set_opt makes sense only with %s channels!\n", misdn_type);
12378  return -1;
12379  }
12380 
12381  if (ast_strlen_zero((char *) data)) {
12382  ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
12383  return -1;
12384  }
12385 
12386  parse = ast_strdupa(data);
12387  for (tok = strtok_r(parse, ":", &tokb);
12388  tok;
12389  tok = strtok_r(NULL, ":", &tokb)) {
12390  int neglect = 0;
12391 
12392  if (tok[0] == '!') {
12393  neglect = 1;
12394  tok++;
12395  }
12396 
12397  switch(tok[0]) {
12398  case 'd' :
12399  ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
12400  chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
12401  break;
12402  case 'n':
12403  chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
12404  ch->bc->nodsp = 1;
12405  break;
12406  case 'j':
12407  chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
12408  tok++;
12409  change_jitter = 1;
12410 
12411  switch (tok[0]) {
12412  case 'b':
12413  ch->jb_len = atoi(++tok);
12414  chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
12415  break;
12416  case 't' :
12417  ch->jb_upper_threshold = atoi(++tok);
12418  chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
12419  break;
12420  case 'n':
12421  ch->bc->nojitter = 1;
12422  chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
12423  break;
12424  default:
12425  ch->jb_len = 4000;
12426  ch->jb_upper_threshold = 0;
12427  chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
12428  chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
12429  break;
12430  }
12431  break;
12432  case 'v':
12433  tok++;
12434 
12435  switch (tok[0]) {
12436  case 'r' :
12437  rxgain = atoi(++tok);
12438  if (rxgain < -8) {
12439  rxgain = -8;
12440  }
12441  if (rxgain > 8) {
12442  rxgain = 8;
12443  }
12444  ch->bc->rxgain = rxgain;
12445  chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
12446  break;
12447  case 't':
12448  txgain = atoi(++tok);
12449  if (txgain < -8) {
12450  txgain = -8;
12451  }
12452  if (txgain > 8) {
12453  txgain = 8;
12454  }
12455  ch->bc->txgain = txgain;
12456  chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
12457  break;
12458  }
12459  break;
12460  case 'c':
12461  keyidx = atoi(++tok);
12462  {
12463  char keys[4096];
12464  char *key = NULL;
12465  char *tmp = keys;
12466  int i;
12467 
12468  misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
12469 
12470  for (i = 0; i < keyidx; i++) {
12471  key = strsep(&tmp, ",");
12472  }
12473 
12474  if (key) {
12475  ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
12476  }
12477 
12478  chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
12479  break;
12480  }
12481  case 'e':
12482  chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
12483 
12484  if (neglect) {
12485  chan_misdn_log(1, ch->bc->port, " --> disabled\n");
12486 #ifdef MISDN_1_2
12487  *ch->bc->pipeline = 0;
12488 #else
12489  ch->bc->ec_enable = 0;
12490 #endif
12491  } else {
12492 #ifdef MISDN_1_2
12493  update_pipeline_config(ch->bc);
12494 #else
12495  ch->bc->ec_enable = 1;
12496  ch->bc->orig = ch->originator;
12497  tok++;
12498  if (*tok) {
12499  ch->bc->ec_deftaps = atoi(tok);
12500  }
12501 #endif
12502  }
12503  break;
12504  case 'h':
12505  chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
12506 
12507  if (strlen(tok) > 1 && tok[1] == '1') {
12508  chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
12509  if (!ch->bc->hdlc) {
12510  ch->bc->hdlc = 1;
12511  }
12512  }
12514  break;
12515  case 's':
12516  chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
12517  ch->bc->send_dtmf = 1;
12518  break;
12519  case 'f':
12520  chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
12521  ch->faxdetect = 1;
12523  break;
12524  case 'a':
12525  chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
12526  ch->ast_dsp = 1;
12527  break;
12528  case 'p':
12529  chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
12530  /* CRICH: callingpres!!! */
12531  if (strstr(tok, "allowed")) {
12532  ch->bc->presentation = 0;
12533  ch->bc->set_presentation = 1;
12534  } else if (strstr(tok, "restricted")) {
12535  ch->bc->presentation = 1;
12536  ch->bc->set_presentation = 1;
12537  } else if (strstr(tok, "not_screened")) {
12538  chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
12539  ch->bc->presentation = 1;
12540  ch->bc->set_presentation = 1;
12541  }
12542  break;
12543  case 'i' :
12544  chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
12545  ch->ignore_dtmf = 1;
12546  break;
12547  default:
12548  break;
12549  }
12550  }
12551 
12552  if (change_jitter) {
12553  config_jitterbuffer(ch);
12554  }
12555 
12556  if (ch->faxdetect || ch->ast_dsp) {
12557  if (!ch->dsp) {
12558  ch->dsp = ast_dsp_new();
12559  }
12560  if (ch->dsp) {
12562  }
12563  }
12564 
12565  if (ch->ast_dsp) {
12566  chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
12567  ch->bc->nodsp = 1;
12568  }
12569 
12570  return 0;
12571 }
12572 
12573 
12574 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len)
12575 {
12576  struct chan_list *ch;
12577  int res;
12578 
12579  ch = find_chan_by_bc(bc);
12580  if (!ch) {
12581  return 0;
12582  }
12583 
12584  if (ch->jb) {
12585  res = misdn_jb_empty(ch->jb, buf, len);
12586  } else {
12587  res = 0;
12588  }
12589  chan_list_unref(ch, "Done emptying jb");
12590 
12591  return res;
12592 }
12593 
12594 
12595 
12596 /*******************************************************/
12597 /***************** JITTERBUFFER ************************/
12598 /*******************************************************/
12599 
12600 
12601 /* allocates the jb-structure and initialize the elements*/
12603 {
12604  struct misdn_jb *jb;
12605 
12606  jb = ast_calloc(1, sizeof(*jb));
12607  if (!jb) {
12608  chan_misdn_log(-1, 0, "No free Mem for jb\n");
12609  return NULL;
12610  }
12611  jb->size = size;
12613  //jb->wp = 0;
12614  //jb->rp = 0;
12615  //jb->state_full = 0;
12616  //jb->state_empty = 0;
12617  //jb->bytes_wrote = 0;
12618  jb->samples = ast_calloc(size, sizeof(*jb->samples));
12619  if (!jb->samples) {
12620  ast_free(jb);
12621  chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
12622  return NULL;
12623  }
12624 
12625  jb->ok = ast_calloc(size, sizeof(*jb->ok));
12626  if (!jb->ok) {
12627  ast_free(jb->samples);
12628  ast_free(jb);
12629  chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
12630  return NULL;
12631  }
12632 
12633  ast_mutex_init(&jb->mutexjb);
12634 
12635  return jb;
12636 }
12637 
12638 /* frees the data and destroys the given jitterbuffer struct */
12639 void misdn_jb_destroy(struct misdn_jb *jb)
12640 {
12641  ast_mutex_destroy(&jb->mutexjb);
12642 
12643  ast_free(jb->ok);
12644  ast_free(jb->samples);
12645  ast_free(jb);
12646 }
12647 
12648 /* fills the jitterbuffer with len data returns < 0 if there was an
12649  error (buffer overflow). */
12650 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
12651 {
12652  int i;
12653  int j;
12654  int rp;
12655  int wp;
12656 
12657  if (!jb || ! data) {
12658  return 0;
12659  }
12660 
12661  ast_mutex_lock(&jb->mutexjb);
12662 
12663  wp = jb->wp;
12664  rp = jb->rp;
12665 
12666  for (i = 0; i < len; i++) {
12667  jb->samples[wp] = data[i];
12668  jb->ok[wp] = 1;
12669  wp = (wp != jb->size - 1) ? wp + 1 : 0;
12670 
12671  if (wp == jb->rp) {
12672  jb->state_full = 1;
12673  }
12674  }
12675 
12676  if (wp >= rp) {
12677  jb->state_buffer = wp - rp;
12678  } else {
12679  jb->state_buffer = jb->size - rp + wp;
12680  }
12681  chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12682 
12683  if (jb->state_full) {
12684  jb->wp = wp;
12685 
12686  rp = wp;
12687  for (j = 0; j < jb->upper_threshold; j++) {
12688  rp = (rp != 0) ? rp - 1 : jb->size - 1;
12689  }
12690  jb->rp = rp;
12691  jb->state_full = 0;
12692  jb->state_empty = 1;
12693 
12694  ast_mutex_unlock(&jb->mutexjb);
12695 
12696  return -1;
12697  }
12698 
12699  if (!jb->state_empty) {
12700  jb->bytes_wrote += len;
12701  if (jb->bytes_wrote >= jb->upper_threshold) {
12702  jb->state_empty = 1;
12703  jb->bytes_wrote = 0;
12704  }
12705  }
12706  jb->wp = wp;
12707 
12708  ast_mutex_unlock(&jb->mutexjb);
12709 
12710  return 0;
12711 }
12712 
12713 /* gets len bytes out of the jitterbuffer if available, else only the
12714 available data is returned and the return value indicates the number
12715 of data. */
12716 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
12717 {
12718  int i;
12719  int wp;
12720  int rp;
12721  int read = 0;
12722 
12723  ast_mutex_lock(&jb->mutexjb);
12724 
12725  rp = jb->rp;
12726  wp = jb->wp;
12727 
12728  if (jb->state_empty) {
12729  for (i = 0; i < len; i++) {
12730  if (wp == rp) {
12731  jb->rp = rp;
12732  jb->state_empty = 0;
12733 
12734  ast_mutex_unlock(&jb->mutexjb);
12735 
12736  return read;
12737  } else {
12738  if (jb->ok[rp] == 1) {
12739  data[i] = jb->samples[rp];
12740  jb->ok[rp] = 0;
12741  rp = (rp != jb->size - 1) ? rp + 1 : 0;
12742  read += 1;
12743  }
12744  }
12745  }
12746 
12747  if (wp >= rp) {
12748  jb->state_buffer = wp - rp;
12749  } else {
12750  jb->state_buffer = jb->size - rp + wp;
12751  }
12752  chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12753 
12754  jb->rp = rp;
12755  } else {
12756  chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
12757  }
12758 
12759  ast_mutex_unlock(&jb->mutexjb);
12760 
12761  return read;
12762 }
12763 
12764 /*******************************************************/
12765 /*************** JITTERBUFFER END *********************/
12766 /*******************************************************/
12767 
12768 static void chan_misdn_log(int level, int port, char *tmpl, ...)
12769 {
12770  va_list ap;
12771  char buf[1024];
12772  char port_buf[8];
12773 
12774  if (!(0 <= port && port <= max_ports)) {
12775  ast_log(LOG_WARNING, "chan_misdn_log called with out-of-range port number! (%d)\n", port);
12776  port = 0;
12777  level = -1;
12778  } else if (!(level == -1
12779  || (misdn_debug_only[port]
12780  ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12781  : level <= misdn_debug[port])
12782  || (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)))) {
12783  /*
12784  * We are not going to print anything so lets not
12785  * go to all the work of generating a string.
12786  */
12787  return;
12788  }
12789 
12790  snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
12791  va_start(ap, tmpl);
12792  vsnprintf(buf, sizeof(buf), tmpl, ap);
12793  va_end(ap);
12794 
12795  if (level == -1) {
12796  ast_log(LOG_WARNING, "%s", buf);
12797  } else if (misdn_debug_only[port]
12798  ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12799  : level <= misdn_debug[port]) {
12800  ast_verbose("%s%s", port_buf, buf);
12801  }
12802 
12803  if (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)) {
12804  char ctimebuf[30];
12805  time_t tm;
12806  char *tmp;
12807  char *p;
12808  FILE *fp;
12809 
12810  fp = fopen(global_tracefile, "a+");
12811  if (!fp) {
12812  ast_verbose("Error opening Tracefile: [ %s ] %s\n", global_tracefile, strerror(errno));
12813  return;
12814  }
12815 
12816  tm = time(NULL);
12817  tmp = ctime_r(&tm, ctimebuf);
12818  p = strchr(tmp, '\n');
12819  if (p) {
12820  *p = ':';
12821  }
12822  fputs(tmp, fp);
12823  fputs(" ", fp);
12824  fputs(port_buf, fp);
12825  fputs(" ", fp);
12826  fputs(buf, fp);
12827 
12828  fclose(fp);
12829  }
12830 }
12831 
12832 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Channel driver for mISDN Support (BRI/PRI)",
12833  .support_level = AST_MODULE_SUPPORT_DEPRECATED,
12834  .load = load_module,
12835  .unload = unload_module,
12836  .reload = reload,
12837  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
12838 );
static int misdn_send_text(struct ast_channel *chan, const char *text)
Definition: chan_misdn.c:8115
int ast_dsp
TRUE if we will use the Asterisk DSP to detect DTMF/Fax.
Definition: chan_misdn.c:484
const char * name
Definition: pbx.h:119
int misdn_lib_maxports_get(void)
Definition: isdn_lib.c:4094
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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:402
static void chan_misdn_log(int level, int port, char *tmpl,...)
Definition: chan_misdn.c:12768
ast_mutex_t mutexjb
Definition: chan_misdn.c:140
#define AST_CAUSE_PROTOCOL_ERROR
Definition: causes.h:144
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel.
Definition: main/app.c:981
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:1574
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:3166
unsigned long long ast_group_t
Definition: channel.h:214
static const char type[]
Definition: chan_ooh323.c:109
char keypad[MISDN_MAX_KEYPAD_LEN]
Q.931 Keypad Facility IE contents.
Definition: isdn_lib.h:647
Information needed to identify an endpoint in a call.
Definition: channel.h:339
enum sip_cc_notify_state state
Definition: chan_sip.c:959
Tone Indication Support.
static int ast_to_misdn_pres(int presentation)
Definition: chan_misdn.c:2145
static int misdn_digit_begin(struct ast_channel *chan, char digit)
Definition: chan_misdn.c:6909
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2022
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
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:442
char digit
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:7434
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char mohinterpret[MAX_MUSICCLASS]
Definition: chan_alsa.c:119
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:1494
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
static int stop_indicate(struct chan_list *cl)
Definition: chan_misdn.c:7743
struct ast_party_dialed::@246 number
Dialed/Called number.
Music on hold handling.
int jb_len
Jitterbuffer length.
Definition: chan_misdn.c:490
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
static struct chan_list * find_hold_call(struct misdn_bchannel *bc)
Definition: chan_misdn.c:8283
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
const char * ast_named_caller_presentation(int data)
Convert caller ID pres value to text code.
Definition: callerid.c:1182
int faxdetect
Fax detection option. (0:no 1:yes 2:yes+nojump)
Definition: chan_misdn.c:461
void debug_numtype(int port, int numtype, char *type)
Definition: chan_misdn.c:5853
struct FacParm fac_out
Outbound FACILITY message function type and contents.
Definition: isdn_lib.h:512
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int misdn_cfg_get_next_port_spin(int port)
Definition: misdn_config.c:946
static void hanguptone_indicate(struct chan_list *cl)
Definition: chan_misdn.c:7738
static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
Definition: chan_misdn.c:8889
const char *const type
Definition: channel.h:630
#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:1832
struct chan_list * next
Next channel call record in the list.
Definition: chan_misdn.c:608
Asterisk main include file. File version handling, generic pbx functions.
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
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4729
static char * handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4230
struct ast_party_id priv_to
Call is redirecting to a new party (Sent to the caller) - private representation. ...
Definition: channel.h:540
char ast_rd_buf[4096]
Read buffer for inbound audio from pipe[0].
Definition: chan_misdn.c:449
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:387
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:7472
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
static void update_config(struct chan_list *ch)
Updates caller ID information from config.
Definition: chan_misdn.c:5761
void * ast_channel_generatordata(const struct ast_channel *chan)
struct ast_set_party_id ani
Definition: channel.h:445
int misdn_lib_pid_restart(int pid)
Definition: isdn_lib.c:3932
struct ast_party_id ast_channel_redirecting_effective_from(struct ast_channel *chan)
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
static char * handle_cli_misdn_port_down(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3940
struct ast_dsp * dsp
Allocated DSP controller.
Definition: chan_misdn.c:510
static int read_config(struct chan_list *ch)
Definition: chan_misdn.c:5922
union misdn_bchannel::@161 AOCD
static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
Definition: chan_misdn.c:2000
String manipulation functions.
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:296
int need_hangup
TRUE if a channel can be hung up by calling asterisk directly when done.
Definition: chan_misdn.c:397
int nodsp
TRUE if we will not use jollys dsp.
Definition: isdn_lib.h:474
void misdn_cfg_destroy(void)
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
int need_queue_hangup
TRUE if a hangup needs to be queued.
Definition: chan_misdn.c:392
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
struct ast_party_id id
Connected party ID.
Definition: channel.h:459
void ast_party_id_reset(struct ast_party_id *id)
Destroy and initialize the given party id structure.
Definition: channel.c:1896
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition: causes.h:121
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
int misdn_cfg_get_next_port(int port)
Definition: misdn_config.c:929
int addr
From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid() ...
Definition: chan_misdn.c:547
static void misdn_update_redirecting(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
Definition: chan_misdn.c:6483
int txgain
Tx gain setting (range -8 to 8)
Definition: isdn_lib.h:708
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
static struct ast_channel * misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int port, int c)
Definition: chan_misdn.c:8174
struct ast_party_id priv_orig
Who originally redirected the call (Sent to the party the call is redirected toward) - private repres...
Definition: channel.h:534
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:174
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:438
int presentation
User set presentation restriction code 0=Allowed, 1=Restricted, 2=Unavailable.
Definition: isdn_lib.h:600
#define bc
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
char * ok
Definition: chan_misdn.c:134
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:528
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:1770
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
char uu[256]
User-User information string.
Definition: isdn_lib.h:663
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:97
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
static int misdn_attempt_transfer(struct chan_list *active_ch, struct chan_list *held_ch)
Definition: chan_misdn.c:8619
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:444
static char * handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5564
void misdn_dump_chanlist(void)
Definition: isdn_lib.c:483
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
Convenient Signal Processing routines.
#define COLOR_YELLOW
Definition: term.h:54
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.
static void misdn_update_caller_id(struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag)
Definition: chan_misdn.c:6171
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1584
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:120
static int misdn_to_ast_pres(int presentation)
Definition: chan_misdn.c:2117
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
static void cl_queue_chan(struct chan_list *chan)
Definition: chan_misdn.c:8377
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Call Pickup API.
static void release_chan_early(struct chan_list *ch)
Definition: chan_misdn.c:8561
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:374
static int pbx_start_chan(struct chan_list *ch)
Definition: chan_misdn.c:8438
int bframe_len
B channel speech sample data buffer size.
Definition: isdn_lib.h:435
descriptor for a cli entry.
Definition: cli.h:171
void manager_ec_enable(struct misdn_bchannel *bc)
Definition: isdn_lib.c:4628
const int argc
Definition: cli.h:160
static int cl_dequeue_chan(struct chan_list *chan)
Definition: chan_misdn.c:8398
#define LOG_WARNING
Definition: logger.h:274
struct misdn_jb * jb
Allocated jitterbuffer controller.
Definition: chan_misdn.c:503
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
#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:6300
struct ast_jb_conf * misdn_get_global_jbconf(void)
static int misdn_hangup(struct ast_channel *ast)
Definition: chan_misdn.c:7117
static void dummy(char *unused,...)
Definition: chan_unistim.c:220
void misdn_jb_destroy(struct misdn_jb *jb)
frees the data and destroys the given jitterbuffer struct
Definition: chan_misdn.c:12639
int faxdetect_timeout
Number of seconds to detect a Fax machine when detection enabled.
Definition: chan_misdn.c:468
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
static const struct allowed_bearers allowed_bearers_array[]
Definition: chan_misdn.c:2362
void misdn_cfg_get_config_string(int port, enum misdn_cfg_elements elem, char *buf, int bufsize)
Definition: misdn_config.c:805
int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun).
Definition: chan_misdn.c:12650
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
misdn_cfg_elements
static int timeout
Definition: cdr_mysql.c:86
struct ast_party_id priv_from
Who is redirecting the call (Sent to the party the call is redirected toward) - private representatio...
Definition: channel.h:537
static int tmp()
Definition: bt_open.c:389
struct robin_list * next
Definition: chan_misdn.c:623
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
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:8495
struct ast_tone_zone * ast_channel_zone(const struct ast_channel *chan)
int add_out_calls(int port)
Definition: chan_misdn.c:8859
int misdn_cfg_init(int max_ports, int reload)
#define var
Definition: ast_expr2f.c:614
int size
Definition: chan_misdn.c:132
struct ast_frame frame
Inbound audio frame returned by misdn_read().
Definition: chan_misdn.c:454
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
int misdn_cfg_is_port_valid(int port)
Definition: misdn_config.c:737
static int misdn_tasks_add(int timeout, ast_sched_cb callback, const void *data)
Definition: chan_misdn.c:3604
int norxtone
Definition: chan_misdn.c:415
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
struct hold_info hold
HELD channel call information.
Definition: chan_misdn.c:535
int jb_upper_threshold
Jitterbuffer upper threshold.
Definition: chan_misdn.c:496
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:152
static const char desc[]
Definition: cdr_mysql.c:73
int presentation
Number presentation restriction code 0=Allowed, 1=Restricted, 2=Unavailable.
Definition: isdn_lib.h:277
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
Definition: sched.c:524
int state_buffer
Definition: chan_misdn.c:138
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:605
static struct robin_list * robin
Definition: chan_misdn.c:626
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
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
static void config_jitterbuffer(struct chan_list *ch)
Definition: chan_misdn.c:5817
static const char * misdn_get_ch_state(struct chan_list *p)
Definition: chan_misdn.c:4102
void misdn_cfg_reload(void)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
char * str
Subscriber name (Malloced)
Definition: channel.h:265
static char * handle_cli_misdn_set_tics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4339
static struct chan_list * find_hold_active_call(struct misdn_bchannel *bc)
Definition: chan_misdn.c:8351
Definition: astman.c:222
Definition of a media format.
Definition: format.c:43
static struct chan_list * get_chan_by_ast_name(const char *name)
Definition: chan_misdn.c:786
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:6437
char txt[255]
Definition: chan_misdn.c:4080
struct ast_party_id ast_channel_redirecting_effective_to(struct ast_channel *chan)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
#define MISDN_ASTERISK_TECH_PVT(ast)
Definition: chan_misdn.c:683
#define AST_DEFINE_APP_ARGS_TYPE(type, arglist)
Define a structure type to hold an application&#39;s arguments.
static struct ast_threadstorage buf2
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static char * handle_cli_misdn_restart_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3874
int(* generate)(struct ast_channel *chan, void *data, int len, int samples)
Definition: channel.h:234
static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
Definition: chan_misdn.c:8875
int capability
SETUP message bearer capability field code value.
Definition: isdn_lib.h:609
#define ast_mutex_lock(a)
Definition: lock.h:187
void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc)
Definition: isdn_lib.c:2276
#define ao2_unlock(a)
Definition: astobj2.h:730
static struct test_val c
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:539
Definition: muted.c:95
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
char * text
Definition: app_queue.c:1508
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
static int * misdn_debug_only
Definition: chan_misdn.c:695
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
void misdn_lib_destroy(void)
Definition: isdn_lib.c:4285
static const char * misdn_to_str_pres(int presentation)
Definition: chan_misdn.c:2084
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:2404
const char * str
Definition: app_jack.c:147
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
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
const char * args
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
int AOCD_need_export
TRUE if AOCDtype and AOCD data are ready to export to Asterisk.
Definition: isdn_lib.h:521
#define NULL
Definition: resample.c:96
char context[AST_MAX_CONTEXT]
Incoming call dialplan context identifier.
Definition: chan_misdn.c:553
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:559
#define COLOR_BRWHITE
Definition: term.h:62
static struct chan_list * cl_te
Global channel call record list head.
Definition: chan_misdn.c:704
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:119
Common implementation-independent jitterbuffer stuff.
int value
Definition: syslog.c:37
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
ast_transfer_result
Definition: bridge.h:1115
static char * handle_cli_misdn_restart_pid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3896
#define AST_FRAME_DTMF
static int misdn_chan_is_valid(struct chan_list *ch)
Definition: chan_misdn.c:749
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:8786
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition: causes.h:115
struct ast_channel * ast
Associated Asterisk channel structure.
Definition: chan_misdn.c:515
static int priority
const char * ext
Definition: http.c:147
static const char * misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
Definition: chan_misdn.c:1958
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len)
Definition: chan_misdn.c:12574
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define AST_PRES_NETWORK_NUMBER
Definition: callerid.h:321
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
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
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:511
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:463
static void chan_list_destructor(void *obj)
Definition: chan_misdn.c:7792
misdn_hold_state
Definition: chan_misdn.c:347
Indicate what information in ast_party_caller should be set.
Definition: channel.h:441
int notxtone
TRUE if we are not to generate tones (Playtones)
Definition: chan_misdn.c:420
void misdn_cfg_get_name(enum misdn_cfg_elements elem, void *buf, int bufsize)
Definition: misdn_config.c:655
static char * handle_cli_misdn_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4144
const char * line
Definition: cli.h:162
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
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:4194
static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
Definition: chan_misdn.c:8659
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
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:3609
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:9904
static pthread_t misdn_tasks_thread
Definition: chan_misdn.c:671
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:603
enum event_response_e(* cb_event)(enum event_e event, struct misdn_bchannel *bc, void *user_data)
Definition: isdn_lib.h:729
char * ast_print_group(char *buf, int buflen, ast_group_t group)
Print call and pickup groups into buffer.
Definition: channel.c:8133
Media Format API.
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
#define AST_PRES_RESTRICTED
Definition: callerid.h:325
threshold
Definition: dsp.h:71
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int stop_bc_tones(struct chan_list *cl)
Definition: chan_misdn.c:7772
struct ast_set_party_id from
Definition: channel.h:560
int misdn_cfg_is_group_method(char *group, enum misdn_cfg_method meth)
Definition: misdn_config.c:744
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
static void misdn_tasks_destroy(void)
Definition: chan_misdn.c:3574
static const struct state_struct state_array[]
Definition: chan_misdn.c:4083
static void misdn_tasks_init(void)
Definition: chan_misdn.c:3554
static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
Definition: chan_misdn.c:6958
Number structure.
Definition: app_followme.c:154
#define BUFFERSIZE
static void print_facility(const struct FacParm *fac, const struct misdn_bchannel *bc)
Definition: chan_misdn.c:2762
static int misdn_l1_task(const void *vdata)
Definition: chan_misdn.c:3619
struct ast_party_id id
Caller party ID.
Definition: channel.h:421
static char * handle_cli_misdn_port_unblock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3852
void ast_change_name(struct ast_channel *chan, const char *newname)
Change channel name.
Definition: channel.c:6854
Configuration File Parser.
static char * handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5611
static ast_mutex_t release_lock
Definition: chan_misdn.c:323
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:452
static struct ast_frame * process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
Definition: chan_misdn.c:7318
#define ast_log
Definition: astobj2.c:42
int set_presentation
TRUE if the user set the presentation restriction code.
Definition: isdn_lib.h:603
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
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:3962
char * samples
Definition: chan_misdn.c:134
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
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:6824
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:9202
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:428
static char * complete_ch(struct ast_cli_args *a)
Definition: chan_misdn.c:5654
int pri
TRUE if ISDN-PRI (ISDN-BRI otherwise)
Definition: isdn_lib.h:367
General Asterisk PBX channel definitions.
#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:1874
void ast_channel_rings_set(struct ast_channel *chan, int value)
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
const char * src
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:7393
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static int load_module(void)
Load the module.
Definition: chan_misdn.c:11315
void ast_channel_generatordata_set(struct ast_channel *chan, void *value)
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:159
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
static char * handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3720
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
const int n
Definition: cli.h:165
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize)
Definition: misdn_config.c:569
static struct ast_cli_entry chan_misdn_clis[]
Definition: chan_misdn.c:5734
static void misdn_tasks_remove(int task_id)
Definition: chan_misdn.c:3614
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define ast_register_application(app, execute, synopsis, description)
Register an application.
Definition: module.h:610
void misdn_lib_release(struct misdn_bchannel *bc)
Definition: isdn_lib.c:1759
int overlap_dial_task
Overlap dialing timeout Task ID. -1 if not running.
Definition: chan_misdn.c:593
ast_cond_t cond
Definition: app_meetme.c:1090
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
Scheduler Routines (derived from cheops)
static int misdn_call(struct ast_channel *ast, const char *dest, int timeout)
Definition: chan_misdn.c:6554
Caller Party information.
Definition: channel.h:419
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
int dropped_frame_cnt
Number of outgoing audio frames dropped since last debug gripe message.
Definition: chan_misdn.c:564
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
Asterisk internal frame definitions.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
static const char * misdn_to_str_screen(int screening)
Definition: chan_misdn.c:2173
#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:85
void misdn_cfg_get_ports_string(char *ports)
Generate a comma separated list of all active ports.
Definition: misdn_config.c:779
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:718
static char * handle_cli_misdn_show_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4421
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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
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:227
#define AST_BRIDGE_DTMF_CHANNEL_1
Report DTMF on channel 1.
Definition: channel.h:2384
struct ast_set_party_id id
Definition: channel.h:443
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
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:9215
int nojitter
TRUE if we will not use the jitter buffer system.
Definition: isdn_lib.h:477
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
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:473
static struct chan_list * find_chan_by_bc(struct misdn_bchannel *bc)
Definition: chan_misdn.c:8259
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
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:696
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:4179
struct FacAOCDCurrency currency
Definition: isdn_lib.h:517
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
char * bc_state2str(enum bchannel_state state)
Definition: isdn_lib.c:617
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1191
enum misdn_chan_state state
State of the channel.
Definition: chan_misdn.c:386
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:570
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
static char global_tracefile[BUFFERSIZE+1]
Definition: chan_misdn.c:127
const char * ast_channel_exten(const struct ast_channel *chan)
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:1139
void misdn_cfg_update_ptp(void)
struct ast_set_party_id priv
Definition: channel.h:496
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:5682
#define MISDN_ASTERISK_TECH_PVT_SET(ast, value)
Definition: chan_misdn.c:684
int port
Logical port the channel call record is HELD on because the B channel is no longer associated...
Definition: chan_misdn.c:362
int misdn_lib_is_ptp(int port)
Definition: isdn_lib.c:128
Format Capabilities API.
enum misdn_cfg_elements misdn_cfg_get_elem(const char *name)
Definition: misdn_config.c:634
#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:4167
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
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:161
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:8811
struct robin_list * prev
Definition: chan_misdn.c:624
char allowed_bearers[BUFFERSIZE+1]
The "allowed_bearers" string read in from /etc/asterisk/misdn.conf.
Definition: chan_misdn.c:381
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:407
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:8725
int dec
TRUE if allocate higher B channels first.
Definition: isdn_lib.h:395
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:2373
static void free_robin_list(void)
Definition: chan_misdn.c:629
static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
Definition: chan_misdn.c:7478
static void sighandler(int sig)
Definition: chan_misdn.c:3524
#define LOG_ERROR
Definition: logger.h:285
struct ast_generator * ast_channel_generator(const struct ast_channel *chan)
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:200
static int misdn_check_l2l1(struct ast_channel *chan, const char *data)
Definition: chan_misdn.c:12291
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
static char * handle_cli_misdn_port_block(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3830
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:1999
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static char * handle_cli_misdn_set_crypt_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3807
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_party_id ast_channel_connected_effective_id(struct ast_channel *chan)
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int tracing
Definition: chan_misdn.c:692
static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
Definition: chan_misdn.c:3424
unsigned char number
Definition: channel.h:366
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:294
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
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:2242
static struct chan_list * find_hold_call_l3(unsigned long l3_id)
Definition: chan_misdn.c:8317
static int * misdn_debug
Definition: chan_misdn.c:694
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static struct ast_sched_context * misdn_tasks
the main schedule context for stuff like l1 watcher, overlap dial, ...
Definition: chan_misdn.c:670
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:6210
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
int errno
Description of a tone.
Definition: indications.h:35
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:455
static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_misdn.c:6915
static struct ast_channel * misdn_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Definition: chan_misdn.c:7855
Connected Line/Party information.
Definition: channel.h:457
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
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:7866
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:432
static int misdn_overlap_dial_task(const void *data)
Definition: chan_misdn.c:3628
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
int port
Logical Layer 1 port associated with this B channel.
Definition: isdn_lib.h:370
static int glob_channel
Definition: chan_misdn.c:8148
char * group
Definition: chan_misdn.c:620
int add_in_calls(int port)
Definition: chan_misdn.c:8844
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:523
#define LOG_NOTICE
Definition: logger.h:263
struct misdn_party_dialing dialed
Dialed/Called information struct.
Definition: isdn_lib.h:337
static void misdn_tasks_wakeup(void)
Definition: chan_misdn.c:3586
struct ast_format_cap * capabilities
Definition: channel.h:633
#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:3987
void misdn_cfg_get_desc(enum misdn_cfg_elements elem, void *buf, int bufsize, void *buf_default, int bufsize_default)
Definition: misdn_config.c:681
static const char misdn_type[]
Definition: chan_misdn.c:690
#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:7707
ast_mutex_t overlap_tv_lock
overlap_tv access lock.
Definition: chan_misdn.c:598
static struct ast_channel_tech misdn_tech
Definition: chan_misdn.c:8130
#define ORG_MISDN
Definition: chan_misdn.c:345
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
static int unload_module(void)
Definition: chan_misdn.c:11262
static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast)
Definition: chan_misdn.c:6382
static char * handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5183
int misdn_lib_get_port_up(int port)
Definition: isdn_lib.c:1781
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1755
#define AST_MAX_CONTEXT
Definition: channel.h:136
static const char name[]
Definition: cdr_mysql.c:74
int source
Information about the source of an update.
Definition: channel.h:483
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
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:673
int active
Seems to have been intended for something to do with the jitter buffer.
Definition: isdn_lib.h:537
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
#define AST_CAUSE_NUMBER_CHANGED
Definition: causes.h:111
static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
Definition: chan_misdn.c:2314
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:5189
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:163
static int _misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data, int variable)
Definition: chan_misdn.c:3591
static void reload_config(void)
Definition: chan_misdn.c:4123
static void * misdn_tasks_thread_func(void *data)
Definition: chan_misdn.c:3528
#define pthread_create
Definition: lock.h:640
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
Channel call record structure.
Definition: chan_misdn.c:377
static char * handle_cli_misdn_send_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5477
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:193
static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
Definition: chan_misdn.c:1916
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
static int request(void *obj)
Definition: chan_pjsip.c:2559
unsigned int inheritance
Definition: datastore.h:73
static int update_ec_config(struct misdn_bchannel *bc)
Definition: chan_misdn.c:5903
static int * misdn_out_calls
Definition: chan_misdn.c:699
static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
Definition: chan_misdn.c:3381
unsigned int l3id
From associated B channel: Layer 3 process ID.
Definition: chan_misdn.c:541
int to_changed
TRUE if the redirecting.to information has changed.
Definition: isdn_lib.h:319
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:543
int(* ast_sched_cb)(const void *data)
scheduler callback
Definition: sched.h:175
#define chan_list_ref(obj, debug)
Definition: chan_misdn.c:371
enum misdn_hold_state state
Call HOLD state.
Definition: chan_misdn.c:357
static struct chan_list * chan_list_init(int orig)
Definition: chan_misdn.c:7831
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
int channel
Original B channel number the HELD call was using.
Definition: chan_misdn.c:368
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
int MAXTICS
Definition: chan_misdn.c:612
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct timeval delivery
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:490
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
Definition: chan_misdn.c:8447
const char * usage
Definition: cli.h:177
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
static int g_config_initialized
Definition: chan_misdn.c:129
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...
#define AST_PRES_RESTRICTION
Definition: callerid.h:323
static void print_bearer(struct misdn_bchannel *bc)
Definition: chan_misdn.c:3355
#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:3458
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2952
int out_cause
Q.931 Cause for disconnection code (sent)
Definition: isdn_lib.h:677
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
#define CLI_SUCCESS
Definition: cli.h:44
char * tag
User-set "tag".
Definition: channel.h:355
struct ast_set_party_id id
Definition: channel.h:492
void ast_deactivate_generator(struct ast_channel *chan)
Definition: channel.c:2902
void * data
Definition: datastore.h:70
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition: channel.c:2179
char * strsep(char **str, const char *delims)
struct ast_set_party_id to
Definition: channel.h:562
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
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:582
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
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:556
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int reload(void)
Definition: chan_misdn.c:11538
int count
Number of times the call was redirected.
Definition: channel.h:549
Standard Command Line Interface.
misdn_chan_state
Definition: chan_misdn.c:325
int ast_channel_hangupcause(const struct ast_channel *chan)
static int start_bc_tones(struct chan_list *cl)
Definition: chan_misdn.c:7764
void ast_channel_context_set(struct ast_channel *chan, const char *value)
struct ast_party_id to
Call is redirecting to a new party (Sent to the caller)
Definition: channel.h:531
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
int faxhandled
TRUE if a fax has been detected.
Definition: chan_misdn.c:478
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
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
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10765
const char * ast_channel_name(const struct ast_channel *chan)
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
Definition: channel.c:2122
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1968
const int pos
Definition: cli.h:164
#define AST_CAUSE_USER_BUSY
Definition: causes.h:106
int misdn_lib_get_port_down(int port)
Definition: isdn_lib.c:1805
void ast_channel_transfercapability_set(struct ast_channel *chan, unsigned short value)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
enum mISDN_NOTIFY_CODE notify_description_code
Notification indicator ie description code.
Definition: isdn_lib.h:606
static ENTRY retval
Definition: hsearch.c:50
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:7011
#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:678
static char * complete_debug_port(struct ast_cli_args *a)
Definition: chan_misdn.c:5659
mISDN_NUMBER_TYPE
Definition: isdn_lib.h:101
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:431
static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
Definition: chan_misdn.c:6226
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: main/cli.c:1830
Data structure associated with a single frame of data.
int progress_indicator
Progress Indicator IE progress description field. Used to determine if there is an inband audio messa...
Definition: isdn_lib.h:492
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:2153
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:133
#define ORG_AST
Definition: chan_misdn.c:343
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:302
int ec_deftaps
Number of taps in the echo cancellor when enabled.
Definition: isdn_lib.h:693
int misdn_lib_port_restart(int port)
Definition: isdn_lib.c:3982
static int * ptp
Definition: misdn_config.c:436
const char * ast_channel_context(const struct ast_channel *chan)
Handy terminal functions for vt* terms.
const char * data
Description of a tone.
Definition: indications.h:52
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
union ast_frame::@263 data
#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
char * bframe
B channel speech sample data buffer.
Definition: isdn_lib.h:432
static int * misdn_in_calls
Definition: chan_misdn.c:698
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:10392
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:1568
#define AST_PRES_UNAVAILABLE
Definition: callerid.h:326
#define ast_mutex_init(pmutex)
Definition: lock.h:184
int state_full
Definition: chan_misdn.c:137
#define ast_channel_trylock(chan)
Definition: channel.h:2947
static void send_digit_to_chan(struct chan_list *cl, char digit)
Definition: chan_misdn.c:3681
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:12168
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
char info_dad[MISDN_MAX_NUMBER_LEN]
Current overlap dialing digits to/from INFORMATION messages.
Definition: isdn_lib.h:650
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:116
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
#define ast_mutex_destroy(a)
Definition: lock.h:186
static struct robin_list * get_robin_position(char *group)
Definition: chan_misdn.c:641
struct ast_format * format
static char * handle_cli_misdn_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4303
static char * handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:5509
const char * ast_channel_macrocontext(const struct ast_channel *chan)
static void update_name(struct ast_channel *tmp, int port, int c)
Definition: chan_misdn.c:8150
void ast_set_party_id_all(struct ast_set_party_id *update_id)
Set the update marker to update all information of a corresponding party id.
Definition: channel.c:1750
Redirecting information struct.
Definition: isdn_lib.h:305
struct misdn_bchannel * bc
Associated B channel structure.
Definition: chan_misdn.c:520
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:372
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:110
void ast_channel_priority_set(struct ast_channel *chan, int value)
Bridging API.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
Asterisk module definitions.
int bytes_wrote
Definition: chan_misdn.c:139
static struct keys keys
static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
Definition: chan_misdn.c:2274
struct misdn_jb * misdn_jb_init(int size, int upper_threshold)
allocates the jb-structure and initialize the elements
Definition: chan_misdn.c:12602
static int misdn_to_ast_screen(int screening)
Definition: chan_misdn.c:2210
char * ast_print_namedgroups(struct ast_str **buf, struct ast_namedgroups *groups)
Print named call groups and named pickup groups.
Definition: channel.c:8158
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:12716
static snd_pcm_format_t format
Definition: chan_alsa.c:102
void(* cb_log)(int level, int port, char *tmpl,...)
Definition: isdn_lib.c:32
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:2390
struct FacParm fac_in
Inbound FACILITY message function type and contents.
Definition: isdn_lib.h:507
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
Definition: chan_misdn.c:6975
int misdn_cfg_is_msn_valid(int port, char *msn)
Definition: misdn_config.c:712
static char * handle_cli_misdn_show_stacks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4361
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel. ...
Definition: channel.c:4391
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
int overlap_dial
Enables overlap dialing for the set amount of seconds. (0 = Disabled)
Definition: chan_misdn.c:588
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:705
static int misdn_set_opt_exec(struct ast_channel *chan, const char *data)
Definition: chan_misdn.c:12365
struct FacAOCDChargingUnit chargingUnit
Definition: isdn_lib.h:518
#define AST_BRIDGE_DTMF_CHANNEL_0
Report DTMF on channel 0.
Definition: channel.h:2382
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
Definition: channel.c:2135
Structure for mutex and tracking information.
Definition: lock.h:135
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:413
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:9095
static char * handle_cli_misdn_show_ports_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:4392
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:6135
static char * handle_cli_misdn_port_up(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_misdn.c:3918
static enum event_response_e cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
Definition: chan_misdn.c:9917
Media Format Cache API.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
event_e
Definition: isdn_lib.h:119
#define ast_mutex_unlock(a)
Definition: lock.h:188
Configuration relating to call pickup.
ast_bridge_result
Definition: channel.h:207
#define AST_APP_ARG(name)
Define an application argument.
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:1008
int state_empty
Definition: chan_misdn.c:136
static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
Definition: chan_misdn.c:2042
int nttimeout
TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
Definition: chan_misdn.c:576
static struct test_val a
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343
int toggle_ec
TRUE if echo canceller is enabled. Value is toggled.
Definition: chan_misdn.c:425
#define max(a, b)
Definition: f2c.h:198