1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
17 int action_timeout(struct lcr_timer *timer, void *instance, int index);
18 int match_timeout(struct lcr_timer *timer, void *instance, int index);
19 int redial_timeout(struct lcr_timer *timer, void *instance, int index);
20 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index);
21 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index);
22 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index);
23 int password_timeout(struct lcr_timer *timer, void *instance, int index);
24 int callback_timeout(struct lcr_timer *timer, void *instance, int index);
27 * EndpointAppPBX constructor
29 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
31 class EndpointAppPBX **apppointer;
33 memset(&e_crypt_handler, 0, sizeof(e_crypt_handler));
34 add_timer(&e_crypt_handler, crypt_handler, this, 0);
35 memset(&e_vbox_refresh, 0, sizeof(e_vbox_refresh));
36 add_timer(&e_vbox_refresh, vbox_refresh, this, 0);
37 memset(&e_action_timeout, 0, sizeof(e_action_timeout));
38 add_timer(&e_action_timeout, action_timeout, this, 0);
39 memset(&e_match_timeout, 0, sizeof(e_match_timeout));
40 add_timer(&e_match_timeout, match_timeout, this, 0);
41 memset(&e_redial_timeout, 0, sizeof(e_redial_timeout));
42 add_timer(&e_redial_timeout, redial_timeout, this, 0);
43 memset(&e_powerdial_timeout, 0, sizeof(e_powerdial_timeout));
44 add_timer(&e_powerdial_timeout, powerdial_timeout, this, 0);
45 memset(&e_cfnr_timeout, 0, sizeof(e_cfnr_timeout));
46 add_timer(&e_cfnr_timeout, cfnr_timeout, this, 0);
47 memset(&e_cfnr_call_timeout, 0, sizeof(e_cfnr_call_timeout));
48 add_timer(&e_cfnr_call_timeout, cfnr_call_timeout, this, 0);
49 memset(&e_callback_timeout, 0, sizeof(e_callback_timeout));
50 add_timer(&e_callback_timeout, callback_timeout, this, 0);
51 memset(&e_password_timeout, 0, sizeof(e_password_timeout));
52 add_timer(&e_password_timeout, password_timeout, this, 0);
55 /* add application to chain */
57 apppointer = &apppbx_first;
59 apppointer = &((*apppointer)->next);
63 memset(&e_ext, 0, sizeof(struct extension));
64 // *************** NOTE: also change value in read_extension() **************
65 e_ext.rights = 4; /* international */
66 e_ext.rx_gain = e_ext.tx_gain = 0;
67 e_state = EPOINT_STATE_IDLE;
68 e_ext.number[0] = '\0';
69 e_extension_interface[0] = '\0';
70 memset(&e_callerinfo, 0, sizeof(struct caller_info));
71 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
72 memset(&e_connectinfo, 0, sizeof(struct connect_info));
73 memset(&e_redirinfo, 0, sizeof(struct redir_info));
74 memset(&e_capainfo, 0, sizeof(struct capa_info));
75 memset(&e_rtpinfo, 0, sizeof(struct rtp_info));
78 e_ruleset = ruleset_main;
80 e_rule = e_ruleset->rule_first;
83 e_match_to_action = NULL;
85 e_extdialing = e_dialinginfo.id;
89 // e_join_tone[0] = e_hold_tone[0] = '\0';
90 e_join_pattern /*= e_hold_pattern*/ = 0;
92 e_adminid = 0; // will be set, if call was initiated via admin socket
95 e_cbdialing[0] = '\0';
98 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
104 e_multipoint_cause = 0;
105 e_multipoint_location = 0;
106 e_dialing_queue[0] = '\0';
108 e_crypt_state = CM_ST_NULL;
109 e_crypt_keyengine_busy = 0;
110 e_crypt_info[0] = '\0';
113 e_tx_state = NOTIFY_STATE_ACTIVE;
114 e_rx_state = NOTIFY_STATE_ACTIVE;
115 e_join_cause = e_join_location = 0;
116 /*********************************
117 *********************************
118 ********* ATTENTION *************
119 *********************************
120 *********************************/
121 /* if you add new values, that must be initialized, also check if they must
122 * be initialized when doing callback
128 * EpointAppPBX destructor
130 EndpointAppPBX::~EndpointAppPBX(void)
132 class EndpointAppPBX *temp, **tempp;
134 del_timer(&e_crypt_handler);
135 del_timer(&e_vbox_refresh);
136 del_timer(&e_action_timeout);
137 del_timer(&e_match_timeout);
138 del_timer(&e_redial_timeout);
139 del_timer(&e_powerdial_timeout);
140 del_timer(&e_cfnr_timeout);
141 del_timer(&e_cfnr_call_timeout);
142 del_timer(&e_callback_timeout);
143 del_timer(&e_password_timeout);
147 tempp = &apppbx_first;
156 FATAL("Endpoint not in endpoint's list.\n");
163 * trace header for application
165 void EndpointAppPBX::trace_header(const char *name, int direction)
169 char msgtext[sizeof(_trace.name)];
173 /* init trace with given values */
176 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
180 ea_endpoint->ep_serial,
187 /* set new endpoint state
189 void EndpointAppPBX::new_state(int state)
192 if (e_state != state) {
193 trace_header("NEW STATE", DIRECTION_NONE);
194 add_trace("state", "old", "%s", state_name[e_state]);
195 add_trace("state", "new", "%s", state_name[state]);
203 /* release join and port (as specified)
205 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force)
207 struct port_list *portlist;
208 struct lcr_msg *message;
211 /* message to test call */
212 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
214 /* if a release is pending */
215 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
216 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
217 if (ea_endpoint->ep_join_id) {
218 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
219 message->param.disconnectinfo.cause = joincause;
220 message->param.disconnectinfo.location = joinlocation;
221 message_put(message);
222 ea_endpoint->ep_join_id = 0;
226 if (release != RELEASE_PORT_JOINONLY) {
228 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
233 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
234 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
235 while((portlist = ea_endpoint->ep_portlist)) {
236 if (portlist->port_id) {
237 SPRINT(cause, "cause_%02x", portcause);
238 set_tone(portlist, cause);
239 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
240 message->param.disconnectinfo.cause = portcause;
241 message->param.disconnectinfo.location = portlocation;
242 message->param.disconnectinfo.force = force; // set, if port should release imediately
243 message_put(message);
244 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
246 ea_endpoint->free_portlist(portlist);
249 /* if callback is enabled, call back with the given caller id */
250 if (e_callback_timeout.active) {
251 /* reset some stuff */
252 new_state(EPOINT_STATE_IDLE);
253 memset(&e_connectinfo, 0, sizeof(struct connect_info));
254 memset(&e_redirinfo, 0, sizeof(struct redir_info));
255 e_start = e_stop = 0;
256 e_ruleset = ruleset_main;
258 e_rule = e_ruleset->rule_first;
260 unsched_timer(&e_action_timeout);
261 unsched_timer(&e_match_timeout);
262 unsched_timer(&e_cfnr_timeout);
263 unsched_timer(&e_cfnr_call_timeout);
264 e_match_to_action = NULL;
266 e_extdialing = e_dialinginfo.id;
272 e_multipoint_cause = 0;
273 e_multipoint_location = 0;
274 e_dialing_queue[0] = '\0';
276 e_crypt_state = CM_ST_NULL;
277 e_crypt_keyengine_busy = 0;
278 e_crypt_info[0] = '\0';
282 e_tx_state = NOTIFY_STATE_ACTIVE;
283 e_rx_state = NOTIFY_STATE_ACTIVE;
284 e_join_cause = e_join_location = 0;
286 /* the caller info of the callback user */
287 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
288 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
289 /* create dialing by callerinfo */
290 if (e_ext.number[0] && e_extension_interface[0]) {
291 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
292 /* create callback to the current terminal */
293 SCPY(e_dialinginfo.id, e_ext.number);
294 SCPY(e_dialinginfo.interfaces, e_extension_interface);
295 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
296 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
299 SCPY(e_dialinginfo.id, e_cbto);
301 /* numberrize caller id and use it to dial to the callback */
302 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
304 e_dialinginfo.itype = INFO_ITYPE_ISDN;
305 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
306 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
311 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
312 if (--ea_endpoint->ep_use <= 0) /* when e_lock is 0, the endpoint will be deleted */
313 trigger_work(&ea_endpoint->ep_delete);
319 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
320 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
322 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
324 /* caller id is not restricted, so we do nothing */
325 if (*present != INFO_PRESENT_RESTRICTED)
328 /* only extensions are restricted */
332 /* if we enabled anonymouse ignore */
333 if (ext->anon_ignore)
336 /* else we remove the caller id */
340 *ntype = INFO_NTYPE_UNKNOWN;
342 // *screen = INFO_SCREEN_USER;
343 // maybe we should not make voip address anonymous
346 // maybe it's no fraud to present extension id
348 // extension[0] = '\0';
353 /* used display message to display callerid as available */
354 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
356 static char display[81];
359 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
361 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
370 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
372 /* internal extension's caller id */
373 if (extension[0] && e_ext.display_int) {
375 SCAT(display, extension);
378 if (itype == INFO_ITYPE_VBOX)
379 SCAT(display, "(vbox)");
381 SCAT(display, "(int)");
384 /* external caller id */
385 if (!extension[0] && e_ext.display_ext) {
388 if (present == INFO_PRESENT_RESTRICTED)
389 SCAT(display, "anonymous");
391 SCAT(display, "unknown");
398 /* display if callerid is anonymouse but available due anon-ignore */
399 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
401 SCAT(display, "unknown");
404 SCAT(display, " anon");
407 /* display if callerid is anonymouse but available due anon-ignore */
408 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
411 if (present == INFO_PRESENT_RESTRICTED)
412 SCAT(display, "anonymous");
414 SCAT(display, "unknown");
419 SCAT(display, " fake");
423 if (name[0] && e_ext.display_name) {
424 if (!display[0] && cid[0])
435 * uses the current state to notify activity
437 void EndpointAppPBX::notify_active(void)
439 struct port_list *portlist = ea_endpoint->ep_portlist;
440 struct lcr_msg *message;
444 case NOTIFY_STATE_ACTIVE:
445 /* we are already active, so we don't do anything */
448 case NOTIFY_STATE_SUSPEND:
449 notify = INFO_NOTIFY_USER_RESUMED;
451 set_tone(portlist, NULL);
452 portlist = portlist->next;
454 portlist = ea_endpoint->ep_portlist;
457 case NOTIFY_STATE_HOLD:
458 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
460 set_tone(portlist, NULL);
461 portlist = portlist->next;
463 portlist = ea_endpoint->ep_portlist;
466 case NOTIFY_STATE_CONFERENCE:
467 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
469 set_tone(portlist, NULL);
470 portlist = portlist->next;
472 portlist = ea_endpoint->ep_portlist;
476 PERROR("unknown e_tx_state = %d\n", e_tx_state);
481 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
482 message->param.notifyinfo.notify = notify;
483 message_put(message);
484 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
485 portlist = portlist->next;
491 * keypad functions during call. one example to use this is to put a call on hold or start a conference
493 void EndpointAppPBX::keypad_function(char digit)
496 /* we must be in a call, in order to send messages to the call */
497 if (e_ext.number[0] == '\0') {
498 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
503 /* join conference */
505 if (ea_endpoint->ep_join_id == 0) {
506 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
509 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
515 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
519 /* crypt key-exchange */
521 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
532 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
537 /* set tone pattern for port */
538 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
540 struct lcr_msg *message;
545 /* store for suspended processes */
549 if (e_join_pattern /* pattern are provided */
550 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
551 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
552 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
553 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
554 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
555 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
556 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
557 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
558 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
559 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
560 && tone[0] && !!strncmp(tone,"crypt_*",6)) {
561 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
566 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
567 SCPY(message->param.tone.dir, e_ext.tones_dir);
568 SCPY(message->param.tone.name, tone);
569 message_put(message);
570 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
572 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
577 /* hunts for the given interface
578 * it does not need to have an mISDNport instance */
579 struct interface *EndpointAppPBX::hunt_interface(char *ifname)
581 struct interface *interface;
582 int there_is_an_external = 0;
584 interface = interface_first;
586 /* first find the given interface or, if not given, one with no extension */
589 if (!there_is_an_external && !(ifname && ifname[0])) {
590 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
591 add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
597 /* check for given interface */
598 if (ifname && ifname[0]) {
599 if (!strcasecmp(interface->name, ifname)) {
600 /* found explicit interface */
601 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
602 add_trace("interface", NULL, "%s", ifname);
607 if (interface->external) {
608 there_is_an_external = 1;
609 /* found non extension */
610 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
611 add_trace("interface", NULL, "%s", interface->name);
617 interface = interface->next;
626 * hunts an mISDNport that is available for an outgoing call
627 * if no ifname was given, any interface that is not an extension
630 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
632 struct interface *interface;
633 struct interface_port *ifport, *ifport_start;
634 struct select_channel *selchannel;
635 struct mISDNport *mISDNport;
637 int there_is_an_external = 0;
639 interface = interface_first;
641 /* first find the given interface or, if not given, one with no extension */
644 if (!there_is_an_external && !(ifname && ifname[0])) {
645 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
646 add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
652 /* check for given interface */
653 if (ifname && ifname[0]) {
654 if (!strcasecmp(interface->name, ifname)) {
655 /* found explicit interface */
656 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
657 add_trace("interface", NULL, "%s", ifname);
663 if (interface->external) {
664 there_is_an_external = 1;
665 /* found non extension */
666 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
667 add_trace("interface", NULL, "%s", interface->name);
673 interface = interface->next;
677 /* see if interface has ports */
678 if (!interface->ifport) {
680 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
681 add_trace("interface", NULL, "%s", interface->name);
683 interface = interface->next;
687 /* select port by algorithm */
688 ifport_start = interface->ifport;
690 if (interface->hunt == HUNT_ROUNDROBIN) {
691 while(ifport_start->next && index<interface->hunt_next) {
692 ifport_start = ifport_start->next;
695 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
696 add_trace("port", NULL, "%d", ifport_start->portnum);
697 add_trace("position", NULL, "%d", index);
702 ifport = ifport_start;
705 /* see if port is available */
706 if (!ifport->mISDNport) {
707 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
708 add_trace("port", NULL, "%d", ifport->portnum);
709 add_trace("position", NULL, "%d", index);
713 mISDNport = ifport->mISDNport;
715 /* see if port is administratively blocked */
717 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
718 add_trace("port", NULL, "%d", ifport->portnum);
719 add_trace("position", NULL, "%d", index);
724 /* see if link is up on PTP*/
725 if (mISDNport->l2hold && mISDNport->l2link<1) {
726 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
727 add_trace("port", NULL, "%d", ifport->portnum);
728 add_trace("position", NULL, "%d", index);
733 /* check for channel form selection list */
736 if (mISDNport->ss5) {
738 port = ss5_hunt_line(mISDNport);
740 *channel = port->p_m_b_channel;
741 trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
742 add_trace("port", NULL, "%d", ifport->portnum);
743 add_trace("position", NULL, "%d", index);
744 add_trace("channel", NULL, "%d", *channel);
750 selchannel = ifport->out_channel;
752 switch(selchannel->channel) {
753 case CHANNEL_FREE: /* free channel */
754 if (mISDNport->b_reserved >= mISDNport->b_num)
755 break; /* all channel in use or reserverd */
758 while(i < mISDNport->b_num) {
759 if (mISDNport->b_port[i] == NULL) {
760 *channel = i+1+(i>=15);
761 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
762 add_trace("port", NULL, "%d", ifport->portnum);
763 add_trace("position", NULL, "%d", index);
764 add_trace("channel", NULL, "%d", *channel);
772 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
773 add_trace("port", NULL, "%d", ifport->portnum);
774 add_trace("position", NULL, "%d", index);
778 case CHANNEL_ANY: /* don't ask for channel */
779 if (mISDNport->b_reserved >= mISDNport->b_num) {
780 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
781 add_trace("port", NULL, "%d", ifport->portnum);
782 add_trace("position", NULL, "%d", index);
783 add_trace("total", NULL, "%d", mISDNport->b_num);
784 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
786 break; /* all channel in use or reserverd */
788 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
789 add_trace("port", NULL, "%d", ifport->portnum);
790 add_trace("position", NULL, "%d", index);
792 *channel = CHANNEL_ANY;
795 case CHANNEL_NO: /* call waiting */
796 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
797 add_trace("port", NULL, "%d", ifport->portnum);
798 add_trace("position", NULL, "%d", index);
800 *channel = CHANNEL_NO;
804 if (selchannel->channel<1 || selchannel->channel==16) {
805 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
806 add_trace("port", NULL, "%d", ifport->portnum);
807 add_trace("position", NULL, "%d", index);
808 add_trace("channel", NULL, "%d", selchannel->channel);
810 break; /* invalid channels */
812 i = selchannel->channel-1-(selchannel->channel>=17);
813 if (i >= mISDNport->b_num) {
814 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
815 add_trace("port", NULL, "%d", ifport->portnum);
816 add_trace("position", NULL, "%d", index);
817 add_trace("channel", NULL, "%d", selchannel->channel);
818 add_trace("channels", NULL, "%d", mISDNport->b_num);
820 break; /* channel not in port */
822 if (mISDNport->b_port[i] == NULL) {
823 *channel = selchannel->channel;
824 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
825 add_trace("port", NULL, "%d", ifport->portnum);
826 add_trace("position", NULL, "%d", index);
827 add_trace("channel", NULL, "%d", *channel);
834 break; /* found channel */
835 selchannel = selchannel->next;
839 /* if channel was found, return mISDNport and channel */
841 /* setting next port to start next time */
842 if (interface->hunt == HUNT_ROUNDROBIN) {
846 interface->hunt_next = index;
852 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
853 add_trace("port", NULL, "%d", ifport->portnum);
854 add_trace("position", NULL, "%d", index);
858 /* go next port, until all ports are checked */
860 ifport = ifport->next;
863 ifport = interface->ifport;
865 if (ifport != ifport_start)
869 interface = interface->next;
873 return(NULL); /* no port found */
876 /* outgoing setup to port(s)
877 * ports will be created and a setup is sent if everything is ok. otherwhise
878 * the endpoint is destroyed.
880 void EndpointAppPBX::out_setup(int cfnr)
882 struct dialing_info dialinginfo;
884 struct port_list *portlist;
885 struct lcr_msg *message;
887 int cause = CAUSE_RESSOURCEUNAVAIL;
890 struct interface *interface;
891 struct mISDNport *mISDNport;
894 class EndpointAppPBX *atemp;
895 // char allowed_ports[256];
897 char ifname[sizeof(e_ext.interfaces)],
899 struct port_settings port_settings;
902 int mode = B_MODE_TRANSPARENT;
903 struct admin_list *admin;
905 /* set bchannel mode */
906 mode = e_capainfo.source_mode;
908 /* create settings for creating port */
909 memset(&port_settings, 0, sizeof(port_settings));
911 SCPY(port_settings.tones_dir, e_ext.tones_dir);
913 SCPY(port_settings.tones_dir, options.tones_dir);
914 port_settings.no_seconds = e_ext.no_seconds;
916 /* NOTE: currently the try_card feature is not supported. it should be used later to try another card, if the outgoing call fails on one port */
918 /* check what dialinginfo.itype we got */
919 switch(e_dialinginfo.itype) {
920 /* *********************** call to extension or vbox */
921 case INFO_ITYPE_ISDN_EXTENSION:
922 /* check if we deny incoming calls when we use an extension */
923 if (e_ext.noknocking) {
924 atemp = apppbx_first;
927 if (!strcmp(atemp->e_ext.number, e_ext.number))
932 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
933 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
934 return; /* must exit here */
937 /* FALL THROUGH !!!! */
938 case INFO_ITYPE_VBOX:
939 /* get dialed extension's info */
940 // SCPY(exten, e_dialinginfo.id);
941 // if (strchr(exten, ','))
942 // *strchr(exten, ',') = '\0';
943 // if (!read_extension(&e_ext, exten))
944 if (!read_extension(&e_ext, e_dialinginfo.id)) {
945 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
946 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
947 return; /* must exit here */
949 e_dialinginfo.sending_complete = 1;
951 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
952 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
957 /* string from unconditional call forward (cfu) */
960 /* present to forwarded party */
961 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
962 e_callerinfo.present = INFO_PRESENT_ALLOWED;
964 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
968 /* string from busy call forward (cfb) */
971 class EndpointAppPBX *checkapp = apppbx_first;
973 if (checkapp != this) { /* any other endpoint except our own */
974 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
975 /* present to forwarded party */
976 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
977 e_callerinfo.present = INFO_PRESENT_ALLOWED;
979 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
983 checkapp = checkapp->next;
987 /* string from no-response call forward (cfnr) */
990 /* when cfnr is done, out_setup() will setup the call */
992 /* present to forwarded party */
993 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
994 e_callerinfo.present = INFO_PRESENT_ALLOWED;
998 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
999 schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
1000 schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* call one second after release */
1001 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) setting time for call-forward-busy to %s with delay %ld.\n", ea_endpoint->ep_serial, e_ext.cfnr, e_ext.cfnr_delay);
1005 /* call to all internal interfaces */
1006 p = e_ext.interfaces;
1007 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1010 while(*p!=',' && *p!='\0')
1012 SCCAT(ifname, *p++);
1015 /* search interface */
1016 interface = hunt_interface(ifname);
1018 trace_header("INTERFACE (not found)", DIRECTION_NONE);
1019 add_trace("interface", NULL, "%s", ifname);
1023 /* found interface */
1024 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1026 if (interface->gsm_bs) {
1027 SPRINT(portname, "%s-%d-out", interface->name, 0);
1028 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
1032 if (interface->gsm_ms) {
1033 SPRINT(portname, "%s-%d-out", interface->name, 0);
1034 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
1038 if (interface->sip) {
1039 SPRINT(portname, "%s-%d-out", interface->name, 0);
1040 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
1044 /* hunt for mISDNport and create Port */
1045 mISDNport = hunt_port(ifname, &channel);
1047 trace_header("INTERFACE (busy)", DIRECTION_NONE);
1048 add_trace("interface", NULL, "%s", ifname);
1053 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1056 port = ss5_hunt_line(mISDNport);
1059 if (mISDNport->ifport->remote) {
1060 admin = admin_first;
1062 if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
1064 admin = admin->next;
1067 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
1068 add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
1072 port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
1074 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1077 FATAL("Failed to create Port instance\n");
1078 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1079 memset(&dialinginfo, 0, sizeof(dialinginfo));
1080 SCPY(dialinginfo.id, e_dialinginfo.id);
1081 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1082 dialinginfo.ntype = e_dialinginfo.ntype;
1083 /* create port_list relation */
1084 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, interface->is_earlyb == IS_YES);
1086 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1088 goto check_anycall_intern;
1090 /* directory.list */
1091 if (e_callerinfo.id[0] && e_ext.display_name) {
1092 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1094 SCPY(e_callerinfo.name, dirname);
1096 // dss1 = (class Pdss1 *)port;
1098 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1099 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1100 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1101 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1102 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1103 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1104 memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
1105 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1106 //terminal if (e_dialinginfo.id)
1107 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1108 /* handle restricted caller ids */
1109 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1110 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1111 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1112 /* display callerid if desired for extension */
1113 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1114 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1115 /* use cnip, if enabld */
1116 // if (!e_ext.centrex)
1117 // message->param.setup.callerinfo.name[0] = '\0';
1118 /* screen clip if prefix is required */
1119 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
1120 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1121 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1122 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1124 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
1125 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
1126 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
1127 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
1129 /* use internal caller id */
1130 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
1131 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1132 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1133 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1135 message_put(message);
1136 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1140 /* string from parallel call forward (cfp) */
1143 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
1144 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1145 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
1149 vbox_only: /* entry point for answering machine only */
1150 cfu_only: /* entry point for cfu */
1151 cfb_only: /* entry point for cfb */
1152 cfnr_only: /* entry point for cfnr */
1153 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1157 /* only if vbox should be dialed, and terminal is given */
1158 if (!strcmp(p, "vbox") && e_ext.number[0]) {
1159 /* go to the end of p */
1162 /* answering vbox call */
1163 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1165 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1166 FATAL("No memory for VBOX Port instance\n");
1167 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1168 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1171 while(*p!=',' && *p!='\0')
1176 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1177 /* hunt for mISDNport and create Port */
1178 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1180 /* creating EXTERNAL port*/
1181 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1184 port = ss5_hunt_line(mISDNport);
1187 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1189 FATAL("No memory for Port instance\n");
1190 earlyb = mISDNport->earlyb;
1193 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1194 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1199 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1200 goto check_anycall_intern;
1202 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1203 memset(&dialinginfo, 0, sizeof(dialinginfo));
1204 SCPY(dialinginfo.id, cfp);
1205 dialinginfo.itype = INFO_ITYPE_ISDN;
1206 dialinginfo.ntype = e_dialinginfo.ntype;
1207 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1209 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1211 goto check_anycall_intern;
1213 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1214 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1215 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1216 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1217 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1218 /* if clip is hidden */
1219 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
1220 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1221 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1222 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1223 message->param.setup.callerinfo.present = e_ext.callerid_present;
1224 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1226 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1227 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1228 //terminal if (e_dialinginfo.id)
1229 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1230 /* handle restricted caller ids */
1231 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1232 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1233 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1234 /* display callerid if desired for extension */
1235 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1236 message_put(message);
1237 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1241 check_anycall_intern:
1242 /* now we have all ports created */
1244 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1246 if (!ea_endpoint->ep_join_id)
1248 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1249 return; /* must exit here */
1253 /* *********************** external call */
1255 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
1256 /* call to extenal interfaces */
1257 if (e_dialinginfo.keypad[0])
1258 p = e_dialinginfo.keypad;
1260 p = e_dialinginfo.id;
1263 while(*p!=',' && *p!='\0')
1264 SCCAT(number, *p++);
1268 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1269 /* search interface */
1270 interface = hunt_interface(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL);
1272 trace_header("INTERFACE (not found)", DIRECTION_NONE);
1273 add_trace("interface", NULL, "%s", ifname);
1275 goto check_anycall_extern;
1277 /* found interface */
1279 if (interface->gsm_bs) {
1280 SPRINT(portname, "%s-%d-out", interface->name, 0);
1281 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
1285 if (interface->gsm_ms) {
1286 SPRINT(portname, "%s-%d-out", interface->name, 0);
1287 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
1291 if (interface->sip) {
1292 SPRINT(portname, "%s-%d-out", interface->name, 0);
1293 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
1297 /* hunt for mISDNport and create Port */
1298 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1300 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1301 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1303 goto check_anycall_extern;
1305 /* creating EXTERNAL port*/
1306 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1309 port = ss5_hunt_line(mISDNport);
1312 if (mISDNport->ifport->remote) {
1313 admin = admin_first;
1315 if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
1317 admin = admin->next;
1320 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
1321 add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
1325 port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
1327 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1330 FATAL("No memory for Port instance\n");
1331 earlyb = (interface->is_earlyb == IS_YES);
1332 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1333 memset(&dialinginfo, 0, sizeof(dialinginfo));
1334 if (e_dialinginfo.keypad[0])
1335 SCPY(dialinginfo.keypad, number);
1337 SCPY(dialinginfo.id, number);
1338 dialinginfo.itype = INFO_ITYPE_ISDN;
1339 dialinginfo.ntype = e_dialinginfo.ntype;
1340 dialinginfo.sending_complete = e_dialinginfo.sending_complete;
1341 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1343 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1345 goto check_anycall_extern;
1347 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1348 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1349 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1350 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1351 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1352 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1353 memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
1354 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1355 //terminal if (e_dialinginfo.id)
1356 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1357 /* handle restricted caller ids */
1358 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1359 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1360 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1361 /* display callerid if desired for extension */
1362 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1363 message_put(message);
1364 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1368 check_anycall_extern:
1369 /* now we have all ports created */
1371 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1373 if (!ea_endpoint->ep_join_id)
1375 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1376 return; /* must exit here */
1383 int action_timeout(struct lcr_timer *timer, void *instance, int index)
1385 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1387 if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
1390 unsched_timer(&ea->e_redial_timeout);
1391 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
1392 ea->e_multipoint_cause = 0;
1393 ea->e_multipoint_location = 0;
1394 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1395 ea->e_join_pattern = 0;
1396 ea->process_dialing(1);
1397 /* we must exit, because our endpoint might be gone */
1402 int match_timeout(struct lcr_timer *timer, void *instance, int index)
1404 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1406 if (!ea->e_action) {
1407 unsched_timer(&ea->e_redial_timeout);
1408 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
1409 ea->process_dialing(0);
1410 /* we must exit, because our endpoint might be gone */
1416 int redial_timeout(struct lcr_timer *timer, void *instance, int index)
1418 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1420 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
1422 ea->new_state(EPOINT_STATE_OUT_SETUP);
1423 /* call special setup routine */
1429 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
1431 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1433 /* leave power dialing on */
1434 ea->e_powerdial_on = 1;
1435 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
1438 ea->e_ruleset = ruleset_main;
1440 ea->e_rule = ea->e_ruleset->rule_first;
1441 ea->e_action = NULL;
1442 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1443 ea->process_dialing(0);
1448 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
1450 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1451 struct port_list *portlist;
1452 struct lcr_msg *message;
1454 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
1456 /* release all ports */
1457 while((portlist = ea->ea_endpoint->ep_portlist)) {
1458 message = message_create(ea->ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1459 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1460 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1461 message_put(message);
1462 ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1463 ea->ea_endpoint->free_portlist(portlist);
1466 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1467 message->param.audiopath = 0;
1468 message_put(message);
1469 /* indicate no patterns */
1470 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1471 message_put(message);
1472 /* set setup state, since we have no response from the new join */
1473 ea->new_state(EPOINT_STATE_OUT_SETUP);
1478 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
1480 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1482 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea->ea_endpoint->ep_serial, ea->e_ext.cfnr);
1488 int callback_timeout(struct lcr_timer *timer, void *instance, int index)
1490 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1492 if (ea->e_state == EPOINT_STATE_IDLE) {
1493 /* epoint is idle, check callback */
1494 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
1495 ea->new_state(EPOINT_STATE_OUT_SETUP);
1502 int password_timeout(struct lcr_timer *timer, void *instance, int index)
1504 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1506 if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
1507 struct port_list *portlist;
1509 ea->e_ruleset = ruleset_main;
1511 ea->e_rule = ea->e_ruleset->rule_first;
1512 ea->e_action = NULL;
1513 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
1514 ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
1516 ea->e_connectedmode = 0;
1518 ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
1519 portlist = ea->ea_endpoint->ep_portlist;
1521 ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1522 ea->set_tone(portlist, "cause_10");
1529 /* doing a hookflash */
1530 void EndpointAppPBX::hookflash(void)
1535 /* be sure that we are active */
1537 e_tx_state = NOTIFY_STATE_ACTIVE;
1539 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1541 if (ea_endpoint->ep_use > 1) {
1542 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1545 /* dialtone after pressing the hash key */
1546 process_hangup(e_join_cause, e_join_location);
1547 e_multipoint_cause = 0;
1548 e_multipoint_location = 0;
1549 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1551 port->set_echotest(0);
1553 if (ea_endpoint->ep_join_id) {
1554 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1556 e_ruleset = ruleset_main;
1558 e_rule = e_ruleset->rule_first;
1560 new_state(EPOINT_STATE_IN_OVERLAP);
1561 e_connectedmode = 1;
1562 SCPY(e_dialinginfo.id, e_ext.prefix);
1563 e_extdialing = e_dialinginfo.id;
1565 if (e_dialinginfo.id[0]) {
1566 set_tone(ea_endpoint->ep_portlist, "dialing");
1569 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1577 /* messages from port
1579 /* port MESSAGE_SETUP */
1580 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1582 struct lcr_msg *message;
1584 int writeext; /* flags need to write extension after modification */
1587 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1589 portlist->port_type = param->setup.port_type;
1590 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1591 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1592 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1593 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1594 memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
1596 /* convert (inter-)national number type */
1597 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
1598 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1600 // e_dtmf = param->setup.dtmf;
1601 /* screen incoming caller id */
1602 if (e_callerinfo.interface[0]) {
1603 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, e_callerinfo.interface);
1604 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, e_callerinfo.interface);
1607 /* process extension */
1608 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1609 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1610 /* port makes call from extension */
1611 SCPY(e_callerinfo.extension, e_callerinfo.id);
1612 SCPY(e_ext.number, e_callerinfo.extension);
1613 SCPY(e_extension_interface, e_callerinfo.interface);
1615 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1618 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1619 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1621 /* get extension's info about caller */
1622 if (!read_extension(&e_ext, e_ext.number)) {
1623 /* extension doesn't exist */
1624 trace_header("EXTENSION (not created)", DIRECTION_IN);
1625 add_trace("extension", NULL, "%s", e_ext.number);
1627 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1628 new_state(EPOINT_STATE_OUT_DISCONNECT);
1629 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1630 e_ext.number[0] = '\0'; /* no terminal */
1635 /* put prefix (next) in front of e_dialinginfo.id */
1636 if (e_ext.next[0]) {
1637 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1638 SCPY(e_dialinginfo.id, buffer);
1639 e_ext.next[0] = '\0';
1641 } else if (e_ext.prefix[0]) {
1642 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1643 SCPY(e_dialinginfo.id, buffer);
1646 /* screen caller id by extension's config */
1647 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1649 SCPY(e_callerinfo.name, e_ext.name);
1650 /* use caller id (or if exist: id_next_call) for this call */
1651 if (e_ext.id_next_call_present >= 0) {
1652 SCPY(e_callerinfo.id, e_ext.id_next_call);
1653 /* if we restrict the pesentation */
1654 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1655 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1656 else e_callerinfo.present = e_ext.id_next_call_present;
1657 e_callerinfo.ntype = e_ext.id_next_call_type;
1658 e_ext.id_next_call_present = -1;
1661 SCPY(e_callerinfo.id, e_ext.callerid);
1662 /* if we restrict the pesentation */
1663 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1664 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1665 else e_callerinfo.present = e_ext.callerid_present;
1666 e_callerinfo.ntype = e_ext.callerid_type;
1668 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1670 /* extension is written */
1672 write_extension(&e_ext, e_ext.number);
1674 /* set volume of rx and tx */
1675 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1676 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1677 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1678 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1679 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1680 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1681 message_put(message);
1684 /* start recording if enabled */
1685 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1686 /* check if we are a terminal */
1687 if (e_ext.number[0] == '\0')
1688 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1690 port = find_port_id(portlist->port_id);
1692 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1696 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1697 /* no terminal identification */
1698 e_ext.number[0] = '\0';
1699 e_extension_interface[0] = '\0';
1700 memset(&e_ext, 0, sizeof(e_ext));
1701 e_ext.rights = 4; /* right to dial internat */
1705 e_ruleset = ruleset_main;
1707 e_rule = e_ruleset->rule_first;
1709 e_extdialing = e_dialinginfo.id;
1710 new_state(EPOINT_STATE_IN_SETUP);
1711 if (e_dialinginfo.id[0]) {
1712 set_tone(portlist, "dialing");
1714 if (e_ext.number[0])
1715 set_tone(portlist, "dialpbx");
1717 set_tone(portlist, "dialtone");
1720 if (e_state == EPOINT_STATE_IN_SETUP) {
1721 /* request MORE info, if not already at higher state */
1722 new_state(EPOINT_STATE_IN_OVERLAP);
1723 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1724 message_put(message);
1725 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1729 /* port MESSAGE_INFORMATION */
1730 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1732 struct lcr_msg *message;
1734 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1736 /* ignore information message without digit information */
1737 if (!param->information.id[0])
1742 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1744 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1749 /* if vbox_play is done, the information are just used as they come */
1751 if (e_action->index == ACTION_VBOX_PLAY) {
1752 /* concat dialing string */
1753 SCAT(e_dialinginfo.id, param->information.id);
1758 /* keypad when disconnect but in connected mode */
1759 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1760 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1761 /* processing keypad function */
1762 if (param->information.id[0] == '0') {
1768 /* keypad when connected */
1769 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1770 if (e_enablekeypad) {
1771 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1772 memcpy(&message->param, param, sizeof(union parameter));
1773 message_put(message);
1777 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1778 /* processing keypad function */
1779 if (param->information.id[0] == '0') {
1782 if (param->information.id[0])
1783 keypad_function(param->information.id[0]);
1785 if (e_ext.number[0])
1786 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1788 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1793 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1794 if (e_ext.number[0])
1795 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1797 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1801 if (!param->information.id[0])
1803 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1804 set_tone(portlist, "dialing");
1807 if (e_action->index==ACTION_OUTDIAL
1808 || e_action->index==ACTION_EXTERNAL
1809 || e_action->index==ACTION_REMOTE) {
1811 set_tone(portlist, "dialing");
1812 else if (!e_extdialing[0])
1813 set_tone(portlist, "dialing");
1815 /* concat dialing string */
1816 SCAT(e_dialinginfo.id, param->information.id);
1820 /* port MESSAGE_DTMF */
1821 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1824 struct lcr_msg *message;
1828 /* only if dtmf detection is enabled */
1830 trace_header("DTMF (disabled)", DIRECTION_IN);
1834 trace_header("DTMF", DIRECTION_IN);
1835 add_trace("digit", NULL, "%c", param->dtmf);
1839 NOTE: vbox is now handled due to overlap state
1840 /* if vbox_play is done, the dtmf digits are just used as they come */
1842 if (e_action->index == ACTION_VBOX_PLAY) {
1843 /* concat dialing string */
1844 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1845 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1846 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1849 /* continue to process *X# sequences */
1853 /* check for *X# sequence */
1854 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1855 if (e_enablekeypad) {
1856 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1857 memcpy(&message->param, param, sizeof(union parameter));
1858 message_put(message);
1861 if (e_dtmf_time+3 < now) {
1862 /* the last digit was too far in the past to be a sequence */
1863 if (param->dtmf == '*')
1864 /* only start is allowed in the sequence */
1869 /* we have a sequence of digits, see what we got */
1870 if (param->dtmf == '*')
1872 else if (param->dtmf>='0' && param->dtmf<='9') {
1873 /* we need to have a star before we receive the digit of the sequence */
1874 if (e_dtmf_last == '*')
1875 e_dtmf_last = param->dtmf;
1876 } else if (param->dtmf == '#') {
1878 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1879 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1880 if (e_dtmf_last == '0') {
1884 /* processing keypad function */
1886 keypad_function(e_dtmf_last);
1892 /* set last time of dtmf */
1897 /* check for ## hookflash during dialing */
1899 if (e_action->index==ACTION_PASSWORD
1900 || e_action->index==ACTION_PASSWORD_WRITE)
1902 if (param->dtmf=='#') { /* current digit is '#' */
1903 if (e_state==EPOINT_STATE_IN_DISCONNECT
1904 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1918 /* dialing using dtmf digit */
1919 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1920 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1921 set_tone(portlist, "dialing");
1923 /* concat dialing string */
1924 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1925 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1926 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1932 /* port MESSAGE_CRYPT */
1933 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1935 /* send crypt response to cryptman */
1936 if (param->crypt.type == CR_MESSAGE_IND)
1937 cryptman_msg2man(param->crypt.data, param->crypt.len);
1939 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1942 /* port MESSAGE_OVERLAP */
1943 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1945 struct lcr_msg *message;
1947 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1949 /* signal to call tool */
1950 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1952 if (e_dialing_queue[0] && portlist) {
1953 /* send what we have not dialed yet, because we had no setup complete */
1954 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1955 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1956 SCPY(message->param.information.id, e_dialing_queue);
1957 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1958 message_put(message);
1959 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1960 e_dialing_queue[0] = '\0';
1962 /* check if pattern is available */
1963 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1964 /* indicate patterns */
1965 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1966 message_put(message);
1968 /* connect audio, if not already */
1969 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1970 message->param.audiopath = 1;
1971 message_put(message);
1973 /* indicate no patterns */
1974 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1975 message_put(message);
1977 /* disconnect audio, if not already */
1978 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1979 message->param.audiopath = 0;
1980 message_put(message);
1982 new_state(EPOINT_STATE_OUT_OVERLAP);
1983 /* if we are in a join */
1984 if (ea_endpoint->ep_join_id) {
1985 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1986 memcpy(&message->param, param, sizeof(union parameter));
1987 message_put(message);
1991 /* port MESSAGE_PROCEEDING */
1992 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1994 struct lcr_msg *message;
1996 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1998 /* signal to call tool */
1999 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2001 e_state = EPOINT_STATE_OUT_PROCEEDING;
2002 /* check if pattern is availatle */
2003 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
2004 /* indicate patterns */
2005 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2006 message_put(message);
2008 /* connect audio, if not already */
2009 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2010 message->param.audiopath = 1;
2011 message_put(message);
2013 /* indicate no patterns */
2014 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2015 message_put(message);
2017 /* disconnect audio, if not already */
2018 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2019 message->param.audiopath = 0;
2020 message_put(message);
2022 /* if we are in a call */
2023 if (ea_endpoint->ep_join_id) {
2024 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2025 memcpy(&message->param, param, sizeof(union parameter));
2026 message_put(message);
2030 /* port MESSAGE_ALERTING */
2031 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2033 struct lcr_msg *message;
2035 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2037 /* signal to call tool */
2038 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2041 // set_tone(portlist, "hold");
2043 new_state(EPOINT_STATE_OUT_ALERTING);
2044 /* check if pattern is available */
2045 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
2046 /* indicate patterns */
2047 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2048 message_put(message);
2050 /* connect audio, if not already */
2051 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2052 message->param.audiopath = 1;
2053 message_put(message);
2055 /* indicate no patterns */
2056 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2057 message_put(message);
2059 /* disconnect audio, if not already */
2060 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2061 message->param.audiopath = 0;
2062 message_put(message);
2064 /* if we are in a call */
2065 if (ea_endpoint->ep_join_id) {
2066 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2067 memcpy(&message->param, param, sizeof(union parameter));
2068 message_put(message);
2072 /* port MESSAGE_CONNECT */
2073 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2075 struct lcr_msg *message;
2077 unsigned int port_id = portlist->port_id;
2078 struct port_list *tportlist;
2082 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2084 /* signal to call tool */
2085 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
2087 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2088 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2089 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
2090 tportlist = ea_endpoint->ep_portlist;
2091 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2092 tportlist = tportlist->next;
2093 if (tportlist->port_id == port_id)
2094 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2095 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2096 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2097 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2098 message_put(message);
2099 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2100 ea_endpoint->free_portlist(tportlist);
2102 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2107 if (e_callerinfo.interface[0])
2108 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, e_connectinfo.interface);
2110 /* screen connected name */
2112 SCPY(e_connectinfo.name, e_ext.name);
2114 /* add internal id to colp */
2115 SCPY(e_connectinfo.extension, e_ext.number);
2117 /* we store the connected port number */
2118 SCPY(e_extension_interface, e_connectinfo.interface);
2120 /* for internal and am calls, we get the extension's id */
2121 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
2122 SCPY(e_connectinfo.id, e_ext.callerid);
2123 SCPY(e_connectinfo.extension, e_ext.number);
2124 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2125 e_connectinfo.ntype = e_ext.callerid_type;
2126 e_connectinfo.present = e_ext.callerid_present;
2128 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
2129 e_connectinfo.itype = INFO_ITYPE_VBOX;
2130 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2133 new_state(EPOINT_STATE_CONNECT);
2135 /* set volume of rx and tx */
2136 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
2137 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2138 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2139 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2140 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2141 message_put(message);
2144 unsched_timer(&e_cfnr_timeout);
2145 unsched_timer(&e_cfnr_call_timeout);
2146 if (e_ext.number[0])
2147 e_dtmf = 1; /* allow dtmf */
2150 /* other calls with no caller id (or not available for the extension) and force colp */
2151 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
2152 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
2153 if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT) {
2154 /* external extension answered */
2155 port = find_port_id(portlist->port_id);
2157 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2158 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2163 /* send connect to join */
2164 if (ea_endpoint->ep_join_id) {
2165 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2166 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2167 message_put(message);
2169 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2170 message->param.audiopath = 1;
2171 message_put(message);
2172 } else if (!e_adminid) {
2174 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2175 SCPY(e_ext.number, e_cbcaller);
2176 new_state(EPOINT_STATE_IN_OVERLAP);
2177 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2179 /* get extension's info about terminal */
2180 if (!read_extension(&e_ext, e_ext.number)) {
2181 /* extension doesn't exist */
2182 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2183 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2184 new_state(EPOINT_STATE_OUT_DISCONNECT);
2185 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2189 /* put prefix in front of e_cbdialing */
2190 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2191 SCPY(e_dialinginfo.id, buffer);
2192 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2193 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2195 /* use caller id (or if exist: id_next_call) for this call */
2196 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2197 SCPY(e_callerinfo.extension, e_ext.number);
2198 if (e_ext.id_next_call_present >= 0) {
2199 SCPY(e_callerinfo.id, e_ext.id_next_call);
2200 e_callerinfo.present = e_ext.id_next_call_present;
2201 e_callerinfo.ntype = e_ext.id_next_call_type;
2202 e_ext.id_next_call_present = -1;
2203 /* extension is written */
2204 write_extension(&e_ext, e_ext.number);
2206 SCPY(e_callerinfo.id, e_ext.callerid);
2207 e_callerinfo.present = e_ext.callerid_present;
2208 e_callerinfo.ntype = e_ext.callerid_type;
2210 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2212 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2215 /* check if caller id is NOT authenticated */
2216 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2217 /* make call state to enter password */
2218 new_state(EPOINT_STATE_IN_OVERLAP);
2219 e_action = &action_password_write;
2220 unsched_timer(&e_match_timeout);
2221 e_match_to_action = NULL;
2222 e_dialinginfo.id[0] = '\0';
2223 e_extdialing = strchr(e_dialinginfo.id, '\0');
2224 schedule_timer(&e_password_timeout, 20, 0);
2227 /* incoming call (callback) */
2228 e_ruleset = ruleset_main;
2230 e_rule = e_ruleset->rule_first;
2232 e_extdialing = e_dialinginfo.id;
2233 if (e_dialinginfo.id[0]) {
2234 set_tone(portlist, "dialing");
2237 set_tone(portlist, "dialpbx");
2240 } else { /* testcall */
2241 set_tone(portlist, "hold");
2244 /* start recording if enabled, not when answering machine answers */
2245 if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
2246 /* check if we are a terminal */
2247 if (e_ext.number[0] == '\0')
2248 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2250 port = find_port_id(portlist->port_id);
2252 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2257 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2258 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2260 struct lcr_msg *message;
2262 unsigned int port_id = portlist->port_id;
2266 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2268 /* signal to call tool */
2269 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2271 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2272 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2273 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2278 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current multipoint cause %d location %d, received cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2279 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2280 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2282 /* check if we have more than one portlist relation and we just ignore the disconnect */
2283 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2284 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2285 portlist = ea_endpoint->ep_portlist;
2287 if (portlist->port_id == port_id)
2289 portlist = portlist->next;
2292 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2293 if (message_type != MESSAGE_RELEASE) {
2294 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2295 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2296 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2297 message_put(message);
2298 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2300 ea_endpoint->free_portlist(portlist);
2301 return; /* one relation removed */
2303 if (e_state == EPOINT_STATE_CONNECT) {
2304 /* use cause from port after connect */
2305 cause = param->disconnectinfo.cause;
2306 location = param->disconnectinfo.location;
2308 /* use multipoint cause if no connect yet */
2309 if (e_multipoint_cause) {
2310 cause = e_multipoint_cause;
2311 location = e_multipoint_location;
2313 cause = CAUSE_NOUSER;
2314 location = LOCATION_PRIVATE_LOCAL;
2318 unsched_timer(&e_cfnr_timeout);
2319 unsched_timer(&e_cfnr_call_timeout);
2321 /* process hangup */
2322 process_hangup(e_join_cause, e_join_location);
2323 e_multipoint_cause = 0;
2324 e_multipoint_location = 0;
2326 if (message_type == MESSAGE_DISCONNECT) {
2327 /* tone to disconnected end */
2328 SPRINT(buffer, "cause_%02x", cause);
2329 if (ea_endpoint->ep_portlist)
2330 set_tone(ea_endpoint->ep_portlist, buffer);
2332 new_state(EPOINT_STATE_IN_DISCONNECT);
2335 if (ea_endpoint->ep_join_id) {
2336 int haspatterns = 0;
2337 /* check if pattern is available */
2338 if (ea_endpoint->ep_portlist)
2339 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2340 if (joinpbx_countrelations(ea_endpoint->ep_join_id)==2 // we must count relations, in order not to disturb the conference ; NOTE: asterisk always counts two, since it is a point to point call
2341 && message_type != MESSAGE_RELEASE) // if we release, we are done
2344 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2345 /* indicate patterns */
2346 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2347 message_put(message);
2348 /* connect audio, if not already */
2349 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2350 message->param.audiopath = 1;
2351 message_put(message);
2352 /* send disconnect */
2353 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2354 memcpy(&message->param, param, sizeof(union parameter));
2355 message_put(message);
2356 /* disable encryption if disconnected */
2357 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2359 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2362 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2365 if (message_type == MESSAGE_RELEASE)
2366 ea_endpoint->free_portlist(portlist);
2367 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
2368 return; /* must exit here */
2371 /* port MESSAGE_TIMEOUT */
2372 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2376 trace_header("TIMEOUT", DIRECTION_IN);
2377 message_type = MESSAGE_DISCONNECT;
2378 switch (param->state) {
2379 case PORT_STATE_OUT_SETUP:
2380 case PORT_STATE_OUT_OVERLAP:
2381 add_trace("state", NULL, "outgoing setup/dialing");
2383 /* no user responding */
2384 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2385 return; /* must exit here */
2387 case PORT_STATE_IN_SETUP:
2388 case PORT_STATE_IN_OVERLAP:
2389 add_trace("state", NULL, "incoming setup/dialing");
2390 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2391 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2394 case PORT_STATE_OUT_PROCEEDING:
2395 add_trace("state", NULL, "outgoing proceeding");
2397 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2398 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2399 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2400 return; /* must exit here */
2402 case PORT_STATE_IN_PROCEEDING:
2403 add_trace("state", NULL, "incoming proceeding");
2404 param->disconnectinfo.cause = CAUSE_NOUSER;
2405 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2408 case PORT_STATE_OUT_ALERTING:
2409 add_trace("state", NULL, "outgoing alerting");
2411 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2412 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2413 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2414 return; /* must exit here */
2416 case PORT_STATE_CONNECT:
2417 add_trace("state", NULL, "connect");
2419 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2420 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2421 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2422 return; /* must exit here */
2424 case PORT_STATE_IN_ALERTING:
2425 add_trace("state", NULL, "incoming alerting");
2426 param->disconnectinfo.cause = CAUSE_NOANSWER;
2427 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2430 case PORT_STATE_IN_DISCONNECT:
2431 case PORT_STATE_OUT_DISCONNECT:
2432 add_trace("state", NULL, "disconnect");
2434 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2435 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2436 return; /* must exit here */
2439 param->disconnectinfo.cause = 31; /* normal unspecified */
2440 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2443 /* release call, disconnect isdn */
2445 new_state(EPOINT_STATE_OUT_DISCONNECT);
2446 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2447 SCPY(e_tone, cause);
2449 set_tone(portlist, cause);
2450 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2451 portlist = portlist->next;
2453 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2456 /* port MESSAGE_NOTIFY */
2457 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2459 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2461 struct lcr_msg *message;
2462 const char *logtext = "";
2465 /* signal to call tool */
2466 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype, options.national, options.international), 0, 0, param->notifyinfo.notify);
2467 if (param->notifyinfo.notify) {
2468 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2471 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2472 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2473 case INFO_NOTIFY_REMOTE_HOLD:
2474 case INFO_NOTIFY_USER_SUSPENDED:
2475 /* tell call about it */
2476 if (ea_endpoint->ep_join_id) {
2477 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2478 message->param.audiopath = 0;
2479 message_put(message);
2483 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2484 case INFO_NOTIFY_USER_RESUMED:
2485 /* set volume of rx and tx */
2486 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2487 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2489 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2490 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2491 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2492 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2493 message_put(message);
2495 /* set current tone */
2497 set_tone(portlist, e_tone);
2498 /* tell call about it */
2499 if (ea_endpoint->ep_join_id) {
2500 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2501 message->param.audiopath = 1;
2502 message_put(message);
2507 /* get name of notify */
2508 switch(param->notifyinfo.notify) {
2513 logtext = "USER_SUSPENDED";
2516 logtext = "BEARER_SERVICE_CHANGED";
2519 logtext = "USER_RESUMED";
2522 logtext = "CONFERENCE_ESTABLISHED";
2525 logtext = "CONFERENCE_DISCONNECTED";
2528 logtext = "OTHER_PARTY_ADDED";
2531 logtext = "ISOLATED";
2534 logtext = "REATTACHED";
2537 logtext = "OTHER_PARTY_ISOLATED";
2540 logtext = "OTHER_PARTY_REATTACHED";
2543 logtext = "OTHER_PARTY_SPLIT";
2546 logtext = "OTHER_PARTY_DISCONNECTED";
2549 logtext = "CONFERENCE_FLOATING";
2552 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2555 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2558 logtext = "CALL_IS_A_WAITING_CALL";
2561 logtext = "DIVERSION_ACTIVATED";
2564 logtext = "RESERVED_CT_1";
2567 logtext = "RESERVED_CT_2";
2570 logtext = "REVERSE_CHARGING";
2573 logtext = "REMOTE_HOLD";
2576 logtext = "REMOTE_RETRIEVAL";
2579 logtext = "CALL_IS_DIVERTING";
2582 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2587 /* notify call if available */
2588 if (ea_endpoint->ep_join_id) {
2589 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2590 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2591 message_put(message);
2596 /* port MESSAGE_PROGRESS */
2597 void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
2599 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2601 struct lcr_msg *message;
2603 /* signal to call tool */
2604 admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
2606 /* send progress to call if available */
2607 if (ea_endpoint->ep_join_id) {
2608 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
2609 memcpy(&message->param.progressinfo, ¶m->progressinfo, sizeof(struct progress_info));
2610 message_put(message);
2615 /* port MESSAGE_FACILITY */
2616 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2618 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2620 struct lcr_msg *message;
2622 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2623 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2624 message_put(message);
2627 /* port MESSAGE_SUSPEND */
2628 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2629 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2631 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2633 /* epoint is now parked */
2634 ea_endpoint->ep_park = 1;
2635 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2636 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2638 /* remove port relation */
2639 ea_endpoint->free_portlist(portlist);
2642 /* port MESSAGE_RESUME */
2643 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2644 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2646 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2648 /* epoint is now resumed */
2649 ea_endpoint->ep_park = 0;
2653 /* port MESSAGE_ENABLEKEYPAD */
2654 void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
2656 struct lcr_msg *message;
2658 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2660 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
2661 memcpy(&message->param, param, sizeof(union parameter));
2662 message_put(message);
2666 /* port sends message to the endpoint
2668 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2670 struct port_list *portlist;
2672 portlist = ea_endpoint->ep_portlist;
2674 if (port_id == portlist->port_id)
2676 portlist = portlist->next;
2679 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) warning: port is not related to this endpoint. This may happen, if port has been released after the message was created.\n", ea_endpoint->ep_serial);
2683 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2684 switch(message_type) {
2685 case MESSAGE_TONE_EOF: /* tone is end of file */
2686 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2688 if (e_action->index == ACTION_VBOX_PLAY) {
2691 if (e_action->index == ACTION_EFI) {
2697 case MESSAGE_TONE_COUNTER: /* counter info received */
2698 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received counter information: %d / %d seconds after start of tone.\n", ea_endpoint->ep_serial, param->counter.current, param->counter.max);
2700 if (e_action->index == ACTION_VBOX_PLAY) {
2701 e_vbox_counter = param->counter.current;
2702 if (param->counter.max >= 0)
2703 e_vbox_counter_max = param->counter.max;
2707 /* PORT sends SETUP message */
2709 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
2710 if (e_state!=EPOINT_STATE_IDLE) {
2711 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2714 port_setup(portlist, message_type, param);
2717 /* PORT sends INFORMATION message */
2718 case MESSAGE_INFORMATION: /* additional digits received */
2719 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.id, e_ext.number, e_callerinfo.id);
2720 port_information(portlist, message_type, param);
2723 /* PORT sends FACILITY message */
2724 case MESSAGE_FACILITY:
2725 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2726 port_facility(portlist, message_type, param);
2729 /* PORT sends DTMF message */
2730 case MESSAGE_DTMF: /* dtmf digits received */
2731 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
2732 port_dtmf(portlist, message_type, param);
2735 /* PORT sends CRYPT message */
2736 case MESSAGE_CRYPT: /* crypt response received */
2737 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2738 port_crypt(portlist, message_type, param);
2741 /* PORT sends MORE message */
2742 case MESSAGE_OVERLAP:
2743 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2744 if (e_state != EPOINT_STATE_OUT_SETUP) {
2745 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2748 port_overlap(portlist, message_type, param);
2751 /* PORT sends PROCEEDING message */
2752 case MESSAGE_PROCEEDING: /* port is proceeding */
2753 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2754 if (e_state!=EPOINT_STATE_OUT_SETUP
2755 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2756 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2759 port_proceeding(portlist, message_type, param);
2762 /* PORT sends ALERTING message */
2763 case MESSAGE_ALERTING:
2764 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2765 if (e_state!=EPOINT_STATE_OUT_SETUP
2766 && e_state!=EPOINT_STATE_OUT_OVERLAP
2767 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2768 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2771 port_alerting(portlist, message_type, param);
2774 /* PORT sends CONNECT message */
2775 case MESSAGE_CONNECT:
2776 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call connected to %s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_connectinfo.id, e_ext.number, e_callerinfo.id);
2777 if (e_state!=EPOINT_STATE_OUT_SETUP
2778 && e_state!=EPOINT_STATE_OUT_OVERLAP
2779 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2780 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2784 port_connect(portlist, message_type, param);
2787 /* PORT sends DISCONNECT message */
2788 case MESSAGE_DISCONNECT: /* port is disconnected */
2789 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call disconnect with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2790 port_disconnect_release(portlist, message_type, param);
2793 /* PORT sends a RELEASE message */
2794 case MESSAGE_RELEASE: /* port releases */
2795 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) release with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2796 /* portlist is release at port_disconnect_release, thanx Paul */
2797 port_disconnect_release(portlist, message_type, param);
2800 /* PORT sends a TIMEOUT message */
2801 case MESSAGE_TIMEOUT:
2802 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received timeout (state=%d).\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->state);
2803 port_timeout(portlist, message_type, param);
2804 break; /* release */
2806 /* PORT sends a NOTIFY message */
2807 case MESSAGE_NOTIFY:
2808 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2809 port_notify(portlist, message_type, param);
2812 /* PORT sends a PROGRESS message */
2813 case MESSAGE_PROGRESS:
2814 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received progress.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2815 port_progress(portlist, message_type, param);
2818 /* PORT sends a SUSPEND message */
2819 case MESSAGE_SUSPEND:
2820 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2821 port_suspend(portlist, message_type, param);
2822 break; /* suspend */
2824 /* PORT sends a RESUME message */
2825 case MESSAGE_RESUME:
2826 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received resume.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2827 port_resume(portlist, message_type, param);
2831 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2832 /* port assigns bchannel */
2833 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2834 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel message %d from port.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
2835 /* only one port is expected to be connected to bchannel */
2836 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2837 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2841 /* PORT requests DTMF */
2842 case MESSAGE_ENABLEKEYPAD:
2843 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') requests DTMF/KEYPAD.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2844 port_enablekeypad(portlist, message_type, param);
2849 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message_type);
2852 /* Note: this endpoint may be destroyed, so we MUST return */
2856 /* messages from join
2858 /* join MESSAGE_CRYPT */
2859 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2861 switch(param->crypt.type) {
2862 /* message from remote port to "crypt manager" */
2863 case CU_ACTK_REQ: /* activate key-exchange */
2864 case CU_ACTS_REQ: /* activate shared key */
2865 case CU_DACT_REQ: /* deactivate */
2866 case CU_INFO_REQ: /* request last info message */
2867 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2870 /* message from "crypt manager" to user */
2871 case CU_ACTK_CONF: /* key-echange done */
2872 case CU_ACTS_CONF: /* shared key done */
2873 case CU_DACT_CONF: /* deactivated */
2874 case CU_DACT_IND: /* deactivated */
2875 case CU_ERROR_IND: /* receive error message */
2876 case CU_INFO_IND: /* receive info message */
2877 case CU_INFO_CONF: /* receive info message */
2878 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2882 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
2886 /* join MESSAGE_INFORMATION */
2887 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2889 struct lcr_msg *message;
2894 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2895 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2896 message_put(message);
2897 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2898 portlist = portlist->next;
2902 /* join MESSAGE_FACILITY */
2903 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2905 struct lcr_msg *message;
2907 if (!e_ext.facility && e_ext.number[0]) {
2912 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2913 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2914 message_put(message);
2915 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2916 portlist = portlist->next;
2920 /* join MESSAGE_MORE */
2921 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2923 struct lcr_msg *message;
2925 new_state(EPOINT_STATE_IN_OVERLAP);
2928 if (e_join_pattern && e_ext.own_setup) {
2929 /* disconnect audio */
2930 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2931 message->param.audiopath = 0;
2932 message_put(message);
2934 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2935 if (e_dialinginfo.id[0])
2936 set_tone(portlist, "dialing");
2938 set_tone(portlist, "dialtone");
2941 if (e_dialinginfo.id[0]) {
2942 set_tone(portlist, "dialing");
2944 if (e_ext.number[0])
2945 set_tone(portlist, "dialpbx");
2947 set_tone(portlist, "dialtone");
2951 /* join MESSAGE_PROCEEDING */
2952 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2954 struct lcr_msg *message;
2956 new_state(EPOINT_STATE_IN_PROCEEDING);
2958 /* own proceeding tone */
2959 if (e_join_pattern) {
2960 /* connect / disconnect audio */
2961 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2962 if (e_ext.own_proceeding)
2963 message->param.audiopath = 0;
2965 message->param.audiopath = 1;
2966 message_put(message);
2968 // UCPY(e_join_tone, "proceeding");
2970 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2971 message_put(message);
2972 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2974 set_tone(portlist, "proceeding");
2977 /* join MESSAGE_ALERTING */
2978 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2980 struct lcr_msg *message;
2982 new_state(EPOINT_STATE_IN_ALERTING);
2984 /* own alerting tone */
2985 if (e_join_pattern) {
2986 /* connect / disconnect audio */
2987 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2988 if (e_ext.own_alerting)
2989 message->param.audiopath = 0;
2991 message->param.audiopath = 1;
2992 message_put(message);
2995 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2996 message_put(message);
2997 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2999 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
3000 set_tone(portlist, "ringing");
3003 if (e_ext.number[0])
3004 set_tone(portlist, "ringpbx");
3006 set_tone(portlist, "ringing");
3008 if (e_ext.number[0])
3009 e_dtmf = 1; /* allow dtmf */
3012 /* join MESSAGE_CONNECT */
3013 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3015 struct lcr_msg *message;
3018 new_state(EPOINT_STATE_CONNECT);
3019 // UCPY(e_join_tone, "");
3021 if (e_ext.number[0])
3022 e_dtmf = 1; /* allow dtmf */
3025 unsched_timer(&e_powerdial_timeout);
3026 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3028 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3029 memcpy(&message->param, param, sizeof(union parameter));
3031 /* screen clip if prefix is required */
3032 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
3033 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3034 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
3035 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3038 /* use internal caller id */
3039 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
3040 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3041 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3044 /* handle restricted caller ids */
3045 apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3046 /* display callerid if desired for extension */
3047 SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
3049 /* use conp, if enabld */
3050 // if (!e_ext.centrex)
3051 // message->param.connectinfo.name[0] = '\0';
3054 message_put(message);
3055 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3057 set_tone(portlist, NULL);
3059 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3060 message->param.audiopath = 1;