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));
77 e_ruleset = ruleset_main;
79 e_rule = e_ruleset->rule_first;
82 e_match_to_action = NULL;
84 e_extdialing = e_dialinginfo.id;
88 // e_join_tone[0] = e_hold_tone[0] = '\0';
89 e_join_pattern /*= e_hold_pattern*/ = 0;
91 e_adminid = 0; // will be set, if call was initiated via admin socket
94 e_cbdialing[0] = '\0';
97 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
103 e_multipoint_cause = 0;
104 e_multipoint_location = 0;
105 e_dialing_queue[0] = '\0';
107 e_crypt_state = CM_ST_NULL;
108 e_crypt_keyengine_busy = 0;
109 e_crypt_info[0] = '\0';
112 e_tx_state = NOTIFY_STATE_ACTIVE;
113 e_rx_state = NOTIFY_STATE_ACTIVE;
114 e_join_cause = e_join_location = 0;
115 /*********************************
116 *********************************
117 ********* ATTENTION *************
118 *********************************
119 *********************************/
120 /* if you add new values, that must be initialized, also check if they must
121 * be initialized when doing callback
127 * EpointAppPBX destructor
129 EndpointAppPBX::~EndpointAppPBX(void)
131 class EndpointAppPBX *temp, **tempp;
133 del_timer(&e_crypt_handler);
134 del_timer(&e_vbox_refresh);
135 del_timer(&e_action_timeout);
136 del_timer(&e_match_timeout);
137 del_timer(&e_redial_timeout);
138 del_timer(&e_powerdial_timeout);
139 del_timer(&e_cfnr_timeout);
140 del_timer(&e_cfnr_call_timeout);
141 del_timer(&e_callback_timeout);
142 del_timer(&e_password_timeout);
146 tempp = &apppbx_first;
155 FATAL("Endpoint not in endpoint's list.\n");
162 * trace header for application
164 void EndpointAppPBX::trace_header(const char *name, int direction)
168 char msgtext[sizeof(_trace.name)];
172 /* init trace with given values */
175 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
179 ea_endpoint->ep_serial,
186 /* set new endpoint state
188 void EndpointAppPBX::new_state(int state)
191 if (e_state != state) {
192 trace_header("NEW STATE", DIRECTION_NONE);
193 add_trace("state", "old", "%s", state_name[e_state]);
194 add_trace("state", "new", "%s", state_name[state]);
202 /* release join and port (as specified)
204 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force)
206 struct port_list *portlist;
207 struct lcr_msg *message;
210 /* message to test call */
211 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
213 /* if a release is pending */
214 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
215 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
216 if (ea_endpoint->ep_join_id) {
217 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
218 message->param.disconnectinfo.cause = joincause;
219 message->param.disconnectinfo.location = joinlocation;
220 message_put(message);
221 ea_endpoint->ep_join_id = 0;
225 if (release != RELEASE_PORT_JOINONLY) {
227 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
232 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
233 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
234 while((portlist = ea_endpoint->ep_portlist)) {
235 if (portlist->port_id) {
236 SPRINT(cause, "cause_%02x", portcause);
237 set_tone(portlist, cause);
238 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
239 message->param.disconnectinfo.cause = portcause;
240 message->param.disconnectinfo.location = portlocation;
241 message->param.disconnectinfo.force = force; // set, if port should release imediately
242 message_put(message);
243 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
245 ea_endpoint->free_portlist(portlist);
248 /* if callback is enabled, call back with the given caller id */
249 if (e_callback_timeout.active) {
250 /* reset some stuff */
251 new_state(EPOINT_STATE_IDLE);
252 memset(&e_connectinfo, 0, sizeof(struct connect_info));
253 memset(&e_redirinfo, 0, sizeof(struct redir_info));
254 e_start = e_stop = 0;
255 e_ruleset = ruleset_main;
257 e_rule = e_ruleset->rule_first;
259 unsched_timer(&e_action_timeout);
260 unsched_timer(&e_match_timeout);
261 unsched_timer(&e_cfnr_timeout);
262 unsched_timer(&e_cfnr_call_timeout);
263 e_match_to_action = NULL;
265 e_extdialing = e_dialinginfo.id;
271 e_multipoint_cause = 0;
272 e_multipoint_location = 0;
273 e_dialing_queue[0] = '\0';
275 e_crypt_state = CM_ST_NULL;
276 e_crypt_keyengine_busy = 0;
277 e_crypt_info[0] = '\0';
281 e_tx_state = NOTIFY_STATE_ACTIVE;
282 e_rx_state = NOTIFY_STATE_ACTIVE;
283 e_join_cause = e_join_location = 0;
285 /* the caller info of the callback user */
286 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
287 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
288 /* create dialing by callerinfo */
289 if (e_ext.number[0] && e_extension_interface[0]) {
290 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
291 /* create callback to the current terminal */
292 SCPY(e_dialinginfo.id, e_ext.number);
293 SCPY(e_dialinginfo.interfaces, e_extension_interface);
294 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
295 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
298 SCPY(e_dialinginfo.id, e_cbto);
300 /* numberrize caller id and use it to dial to the callback */
301 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
303 e_dialinginfo.itype = INFO_ITYPE_ISDN;
304 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
305 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
310 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
311 if (--ea_endpoint->ep_use <= 0) /* when e_lock is 0, the endpoint will be deleted */
312 trigger_work(&ea_endpoint->ep_delete);
318 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
319 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
321 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");
323 /* caller id is not restricted, so we do nothing */
324 if (*present != INFO_PRESENT_RESTRICTED)
327 /* only extensions are restricted */
331 /* if we enabled anonymouse ignore */
332 if (ext->anon_ignore)
335 /* else we remove the caller id */
339 *ntype = INFO_NTYPE_UNKNOWN;
341 // *screen = INFO_SCREEN_USER;
342 // maybe we should not make voip address anonymous
345 // maybe it's no fraud to present extension id
347 // extension[0] = '\0';
352 /* used display message to display callerid as available */
353 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
355 static char display[81];
358 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
360 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");
369 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
371 /* internal extension's caller id */
372 if (extension[0] && e_ext.display_int) {
374 SCAT(display, extension);
377 if (itype == INFO_ITYPE_VBOX)
378 SCAT(display, "(vbox)");
380 SCAT(display, "(int)");
383 /* external caller id */
384 if (!extension[0] && e_ext.display_ext) {
387 if (present == INFO_PRESENT_RESTRICTED)
388 SCAT(display, "anonymous");
390 SCAT(display, "unknown");
397 /* display if callerid is anonymouse but available due anon-ignore */
398 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
400 SCAT(display, "unknown");
403 SCAT(display, " anon");
406 /* display if callerid is anonymouse but available due anon-ignore */
407 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
410 if (present == INFO_PRESENT_RESTRICTED)
411 SCAT(display, "anonymous");
413 SCAT(display, "unknown");
418 SCAT(display, " fake");
422 if (name[0] && e_ext.display_name) {
423 if (!display[0] && cid[0])
434 * uses the current state to notify activity
436 void EndpointAppPBX::notify_active(void)
438 struct port_list *portlist = ea_endpoint->ep_portlist;
439 struct lcr_msg *message;
443 case NOTIFY_STATE_ACTIVE:
444 /* we are already active, so we don't do anything */
447 case NOTIFY_STATE_SUSPEND:
448 notify = INFO_NOTIFY_USER_RESUMED;
450 set_tone(portlist, NULL);
451 portlist = portlist->next;
453 portlist = ea_endpoint->ep_portlist;
456 case NOTIFY_STATE_HOLD:
457 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
459 set_tone(portlist, NULL);
460 portlist = portlist->next;
462 portlist = ea_endpoint->ep_portlist;
465 case NOTIFY_STATE_CONFERENCE:
466 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
468 set_tone(portlist, NULL);
469 portlist = portlist->next;
471 portlist = ea_endpoint->ep_portlist;
475 PERROR("unknown e_tx_state = %d\n", e_tx_state);
480 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
481 message->param.notifyinfo.notify = notify;
482 message_put(message);
483 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
484 portlist = portlist->next;
490 * keypad functions during call. one example to use this is to put a call on hold or start a conference
492 void EndpointAppPBX::keypad_function(char digit)
495 /* we must be in a call, in order to send messages to the call */
496 if (e_ext.number[0] == '\0') {
497 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
502 /* join conference */
504 if (ea_endpoint->ep_join_id == 0) {
505 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
518 /* crypt key-exchange */
520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
526 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
531 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
536 /* set tone pattern for port */
537 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
539 struct lcr_msg *message;
544 /* store for suspended processes */
548 if (e_join_pattern /* pattern are provided */
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
550 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
551 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
552 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
553 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
554 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
555 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
556 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
557 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
558 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
559 && tone[0] && !!strncmp(tone,"crypt_*",6)) {
560 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
565 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
566 SCPY(message->param.tone.dir, e_ext.tones_dir);
567 SCPY(message->param.tone.name, tone);
568 message_put(message);
569 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
571 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
578 * hunts an mISDNport that is available for an outgoing call
579 * if no ifname was given, any interface that is not an extension
582 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
584 struct interface *interface;
585 struct interface_port *ifport, *ifport_start;
586 struct select_channel *selchannel;
587 struct mISDNport *mISDNport;
589 int there_is_an_external = 0;
591 interface = interface_first;
593 /* first find the given interface or, if not given, one with no extension */
596 if (!there_is_an_external && !(ifname && ifname[0])) {
597 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
598 add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
604 /* check for given interface */
605 if (ifname && ifname[0]) {
606 if (!strcasecmp(interface->name, ifname)) {
607 /* found explicit interface */
608 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
609 add_trace("interface", NULL, "%s", ifname);
615 if (interface->external) {
616 there_is_an_external = 1;
617 /* found non extension */
618 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
619 add_trace("interface", NULL, "%s", interface->name);
625 interface = interface->next;
629 /* see if interface has ports */
630 if (!interface->ifport) {
632 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
633 add_trace("interface", NULL, "%s", interface->name);
635 interface = interface->next;
639 /* select port by algorithm */
640 ifport_start = interface->ifport;
642 if (interface->hunt == HUNT_ROUNDROBIN) {
643 while(ifport_start->next && index<interface->hunt_next) {
644 ifport_start = ifport_start->next;
647 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
648 add_trace("port", NULL, "%d", ifport_start->portnum);
649 add_trace("position", NULL, "%d", index);
654 ifport = ifport_start;
657 /* see if port is available */
658 if (!ifport->mISDNport) {
659 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
660 add_trace("port", NULL, "%d", ifport->portnum);
661 add_trace("position", NULL, "%d", index);
665 mISDNport = ifport->mISDNport;
667 /* see if port is administratively blocked */
669 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
670 add_trace("port", NULL, "%d", ifport->portnum);
671 add_trace("position", NULL, "%d", index);
676 /* see if link is up on PTP*/
677 if (mISDNport->l2hold && mISDNport->l2link<1) {
678 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
679 add_trace("port", NULL, "%d", ifport->portnum);
680 add_trace("position", NULL, "%d", index);
685 /* check for channel form selection list */
688 if (mISDNport->ss5) {
690 port = ss5_hunt_line(mISDNport);
692 *channel = port->p_m_b_channel;
693 trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
694 add_trace("port", NULL, "%d", ifport->portnum);
695 add_trace("position", NULL, "%d", index);
696 add_trace("channel", NULL, "%d", *channel);
702 selchannel = ifport->out_channel;
704 switch(selchannel->channel) {
705 case CHANNEL_FREE: /* free channel */
706 if (mISDNport->b_reserved >= mISDNport->b_num)
707 break; /* all channel in use or reserverd */
710 while(i < mISDNport->b_num) {
711 if (mISDNport->b_port[i] == NULL) {
712 *channel = i+1+(i>=15);
713 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
714 add_trace("port", NULL, "%d", ifport->portnum);
715 add_trace("position", NULL, "%d", index);
716 add_trace("channel", NULL, "%d", *channel);
724 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
725 add_trace("port", NULL, "%d", ifport->portnum);
726 add_trace("position", NULL, "%d", index);
730 case CHANNEL_ANY: /* don't ask for channel */
731 if (mISDNport->b_reserved >= mISDNport->b_num) {
732 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
733 add_trace("port", NULL, "%d", ifport->portnum);
734 add_trace("position", NULL, "%d", index);
735 add_trace("total", NULL, "%d", mISDNport->b_num);
736 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
738 break; /* all channel in use or reserverd */
740 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
741 add_trace("port", NULL, "%d", ifport->portnum);
742 add_trace("position", NULL, "%d", index);
744 *channel = CHANNEL_ANY;
747 case CHANNEL_NO: /* call waiting */
748 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
749 add_trace("port", NULL, "%d", ifport->portnum);
750 add_trace("position", NULL, "%d", index);
752 *channel = CHANNEL_NO;
756 if (selchannel->channel<1 || selchannel->channel==16) {
757 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
758 add_trace("port", NULL, "%d", ifport->portnum);
759 add_trace("position", NULL, "%d", index);
760 add_trace("channel", NULL, "%d", selchannel->channel);
762 break; /* invalid channels */
764 i = selchannel->channel-1-(selchannel->channel>=17);
765 if (i >= mISDNport->b_num) {
766 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
767 add_trace("port", NULL, "%d", ifport->portnum);
768 add_trace("position", NULL, "%d", index);
769 add_trace("channel", NULL, "%d", selchannel->channel);
770 add_trace("channels", NULL, "%d", mISDNport->b_num);
772 break; /* channel not in port */
774 if (mISDNport->b_port[i] == NULL) {
775 *channel = selchannel->channel;
776 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
777 add_trace("port", NULL, "%d", ifport->portnum);
778 add_trace("position", NULL, "%d", index);
779 add_trace("channel", NULL, "%d", *channel);
786 break; /* found channel */
787 selchannel = selchannel->next;
791 /* if channel was found, return mISDNport and channel */
793 /* setting next port to start next time */
794 if (interface->hunt == HUNT_ROUNDROBIN) {
798 interface->hunt_next = index;
804 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
805 add_trace("port", NULL, "%d", ifport->portnum);
806 add_trace("position", NULL, "%d", index);
810 /* go next port, until all ports are checked */
812 ifport = ifport->next;
815 ifport = interface->ifport;
817 if (ifport != ifport_start)
821 interface = interface->next;
825 return(NULL); /* no port found */
828 /* outgoing setup to port(s)
829 * ports will be created and a setup is sent if everything is ok. otherwhise
830 * the endpoint is destroyed.
832 void EndpointAppPBX::out_setup(int cfnr)
834 struct dialing_info dialinginfo;
836 struct port_list *portlist;
837 struct lcr_msg *message;
839 int cause = CAUSE_RESSOURCEUNAVAIL;
842 struct mISDNport *mISDNport;
845 class EndpointAppPBX *atemp;
846 // char allowed_ports[256];
848 char ifname[sizeof(e_ext.interfaces)],
850 struct port_settings port_settings;
853 int mode = B_MODE_TRANSPARENT;
855 /* set bchannel mode */
856 mode = e_capainfo.source_mode;
858 /* create settings for creating port */
859 memset(&port_settings, 0, sizeof(port_settings));
861 SCPY(port_settings.tones_dir, e_ext.tones_dir);
863 SCPY(port_settings.tones_dir, options.tones_dir);
864 port_settings.no_seconds = e_ext.no_seconds;
866 /* 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 */
868 /* check what dialinginfo.itype we got */
869 switch(e_dialinginfo.itype) {
870 /* *********************** call to extension or vbox */
871 case INFO_ITYPE_ISDN_EXTENSION:
872 /* check if we deny incoming calls when we use an extension */
873 if (e_ext.noknocking) {
874 atemp = apppbx_first;
877 if (!strcmp(atemp->e_ext.number, e_ext.number))
882 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
883 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
884 return; /* must exit here */
887 /* FALL THROUGH !!!! */
888 case INFO_ITYPE_VBOX:
889 /* get dialed extension's info */
890 // SCPY(exten, e_dialinginfo.id);
891 // if (strchr(exten, ','))
892 // *strchr(exten, ',') = '\0';
893 // if (!read_extension(&e_ext, exten))
894 if (!read_extension(&e_ext, e_dialinginfo.id)) {
895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
896 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
897 return; /* must exit here */
899 e_dialinginfo.sending_complete = 1;
901 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
902 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
907 /* string from unconditional call forward (cfu) */
910 /* present to forwarded party */
911 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
912 e_callerinfo.present = INFO_PRESENT_ALLOWED;
914 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
918 /* string from busy call forward (cfb) */
921 class EndpointAppPBX *checkapp = apppbx_first;
923 if (checkapp != this) { /* any other endpoint except our own */
924 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
925 /* present to forwarded party */
926 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
927 e_callerinfo.present = INFO_PRESENT_ALLOWED;
929 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
933 checkapp = checkapp->next;
937 /* string from no-response call forward (cfnr) */
940 /* when cfnr is done, out_setup() will setup the call */
942 /* present to forwarded party */
943 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
944 e_callerinfo.present = INFO_PRESENT_ALLOWED;
948 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
949 schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
950 schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* call one second after release */
951 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);
955 /* call to all internal interfaces */
956 p = e_ext.interfaces;
957 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
960 while(*p!=',' && *p!='\0')
965 /* found interface */
966 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
967 /* hunt for mISDNport and create Port */
968 mISDNport = hunt_port(ifname, &channel);
970 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
971 add_trace("interface", NULL, "%s", ifname);
975 /* creating INTERNAL port */
976 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
979 port = ss5_hunt_line(mISDNport);
983 if (mISDNport->gsm_bs)
984 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
988 if (mISDNport->gsm_ms)
989 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
992 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);
994 FATAL("Failed to create Port instance\n");
995 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
996 memset(&dialinginfo, 0, sizeof(dialinginfo));
997 SCPY(dialinginfo.id, e_dialinginfo.id);
998 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
999 dialinginfo.ntype = e_dialinginfo.ntype;
1000 /* create port_list relation */
1001 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1003 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1005 goto check_anycall_intern;
1007 /* directory.list */
1008 if (e_callerinfo.id[0] && e_ext.display_name) {
1009 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1011 SCPY(e_callerinfo.name, dirname);
1013 // dss1 = (class Pdss1 *)port;
1015 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1016 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1017 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1018 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1019 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1020 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1021 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1022 //terminal if (e_dialinginfo.id)
1023 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1024 /* handle restricted caller ids */
1025 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);
1026 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);
1027 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);
1028 /* display callerid if desired for extension */
1029 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));
1030 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1031 /* use cnip, if enabld */
1032 // if (!e_ext.centrex)
1033 // message->param.setup.callerinfo.name[0] = '\0';
1034 /* screen clip if prefix is required */
1035 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
1036 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1037 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1038 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1040 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
1041 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
1042 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
1043 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
1045 /* use internal caller id */
1046 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
1047 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1048 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1049 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1051 message_put(message);
1052 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1056 /* string from parallel call forward (cfp) */
1059 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
1060 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1061 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
1065 vbox_only: /* entry point for answering machine only */
1066 cfu_only: /* entry point for cfu */
1067 cfb_only: /* entry point for cfb */
1068 cfnr_only: /* entry point for cfnr */
1069 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1073 /* only if vbox should be dialed, and terminal is given */
1074 if (!strcmp(p, "vbox") && e_ext.number[0]) {
1075 /* go to the end of p */
1078 /* answering vbox call */
1079 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1081 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1082 FATAL("No memory for VBOX Port instance\n");
1083 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1084 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1087 while(*p!=',' && *p!='\0')
1092 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1093 /* hunt for mISDNport and create Port */
1094 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1096 /* creating EXTERNAL port*/
1097 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1100 port = ss5_hunt_line(mISDNport);
1103 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);
1105 FATAL("No memory for Port instance\n");
1106 earlyb = mISDNport->earlyb;
1109 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1110 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1115 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1116 goto check_anycall_intern;
1118 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1119 memset(&dialinginfo, 0, sizeof(dialinginfo));
1120 SCPY(dialinginfo.id, cfp);
1121 dialinginfo.itype = INFO_ITYPE_ISDN;
1122 dialinginfo.ntype = e_dialinginfo.ntype;
1123 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1125 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1127 goto check_anycall_intern;
1129 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1130 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1131 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1132 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1133 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1134 /* if clip is hidden */
1135 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
1136 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1137 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1138 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1139 message->param.setup.callerinfo.present = e_ext.callerid_present;
1140 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1142 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1143 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1144 //terminal if (e_dialinginfo.id)
1145 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1146 /* handle restricted caller ids */
1147 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);
1148 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);
1149 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);
1150 /* display callerid if desired for extension */
1151 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));
1152 message_put(message);
1153 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1157 check_anycall_intern:
1158 /* now we have all ports created */
1160 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1162 if (!ea_endpoint->ep_join_id)
1164 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1165 return; /* must exit here */
1169 /* *********************** external call */
1171 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
1172 /* call to extenal interfaces */
1173 if (e_dialinginfo.keypad[0])
1174 p = e_dialinginfo.keypad;
1176 p = e_dialinginfo.id;
1179 while(*p!=',' && *p!='\0')
1180 SCCAT(number, *p++);
1184 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");
1185 /* hunt for mISDNport and create Port */
1186 /* hunt for mISDNport and create Port */
1187 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1189 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1190 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1192 goto check_anycall_extern;
1194 /* creating EXTERNAL port*/
1195 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1198 port = ss5_hunt_line(mISDNport);
1202 if (mISDNport->gsm_bs)
1203 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1207 if (mISDNport->gsm_ms)
1208 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1211 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);
1213 FATAL("No memory for Port instance\n");
1214 earlyb = mISDNport->earlyb;
1215 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1216 memset(&dialinginfo, 0, sizeof(dialinginfo));
1217 if (e_dialinginfo.keypad[0])
1218 SCPY(dialinginfo.keypad, number);
1220 SCPY(dialinginfo.id, number);
1221 dialinginfo.itype = INFO_ITYPE_ISDN;
1222 dialinginfo.ntype = e_dialinginfo.ntype;
1223 dialinginfo.sending_complete = e_dialinginfo.sending_complete;
1224 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1226 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1228 goto check_anycall_extern;
1230 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1231 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1232 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1233 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1234 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1235 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1236 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1237 //terminal if (e_dialinginfo.id)
1238 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1239 /* handle restricted caller ids */
1240 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);
1241 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);
1242 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);
1243 /* display callerid if desired for extension */
1244 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));
1245 message_put(message);
1246 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1250 check_anycall_extern:
1251 /* now we have all ports created */
1253 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1255 if (!ea_endpoint->ep_join_id)
1257 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1258 return; /* must exit here */
1265 int action_timeout(struct lcr_timer *timer, void *instance, int index)
1267 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1269 if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
1272 unsched_timer(&ea->e_redial_timeout);
1273 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
1274 ea->e_multipoint_cause = 0;
1275 ea->e_multipoint_location = 0;
1276 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1277 ea->e_join_pattern = 0;
1278 ea->process_dialing(1);
1279 /* we must exit, because our endpoint might be gone */
1284 int match_timeout(struct lcr_timer *timer, void *instance, int index)
1286 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1288 if (!ea->e_action) {
1289 unsched_timer(&ea->e_redial_timeout);
1290 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
1291 ea->process_dialing(0);
1292 /* we must exit, because our endpoint might be gone */
1298 int redial_timeout(struct lcr_timer *timer, void *instance, int index)
1300 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1302 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
1304 ea->new_state(EPOINT_STATE_OUT_SETUP);
1305 /* call special setup routine */
1311 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
1313 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1315 /* leave power dialing on */
1316 ea->e_powerdial_on = 1;
1317 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
1320 ea->e_ruleset = ruleset_main;
1322 ea->e_rule = ea->e_ruleset->rule_first;
1323 ea->e_action = NULL;
1324 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1325 ea->process_dialing(0);
1330 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
1332 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1333 struct port_list *portlist;
1334 struct lcr_msg *message;
1336 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
1338 /* release all ports */
1339 while((portlist = ea->ea_endpoint->ep_portlist)) {
1340 message = message_create(ea->ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1341 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1342 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1343 message_put(message);
1344 ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1345 ea->ea_endpoint->free_portlist(portlist);
1348 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1349 message->param.audiopath = 0;
1350 message_put(message);
1351 /* indicate no patterns */
1352 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1353 message_put(message);
1354 /* set setup state, since we have no response from the new join */
1355 ea->new_state(EPOINT_STATE_OUT_SETUP);
1360 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
1362 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1364 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);
1370 int callback_timeout(struct lcr_timer *timer, void *instance, int index)
1372 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1374 if (ea->e_state == EPOINT_STATE_IDLE) {
1375 /* epoint is idle, check callback */
1376 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
1377 ea->new_state(EPOINT_STATE_OUT_SETUP);
1384 int password_timeout(struct lcr_timer *timer, void *instance, int index)
1386 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1388 if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
1389 struct port_list *portlist;
1391 ea->e_ruleset = ruleset_main;
1393 ea->e_rule = ea->e_ruleset->rule_first;
1394 ea->e_action = NULL;
1395 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
1396 ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
1398 ea->e_connectedmode = 0;
1400 ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
1401 portlist = ea->ea_endpoint->ep_portlist;
1403 ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1404 ea->set_tone(portlist, "cause_10");
1411 /* doing a hookflash */
1412 void EndpointAppPBX::hookflash(void)
1417 /* be sure that we are active */
1419 e_tx_state = NOTIFY_STATE_ACTIVE;
1421 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1423 if (ea_endpoint->ep_use > 1) {
1424 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1427 /* dialtone after pressing the hash key */
1428 process_hangup(e_join_cause, e_join_location);
1429 e_multipoint_cause = 0;
1430 e_multipoint_location = 0;
1431 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1433 port->set_echotest(0);
1435 if (ea_endpoint->ep_join_id) {
1436 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1438 e_ruleset = ruleset_main;
1440 e_rule = e_ruleset->rule_first;
1442 new_state(EPOINT_STATE_IN_OVERLAP);
1443 e_connectedmode = 1;
1444 SCPY(e_dialinginfo.id, e_ext.prefix);
1445 e_extdialing = e_dialinginfo.id;
1447 if (e_dialinginfo.id[0]) {
1448 set_tone(ea_endpoint->ep_portlist, "dialing");
1451 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1459 /* messages from port
1461 /* port MESSAGE_SETUP */
1462 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1464 struct lcr_msg *message;
1466 int writeext; /* flags need to write extension after modification */
1468 struct interface *interface;
1470 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1472 portlist->port_type = param->setup.port_type;
1473 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1474 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1475 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1476 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1478 /* convert (inter-)national number type */
1479 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
1480 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1482 // e_dtmf = param->setup.dtmf;
1483 /* screen incoming caller id */
1484 interface = interface_first;
1486 if (!strcmp(e_callerinfo.interface, interface->name)) {
1489 interface = interface->next;
1492 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1493 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
1496 /* process extension */
1497 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1498 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1499 /* port makes call from extension */
1500 SCPY(e_callerinfo.extension, e_callerinfo.id);
1501 SCPY(e_ext.number, e_callerinfo.extension);
1502 SCPY(e_extension_interface, e_callerinfo.interface);
1504 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1507 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1510 /* get extension's info about caller */
1511 if (!read_extension(&e_ext, e_ext.number)) {
1512 /* extension doesn't exist */
1513 trace_header("EXTENSION (not created)", DIRECTION_IN);
1514 add_trace("extension", NULL, "%s", e_ext.number);
1516 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1517 new_state(EPOINT_STATE_OUT_DISCONNECT);
1518 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1519 e_ext.number[0] = '\0'; /* no terminal */
1524 /* put prefix (next) in front of e_dialinginfo.id */
1525 if (e_ext.next[0]) {
1526 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1527 SCPY(e_dialinginfo.id, buffer);
1528 e_ext.next[0] = '\0';
1530 } else if (e_ext.prefix[0]) {
1531 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1532 SCPY(e_dialinginfo.id, buffer);
1535 /* screen caller id by extension's config */
1536 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1538 SCPY(e_callerinfo.name, e_ext.name);
1539 /* use caller id (or if exist: id_next_call) for this call */
1540 if (e_ext.id_next_call_present >= 0) {
1541 SCPY(e_callerinfo.id, e_ext.id_next_call);
1542 /* if we restrict the pesentation */
1543 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1544 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1545 else e_callerinfo.present = e_ext.id_next_call_present;
1546 e_callerinfo.ntype = e_ext.id_next_call_type;
1547 e_ext.id_next_call_present = -1;
1550 SCPY(e_callerinfo.id, e_ext.callerid);
1551 /* if we restrict the pesentation */
1552 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1553 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1554 else e_callerinfo.present = e_ext.callerid_present;
1555 e_callerinfo.ntype = e_ext.callerid_type;
1557 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1559 /* extension is written */
1561 write_extension(&e_ext, e_ext.number);
1563 /* set volume of rx and tx */
1564 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1565 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1566 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1567 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1568 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1569 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1570 message_put(message);
1573 /* start recording if enabled */
1574 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1575 /* check if we are a terminal */
1576 if (e_ext.number[0] == '\0')
1577 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1579 port = find_port_id(portlist->port_id);
1581 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1585 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1586 /* no terminal identification */
1587 e_ext.number[0] = '\0';
1588 e_extension_interface[0] = '\0';
1589 memset(&e_ext, 0, sizeof(e_ext));
1590 e_ext.rights = 4; /* right to dial internat */
1594 e_ruleset = ruleset_main;
1596 e_rule = e_ruleset->rule_first;
1598 e_extdialing = e_dialinginfo.id;
1599 new_state(EPOINT_STATE_IN_SETUP);
1600 if (e_dialinginfo.id[0]) {
1601 set_tone(portlist, "dialing");
1603 if (e_ext.number[0])
1604 set_tone(portlist, "dialpbx");
1606 set_tone(portlist, "dialtone");
1609 if (e_state == EPOINT_STATE_IN_SETUP) {
1610 /* request MORE info, if not already at higher state */
1611 new_state(EPOINT_STATE_IN_OVERLAP);
1612 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1613 message_put(message);
1614 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1618 /* port MESSAGE_INFORMATION */
1619 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1621 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1623 /* ignore information message without digit information */
1624 if (!param->information.id[0])
1629 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1631 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1636 /* if vbox_play is done, the information are just used as they come */
1638 if (e_action->index == ACTION_VBOX_PLAY) {
1639 /* concat dialing string */
1640 SCAT(e_dialinginfo.id, param->information.id);
1645 /* keypad when disconnect but in connected mode */
1646 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1647 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1648 /* processing keypad function */
1649 if (param->information.id[0] == '0') {
1655 /* keypad when connected */
1656 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1657 if (e_ext.keypad || e_enablekeypad) {
1658 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1659 /* processing keypad function */
1660 if (param->information.id[0] == '0') {
1663 if (param->information.id[0])
1664 keypad_function(param->information.id[0]);
1666 if (e_ext.number[0])
1667 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1669 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1674 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1675 if (e_ext.number[0])
1676 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1678 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1682 if (!param->information.id[0])
1684 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1685 set_tone(portlist, "dialing");
1688 if (e_action->index==ACTION_OUTDIAL
1689 || e_action->index==ACTION_EXTERNAL
1690 || e_action->index==ACTION_REMOTE) {
1692 set_tone(portlist, "dialing");
1693 else if (!e_extdialing[0])
1694 set_tone(portlist, "dialing");
1696 /* concat dialing string */
1697 SCAT(e_dialinginfo.id, param->information.id);
1701 /* port MESSAGE_DTMF */
1702 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1708 /* only if dtmf detection is enabled */
1710 trace_header("DTMF (disabled)", DIRECTION_IN);
1714 trace_header("DTMF", DIRECTION_IN);
1715 add_trace("digit", NULL, "%c", param->dtmf);
1719 NOTE: vbox is now handled due to overlap state
1720 /* if vbox_play is done, the dtmf digits are just used as they come */
1722 if (e_action->index == ACTION_VBOX_PLAY) {
1723 /* concat dialing string */
1724 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1725 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1726 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1729 /* continue to process *X# sequences */
1733 /* check for *X# sequence */
1734 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1735 if (e_dtmf_time+3 < now) {
1736 /* the last digit was too far in the past to be a sequence */
1737 if (param->dtmf == '*')
1738 /* only start is allowed in the sequence */
1743 /* we have a sequence of digits, see what we got */
1744 if (param->dtmf == '*')
1746 else if (param->dtmf>='0' && param->dtmf<='9') {
1747 /* we need to have a star before we receive the digit of the sequence */
1748 if (e_dtmf_last == '*')
1749 e_dtmf_last = param->dtmf;
1750 } else if (param->dtmf == '#') {
1752 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1753 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1754 if (e_dtmf_last == '0') {
1758 /* processing keypad function */
1760 keypad_function(e_dtmf_last);
1766 /* set last time of dtmf */
1771 /* check for ## hookflash during dialing */
1773 if (e_action->index==ACTION_PASSWORD
1774 || e_action->index==ACTION_PASSWORD_WRITE)
1776 if (param->dtmf=='#') { /* current digit is '#' */
1777 if (e_state==EPOINT_STATE_IN_DISCONNECT
1778 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1792 /* dialing using dtmf digit */
1793 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1794 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1795 set_tone(portlist, "dialing");
1797 /* concat dialing string */
1798 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1799 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1800 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1806 /* port MESSAGE_CRYPT */
1807 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1809 /* send crypt response to cryptman */
1810 if (param->crypt.type == CR_MESSAGE_IND)
1811 cryptman_msg2man(param->crypt.data, param->crypt.len);
1813 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1816 /* port MESSAGE_OVERLAP */
1817 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1819 struct lcr_msg *message;
1821 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1823 /* signal to call tool */
1824 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1826 if (e_dialing_queue[0] && portlist) {
1827 /* send what we have not dialed yet, because we had no setup complete */
1828 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1829 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1830 SCPY(message->param.information.id, e_dialing_queue);
1831 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1832 message_put(message);
1833 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1834 e_dialing_queue[0] = '\0';
1836 /* check if pattern is available */
1837 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1838 /* indicate patterns */
1839 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1840 message_put(message);
1842 /* connect audio, if not already */
1843 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1844 message->param.audiopath = 1;
1845 message_put(message);
1847 /* indicate no patterns */
1848 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1849 message_put(message);
1851 /* disconnect audio, if not already */
1852 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1853 message->param.audiopath = 0;
1854 message_put(message);
1856 new_state(EPOINT_STATE_OUT_OVERLAP);
1857 /* if we are in a join */
1858 if (ea_endpoint->ep_join_id) {
1859 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1860 memcpy(&message->param, param, sizeof(union parameter));
1861 message_put(message);
1865 /* port MESSAGE_PROCEEDING */
1866 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1868 struct lcr_msg *message;
1870 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1872 /* signal to call tool */
1873 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1875 e_state = EPOINT_STATE_OUT_PROCEEDING;
1876 /* check if pattern is availatle */
1877 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1878 /* indicate patterns */
1879 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1880 message_put(message);
1882 /* connect audio, if not already */
1883 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1884 message->param.audiopath = 1;
1885 message_put(message);
1887 /* indicate no patterns */
1888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1889 message_put(message);
1891 /* disconnect audio, if not already */
1892 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1893 message->param.audiopath = 0;
1894 message_put(message);
1896 /* if we are in a call */
1897 if (ea_endpoint->ep_join_id) {
1898 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1899 memcpy(&message->param, param, sizeof(union parameter));
1900 message_put(message);
1904 /* port MESSAGE_ALERTING */
1905 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1907 struct lcr_msg *message;
1909 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1911 /* signal to call tool */
1912 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1915 // set_tone(portlist, "hold");
1917 new_state(EPOINT_STATE_OUT_ALERTING);
1918 /* check if pattern is available */
1919 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1920 /* indicate patterns */
1921 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1922 message_put(message);
1924 /* connect audio, if not already */
1925 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1926 message->param.audiopath = 1;
1927 message_put(message);
1929 /* indicate no patterns */
1930 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1931 message_put(message);
1933 /* disconnect audio, if not already */
1934 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1935 message->param.audiopath = 0;
1936 message_put(message);
1938 /* if we are in a call */
1939 if (ea_endpoint->ep_join_id) {
1940 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1941 memcpy(&message->param, param, sizeof(union parameter));
1942 message_put(message);
1946 /* port MESSAGE_CONNECT */
1947 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1949 struct lcr_msg *message;
1951 unsigned int port_id = portlist->port_id;
1952 struct port_list *tportlist;
1954 struct interface *interface;
1957 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1959 /* signal to call tool */
1960 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1962 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1963 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1964 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1965 tportlist = ea_endpoint->ep_portlist;
1966 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1967 tportlist = tportlist->next;
1968 if (tportlist->port_id == port_id)
1969 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1970 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1971 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1972 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1973 message_put(message);
1974 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1975 ea_endpoint->free_portlist(tportlist);
1977 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1982 /* screen incoming connected id */
1983 interface = interface_first;
1985 if (!strcmp(e_connectinfo.interface, interface->name)) {
1988 interface = interface->next;
1991 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
1993 /* screen connected name */
1995 SCPY(e_connectinfo.name, e_ext.name);
1997 /* add internal id to colp */
1998 SCPY(e_connectinfo.extension, e_ext.number);
2000 /* we store the connected port number */
2001 SCPY(e_extension_interface, e_connectinfo.interface);
2003 /* for internal and am calls, we get the extension's id */
2004 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
2005 SCPY(e_connectinfo.id, e_ext.callerid);
2006 SCPY(e_connectinfo.extension, e_ext.number);
2007 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2008 e_connectinfo.ntype = e_ext.callerid_type;
2009 e_connectinfo.present = e_ext.callerid_present;
2011 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
2012 e_connectinfo.itype = INFO_ITYPE_VBOX;
2013 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2016 new_state(EPOINT_STATE_CONNECT);
2018 /* set volume of rx and tx */
2019 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
2020 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2021 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2022 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2023 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2024 message_put(message);
2027 unsched_timer(&e_cfnr_timeout);
2028 unsched_timer(&e_cfnr_call_timeout);
2029 if (e_ext.number[0])
2030 e_dtmf = 1; /* allow dtmf */
2033 /* other calls with no caller id (or not available for the extension) and force colp */
2034 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
2035 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
2036 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT
2037 || portlist->port_type==PORT_TYPE_DSS1_NT_OUT
2038 || portlist->port_type==PORT_TYPE_GSM_BS_OUT
2039 || portlist->port_type==PORT_TYPE_GSM_MS_OUT) { /* external extension answered */
2040 port = find_port_id(portlist->port_id);
2042 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2043 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2048 /* send connect to join */
2049 if (ea_endpoint->ep_join_id) {
2050 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2051 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2052 message_put(message);
2054 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2055 message->param.audiopath = 1;
2056 message_put(message);
2057 } else if (!e_adminid) {
2059 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2060 SCPY(e_ext.number, e_cbcaller);
2061 new_state(EPOINT_STATE_IN_OVERLAP);
2062 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2064 /* get extension's info about terminal */
2065 if (!read_extension(&e_ext, e_ext.number)) {
2066 /* extension doesn't exist */
2067 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2068 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2069 new_state(EPOINT_STATE_OUT_DISCONNECT);
2070 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2074 /* put prefix in front of e_cbdialing */
2075 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2076 SCPY(e_dialinginfo.id, buffer);
2077 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2078 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2080 /* use caller id (or if exist: id_next_call) for this call */
2081 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2082 SCPY(e_callerinfo.extension, e_ext.number);
2083 if (e_ext.id_next_call_present >= 0) {
2084 SCPY(e_callerinfo.id, e_ext.id_next_call);
2085 e_callerinfo.present = e_ext.id_next_call_present;
2086 e_callerinfo.ntype = e_ext.id_next_call_type;
2087 e_ext.id_next_call_present = -1;
2088 /* extension is written */
2089 write_extension(&e_ext, e_ext.number);
2091 SCPY(e_callerinfo.id, e_ext.callerid);
2092 e_callerinfo.present = e_ext.callerid_present;
2093 e_callerinfo.ntype = e_ext.callerid_type;
2095 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2097 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2100 /* check if caller id is NOT authenticated */
2101 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2102 /* make call state to enter password */
2103 new_state(EPOINT_STATE_IN_OVERLAP);
2104 e_action = &action_password_write;
2105 unsched_timer(&e_match_timeout);
2106 e_match_to_action = NULL;
2107 e_dialinginfo.id[0] = '\0';
2108 e_extdialing = strchr(e_dialinginfo.id, '\0');
2109 schedule_timer(&e_password_timeout, 20, 0);
2112 /* incoming call (callback) */
2113 e_ruleset = ruleset_main;
2115 e_rule = e_ruleset->rule_first;
2117 e_extdialing = e_dialinginfo.id;
2118 if (e_dialinginfo.id[0]) {
2119 set_tone(portlist, "dialing");
2122 set_tone(portlist, "dialpbx");
2125 } else { /* testcall */
2126 set_tone(portlist, "hold");
2129 /* start recording if enabled, not when answering machine answers */
2130 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)) {
2131 /* check if we are a terminal */
2132 if (e_ext.number[0] == '\0')
2133 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2135 port = find_port_id(portlist->port_id);
2137 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2142 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2143 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2145 struct lcr_msg *message;
2147 unsigned int port_id = portlist->port_id;
2151 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2153 /* signal to call tool */
2154 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2156 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2157 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2158 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2163 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);
2164 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2165 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2167 /* check if we have more than one portlist relation and we just ignore the disconnect */
2168 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2169 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2170 portlist = ea_endpoint->ep_portlist;
2172 if (portlist->port_id == port_id)
2174 portlist = portlist->next;
2177 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2178 if (message_type != MESSAGE_RELEASE) {
2179 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2180 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2181 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2182 message_put(message);
2183 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2185 ea_endpoint->free_portlist(portlist);
2186 return; /* one relation removed */
2188 if (e_state == EPOINT_STATE_CONNECT) {
2189 /* use cause from port after connect */
2190 cause = param->disconnectinfo.cause;
2191 location = param->disconnectinfo.location;
2193 /* use multipoint cause if no connect yet */
2194 if (e_multipoint_cause) {
2195 cause = e_multipoint_cause;
2196 location = e_multipoint_location;
2198 cause = CAUSE_NOUSER;
2199 location = LOCATION_PRIVATE_LOCAL;
2203 unsched_timer(&e_cfnr_timeout);
2204 unsched_timer(&e_cfnr_call_timeout);
2206 /* process hangup */
2207 process_hangup(e_join_cause, e_join_location);
2208 e_multipoint_cause = 0;
2209 e_multipoint_location = 0;
2211 if (message_type == MESSAGE_DISCONNECT) {
2212 /* tone to disconnected end */
2213 SPRINT(buffer, "cause_%02x", cause);
2214 if (ea_endpoint->ep_portlist)
2215 set_tone(ea_endpoint->ep_portlist, buffer);
2217 new_state(EPOINT_STATE_IN_DISCONNECT);
2220 if (ea_endpoint->ep_join_id) {
2221 int haspatterns = 0;
2222 /* check if pattern is available */
2223 if (ea_endpoint->ep_portlist)
2224 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2225 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
2226 && message_type != MESSAGE_RELEASE) // if we release, we are done
2229 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2230 /* indicate patterns */
2231 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2232 message_put(message);
2233 /* connect audio, if not already */
2234 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2235 message->param.audiopath = 1;
2236 message_put(message);
2237 /* send disconnect */
2238 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2239 memcpy(&message->param, param, sizeof(union parameter));
2240 message_put(message);
2241 /* disable encryption if disconnected */
2242 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2244 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2247 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2250 if (message_type == MESSAGE_RELEASE)
2251 ea_endpoint->free_portlist(portlist);
2252 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
2253 return; /* must exit here */
2256 /* port MESSAGE_TIMEOUT */
2257 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2261 trace_header("TIMEOUT", DIRECTION_IN);
2262 message_type = MESSAGE_DISCONNECT;
2263 switch (param->state) {
2264 case PORT_STATE_OUT_SETUP:
2265 case PORT_STATE_OUT_OVERLAP:
2266 add_trace("state", NULL, "outgoing setup/dialing");
2268 /* no user responding */
2269 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2270 return; /* must exit here */
2272 case PORT_STATE_IN_SETUP:
2273 case PORT_STATE_IN_OVERLAP:
2274 add_trace("state", NULL, "incoming setup/dialing");
2275 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2276 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2279 case PORT_STATE_OUT_PROCEEDING:
2280 add_trace("state", NULL, "outgoing proceeding");
2282 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2283 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2284 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2285 return; /* must exit here */
2287 case PORT_STATE_IN_PROCEEDING:
2288 add_trace("state", NULL, "incoming proceeding");
2289 param->disconnectinfo.cause = CAUSE_NOUSER;
2290 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2293 case PORT_STATE_OUT_ALERTING:
2294 add_trace("state", NULL, "outgoing alerting");
2296 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2297 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2298 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2299 return; /* must exit here */
2301 case PORT_STATE_CONNECT:
2302 add_trace("state", NULL, "connect");
2304 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2305 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2306 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2307 return; /* must exit here */
2309 case PORT_STATE_IN_ALERTING:
2310 add_trace("state", NULL, "incoming alerting");
2311 param->disconnectinfo.cause = CAUSE_NOANSWER;
2312 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2315 case PORT_STATE_IN_DISCONNECT:
2316 case PORT_STATE_OUT_DISCONNECT:
2317 add_trace("state", NULL, "disconnect");
2319 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2320 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2321 return; /* must exit here */
2324 param->disconnectinfo.cause = 31; /* normal unspecified */
2325 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2328 /* release call, disconnect isdn */
2330 new_state(EPOINT_STATE_OUT_DISCONNECT);
2331 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2332 SCPY(e_tone, cause);
2334 set_tone(portlist, cause);
2335 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2336 portlist = portlist->next;
2338 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2341 /* port MESSAGE_NOTIFY */
2342 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2344 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2346 struct lcr_msg *message;
2347 const char *logtext = "";
2350 /* signal to call tool */
2351 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);
2352 if (param->notifyinfo.notify) {
2353 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2356 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2357 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2358 case INFO_NOTIFY_REMOTE_HOLD:
2359 case INFO_NOTIFY_USER_SUSPENDED:
2360 /* tell call about it */
2361 if (ea_endpoint->ep_join_id) {
2362 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2363 message->param.audiopath = 0;
2364 message_put(message);
2368 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2369 case INFO_NOTIFY_USER_RESUMED:
2370 /* set volume of rx and tx */
2371 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2372 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2374 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2375 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2376 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2377 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2378 message_put(message);
2380 /* set current tone */
2382 set_tone(portlist, e_tone);
2383 /* tell call about it */
2384 if (ea_endpoint->ep_join_id) {
2385 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2386 message->param.audiopath = 1;
2387 message_put(message);
2392 /* get name of notify */
2393 switch(param->notifyinfo.notify) {
2398 logtext = "USER_SUSPENDED";
2401 logtext = "BEARER_SERVICE_CHANGED";
2404 logtext = "USER_RESUMED";
2407 logtext = "CONFERENCE_ESTABLISHED";
2410 logtext = "CONFERENCE_DISCONNECTED";
2413 logtext = "OTHER_PARTY_ADDED";
2416 logtext = "ISOLATED";
2419 logtext = "REATTACHED";
2422 logtext = "OTHER_PARTY_ISOLATED";
2425 logtext = "OTHER_PARTY_REATTACHED";
2428 logtext = "OTHER_PARTY_SPLIT";
2431 logtext = "OTHER_PARTY_DISCONNECTED";
2434 logtext = "CONFERENCE_FLOATING";
2437 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2440 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2443 logtext = "CALL_IS_A_WAITING_CALL";
2446 logtext = "DIVERSION_ACTIVATED";
2449 logtext = "RESERVED_CT_1";
2452 logtext = "RESERVED_CT_2";
2455 logtext = "REVERSE_CHARGING";
2458 logtext = "REMOTE_HOLD";
2461 logtext = "REMOTE_RETRIEVAL";
2464 logtext = "CALL_IS_DIVERTING";
2467 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2472 /* notify call if available */
2473 if (ea_endpoint->ep_join_id) {
2474 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2475 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2476 message_put(message);
2481 /* port MESSAGE_PROGRESS */
2482 void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
2484 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2486 struct lcr_msg *message;
2488 /* signal to call tool */
2489 admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
2491 /* send progress to call if available */
2492 if (ea_endpoint->ep_join_id) {
2493 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
2494 memcpy(&message->param.progressinfo, ¶m->progressinfo, sizeof(struct progress_info));
2495 message_put(message);
2500 /* port MESSAGE_FACILITY */
2501 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2503 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2505 struct lcr_msg *message;
2507 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2508 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2509 message_put(message);
2512 /* port MESSAGE_SUSPEND */
2513 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2514 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2516 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2518 /* epoint is now parked */
2519 ea_endpoint->ep_park = 1;
2520 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2521 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2523 /* remove port relation */
2524 ea_endpoint->free_portlist(portlist);
2527 /* port MESSAGE_RESUME */
2528 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2529 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2531 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2533 /* epoint is now resumed */
2534 ea_endpoint->ep_park = 0;
2539 /* port sends message to the endpoint
2541 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2543 struct port_list *portlist;
2545 portlist = ea_endpoint->ep_portlist;
2547 if (port_id == portlist->port_id)
2549 portlist = portlist->next;
2552 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);
2556 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2557 switch(message_type) {
2558 case MESSAGE_DATA: /* data from port */
2559 /* check if there is a call */
2560 if (!ea_endpoint->ep_join_id)
2562 /* continue if only one portlist */
2563 if (ea_endpoint->ep_portlist->next != NULL)
2565 /* forward message */
2566 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2569 case MESSAGE_TONE_EOF: /* tone is end of file */
2570 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2572 if (e_action->index == ACTION_VBOX_PLAY) {
2575 if (e_action->index == ACTION_EFI) {
2581 case MESSAGE_TONE_COUNTER: /* counter info received */
2582 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);
2584 if (e_action->index == ACTION_VBOX_PLAY) {
2585 e_vbox_counter = param->counter.current;
2586 if (param->counter.max >= 0)
2587 e_vbox_counter_max = param->counter.max;
2591 /* PORT sends SETUP message */
2593 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);
2594 if (e_state!=EPOINT_STATE_IDLE) {
2595 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2598 port_setup(portlist, message_type, param);
2601 /* PORT sends INFORMATION message */
2602 case MESSAGE_INFORMATION: /* additional digits received */
2603 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);
2604 port_information(portlist, message_type, param);
2607 /* PORT sends FACILITY message */
2608 case MESSAGE_FACILITY:
2609 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2610 port_facility(portlist, message_type, param);
2613 /* PORT sends DTMF message */
2614 case MESSAGE_DTMF: /* dtmf digits received */
2615 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);
2616 port_dtmf(portlist, message_type, param);
2619 /* PORT sends CRYPT message */
2620 case MESSAGE_CRYPT: /* crypt response received */
2621 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2622 port_crypt(portlist, message_type, param);
2625 /* PORT sends MORE message */
2626 case MESSAGE_OVERLAP:
2627 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);
2628 if (e_state != EPOINT_STATE_OUT_SETUP) {
2629 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);
2632 port_overlap(portlist, message_type, param);
2635 /* PORT sends PROCEEDING message */
2636 case MESSAGE_PROCEEDING: /* port is proceeding */
2637 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);
2638 if (e_state!=EPOINT_STATE_OUT_SETUP
2639 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2640 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);
2643 port_proceeding(portlist, message_type, param);
2646 /* PORT sends ALERTING message */
2647 case MESSAGE_ALERTING:
2648 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);
2649 if (e_state!=EPOINT_STATE_OUT_SETUP
2650 && e_state!=EPOINT_STATE_OUT_OVERLAP
2651 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2652 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);
2655 port_alerting(portlist, message_type, param);
2658 /* PORT sends CONNECT message */
2659 case MESSAGE_CONNECT:
2660 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);
2661 if (e_state!=EPOINT_STATE_OUT_SETUP
2662 && e_state!=EPOINT_STATE_OUT_OVERLAP
2663 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2664 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2665 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2668 port_connect(portlist, message_type, param);
2671 /* PORT sends DISCONNECT message */
2672 case MESSAGE_DISCONNECT: /* port is disconnected */
2673 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);
2674 port_disconnect_release(portlist, message_type, param);
2677 /* PORT sends a RELEASE message */
2678 case MESSAGE_RELEASE: /* port releases */
2679 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);
2680 /* portlist is release at port_disconnect_release, thanx Paul */
2681 port_disconnect_release(portlist, message_type, param);
2684 /* PORT sends a TIMEOUT message */
2685 case MESSAGE_TIMEOUT:
2686 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);
2687 port_timeout(portlist, message_type, param);
2688 break; /* release */
2690 /* PORT sends a NOTIFY message */
2691 case MESSAGE_NOTIFY:
2692 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);
2693 port_notify(portlist, message_type, param);
2696 /* PORT sends a PROGRESS message */
2697 case MESSAGE_PROGRESS:
2698 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);
2699 port_progress(portlist, message_type, param);
2702 /* PORT sends a SUSPEND message */
2703 case MESSAGE_SUSPEND:
2704 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);
2705 port_suspend(portlist, message_type, param);
2706 break; /* suspend */
2708 /* PORT sends a RESUME message */
2709 case MESSAGE_RESUME:
2710 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);
2711 port_resume(portlist, message_type, param);
2715 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2716 /* port assigns bchannel */
2717 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2718 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);
2719 /* only one port is expected to be connected to bchannel */
2720 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2721 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2727 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);
2730 /* Note: this endpoint may be destroyed, so we MUST return */
2734 /* messages from join
2736 /* join MESSAGE_CRYPT */
2737 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2739 switch(param->crypt.type) {
2740 /* message from remote port to "crypt manager" */
2741 case CU_ACTK_REQ: /* activate key-exchange */
2742 case CU_ACTS_REQ: /* activate shared key */
2743 case CU_DACT_REQ: /* deactivate */
2744 case CU_INFO_REQ: /* request last info message */
2745 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2748 /* message from "crypt manager" to user */
2749 case CU_ACTK_CONF: /* key-echange done */
2750 case CU_ACTS_CONF: /* shared key done */
2751 case CU_DACT_CONF: /* deactivated */
2752 case CU_DACT_IND: /* deactivated */
2753 case CU_ERROR_IND: /* receive error message */
2754 case CU_INFO_IND: /* receive info message */
2755 case CU_INFO_CONF: /* receive info message */
2756 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2760 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);
2764 /* join MESSAGE_INFORMATION */
2765 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2767 struct lcr_msg *message;
2772 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2773 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2774 message_put(message);
2775 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2776 portlist = portlist->next;
2780 /* join MESSAGE_FACILITY */
2781 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2783 struct lcr_msg *message;
2785 if (!e_ext.facility && e_ext.number[0]) {
2790 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2791 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2792 message_put(message);
2793 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2794 portlist = portlist->next;
2798 /* join MESSAGE_MORE */
2799 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2801 struct lcr_msg *message;
2803 new_state(EPOINT_STATE_IN_OVERLAP);
2806 if (e_join_pattern && e_ext.own_setup) {
2807 /* disconnect audio */
2808 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2809 message->param.audiopath = 0;
2810 message_put(message);
2812 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2813 if (e_dialinginfo.id[0])
2814 set_tone(portlist, "dialing");
2816 set_tone(portlist, "dialtone");
2819 if (e_dialinginfo.id[0]) {
2820 set_tone(portlist, "dialing");
2822 if (e_ext.number[0])
2823 set_tone(portlist, "dialpbx");
2825 set_tone(portlist, "dialtone");
2829 /* join MESSAGE_PROCEEDING */
2830 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2832 struct lcr_msg *message;
2834 new_state(EPOINT_STATE_IN_PROCEEDING);
2836 /* own proceeding tone */
2837 if (e_join_pattern) {
2838 /* connect / disconnect audio */
2839 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2840 if (e_ext.own_proceeding)
2841 message->param.audiopath = 0;
2843 message->param.audiopath = 1;
2844 message_put(message);
2846 // UCPY(e_join_tone, "proceeding");
2848 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2849 message_put(message);
2850 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2852 set_tone(portlist, "proceeding");
2855 /* join MESSAGE_ALERTING */
2856 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2858 struct lcr_msg *message;
2860 new_state(EPOINT_STATE_IN_ALERTING);
2862 /* own alerting tone */
2863 if (e_join_pattern) {
2864 /* connect / disconnect audio */
2865 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2866 if (e_ext.own_alerting)
2867 message->param.audiopath = 0;
2869 message->param.audiopath = 1;
2870 message_put(message);
2873 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2874 message_put(message);
2875 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2877 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2878 set_tone(portlist, "ringing");
2881 if (e_ext.number[0])
2882 set_tone(portlist, "ringpbx");
2884 set_tone(portlist, "ringing");
2886 if (e_ext.number[0])
2887 e_dtmf = 1; /* allow dtmf */
2890 /* join MESSAGE_CONNECT */
2891 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2893 struct lcr_msg *message;
2896 new_state(EPOINT_STATE_CONNECT);
2897 // UCPY(e_join_tone, "");
2899 if (e_ext.number[0])
2900 e_dtmf = 1; /* allow dtmf */
2903 unsched_timer(&e_powerdial_timeout);
2904 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2906 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2907 memcpy(&message->param, param, sizeof(union parameter));
2909 /* screen clip if prefix is required */
2910 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2911 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2912 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2913 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2916 /* use internal caller id */
2917 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2918 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2919 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2922 /* handle restricted caller ids */
2923 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);
2924 /* display callerid if desired for extension */
2925 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));
2927 /* use conp, if enabld */
2928 // if (!e_ext.centrex)
2929 // message->param.connectinfo.name[0] = '\0';
2932 message_put(message);
2933 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2935 set_tone(portlist, NULL);
2937 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2938 message->param.audiopath = 1;
2939 message_put(message);
2944 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2945 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2948 struct lcr_msg *message;
2949 struct port_list *portlist = NULL;
2953 /* be sure that we are active */
2955 e_tx_state = NOTIFY_STATE_ACTIVE;
2957 /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
2958 if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2959 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
2961 /* set time for power dialing */
2962 schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
2965 /* set redial tone */
2966 if (ea_endpoint->ep_portlist) {
2969 set_tone(ea_endpoint->ep_portlist, "redial");
2970 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (int)e_powerdelay);
2971 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2972 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2973 new_state(EPOINT_STATE_IN_PROCEEDING);
2974 if (ea_endpoint->ep_portlist) {
2975 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2976 message_put(message);
2977 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2979 /* caused the error, that the first knock sound was not there */
2980 /* set_tone(portlist, "proceeding"); */
2982 /* send display of powerdialing */
2983 if (e_ext.display_dialing) {
2984 portlist = ea_endpoint->ep_portlist;
2986 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2988 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2990 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2991 message_put(message);
2992 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2993 portlist = portlist->next;
3003 if ((e_state!=EPOINT_STATE_CONNECT
3004 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3005 && e_state!=EPOINT_STATE_IN_OVERLAP
3006 && e_state!=EPOINT_STATE_IN_PROCEEDING
3007 && e_state!=EPOINT_STATE_IN_ALERTING)
3008 || !ea_endpoint->ep_portlist) { /* or no port */
3009 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3010 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
3011 return; /* must exit here */
3014 if (!e_join_cause) {
3015 e_join_cause = param->disconnectinfo.cause;
3016 e_join_location = param->disconnectinfo.location;
3019 /* on release we need the audio again! */
3020 if (message_type == MESSAGE_RELEASE) {
3022 ea_endpoint->ep_join_id = 0;
3024 /* disconnect and select tone */
3025 new_state(EPOINT_STATE_OUT_DISCONNECT);
3026 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3027 /* if own_cause, we must release the join */
3028 if (e_ext.own_cause /* own cause */
3029 || !e_join_pattern) { /* no patterns */
3030 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have own cause or we have no patterns. (own_cause=%d pattern=%d)\n", ea_endpoint->ep_serial, e_ext.own_cause, e_join_pattern);
3031 if (message_type != MESSAGE_RELEASE)
3032 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
3034 } else { /* else we enable audio */
3035 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3036 message->param.audiopath = 1;
3037 message_put(message);
3039 /* send disconnect message */
3040 SCPY(e_tone, cause);
3041 portlist = ea_endpoint->ep_portlist;
3043 set_tone(portlist, cause);
3044 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3045 portlist = portlist->next;
3049 /* join MESSAGE_SETUP */
3050 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3052 struct lcr_msg *message;
3053 // struct interface *interface;
3055 /* if we already in setup state, we just update the dialing with new digits */
3056 if (e_state == EPOINT_STATE_OUT_SETUP
3057 || e_state == EPOINT_STATE_OUT_OVERLAP) {
3058 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3059 /* if digits changed, what we have already dialed */
3060 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
3061 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have dialed digits which have been changed or we have a new multidial, so we must redial.\n", ea_endpoint->ep_serial);
3062 /* release all ports */
3063 while((portlist = ea_endpoint->ep_portlist)) {
3064 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3065 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3066 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3067 message_put(message);
3068 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3069 ea_endpoint->free_portlist(portlist);
3072 /* disconnect audio */
3073 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3074 message->param.audiopath = 0;
3075 message_put(message);
3077 /* get dialing info */
3078 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3079 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3080 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3081 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3082 new_state(EPOINT_STATE_OUT_OVERLAP);
3085 schedule_timer(&e_redial_timeout, 1, 0);
3088 /* if we have a pending redial, so we just adjust the dialing number */
3089 if (e_redial_timeout.active) {
3090 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3091 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3094 if (!ea_endpoint->ep_portlist) {
3095 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3097 if (ea_endpoint->ep_portlist->next) {
3098 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3100 if (e_state == EPOINT_STATE_OUT_SETUP) {
3102 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) digits '%s' are queued because we didn't receive a setup acknowledge.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3103 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3106 /* get what we have not dialed yet */
3107 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.id+strlen(e_dialinginfo.id));
3108 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3109 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3110 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3111 message_put(message);
3112 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3114 /* always store what we have dialed or queued */
3115 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3119 if (e_state != EPOINT_STATE_IDLE) {
3120 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3123 /* if an internal extension is dialed, copy that number */
3124 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3125 SCPY(e_ext.number, param->setup.dialinginfo.id);
3126 /* if an internal extension is dialed, get extension's info about caller */
3127 if (e_ext.number[0]) {
3128 if (!read_extension(&e_ext, e_ext.number)) {
3129 e_ext.number[0] = '\0';
3130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3134 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3135 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3136 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3137 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3139 /* process (voice over) data calls */
3140 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3141 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3142 memset(&e_capainfo, 0, sizeof(e_capainfo));
3143 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3144 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3145 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3148 new_state(EPOINT_STATE_OUT_SETUP);
3149 /* call special setup routine */
3153 /* join MESSAGE_mISDNSIGNAL */
3154 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3156 struct lcr_msg *message;
3159 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3160 memcpy(&message->param, param, sizeof(union parameter));
3161 message_put(message);
3162 portlist = portlist->next;
3166 /* join MESSAGE_NOTIFY */
3167 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3169 struct lcr_msg *message;
3172 if (param->notifyinfo.notify) {
3173 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3174 // /* if notification was generated locally, we turn hold music on/off */
3175 // if (param->notifyinfo.local)
3176 // NOTE: we always assume that we send hold music on suspension of call, because we don't track if audio is available or not (we assume that we always have no audio, to make it easier)
3180 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3181 if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3183 set_tone(portlist, "");
3184 portlist = portlist->next;
3187 portlist = ea_endpoint->ep_portlist;
3192 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3194 set_tone(portlist, "hold");
3195 portlist = portlist->next;
3197 portlist = ea_endpoint->ep_portlist;
3202 /* save new state */
3203 e_tx_state = new_state;
3206 /* notify port(s) about it */
3208 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3209 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3210 /* handle restricted caller ids */
3211 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3212 /* display callerid if desired for extension */
3213 SCPY(message->param.notifyinfo.display, apply_callerid_display(message->param.notifyinfo.id, message->param.notifyinfo.itype, message->param.notifyinfo.ntype, message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL));
3214 message_put(message);
3215 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3216 portlist = portlist->next;
3220 /* JOIN sends messages to the endpoint
3222 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3224 struct port_list *portlist;
3225 struct lcr_msg *message;
3228 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3232 portlist = ea_endpoint->ep_portlist;
3234 /* send MESSAGE_DATA to port */
3235 if (message_type == MESSAGE_DATA) {
3236 if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
3237 /* skip if no port relation */
3240 /* skip if more than one port relation */
3243 /* forward audio data to port */
3244 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3249 // PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3250 switch(message_type) {
3251 /* JOIN SENDS TONE message */
3253 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received tone message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->tone.name);
3254 set_tone(portlist, param->tone.name);
3257 /* JOIN SENDS CRYPT message */
3259 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3260 join_crypt(portlist, message_type, param);
3263 /* JOIN sends INFORMATION message */
3264 case MESSAGE_INFORMATION:
3265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.id);
3266 join_information(portlist, message_type, param);
3269 /* JOIN sends FACILITY message */
3270 case MESSAGE_FACILITY:
3271 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3272 join_facility(portlist, message_type, param);
3275 /* JOIN sends OVERLAP message */
3276 case MESSAGE_OVERLAP:
3277 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info required'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3278 if (e_state!=EPOINT_STATE_IN_SETUP
3279 && e_state!=EPOINT_STATE_IN_OVERLAP) {
3280 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3283 join_overlap(portlist, message_type, param);
3286 /* JOIN sends PROCEEDING message */
3287 case MESSAGE_PROCEEDING:
3288 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3289 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3290 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3293 join_proceeding(portlist, message_type, param);
3296 /* JOIN sends ALERTING message */
3297 case MESSAGE_ALERTING:
3298 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3299 if (e_state!=EPOINT_STATE_IN_OVERLAP
3300 && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3301 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3304 join_alerting(portlist, message_type, param);
3307 /* JOIN sends CONNECT message */
3308 case MESSAGE_CONNECT:
3309 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3310 if (e_state!=EPOINT_STATE_IN_OVERLAP
3311 && e_state!=EPOINT_STATE_IN_PROCEEDING
3312 && e_state!=EPOINT_STATE_IN_ALERTING) {
3313 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3316 join_connect(portlist, message_type, param);
3319 /* JOIN sends DISCONNECT/RELEASE message */
3320 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3321 case MESSAGE_RELEASE: /* JOIN releases */
3322 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3323 join_disconnect_release(message_type, param);
3326 /* JOIN sends SETUP message */
3328 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from terminal='%s',id='%s' to id='%s' (dialing itype=%d)\n", ea_endpoint->ep_serial, param->setup.callerinfo.extension, param->setup.callerinfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.itype);
3329 join_setup(portlist, message_type, param);
3332 /* JOIN sends special mISDNSIGNAL message */
3333 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3334 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3335 join_mISDNsignal(portlist, message_type, param);
3339 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3340 /* JOIN requests bchannel */
3341 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3342 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
3343 /* only one port is expected to be connected to bchannel */
3350 set_tone(portlist, NULL);
3351 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3352 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3356 /* JOIN has pattern available */
3357 case MESSAGE_PATTERN: /* indicating pattern available */
3358 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3359 if (!e_join_pattern) {
3360 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3364 set_tone(portlist, NULL);
3365 portlist = portlist->next;
3367 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3368 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3369 message->param.audiopath = 1;
3370 message_put(message);
3374 /* JOIN has no pattern available */
3375 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3376 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3377 if (e_join_pattern) {
3378 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3380 /* disconnect our audio tx and rx */
3381 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3382 message->param.audiopath = 0;
3383 message_put(message);
3388 /* JOIN (dunno at the moment) */
3389 case MESSAGE_REMOTE_AUDIO:
3390 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3391 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3392 message->param.audiopath = param->channel;
3393 message_put(message);
3397 /* JOIN sends a notify message */
3398 case MESSAGE_NOTIFY:
3399 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);
3400 join_notify(portlist, message_type, param);
3403 /* JOIN wants keypad / dtmf */
3404 case MESSAGE_ENABLEKEYPAD:
3405 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received keypad enable request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3408 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3413 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);
3418 /* pick_join will connect the first incoming call found. the endpoint
3419 * will receivce a MESSAGE_CONNECT.
3421 int match_list(char *list, char *item)
3423 char *end, *next = NULL;
3425 /* no list make matching */
3430 /* eliminate white spaces */
3431 while (*list <= ' ')
3437 /* if end of list is reached, we return */
3438 if (list[0] == '\0')
3440 /* if we have more than one entry (left) */
3441 if ((end = strchr(list, ',')))
3444 next = end = strchr(list, '\0');
3445 while (*(end-1) <= ' ')
3447 /* if string part matches item */
3448 if (!strncmp(list, item, end-list))
3454 void EndpointAppPBX::pick_join(char *extensions)
3456 struct lcr_msg *message;
3457 struct port_list *portlist;
3459 class EndpointAppPBX *eapp, *found;
3461 class JoinPBX *joinpbx;
3462 struct join_relation *relation;
3465 /* find an endpoint that is ringing internally or vbox with higher priority */
3468 eapp = apppbx_first;
3470 if (eapp!=this && ea_endpoint->ep_portlist) {
3471 portlist = eapp->ea_endpoint->ep_portlist;
3473 if ((port = find_port_id(portlist->port_id))) {
3474 if (port->p_type == PORT_TYPE_VBOX_OUT) {
3475 if (match_list(extensions, eapp->e_ext.number)) {
3481 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT
3482 || port->p_type==PORT_TYPE_DSS1_TE_OUT
3483 || port->p_type==PORT_TYPE_GSM_BS_OUT
3484 || port->p_type==PORT_TYPE_GSM_MS_OUT)
3485 && port->p_state==PORT_STATE_OUT_ALERTING)
3486 if (match_list(extensions, eapp->e_ext.number)) {
3490 portlist = portlist->next;
3498 /* if no endpoint found */
3500 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) nobody is ringing internally (or we don't have her in the access list), so we disconnect.\n", ea_endpoint->ep_serial);
3502 set_tone(ea_endpoint->ep_portlist, "cause_10");
3503 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3504 new_state(EPOINT_STATE_OUT_DISCONNECT);
3509 if (ea_endpoint->ep_join_id) {
3510 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3513 if (!eapp->ea_endpoint->ep_join_id) {
3514 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3517 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3519 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3522 if (join->j_type != JOIN_TYPE_PBX) {
3523 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3526 joinpbx = (class JoinPBX *)join;
3527 relation = joinpbx->j_relation;
3529 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3532 while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
3533 relation = relation->next;
3535 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3540 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3542 if (options.deb & DEBUG_EPOINT) {
3543 class Join *debug_c = join_first;
3544 class Endpoint *debug_e = epoint_first;
3545 class Port *debug_p = port_first;
3547 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3549 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3551 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3552 debug_c = debug_c->next;
3554 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3556 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3557 debug_e = debug_e->next;
3559 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3561 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3562 debug_p = debug_p->next;
3567 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3568 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3569 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3571 /* connnecting our endpoint */
3572 new_state(EPOINT_STATE_CONNECT);
3573 if (e_ext.number[0])
3575 set_tone(ea_endpoint->ep_portlist, NULL);
3577 /* now we send a release to the ringing endpoint */
3578 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3579 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3580 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3581 message_put(message);
3583 /* we send a connect to the join with our caller id */
3584 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3585 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3586 message->param.connectinfo.present = e_callerinfo.present;
3587 message->param.connectinfo.screen = e_callerinfo.screen;
3588 message->param.connectinfo.itype = e_callerinfo.itype;
3589 message->param.connectinfo.ntype = e_callerinfo.ntype;
3590 message_put(message);
3592 /* we send a connect to our port with the remote callerid */
3593 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3594 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3595 message->param.connectinfo.present = eapp->e_callerinfo.present;
3596 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3597 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3598 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3599 /* handle restricted caller ids */
3600 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);
3601 /* display callerid if desired for extension */
3602 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));
3603 message_put(message);
3605 /* we send a connect to the audio path (not for vbox) */
3606 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3607 message->param.audiopath = 1;
3608 message_put(message);
3610 /* beeing paranoid, we make call update */
3611 trigger_work(&joinpbx->j_updatebridge);
3613 if (options.deb & DEBUG_EPOINT) {
3614 class Join *debug_c = join_first;
3615 class Endpoint *debug_e = epoint_first;
3616 class Port *debug_p = port_first;
3618 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3620 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3622 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3623 debug_c = debug_c->next;
3625 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3627 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3628 debug_e = debug_e->next;
3630 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3632 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3633 debug_p = debug_p->next;
3639 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3641 void EndpointAppPBX::join_join(void)
3643 struct lcr_msg *message;
3644 struct join_relation *our_relation, *other_relation;
3645 struct join_relation **our_relation_pointer, **other_relation_pointer;
3646 class Join *our_join, *other_join;
3647 class JoinPBX *our_joinpbx, *other_joinpbx;
3648 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3649 class Port *our_port, *other_port;
3650 class Pdss1 *our_pdss1, *other_pdss1;
3652 /* are we a candidate to join a join? */
3653 our_join = find_join_id(ea_endpoint->ep_join_id);
3655 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3658 if (our_join->j_type != JOIN_TYPE_PBX) {
3659 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3662 our_joinpbx = (class JoinPBX *)our_join;
3663 if (!ea_endpoint->ep_portlist) {
3664 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3667 if (!e_ext.number[0]) {
3668 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3671 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3676 if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
3677 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3680 our_pdss1 = (class Pdss1 *)our_port;
3682 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3683 other_eapp = apppbx_first;
3685 if (other_eapp == this) {
3686 other_eapp = other_eapp->next;
3689 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s join=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_join_id);
3690 if (other_eapp->e_ext.number[0] /* has terminal */
3691 && other_eapp->ea_endpoint->ep_portlist /* has port */
3692 && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3693 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3694 if (other_port) { /* port still exists */
3695 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3696 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3697 other_pdss1 = (class Pdss1 *)other_port;
3698 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
3699 if (other_pdss1->p_m_hold /* port is on hold */
3700 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3701 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3704 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3707 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3710 other_eapp = other_eapp->next;
3713 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3716 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3718 /* if we have the same join */
3719 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3720 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3723 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3725 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3728 if (other_join->j_type != JOIN_TYPE_PBX) {
3729 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3732 other_joinpbx = (class JoinPBX *)other_join;
3733 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3734 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3738 /* remove relation to endpoint for join on hold */
3739 other_relation = other_joinpbx->j_relation;
3740 other_relation_pointer = &other_joinpbx->j_relation;
3741 while(other_relation) {
3742 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial) {
3743 /* detach other endpoint on hold */
3744 *other_relation_pointer = other_relation->next;
3745 FREE(other_relation, sizeof(struct join_relation));
3747 other_relation = *other_relation_pointer;
3748 other_eapp->ea_endpoint->ep_join_id = 0;
3752 /* change join/hold pointer of endpoint to the new join */
3753 temp_epoint = find_epoint_id(other_relation->epoint_id);
3755 if (temp_epoint->ep_join_id == other_join->j_serial)
3756 temp_epoint->ep_join_id = our_join->j_serial;
3759 other_relation_pointer = &other_relation->next;
3760 other_relation = other_relation->next;
3762 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3764 /* join call relations */
3765 our_relation = our_joinpbx->j_relation;
3766 our_relation_pointer = &our_joinpbx->j_relation;
3767 while(our_relation) {
3768 our_relation_pointer = &our_relation->next;
3769 our_relation = our_relation->next;
3771 *our_relation_pointer = other_joinpbx->j_relation;
3772 other_joinpbx->j_relation = NULL;
3773 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3775 /* release endpoint on hold */
3776 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3777 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3778 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3779 message_put(message);
3781 /* if we are not a partyline, we get partyline state from other join */
3782 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3784 /* remove empty join */
3786 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3788 /* mixer must update */
3789 trigger_work(&our_joinpbx->j_updatebridge);
3791 /* we send a retrieve to that endpoint */
3792 // mixer will update the hold-state of the join and send it to the endpoints is changes
3796 /* check if we have an external call
3797 * this is used to check for encryption ability
3799 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3801 struct join_relation *relation;
3803 class JoinPBX *joinpbx;
3804 class Endpoint *epoint;
3806 /* some paranoia check */
3807 if (!ea_endpoint->ep_portlist) {
3808 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3809 *errstr = "No Call";
3812 if (!e_ext.number[0]) {
3813 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3814 *errstr = "No Call";
3818 /* check if we have a join with 2 parties */
3819 join = find_join_id(ea_endpoint->ep_join_id);
3821 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3822 *errstr = "No Call";
3825 if (join->j_type != JOIN_TYPE_PBX) {
3826 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3827 *errstr = "No PBX Call";
3830 joinpbx = (class JoinPBX *)join;
3831 relation = joinpbx->j_relation;
3833 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3834 *errstr = "No Call";
3837 if (!relation->next) {
3838 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3839 *errstr = "No Call";
3842 if (relation->next->next) {
3843 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3844 *errstr = "Err: Conference";
3847 if (relation->epoint_id == ea_endpoint->ep_serial) {
3848 relation = relation->next;
3849 if (relation->epoint_id == ea_endpoint->ep_serial) {
3850 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
3851 *errstr = "Software Error";
3856 /* check remote port for external call */
3857 epoint = find_epoint_id(relation->epoint_id);
3859 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
3860 *errstr = "No Call";
3863 if (!epoint->ep_portlist) {
3864 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
3865 *errstr = "No Call";
3868 *port = find_port_id(epoint->ep_portlist->port_id);
3870 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
3871 *errstr = "No Call";
3874 if (((*port)->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) { /* port is not external isdn */
3875 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
3876 *errstr = "No Ext Call";
3879 if ((*port)->p_state != PORT_STATE_CONNECT) {
3880 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
3881 *errstr = "No Ext Connect";
3887 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
3889 const char *logtext = "unknown";
3892 switch(message_type) {
3894 trace_header("SETUP", dir);
3895 if (dir == DIRECTION_OUT)
3896 add_trace("to", NULL, "CH(%lu)", port_id);
3897 if (dir == DIRECTION_IN)
3898 add_trace("from", NULL, "CH(%lu)", port_id);
3899 if (param->setup.callerinfo.extension[0])
3900 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
3901 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
3902 switch(param->setup.callerinfo.present) {
3903 case INFO_PRESENT_RESTRICTED:
3904 add_trace("caller id", "present", "restricted");
3906 case INFO_PRESENT_ALLOWED:
3907 add_trace("caller id", "present", "allowed");
3910 add_trace("caller id", "present", "not available");
3912 if (param->setup.callerinfo.ntype2) {
3913 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
3914 switch(param->setup.callerinfo.present) {
3915 case INFO_PRESENT_RESTRICTED:
3916 add_trace("caller id2", "present", "restricted");
3918 case INFO_PRESENT_ALLOWED:
3919 add_trace("caller id2", "present", "allowed");
3922 add_trace("caller id2", "present", "not available");
3925 if (param->setup.redirinfo.id[0]) {
3926 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
3927 switch(param->setup.redirinfo.present) {
3928 case INFO_PRESENT_RESTRICTED:
3929 add_trace("redir'ing", "present", "restricted");
3931 case INFO_PRESENT_ALLOWED:
3932 add_trace("redir'ing", "present", "allowed");
3935 add_trace("redir'ing", "present", "not available");
3938 if (param->setup.dialinginfo.id[0])
3939 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
3940 if (param->setup.dialinginfo.keypad[0])
3941 add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
3942 if (param->setup.dialinginfo.display[0])
3943 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
3944 if (param->setup.dialinginfo.sending_complete)
3945 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
3949 case MESSAGE_OVERLAP:
3950 trace_header("SETUP ACKNOWLEDGE", dir);
3951 if (dir == DIRECTION_OUT)
3952 add_trace("to", NULL, "CH(%lu)", port_id);
3953 if (dir == DIRECTION_IN)
3954 add_trace("from", NULL, "CH(%lu)", port_id);
3958 case MESSAGE_PROCEEDING:
3959 trace_header("PROCEEDING", dir);
3960 if (dir == DIRECTION_OUT)
3961 add_trace("to", NULL, "CH(%lu)", port_id);
3962 if (dir == DIRECTION_IN)
3963 add_trace("from", NULL, "CH(%lu)", port_id);
3967 case MESSAGE_ALERTING:
3968 trace_header("ALERTING", dir);
3969 if (dir == DIRECTION_OUT)
3970 add_trace("to", NULL, "CH(%lu)", port_id);
3971 if (dir == DIRECTION_IN)
3972 add_trace("from", NULL, "CH(%lu)", port_id);
3976 case MESSAGE_CONNECT:
3977 trace_header("CONNECT", dir);
3978 if (dir == DIRECTION_OUT)
3979 add_trace("to", NULL, "CH(%lu)", port_id);
3980 if (dir == DIRECTION_IN)
3981 add_trace("from", NULL, "CH(%lu)", port_id);
3982 if (param->connectinfo.extension[0])
3983 add_trace("extension", NULL, "%s", param->connectinfo.extension);
3984 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
3985 switch(param->connectinfo.present) {
3986 case INFO_PRESENT_RESTRICTED:
3987 add_trace("connect id", "present", "restricted");
3989 case INFO_PRESENT_ALLOWED:
3990 add_trace("connect id", "present", "allowed");
3993 add_trace("connect id", "present", "not available");
3995 if (param->connectinfo.display[0])
3996 add_trace("display", NULL, "%s", param->connectinfo.display);
4000 case MESSAGE_DISCONNECT:
4001 case MESSAGE_RELEASE:
4002 if (message_type == MESSAGE_DISCONNECT)
4003 trace_header("DISCONNECT", dir);
4005 trace_header("RELEASE", dir);
4006 if (dir == DIRECTION_OUT)
4007 add_trace("to", NULL, "CH(%lu)", port_id);
4008 if (dir == DIRECTION_IN)
4009 add_trace("from", NULL, "CH(%lu)", port_id);
4010 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4011 switch(param->disconnectinfo.location) {
4013 add_trace("cause", "location", "0-User");
4015 case LOCATION_PRIVATE_LOCAL:
4016 add_trace("cause", "location", "1-Local-PBX");
4018 case LOCATION_PUBLIC_LOCAL:
4019 add_trace("cause", "location", "2-Local-Exchange");
4021 case LOCATION_TRANSIT:
4022 add_trace("cause", "location", "3-Transit");
4024 case LOCATION_PUBLIC_REMOTE:
4025 add_trace("cause", "location", "4-Remote-Exchange");
4027 case LOCATION_PRIVATE_REMOTE:
4028 add_trace("cause", "location", "5-Remote-PBX");
4030 case LOCATION_INTERNATIONAL:
4031 add_trace("cause", "location", "7-International-Exchange");
4033 case LOCATION_BEYOND:
4034 add_trace("cause", "location", "10-Beyond-Interworking");
4037 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4039 if (param->disconnectinfo.display[0])
4040 add_trace("display", NULL, "%s", param->disconnectinfo.display);
4044 case MESSAGE_NOTIFY:
4045 switch(param->notifyinfo.notify) {
4050 logtext = "USER_SUSPENDED";
4053 logtext = "BEARER_SERVICE_CHANGED";
4056 logtext = "USER_RESUMED";
4059 logtext = "CONFERENCE_ESTABLISHED";
4062 logtext = "CONFERENCE_DISCONNECTED";
4065 logtext = "OTHER_PARTY_ADDED";
4068 logtext = "ISOLATED";
4071 logtext = "REATTACHED";
4074 logtext = "OTHER_PARTY_ISOLATED";
4077 logtext = "OTHER_PARTY_REATTACHED";
4080 logtext = "OTHER_PARTY_SPLIT";
4083 logtext = "OTHER_PARTY_DISCONNECTED";
4086 logtext = "CONFERENCE_FLOATING";
4089 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4092 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4095 logtext = "CALL_IS_A_WAITING_CALL";
4098 logtext = "DIVERSION_ACTIVATED";
4101 logtext = "RESERVED_CT_1";
4104 logtext = "RESERVED_CT_2";
4107 logtext = "REVERSE_CHARGING";
4110 logtext = "REMOTE_HOLD";
4113 logtext = "REMOTE_RETRIEVAL";
4116 logtext = "CALL_IS_DIVERTING";
4119 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4123 trace_header("NOTIFY", dir);
4124 if (dir == DIRECTION_OUT)
4125 add_trace("to", NULL, "CH(%lu)", port_id);
4126 if (dir == DIRECTION_IN)
4127 add_trace("from", NULL, "CH(%lu)", port_id);
4128 if (param->notifyinfo.notify)
4129 add_trace("indicator", NULL, "%s", logtext);
4130 if (param->notifyinfo.id[0]) {
4131 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4132 switch(param->notifyinfo.present) {
4133 case INFO_PRESENT_RESTRICTED:
4134 add_trace("redir'on", "present", "restricted");
4136 case INFO_PRESENT_ALLOWED:
4137 add_trace("redir'on", "present", "allowed");
4140 add_trace("redir'on", "present", "not available");
4143 if (param->notifyinfo.display[0])
4144 add_trace("display", NULL, "%s", param->notifyinfo.display);
4148 case MESSAGE_PROGRESS:
4149 switch(param->progressinfo.progress) {
4151 logtext = "Call is not end to end ISDN";
4154 logtext = "Destination address is non-ISDN";
4157 logtext = "Origination address is non-ISDN";
4160 logtext = "Call has returned to the ISDN";
4163 logtext = "In-band info or pattern available";
4166 SPRINT(buffer, "%d", param->progressinfo.progress);
4170 trace_header("PROGRESS", dir);
4171 if (dir == DIRECTION_OUT)
4172 add_trace("to", NULL, "CH(%lu)", port_id);
4173 if (dir == DIRECTION_IN)
4174 add_trace("from", NULL, "CH(%lu)", port_id);
4175 add_trace("indicator", NULL, "%s", logtext);
4176 switch(param->progressinfo.location) {
4178 add_trace("cause", "location", "0-User");
4180 case LOCATION_PRIVATE_LOCAL:
4181 add_trace("cause", "location", "1-Local-PBX");
4183 case LOCATION_PUBLIC_LOCAL:
4184 add_trace("cause", "location", "2-Local-Exchange");
4186 case LOCATION_TRANSIT:
4187 add_trace("cause", "location", "3-Transit");
4189 case LOCATION_PUBLIC_REMOTE:
4190 add_trace("cause", "location", "4-Remote-Exchange");
4192 case LOCATION_PRIVATE_REMOTE:
4193 add_trace("cause", "location", "5-Remote-PBX");
4195 case LOCATION_INTERNATIONAL:
4196 add_trace("cause", "location", "7-International-Exchange");
4198 case LOCATION_BEYOND:
4199 add_trace("cause", "location", "10-Beyond-Interworking");
4202 add_trace("cause", "location", "%d", param->progressinfo.location);
4207 case MESSAGE_INFORMATION:
4208 trace_header("INFORMATION", dir);
4209 if (dir == DIRECTION_OUT)
4210 add_trace("to", NULL, "CH(%lu)", port_id);
4211 if (dir == DIRECTION_IN)
4212 add_trace("from", NULL, "CH(%lu)", port_id);
4213 if (param->information.id[0])
4214 add_trace("dialing", NULL, "%s", param->information.id);
4215 if (param->information.display[0])
4216 add_trace("display", NULL, "%s", param->information.display);
4217 if (param->information.sending_complete)
4218 add_trace("complete", NULL, "true", param->information.sending_complete);
4222 case MESSAGE_FACILITY:
4223 trace_header("FACILITY", dir);
4224 if (dir == DIRECTION_OUT)
4225 add_trace("to", NULL, "CH(%lu)", port_id);
4226 if (dir == DIRECTION_IN)
4227 add_trace("from", NULL, "CH(%lu)", port_id);
4232 trace_header("TONE", dir);
4233 if (dir == DIRECTION_OUT)
4234 add_trace("to", NULL, "CH(%lu)", port_id);
4235 if (dir == DIRECTION_IN)
4236 add_trace("from", NULL, "CH(%lu)", port_id);
4237 if (param->tone.name[0]) {
4238 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4239 add_trace("name", NULL, "%s", param->tone.name);
4241 add_trace("off", NULL, NULL);
4245 case MESSAGE_SUSPEND:
4246 case MESSAGE_RESUME:
4247 if (message_type == MESSAGE_SUSPEND)
4248 trace_header("SUSPEND", dir);
4250 trace_header("RESUME", dir);
4251 if (dir == DIRECTION_OUT)
4252 add_trace("to", NULL, "CH(%lu)", port_id);
4253 if (dir == DIRECTION_IN)
4254 add_trace("from", NULL, "CH(%lu)", port_id);
4255 if (param->parkinfo.len)
4256 add_trace("length", NULL, "%d", param->parkinfo.len);
4261 case MESSAGE_BCHANNEL:
4262 trace_header("BCHANNEL", dir);
4263 switch(param->bchannel.type) {
4264 case BCHANNEL_REQUEST:
4265 add_trace("type", NULL, "request");
4267 case BCHANNEL_ASSIGN:
4268 add_trace("type", NULL, "assign");
4270 case BCHANNEL_ASSIGN_ACK:
4271 add_trace("type", NULL, "assign_ack");
4273 case BCHANNEL_REMOVE:
4274 add_trace("type", NULL, "remove");
4276 case BCHANNEL_REMOVE_ACK:
4277 add_trace("type", NULL, "remove_ack");
4280 if (param->bchannel.addr)
4281 add_trace("address", NULL, "%x", param->bchannel.addr);
4287 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4291 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4293 struct lcr_msg *message;
4297 if (!portlist->port_id)
4300 if (!e_connectedmode) {
4301 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4302 message->param.disconnectinfo.cause = cause;
4303 message->param.disconnectinfo.location = location;
4305 SCPY(message->param.disconnectinfo.display, display);
4307 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4309 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4311 SCPY(message->param.notifyinfo.display, display);
4313 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4315 message_put(message);
4316 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);